Skip to content

Commit 9cbcae5

Browse files
tschmetzernyalldawson
authored andcommittedJan 6, 2022
Add QgsGeometryUtils::perpendicularCenterSegment() with description in header file, test case and sip.in for Docx
1 parent c6fd773 commit 9cbcae5

File tree

4 files changed

+122
-0
lines changed

4 files changed

+122
-0
lines changed
 

‎python/core/auto_generated/geometry/qgsgeometryutils.sip.in

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,38 @@ Create a perpendicular line segment from p to segment [s1, s2]
644644
%End
645645

646646

647+
static void perpendicularCenterSegment( double centerPointx, double centerPointy,
648+
double segmentPoint1x, double segmentPoint1y,
649+
double segmentPoint2x, double segmentPoint2y,
650+
double &perpendicularSegmentPoint1x /Out/, double &perpendicularSegmentPoint1y /Out/,
651+
double &perpendicularSegmentPoint2x /Out/, double &perpendicularSegmentPoint2y /Out/,
652+
double *segmentLength=0
653+
) /HoldGIL/;
654+
%Docstring
655+
Create a perpendicular line segment to a given segment [``segmentPoint1``,``segmentPoint2``] with its center at ``centerPoint``.
656+
657+
May be used to split geometries. The new centered perpendicular line segment will have double the length of the input segment
658+
659+
:param centerPointx: x-coordinate of the point where the center of the perpendicular should be located
660+
:param centerPointy: y-coordinate of the point where the center of the perpendicular should be located
661+
662+
:param segmentPoint1x: : x-coordinate of segmentPoint1, the segment's start point
663+
:param segmentPoint1y: : y-coordinate of segmentPoint1, the segment's start point
664+
:param segmentPoint2x: : x-coordinate of segmentPoint2, the segment's end point
665+
:param y2: : y-coordinate of segmentPoint2, the segment's end point
666+
667+
Result is a line (segment) centered in point p and perpendicular to segment [segmentPoint1, segmentPoint2]
668+
669+
:param perpendicularSegmentPoint1x: : x-coordinate of the perpendicularCenterSegment's start point
670+
:param perpendicularSegmentPoint1y: : y-coordinate of the perpendicularCenterSegment's start point
671+
:param perpendicularSegmentPoint2x: : x-coordinate of the perpendicularCenterSegment's end point
672+
:param perpendicularSegmentPoint2y: : y-coordinate of the perpendicularCenterSegment's end point
673+
674+
\param (optional parameter) segmentLength trims to given length. Default length is double the length of the input segment. Set to 0 for normalized length which is equal to 1.
675+
676+
.. versionadded:: 3.17
677+
%End
678+
647679
static double skewLinesDistance( const QgsVector3D &P1, const QgsVector3D &P12,
648680
const QgsVector3D &P2, const QgsVector3D &P22 ) /HoldGIL/;
649681
%Docstring

‎src/core/geometry/qgsgeometryutils.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1605,6 +1605,48 @@ QgsLineString QgsGeometryUtils::perpendicularSegment( const QgsPoint &p, const Q
16051605
return line;
16061606
}
16071607

1608+
QgsLineString QgsGeometryUtils::perpendicularCenterSegment( const QgsPoint &point, const QgsPoint &segmentPoint1, const QgsPoint &segmentPoint2 )
1609+
{
1610+
QgsLineString segment;
1611+
QgsPoint p2;
1612+
1613+
/*
1614+
if ( ( p == s1 ) || ( p == s2 ) )
1615+
{
1616+
return line;
1617+
}
1618+
1619+
double a, b, c;
1620+
coefficients( s1, s2, a, b, c );
1621+
1622+
if ( qgsDoubleNear( a, 0 ) )
1623+
{
1624+
p2 = QgsPoint( p.x(), s1.y() );
1625+
}
1626+
else if ( qgsDoubleNear( b, 0 ) )
1627+
{
1628+
p2 = QgsPoint( s1.x(), p.y() );
1629+
}
1630+
else
1631+
{
1632+
double y = ( -c - a * p.x() ) / b;
1633+
double m = gradient( s1, s2 );
1634+
double d2 = 1 + m * m;
1635+
double H = p.y() - y;
1636+
double dx = m * H / d2;
1637+
double dy = m * dx;
1638+
p2 = QgsPoint( p.x() + dx, y + dy );
1639+
}*/
1640+
1641+
1642+
QgsVector segmentVector = QgsVector(segmentPoint2-segmentPoint1);
1643+
QgsVector perpendicularVector=segmentVector.perpVector();
1644+
segment.addVertex( point-perpendicularVector );
1645+
segment.addVertex( point+perpendicularVector );
1646+
return segment;
1647+
1648+
}
1649+
16081650
double QgsGeometryUtils::lineAngle( double x1, double y1, double x2, double y2 )
16091651
{
16101652
const double at = std::atan2( y2 - y1, x2 - x1 );

‎src/core/geometry/qgsgeometryutils.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,15 @@ class CORE_EXPORT QgsGeometryUtils
674674
*/
675675
static QgsLineString perpendicularSegment( const QgsPoint &p, const QgsPoint &s1, const QgsPoint &s2 ) SIP_HOLDGIL;
676676

677+
/**
678+
* \brief Create a perpendicular line segment to a given segment [segmentPoint1, segmentPoint2] with its center at centerPoint
679+
* May be used to split geometries
680+
* \param centerPoint Point where the center of the perpendicular should be located
681+
* \param segmentPoint1 The segment's start point
682+
* \param segmentPoint2 The segment's end point
683+
* \returns A line (segment) centered in point p and perpendicular to segment [segmentPoint1, segmentPoint2]
684+
*/
685+
static QgsLineString perpendicularCenterSegment( const QgsPoint &point, const QgsPoint &segmentPoint1, const QgsPoint &segmentPoint2 ) SIP_HOLDGIL;
677686

678687
/**
679688
* An algorithm to calculate the shortest distance between two skew lines.

‎tests/src/core/geometry/testqgsgeometryutils.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class TestQgsGeometryUtils: public QObject
6060
void testGradient();
6161
void testCoefficients();
6262
void testPerpendicularSegment();
63+
void testPerpendicularCenterSegment();
6364
void testClosestPoint();
6465
void testlinesIntersection3D();
6566
void testSegmentIntersection();
@@ -729,6 +730,44 @@ void TestQgsGeometryUtils::testPerpendicularSegment()
729730
QCOMPARE( line.pointN( 1 ), line_r.pointN( 1 ) );
730731
}
731732

733+
void TestQgsGeometryUtils::testPerpendicularCenterSegment()
734+
{
735+
// default case 1: centerPoint and perpendicular line on given segment
736+
QgsPoint centerPoint(2,1.5);
737+
QgsPoint segmentPoint1(2,1);
738+
QgsPoint segmentPoint2(2,2);
739+
QgsLineString perpendicular_line = QgsGeometryUtils::perpendicularCenterSegment( centerPoint, segmentPoint1, segmentPoint2 );
740+
QCOMPARE( perpendicular_line.pointN( 0 ),QgsPoint(1,1.5) );
741+
QCOMPARE( perpendicular_line.pointN( 1 ),QgsPoint(3,1.5));
742+
743+
// default case 2: centerPoint not on given segment
744+
perpendicular_line.clear();
745+
centerPoint=QgsPoint( 3, 13 );
746+
segmentPoint1=QgsPoint( 2, 3 );
747+
segmentPoint2=QgsPoint( 7, 11 );
748+
perpendicular_line = QgsGeometryUtils::perpendicularCenterSegment( centerPoint, segmentPoint1, segmentPoint2 );
749+
QCOMPARE( perpendicular_line.pointN( 0 ),QgsPoint(-5,18) );
750+
QCOMPARE( perpendicular_line.pointN( 1 ),QgsPoint(11,18) );
751+
752+
// horizontal
753+
perpendicular_line.clear();
754+
segmentPoint1 = QgsPoint( -3, 3 );
755+
segmentPoint2 = QgsPoint( 2, 3 );
756+
centerPoint = QgsPoint( 3, 13 );
757+
perpendicular_line = QgsGeometryUtils::perpendicularCenterSegment( centerPoint, segmentPoint1, segmentPoint2 );
758+
QCOMPARE( perpendicular_line.pointN( 0 ), QgsPoint(3,8) );
759+
QCOMPARE( perpendicular_line.pointN( 1 ), QgsPoint(3,18) );
760+
761+
// vertical
762+
perpendicular_line.clear();
763+
segmentPoint1 = QgsPoint( 3, 13 );
764+
segmentPoint2 = QgsPoint( 3, 3 );
765+
centerPoint = QgsPoint( -7, 8 );
766+
perpendicular_line = QgsGeometryUtils::perpendicularCenterSegment( centerPoint, segmentPoint1, segmentPoint2 );
767+
QCOMPARE( perpendicular_line.pointN( 0 ), QgsPoint(3,8) );
768+
QCOMPARE( perpendicular_line.pointN( 1 ), QgsPoint(-17,8) );
769+
}
770+
732771
void TestQgsGeometryUtils::testClosestPoint()
733772
{
734773
const QgsLineString linestringZ( QVector<QgsPoint>()

0 commit comments

Comments
 (0)
Please sign in to comment.