Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add QgsGeometryUtils::perpendicularCenterSegment() with description i…
…n header file, test case and sip.in for Docx
  • Loading branch information
tschmetzer authored and nyalldawson committed Jan 6, 2022
1 parent c6fd773 commit 9cbcae5
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 0 deletions.
32 changes: 32 additions & 0 deletions python/core/auto_generated/geometry/qgsgeometryutils.sip.in
Expand Up @@ -644,6 +644,38 @@ Create a perpendicular line segment from p to segment [s1, s2]
%End


static void perpendicularCenterSegment( double centerPointx, double centerPointy,
double segmentPoint1x, double segmentPoint1y,
double segmentPoint2x, double segmentPoint2y,
double &perpendicularSegmentPoint1x /Out/, double &perpendicularSegmentPoint1y /Out/,
double &perpendicularSegmentPoint2x /Out/, double &perpendicularSegmentPoint2y /Out/,
double *segmentLength=0
) /HoldGIL/;
%Docstring
Create a perpendicular line segment to a given segment [``segmentPoint1``,``segmentPoint2``] with its center at ``centerPoint``.

May be used to split geometries. The new centered perpendicular line segment will have double the length of the input segment

:param centerPointx: x-coordinate of the point where the center of the perpendicular should be located
:param centerPointy: y-coordinate of the point where the center of the perpendicular should be located

:param segmentPoint1x: : x-coordinate of segmentPoint1, the segment's start point
:param segmentPoint1y: : y-coordinate of segmentPoint1, the segment's start point
:param segmentPoint2x: : x-coordinate of segmentPoint2, the segment's end point
:param y2: : y-coordinate of segmentPoint2, the segment's end point

Result is a line (segment) centered in point p and perpendicular to segment [segmentPoint1, segmentPoint2]

:param perpendicularSegmentPoint1x: : x-coordinate of the perpendicularCenterSegment's start point
:param perpendicularSegmentPoint1y: : y-coordinate of the perpendicularCenterSegment's start point
:param perpendicularSegmentPoint2x: : x-coordinate of the perpendicularCenterSegment's end point
:param perpendicularSegmentPoint2y: : y-coordinate of the perpendicularCenterSegment's end point

\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.

.. versionadded:: 3.17
%End

static double skewLinesDistance( const QgsVector3D &P1, const QgsVector3D &P12,
const QgsVector3D &P2, const QgsVector3D &P22 ) /HoldGIL/;
%Docstring
Expand Down
42 changes: 42 additions & 0 deletions src/core/geometry/qgsgeometryutils.cpp
Expand Up @@ -1605,6 +1605,48 @@ QgsLineString QgsGeometryUtils::perpendicularSegment( const QgsPoint &p, const Q
return line;
}

QgsLineString QgsGeometryUtils::perpendicularCenterSegment( const QgsPoint &point, const QgsPoint &segmentPoint1, const QgsPoint &segmentPoint2 )
{
QgsLineString segment;
QgsPoint p2;

/*
if ( ( p == s1 ) || ( p == s2 ) )
{
return line;
}
double a, b, c;
coefficients( s1, s2, a, b, c );
if ( qgsDoubleNear( a, 0 ) )
{
p2 = QgsPoint( p.x(), s1.y() );
}
else if ( qgsDoubleNear( b, 0 ) )
{
p2 = QgsPoint( s1.x(), p.y() );
}
else
{
double y = ( -c - a * p.x() ) / b;
double m = gradient( s1, s2 );
double d2 = 1 + m * m;
double H = p.y() - y;
double dx = m * H / d2;
double dy = m * dx;
p2 = QgsPoint( p.x() + dx, y + dy );
}*/


QgsVector segmentVector = QgsVector(segmentPoint2-segmentPoint1);
QgsVector perpendicularVector=segmentVector.perpVector();
segment.addVertex( point-perpendicularVector );
segment.addVertex( point+perpendicularVector );
return segment;

}

double QgsGeometryUtils::lineAngle( double x1, double y1, double x2, double y2 )
{
const double at = std::atan2( y2 - y1, x2 - x1 );
Expand Down
9 changes: 9 additions & 0 deletions src/core/geometry/qgsgeometryutils.h
Expand Up @@ -674,6 +674,15 @@ class CORE_EXPORT QgsGeometryUtils
*/
static QgsLineString perpendicularSegment( const QgsPoint &p, const QgsPoint &s1, const QgsPoint &s2 ) SIP_HOLDGIL;

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

/**
* An algorithm to calculate the shortest distance between two skew lines.
Expand Down
39 changes: 39 additions & 0 deletions tests/src/core/geometry/testqgsgeometryutils.cpp
Expand Up @@ -60,6 +60,7 @@ class TestQgsGeometryUtils: public QObject
void testGradient();
void testCoefficients();
void testPerpendicularSegment();
void testPerpendicularCenterSegment();
void testClosestPoint();
void testlinesIntersection3D();
void testSegmentIntersection();
Expand Down Expand Up @@ -729,6 +730,44 @@ void TestQgsGeometryUtils::testPerpendicularSegment()
QCOMPARE( line.pointN( 1 ), line_r.pointN( 1 ) );
}

void TestQgsGeometryUtils::testPerpendicularCenterSegment()
{
// default case 1: centerPoint and perpendicular line on given segment
QgsPoint centerPoint(2,1.5);
QgsPoint segmentPoint1(2,1);
QgsPoint segmentPoint2(2,2);
QgsLineString perpendicular_line = QgsGeometryUtils::perpendicularCenterSegment( centerPoint, segmentPoint1, segmentPoint2 );
QCOMPARE( perpendicular_line.pointN( 0 ),QgsPoint(1,1.5) );
QCOMPARE( perpendicular_line.pointN( 1 ),QgsPoint(3,1.5));

// default case 2: centerPoint not on given segment
perpendicular_line.clear();
centerPoint=QgsPoint( 3, 13 );
segmentPoint1=QgsPoint( 2, 3 );
segmentPoint2=QgsPoint( 7, 11 );
perpendicular_line = QgsGeometryUtils::perpendicularCenterSegment( centerPoint, segmentPoint1, segmentPoint2 );
QCOMPARE( perpendicular_line.pointN( 0 ),QgsPoint(-5,18) );
QCOMPARE( perpendicular_line.pointN( 1 ),QgsPoint(11,18) );

// horizontal
perpendicular_line.clear();
segmentPoint1 = QgsPoint( -3, 3 );
segmentPoint2 = QgsPoint( 2, 3 );
centerPoint = QgsPoint( 3, 13 );
perpendicular_line = QgsGeometryUtils::perpendicularCenterSegment( centerPoint, segmentPoint1, segmentPoint2 );
QCOMPARE( perpendicular_line.pointN( 0 ), QgsPoint(3,8) );
QCOMPARE( perpendicular_line.pointN( 1 ), QgsPoint(3,18) );

// vertical
perpendicular_line.clear();
segmentPoint1 = QgsPoint( 3, 13 );
segmentPoint2 = QgsPoint( 3, 3 );
centerPoint = QgsPoint( -7, 8 );
perpendicular_line = QgsGeometryUtils::perpendicularCenterSegment( centerPoint, segmentPoint1, segmentPoint2 );
QCOMPARE( perpendicular_line.pointN( 0 ), QgsPoint(3,8) );
QCOMPARE( perpendicular_line.pointN( 1 ), QgsPoint(-17,8) );
}

void TestQgsGeometryUtils::testClosestPoint()
{
const QgsLineString linestringZ( QVector<QgsPoint>()
Expand Down

0 comments on commit 9cbcae5

Please sign in to comment.