28 #include <QtConcurrentMap> 
   33 QgsSnapIndex::PointSnapItem::PointSnapItem( 
const QgsSnapIndex::CoordIdx *_idx, 
bool isEndPoint )
 
   34   : SnapItem( isEndPoint ? QgsSnapIndex::SnapEndPoint : QgsSnapIndex::SnapPoint )
 
   43 QgsSnapIndex::SegmentSnapItem::SegmentSnapItem( 
const QgsSnapIndex::CoordIdx *_idxFrom, 
const QgsSnapIndex::CoordIdx *_idxTo )
 
   44   : SnapItem( QgsSnapIndex::SnapSegment )
 
   49 QgsPoint QgsSnapIndex::SegmentSnapItem::getSnapPoint( 
const QgsPoint &p )
 const 
   56   const QgsPoint &q1 = idxFrom->point(), & q2 = idxTo->point();
 
   59   double vl = v.length();
 
   60   double wl = w.length();
 
   69   double d = v.y() * w.x() - v.x() * w.y();
 
   74   double dx = q1.
x() - p1.
x();
 
   75   double dy = q1.
y() - p1.
y();
 
   76   double k = ( dy * w.x() - dx * w.y() ) / d;
 
   78   inter = 
QgsPoint( p1.
x() + v.x() * k, p1.
y() + v.y() * k );
 
   80   double lambdav = 
QgsVector( inter.
x() - p1.
x(), inter.
y() - p1.
y() ) *  v;
 
   81   if ( lambdav < 0. + 1E-8 || lambdav > vl - 1E-8 )
 
   84   double lambdaw = 
QgsVector( inter.
x() - q1.
x(), inter.
y() - q1.
y() ) * w;
 
   85   return !( lambdaw < 0. + 1E-8 || lambdaw >= wl - 1E-8 );
 
   88 bool QgsSnapIndex::SegmentSnapItem::getProjection( 
const QgsPoint &p, 
QgsPoint &pProj )
 
   90   const QgsPoint &s1 = idxFrom->point();
 
   92   double nx = s2.
y() - s1.
y();
 
   93   double ny = -( s2.
x() - s1.
x() );
 
   94   double t = ( p.
x() * ny - p.
y() * nx - s1.
x() * ny + s1.
y() * nx ) / ( ( s2.
x() - s1.
x() ) * ny - ( s2.
y() - s1.
y() ) * nx );
 
   95   if ( t < 0. || t > 1. )
 
   99   pProj = 
QgsPoint( s1.
x() + ( s2.
x() - s1.
x() ) * t, s1.
y() + ( s2.
y() - s1.
y() ) * t );
 
  110     Raytracer( 
float x0, 
float y0, 
float x1, 
float y1 )
 
  111       : m_dx( std::fabs( x1 - x0 ) )
 
  112       , m_dy( std::fabs( y1 - y0 ) )
 
  113       , m_x( std::floor( x0 ) )
 
  114       , m_y( std::floor( y0 ) )
 
  120         m_error = std::numeric_limits<float>::infinity();
 
  125         m_n += int( std::floor( x1 ) ) - m_x;
 
  126         m_error = ( std::floor( x0 ) + 1 - x0 ) * m_dy;
 
  131         m_n += m_x - int( std::floor( x1 ) );
 
  132         m_error = ( x0 - std::floor( x0 ) ) * m_dy;
 
  137         m_error = -std::numeric_limits<float>::infinity();
 
  142         m_n += int( std::floor( y1 ) ) - m_y;
 
  143         m_error -= ( std::floor( y0 ) + 1 - y0 ) * m_dx;
 
  148         m_n += m_y - int( std::floor( y1 ) );
 
  149         m_error -= ( y0 - std::floor( y0 ) ) * m_dx;
 
  152     int curCol()
 const { 
return m_x; }
 
  153     int curRow()
 const { 
return m_y; }
 
  161       else if ( m_error < 0 )
 
  177     bool isValid()
 const { 
return m_n > 0; }
 
  189 QgsSnapIndex::QgsSnapIndex( 
const QgsPoint &origin, 
double cellSize )
 
  191   , mCellSize( cellSize )
 
  196 QgsSnapIndex::~QgsSnapIndex()
 
  198   qDeleteAll( mCoordIdxs );
 
  199   qDeleteAll( mSnapItems );
 
  204 void QgsSnapIndex::addPoint( 
const CoordIdx *idx, 
bool isEndPoint )
 
  207   int col = std::floor( ( p.
x() - mOrigin.x() ) / mCellSize );
 
  208   int row = std::floor( ( p.
y() - mOrigin.y() ) / mCellSize );
 
  211 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 
  212   geos::unique_ptr point( GEOSGeom_createPointFromXY_r( geosctxt, row, col ) );
 
  214   GEOSCoordSequence *seq = GEOSCoordSeq_create_r( geosctxt, 1, 2 );
 
  215   GEOSCoordSeq_setX_r( geosctxt, seq, 0, row );
 
  216   GEOSCoordSeq_setY_r( geosctxt, seq, 0, col );
 
  220   PointSnapItem *item = 
new PointSnapItem( idx, isEndPoint );
 
  221   GEOSSTRtree_insert_r( geosctxt, mSTRTree, point.get(), item );
 
  222 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR<9 
  223   mSTRTreeItems.emplace_back( std::move( point ) );
 
  228 void QgsSnapIndex::addSegment( 
const CoordIdx *idxFrom, 
const CoordIdx *idxTo )
 
  233   float x0 = ( pFrom.
x() - mOrigin.x() ) / mCellSize;
 
  234   float y0 = ( pFrom.
y() - mOrigin.y() ) / mCellSize;
 
  235   float x1 = ( pTo.
x() - mOrigin.x() ) / mCellSize;
 
  236   float y1 = ( pTo.
y() - mOrigin.y() ) / mCellSize;
 
  238   Raytracer rt( x0, y0, x1, y1 );
 
  240   for ( ; rt.isValid(); rt.next() )
 
  242 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 
  243     geos::unique_ptr point( GEOSGeom_createPointFromXY_r( geosctxt, rt.curRow(), rt.curCol() ) );
 
  245     GEOSCoordSequence *seq = GEOSCoordSeq_create_r( geosctxt, 1, 2 );
 
  246     GEOSCoordSeq_setX_r( geosctxt, seq, 0, rt.curRow() );
 
  247     GEOSCoordSeq_setY_r( geosctxt, seq, 0, rt.curCol() );
 
  251     SegmentSnapItem *item = 
new SegmentSnapItem( idxFrom, idxTo );
 
  252     GEOSSTRtree_insert_r( geosctxt, mSTRTree, point.get(), item );
 
  253 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR<9 
  254     mSTRTreeItems.push_back( std::move( point ) );
 
  262   for ( 
int iPart = 0, nParts = geom->
partCount(); iPart < nParts; ++iPart )
 
  264     for ( 
int iRing = 0, nRings = geom->
ringCount( iPart ); iRing < nRings; ++iRing )
 
  268       if ( qgsgeometry_cast< const QgsSurface * >( geom ) )
 
  270       else if ( 
const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( geom ) )
 
  272         if ( curve->isClosed() )
 
  276       for ( 
int iVert = 0; iVert < nVerts; ++iVert )
 
  278         CoordIdx *idx = 
new CoordIdx( geom, 
QgsVertexId( iPart, iRing, iVert ) );
 
  279         CoordIdx *idx1 = 
new CoordIdx( geom, 
QgsVertexId( iPart, iRing, iVert + 1 ) );
 
  280         mCoordIdxs.append( idx );
 
  281         mCoordIdxs.append( idx1 );
 
  282         addPoint( idx, iVert == 0 || iVert == nVerts - 1 );
 
  283         if ( iVert < nVerts - 1 )
 
  284           addSegment( idx, idx1 );
 
  290 struct _GEOSQueryCallbackData
 
  292   QList< QgsSnapIndex::SnapItem * > *list;
 
  295 void _GEOSQueryCallback( 
void *item, 
void *userdata )
 
  297   reinterpret_cast<_GEOSQueryCallbackData *
>( userdata )->list->append( 
static_cast<QgsSnapIndex::SnapItem *
>( item ) );
 
  309   float x0 = ( p.
x() - mOrigin.x() ) / mCellSize;
 
  310   float y0 = ( p.
y() - mOrigin.y() ) / mCellSize;
 
  311   float x1 = ( p2.
x() - mOrigin.x() ) / mCellSize;
 
  312   float y1 = ( p2.
y() - mOrigin.y() ) / mCellSize;
 
  314   Raytracer rt( x0, y0, x1, y1 );
 
  315   double dMin = std::numeric_limits<double>::max();
 
  317   for ( ; rt.isValid(); rt.next() )
 
  319 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 
  320     geos::unique_ptr searchPoint( GEOSGeom_createPointFromXY_r( geosctxt, rt.curRow(), rt.curCol() ) );
 
  322     GEOSCoordSequence *seq = GEOSCoordSeq_create_r( geosctxt, 1, 2 );
 
  323     GEOSCoordSeq_setX_r( geosctxt, seq, 0, rt.curRow() );
 
  324     GEOSCoordSeq_setY_r( geosctxt, seq, 0, rt.curCol() );
 
  327     QList<SnapItem *> items;
 
  328     struct _GEOSQueryCallbackData callbackData;
 
  329     callbackData.list = &items;
 
  330     GEOSSTRtree_query_r( geosctxt, mSTRTree, searchPoint.get(), _GEOSQueryCallback, &callbackData );
 
  331     for ( 
const SnapItem *item : items )
 
  333       if ( item->type == SnapSegment )
 
  336         if ( 
static_cast<const SegmentSnapItem *
>( item )->getIntersection( p, p2, inter ) )
 
  352 QgsSnapIndex::SnapItem *QgsSnapIndex::getSnapItem( 
const QgsPoint &pos, 
double tol, QgsSnapIndex::PointSnapItem **pSnapPoint, QgsSnapIndex::SegmentSnapItem **pSnapSegment, 
bool endPointOnly )
 const 
  354   int colStart = std::floor( ( pos.
x() - tol - mOrigin.x() ) / mCellSize );
 
  355   int rowStart = std::floor( ( pos.
y() - tol - mOrigin.y() ) / mCellSize );
 
  356   int colEnd = std::floor( ( pos.
x() + tol - mOrigin.x() ) / mCellSize );
 
  357   int rowEnd = std::floor( ( pos.
y() + tol - mOrigin.y() ) / mCellSize );
 
  361   GEOSCoordSequence *coord = GEOSCoordSeq_create_r( geosctxt, 2, 2 );
 
  362 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8 
  363   GEOSCoordSeq_setXY_r( geosctxt, coord, 0, rowStart, colStart );
 
  364   GEOSCoordSeq_setXY_r( geosctxt, coord, 1, rowEnd, colEnd );
 
  366   GEOSCoordSeq_setX_r( geosctxt, coord, 0, rowStart );
 
  367   GEOSCoordSeq_setY_r( geosctxt, coord, 0, colStart );
 
  368   GEOSCoordSeq_setX_r( geosctxt, coord, 1, rowEnd );
 
  369   GEOSCoordSeq_setY_r( geosctxt, coord, 1, colEnd );
 
  372   geos::unique_ptr searchDiagonal( GEOSGeom_createLineString_r( geosctxt, coord ) );
 
  374   QList<SnapItem *> items;
 
  375   struct _GEOSQueryCallbackData callbackData;
 
  376   callbackData.list = &items;
 
  377   GEOSSTRtree_query_r( geosctxt, mSTRTree, searchDiagonal.get(), _GEOSQueryCallback, &callbackData );
 
  379   double minDistSegment = std::numeric_limits<double>::max();
 
  380   double minDistPoint = std::numeric_limits<double>::max();
 
  381   QgsSnapIndex::SegmentSnapItem *snapSegment = 
nullptr;
 
  382   QgsSnapIndex::PointSnapItem *snapPoint = 
nullptr;
 
  384   const auto constItems = items;
 
  385   for ( QgsSnapIndex::SnapItem *item : constItems )
 
  387     if ( ( ! endPointOnly && item->type == SnapPoint ) || item->type == SnapEndPoint )
 
  390       if ( dist < minDistPoint )
 
  393         snapPoint = 
static_cast<PointSnapItem *
>( item );
 
  396     else if ( item->type == SnapSegment && !endPointOnly )
 
  399       if ( !
static_cast<SegmentSnapItem *
>( item )->getProjection( pos, pProj ) )
 
  404       if ( dist < minDistSegment )
 
  406         minDistSegment = dist;
 
  407         snapSegment = 
static_cast<SegmentSnapItem *
>( item );
 
  411   snapPoint = minDistPoint < tol * tol ? snapPoint : 
nullptr;
 
  412   snapSegment = minDistSegment < tol * tol ? snapSegment : 
nullptr;
 
  413   if ( pSnapPoint ) *pSnapPoint = snapPoint;
 
  414   if ( pSnapSegment ) *pSnapSegment = snapSegment;
 
  415   return minDistPoint < minDistSegment ? static_cast<QgsSnapIndex::SnapItem *>( snapPoint ) : static_cast<QgsSnapIndex::SnapItem *>( snapSegment );
 
  426   : mReferenceSource( referenceSource )
 
  435   QtConcurrent::blockingMap( list, ProcessFeatureWrapper( 
this, snapTolerance, mode ) );
 
  439 void QgsGeometrySnapper::processFeature( 
QgsFeature &feature, 
double snapTolerance, SnapMode mode )
 
  449   QList<QgsGeometry> refGeometries;
 
  452   searchBounds.
grow( snapTolerance );
 
  454   mIndexMutex.unlock();
 
  456   if ( refFeatureIds.isEmpty() )
 
  459   refGeometries.reserve( refFeatureIds.size() );
 
  461   const QgsFeatureIds cachedIds = qgis::listToSet( mCachedReferenceGeometries.keys() );
 
  464     if ( cachedIds.contains( 
id ) )
 
  466       refGeometries.append( mCachedReferenceGeometries[
id] );
 
  470       missingFeatureIds << id;
 
  474   if ( missingFeatureIds.size() > 0 )
 
  477     mReferenceLayerMutex.lock();
 
  483       refGeometries.append( refFeature.
geometry() );
 
  485     mReferenceLayerMutex.unlock();
 
  488   return snapGeometry( geometry, snapTolerance, refGeometries, mode );
 
  500   QgsSnapIndex refSnapIndex( center, 10 * snapTolerance );
 
  501   for ( 
const QgsGeometry &geom : referenceGeometries )
 
  503     refSnapIndex.addGeometry( geom.constGet() );
 
  508   QList < QList< QList<PointFlag> > > subjPointFlags;
 
  511   for ( 
int iPart = 0, nParts = subjGeom->
partCount(); iPart < nParts; ++iPart )
 
  513     subjPointFlags.append( QList< QList<PointFlag> >() );
 
  515     for ( 
int iRing = 0, nRings = subjGeom->
ringCount( iPart ); iRing < nRings; ++iRing )
 
  517       subjPointFlags[iPart].append( QList<PointFlag>() );
 
  519       for ( 
int iVert = 0, nVerts = polyLineSize( subjGeom, iPart, iRing ); iVert < nVerts; ++iVert )
 
  525           subjPointFlags[iPart][iRing].append( Unsnapped );
 
  529         QgsSnapIndex::PointSnapItem *snapPoint = 
nullptr;
 
  530         QgsSnapIndex::SegmentSnapItem *snapSegment = 
nullptr;
 
  533         if ( !refSnapIndex.getSnapItem( p, snapTolerance, &snapPoint, &snapSegment, mode == 
EndPointToEndPoint ) )
 
  535           subjPointFlags[iPart][iRing].append( Unsnapped );
 
  549                 subjGeom->
moveVertex( vidx, snapPoint->getSnapPoint( p ) );
 
  550                 subjPointFlags[iPart][iRing].append( SnappedToRefNode );
 
  552               else if ( snapSegment )
 
  554                 subjGeom->
moveVertex( vidx, snapSegment->getSnapPoint( p ) );
 
  555                 subjPointFlags[iPart][iRing].append( SnappedToRefSegment );
 
  565               double distanceNode = std::numeric_limits<double>::max();
 
  566               double distanceSegment = std::numeric_limits<double>::max();
 
  569                 nodeSnap = snapPoint->getSnapPoint( p );
 
  574                 segmentSnap = snapSegment->getSnapPoint( p );
 
  577               if ( snapPoint && distanceNode < distanceSegment )
 
  580                 subjPointFlags[iPart][iRing].append( SnappedToRefNode );
 
  582               else if ( snapSegment )
 
  585                 subjPointFlags[iPart][iRing].append( SnappedToRefSegment );
 
  596   if ( qgsgeometry_cast< const QgsPoint * >( subjGeom ) )
 
  607   std::unique_ptr< QgsSnapIndex > subjSnapIndex( 
new QgsSnapIndex( center, 10 * snapTolerance ) );
 
  608   subjSnapIndex->addGeometry( subjGeom );
 
  610   std::unique_ptr< QgsAbstractGeometry > origSubjGeom( subjGeom->
clone() );
 
  611   std::unique_ptr< QgsSnapIndex > origSubjSnapIndex( 
new QgsSnapIndex( center, 10 * snapTolerance ) );
 
  612   origSubjSnapIndex->addGeometry( origSubjGeom.get() );
 
  615   for ( 
const QgsGeometry &refGeom : referenceGeometries )
 
  617     for ( 
int iPart = 0, nParts = refGeom.constGet()->partCount(); iPart < nParts; ++iPart )
 
  619       for ( 
int iRing = 0, nRings = refGeom.constGet()->ringCount( iPart ); iRing < nRings; ++iRing )
 
  621         for ( 
int iVert = 0, nVerts = polyLineSize( refGeom.constGet(), iPart, iRing ); iVert < nVerts; ++iVert )
 
  624           QgsSnapIndex::PointSnapItem *snapPoint = 
nullptr;
 
  625           QgsSnapIndex::SegmentSnapItem *snapSegment = 
nullptr;
 
  627           if ( subjSnapIndex->getSnapItem( point, snapTolerance, &snapPoint, &snapSegment ) )
 
  634             else if ( snapSegment )
 
  637               QgsPoint pProj = snapSegment->getSnapPoint( point );
 
  638               QgsPoint closest = refSnapIndex.getClosestSnapToPoint( point, pProj );
 
  645               if ( !origSubjSnapIndex->getSnapItem( point, snapTolerance ) )
 
  650               const QgsSnapIndex::CoordIdx *idx = snapSegment->idxFrom;
 
  652               subjPointFlags[idx->vidx.part][idx->vidx.ring].insert( idx->vidx.vertex + 1, SnappedToRefNode );
 
  653               subjSnapIndex.reset( 
new QgsSnapIndex( center, 10 * snapTolerance ) );
 
  654               subjSnapIndex->addGeometry( subjGeom );
 
  661   subjSnapIndex.reset();
 
  662   origSubjSnapIndex.reset();
 
  663   origSubjGeom.reset();
 
  666   for ( 
int iPart = 0, nParts = subjGeom->
partCount(); iPart < nParts; ++iPart )
 
  668     for ( 
int iRing = 0, nRings = subjGeom->
ringCount( iPart ); iRing < nRings; ++iRing )
 
  671       for ( 
int iVert = 0, nVerts = polyLineSize( subjGeom, iPart, iRing ); iVert < nVerts; ++iVert )
 
  673         int iPrev = ( iVert - 1 + nVerts ) % nVerts;
 
  674         int iNext = ( iVert + 1 ) % nVerts;
 
  679         if ( subjPointFlags[iPart][iRing][iVert] == SnappedToRefSegment &&
 
  680              subjPointFlags[iPart][iRing][iPrev] != Unsnapped &&
 
  681              subjPointFlags[iPart][iRing][iNext] != Unsnapped &&
 
  684           if ( ( ringIsClosed && nVerts > 3 ) || ( !ringIsClosed && nVerts > 2 ) )
 
  687             subjPointFlags[iPart][iRing].removeAt( iVert );
 
  706 int QgsGeometrySnapper::polyLineSize( 
const QgsAbstractGeometry *geom, 
int iPart, 
int iRing )
 
  710   if ( qgsgeometry_cast< const QgsSurface * >( geom ) || qgsgeometry_cast< const QgsMultiSurface * >( geom ) )
 
  730   : mSnapTolerance( snapTolerance )
 
  741   if ( !mFirstFeature )
 
  746     searchBounds.
grow( mSnapTolerance );
 
  748     if ( !refFeatureIds.isEmpty() )
 
  750       QList< QgsGeometry > refGeometries;
 
  751       const auto constRefFeatureIds = refFeatureIds;
 
  754         refGeometries << mProcessedGeometries.value( 
id );
 
  760   mProcessedGeometries.insert( feat.
id(), geometry );
 
  762   mFirstFeature = 
false;
 
Abstract base class for all geometries.
virtual int ringCount(int part=0) const =0
Returns the number of rings of which this geometry is built.
virtual bool moveVertex(QgsVertexId position, const QgsPoint &newPos)=0
Moves a vertex within the geometry.
virtual int vertexCount(int part=0, int ring=0) const =0
Returns the number of vertices of which this geometry is built.
virtual QgsRectangle boundingBox() const =0
Returns the minimal bounding box for the geometry.
virtual QgsPoint vertexAt(QgsVertexId id) const =0
Returns the point corresponding to a specified vertex id.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
virtual bool insertVertex(QgsVertexId position, const QgsPoint &vertex)=0
Inserts a vertex into the geometry.
virtual int partCount() const =0
Returns count of parts contained in the geometry.
virtual bool deleteVertex(QgsVertexId position)=0
Deletes a vertex within the geometry.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
Abstract base class for curved geometry type.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets feature IDs that should be fetched.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
An interface for objects which provide features via a getFeatures method.
virtual QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const =0
Returns an iterator for the features in the source.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool hasGeometry() const
Returns true if the feature has an associated geometry.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
void featureSnapped()
Emitted each time a feature has been processed when calling snapFeatures()
QgsFeatureList snapFeatures(const QgsFeatureList &features, double snapTolerance, SnapMode mode=PreferNodes)
Snaps a set of features to the reference layer and returns the result.
QgsGeometry snapGeometry(const QgsGeometry &geometry, double snapTolerance, SnapMode mode=PreferNodes) const
Snaps a geometry to the reference layer and returns the result.
@ EndPointPreferClosest
Only snap start/end points of lines (point features will also be snapped, polygon features will not b...
@ PreferClosestNoExtraVertices
Snap to closest point, regardless of it is a node or a segment. No new nodes will be inserted.
@ EndPointPreferNodes
Only snap start/end points of lines (point features will also be snapped, polygon features will not b...
@ PreferNodes
Prefer to snap to nodes, even when a segment may be closer than a node. New nodes will be inserted to...
@ PreferClosest
Snap to closest point, regardless of it is a node or a segment. New nodes will be inserted to make ge...
@ EndPointToEndPoint
Only snap the start/end points of lines to other start/end points of lines.
@ PreferNodesNoExtraVertices
Prefer to snap to nodes, even when a segment may be closer than a node. No new nodes will be inserted...
QgsGeometrySnapper(QgsFeatureSource *referenceSource)
Constructor for QgsGeometrySnapper.
static double sqrDistance2D(const QgsPoint &pt1, const QgsPoint &pt2) SIP_HOLDGIL
Returns the squared 2D distance between two points.
static QgsPoint projectPointOnSegment(const QgsPoint &p, const QgsPoint &s1, const QgsPoint &s2) SIP_HOLDGIL
Project the point on a segment.
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
bool removeDuplicateNodes(double epsilon=4 *std::numeric_limits< double >::epsilon(), bool useZValues=false)
Removes duplicate nodes from the geometry, wherever removing the nodes does not result in a degenerat...
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
static GEOSContextHandle_t getGEOSHandler()
QgsInternalGeometrySnapper(double snapTolerance, QgsGeometrySnapper::SnapMode mode=QgsGeometrySnapper::PreferNodes)
Constructor for QgsInternalGeometrySnapper.
QgsGeometry snapFeature(const QgsFeature &feature)
Snaps a single feature's geometry against all feature geometries already processed by calls to snapFe...
Point geometry type, with support for z-dimension and m-values.
QgsPoint vertexAt(QgsVertexId) const override
Returns the point corresponding to a specified vertex id.
double distanceSquared(double x, double y) const SIP_HOLDGIL
Returns the Cartesian 2D squared distance between this point a specified x, y coordinate.
A rectangle specified with double values.
void grow(double delta)
Grows the rectangle in place by the specified amount.
QgsPointXY center() const SIP_HOLDGIL
Returns the center point of the rectangle.
A spatial index for QgsFeature objects.
QList< QgsFeatureId > intersects(const QgsRectangle &rectangle) const
Returns a list of features with a bounding box which intersects the specified rectangle.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a feature to the index.
A class to represent a vector.
static GeometryType geometryType(Type type) SIP_HOLDGIL
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
std::unique_ptr< GEOSGeometry, GeosDeleter > unique_ptr
Scoped GEOS pointer.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QList< QgsFeature > QgsFeatureList
QSet< QgsFeatureId > QgsFeatureIds
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Utility class for identifying a unique vertex within a geometry.