Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

[geometry snapper] Fix wrong point-to-segment distance within maths #56426

Merged
merged 2 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/analysis/vector/qgsgeometrysnapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,10 @@ bool QgsSnapIndex::SegmentSnapItem::getProjection( const QgsPoint &p, QgsPoint &
return true;
}

bool QgsSnapIndex::SegmentSnapItem::withinDistance( const QgsPoint &p, const double tolerance )
bool QgsSnapIndex::SegmentSnapItem::withinSquaredDistance( const QgsPoint &p, const double squaredDistance )
{
double minDistX, minDistY;
const double distance = QgsGeometryUtilsBase::sqrDistToLine( p.x(), p.y(), idxFrom->point().x(), idxFrom->point().y(), idxTo->point().x(), idxTo->point().y(), minDistX, minDistY, 4 * std::numeric_limits<double>::epsilon() );
return distance <= tolerance;
return QgsGeometryUtilsBase::sqrDistToLine( p.x(), p.y(), idxFrom->point().x(), idxFrom->point().y(), idxTo->point().x(), idxTo->point().y(), minDistX, minDistY, 4 * std::numeric_limits<double>::epsilon() ) <= squaredDistance;
}

///////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -250,6 +249,7 @@ QgsSnapIndex::SnapItem *QgsSnapIndex::getSnapItem( const QgsPoint &pos, const do
QgsSnapIndex::SegmentSnapItem *snapSegment = nullptr;
QgsSnapIndex::PointSnapItem *snapPoint = nullptr;

const double squaredTolerance = tolerance * tolerance;
const auto constItems = items;
for ( QgsSnapIndex::SnapItem *item : constItems )
{
Expand All @@ -264,7 +264,7 @@ QgsSnapIndex::SnapItem *QgsSnapIndex::getSnapItem( const QgsPoint &pos, const do
}
else if ( item->type == SnapSegment && !endPointOnly )
{
if ( !static_cast<SegmentSnapItem *>( item )->withinDistance( pos, tolerance ) )
if ( !static_cast<SegmentSnapItem *>( item )->withinSquaredDistance( pos, squaredTolerance ) )
continue;

QgsPoint pProj;
Expand All @@ -279,8 +279,8 @@ QgsSnapIndex::SnapItem *QgsSnapIndex::getSnapItem( const QgsPoint &pos, const do
}
}
}
snapPoint = minDistPoint < tolerance * tolerance ? snapPoint : nullptr;
snapSegment = minDistSegment < tolerance * tolerance ? snapSegment : nullptr;
snapPoint = minDistPoint < squaredTolerance ? snapPoint : nullptr;
snapSegment = minDistSegment < squaredTolerance ? snapSegment : nullptr;
if ( pSnapPoint ) *pSnapPoint = snapPoint;
if ( pSnapSegment ) *pSnapSegment = snapSegment;
return minDistPoint < minDistSegment ? static_cast<QgsSnapIndex::SnapItem *>( snapPoint ) : static_cast<QgsSnapIndex::SnapItem *>( snapSegment );
Expand Down
2 changes: 1 addition & 1 deletion src/analysis/vector/qgsgeometrysnapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ class QgsSnapIndex
QgsPoint getSnapPoint( const QgsPoint &p ) const override;
bool getIntersection( const QgsPoint &p1, const QgsPoint &p2, QgsPoint &inter ) const;
bool getProjection( const QgsPoint &p, QgsPoint &pProj ) const;
bool withinDistance( const QgsPoint &p, const double distance );
bool withinSquaredDistance( const QgsPoint &p, const double squaredDistance );
const CoordIdx *idxFrom = nullptr;
const CoordIdx *idxTo = nullptr;
};
Expand Down
4 changes: 4 additions & 0 deletions tests/src/analysis/testqgsgeometrysnapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,10 @@ void TestQgsGeometrySnapper::snapPointToLine()
pointGeom = QgsGeometry::fromWkt( QStringLiteral( "Point(0.5 0.5)" ) );
result = snapper.snapGeometry( pointGeom, 1 );
QCOMPARE( result.asWkt(), QStringLiteral( "Point (0 0)" ) );

pointGeom = QgsGeometry::fromWkt( QStringLiteral( "Point(3 3)" ) );
result = snapper.snapGeometry( pointGeom, 4 );
QCOMPARE( result.asWkt(), QStringLiteral( "Point (3 0)" ) );
}

void TestQgsGeometrySnapper::snapPointToLinePreferNearest()
Expand Down
Loading