QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgspointlocator.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspointlocator.cpp
3  --------------------------------------
4  Date : November 2014
5  Copyright : (C) 2014 by Martin Dobias
6  Email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgspointlocator.h"
17 
18 #include "qgsfeatureiterator.h"
19 #include "qgsgeometry.h"
20 #include "qgsvectorlayer.h"
21 #include "qgswkbptr.h"
22 #include "qgis.h"
23 #include "qgslogger.h"
24 #include "qgsrenderer.h"
25 #include "qgsapplication.h"
28 #include "qgslinestring.h"
29 #include "qgscurvepolygon.h"
30 #include "qgsrendercontext.h"
32 #include <spatialindex/SpatialIndex.h>
33 
34 #include <QLinkedListIterator>
35 #include <QtConcurrent>
36 
37 using namespace SpatialIndex;
38 
39 
40 
41 static SpatialIndex::Point point2point( const QgsPointXY &point )
42 {
43  double plow[2] = { point.x(), point.y() };
44  return Point( plow, 2 );
45 }
46 
47 
48 static SpatialIndex::Region rect2region( const QgsRectangle &rect )
49 {
50  double pLow[2] = { rect.xMinimum(), rect.yMinimum() };
51  double pHigh[2] = { rect.xMaximum(), rect.yMaximum() };
52  return SpatialIndex::Region( pLow, pHigh, 2 );
53 }
54 
55 
56 // Ahh.... another magic number. Taken from QgsVectorLayer::snapToGeometry() call to closestSegmentWithContext().
57 // The default epsilon used for sqrDistToSegment (1e-8) is too high when working with lat/lon coordinates
58 // I still do not fully understand why the sqrDistToSegment() code uses epsilon and if the square distance
59 // is lower than epsilon it will have a special logic...
60 static const double POINT_LOC_EPSILON = 1e-12;
61 
63 
64 
70 class QgsPointLocator_Stream : public IDataStream
71 {
72  public:
73  explicit QgsPointLocator_Stream( const QLinkedList<RTree::Data *> &dataList )
74  : mDataList( dataList )
75  , mIt( mDataList )
76  { }
77 
78  IData *getNext() override { return mIt.next(); }
79  bool hasNext() override { return mIt.hasNext(); }
80 
81  uint32_t size() override { Q_ASSERT( false && "not available" ); return 0; }
82  void rewind() override { Q_ASSERT( false && "not available" ); }
83 
84  private:
85  QLinkedList<RTree::Data *> mDataList;
86  QLinkedListIterator<RTree::Data *> mIt;
87 };
88 
89 
91 
92 
98 class QgsPointLocator_VisitorNearestVertex : public IVisitor
99 {
100  public:
102  : mLocator( pl )
103  , mBest( m )
104  , mSrcPoint( srcPoint )
105  , mFilter( filter )
106  {}
107 
108  void visitNode( const INode &n ) override { Q_UNUSED( n ) }
109  void visitData( std::vector<const IData *> &v ) override { Q_UNUSED( v ) }
110 
111  void visitData( const IData &d ) override
112  {
113  const QgsFeatureId id = d.getIdentifier();
114  QgsGeometry *geom = mLocator->mGeoms.value( id );
115  if ( !geom )
116  return; // should not happen, but be safe
117  int vertexIndex, beforeVertex, afterVertex;
118  double sqrDist;
119 
120  const QgsPointXY pt = geom->closestVertex( mSrcPoint, vertexIndex, beforeVertex, afterVertex, sqrDist );
121  if ( sqrDist < 0 )
122  return; // probably empty geometry
123 
124  const QgsPointLocator::Match m( QgsPointLocator::Vertex, mLocator->mLayer, id, std::sqrt( sqrDist ), pt, vertexIndex );
125  // in range queries the filter may reject some matches
126  if ( mFilter && !mFilter->acceptMatch( m ) )
127  return;
128 
129  if ( !mBest.isValid() || m.distance() < mBest.distance() )
130  mBest = m;
131  }
132 
133  private:
134  QgsPointLocator *mLocator = nullptr;
135  QgsPointLocator::Match &mBest;
136  QgsPointXY mSrcPoint;
137  QgsPointLocator::MatchFilter *mFilter = nullptr;
138 };
139 
140 
141 
149 {
150  public:
151 
159  : mLocator( pl )
160  , mBest( m )
161  , mSrcPoint( srcPoint )
162  , mFilter( filter )
163  {}
164 
165  void visitNode( const INode &n ) override { Q_UNUSED( n ) }
166  void visitData( std::vector<const IData *> &v ) override { Q_UNUSED( v ) }
167 
168  void visitData( const IData &d ) override
169  {
170  const QgsFeatureId id = d.getIdentifier();
171  QgsGeometry *geom = mLocator->mGeoms.value( id );
172  if ( !geom )
173  return; // should not happen, but be safe
174 
175  const QgsPointXY pt = geom->centroid().asPoint();
176 
177  const QgsPointLocator::Match m( QgsPointLocator::Centroid, mLocator->mLayer, id, std::sqrt( mSrcPoint.sqrDist( pt ) ), pt, -1 );
178  // in range queries the filter may reject some matches
179  if ( mFilter && !mFilter->acceptMatch( m ) )
180  return;
181 
182  if ( !mBest.isValid() || m.distance() < mBest.distance() )
183  mBest = m;
184 
185  }
186 
187  private:
188  QgsPointLocator *mLocator = nullptr;
189  QgsPointLocator::Match &mBest;
190  QgsPointXY mSrcPoint;
191  QgsPointLocator::MatchFilter *mFilter = nullptr;
192 };
193 
195 
203 {
204  public:
205 
213  : mLocator( pl )
214  , mBest( m )
215  , mSrcPoint( srcPoint )
216  , mFilter( filter )
217  {}
218 
219  void visitNode( const INode &n ) override { Q_UNUSED( n ) }
220  void visitData( std::vector<const IData *> &v ) override { Q_UNUSED( v ) }
221 
222  void visitData( const IData &d ) override
223  {
224  const QgsFeatureId id = d.getIdentifier();
225  QgsGeometry *geom = mLocator->mGeoms.value( id );
226  if ( !geom )
227  return; // should not happen, but be safe
228 
229  QgsPointXY pt;
230  int afterVertex;
231  const double sqrDist = geom->closestSegmentWithContext( mSrcPoint, pt, afterVertex, nullptr, POINT_LOC_EPSILON );
232  if ( sqrDist < 0 )
233  return;
234 
235  QgsPointXY edgePoints[2];
236  edgePoints[0] = geom->vertexAt( afterVertex - 1 );
237  edgePoints[1] = geom->vertexAt( afterVertex );
238  pt = QgsPointXY( ( edgePoints[0].x() + edgePoints[1].x() ) / 2.0, ( edgePoints[0].y() + edgePoints[1].y() ) / 2.0 );
239 
240  const QgsPointLocator::Match m( QgsPointLocator::MiddleOfSegment, mLocator->mLayer, id, std::sqrt( mSrcPoint.sqrDist( pt ) ), pt, afterVertex - 1 );
241  // in range queries the filter may reject some matches
242  if ( mFilter && !mFilter->acceptMatch( m ) )
243  return;
244 
245  if ( !mBest.isValid() || m.distance() < mBest.distance() )
246  mBest = m;
247 
248  }
249 
250  private:
251  QgsPointLocator *mLocator = nullptr;
252  QgsPointLocator::Match &mBest;
253  QgsPointXY mSrcPoint;
254  QgsPointLocator::MatchFilter *mFilter = nullptr;
255 };
256 
258 
266 {
267  public:
268 
274  : mLocator( pl )
275  , mBest( m )
276  , mSrcPoint( srcPoint )
277  , mFilter( filter )
278  {}
279 
280  void visitNode( const INode &n ) override { Q_UNUSED( n ) }
281  void visitData( std::vector<const IData *> &v ) override { Q_UNUSED( v ) }
282 
283  void visitData( const IData &d ) override
284  {
285  const QgsFeatureId id = d.getIdentifier();
286  const QgsGeometry *geom = mLocator->mGeoms.value( id );
287  if ( !geom )
288  return; // should not happen, but be safe
289 
290  QgsPointXY bestPoint;
291  int bestVertexNumber = -1;
292  auto replaceIfBetter = [this, &bestPoint, &bestVertexNumber]( const QgsPoint & candidate, int vertexNumber )
293  {
294  if ( bestPoint.isEmpty() || candidate.distanceSquared( mSrcPoint.x(), mSrcPoint.y() ) < bestPoint.sqrDist( mSrcPoint ) )
295  {
296  bestPoint = QgsPointXY( candidate );
297  bestVertexNumber = vertexNumber;
298  }
299  };
300 
301  switch ( QgsWkbTypes::geometryType( geom->wkbType() ) )
302  {
306  return;
307 
309  {
310  int partStartVertexNum = 0;
311  for ( auto partIt = geom->const_parts_begin(); partIt != geom->const_parts_end(); ++partIt )
312  {
313  if ( const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( *partIt ) )
314  {
315  replaceIfBetter( curve->startPoint(), partStartVertexNum );
316  replaceIfBetter( curve->endPoint(), partStartVertexNum + curve->numPoints() - 1 );
317  partStartVertexNum += curve->numPoints();
318  }
319  }
320  break;
321  }
322 
324  {
325  int partStartVertexNum = 0;
326  for ( auto partIt = geom->const_parts_begin(); partIt != geom->const_parts_end(); ++partIt )
327  {
328  if ( const QgsCurvePolygon *polygon = qgsgeometry_cast< const QgsCurvePolygon * >( *partIt ) )
329  {
330  if ( polygon->exteriorRing() )
331  {
332  replaceIfBetter( polygon->exteriorRing()->startPoint(), partStartVertexNum );
333  partStartVertexNum += polygon->exteriorRing()->numPoints();
334  }
335  for ( int i = 0; i < polygon->numInteriorRings(); ++i )
336  {
337  const QgsCurve *ring = polygon->interiorRing( i );
338  replaceIfBetter( ring->startPoint(), partStartVertexNum );
339  partStartVertexNum += ring->numPoints();
340  }
341  }
342  }
343  break;
344  }
345  }
346 
347  const QgsPointLocator::Match m( QgsPointLocator::LineEndpoint, mLocator->mLayer, id, std::sqrt( mSrcPoint.sqrDist( bestPoint ) ), bestPoint, bestVertexNumber );
348  // in range queries the filter may reject some matches
349  if ( mFilter && !mFilter->acceptMatch( m ) )
350  return;
351 
352  if ( !mBest.isValid() || m.distance() < mBest.distance() )
353  mBest = m;
354  }
355 
356  private:
357  QgsPointLocator *mLocator = nullptr;
358  QgsPointLocator::Match &mBest;
359  QgsPointXY mSrcPoint;
360  QgsPointLocator::MatchFilter *mFilter = nullptr;
361 };
362 
363 
365 
366 
372 class QgsPointLocator_VisitorNearestEdge : public IVisitor
373 {
374  public:
376  : mLocator( pl )
377  , mBest( m )
378  , mSrcPoint( srcPoint )
379  , mFilter( filter )
380  {}
381 
382  void visitNode( const INode &n ) override { Q_UNUSED( n ) }
383  void visitData( std::vector<const IData *> &v ) override { Q_UNUSED( v ) }
384 
385  void visitData( const IData &d ) override
386  {
387  const QgsFeatureId id = d.getIdentifier();
388  QgsGeometry *geom = mLocator->mGeoms.value( id );
389  if ( !geom )
390  return; // should not happen, but be safe
391 
392  QgsPointXY pt;
393  int afterVertex;
394  const double sqrDist = geom->closestSegmentWithContext( mSrcPoint, pt, afterVertex, nullptr, POINT_LOC_EPSILON );
395  if ( sqrDist < 0 )
396  return;
397 
398  QgsPointXY edgePoints[2];
399  edgePoints[0] = geom->vertexAt( afterVertex - 1 );
400  edgePoints[1] = geom->vertexAt( afterVertex );
401  const QgsPointLocator::Match m( QgsPointLocator::Edge, mLocator->mLayer, id, std::sqrt( sqrDist ), pt, afterVertex - 1, edgePoints );
402  // in range queries the filter may reject some matches
403  if ( mFilter && !mFilter->acceptMatch( m ) )
404  return;
405 
406  if ( !mBest.isValid() || m.distance() < mBest.distance() )
407  mBest = m;
408  }
409 
410  private:
411  QgsPointLocator *mLocator = nullptr;
412  QgsPointLocator::Match &mBest;
413  QgsPointXY mSrcPoint;
414  QgsPointLocator::MatchFilter *mFilter = nullptr;
415 };
416 
417 
419 
425 class QgsPointLocator_VisitorArea : public IVisitor
426 {
427  public:
430  : mLocator( pl )
431  , mList( list )
432  , mGeomPt( QgsGeometry::fromPointXY( origPt ) )
433  {}
434 
435  void visitNode( const INode &n ) override { Q_UNUSED( n ) }
436  void visitData( std::vector<const IData *> &v ) override { Q_UNUSED( v ) }
437 
438  void visitData( const IData &d ) override
439  {
440  const QgsFeatureId id = d.getIdentifier();
441  QgsGeometry *g = mLocator->mGeoms.value( id );
442  if ( !g )
443  return; // should not happen, but be safe
444 
445  if ( g->intersects( mGeomPt ) )
446  mList << QgsPointLocator::Match( QgsPointLocator::Area, mLocator->mLayer, id, 0, mGeomPt.asPoint() );
447  }
448  private:
449  QgsPointLocator *mLocator = nullptr;
451  QgsGeometry mGeomPt;
452 };
453 
454 
456 
457 // code adapted from
458 // http://en.wikipedia.org/wiki/Cohen%E2%80%93Sutherland_algorithm
460 {
461  explicit _CohenSutherland( const QgsRectangle &rect ) : mRect( rect ) {}
462 
463  typedef int OutCode;
464 
465  static const int INSIDE = 0; // 0000
466  static const int LEFT = 1; // 0001
467  static const int RIGHT = 2; // 0010
468  static const int BOTTOM = 4; // 0100
469  static const int TOP = 8; // 1000
470 
472 
473  OutCode computeOutCode( double x, double y )
474  {
475  OutCode code = INSIDE; // initialized as being inside of clip window
476  if ( x < mRect.xMinimum() ) // to the left of clip window
477  code |= LEFT;
478  else if ( x > mRect.xMaximum() ) // to the right of clip window
479  code |= RIGHT;
480  if ( y < mRect.yMinimum() ) // below the clip window
481  code |= BOTTOM;
482  else if ( y > mRect.yMaximum() ) // above the clip window
483  code |= TOP;
484  return code;
485  }
486 
487  bool isSegmentInRect( double x0, double y0, double x1, double y1 )
488  {
489  // compute outcodes for P0, P1, and whatever point lies outside the clip rectangle
490  OutCode outcode0 = computeOutCode( x0, y0 );
491  OutCode outcode1 = computeOutCode( x1, y1 );
492  bool accept = false;
493 
494  while ( true )
495  {
496  if ( !( outcode0 | outcode1 ) )
497  {
498  // Bitwise OR is 0. Trivially accept and get out of loop
499  accept = true;
500  break;
501  }
502  else if ( outcode0 & outcode1 )
503  {
504  // Bitwise AND is not 0. Trivially reject and get out of loop
505  break;
506  }
507  else
508  {
509  // failed both tests, so calculate the line segment to clip
510  // from an outside point to an intersection with clip edge
511  double x, y;
512 
513  // At least one endpoint is outside the clip rectangle; pick it.
514  const OutCode outcodeOut = outcode0 ? outcode0 : outcode1;
515 
516  // Now find the intersection point;
517  // use formulas y = y0 + slope * (x - x0), x = x0 + (1 / slope) * (y - y0)
518  if ( outcodeOut & TOP )
519  {
520  // point is above the clip rectangle
521  x = x0 + ( x1 - x0 ) * ( mRect.yMaximum() - y0 ) / ( y1 - y0 );
522  y = mRect.yMaximum();
523  }
524  else if ( outcodeOut & BOTTOM )
525  {
526  // point is below the clip rectangle
527  x = x0 + ( x1 - x0 ) * ( mRect.yMinimum() - y0 ) / ( y1 - y0 );
528  y = mRect.yMinimum();
529  }
530  else if ( outcodeOut & RIGHT )
531  {
532  // point is to the right of clip rectangle
533  y = y0 + ( y1 - y0 ) * ( mRect.xMaximum() - x0 ) / ( x1 - x0 );
534  x = mRect.xMaximum();
535  }
536  else if ( outcodeOut & LEFT )
537  {
538  // point is to the left of clip rectangle
539  y = y0 + ( y1 - y0 ) * ( mRect.xMinimum() - x0 ) / ( x1 - x0 );
540  x = mRect.xMinimum();
541  }
542  else
543  break;
544 
545  // Now we move outside point to intersection point to clip
546  // and get ready for next pass.
547  if ( outcodeOut == outcode0 )
548  {
549  x0 = x;
550  y0 = y;
551  outcode0 = computeOutCode( x0, y0 );
552  }
553  else
554  {
555  x1 = x;
556  y1 = y;
557  outcode1 = computeOutCode( x1, y1 );
558  }
559  }
560  }
561  return accept;
562  }
563 };
564 
565 
566 static QgsPointLocator::MatchList _geometrySegmentsInRect( QgsGeometry *geom, const QgsRectangle &rect, QgsVectorLayer *vl, QgsFeatureId fid )
567 {
568  // this code is stupidly based on QgsGeometry::closestSegmentWithContext
569  // we need iterator for segments...
570 
572 
573  // geom is converted to a MultiCurve
574  QgsGeometry straightGeom = geom->convertToType( QgsWkbTypes::LineGeometry, true );
575  // and convert to straight segemnt / converts curve to linestring
576  straightGeom.convertToStraightSegment();
577 
578  // so, you must have multilinestring
579  //
580  // Special case: Intersections cannot be done on an empty linestring like
581  // QgsGeometry(QgsLineString()) or QgsGeometry::fromWkt("LINESTRING EMPTY")
582  if ( straightGeom.isEmpty() || ( ( straightGeom.type() != QgsWkbTypes::LineGeometry ) && ( !straightGeom.isMultipart() ) ) )
583  return lst;
584 
585  _CohenSutherland cs( rect );
586 
587  int pointIndex = 0;
588  for ( auto part = straightGeom.const_parts_begin(); part != straightGeom.const_parts_end(); ++part )
589  {
590  // Checking for invalid linestrings
591  // A linestring should/(must?) have at least two points.
592  QgsCurve *curve = qgsgeometry_cast<QgsCurve *>( *part );
593  Q_ASSERT( !curve->hasCurvedSegments() );
594  if ( curve->numPoints() < 2 )
595  continue;
596 
597  QgsAbstractGeometry::vertex_iterator it = ( *part )->vertices_begin();
598  QgsPointXY prevPoint( *it );
599  it++;
600  while ( it != ( *part )->vertices_end() )
601  {
602  const QgsPointXY thisPoint( *it );
603  if ( cs.isSegmentInRect( prevPoint.x(), prevPoint.y(), thisPoint.x(), thisPoint.y() ) )
604  {
605  QgsPointXY edgePoints[2];
606  edgePoints[0] = prevPoint;
607  edgePoints[1] = thisPoint;
608  lst << QgsPointLocator::Match( QgsPointLocator::Edge, vl, fid, 0, QgsPointXY(), pointIndex - 1, edgePoints );
609  }
610  prevPoint = QgsPointXY( *it );
611  it++;
612  pointIndex += 1;
613 
614  }
615  }
616  return lst;
617 }
618 
624 class QgsPointLocator_VisitorEdgesInRect : public IVisitor
625 {
626  public:
628  : mLocator( pl )
629  , mList( lst )
630  , mSrcRect( srcRect )
631  , mFilter( filter )
632  {}
633 
634  void visitNode( const INode &n ) override { Q_UNUSED( n ) }
635  void visitData( std::vector<const IData *> &v ) override { Q_UNUSED( v ) }
636 
637  void visitData( const IData &d ) override
638  {
639  const QgsFeatureId id = d.getIdentifier();
640  QgsGeometry *geom = mLocator->mGeoms.value( id );
641  if ( !geom )
642  return; // should not happen, but be safe
643 
644  const auto segmentsInRect {_geometrySegmentsInRect( geom, mSrcRect, mLocator->mLayer, id )};
645  for ( const QgsPointLocator::Match &m : segmentsInRect )
646  {
647  // in range queries the filter may reject some matches
648  if ( mFilter && !mFilter->acceptMatch( m ) )
649  continue;
650 
651  mList << m;
652  }
653  }
654 
655  private:
656  QgsPointLocator *mLocator = nullptr;
658  QgsRectangle mSrcRect;
659  QgsPointLocator::MatchFilter *mFilter = nullptr;
660 };
661 
663 
671 {
672  public:
675  : mLocator( pl )
676  , mList( lst )
677  , mSrcRect( srcRect )
678  , mFilter( filter )
679  {}
680 
681  void visitNode( const INode &n ) override { Q_UNUSED( n ) }
682  void visitData( std::vector<const IData *> &v ) override { Q_UNUSED( v ) }
683 
684  void visitData( const IData &d ) override
685  {
686  const QgsFeatureId id = d.getIdentifier();
687  const QgsGeometry *geom = mLocator->mGeoms.value( id );
688  if ( !geom )
689  return; // should not happen, but be safe
690 
691  for ( QgsAbstractGeometry::vertex_iterator it = geom->vertices_begin(); it != geom->vertices_end(); ++it )
692  {
693  if ( mSrcRect.contains( *it ) )
694  {
695  const QgsPointLocator::Match m( QgsPointLocator::Vertex, mLocator->mLayer, id, 0, *it, geom->vertexNrFromVertexId( it.vertexId() ) );
696 
697  // in range queries the filter may reject some matches
698  if ( mFilter && !mFilter->acceptMatch( m ) )
699  continue;
700 
701  mList << m;
702  }
703  }
704  }
705 
706  private:
707  QgsPointLocator *mLocator = nullptr;
709  QgsRectangle mSrcRect;
710  QgsPointLocator::MatchFilter *mFilter = nullptr;
711 };
712 
720 {
721  public:
724  : mLocator( pl )
725  , mList( lst )
726  , mSrcRect( srcRect )
727  , mFilter( filter )
728  {}
729 
730  void visitNode( const INode &n ) override { Q_UNUSED( n ); }
731  void visitData( std::vector<const IData *> &v ) override { Q_UNUSED( v ); }
732 
733  void visitData( const IData &d ) override
734  {
735  const QgsFeatureId id = d.getIdentifier();
736  const QgsGeometry *geom = mLocator->mGeoms.value( id );
737  if ( !geom )
738  return; // should not happen, but be safe
739 
740  const QgsPointXY centroid = geom->centroid().asPoint();
741  if ( mSrcRect.contains( centroid ) )
742  {
743  const QgsPointLocator::Match m( QgsPointLocator::Centroid, mLocator->mLayer, id, 0, centroid, -1 );
744 
745  // in range queries the filter may reject some matches
746  if ( !( mFilter && !mFilter->acceptMatch( m ) ) )
747  mList << m;
748  }
749  }
750 
751  private:
752  QgsPointLocator *mLocator = nullptr;
754  QgsRectangle mSrcRect;
755  QgsPointLocator::MatchFilter *mFilter = nullptr;
756 };
757 
765 {
766  public:
769  : mLocator( pl )
770  , mList( lst )
771  , mSrcRect( srcRect )
772  , mFilter( filter )
773  {}
774 
775  void visitNode( const INode &n ) override { Q_UNUSED( n ); }
776  void visitData( std::vector<const IData *> &v ) override { Q_UNUSED( v ); }
777 
778  void visitData( const IData &d ) override
779  {
780  const QgsFeatureId id = d.getIdentifier();
781  const QgsGeometry *geom = mLocator->mGeoms.value( id );
782  if ( !geom )
783  return; // should not happen, but be safe
784 
785  for ( QgsAbstractGeometry::const_part_iterator itPart = geom->const_parts_begin() ; itPart != geom->const_parts_end() ; ++itPart )
786  {
787  QgsAbstractGeometry::vertex_iterator it = ( *itPart )->vertices_begin();
788  QgsAbstractGeometry::vertex_iterator itPrevious = ( *itPart )->vertices_begin();
789  it++;
790  for ( ; it != geom->vertices_end(); ++it, ++itPrevious )
791  {
792  const QgsPointXY pt( ( ( *itPrevious ).x() + ( *it ).x() ) / 2.0, ( ( *itPrevious ).y() + ( *it ).y() ) / 2.0 );
793  if ( mSrcRect.contains( pt ) )
794  {
795  const QgsPointLocator::Match m( QgsPointLocator::MiddleOfSegment, mLocator->mLayer, id, 0, pt, geom->vertexNrFromVertexId( it.vertexId() ) );
796 
797  // in range queries the filter may reject some matches
798  if ( mFilter && !mFilter->acceptMatch( m ) )
799  continue;
800 
801  mList << m;
802  }
803  }
804  }
805  }
806 
807  private:
808  QgsPointLocator *mLocator = nullptr;
810  QgsRectangle mSrcRect;
811  QgsPointLocator::MatchFilter *mFilter = nullptr;
812 };
813 
815 #include <QStack>
816 
822 class QgsPointLocator_DumpTree : public SpatialIndex::IQueryStrategy
823 {
824  private:
825  QStack<id_type> ids;
826 
827  public:
828 
829  void getNextEntry( const IEntry &entry, id_type &nextEntry, bool &hasNext ) override
830  {
831  const INode *n = dynamic_cast<const INode *>( &entry );
832  if ( !n )
833  return;
834 
835  QgsDebugMsgLevel( QStringLiteral( "NODE: %1" ).arg( n->getIdentifier() ), 4 );
836  if ( n->getLevel() > 0 )
837  {
838  // inner nodes
839  for ( uint32_t cChild = 0; cChild < n->getChildrenCount(); cChild++ )
840  {
841  QgsDebugMsgLevel( QStringLiteral( "- CH: %1" ).arg( n->getChildIdentifier( cChild ) ), 4 );
842  ids.push( n->getChildIdentifier( cChild ) );
843  }
844  }
845  else
846  {
847  // leaves
848  for ( uint32_t cChild = 0; cChild < n->getChildrenCount(); cChild++ )
849  {
850  QgsDebugMsgLevel( QStringLiteral( "- L: %1" ).arg( n->getChildIdentifier( cChild ) ), 4 );
851  }
852  }
853 
854  if ( ! ids.empty() )
855  {
856  nextEntry = ids.back();
857  ids.pop();
858  hasNext = true;
859  }
860  else
861  hasNext = false;
862  }
863 };
864 
866 
867 
869  : mLayer( layer )
870 {
871  if ( destCRS.isValid() )
872  {
873  mTransform = QgsCoordinateTransform( layer->crs(), destCRS, transformContext );
874  }
875 
876  setExtent( extent );
877 
878  mStorage.reset( StorageManager::createNewMemoryStorageManager() );
879 
880  connect( mLayer, &QgsVectorLayer::featureAdded, this, &QgsPointLocator::onFeatureAdded );
881  connect( mLayer, &QgsVectorLayer::featureDeleted, this, &QgsPointLocator::onFeatureDeleted );
882  connect( mLayer, &QgsVectorLayer::geometryChanged, this, &QgsPointLocator::onGeometryChanged );
883  connect( mLayer, &QgsVectorLayer::attributeValueChanged, this, &QgsPointLocator::onAttributeValueChanged );
885 }
886 
887 
889 {
890  // don't delete a locator if there is an indexing task running on it
891  mIsDestroying = true;
892  if ( mIsIndexing )
894 
895  destroyIndex();
896 }
897 
899 {
900  return mTransform.isValid() ? mTransform.destinationCrs() : QgsCoordinateReferenceSystem();
901 }
902 
904 {
905  if ( mIsIndexing )
906  // already indexing, return!
907  return;
908 
909  mExtent.reset( extent ? new QgsRectangle( *extent ) : nullptr );
910 
911  destroyIndex();
912 }
913 
915 {
916  if ( mIsIndexing )
917  // already indexing, return!
918  return;
919 
920  disconnect( mLayer, &QgsVectorLayer::styleChanged, this, &QgsPointLocator::destroyIndex );
921 
922  destroyIndex();
923  mContext.reset( nullptr );
924 
925  if ( context )
926  {
927  mContext = std::unique_ptr<QgsRenderContext>( new QgsRenderContext( *context ) );
929  }
930 
931 }
932 
933 void QgsPointLocator::onInitTaskFinished()
934 {
935  Q_ASSERT_X( QThread::currentThread() == qApp->thread(), "QgsPointLocator::onInitTaskFinished", "was not called on main thread" );
936 
937  // Check that we don't call this method twice, when calling waitForFinished
938  // for instance (because of taskCompleted signal)
939  if ( !mIsIndexing )
940  return;
941 
942  if ( mIsDestroying )
943  return;
944 
945  mIsIndexing = false;
946  mRenderer.reset();
947  mSource.reset();
948 
949  // treat added and deleted feature while indexing
950  for ( const QgsFeatureId fid : std::as_const( mAddedFeatures ) )
951  onFeatureAdded( fid );
952  mAddedFeatures.clear();
953 
954  for ( const QgsFeatureId fid : std::as_const( mDeletedFeatures ) )
955  onFeatureDeleted( fid );
956  mDeletedFeatures.clear();
957 
958  emit initFinished( mInitTask->isBuildOK() );
959 }
960 
961 bool QgsPointLocator::init( int maxFeaturesToIndex, bool relaxed )
962 {
963  const QgsWkbTypes::GeometryType geomType = mLayer->geometryType();
964  if ( geomType == QgsWkbTypes::NullGeometry // nothing to index
965  || hasIndex()
966  || mIsIndexing ) // already indexing, return!
967  return true;
968 
969  if ( !mLayer->dataProvider()
970  || !mLayer->dataProvider()->isValid() )
971  return false;
972 
973  mSource.reset( new QgsVectorLayerFeatureSource( mLayer ) );
974 
975  if ( mContext )
976  {
977  mRenderer.reset( mLayer->renderer() ? mLayer->renderer()->clone() : nullptr );
978  mContext->expressionContext() << QgsExpressionContextUtils::layerScope( mLayer );
979  }
980 
981  mIsIndexing = true;
982 
983  if ( relaxed )
984  {
985  mInitTask = new QgsPointLocatorInitTask( this );
986  connect( mInitTask, &QgsPointLocatorInitTask::taskTerminated, this, &QgsPointLocator::onInitTaskFinished );
987  connect( mInitTask, &QgsPointLocatorInitTask::taskCompleted, this, &QgsPointLocator::onInitTaskFinished );
988  QgsApplication::taskManager()->addTask( mInitTask );
989  return true;
990  }
991  else
992  {
993  const bool ok = rebuildIndex( maxFeaturesToIndex );
994  mIsIndexing = false;
995  emit initFinished( ok );
996  return ok;
997  }
998 }
999 
1001 {
1002  disconnect( mInitTask, &QgsPointLocatorInitTask::taskTerminated, this, &QgsPointLocator::onInitTaskFinished );
1003  disconnect( mInitTask, &QgsPointLocatorInitTask::taskCompleted, this, &QgsPointLocator::onInitTaskFinished );
1004  mInitTask->waitForFinished();
1005 
1006  if ( !mIsDestroying )
1007  onInitTaskFinished();
1008 }
1009 
1011 {
1012  return mIsIndexing || mRTree || mIsEmptyLayer;
1013 }
1014 
1015 bool QgsPointLocator::prepare( bool relaxed )
1016 {
1017  if ( mIsIndexing )
1018  {
1019  if ( relaxed )
1020  return false;
1021  else
1023  }
1024 
1025  if ( !mRTree )
1026  {
1027  init( -1, relaxed );
1028  if ( ( relaxed && mIsIndexing ) || !mRTree ) // relaxed mode and currently indexing or still invalid?
1029  return false;
1030  }
1031 
1032  return true;
1033 }
1034 
1035 bool QgsPointLocator::rebuildIndex( int maxFeaturesToIndex )
1036 {
1037  QElapsedTimer t;
1038  t.start();
1039 
1040  QgsDebugMsgLevel( QStringLiteral( "RebuildIndex start : %1" ).arg( mSource->id() ), 2 );
1041 
1042  destroyIndex();
1043 
1044  QLinkedList<RTree::Data *> dataList;
1045  QgsFeature f;
1046 
1047  QgsFeatureRequest request;
1048  request.setNoAttributes();
1049 
1050  if ( mExtent )
1051  {
1052  QgsRectangle rect = *mExtent;
1053  if ( !mTransform.isShortCircuited() )
1054  {
1055  QgsCoordinateTransform rectTransform = mTransform;
1056  rectTransform.setBallparkTransformsAreAppropriate( true );
1057  try
1058  {
1059  rect = rectTransform.transformBoundingBox( rect, Qgis::TransformDirection::Reverse );
1060  }
1061  catch ( const QgsException &e )
1062  {
1063  Q_UNUSED( e )
1064  // See https://github.com/qgis/QGIS/issues/20749
1065  QgsDebugMsg( QStringLiteral( "could not transform bounding box to map, skipping the snap filter (%1)" ).arg( e.what() ) );
1066  }
1067  }
1068  request.setFilterRect( rect );
1069  }
1070 
1071  bool filter = false;
1072  QgsRenderContext *ctx = nullptr;
1073  if ( mContext )
1074  {
1075  ctx = mContext.get();
1076  if ( mRenderer )
1077  {
1078  // setup scale for scale dependent visibility (rule based)
1079  mRenderer->startRender( *ctx, mSource->fields() );
1080  filter = mRenderer->capabilities() & QgsFeatureRenderer::Filter;
1081  request.setSubsetOfAttributes( mRenderer->usedAttributes( *ctx ), mSource->fields() );
1082  }
1083  }
1084 
1085  QgsFeatureIterator fi = mSource->getFeatures( request );
1086  int indexedCount = 0;
1087 
1088  while ( fi.nextFeature( f ) )
1089  {
1090  if ( !f.hasGeometry() )
1091  continue;
1092 
1093  if ( filter && ctx && mRenderer )
1094  {
1095  ctx->expressionContext().setFeature( f );
1096  if ( !mRenderer->willRenderFeature( f, *ctx ) )
1097  {
1098  continue;
1099  }
1100  }
1101 
1102  if ( mTransform.isValid() )
1103  {
1104  try
1105  {
1106  QgsGeometry transformedGeometry = f.geometry();
1107  transformedGeometry.transform( mTransform );
1108  f.setGeometry( transformedGeometry );
1109  }
1110  catch ( const QgsException &e )
1111  {
1112  Q_UNUSED( e )
1113  // See https://github.com/qgis/QGIS/issues/20749
1114  QgsDebugMsg( QStringLiteral( "could not transform geometry to map, skipping the snap for it (%1)" ).arg( e.what() ) );
1115  continue;
1116  }
1117  }
1118 
1119  const QgsRectangle bbox = f.geometry().boundingBox();
1120  if ( bbox.isFinite() )
1121  {
1122  SpatialIndex::Region r( rect2region( bbox ) );
1123  dataList << new RTree::Data( 0, nullptr, r, f.id() );
1124 
1125  auto it = mGeoms.find( f.id() );
1126  if ( it != mGeoms.end() )
1127  {
1128  delete *it;
1129  *it = new QgsGeometry( f.geometry() );
1130  }
1131  else
1132  {
1133  mGeoms[f.id()] = new QgsGeometry( f.geometry() );
1134  }
1135  ++indexedCount;
1136  }
1137 
1138  if ( maxFeaturesToIndex != -1 && indexedCount > maxFeaturesToIndex )
1139  {
1140  qDeleteAll( dataList );
1141  destroyIndex();
1142  return false;
1143  }
1144  }
1145 
1146  // R-Tree parameters
1147  const double fillFactor = 0.7;
1148  const unsigned long indexCapacity = 10;
1149  const unsigned long leafCapacity = 10;
1150  const unsigned long dimension = 2;
1151  const RTree::RTreeVariant variant = RTree::RV_RSTAR;
1152  SpatialIndex::id_type indexId;
1153 
1154  if ( dataList.isEmpty() )
1155  {
1156  mIsEmptyLayer = true;
1157  return true; // no features
1158  }
1159 
1160  QgsPointLocator_Stream stream( dataList );
1161  mRTree.reset( RTree::createAndBulkLoadNewRTree( RTree::BLM_STR, stream, *mStorage, fillFactor, indexCapacity,
1162  leafCapacity, dimension, variant, indexId ) );
1163 
1164  if ( ctx && mRenderer )
1165  {
1166  mRenderer->stopRender( *ctx );
1167  }
1168 
1169  QgsDebugMsgLevel( QStringLiteral( "RebuildIndex end : %1 ms (%2)" ).arg( t.elapsed() ).arg( mSource->id() ), 2 );
1170 
1171  return true;
1172 }
1173 
1174 
1176 {
1177  mRTree.reset();
1178 
1179  mIsEmptyLayer = false;
1180 
1181  qDeleteAll( mGeoms );
1182 
1183  mGeoms.clear();
1184 }
1185 
1186 void QgsPointLocator::onFeatureAdded( QgsFeatureId fid )
1187 {
1188  if ( mIsIndexing )
1189  {
1190  // will modify index once current indexing is finished
1191  mAddedFeatures << fid;
1192  return;
1193  }
1194 
1195  if ( !mRTree )
1196  {
1197  if ( mIsEmptyLayer )
1198  {
1199  // layer is not empty any more, let's build the index
1200  mIsEmptyLayer = false;
1201  init();
1202  }
1203  return; // nothing to do if we are not initialized yet
1204  }
1205 
1206  QgsFeature f;
1207  if ( mLayer->getFeatures( mContext ? QgsFeatureRequest( fid ) : QgsFeatureRequest( fid ).setNoAttributes() ).nextFeature( f ) )
1208  {
1209  if ( !f.hasGeometry() )
1210  return;
1211 
1212  if ( mContext )
1213  {
1214  std::unique_ptr< QgsFeatureRenderer > renderer( mLayer->renderer() ? mLayer->renderer()->clone() : nullptr );
1215  QgsRenderContext *ctx = nullptr;
1216 
1217  mContext->expressionContext() << QgsExpressionContextUtils::layerScope( mLayer );
1218  ctx = mContext.get();
1219  if ( renderer && ctx )
1220  {
1221  bool pass = false;
1222  renderer->startRender( *ctx, mLayer->fields() );
1223 
1224  ctx->expressionContext().setFeature( f );
1225  if ( !renderer->willRenderFeature( f, *ctx ) )
1226  {
1227  pass = true;
1228  }
1229 
1230  renderer->stopRender( *ctx );
1231  if ( pass )
1232  return;
1233  }
1234  }
1235 
1236  if ( mTransform.isValid() )
1237  {
1238  try
1239  {
1240  QgsGeometry transformedGeom = f.geometry();
1241  transformedGeom.transform( mTransform );
1242  f.setGeometry( transformedGeom );
1243  }
1244  catch ( const QgsException &e )
1245  {
1246  Q_UNUSED( e )
1247  // See https://github.com/qgis/QGIS/issues/20749
1248  QgsDebugMsg( QStringLiteral( "could not transform geometry to map, skipping the snap for it (%1)" ).arg( e.what() ) );
1249  return;
1250  }
1251  }
1252 
1253  const QgsRectangle bbox = f.geometry().boundingBox();
1254  if ( bbox.isFinite() )
1255  {
1256  const SpatialIndex::Region r( rect2region( bbox ) );
1257  mRTree->insertData( 0, nullptr, r, f.id() );
1258 
1259  auto it = mGeoms.find( f.id() );
1260  if ( it != mGeoms.end() )
1261  {
1262  delete *it;
1263  *it = new QgsGeometry( f.geometry() );
1264  }
1265  else
1266  {
1267  mGeoms[fid] = new QgsGeometry( f.geometry() );
1268  }
1269  }
1270  }
1271 }
1272 
1273 void QgsPointLocator::onFeatureDeleted( QgsFeatureId fid )
1274 {
1275  if ( mIsIndexing )
1276  {
1277  if ( mAddedFeatures.contains( fid ) )
1278  {
1279  mAddedFeatures.remove( fid );
1280  }
1281  else
1282  {
1283  // will modify index once current indexing is finished
1284  mDeletedFeatures << fid;
1285  }
1286  return;
1287  }
1288 
1289  if ( !mRTree )
1290  return; // nothing to do if we are not initialized yet
1291 
1292  auto it = mGeoms.find( fid );
1293  if ( it != mGeoms.end() )
1294  {
1295  mRTree->deleteData( rect2region( ( *it )->boundingBox() ), fid );
1296  delete *it;
1297  mGeoms.erase( it );
1298  }
1299 
1300 }
1301 
1302 void QgsPointLocator::onGeometryChanged( QgsFeatureId fid, const QgsGeometry &geom )
1303 {
1304  Q_UNUSED( geom )
1305  onFeatureDeleted( fid );
1306  onFeatureAdded( fid );
1307 }
1308 
1309 void QgsPointLocator::onAttributeValueChanged( QgsFeatureId fid, int idx, const QVariant &value )
1310 {
1311  Q_UNUSED( idx )
1312  Q_UNUSED( value )
1313  if ( mContext )
1314  {
1315  onFeatureDeleted( fid );
1316  onFeatureAdded( fid );
1317  }
1318 }
1319 
1320 
1321 QgsPointLocator::Match QgsPointLocator::nearestVertex( const QgsPointXY &point, double tolerance, MatchFilter *filter, bool relaxed )
1322 {
1323  if ( !prepare( relaxed ) )
1324  return Match();
1325 
1326  Match m;
1327  QgsPointLocator_VisitorNearestVertex visitor( this, m, point, filter );
1328  const QgsRectangle rect( point.x() - tolerance, point.y() - tolerance, point.x() + tolerance, point.y() + tolerance );
1329  mRTree->intersectsWithQuery( rect2region( rect ), visitor );
1330  if ( m.isValid() && m.distance() > tolerance )
1331  return Match(); // make sure that only match strictly within the tolerance is returned
1332  return m;
1333 }
1334 
1335 QgsPointLocator::Match QgsPointLocator::nearestCentroid( const QgsPointXY &point, double tolerance, MatchFilter *filter, bool relaxed )
1336 {
1337  if ( !prepare( relaxed ) )
1338  return Match();
1339 
1340  Match m;
1341  QgsPointLocator_VisitorNearestCentroid visitor( this, m, point, filter );
1342 
1343  const QgsRectangle rect( point.x() - tolerance, point.y() - tolerance, point.x() + tolerance, point.y() + tolerance );
1344  mRTree->intersectsWithQuery( rect2region( rect ), visitor );
1345  if ( m.isValid() && m.distance() > tolerance )
1346  return Match(); // make sure that only match strictly within the tolerance is returned
1347  return m;
1348 }
1349 
1350 QgsPointLocator::Match QgsPointLocator::nearestMiddleOfSegment( const QgsPointXY &point, double tolerance, MatchFilter *filter, bool relaxed )
1351 {
1352  if ( !prepare( relaxed ) )
1353  return Match();
1354 
1355  Match m;
1356  QgsPointLocator_VisitorNearestMiddleOfSegment visitor( this, m, point, filter );
1357 
1358  const QgsRectangle rect( point.x() - tolerance, point.y() - tolerance, point.x() + tolerance, point.y() + tolerance );
1359  mRTree->intersectsWithQuery( rect2region( rect ), visitor );
1360  if ( m.isValid() && m.distance() > tolerance )
1361  return Match(); // make sure that only match strictly within the tolerance is returned
1362  return m;
1363 }
1364 
1366 {
1367  if ( !prepare( relaxed ) )
1368  return Match();
1369 
1370  Match m;
1371  QgsPointLocator_VisitorNearestLineEndpoint visitor( this, m, point, filter );
1372 
1373  const QgsRectangle rect( point.x() - tolerance, point.y() - tolerance, point.x() + tolerance, point.y() + tolerance );
1374  mRTree->intersectsWithQuery( rect2region( rect ), visitor );
1375  if ( m.isValid() && m.distance() > tolerance )
1376  return Match(); // make sure that only match strictly within the tolerance is returned
1377  return m;
1378 }
1379 
1380 QgsPointLocator::Match QgsPointLocator::nearestEdge( const QgsPointXY &point, double tolerance, MatchFilter *filter, bool relaxed )
1381 {
1382  if ( !prepare( relaxed ) )
1383  return Match();
1384 
1385  const QgsWkbTypes::GeometryType geomType = mLayer->geometryType();
1386  if ( geomType == QgsWkbTypes::PointGeometry )
1387  return Match();
1388 
1389  Match m;
1390  QgsPointLocator_VisitorNearestEdge visitor( this, m, point, filter );
1391  const QgsRectangle rect( point.x() - tolerance, point.y() - tolerance, point.x() + tolerance, point.y() + tolerance );
1392  mRTree->intersectsWithQuery( rect2region( rect ), visitor );
1393  if ( m.isValid() && m.distance() > tolerance )
1394  return Match(); // make sure that only match strictly within the tolerance is returned
1395  return m;
1396 }
1397 
1398 QgsPointLocator::Match QgsPointLocator::nearestArea( const QgsPointXY &point, double tolerance, MatchFilter *filter, bool relaxed )
1399 {
1400  if ( !prepare( relaxed ) )
1401  return Match();
1402 
1403  const MatchList mlist = pointInPolygon( point );
1404  if ( !mlist.isEmpty() && mlist.at( 0 ).isValid() )
1405  {
1406  return mlist.at( 0 );
1407  }
1408 
1409  if ( tolerance == 0 )
1410  {
1411  return Match();
1412  }
1413 
1414  // discard point and line layers to keep only polygons
1415  const QgsWkbTypes::GeometryType geomType = mLayer->geometryType();
1416  if ( geomType == QgsWkbTypes::PointGeometry || geomType == QgsWkbTypes::LineGeometry )
1417  return Match();
1418 
1419  // use edges for adding tolerance
1420  const Match m = nearestEdge( point, tolerance, filter );
1421  if ( m.isValid() )
1422  return Match( Area, m.layer(), m.featureId(), m.distance(), m.point() );
1423  else
1424  return Match();
1425 }
1426 
1427 
1429 {
1430  if ( !prepare( relaxed ) )
1431  return MatchList();
1432 
1433  const QgsWkbTypes::GeometryType geomType = mLayer->geometryType();
1434  if ( geomType == QgsWkbTypes::PointGeometry )
1435  return MatchList();
1436 
1437  MatchList lst;
1438  QgsPointLocator_VisitorEdgesInRect visitor( this, lst, rect, filter );
1439  mRTree->intersectsWithQuery( rect2region( rect ), visitor );
1440 
1441  return lst;
1442 }
1443 
1445 {
1446  const QgsRectangle rect( point.x() - tolerance, point.y() - tolerance, point.x() + tolerance, point.y() + tolerance );
1447  return edgesInRect( rect, filter, relaxed );
1448 }
1449 
1451 {
1452  if ( !prepare( relaxed ) )
1453  return MatchList();
1454 
1455  MatchList lst;
1456  QgsPointLocator_VisitorVerticesInRect visitor( this, lst, rect, filter );
1457  mRTree->intersectsWithQuery( rect2region( rect ), visitor );
1458 
1459  return lst;
1460 }
1461 
1463 {
1464  const QgsRectangle rect( point.x() - tolerance, point.y() - tolerance, point.x() + tolerance, point.y() + tolerance );
1465  return verticesInRect( rect, filter, relaxed );
1466 }
1467 
1469 {
1470  if ( !prepare( relaxed ) )
1471  return MatchList();
1472 
1473  const QgsWkbTypes::GeometryType geomType = mLayer->geometryType();
1474  if ( geomType == QgsWkbTypes::PointGeometry || geomType == QgsWkbTypes::LineGeometry )
1475  return MatchList();
1476 
1477  MatchList lst;
1478  QgsPointLocator_VisitorArea visitor( this, point, lst );
1479  mRTree->intersectsWithQuery( point2point( point ), visitor );
1480  return lst;
1481 }
QgsCurve
Abstract base class for curved geometry type.
Definition: qgscurve.h:35
QgsPointLocator_VisitorNearestEdge::visitData
void visitData(std::vector< const IData * > &v) override
Definition: qgspointlocator.cpp:383
QgsVectorLayer::getFeatures
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
Definition: qgsvectorlayer.cpp:1052
SpatialIndex
Definition: qgspointlocator.h:83
QgsMapLayer::crs
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:79
QgsPointLocator_VisitorArea
Helper class used when traversing the index with areas - builds a list of matches.
Definition: qgspointlocator.cpp:425
qgsexpressioncontextutils.h
QgsFeatureRenderer::Filter
@ Filter
Features may be filtered, i.e. some features may not be rendered (categorized, rule based ....
Definition: qgsrenderer.h:265
QgsRectangle::isFinite
bool isFinite() const
Returns true if the rectangle has finite boundaries.
Definition: qgsrectangle.h:559
QgsPointLocator_VisitorArea::visitData
void visitData(std::vector< const IData * > &v) override
Definition: qgspointlocator.cpp:436
QgsPointXY::y
double y
Definition: qgspointxy.h:63
QgsException
Defines a QGIS exception class.
Definition: qgsexception.h:34
QgsCoordinateTransformContext
Contains information about the context in which a coordinate transform is executed.
Definition: qgscoordinatetransformcontext.h:57
QgsPointLocator_VisitorEdgesInRect::visitData
void visitData(std::vector< const IData * > &v) override
Definition: qgspointlocator.cpp:635
QgsVectorLayer::dataProvider
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
Definition: qgsvectorlayer.cpp:676
QgsRenderContext::expressionContext
QgsExpressionContext & expressionContext()
Gets the expression context.
Definition: qgsrendercontext.h:625
qgslinestring.h
QgsCurve::startPoint
virtual QgsPoint startPoint() const =0
Returns the starting point of the curve.
QgsWkbTypes::NullGeometry
@ NullGeometry
Definition: qgswkbtypes.h:146
QgsPointLocator_Stream::rewind
void rewind() override
Definition: qgspointlocator.cpp:82
QgsPoint
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:48
QgsGeometry::const_parts_end
QgsAbstractGeometry::const_part_iterator const_parts_end() const
Returns STL-style iterator pointing to the imaginary part after the last part of the geometry.
Definition: qgsgeometry.cpp:2026
qgswkbptr.h
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsGeometry::transform
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
Definition: qgsgeometry.cpp:3128
QgsMeshUtils::centroid
CORE_EXPORT QgsMeshVertex centroid(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns the centroid of the face.
Definition: qgstriangularmesh.cpp:955
QgsPointLocator::setRenderContext
void setRenderContext(const QgsRenderContext *context)
Configure render context - if not nullptr, it will use to index only visible feature.
Definition: qgspointlocator.cpp:914
LEFT
#define LEFT(x)
Definition: priorityqueue.h:38
QgsPointLocator::nearestArea
Match nearestArea(const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter=nullptr, bool relaxed=false)
Find nearest area to the specified point - up to distance specified by tolerance Optional filter may ...
Definition: qgspointlocator.cpp:1398
QgsPointLocator_VisitorNearestLineEndpoint::visitData
void visitData(std::vector< const IData * > &v) override
Definition: qgspointlocator.cpp:281
QgsCurvePolygon
Curve polygon geometry type.
Definition: qgscurvepolygon.h:34
qgsfeatureiterator.h
QgsRectangle::yMinimum
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
QgsCoordinateTransform::transformBoundingBox
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool handle180Crossover=false) const SIP_THROW(QgsCsException)
Transforms a rectangle from the source CRS to the destination CRS.
Definition: qgscoordinatetransform.cpp:560
QgsExpressionContextUtils::layerScope
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
Definition: qgsexpressioncontextutils.cpp:334
QgsGeometry::centroid
QgsGeometry centroid() const
Returns the center of mass of a geometry.
Definition: qgsgeometry.cpp:2284
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:71
qgis.h
QgsRenderContext
Contains information about the context of a rendering operation.
Definition: qgsrendercontext.h:59
QgsPointLocator_VisitorNearestMiddleOfSegment::visitData
void visitData(std::vector< const IData * > &v) override
Definition: qgspointlocator.cpp:220
QgsPointLocator_VisitorCentroidsInRect::QgsPointLocator_VisitorCentroidsInRect
QgsPointLocator_VisitorCentroidsInRect(QgsPointLocator *pl, QgsPointLocator::MatchList &lst, const QgsRectangle &srcRect, QgsPointLocator::MatchFilter *filter=nullptr)
Constructs the visitor.
Definition: qgspointlocator.cpp:723
QgsPointLocator_VisitorNearestCentroid::visitData
void visitData(std::vector< const IData * > &v) override
Definition: qgspointlocator.cpp:166
QgsGeometry::const_parts_begin
QgsAbstractGeometry::const_part_iterator const_parts_begin() const
Returns STL-style const iterator pointing to the first part of the geometry.
Definition: qgsgeometry.cpp:2019
QgsPointXY::isEmpty
bool isEmpty() const SIP_HOLDGIL
Returns true if the geometry is empty.
Definition: qgspointxy.h:249
QgsPointLocator::~QgsPointLocator
~QgsPointLocator() override
Definition: qgspointlocator.cpp:888
QgsVectorLayer::featureDeleted
void featureDeleted(QgsFeatureId fid)
Emitted when a feature has been deleted.
QgsFeatureRequest::setSubsetOfAttributes
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
Definition: qgsfeaturerequest.cpp:228
QgsPointLocator::Match::point
QgsPointXY point() const
for vertex / edge match coords depending on what class returns it (geom.cache: layer coords,...
Definition: qgspointlocator.h:238
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsPointLocator_DumpTree::getNextEntry
void getNextEntry(const IEntry &entry, id_type &nextEntry, bool &hasNext) override
Definition: qgspointlocator.cpp:829
QgsPointLocator_VisitorNearestVertex
Helper class used when traversing the index looking for vertices - builds a list of matches.
Definition: qgspointlocator.cpp:98
QgsPointLocator_VisitorNearestCentroid::visitData
void visitData(const IData &d) override
Definition: qgspointlocator.cpp:168
QgsCoordinateTransform::isValid
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
Definition: qgscoordinatetransform.cpp:900
QgsPointLocator_VisitorMiddlesInRect::visitData
void visitData(const IData &d) override
Definition: qgspointlocator.cpp:778
QgsPointLocator::edgesInRect
MatchList edgesInRect(const QgsRectangle &rect, QgsPointLocator::MatchFilter *filter=nullptr, bool relaxed=false)
Find edges within a specified rectangle Optional filter may discard unwanted matches.
Definition: qgspointlocator.cpp:1428
QgsPointLocator_VisitorCentroidsInRect
Helper class used when traversing the index looking for centroid - builds a list of matches.
Definition: qgspointlocator.cpp:719
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsWkbTypes::PolygonGeometry
@ PolygonGeometry
Definition: qgswkbtypes.h:144
QgsGeometry::closestVertex
QgsPointXY closestVertex(const QgsPointXY &point, int &closestVertexIndex, int &previousVertexIndex, int &nextVertexIndex, double &sqrDist) const
Returns the vertex closest to the given point, the corresponding vertex index, squared distance snap ...
Definition: qgsgeometry.cpp:397
QgsPointLocator_VisitorNearestMiddleOfSegment::visitNode
void visitNode(const INode &n) override
Definition: qgspointlocator.cpp:219
QgsPointLocator_VisitorNearestMiddleOfSegment
Helper class used when traversing the index looking for middle segment - builds a list of matches.
Definition: qgspointlocator.cpp:202
QgsPointLocator::init
bool init(int maxFeaturesToIndex=-1, bool relaxed=false)
Prepare the index for queries.
Definition: qgspointlocator.cpp:961
QgsTaskManager::addTask
long addTask(QgsTask *task, int priority=0)
Adds a task to the manager.
Definition: qgstaskmanager.cpp:420
QgsPointLocator_VisitorNearestCentroid
Helper class used when traversing the index looking for centroid - builds a list of matches.
Definition: qgspointlocator.cpp:148
QgsGeometry::isMultipart
bool isMultipart() const SIP_HOLDGIL
Returns true if WKB of the geometry is of WKBMulti* type.
Definition: qgsgeometry.cpp:389
QgsPointLocator::nearestVertex
Match nearestVertex(const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter=nullptr, bool relaxed=false)
Find nearest vertex to the specified point - up to distance specified by tolerance Optional filter ma...
Definition: qgspointlocator.cpp:1321
QgsPointLocator_VisitorNearestVertex::visitNode
void visitNode(const INode &n) override
Definition: qgspointlocator.cpp:108
qgsapplication.h
QgsPointXY::sqrDist
double sqrDist(double x, double y) const SIP_HOLDGIL
Returns the squared distance between this point a specified x, y coordinate.
Definition: qgspointxy.h:190
QgsPointLocator_VisitorNearestLineEndpoint::visitNode
void visitNode(const INode &n) override
Definition: qgspointlocator.cpp:280
QgsCoordinateTransform::destinationCrs
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system, which the transform will transform coordinates t...
Definition: qgscoordinatetransform.cpp:267
QgsGeometry::convertToStraightSegment
void convertToStraightSegment(double tolerance=M_PI/180., QgsAbstractGeometry::SegmentationToleranceType toleranceType=QgsAbstractGeometry::MaximumAngle)
Converts the geometry to straight line segments, if it is a curved geometry type.
Definition: qgsgeometry.cpp:3107
QgsFeatureRequest::setFilterRect
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
Definition: qgsfeaturerequest.cpp:101
QgsVectorLayer::fields
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Definition: qgsvectorlayer.cpp:3436
QgsPointLocator::rebuildIndex
bool rebuildIndex(int maxFeaturesToIndex=-1)
Definition: qgspointlocator.cpp:1035
QgsRectangle::xMaximum
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
QgsFeature::id
QgsFeatureId id
Definition: qgsfeature.h:68
QgsPointLocator_VisitorCentroidsInRect::visitData
void visitData(std::vector< const IData * > &v) override
Definition: qgspointlocator.cpp:731
QgsFeatureRequest
This class wraps a request for features to a vector layer (or directly its vector data provider).
Definition: qgsfeaturerequest.h:83
QgsPointLocator_VisitorMiddlesInRect::visitNode
void visitNode(const INode &n) override
Definition: qgspointlocator.cpp:775
QgsGeometry::intersects
bool intersects(const QgsRectangle &rectangle) const
Returns true if this geometry exactly intersects with a rectangle.
Definition: qgsgeometry.cpp:1255
_CohenSutherland::isSegmentInRect
bool isSegmentInRect(double x0, double y0, double x1, double y1)
Definition: qgspointlocator.cpp:487
QgsCoordinateTransform::isShortCircuited
bool isShortCircuited() const
Returns true if the transform short circuits because the source and destination are equivalent.
Definition: qgscoordinatetransform.cpp:905
QgsPointLocator_VisitorNearestLineEndpoint
Helper class used when traversing the index looking for line endpoints (start or end vertex) - builds...
Definition: qgspointlocator.cpp:265
QgsPointLocator_VisitorNearestVertex::visitData
void visitData(const IData &d) override
Definition: qgspointlocator.cpp:111
QgsFeature::setGeometry
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:170
QgsPointLocator::verticesInRect
MatchList verticesInRect(const QgsRectangle &rect, QgsPointLocator::MatchFilter *filter=nullptr, bool relaxed=false)
Find vertices within a specified rectangle This method is either blocking or non blocking according t...
Definition: qgspointlocator.cpp:1450
QgsCoordinateTransform::setBallparkTransformsAreAppropriate
void setBallparkTransformsAreAppropriate(bool appropriate)
Sets whether approximate "ballpark" results are appropriate for this coordinate transform.
Definition: qgscoordinatetransform.cpp:939
_CohenSutherland::computeOutCode
OutCode computeOutCode(double x, double y)
Definition: qgspointlocator.cpp:473
QgsPointLocator_VisitorEdgesInRect::visitNode
void visitNode(const INode &n) override
Definition: qgspointlocator.cpp:634
QgsPointLocator::MatchList
class QList< QgsPointLocator::Match > MatchList
Definition: qgspointlocator.h:339
QgsPointLocator_VisitorNearestLineEndpoint::QgsPointLocator_VisitorNearestLineEndpoint
QgsPointLocator_VisitorNearestLineEndpoint(QgsPointLocator *pl, QgsPointLocator::Match &m, const QgsPointXY &srcPoint, QgsPointLocator::MatchFilter *filter=nullptr)
Helper class used when traversing the index looking for line endpoints (start or end vertex) - builds...
Definition: qgspointlocator.cpp:273
QgsAbstractGeometry::const_part_iterator
The part_iterator class provides STL-style iterator for const references to geometry parts.
Definition: qgsabstractgeometry.h:864
QgsPointLocator_DumpTree
Helper class to dump the R-index nodes and their content.
Definition: qgspointlocator.cpp:822
QgsMapLayer::styleChanged
void styleChanged()
Signal emitted whenever a change affects the layer's style.
QgsPointLocator::nearestLineEndpoints
Match nearestLineEndpoints(const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter=nullptr, bool relaxed=false)
Find nearest line endpoint (start or end vertex) to the specified point - up to distance specified by...
Definition: qgspointlocator.cpp:1365
QgsFeatureRenderer::clone
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
_CohenSutherland::OutCode
int OutCode
Definition: qgspointlocator.cpp:463
QgsPointLocator_VisitorNearestEdge::visitNode
void visitNode(const INode &n) override
Definition: qgspointlocator.cpp:382
QgsPointLocator::nearestMiddleOfSegment
Match nearestMiddleOfSegment(const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter=nullptr, bool relaxed=false)
Find nearest middle of segment to the specified point - up to distance specified by tolerance Optiona...
Definition: qgspointlocator.cpp:1350
QgsException::what
QString what() const
Definition: qgsexception.h:48
QgsVectorLayer::attributeValueChanged
void attributeValueChanged(QgsFeatureId fid, int idx, const QVariant &value)
Emitted whenever an attribute value change is done in the edit buffer.
QgsPointLocator::hasIndex
bool hasIndex() const
Indicate whether the data have been already indexed.
Definition: qgspointlocator.cpp:1010
QgsPointLocator_VisitorVerticesInRect::QgsPointLocator_VisitorVerticesInRect
QgsPointLocator_VisitorVerticesInRect(QgsPointLocator *pl, QgsPointLocator::MatchList &lst, const QgsRectangle &srcRect, QgsPointLocator::MatchFilter *filter=nullptr)
Constructs the visitor.
Definition: qgspointlocator.cpp:674
QgsPointLocator_VisitorNearestEdge
Helper class used when traversing the index looking for edges - builds a list of matches.
Definition: qgspointlocator.cpp:372
QgsApplication::taskManager
static QgsTaskManager * taskManager()
Returns the application's task manager, used for managing application wide background task handling.
Definition: qgsapplication.cpp:2300
QgsPointLocator::LineEndpoint
@ LineEndpoint
Start or end points of lines only (since QGIS 3.20)
Definition: qgspointlocator.h:163
qgsrendercontext.h
QgsPointLocator::Match::isValid
bool isValid() const
Definition: qgspointlocator.h:209
QgsCoordinateReferenceSystem::isValid
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Definition: qgscoordinatereferencesystem.cpp:977
QgsPointLocator::setExtent
void setExtent(const QgsRectangle *extent)
Configure extent - if not nullptr, it will index only that area.
Definition: qgspointlocator.cpp:903
QgsPointLocator::Centroid
@ Centroid
Snapped to a centroid.
Definition: qgspointlocator.h:161
QgsPointLocator_VisitorNearestMiddleOfSegment::visitData
void visitData(const IData &d) override
Definition: qgspointlocator.cpp:222
QgsPointLocator_VisitorMiddlesInRect::visitData
void visitData(std::vector< const IData * > &v) override
Definition: qgspointlocator.cpp:776
QgsGeometry::isEmpty
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
Definition: qgsgeometry.cpp:379
qgsvectorlayerfeatureiterator.h
QgsPointLocator_VisitorVerticesInRect
Helper class used when traversing the index looking for vertices - builds a list of matches.
Definition: qgspointlocator.cpp:670
QgsPointLocator_VisitorNearestEdge::visitData
void visitData(const IData &d) override
Definition: qgspointlocator.cpp:385
QgsPointLocator::Match::layer
QgsVectorLayer * layer() const
The vector layer where the snap occurred.
Definition: qgspointlocator.h:247
QgsPointLocator_VisitorVerticesInRect::visitData
void visitData(const IData &d) override
Definition: qgspointlocator.cpp:684
QgsPointLocator::extent
const QgsRectangle * extent() const
Gets extent of the area point locator covers - if nullptr then it caches the whole layer.
Definition: qgspointlocator.h:138
QgsPointLocator_VisitorMiddlesInRect
Helper class used when traversing the index looking for middle segment - builds a list of matches.
Definition: qgspointlocator.cpp:764
QgsAbstractGeometry::hasCurvedSegments
virtual bool hasCurvedSegments() const
Returns true if the geometry contains curved segments.
Definition: qgsabstractgeometry.cpp:385
QgsPointLocator_Stream::hasNext
bool hasNext() override
Definition: qgspointlocator.cpp:79
QgsAbstractGeometry::vertex_iterator::vertexId
QgsVertexId vertexId() const
Returns vertex ID of the current item.
Definition: qgsabstractgeometry.cpp:447
QgsRectangle::xMinimum
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
qgsrenderer.h
QgsGeometry::closestSegmentWithContext
double closestSegmentWithContext(const QgsPointXY &point, QgsPointXY &minDistPoint, int &nextVertexIndex, int *leftOrRightOfSegment=nullptr, double epsilon=DEFAULT_SEGMENT_EPSILON) const
Searches for the closest segment of geometry to the given point.
Definition: qgsgeometry.cpp:751
_CohenSutherland::mRect
QgsRectangle mRect
Definition: qgspointlocator.cpp:471
QgsFeatureRequest::setNoAttributes
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
Definition: qgsfeaturerequest.cpp:235
qgscurvepolygon.h
QgsCoordinateReferenceSystem
This class represents a coordinate reference system (CRS).
Definition: qgscoordinatereferencesystem.h:211
QgsPointLocator::Vertex
@ Vertex
Snapped to a vertex. Can be a vertex of the geometry or an intersection.
Definition: qgspointlocator.h:158
QgsPointLocator_VisitorNearestEdge::QgsPointLocator_VisitorNearestEdge
QgsPointLocator_VisitorNearestEdge(QgsPointLocator *pl, QgsPointLocator::Match &m, const QgsPointXY &srcPoint, QgsPointLocator::MatchFilter *filter=nullptr)
Definition: qgspointlocator.cpp:375
QgsPointLocator_VisitorNearestLineEndpoint::visitData
void visitData(const IData &d) override
Definition: qgspointlocator.cpp:283
QgsGeometry::vertexAt
QgsPoint vertexAt(int atVertex) const
Returns coordinates of a vertex.
Definition: qgsgeometry.cpp:683
QgsPointLocator::Match
Definition: qgspointlocator.h:187
qgsvectorlayer.h
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:58
QgsPointLocator::destinationCrs
QgsCoordinateReferenceSystem destinationCrs() const
Gets destination CRS - may be an invalid QgsCoordinateReferenceSystem if not doing OTF reprojection.
Definition: qgspointlocator.cpp:898
QgsPointLocator_VisitorEdgesInRect
Helper class used when traversing the index looking for edges - builds a list of matches.
Definition: qgspointlocator.cpp:624
QgsMapLayer::dataChanged
void dataChanged()
Data of layer changed.
QgsGeometry::asPoint
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
Definition: qgsgeometry.cpp:1662
QgsPointLocator_VisitorVerticesInRect::visitData
void visitData(std::vector< const IData * > &v) override
Definition: qgspointlocator.cpp:682
_CohenSutherland::_CohenSutherland
_CohenSutherland(const QgsRectangle &rect)
Definition: qgspointlocator.cpp:461
QgsPointLocator_VisitorNearestCentroid::visitNode
void visitNode(const INode &n) override
Definition: qgspointlocator.cpp:165
QgsPointLocator::Match::featureId
QgsFeatureId featureId() const
The id of the feature to which the snapped geometry belongs.
Definition: qgspointlocator.h:252
QgsWkbTypes::LineGeometry
@ LineGeometry
Definition: qgswkbtypes.h:143
QgsPointLocator_VisitorNearestCentroid::QgsPointLocator_VisitorNearestCentroid
QgsPointLocator_VisitorNearestCentroid(QgsPointLocator *pl, QgsPointLocator::Match &m, const QgsPointXY &srcPoint, QgsPointLocator::MatchFilter *filter=nullptr)
Helper class used when traversing the index looking for centroid - builds a list of matches.
Definition: qgspointlocator.cpp:158
QgsWkbTypes::PointGeometry
@ PointGeometry
Definition: qgswkbtypes.h:142
QgsRectangle::yMaximum
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
qgsgeometry.h
QgsWkbTypes::GeometryType
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:140
QgsAbstractGeometry::vertex_iterator
The vertex_iterator class provides STL-style iterator for vertices.
Definition: qgsabstractgeometry.h:924
QgsFeatureIterator::nextFeature
bool nextFeature(QgsFeature &f)
Definition: qgsfeatureiterator.h:399
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsPointLocator::Edge
@ Edge
Snapped to an edge.
Definition: qgspointlocator.h:159
QgsPointLocator_Stream::QgsPointLocator_Stream
QgsPointLocator_Stream(const QLinkedList< RTree::Data * > &dataList)
Definition: qgspointlocator.cpp:73
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:391
QgsFeature::hasGeometry
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:230
_CohenSutherland
Definition: qgspointlocator.cpp:459
QgsVectorLayer::geometryChanged
void geometryChanged(QgsFeatureId fid, const QgsGeometry &geometry)
Emitted whenever a geometry change is done in the edit buffer.
RIGHT
#define RIGHT(x)
Definition: priorityqueue.h:39
QgsPointXY::x
double x
Definition: qgspointxy.h:62
QgsVectorLayerFeatureSource
Partial snapshot of vector layer's state (only the members necessary for access to features)
Definition: qgsvectorlayerfeatureiterator.h:52
QgsPointLocator::pointInPolygon
MatchList pointInPolygon(const QgsPointXY &point, bool relaxed=false)
find out if the point is in any polygons This method is either blocking or non blocking according to ...
Definition: qgspointlocator.cpp:1468
QgsPointLocator
The class defines interface for querying point location:
Definition: qgspointlocator.h:101
QgsPointLocator::QgsPointLocator
QgsPointLocator(QgsVectorLayer *layer, const QgsCoordinateReferenceSystem &destinationCrs=QgsCoordinateReferenceSystem(), const QgsCoordinateTransformContext &transformContext=QgsCoordinateTransformContext(), const QgsRectangle *extent=nullptr)
Construct point locator for a layer.
Definition: qgspointlocator.cpp:868
QgsGeometry::convertToType
QgsGeometry convertToType(QgsWkbTypes::GeometryType destType, bool destMultipart=false) const
Try to convert the geometry to the requested type.
Definition: qgsgeometry.cpp:1553
QgsPointLocator_VisitorArea::visitData
void visitData(const IData &d) override
Definition: qgspointlocator.cpp:438
QgsGeometry::vertexNrFromVertexId
int vertexNrFromVertexId(QgsVertexId id) const
Returns the vertex number corresponding to a vertex id.
Definition: qgsgeometry.cpp:3299
QgsPointLocator_VisitorNearestVertex::visitData
void visitData(std::vector< const IData * > &v) override
Definition: qgspointlocator.cpp:109
QgsPointLocator_VisitorArea::visitNode
void visitNode(const INode &n) override
Definition: qgspointlocator.cpp:435
QgsWkbTypes::UnknownGeometry
@ UnknownGeometry
Definition: qgswkbtypes.h:145
QgsPointLocator::layer
QgsVectorLayer * layer() const
Gets associated layer.
Definition: qgspointlocator.h:126
QgsWkbTypes::geometryType
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...
Definition: qgswkbtypes.h:968
QgsPointLocator::QgsPointLocatorInitTask
friend class QgsPointLocatorInitTask
Definition: qgspointlocator.h:525
QgsPointLocator::nearestCentroid
Match nearestCentroid(const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter=nullptr, bool relaxed=false)
Find nearest centroid to the specified point - up to distance specified by tolerance Optional filter ...
Definition: qgspointlocator.cpp:1335
QgsPointLocator::destroyIndex
void destroyIndex()
Definition: qgspointlocator.cpp:1175
QgsPointLocator::MatchFilter
Interface that allows rejection of some matches in intersection queries (e.g.
Definition: qgspointlocator.h:349
QgsPointLocator_Stream
Helper class for bulk loading of R-trees.
Definition: qgspointlocator.cpp:70
QgsGeometry::boundingBox
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Definition: qgsgeometry.cpp:1080
qgspointlocatorinittask.h
qgspointlocator.h
QgsPointLocator_VisitorNearestMiddleOfSegment::QgsPointLocator_VisitorNearestMiddleOfSegment
QgsPointLocator_VisitorNearestMiddleOfSegment(QgsPointLocator *pl, QgsPointLocator::Match &m, const QgsPointXY &srcPoint, QgsPointLocator::MatchFilter *filter=nullptr)
Helper class used when traversing the index looking for middle segment - builds a list of matches.
Definition: qgspointlocator.cpp:212
QgsPointLocator::nearestEdge
Match nearestEdge(const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter=nullptr, bool relaxed=false)
Find nearest edge to the specified point - up to distance specified by tolerance Optional filter may ...
Definition: qgspointlocator.cpp:1380
QgsFeature
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:55
QgsPointLocator_VisitorMiddlesInRect::QgsPointLocator_VisitorMiddlesInRect
QgsPointLocator_VisitorMiddlesInRect(QgsPointLocator *pl, QgsPointLocator::MatchList &lst, const QgsRectangle &srcRect, QgsPointLocator::MatchFilter *filter=nullptr)
Constructs the visitor.
Definition: qgspointlocator.cpp:768
QgsCurve::numPoints
virtual int numPoints() const =0
Returns the number of points in the curve.
QgsGeometry::vertices_end
QgsAbstractGeometry::vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry.
Definition: qgsgeometry.cpp:1989
QgsPointLocator::MiddleOfSegment
@ MiddleOfSegment
Snapped to the middle of a segment.
Definition: qgspointlocator.h:162
QgsPointLocator_VisitorVerticesInRect::visitNode
void visitNode(const INode &n) override
Definition: qgspointlocator.cpp:681
qgslogger.h
QgsGeometry::vertices_begin
QgsAbstractGeometry::vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
Definition: qgsgeometry.cpp:1982
QgsPointLocator_VisitorArea::QgsPointLocator_VisitorArea
QgsPointLocator_VisitorArea(QgsPointLocator *pl, const QgsPointXY &origPt, QgsPointLocator::MatchList &list)
constructor
Definition: qgspointlocator.cpp:429
QgsCoordinateTransform
Class for doing transforms between two map coordinate systems.
Definition: qgscoordinatetransform.h:57
QgsPointLocator::initFinished
void initFinished(bool ok)
Emitted whenever index has been built and initialization is finished.
QgsPointLocator_Stream::size
uint32_t size() override
Definition: qgspointlocator.cpp:81
QgsGeometry::type
QgsWkbTypes::GeometryType type
Definition: qgsgeometry.h:128
QgsFeatureIterator
Wrapper for iterator of features from vector data provider or vector layer.
Definition: qgsfeatureiterator.h:289
QgsVectorLayer::geometryType
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
Definition: qgsvectorlayer.cpp:720
QgsPointLocator_Stream::getNext
IData * getNext() override
Definition: qgspointlocator.cpp:78
QgsPointLocator_VisitorCentroidsInRect::visitData
void visitData(const IData &d) override
Definition: qgspointlocator.cpp:733
QgsPointLocator_VisitorCentroidsInRect::visitNode
void visitNode(const INode &n) override
Definition: qgspointlocator.cpp:730
QgsPointLocator_VisitorNearestVertex::QgsPointLocator_VisitorNearestVertex
QgsPointLocator_VisitorNearestVertex(QgsPointLocator *pl, QgsPointLocator::Match &m, const QgsPointXY &srcPoint, QgsPointLocator::MatchFilter *filter=nullptr)
Definition: qgspointlocator.cpp:101
QgsPointLocator::waitForIndexingFinished
void waitForIndexingFinished()
If the point locator has been initialized relaxedly and is currently indexing, this methods waits for...
Definition: qgspointlocator.cpp:1000
QgsGeometry::wkbType
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
Definition: qgsgeometry.cpp:357
QgsDataProvider::isValid
virtual bool isValid() const =0
Returns true if this is a valid layer.
QgsPointLocator_VisitorEdgesInRect::visitData
void visitData(const IData &d) override
Definition: qgspointlocator.cpp:637
QgsFeatureId
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
QgsPointLocator::Area
@ Area
Snapped to an area.
Definition: qgspointlocator.h:160
QgsPointLocator_VisitorEdgesInRect::QgsPointLocator_VisitorEdgesInRect
QgsPointLocator_VisitorEdgesInRect(QgsPointLocator *pl, QgsPointLocator::MatchList &lst, const QgsRectangle &srcRect, QgsPointLocator::MatchFilter *filter=nullptr)
Definition: qgspointlocator.cpp:627
QgsExpressionContext::setFeature
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Definition: qgsexpressioncontext.cpp:525
QgsPointLocator::Match::distance
double distance() const
for vertex / edge match units depending on what class returns it (geom.cache: layer units,...
Definition: qgspointlocator.h:232
QgsVectorLayer::renderer
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
Definition: qgsvectorlayer.h:903
QgsVectorLayer::featureAdded
void featureAdded(QgsFeatureId fid)
Emitted when a new feature has been added to the layer.