Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #5758 from nyalldawson/leftof
Geometry "leftOf" improvements
  • Loading branch information
nyalldawson committed Nov 29, 2017
2 parents 62dbf4c + b8a62f4 commit e4ce623
Show file tree
Hide file tree
Showing 32 changed files with 168 additions and 144 deletions.
4 changes: 4 additions & 0 deletions doc/api_break.dox
Expand Up @@ -456,6 +456,9 @@ QgsAbstractGeometry {#qgis_api_break_3_0_QgsAbstractGeometry}
- asGML2() was renamed to asGml2()
- asGML3() was renamed to asGml3()
- asJSON() was renamed to asJson()
- closestSegment() now returns an integer value for the leftOf test (-1 if point is to the left
of the geometry, +1 if the point is to the right of the geometry, or 0 for cases where left/right could not
be determined, e.g. point exactly on a line)


QgsActionManager {#qgis_api_break_3_0_QgsActionManager}
Expand Down Expand Up @@ -1338,6 +1341,7 @@ maintains Z or M dimensions from the input points and is more efficient.
- fromMultiPolygon() was renamed to fromMultiPolygonXY()
- exportToWkt() was renamed to asWkt()
- exportToGeoJSON() was renamed to asJson()
- closestSegmentWithContext() now returns an extra value, indicating whether the point is to the left of the geometry


QgsGeometryAnalyzer {#qgis_api_break_3_0_QgsGeometryAnalyzer}
Expand Down
6 changes: 4 additions & 2 deletions python/core/geometry/qgsabstractgeometry.sip
Expand Up @@ -299,13 +299,15 @@ class QgsAbstractGeometry

virtual double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt /Out/,
QgsVertexId &vertexAfter /Out/,
bool *leftOf /Out/ = 0, double epsilon = 4 * DBL_EPSILON ) const = 0;
int *leftOf /Out/ = 0, double epsilon = 4 * DBL_EPSILON ) const = 0;
%Docstring
Searches for the closest segment of the geometry to a given point.
\param pt specifies the point to find closest segment to
\param segmentPt storage for the closest point within the geometry
\param vertexAfter storage for the ID of the vertex at the end of the closest segment
\param leftOf returns whether the point lies on the left side of the nearest segment (true if point is to left of segment,
\param leftOf indicates whether the point lies on the left side of the geometry (-1 if point is to the left
of the geometry, +1 if the point is to the right of the geometry, or 0 for cases where left/right could not
be determined, e.g. point exactly on a line)
false if point is to right of segment)
\param epsilon epsilon for segment snapping
:return: squared distance to closest segment or negative value on error
Expand Down
2 changes: 1 addition & 1 deletion python/core/geometry/qgscircularstring.sip
Expand Up @@ -99,7 +99,7 @@ class QgsCircularString: QgsCurve

virtual bool deleteVertex( QgsVertexId position );

virtual double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt /Out/, QgsVertexId &vertexAfter /Out/, bool *leftOf /Out/ = 0, double epsilon = 4 * DBL_EPSILON ) const;
virtual double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt /Out/, QgsVertexId &vertexAfter /Out/, int *leftOf /Out/ = 0, double epsilon = 4 * DBL_EPSILON ) const;

virtual bool pointAt( int node, QgsPoint &point, QgsVertexId::VertexType &type ) const;

Expand Down
2 changes: 1 addition & 1 deletion python/core/geometry/qgscompoundcurve.sip
Expand Up @@ -124,7 +124,7 @@ class QgsCompoundCurve: QgsCurve

virtual bool deleteVertex( QgsVertexId position );

virtual double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt /Out/, QgsVertexId &vertexAfter /Out/, bool *leftOf /Out/ = 0, double epsilon = 4 * DBL_EPSILON ) const;
virtual double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt /Out/, QgsVertexId &vertexAfter /Out/, int *leftOf /Out/ = 0, double epsilon = 4 * DBL_EPSILON ) const;

virtual bool pointAt( int node, QgsPoint &point, QgsVertexId::VertexType &type ) const;

Expand Down
2 changes: 1 addition & 1 deletion python/core/geometry/qgscurvepolygon.sip
Expand Up @@ -149,7 +149,7 @@ Adds an interior ring to the geometry (takes ownership)

virtual bool isEmpty() const;

virtual double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt /Out/, QgsVertexId &vertexAfter /Out/, bool *leftOf /Out/ = 0, double epsilon = 4 * DBL_EPSILON ) const;
virtual double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt /Out/, QgsVertexId &vertexAfter /Out/, int *leftOf /Out/ = 0, double epsilon = 4 * DBL_EPSILON ) const;


virtual bool nextVertex( QgsVertexId &id, QgsPoint &vertex /Out/ ) const;
Expand Down
5 changes: 3 additions & 2 deletions python/core/geometry/qgsgeometry.sip
Expand Up @@ -493,14 +493,15 @@ Returns true if WKB of the geometry is of WKBMulti* type
:rtype: float
%End

double closestSegmentWithContext( const QgsPointXY &point, QgsPointXY &minDistPoint /Out/, int &afterVertex /Out/ ) const;
double closestSegmentWithContext( const QgsPointXY &point, QgsPointXY &minDistPoint /Out/, int &afterVertex /Out/, int *leftOf /Out/ = 0, double epsilon = DEFAULT_SEGMENT_EPSILON ) const;
%Docstring
Searches for the closest segment of geometry to the given point
\param point Specifies the point for search
\param minDistPoint Receives the nearest point on the segment
\param afterVertex Receives index of the vertex after the closest segment. The vertex
before the closest segment is always afterVertex - 1
\param leftOf Out: Returns if the point lies on the left of right side of the segment ( < 0 means left, > 0 means right )
\param leftOf Out: Returns if the point lies on the left of left side of the geometry ( < 0 means left, > 0 means right, 0 indicates
that the test was unsuccesful, e.g. for a point exactly on the line)
\param epsilon epsilon for segment snapping
:return: The squared Cartesian distance is also returned in sqrDist, negative number on error
:rtype: float
Expand Down
2 changes: 1 addition & 1 deletion python/core/geometry/qgsgeometrycollection.sip
Expand Up @@ -112,7 +112,7 @@ Adds a geometry and takes ownership. Returns true in case of success.
virtual int nCoordinates() const;


virtual double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt /Out/, QgsVertexId &vertexAfter /Out/, bool *leftOf /Out/ = 0, double epsilon = 4 * DBL_EPSILON ) const;
virtual double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt /Out/, QgsVertexId &vertexAfter /Out/, int *leftOf /Out/ = 0, double epsilon = 4 * DBL_EPSILON ) const;

virtual bool nextVertex( QgsVertexId &id, QgsPoint &vertex /Out/ ) const;

Expand Down
4 changes: 2 additions & 2 deletions python/core/geometry/qgsgeometryutils.sip
Expand Up @@ -123,14 +123,14 @@ class QgsGeometryUtils



static double leftOfLine( double x, double y, double x1, double y1, double x2, double y2 );
static int leftOfLine( double x, double y, double x1, double y1, double x2, double y2 );
%Docstring
Returns a value < 0 if the point (``x``, ``y``) is left of the line from (``x1``, ``y1``) -> ( ``x2``, ``y2``).
A positive return value indicates the point is to the right of the line.

If the return value is 0, then the test was unsuccessful (e.g. due to testing a point exactly
on the line, or exactly in line with the segment) and the result is undefined.
:rtype: float
:rtype: int
%End

static QgsPoint pointOnLineWithDistance( const QgsPoint &startPoint, const QgsPoint &directionPoint, double distance );
Expand Down
2 changes: 1 addition & 1 deletion python/core/geometry/qgslinestring.sip
Expand Up @@ -243,7 +243,7 @@ Closes the line string by appending the first point to the end of the line, if i
virtual QgsLineString *reversed() const /Factory/;


virtual double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt /Out/, QgsVertexId &vertexAfter /Out/, bool *leftOf /Out/ = 0, double epsilon = 4 * DBL_EPSILON ) const;
virtual double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt /Out/, QgsVertexId &vertexAfter /Out/, int *leftOf /Out/ = 0, double epsilon = 4 * DBL_EPSILON ) const;

virtual bool pointAt( int node, QgsPoint &point, QgsVertexId::VertexType &type ) const;

Expand Down
2 changes: 1 addition & 1 deletion python/core/geometry/qgspoint.sip
Expand Up @@ -377,7 +377,7 @@ class QgsPoint: QgsAbstractGeometry
virtual bool deleteVertex( QgsVertexId position );


virtual double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt /Out/, QgsVertexId &vertexAfter /Out/, bool *leftOf /Out/ = 0, double epsilon = 4 * DBL_EPSILON ) const;
virtual double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt /Out/, QgsVertexId &vertexAfter /Out/, int *leftOf /Out/ = 0, double epsilon = 4 * DBL_EPSILON ) const;

virtual bool nextVertex( QgsVertexId &id, QgsPoint &vertex /Out/ ) const;

Expand Down
6 changes: 3 additions & 3 deletions src/app/qgsmaptooloffsetcurve.cpp
Expand Up @@ -242,7 +242,7 @@ void QgsMapToolOffsetCurve::canvasMoveEvent( QgsMapMouseEvent *e )

QgsPointXY minDistPoint;
int beforeVertex;
double leftOf;
int leftOf = 0;
double offset = std::sqrt( mOriginalGeometry.closestSegmentWithContext( layerCoords, minDistPoint, beforeVertex, &leftOf ) );
if ( offset == 0.0 )
{
Expand All @@ -254,13 +254,13 @@ void QgsMapToolOffsetCurve::canvasMoveEvent( QgsMapMouseEvent *e )
if ( mDistanceWidget )
{
// this will also set the rubber band
mDistanceWidget->setValue( leftOf < 0 ? -offset : offset );
mDistanceWidget->setValue( leftOf < 0 ? offset : -offset );
mDistanceWidget->setFocus( Qt::TabFocusReason );
}
else
{
//create offset geometry using geos
setOffsetForRubberBand( leftOf < 0 ? -offset : offset );
setOffsetForRubberBand( leftOf < 0 ? offset : -offset );
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/app/qgsmaptoolrectangle3points.cpp
Expand Up @@ -76,9 +76,9 @@ void QgsMapToolRectangle3Points::cadCanvasMoveEvent( QgsMapMouseEvent *e )
{

setDistance2( mPoints.at( 1 ).distance( mapPoint ) );
double side = QgsGeometryUtils::leftOfLine( mapPoint.x(), mapPoint.y(),
mPoints.at( 0 ).x(), mPoints.at( 0 ).y(),
mPoints.at( 1 ).x(), mPoints.at( 1 ).y() );
int side = QgsGeometryUtils::leftOfLine( mapPoint.x(), mapPoint.y(),
mPoints.at( 0 ).x(), mPoints.at( 0 ).y(),
mPoints.at( 1 ).x(), mPoints.at( 1 ).y() );

setSide( side < 0 ? -1 : 1 );

Expand Down
6 changes: 4 additions & 2 deletions src/core/geometry/qgsabstractgeometry.h
Expand Up @@ -324,14 +324,16 @@ class CORE_EXPORT QgsAbstractGeometry
* \param pt specifies the point to find closest segment to
* \param segmentPt storage for the closest point within the geometry
* \param vertexAfter storage for the ID of the vertex at the end of the closest segment
* \param leftOf returns whether the point lies on the left side of the nearest segment (true if point is to left of segment,
* \param leftOf indicates whether the point lies on the left side of the geometry (-1 if point is to the left
* of the geometry, +1 if the point is to the right of the geometry, or 0 for cases where left/right could not
* be determined, e.g. point exactly on a line)
* false if point is to right of segment)
* \param epsilon epsilon for segment snapping
* \returns squared distance to closest segment or negative value on error
*/
virtual double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt SIP_OUT,
QgsVertexId &vertexAfter SIP_OUT,
bool *leftOf SIP_OUT = nullptr, double epsilon = 4 * DBL_EPSILON ) const = 0;
int *leftOf SIP_OUT = nullptr, double epsilon = 4 * DBL_EPSILON ) const = 0;

//low-level editing

Expand Down
11 changes: 6 additions & 5 deletions src/core/geometry/qgscircularstring.cpp
Expand Up @@ -732,12 +732,12 @@ void QgsCircularString::deleteVertex( int i )
clearCache();
}

double QgsCircularString::closestSegment( const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, bool *leftOf, double epsilon ) const
double QgsCircularString::closestSegment( const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf, double epsilon ) const
{
double minDist = std::numeric_limits<double>::max();
QgsPoint minDistSegmentPoint;
QgsVertexId minDistVertexAfter;
bool minDistLeftOf = false;
int minDistLeftOf = 0;

double currentDist = 0.0;

Expand Down Expand Up @@ -766,7 +766,7 @@ double QgsCircularString::closestSegment( const QgsPoint &pt, QgsPoint &segmentP
vertexAfter.ring = 0;
if ( leftOf )
{
*leftOf = minDistLeftOf;
*leftOf = qgsDoubleNear( minDist, 0.0 ) ? 0 : minDistLeftOf;
}
return minDist;
}
Expand Down Expand Up @@ -849,7 +849,7 @@ bool QgsCircularString::hasCurvedSegments() const
}

double QgsCircularString::closestPointOnArc( double x1, double y1, double x2, double y2, double x3, double y3,
const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, bool *leftOf, double epsilon )
const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf, double epsilon )
{
double radius, centerX, centerY;
QgsPoint pt1( x1, y1 );
Expand Down Expand Up @@ -892,7 +892,8 @@ double QgsCircularString::closestPointOnArc( double x1, double y1, double x2, do
if ( leftOf )
{
double sqrDistancePointToCenter = ( pt.x() - centerX ) * ( pt.x() - centerX ) + ( pt.y() - centerY ) * ( pt.y() - centerY );
*leftOf = clockwise ? sqrDistancePointToCenter > radius * radius : sqrDistancePointToCenter < radius * radius;
*leftOf = clockwise ? ( sqrDistancePointToCenter > radius * radius ? -1 : 1 )
: ( sqrDistancePointToCenter < radius * radius ? -1 : 1 );
}

return sqrDistance;
Expand Down
4 changes: 2 additions & 2 deletions src/core/geometry/qgscircularstring.h
Expand Up @@ -82,7 +82,7 @@ class CORE_EXPORT QgsCircularString: public QgsCurve
bool insertVertex( QgsVertexId position, const QgsPoint &vertex ) override;
bool moveVertex( QgsVertexId position, const QgsPoint &newPos ) override;
bool deleteVertex( QgsVertexId position ) override;
double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt SIP_OUT, QgsVertexId &vertexAfter SIP_OUT, bool *leftOf SIP_OUT = nullptr, double epsilon = 4 * DBL_EPSILON ) const override;
double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt SIP_OUT, QgsVertexId &vertexAfter SIP_OUT, int *leftOf SIP_OUT = nullptr, double epsilon = 4 * DBL_EPSILON ) const override;
bool pointAt( int node, QgsPoint &point, QgsVertexId::VertexType &type ) const override;
void sumUpArea( double &sum SIP_OUT ) const override;
bool hasCurvedSegments() const override;
Expand Down Expand Up @@ -129,7 +129,7 @@ class CORE_EXPORT QgsCircularString: public QgsCurve
static QgsRectangle segmentBoundingBox( const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3 );
static QgsPointSequence compassPointsOnSegment( double p1Angle, double p2Angle, double p3Angle, double centerX, double centerY, double radius );
static double closestPointOnArc( double x1, double y1, double x2, double y2, double x3, double y3,
const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, bool *leftOf, double epsilon );
const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf, double epsilon );
void insertVertexBetween( int after, int before, int pointOnCircle );
void deleteVertex( int i );

Expand Down
2 changes: 1 addition & 1 deletion src/core/geometry/qgscompoundcurve.cpp
Expand Up @@ -699,7 +699,7 @@ QVector< QPair<int, QgsVertexId> > QgsCompoundCurve::curveVertexId( QgsVertexId
return curveIds;
}

double QgsCompoundCurve::closestSegment( const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, bool *leftOf, double epsilon ) const
double QgsCompoundCurve::closestSegment( const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf, double epsilon ) const
{
return QgsGeometryUtils::closestSegmentFromComponents( mCurves, QgsGeometryUtils::Vertex, pt, segmentPt, vertexAfter, leftOf, epsilon );
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/geometry/qgscompoundcurve.h
Expand Up @@ -105,7 +105,7 @@ class CORE_EXPORT QgsCompoundCurve: public QgsCurve
bool insertVertex( QgsVertexId position, const QgsPoint &vertex ) override;
bool moveVertex( QgsVertexId position, const QgsPoint &newPos ) override;
bool deleteVertex( QgsVertexId position ) override;
double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt SIP_OUT, QgsVertexId &vertexAfter SIP_OUT, bool *leftOf SIP_OUT = nullptr, double epsilon = 4 * DBL_EPSILON ) const override;
double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt SIP_OUT, QgsVertexId &vertexAfter SIP_OUT, int *leftOf SIP_OUT = nullptr, double epsilon = 4 * DBL_EPSILON ) const override;
bool pointAt( int node, QgsPoint &point, QgsVertexId::VertexType &type ) const override;
void sumUpArea( double &sum SIP_OUT ) const override;

Expand Down
2 changes: 1 addition & 1 deletion src/core/geometry/qgscurvepolygon.cpp
Expand Up @@ -798,7 +798,7 @@ bool QgsCurvePolygon::isEmpty() const
return mExteriorRing->isEmpty();
}

double QgsCurvePolygon::closestSegment( const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, bool *leftOf, double epsilon ) const
double QgsCurvePolygon::closestSegment( const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf, double epsilon ) const
{
if ( !mExteriorRing )
{
Expand Down
2 changes: 1 addition & 1 deletion src/core/geometry/qgscurvepolygon.h
Expand Up @@ -121,7 +121,7 @@ class CORE_EXPORT QgsCurvePolygon: public QgsSurface
int nCoordinates() const override;
int vertexNumberFromVertexId( QgsVertexId id ) const override;
bool isEmpty() const override;
double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt SIP_OUT, QgsVertexId &vertexAfter SIP_OUT, bool *leftOf SIP_OUT = nullptr, double epsilon = 4 * DBL_EPSILON ) const override;
double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt SIP_OUT, QgsVertexId &vertexAfter SIP_OUT, int *leftOf SIP_OUT = nullptr, double epsilon = 4 * DBL_EPSILON ) const override;

bool nextVertex( QgsVertexId &id, QgsPoint &vertex SIP_OUT ) const override;
void adjacentVertices( QgsVertexId vertex, QgsVertexId &previousVertex SIP_OUT, QgsVertexId &nextVertex SIP_OUT ) const override;
Expand Down
18 changes: 6 additions & 12 deletions src/core/geometry/qgsgeometry.cpp
Expand Up @@ -584,12 +584,11 @@ double QgsGeometry::closestVertexWithContext( const QgsPointXY &point, int &atVe
return QgsGeometryUtils::sqrDistance2D( closestPoint, pt );
}

double QgsGeometry::closestSegmentWithContext(
const QgsPointXY &point,
QgsPointXY &minDistPoint,
int &afterVertex,
double *leftOf,
double epsilon ) const
double QgsGeometry::closestSegmentWithContext( const QgsPointXY &point,
QgsPointXY &minDistPoint,
int &afterVertex,
int *leftOf,
double epsilon ) const
{
if ( !d->geometry )
{
Expand All @@ -598,19 +597,14 @@ double QgsGeometry::closestSegmentWithContext(

QgsPoint segmentPt;
QgsVertexId vertexAfter;
bool leftOfBool;

double sqrDist = d->geometry->closestSegment( QgsPoint( point.x(), point.y() ), segmentPt, vertexAfter, &leftOfBool, epsilon );
double sqrDist = d->geometry->closestSegment( QgsPoint( point.x(), point.y() ), segmentPt, vertexAfter, leftOf, epsilon );
if ( sqrDist < 0 )
return -1;

minDistPoint.setX( segmentPt.x() );
minDistPoint.setY( segmentPt.y() );
afterVertex = vertexNrFromVertexId( vertexAfter );
if ( leftOf )
{
*leftOf = leftOfBool ? 1.0 : -1.0;
}
return sqrDist;
}

Expand Down
9 changes: 3 additions & 6 deletions src/core/geometry/qgsgeometry.h
Expand Up @@ -555,15 +555,12 @@ class CORE_EXPORT QgsGeometry
* \param minDistPoint Receives the nearest point on the segment
* \param afterVertex Receives index of the vertex after the closest segment. The vertex
* before the closest segment is always afterVertex - 1
* \param leftOf Out: Returns if the point lies on the left of right side of the segment ( < 0 means left, > 0 means right )
* \param leftOf Out: Returns if the point lies on the left of left side of the geometry ( < 0 means left, > 0 means right, 0 indicates
* that the test was unsuccesful, e.g. for a point exactly on the line)
* \param epsilon epsilon for segment snapping
* \returns The squared Cartesian distance is also returned in sqrDist, negative number on error
*/
#ifndef SIP_RUN
double closestSegmentWithContext( const QgsPointXY &point, QgsPointXY &minDistPoint, int &afterVertex, double *leftOf = nullptr, double epsilon = DEFAULT_SEGMENT_EPSILON ) const;
#else
double closestSegmentWithContext( const QgsPointXY &point, QgsPointXY &minDistPoint SIP_OUT, int &afterVertex SIP_OUT ) const;
#endif
double closestSegmentWithContext( const QgsPointXY &point, QgsPointXY &minDistPoint SIP_OUT, int &afterVertex SIP_OUT, int *leftOf SIP_OUT = nullptr, double epsilon = DEFAULT_SEGMENT_EPSILON ) const;

/**
* Adds a new ring to this geometry. This makes only sense for polygon and multipolygons.
Expand Down
2 changes: 1 addition & 1 deletion src/core/geometry/qgsgeometrycollection.cpp
Expand Up @@ -455,7 +455,7 @@ int QgsGeometryCollection::nCoordinates() const
return count;
}

double QgsGeometryCollection::closestSegment( const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, bool *leftOf, double epsilon ) const
double QgsGeometryCollection::closestSegment( const QgsPoint &pt, QgsPoint &segmentPt, QgsVertexId &vertexAfter, int *leftOf, double epsilon ) const
{
return QgsGeometryUtils::closestSegmentFromComponents( mGeometries, QgsGeometryUtils::Part, pt, segmentPt, vertexAfter, leftOf, epsilon );
}
Expand Down

0 comments on commit e4ce623

Please sign in to comment.