Skip to content

Commit eb292c9

Browse files
committed
Apply segmentIntersection on some tools with tests.
1 parent 342985f commit eb292c9

File tree

4 files changed

+39
-82
lines changed

4 files changed

+39
-82
lines changed

src/app/qgsmaptoolcircle2tangentspoint.cpp

+22-75
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "qgslinestring.h"
2626
#include "qgsmultipolygon.h"
2727
#include "qgsspinbox.h"
28+
#include "qgsgeometryutils.h"
2829
#include <memory>
2930
#include <QMouseEvent>
3031

@@ -61,9 +62,12 @@ void QgsMapToolCircle2TangentsPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e
6162
}
6263
if ( mPoints.size() == 4 )
6364
{
64-
QgsPointXY ptInter = intersect( QgsPointXY( mPoints.at( 0 ) ), QgsPointXY( mPoints.at( 1 ) ),
65-
QgsPointXY( mPoints.at( 2 ) ), QgsPointXY( mPoints.at( 3 ) ) );
66-
if ( ptInter == QgsPointXY() )
65+
bool isIntersect;
66+
const double epsilon = 1e-8;
67+
QgsPoint ptInter;
68+
QgsGeometryUtils::segmentIntersection( mPoints.at( 0 ), mPoints.at( 1 ),
69+
mPoints.at( 2 ), mPoints.at( 3 ), ptInter, isIntersect, epsilon );
70+
if ( !isIntersect )
6771
{
6872
QgisApp::instance()->messageBar()->pushMessage( tr( "Error" ), tr( "Segments are parallels" ),
6973
QgsMessageBar::CRITICAL, QgisApp::instance()->messageTimeout() );
@@ -144,64 +148,6 @@ void QgsMapToolCircle2TangentsPoint::cadCanvasMoveEvent( QgsMapMouseEvent *e )
144148
}
145149
}
146150

147-
QgsPointXY QgsMapToolCircle2TangentsPoint::intersect( QgsPointXY seg1_pt1, QgsPointXY seg1_pt2, QgsPointXY seg2_pt1, QgsPointXY seg2_pt2 )
148-
{
149-
/*
150-
* Public domain function by Darel Rex Finley, 2006
151-
* http://alienryderflex.com/intersect/
152-
*/
153-
QgsPointXY ptInter;
154-
155-
double Ax = seg1_pt1.x();
156-
double Ay = seg1_pt1.y();
157-
double Bx = seg1_pt2.x();
158-
double By = seg1_pt2.y();
159-
160-
double Cx = seg2_pt1.x();
161-
double Cy = seg2_pt1.y();
162-
double Dx = seg2_pt2.x();
163-
double Dy = seg2_pt2.y();
164-
165-
if ( ( ( Ax == Bx ) && ( Ay == By ) ) || ( ( Cx == Dx ) && ( Cy == Dy ) ) )
166-
return ptInter;
167-
168-
// (1) Translate the system so that point A is on the origin.
169-
Bx -= Ax;
170-
By -= Ay;
171-
Cx -= Ax;
172-
Cy -= Ay;
173-
Dx -= Ax;
174-
Dy -= Ay;
175-
176-
// Discover the length of segment A-B
177-
double distAB = sqrt( Bx * Bx + By * By );
178-
179-
// (2) Rotate the system so that point B is on the positive X axis.
180-
double theCos = Bx / distAB;
181-
double theSin = By / distAB;
182-
double newX = Cx * theCos + Cy * theSin;
183-
Cy = Cy * theCos - Cx * theSin;
184-
Cx = newX;
185-
newX = Dx * theCos + Dy * theSin;
186-
Dy = Dy * theCos - Dx * theSin;
187-
Dx = newX;
188-
189-
// Fail if the lines are parallel.
190-
if ( Cy == Dy )
191-
return ptInter;
192-
193-
// (3) Discover the position of the intersection point along line A-B.
194-
double ABpos = Dx + ( Cx - Dx ) * Dy / ( Dy - Cy );
195-
196-
// (4) Apply the discovered position to line A-B
197-
// in the original coordinate system.
198-
ptInter.setX( Ax + ABpos * theCos );
199-
ptInter.setY( Ay + ABpos * theSin );
200-
201-
// Success
202-
return ptInter;
203-
}
204-
205151
void QgsMapToolCircle2TangentsPoint::getPossibleCenter( )
206152
{
207153

@@ -226,20 +172,21 @@ void QgsMapToolCircle2TangentsPoint::getPossibleCenter( )
226172
QgsGeometry line2m = line2.offsetCurve( - mRadius, 8, QgsGeometry::JoinStyleBevel, 5 );
227173
QgsGeometry line2p = line2.offsetCurve( + mRadius, 8, QgsGeometry::JoinStyleBevel, 5 );
228174

229-
QgsPointXY p1 = intersect( line1m.asPolyline().at( 0 ), line1m.asPolyline().at( 1 ),
230-
line2m.asPolyline().at( 0 ), line2m.asPolyline().at( 1 ) );
231-
QgsPointXY p2 = intersect( line1m.asPolyline().at( 0 ), line1m.asPolyline().at( 1 ),
232-
line2p.asPolyline().at( 0 ), line2p.asPolyline().at( 1 ) );
233-
QgsPointXY p3 = intersect( line1p.asPolyline().at( 0 ), line1p.asPolyline().at( 1 ),
234-
line2m.asPolyline().at( 0 ), line2m.asPolyline().at( 1 ) );
235-
QgsPointXY p4 = intersect( line1p.asPolyline().at( 0 ), line1p.asPolyline().at( 1 ),
236-
line2p.asPolyline().at( 0 ), line2p.asPolyline().at( 1 ) );
237-
238-
mCenters.append( p1 );
239-
mCenters.append( p2 );
240-
mCenters.append( p3 );
241-
mCenters.append( p4 );
242-
175+
bool isIntersect;
176+
const double epsilon = 1e-8;
177+
QgsPoint inter;
178+
QgsGeometryUtils::segmentIntersection( QgsPoint( line1m.asPolyline().at( 0 ) ), QgsPoint( line1m.asPolyline().at( 1 ) ),
179+
QgsPoint( line2m.asPolyline().at( 0 ) ), QgsPoint( line2m.asPolyline().at( 1 ) ), inter, isIntersect, epsilon );
180+
mCenters.append( QgsPointXY( inter ) );
181+
QgsGeometryUtils::segmentIntersection( QgsPoint( line1m.asPolyline().at( 0 ) ), QgsPoint( line1m.asPolyline().at( 1 ) ),
182+
QgsPoint( line2p.asPolyline().at( 0 ) ), QgsPoint( line2p.asPolyline().at( 1 ) ), inter, isIntersect, epsilon );
183+
mCenters.append( QgsPointXY( inter ) );
184+
QgsGeometryUtils::segmentIntersection( QgsPoint( line1p.asPolyline().at( 0 ) ), QgsPoint( line1p.asPolyline().at( 1 ) ),
185+
QgsPoint( line2m.asPolyline().at( 0 ) ), QgsPoint( line2m.asPolyline().at( 1 ) ), inter, isIntersect, epsilon );
186+
mCenters.append( QgsPointXY( inter ) );
187+
QgsGeometryUtils::segmentIntersection( QgsPoint( line1p.asPolyline().at( 0 ) ), QgsPoint( line1p.asPolyline().at( 1 ) ),
188+
QgsPoint( line2p.asPolyline().at( 0 ) ), QgsPoint( line2p.asPolyline().at( 1 ) ), inter, isIntersect, epsilon );
189+
mCenters.append( QgsPointXY( inter ) );
243190
}
244191
}
245192

src/app/qgsmaptoolcircle2tangentspoint.h

-3
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,6 @@ class QgsMapToolCircle2TangentsPoint: public QgsMapToolAddCircle
3838
void radiusSpinBoxChanged( int radius );
3939

4040
private:
41-
//! Return the point where segments are intersected. Method from QgsGeometryUtils doesn't work for special cases used by this tool.
42-
QgsPointXY intersect( QgsPointXY seg1_pt1, QgsPointXY seg1_pt2, QgsPointXY seg2_pt1, QgsPointXY seg2_pt2 );
43-
4441
//! Compute 4 possible centers
4542
void getPossibleCenter();
4643

src/core/geometry/qgscircle.cpp

+10-4
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,16 @@ QgsCircle QgsCircle::fromCenterPoint( const QgsPoint &center, const QgsPoint &pt
182182
QgsCircle QgsCircle::from3Tangents( const QgsPoint &pt1_tg1, const QgsPoint &pt2_tg1, const QgsPoint &pt1_tg2, const QgsPoint &pt2_tg2, const QgsPoint &pt1_tg3, const QgsPoint &pt2_tg3, double epsilon )
183183
{
184184
QgsPoint p1, p2, p3;
185-
bool intersection;
186-
QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg2, pt2_tg2, p1, intersection, epsilon );
187-
QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg3, pt2_tg3, p2, intersection, epsilon );
188-
QgsGeometryUtils::segmentIntersection( pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, p3, intersection, epsilon );
185+
bool isIntersect;
186+
QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg2, pt2_tg2, p1, isIntersect, epsilon );
187+
if ( !isIntersect )
188+
return QgsCircle();
189+
QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg3, pt2_tg3, p2, isIntersect, epsilon );
190+
if ( !isIntersect )
191+
return QgsCircle();
192+
QgsGeometryUtils::segmentIntersection( pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, p3, isIntersect, epsilon );
193+
if ( !isIntersect )
194+
return QgsCircle();
189195

190196
return QgsTriangle( p1, p2, p3 ).inscribedCircle();
191197
}

tests/src/core/testqgsgeometry.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -6973,6 +6973,13 @@ void TestQgsGeometry::circle()
69736973
QgsCircle circ_tgt = QgsCircle().from3Tangents( QgsPoint( 0, 0 ), QgsPoint( 0, 1 ), QgsPoint( 2, 0 ), QgsPoint( 3, 0 ), QgsPoint( 5, 0 ), QgsPoint( 0, 5 ) );
69746974
QGSCOMPARENEARPOINT( circ_tgt.center(), QgsPoint( 1.4645, 1.4645 ), 0.0001 );
69756975
QGSCOMPARENEAR( circ_tgt.radius(), 1.4645, 0.0001 );
6976+
// with parallels
6977+
circ_tgt = QgsCircle().from3Tangents( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 0 ), QgsPoint( 1, 5 ), QgsPoint( 5, 0 ), QgsPoint( 0, 5 ) );
6978+
QVERIFY( circ_tgt.isEmpty() );
6979+
circ_tgt = QgsCircle().from3Tangents( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 5, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 0 ), QgsPoint( 1, 5 ) );
6980+
QVERIFY( circ_tgt.isEmpty() );
6981+
circ_tgt = QgsCircle().from3Tangents( QgsPoint( 5, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 0 ), QgsPoint( 1, 5 ) );
6982+
QVERIFY( circ_tgt.isEmpty() );
69766983
// minimalCircleFrom3points
69776984
QgsCircle minCircle3Points = QgsCircle().minimalCircleFrom3Points( QgsPoint( 0, 5 ), QgsPoint( 0, -5 ), QgsPoint( 1, 2 ) );
69786985
QGSCOMPARENEARPOINT( minCircle3Points.center(), QgsPoint( 0, 0 ), 0.0001 );

0 commit comments

Comments
 (0)