mirror of
https://github.com/qgis/QGIS.git
synced 2025-03-28 00:04:04 -04:00
Apply segmentIntersection on some tools with tests.
This commit is contained in:
parent
342985f162
commit
eb292c93bb
@ -25,6 +25,7 @@
|
||||
#include "qgslinestring.h"
|
||||
#include "qgsmultipolygon.h"
|
||||
#include "qgsspinbox.h"
|
||||
#include "qgsgeometryutils.h"
|
||||
#include <memory>
|
||||
#include <QMouseEvent>
|
||||
|
||||
@ -61,9 +62,12 @@ void QgsMapToolCircle2TangentsPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e
|
||||
}
|
||||
if ( mPoints.size() == 4 )
|
||||
{
|
||||
QgsPointXY ptInter = intersect( QgsPointXY( mPoints.at( 0 ) ), QgsPointXY( mPoints.at( 1 ) ),
|
||||
QgsPointXY( mPoints.at( 2 ) ), QgsPointXY( mPoints.at( 3 ) ) );
|
||||
if ( ptInter == QgsPointXY() )
|
||||
bool isIntersect;
|
||||
const double epsilon = 1e-8;
|
||||
QgsPoint ptInter;
|
||||
QgsGeometryUtils::segmentIntersection( mPoints.at( 0 ), mPoints.at( 1 ),
|
||||
mPoints.at( 2 ), mPoints.at( 3 ), ptInter, isIntersect, epsilon );
|
||||
if ( !isIntersect )
|
||||
{
|
||||
QgisApp::instance()->messageBar()->pushMessage( tr( "Error" ), tr( "Segments are parallels" ),
|
||||
QgsMessageBar::CRITICAL, QgisApp::instance()->messageTimeout() );
|
||||
@ -144,64 +148,6 @@ void QgsMapToolCircle2TangentsPoint::cadCanvasMoveEvent( QgsMapMouseEvent *e )
|
||||
}
|
||||
}
|
||||
|
||||
QgsPointXY QgsMapToolCircle2TangentsPoint::intersect( QgsPointXY seg1_pt1, QgsPointXY seg1_pt2, QgsPointXY seg2_pt1, QgsPointXY seg2_pt2 )
|
||||
{
|
||||
/*
|
||||
* Public domain function by Darel Rex Finley, 2006
|
||||
* http://alienryderflex.com/intersect/
|
||||
*/
|
||||
QgsPointXY ptInter;
|
||||
|
||||
double Ax = seg1_pt1.x();
|
||||
double Ay = seg1_pt1.y();
|
||||
double Bx = seg1_pt2.x();
|
||||
double By = seg1_pt2.y();
|
||||
|
||||
double Cx = seg2_pt1.x();
|
||||
double Cy = seg2_pt1.y();
|
||||
double Dx = seg2_pt2.x();
|
||||
double Dy = seg2_pt2.y();
|
||||
|
||||
if ( ( ( Ax == Bx ) && ( Ay == By ) ) || ( ( Cx == Dx ) && ( Cy == Dy ) ) )
|
||||
return ptInter;
|
||||
|
||||
// (1) Translate the system so that point A is on the origin.
|
||||
Bx -= Ax;
|
||||
By -= Ay;
|
||||
Cx -= Ax;
|
||||
Cy -= Ay;
|
||||
Dx -= Ax;
|
||||
Dy -= Ay;
|
||||
|
||||
// Discover the length of segment A-B
|
||||
double distAB = sqrt( Bx * Bx + By * By );
|
||||
|
||||
// (2) Rotate the system so that point B is on the positive X axis.
|
||||
double theCos = Bx / distAB;
|
||||
double theSin = By / distAB;
|
||||
double newX = Cx * theCos + Cy * theSin;
|
||||
Cy = Cy * theCos - Cx * theSin;
|
||||
Cx = newX;
|
||||
newX = Dx * theCos + Dy * theSin;
|
||||
Dy = Dy * theCos - Dx * theSin;
|
||||
Dx = newX;
|
||||
|
||||
// Fail if the lines are parallel.
|
||||
if ( Cy == Dy )
|
||||
return ptInter;
|
||||
|
||||
// (3) Discover the position of the intersection point along line A-B.
|
||||
double ABpos = Dx + ( Cx - Dx ) * Dy / ( Dy - Cy );
|
||||
|
||||
// (4) Apply the discovered position to line A-B
|
||||
// in the original coordinate system.
|
||||
ptInter.setX( Ax + ABpos * theCos );
|
||||
ptInter.setY( Ay + ABpos * theSin );
|
||||
|
||||
// Success
|
||||
return ptInter;
|
||||
}
|
||||
|
||||
void QgsMapToolCircle2TangentsPoint::getPossibleCenter( )
|
||||
{
|
||||
|
||||
@ -226,20 +172,21 @@ void QgsMapToolCircle2TangentsPoint::getPossibleCenter( )
|
||||
QgsGeometry line2m = line2.offsetCurve( - mRadius, 8, QgsGeometry::JoinStyleBevel, 5 );
|
||||
QgsGeometry line2p = line2.offsetCurve( + mRadius, 8, QgsGeometry::JoinStyleBevel, 5 );
|
||||
|
||||
QgsPointXY p1 = intersect( line1m.asPolyline().at( 0 ), line1m.asPolyline().at( 1 ),
|
||||
line2m.asPolyline().at( 0 ), line2m.asPolyline().at( 1 ) );
|
||||
QgsPointXY p2 = intersect( line1m.asPolyline().at( 0 ), line1m.asPolyline().at( 1 ),
|
||||
line2p.asPolyline().at( 0 ), line2p.asPolyline().at( 1 ) );
|
||||
QgsPointXY p3 = intersect( line1p.asPolyline().at( 0 ), line1p.asPolyline().at( 1 ),
|
||||
line2m.asPolyline().at( 0 ), line2m.asPolyline().at( 1 ) );
|
||||
QgsPointXY p4 = intersect( line1p.asPolyline().at( 0 ), line1p.asPolyline().at( 1 ),
|
||||
line2p.asPolyline().at( 0 ), line2p.asPolyline().at( 1 ) );
|
||||
|
||||
mCenters.append( p1 );
|
||||
mCenters.append( p2 );
|
||||
mCenters.append( p3 );
|
||||
mCenters.append( p4 );
|
||||
|
||||
bool isIntersect;
|
||||
const double epsilon = 1e-8;
|
||||
QgsPoint inter;
|
||||
QgsGeometryUtils::segmentIntersection( QgsPoint( line1m.asPolyline().at( 0 ) ), QgsPoint( line1m.asPolyline().at( 1 ) ),
|
||||
QgsPoint( line2m.asPolyline().at( 0 ) ), QgsPoint( line2m.asPolyline().at( 1 ) ), inter, isIntersect, epsilon );
|
||||
mCenters.append( QgsPointXY( inter ) );
|
||||
QgsGeometryUtils::segmentIntersection( QgsPoint( line1m.asPolyline().at( 0 ) ), QgsPoint( line1m.asPolyline().at( 1 ) ),
|
||||
QgsPoint( line2p.asPolyline().at( 0 ) ), QgsPoint( line2p.asPolyline().at( 1 ) ), inter, isIntersect, epsilon );
|
||||
mCenters.append( QgsPointXY( inter ) );
|
||||
QgsGeometryUtils::segmentIntersection( QgsPoint( line1p.asPolyline().at( 0 ) ), QgsPoint( line1p.asPolyline().at( 1 ) ),
|
||||
QgsPoint( line2m.asPolyline().at( 0 ) ), QgsPoint( line2m.asPolyline().at( 1 ) ), inter, isIntersect, epsilon );
|
||||
mCenters.append( QgsPointXY( inter ) );
|
||||
QgsGeometryUtils::segmentIntersection( QgsPoint( line1p.asPolyline().at( 0 ) ), QgsPoint( line1p.asPolyline().at( 1 ) ),
|
||||
QgsPoint( line2p.asPolyline().at( 0 ) ), QgsPoint( line2p.asPolyline().at( 1 ) ), inter, isIntersect, epsilon );
|
||||
mCenters.append( QgsPointXY( inter ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,9 +38,6 @@ class QgsMapToolCircle2TangentsPoint: public QgsMapToolAddCircle
|
||||
void radiusSpinBoxChanged( int radius );
|
||||
|
||||
private:
|
||||
//! Return the point where segments are intersected. Method from QgsGeometryUtils doesn't work for special cases used by this tool.
|
||||
QgsPointXY intersect( QgsPointXY seg1_pt1, QgsPointXY seg1_pt2, QgsPointXY seg2_pt1, QgsPointXY seg2_pt2 );
|
||||
|
||||
//! Compute 4 possible centers
|
||||
void getPossibleCenter();
|
||||
|
||||
|
@ -182,10 +182,16 @@ QgsCircle QgsCircle::fromCenterPoint( const QgsPoint ¢er, const QgsPoint &pt
|
||||
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 )
|
||||
{
|
||||
QgsPoint p1, p2, p3;
|
||||
bool intersection;
|
||||
QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg2, pt2_tg2, p1, intersection, epsilon );
|
||||
QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg3, pt2_tg3, p2, intersection, epsilon );
|
||||
QgsGeometryUtils::segmentIntersection( pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, p3, intersection, epsilon );
|
||||
bool isIntersect;
|
||||
QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg2, pt2_tg2, p1, isIntersect, epsilon );
|
||||
if ( !isIntersect )
|
||||
return QgsCircle();
|
||||
QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg3, pt2_tg3, p2, isIntersect, epsilon );
|
||||
if ( !isIntersect )
|
||||
return QgsCircle();
|
||||
QgsGeometryUtils::segmentIntersection( pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, p3, isIntersect, epsilon );
|
||||
if ( !isIntersect )
|
||||
return QgsCircle();
|
||||
|
||||
return QgsTriangle( p1, p2, p3 ).inscribedCircle();
|
||||
}
|
||||
|
@ -6973,6 +6973,13 @@ void TestQgsGeometry::circle()
|
||||
QgsCircle circ_tgt = QgsCircle().from3Tangents( QgsPoint( 0, 0 ), QgsPoint( 0, 1 ), QgsPoint( 2, 0 ), QgsPoint( 3, 0 ), QgsPoint( 5, 0 ), QgsPoint( 0, 5 ) );
|
||||
QGSCOMPARENEARPOINT( circ_tgt.center(), QgsPoint( 1.4645, 1.4645 ), 0.0001 );
|
||||
QGSCOMPARENEAR( circ_tgt.radius(), 1.4645, 0.0001 );
|
||||
// with parallels
|
||||
circ_tgt = QgsCircle().from3Tangents( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 0 ), QgsPoint( 1, 5 ), QgsPoint( 5, 0 ), QgsPoint( 0, 5 ) );
|
||||
QVERIFY( circ_tgt.isEmpty() );
|
||||
circ_tgt = QgsCircle().from3Tangents( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 5, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 0 ), QgsPoint( 1, 5 ) );
|
||||
QVERIFY( circ_tgt.isEmpty() );
|
||||
circ_tgt = QgsCircle().from3Tangents( QgsPoint( 5, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 0 ), QgsPoint( 1, 5 ) );
|
||||
QVERIFY( circ_tgt.isEmpty() );
|
||||
// minimalCircleFrom3points
|
||||
QgsCircle minCircle3Points = QgsCircle().minimalCircleFrom3Points( QgsPoint( 0, 5 ), QgsPoint( 0, -5 ), QgsPoint( 1, 2 ) );
|
||||
QGSCOMPARENEARPOINT( minCircle3Points.center(), QgsPoint( 0, 0 ), 0.0001 );
|
||||
|
Loading…
x
Reference in New Issue
Block a user