27 #include <spatialindex/SpatialIndex.h> 29 #include <QLinkedListIterator> 35 static SpatialIndex::Point point2point(
const QgsPointXY &point )
37 double plow[2] = { point.
x(), point.
y() };
38 return Point( plow, 2 );
42 static SpatialIndex::Region rect2region(
const QgsRectangle &rect )
46 return SpatialIndex::Region( pLow, pHigh, 2 );
54 static const double POINT_LOC_EPSILON = 1e-12;
68 : mDataList( dataList )
72 IData *
getNext()
override {
return mIt.next(); }
73 bool hasNext()
override {
return mIt.hasNext(); }
75 uint32_t
size()
override { Q_ASSERT(
false &&
"not available" );
return 0; }
76 void rewind()
override { Q_ASSERT(
false &&
"not available" ); }
79 QLinkedList<RTree::Data *> mDataList;
80 QLinkedListIterator<RTree::Data *> mIt;
98 , mSrcPoint( srcPoint )
102 void visitNode(
const INode &n )
override { Q_UNUSED( n ); }
103 void visitData( std::vector<const IData *> &v )
override { Q_UNUSED( v ); }
109 int vertexIndex, beforeVertex, afterVertex;
118 if ( mFilter && !mFilter->acceptMatch( m ) )
121 if ( !mBest.isValid() || m.
distance() < mBest.distance() )
147 , mSrcPoint( srcPoint )
151 void visitNode(
const INode &n )
override { Q_UNUSED( n ); }
152 void visitData( std::vector<const IData *> &v )
override { Q_UNUSED( v ); }
165 edgePoints[0] = geom->
vertexAt( afterVertex - 1 );
166 edgePoints[1] = geom->
vertexAt( afterVertex );
169 if ( mFilter && !mFilter->acceptMatch( m ) )
172 if ( !mBest.isValid() || m.
distance() < mBest.distance() )
201 void visitNode(
const INode &n )
override { Q_UNUSED( n ); }
202 void visitData( std::vector<const IData *> &v )
override { Q_UNUSED( v ); }
228 static const int INSIDE = 0;
231 static const int BOTTOM = 4;
232 static const int TOP = 8;
238 OutCode code = INSIDE;
253 OutCode outcode0 = computeOutCode( x0, y0 );
254 OutCode outcode1 = computeOutCode( x1, y1 );
259 if ( !( outcode0 | outcode1 ) )
265 else if ( outcode0 & outcode1 )
277 OutCode outcodeOut = outcode0 ? outcode0 : outcode1;
281 if ( outcodeOut & TOP )
284 x = x0 + ( x1 - x0 ) * ( mRect.
yMaximum() - y0 ) / ( y1 - y0 );
287 else if ( outcodeOut & BOTTOM )
290 x = x0 + ( x1 - x0 ) * ( mRect.
yMinimum() - y0 ) / ( y1 - y0 );
293 else if ( outcodeOut & RIGHT )
296 y = y0 + ( y1 - y0 ) * ( mRect.
xMaximum() - x0 ) / ( x1 - x0 );
299 else if ( outcodeOut & LEFT )
302 y = y0 + ( y1 - y0 ) * ( mRect.
xMinimum() - x0 ) / ( x1 - x0 );
310 if ( outcodeOut == outcode0 )
314 outcode0 = computeOutCode( x0, y0 );
320 outcode1 = computeOutCode( x1, y1 );
335 QByteArray wkb( geom->
asWkb() );
346 bool hasZValue =
false;
367 double prevx = 0.0, prevy = 0.0;
368 for (
int index = 0; index < nPoints; ++index )
370 double thisx = 0.0, thisy = 0.0;
371 wkbPtr >> thisx >> thisy;
373 wkbPtr +=
sizeof( double );
380 edgePoints[0].
set( prevx, prevy );
381 edgePoints[1].
set( thisx, thisy );
400 for (
int linenr = 0, pointIndex = 0; linenr < nLines; ++linenr )
406 double prevx = 0.0, prevy = 0.0;
407 for (
int pointnr = 0; pointnr < nPoints; ++pointnr )
409 double thisx = 0.0, thisy = 0.0;
410 wkbPtr >> thisx >> thisy;
412 wkbPtr +=
sizeof( double );
419 edgePoints[0].
set( prevx, prevy );
420 edgePoints[1].
set( thisx, thisy );
442 for (
int ringnr = 0, pointIndex = 0; ringnr < nRings; ++ringnr )
447 double prevx = 0.0, prevy = 0.0;
448 for (
int pointnr = 0; pointnr < nPoints; ++pointnr )
450 double thisx = 0.0, thisy = 0.0;
451 wkbPtr >> thisx >> thisy;
453 wkbPtr +=
sizeof( double );
460 edgePoints[0].
set( prevx, prevy );
461 edgePoints[1].
set( thisx, thisy );
482 for (
int polynr = 0, pointIndex = 0; polynr < nPolygons; ++polynr )
487 for (
int ringnr = 0; ringnr < nRings; ++ringnr )
492 double prevx = 0.0, prevy = 0.0;
493 for (
int pointnr = 0; pointnr < nPoints; ++pointnr )
495 double thisx = 0.0, thisy = 0.0;
496 wkbPtr >> thisx >> thisy;
498 wkbPtr +=
sizeof( double );
505 edgePoints[0].
set( prevx, prevy );
506 edgePoints[1].
set( thisx, thisy );
539 , mSrcRect( srcRect )
543 void visitNode(
const INode &n )
override { Q_UNUSED( n ); }
544 void visitData( std::vector<const IData *> &v )
override { Q_UNUSED( v ); }
551 Q_FOREACH (
const QgsPointLocator::Match &m, _geometrySegmentsInRect( geom, mSrcRect, mLocator->mLayer,
id ) )
554 if ( mFilter && !mFilter->acceptMatch( m ) )
583 , mSrcRect( srcRect )
587 void visitNode(
const INode &n )
override { Q_UNUSED( n ); }
588 void visitData( std::vector<const IData *> &v )
override { Q_UNUSED( v ); }
593 const QgsGeometry *geom = mLocator->mGeoms.value(
id );
597 if ( mSrcRect.contains( *it ) )
602 if ( mFilter && !mFilter->acceptMatch( m ) )
633 void getNextEntry(
const IEntry &entry, id_type &nextEntry,
bool &hasNext )
override 635 const INode *n =
dynamic_cast<const INode *
>( &entry );
639 QgsDebugMsgLevel( QStringLiteral(
"NODE: %1" ).arg( n->getIdentifier() ), 4 );
640 if ( n->getLevel() > 0 )
643 for ( uint32_t cChild = 0; cChild < n->getChildrenCount(); cChild++ )
645 QgsDebugMsgLevel( QStringLiteral(
"- CH: %1" ).arg( n->getChildIdentifier( cChild ) ), 4 );
646 ids.push( n->getChildIdentifier( cChild ) );
652 for ( uint32_t cChild = 0; cChild < n->getChildrenCount(); cChild++ )
654 QgsDebugMsgLevel( QStringLiteral(
"- L: %1" ).arg( n->getChildIdentifier( cChild ) ), 4 );
660 nextEntry = ids.back();
682 mStorage.reset( StorageManager::createNewMemoryStorageManager() );
704 mExtent.reset( extent ?
new QgsRectangle( *extent ) :
nullptr );
714 mContext.reset(
nullptr );
718 mContext = std::unique_ptr<QgsRenderContext>(
new QgsRenderContext( *context ) );
732 return mRTree || mIsEmptyLayer;
740 QLinkedList<RTree::Data *> dataList;
762 QgsDebugMsg( QStringLiteral(
"could not transform bounding box to map, skipping the snap filter (%1)" ).arg( e.
what() ) );
769 std::unique_ptr< QgsFeatureRenderer > renderer( mLayer->
renderer() ? mLayer->
renderer()->
clone() : nullptr );
774 ctx = mContext.get();
778 renderer->startRender( *ctx, mLayer->
fields() );
785 int indexedCount = 0;
792 if ( filter && ctx && renderer )
794 ctx->expressionContext().setFeature( f );
795 if ( !renderer->willRenderFeature( f, *ctx ) )
806 transformedGeometry.
transform( mTransform );
813 QgsDebugMsg( QStringLiteral(
"could not transform geometry to map, skipping the snap for it (%1)" ).arg( e.
what() ) );
819 dataList <<
new RTree::Data( 0,
nullptr, r, f.
id() );
821 if ( mGeoms.contains( f.
id() ) )
822 delete mGeoms.take( f.
id() );
826 if ( maxFeaturesToIndex != -1 && indexedCount > maxFeaturesToIndex )
828 qDeleteAll( dataList );
835 double fillFactor = 0.7;
836 unsigned long indexCapacity = 10;
837 unsigned long leafCapacity = 10;
838 unsigned long dimension = 2;
839 RTree::RTreeVariant variant = RTree::RV_RSTAR;
840 SpatialIndex::id_type indexId;
842 if ( dataList.isEmpty() )
844 mIsEmptyLayer =
true;
849 mRTree.reset( RTree::createAndBulkLoadNewRTree( RTree::BLM_STR, stream, *mStorage, fillFactor, indexCapacity,
850 leafCapacity, dimension, variant, indexId ) );
852 if ( ctx && renderer )
854 renderer->stopRender( *ctx );
864 mIsEmptyLayer =
false;
866 qDeleteAll( mGeoms );
871 void QgsPointLocator::onFeatureAdded(
QgsFeatureId fid )
888 std::unique_ptr< QgsFeatureRenderer > renderer( mLayer->
renderer() ? mLayer->
renderer()->
clone() : nullptr );
892 ctx = mContext.get();
893 if ( renderer && ctx )
896 renderer->startRender( *ctx, mLayer->
fields() );
898 ctx->expressionContext().setFeature( f );
899 if ( !renderer->willRenderFeature( f, *ctx ) )
904 renderer->stopRender( *ctx );
922 QgsDebugMsg( QStringLiteral(
"could not transform geometry to map, skipping the snap for it (%1)" ).arg( e.
what() ) );
930 SpatialIndex::Region r( rect2region( bbox ) );
931 mRTree->insertData( 0,
nullptr, r, f.
id() );
933 if ( mGeoms.contains( f.
id() ) )
934 delete mGeoms.take( f.
id() );
940 void QgsPointLocator::onFeatureDeleted(
QgsFeatureId fid )
945 if ( mGeoms.contains( fid ) )
947 mRTree->deleteData( rect2region( mGeoms[fid]->boundingBox() ), fid );
948 delete mGeoms.take( fid );
956 onFeatureDeleted( fid );
957 onFeatureAdded( fid );
960 void QgsPointLocator::onAttributeValueChanged(
QgsFeatureId fid,
int idx,
const QVariant &value )
966 onFeatureDeleted( fid );
967 onFeatureAdded( fid );
983 QgsRectangle rect( point.
x() - tolerance, point.
y() - tolerance, point.
x() + tolerance, point.
y() + tolerance );
984 mRTree->intersectsWithQuery( rect2region( rect ), visitor );
1005 QgsRectangle rect( point.
x() - tolerance, point.
y() - tolerance, point.
x() + tolerance, point.
y() + tolerance );
1006 mRTree->intersectsWithQuery( rect2region( rect ), visitor );
1022 if ( mlist.count() && mlist.at( 0 ).isValid() )
1024 return mlist.at( 0 );
1027 if ( tolerance == 0 )
1061 mRTree->intersectsWithQuery( rect2region( rect ), visitor );
1068 QgsRectangle rect( point.
x() - tolerance, point.
y() - tolerance, point.
x() + tolerance, point.
y() + tolerance );
1083 mRTree->intersectsWithQuery( rect2region( rect ), visitor );
1090 QgsRectangle rect( point.
x() - tolerance, point.
y() - tolerance, point.
x() + tolerance, point.
y() + tolerance );
1110 mRTree->intersectsWithQuery( point2point( point ), visitor );
The class defines interface for querying point location:
Wrapper for iterator of features from vector data provider or vector layer.
double closestSegmentWithContext(const QgsPointXY &point, QgsPointXY &minDistPoint, int &afterVertex, int *leftOf=nullptr, double epsilon=DEFAULT_SEGMENT_EPSILON) const
Searches for the closest segment of geometry to the given point.
void visitData(std::vector< const IData *> &v) override
void set(double x, double y)
Sets the x and y value of the point.
A rectangle specified with double values.
OperationResult transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection direction=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
QgsVectorLayer * layer() const
The vector layer where the snap occurred.
void visitData(const IData &d) override
bool hasIndex() const
Indicate whether the data have been already indexed.
Features may be filtered, i.e. some features may not be rendered (categorized, rule based ...
QgsWkbTypes::Type wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
QgsPointLocator_VisitorArea(QgsPointLocator *pl, const QgsPointXY &origPt, QgsPointLocator::MatchList &list)
constructor
A class to represent a 2D point.
Match nearestEdge(const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter=nullptr)
Find nearest edge to the specified point - up to distance specified by tolerance Optional filter may ...
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsCoordinateReferenceSystem destinationCrs() const
Gets destination CRS - may be an invalid QgsCoordinateReferenceSystem if not doing OTF reprojection...
QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
QgsPointLocator_VisitorVerticesInRect(QgsPointLocator *pl, QgsPointLocator::MatchList &lst, const QgsRectangle &srcRect, QgsPointLocator::MatchFilter *filter=nullptr)
Constructs the visitor.
class QList< QgsPointLocator::Match > MatchList
Helper class used when traversing the index looking for edges - builds a list of matches.
A geometry is the spatial representation of a feature.
Match nearestArea(const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter=nullptr)
Find nearest area to the specified point - up to distance specified by tolerance Optional filter may ...
bool rebuildIndex(int maxFeaturesToIndex=-1)
void visitNode(const INode &n) override
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Interface that allows rejection of some matches in intersection queries (e.g.
bool hasGeometry() const
Returns true if the feature has an associated geometry.
void visitData(std::vector< const IData *> &v) override
void featureDeleted(QgsFeatureId fid)
Emitted when a feature has been deleted.
void styleChanged()
Signal emitted whenever a change affects the layer's style.
QgsPointLocator_Stream(const QLinkedList< RTree::Data *> &dataList)
QgsPointXY closestVertex(const QgsPointXY &point, int &atVertex, int &beforeVertex, int &afterVertex, double &sqrDist) const
Returns the vertex closest to the given point, the corresponding vertex index, squared distance snap ...
bool intersects(const QgsRectangle &rectangle) const
Returns true if this geometry exactly intersects with a rectangle.
~QgsPointLocator() override
Type
The WKB type describes the number of dimensions a geometry has.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
#define QgsDebugMsgLevel(str, level)
QgsPointLocator_VisitorNearestVertex(QgsPointLocator *pl, QgsPointLocator::Match &m, const QgsPointXY &srcPoint, QgsPointLocator::MatchFilter *filter=nullptr)
OutCode computeOutCode(double x, double y)
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
void setRenderContext(const QgsRenderContext *context)
Configure render context - if not null, it will use to index only visible feature.
Snapped to a vertex. Can be a vertex of the geometry or an intersection.
Helper class to dump the R-index nodes and their content.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
bool isSegmentInRect(double x0, double y0, double x1, double y1)
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
void geometryChanged(QgsFeatureId fid, const QgsGeometry &geometry)
Is emitted whenever a geometry change is done in the edit buffer.
void visitNode(const INode &n) override
void setExtent(const QgsRectangle *extent)
Configure extent - if not null, it will index only that area.
Helper class used when traversing the index with areas - builds a list of matches.
QgsFeatureRenderer * renderer()
Returns renderer.
void attributeValueChanged(QgsFeatureId fid, int idx, const QVariant &value)
Is emitted whenever an attribute value change is done in the edit buffer.
void featureAdded(QgsFeatureId fid)
Emitted when a new feature has been added to the layer.
Contains information about the context in which a coordinate transform is executed.
The vertex_iterator class provides STL-style iterator for vertices.
void visitData(const IData &d) override
Helper class used when traversing the index looking for vertices - builds a list of matches...
const QgsRectangle * extent() const
Gets extent of the area point locator covers - if null then it caches the whole layer.
void visitData(std::vector< const IData *> &v) override
void visitNode(const INode &n) override
QByteArray asWkb() const
Export the geometry to WKB.
IData * getNext() override
void visitData(std::vector< const IData *> &v) override
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double xMaximum() const
Returns the x maximum value (right side of rectangle).
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
QgsPointLocator(QgsVectorLayer *layer, const QgsCoordinateReferenceSystem &destinationCrs=QgsCoordinateReferenceSystem(), const QgsCoordinateTransformContext &transformContext=QgsCoordinateTransformContext(), const QgsRectangle *extent=nullptr)
Construct point locator for a layer.
QgsPointXY point() const
for vertex / edge match coords depending on what class returns it (geom.cache: layer coords...
Contains information about the context of a rendering operation.
QgsPoint vertexAt(int atVertex) const
Returns coordinates of a vertex.
MatchList verticesInRect(const QgsRectangle &rect, QgsPointLocator::MatchFilter *filter=nullptr)
Find vertices within a specified recangle Optional filter may discard unwanted matches.
void visitData(std::vector< const IData *> &v) override
QgsPointLocator_VisitorNearestEdge(QgsPointLocator *pl, QgsPointLocator::Match &m, const QgsPointXY &srcPoint, QgsPointLocator::MatchFilter *filter=nullptr)
Helper class for bulk loading of R-trees.
int vertexNrFromVertexId(QgsVertexId id) const
Returns the vertex number corresponding to a vertex id.
void visitData(const IData &d) override
MatchList pointInPolygon(const QgsPointXY &point)
find out if the point is in any polygons
void visitNode(const INode &n) override
bool init(int maxFeaturesToIndex=-1)
Prepare the index for queries.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
This class represents a coordinate reference system (CRS).
_CohenSutherland(const QgsRectangle &rect)
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
void getNextEntry(const IEntry &entry, id_type &nextEntry, bool &hasNext) override
Match nearestVertex(const QgsPointXY &point, double tolerance, QgsPointLocator::MatchFilter *filter=nullptr)
Find nearest vertex to the specified point - up to distance specified by tolerance Optional filter ma...
void visitData(const IData &d) override
double xMinimum() const
Returns the x minimum value (left side of rectangle).
void dataChanged()
Data of layer changed.
Helper class used when traversing the index looking for vertices - builds a list of matches...
double distance() const
for vertex / edge match units depending on what class returns it (geom.cache: layer units...
double yMaximum() const
Returns the y maximum value (top side of rectangle).
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Query the layer for features specified in request.
Helper class used when traversing the index looking for edges - builds a list of matches.
void visitNode(const INode &n) override
MatchList edgesInRect(const QgsRectangle &rect, QgsPointLocator::MatchFilter *filter=nullptr)
Find edges within a specified recangle Optional filter may discard unwanted matches.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
QgsFeatureId featureId() const
The id of the feature to which the snapped geometry belongs.
bool nextFeature(QgsFeature &f)
Represents a vector layer which manages a vector based data sets.
QgsAbstractGeometry::vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry...
QgsWkbTypes::Type readHeader() const
readHeader
Defines a QGIS exception class.
QgsAbstractGeometry::vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
void visitData(const IData &d) override
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
QgsPointLocator_VisitorEdgesInRect(QgsPointLocator *pl, QgsPointLocator::MatchList &lst, const QgsRectangle &srcRect, QgsPointLocator::MatchFilter *filter=nullptr)
QgsCoordinateReferenceSystem crs
bool isValid() const
Returns whether this CRS is correctly initialized and usable.