33 #include <QtAlgorithms>    35 #include "SpatialIndex.h"    43     : additionalPointId( additionalPointId )
    44     , mNetworkFeatureId( featureId )
    45     , mFirstPoint( start )
    49   int additionalPointId = -1;
    51   double mLength = DBL_MAX;
    59     const QString &directDirectionValue,
    60     const QString &reverseDirectionValue,
    61     const QString &bothDirectionValue,
    64   , mDirectionFieldId( directionFieldId )
    65   , mDirectDirectionValue( directDirectionValue )
    66   , mReverseDirectionValue( reverseDirectionValue )
    67   , mBothDirectionValue( bothDirectionValue )
    68   , mDefaultDirection( defaultDirection )
    74   return QStringLiteral( 
"Vector line" );
    81   if ( mDirectionFieldId != -1 )
    82     attrs.insert( mDirectionFieldId );
    86     attrs.unite( strategy->requiredAttributes() );
    88   return attrs.toList();
    93   if ( mDirectionFieldId < 0 )
    94     return mDefaultDirection;
    96   QString str = feature.
attribute( mDirectionFieldId ).toString();
    97   if ( str == mBothDirectionValue )
    99     return Direction::DirectionBoth;
   101   else if ( str == mDirectDirectionValue )
   103     return Direction::DirectionForward;
   105   else if ( str == mReverseDirectionValue )
   107     return Direction::DirectionBackward;
   111     return mDefaultDirection;
   116 class QgsNetworkVisitor : 
public SpatialIndex::IVisitor
   119     explicit QgsNetworkVisitor( QVector< int > &pointIndexes )
   120       : mPoints( pointIndexes ) {}
   122     void visitNode( 
const INode &n )
 override   125     void visitData( 
const IData &d )
 override   127       mPoints.append( d.getIdentifier() );
   130     void visitData( std::vector<const IData *> &v )
 override   134     QVector< int > &mPoints;
   142   double fillFactor = 0.7;
   143   unsigned long indexCapacity = 10;
   144   unsigned long leafCapacity = 10;
   145   unsigned long dimension = 2;
   146   RTree::RTreeVariant variant = RTree::RV_RSTAR;
   149   SpatialIndex::id_type indexId;
   150   std::unique_ptr< SpatialIndex::ISpatialIndex > iRTree( RTree::createNewRTree( storageManager, fillFactor, indexCapacity,
   151       leafCapacity, dimension, variant, indexId ) );
   157   QVector< int > matching;
   158   QgsNetworkVisitor visitor( matching );
   160   double pt1[2] = { point.
x() - tolerance, point.
y() - tolerance },
   161                   pt2[2] = { point.
x() + tolerance, point.
y() + tolerance };
   162   SpatialIndex::Region searchRegion( pt1, pt2, 2 );
   164   index->intersectsWithQuery( searchRegion, visitor );
   166   return matching.empty() ? -1 : matching.at( 0 );
   170                                         QVector< QgsPointXY > &snappedPoints, 
QgsFeedback *feedback )
 const   172   long featureCount = mSource->featureCount() * 2;
   183   snappedPoints = QVector< QgsPointXY >( additionalPoints.size(), 
QgsPointXY( 0.0, 0.0 ) );
   185   QVector< TiePointInfo > additionalTiePoints( additionalPoints.size() );
   188   QVector< QgsPointXY > graphVertices;
   191   std::unique_ptr< SpatialIndex::IStorageManager > iStorage( StorageManager::createNewMemoryStorageManager() );
   195   auto findPointWithinTolerance = [&iRTree, tolerance]( 
const QgsPointXY & point )->
int   199   auto addPointToIndex = [&iRTree]( 
const QgsPointXY & point, 
int index )
   201     double coords[] = {point.
x(), point.
y()};
   202     iRTree->insertData( 0, 
nullptr, SpatialIndex::Point( coords, 2 ), index );
   222       bool isFirstPoint = 
true;
   227         int pt2Idx = findPointWithinTolerance( pt2 ) ;
   231           addPointToIndex( pt2, graphVertices.count() );
   232           graphVertices.push_back( pt2 );
   237           pt2 = graphVertices.at( pt2Idx );
   244           for ( 
const QgsPointXY &additionalPoint : additionalPoints )
   248             double thisSegmentClosestDist = DBL_MAX;
   251               thisSegmentClosestDist = additionalPoint.
sqrDist( pt1 );
   257                                        pt2.
x(), pt2.
y(), snappedPoint );
   260             if ( thisSegmentClosestDist < additionalTiePoints[ i ].mLength )
   264               info.
mLength = thisSegmentClosestDist;
   265               info.mTiedPoint = snappedPoint;
   267               additionalTiePoints[ i ] = info;
   268               snappedPoints[ i ] = info.mTiedPoint;
   274         isFirstPoint = 
false;
   278       feedback->
setProgress( 100.0 * static_cast< double >( ++step ) / featureCount );
   282   QHash< QgsFeatureId, QList< int > > tiePointNetworkFeatures;
   286     tiePointNetworkFeatures[ info.mNetworkFeatureId ] << i;
   291   for ( 
int i = 0; i < snappedPoints.size(); ++i )
   294     const QgsPointXY point = snappedPoints.at( i );
   295     int ptIdx = findPointWithinTolerance( point );
   299       addPointToIndex( point, graphVertices.count() );
   300       graphVertices.push_back( point );
   305       snappedPoints[ i ] = graphVertices.at( ptIdx );
   309   for ( 
int i = 0; i < additionalTiePoints.count(); ++i )
   311     additionalTiePoints[ i ].mTiedPoint = snappedPoints.at( additionalTiePoints.at( i ).additionalPointId );
   320     for ( 
const QgsPointXY &point : graphVertices )
   327   fit = mSource->getFeatures( 
QgsFeatureRequest().setSubsetOfAttributes( requiredAttributes() ) );
   333     Direction direction = directionForFeature( feature );
   346       bool isFirstPoint = 
true;
   350         int pPt2idx = findPointWithinTolerance( pt2 );
   351         Q_ASSERT_X( pPt2idx >= 0, 
"QgsVectorLayerDirectory::makeGraph", 
"encountered a vertex which was not present in graph" );
   352         pt2 = graphVertices.at( pPt2idx );
   356           QMap< double, QgsPointXY > pointsOnArc;
   357           pointsOnArc[ 0.0 ] = pt1;
   358           pointsOnArc[ pt1.
sqrDist( pt2 )] = pt2;
   360           const QList< int > tiePointsForCurrentFeature = tiePointNetworkFeatures.value( feature.
id() );
   361           for ( 
int tiePointIdx : tiePointsForCurrentFeature )
   363             const TiePointInfo &t = additionalTiePoints.at( tiePointIdx );
   374           bool isFirstPoint = 
true;
   375           for ( 
auto arcPointIt = pointsOnArc.constBegin(); arcPointIt != pointsOnArc.constEnd(); ++arcPointIt )
   377             arcPt2 = arcPointIt.value();
   379             pt2idx = findPointWithinTolerance( arcPt2 );
   380             Q_ASSERT_X( pt2idx >= 0, 
"QgsVectorLayerDirectory::makeGraph", 
"encountered a vertex which was not present in graph" );
   381             arcPt2 = graphVertices.at( pt2idx );
   383             if ( !isFirstPoint && arcPt1 != arcPt2 )
   386               QVector< QVariant > prop;
   389                 prop.push_back( strategy->cost( distance, feature ) );
   392               if ( direction == Direction::DirectionForward ||
   393                    direction == Direction::DirectionBoth )
   395                 builder->
addEdge( pt1idx, arcPt1, pt2idx, arcPt2, prop );
   397               if ( direction == Direction::DirectionBackward ||
   398                    direction == Direction::DirectionBoth )
   400                 builder->
addEdge( pt2idx, arcPt2, pt1idx, arcPt1, prop );
   405             isFirstPoint = 
false;
   409         isFirstPoint = 
false;
   414       feedback->
setProgress( 100.0 * static_cast< double >( ++step ) / featureCount );
 
Wrapper for iterator of features from vector data provider or vector layer. 
 
QgsNetworkStrategy defines strategy used for calculation of the edge cost. For example it can take in...
 
Direction
Edge direction Edge can be one-way with direct flow (one can move only from the start point to the en...
 
int findClosestVertex(const QgsPointXY &point, SpatialIndex::ISpatialIndex *index, double tolerance)
 
void makeGraph(QgsGraphBuilderInterface *builder, const QVector< QgsPointXY > &additionalPoints, QVector< QgsPointXY > &snappedPoints, QgsFeedback *feedback=nullptr) const override
Make a graph using QgsGraphBuilder. 
 
QgsWkbTypes::Type wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.) 
 
bool coordinateTransformationEnabled()
Returns coordinate transformation enabled. 
 
A class to represent a 2D point. 
 
void setProgress(double progress)
Sets the current progress for the feedback object. 
 
Determine interface for creating a graph. 
 
TiePointInfo(int additionalPointId, QgsFeatureId featureId, const QgsPointXY &start, const QgsPointXY &end)
 
virtual void addEdge(int pt1id, const QgsPointXY &pt1, int pt2id, const QgsPointXY &pt2, const QVector< QVariant > &strategies)
Add edge to the graph. 
 
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
 
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes. 
 
double sqrDist(double x, double y) const
Returns the squared distance between this point a specified x, y coordinate. 
 
QgsMultiPolylineXY asMultiPolyline() const
Returns contents of the geometry as a multi linestring if wkbType is WKBMultiLineString, otherwise an empty list. 
 
Base class for feedback objects to be used for cancelation of something running in a worker thread...
 
double sqrDistToSegment(double x1, double y1, double x2, double y2, QgsPointXY &minDistPoint, double epsilon=DEFAULT_SEGMENT_EPSILON) const
Returns the minimum distance between this point and a segment. 
 
This class wraps a request for features to a vector layer (or directly its vector data provider)...
 
QgsVectorLayerDirector(QgsFeatureSource *source, int directionFieldId, const QString &directDirectionValue, const QString &reverseDirectionValue, const QString &bothDirectionValue, const Direction defaultDirection)
Default constructor. 
 
QgsGeometry geometry() const
Returns the geometry associated with this feature. 
 
std::unique_ptr< SpatialIndex::ISpatialIndex > createVertexSpatialIndex(SpatialIndex::IStorageManager &storageManager)
 
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points. 
 
bool isCanceled() const
Tells whether the operation has been canceled already. 
 
An interface for objects which provide features via a getFeatures method. 
 
virtual void addVertex(int id, const QgsPointXY &pt)
Add vertex to the graph. 
 
QList< QgsNetworkStrategy * > mStrategies
 
double topologyTolerance()
Returns topology tolerance. 
 
QgsPolylineXY asPolyline() const
Returns contents of the geometry as a polyline if wkbType is WKBLineString, otherwise an empty list...
 
QList< int > QgsAttributeList
 
bool nextFeature(QgsFeature &f)
 
QgsCoordinateReferenceSystem destinationCrs() const
Returns destinaltion CRS. 
 
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name. 
 
static Type flatType(Type type)
Returns the flat type for a WKB type. 
 
QgsDistanceArea * distanceArea()
Returns measurement tool. 
 
double measureLine(const QVector< QgsPointXY > &points) const
Measures the length of a line with multiple segments. 
 
QString name() const override
Returns director name.