22#include "moc_qgsvectorlayerdirector.cpp" 
   33#include <QtAlgorithms> 
   35#include <spatialindex/SpatialIndex.h> 
   51    double mLength = std::numeric_limits<double>::max();
 
 
   59  , mDirectionFieldId( directionFieldId )
 
   60  , mDirectDirectionValue( directDirectionValue )
 
   61  , mReverseDirectionValue( reverseDirectionValue )
 
   62  , mBothDirectionValue( bothDirectionValue )
 
   63  , mDefaultDirection( defaultDirection )
 
 
   69  return QStringLiteral( 
"Vector line" );
 
 
   76  if ( mDirectionFieldId != -1 )
 
   77    attrs.insert( mDirectionFieldId );
 
   81    attrs.unite( strategy->requiredAttributes() );
 
   83  return qgis::setToList( attrs );
 
   88  if ( mDirectionFieldId < 0 )
 
   89    return mDefaultDirection;
 
   91  QString str = feature.
attribute( mDirectionFieldId ).toString();
 
   92  if ( str == mBothDirectionValue )
 
   96  else if ( str == mDirectDirectionValue )
 
  100  else if ( str == mReverseDirectionValue )
 
  106    return mDefaultDirection;
 
  111class QgsNetworkVisitor : 
public SpatialIndex::IVisitor
 
  114    explicit QgsNetworkVisitor( QVector<int> &pointIndexes )
 
  115      : mPoints( pointIndexes ) {}
 
  117    void visitNode( 
const INode &n )
 override 
  122    void visitData( 
const IData &d )
 override 
  124      mPoints.append( d.getIdentifier() );
 
  127    void visitData( std::vector<const IData *> &v )
 override 
  133    QVector<int> &mPoints;
 
  141  double fillFactor = 0.7;
 
  142  unsigned long indexCapacity = 10;
 
  143  unsigned long leafCapacity = 10;
 
  144  unsigned long dimension = 2;
 
  145  RTree::RTreeVariant variant = RTree::RV_RSTAR;
 
  148  SpatialIndex::id_type indexId;
 
  149  std::unique_ptr<SpatialIndex::ISpatialIndex> iRTree( RTree::createNewRTree( storageManager, fillFactor, indexCapacity, leafCapacity, dimension, variant, indexId ) );
 
 
  155  QVector<int> matching;
 
  156  QgsNetworkVisitor visitor( matching );
 
  158  double pt1[2] = { point.
x() - tolerance, point.
y() - tolerance },
 
  159         pt2[2] = { point.
x() + tolerance, point.
y() + tolerance };
 
  160  SpatialIndex::Region searchRegion( pt1, pt2, 2 );
 
  162  index->intersectsWithQuery( searchRegion, visitor );
 
  164  return matching.empty() ? -1 : matching.at( 0 );
 
 
  180  snappedPoints = QVector<QgsPointXY>( additionalPoints.size(), 
QgsPointXY( 0.0, 0.0 ) );
 
  182  QVector<TiePointInfo> additionalTiePoints( additionalPoints.size() );
 
  185  QVector<QgsPointXY> graphVertices;
 
  188  std::unique_ptr<SpatialIndex::IStorageManager> iStorage( StorageManager::createNewMemoryStorageManager() );
 
  192  auto findPointWithinTolerance = [&iRTree, tolerance]( 
const QgsPointXY &point ) -> 
int {
 
  195  auto addPointToIndex = [&iRTree]( 
const QgsPointXY &point, 
int index ) {
 
  196    double coords[] = { point.
x(), point.
y() };
 
  197    iRTree->insertData( 0, 
nullptr, SpatialIndex::Point( coords, 2 ), index );
 
  217      bool isFirstPoint = 
true;
 
  222        int pt2Idx = findPointWithinTolerance( pt2 );
 
  226          addPointToIndex( pt2, graphVertices.count() );
 
  227          graphVertices.push_back( pt2 );
 
  232          pt2 = graphVertices.at( pt2Idx );
 
  239          for ( 
const QgsPointXY &additionalPoint : additionalPoints )
 
  242            double thisSegmentClosestDist = std::numeric_limits<double>::max();
 
  245              thisSegmentClosestDist = additionalPoint.sqrDist( pt1 );
 
  250              thisSegmentClosestDist = additionalPoint.
sqrDistToSegment( pt1.
x(), pt1.
y(), pt2.
x(), pt2.
y(), snappedPoint, 0 );
 
  253            if ( thisSegmentClosestDist < additionalTiePoints[i].mLength )
 
  257              info.
mLength = thisSegmentClosestDist;
 
  260              additionalTiePoints[i] = info;
 
  267        isFirstPoint = 
false;
 
  271      feedback->
setProgress( 100.0 * 
static_cast<double>( ++step ) / featureCount );
 
  275  QHash<QgsFeatureId, QList<int>> tiePointNetworkFeatures;
 
  279    tiePointNetworkFeatures[info.mNetworkFeatureId] << i;
 
  284  for ( 
int i = 0; i < snappedPoints.size(); ++i )
 
  287    const QgsPointXY point = snappedPoints.at( i );
 
  288    int ptIdx = findPointWithinTolerance( point );
 
  292      addPointToIndex( point, graphVertices.count() );
 
  293      graphVertices.push_back( point );
 
  298      snappedPoints[i] = graphVertices.at( ptIdx );
 
  302  for ( 
int i = 0; i < additionalTiePoints.count(); ++i )
 
  304    additionalTiePoints[i].mTiedPoint = snappedPoints.at( additionalTiePoints.at( i ).additionalPointId );
 
  313    for ( 
const QgsPointXY &point : graphVertices )
 
  326    Direction direction = directionForFeature( feature );
 
  339      bool isFirstPoint = 
true;
 
  343        int pPt2idx = findPointWithinTolerance( pt2 );
 
  344        Q_ASSERT_X( pPt2idx >= 0, 
"QgsVectorLayerDirectory::makeGraph", 
"encountered a vertex which was not present in graph" );
 
  345        pt2 = graphVertices.at( pPt2idx );
 
  349          QMap<double, QgsPointXY> pointsOnArc;
 
  350          pointsOnArc[0.0] = pt1;
 
  351          pointsOnArc[pt1.
sqrDist( pt2 )] = pt2;
 
  353          const QList<int> tiePointsForCurrentFeature = tiePointNetworkFeatures.value( feature.
id() );
 
  354          for ( 
int tiePointIdx : tiePointsForCurrentFeature )
 
  356            const TiePointInfo &t = additionalTiePoints.at( tiePointIdx );
 
  367          bool isFirstPoint = 
true;
 
  368          for ( 
auto arcPointIt = pointsOnArc.constBegin(); arcPointIt != pointsOnArc.constEnd(); ++arcPointIt )
 
  370            arcPt2 = arcPointIt.value();
 
  372            pt2idx = findPointWithinTolerance( arcPt2 );
 
  373            Q_ASSERT_X( pt2idx >= 0, 
"QgsVectorLayerDirectory::makeGraph", 
"encountered a vertex which was not present in graph" );
 
  374            arcPt2 = graphVertices.at( pt2idx );
 
  376            if ( !isFirstPoint && arcPt1 != arcPt2 )
 
  386                QgsDebugError( QStringLiteral( 
"An error occurred while calculating length" ) );
 
  389              QVector<QVariant> prop;
 
  393                prop.push_back( strategy->cost( distance, feature ) );
 
  398                builder->
addEdge( pt1idx, arcPt1, pt2idx, arcPt2, prop );
 
  402                builder->
addEdge( pt2idx, arcPt2, pt1idx, arcPt1, prop );
 
  407            isFirstPoint = 
false;
 
  411        isFirstPoint = 
false;
 
  416      feedback->
setProgress( 100.0 * 
static_cast<double>( ++step ) / featureCount );
 
 
@ MultiLineString
MultiLineString.
 
Custom exception class for Coordinate Reference System related exceptions.
 
double measureLine(const QVector< QgsPointXY > &points) const
Measures the length of a line with multiple segments.
 
Wrapper for iterator of features from vector data provider or vector layer.
 
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
 
Wraps a request for features to a vector layer (or directly its vector data provider).
 
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
 
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
 
An interface for objects which provide features via a getFeatures method.
 
virtual QgsCoordinateReferenceSystem sourceCrs() const =0
Returns the coordinate reference system for features in the source.
 
virtual QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const =0
Returns an iterator for the features in the source.
 
virtual long long featureCount() const =0
Returns the number of features contained in the source, or -1 if the feature count is unknown.
 
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
 
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
 
Base class for feedback objects to be used for cancellation of something running in a worker thread.
 
bool isCanceled() const
Tells whether the operation has been canceled already.
 
void setProgress(double progress)
Sets the current progress for the feedback object.
 
QgsPolylineXY asPolyline() const
Returns the contents of the geometry as a polyline.
 
QgsMultiPolylineXY asMultiPolyline() const
Returns the contents of the geometry as a multi-linestring.
 
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
 
Interface for creating a graph.
 
virtual void addVertex(int id, const QgsPointXY &pt)
Add vertex to the graph.
 
QgsCoordinateReferenceSystem destinationCrs() const
Returns destinaltion CRS.
 
QgsDistanceArea * distanceArea()
Returns measurement tool.
 
virtual void addEdge(int pt1id, const QgsPointXY &pt1, int pt2id, const QgsPointXY &pt2, const QVector< QVariant > &strategies)
Add edge to the graph.
 
double topologyTolerance() const
Returns topology tolerance.
 
bool coordinateTransformationEnabled() const
Returns coordinate transformation enabled.
 
QList< QgsNetworkStrategy * > mStrategies
 
Defines strategy used for calculation of the edge cost in networks.
 
double sqrDist(double x, double y) const
Returns the squared distance between this point a specified x, y coordinate.
 
double sqrDistToSegment(double x1, double y1, double x2, double y2, QgsPointXY &minDistPoint, double epsilon=Qgis::DEFAULT_SEGMENT_EPSILON) const
Returns the minimum distance between this point and a segment.
 
QString name() const override
Returns director name.
 
void makeGraph(QgsGraphBuilderInterface *builder, const QVector< QgsPointXY > &additionalPoints, QVector< QgsPointXY > &snappedPoints, QgsFeedback *feedback=nullptr) const override
Make a graph using QgsGraphBuilder.
 
Direction
Edge direction Edge can be one-way with direct flow (one can move only from the start point to the en...
 
@ DirectionForward
One-way direct.
 
@ DirectionBackward
One-way reversed.
 
QgsVectorLayerDirector(QgsFeatureSource *source, int directionFieldId, const QString &directDirectionValue, const QString &reverseDirectionValue, const QString &bothDirectionValue, Direction defaultDirection)
Default constructor.
 
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
 
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
 
QList< int > QgsAttributeList
 
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
 
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
 
#define QgsDebugError(str)
 
std::unique_ptr< SpatialIndex::ISpatialIndex > createVertexSpatialIndex(SpatialIndex::IStorageManager &storageManager)
 
int findClosestVertex(const QgsPointXY &point, SpatialIndex::ISpatialIndex *index, double tolerance)
 
TiePointInfo(int additionalPointId, QgsFeatureId featureId, const QgsPointXY &start, const QgsPointXY &end)
 
QgsFeatureId mNetworkFeatureId