32#include <QtAlgorithms> 
   34#include <spatialindex/SpatialIndex.h> 
   50  double mLength = std::numeric_limits<double>::max();
 
   58    const QString &directDirectionValue,
 
   59    const QString &reverseDirectionValue,
 
   60    const QString &bothDirectionValue,
 
   63  , mDirectionFieldId( directionFieldId )
 
   64  , mDirectDirectionValue( directDirectionValue )
 
   65  , mReverseDirectionValue( reverseDirectionValue )
 
   66  , mBothDirectionValue( bothDirectionValue )
 
   67  , mDefaultDirection( defaultDirection )
 
   73  return QStringLiteral( 
"Vector line" );
 
   80  if ( mDirectionFieldId != -1 )
 
   81    attrs.insert( mDirectionFieldId );
 
   85    attrs.unite( strategy->requiredAttributes() );
 
   87  return qgis::setToList( attrs );
 
   92  if ( mDirectionFieldId < 0 )
 
   93    return mDefaultDirection;
 
   95  QString 
str = feature.
attribute( mDirectionFieldId ).toString();
 
   96  if ( 
str == mBothDirectionValue )
 
   98    return Direction::DirectionBoth;
 
  100  else if ( 
str == mDirectDirectionValue )
 
  102    return Direction::DirectionForward;
 
  104  else if ( 
str == mReverseDirectionValue )
 
  106    return Direction::DirectionBackward;
 
  110    return mDefaultDirection;
 
  115class QgsNetworkVisitor : 
public SpatialIndex::IVisitor
 
  118    explicit QgsNetworkVisitor( QVector< int > &pointIndexes )
 
  119      : mPoints( pointIndexes ) {}
 
  121    void visitNode( 
const INode &n )
 override 
  124    void visitData( 
const IData &d )
 override 
  126      mPoints.append( d.getIdentifier() );
 
  129    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,
 
  150      leafCapacity, dimension, variant, indexId ) );
 
  156  QVector< int > matching;
 
  157  QgsNetworkVisitor visitor( matching );
 
  159  double pt1[2] = { point.
x() - tolerance, point.
y() - tolerance },
 
  160                  pt2[2] = { point.
x() + tolerance, point.
y() + tolerance };
 
  161  SpatialIndex::Region searchRegion( pt1, pt2, 2 );
 
  163  index->intersectsWithQuery( searchRegion, visitor );
 
  165  return matching.empty() ? -1 : matching.at( 0 );
 
  169                                        QVector< QgsPointXY > &snappedPoints, 
QgsFeedback *feedback )
 const 
  182  snappedPoints = QVector< QgsPointXY >( additionalPoints.size(), 
QgsPointXY( 0.0, 0.0 ) );
 
  184  QVector< TiePointInfo > additionalTiePoints( additionalPoints.size() );
 
  187  QVector< QgsPointXY > graphVertices;
 
  190  std::unique_ptr< SpatialIndex::IStorageManager > iStorage( StorageManager::createNewMemoryStorageManager() );
 
  194  auto findPointWithinTolerance = [&iRTree, tolerance]( 
const QgsPointXY & point )->
int 
  198  auto addPointToIndex = [&iRTree]( 
const QgsPointXY & point, 
int index )
 
  200    double coords[] = {point.
x(), point.
y()};
 
  201    iRTree->insertData( 0, 
nullptr, SpatialIndex::Point( coords, 2 ), index );
 
  221      bool isFirstPoint = 
true;
 
  226        int pt2Idx = findPointWithinTolerance( pt2 ) ;
 
  230          addPointToIndex( pt2, graphVertices.count() );
 
  231          graphVertices.push_back( pt2 );
 
  236          pt2 = graphVertices.at( pt2Idx );
 
  243          for ( 
const QgsPointXY &additionalPoint : additionalPoints )
 
  247            double thisSegmentClosestDist = std::numeric_limits<double>::max();
 
  250              thisSegmentClosestDist = additionalPoint.sqrDist( pt1 );
 
  256                                       pt2.
x(), pt2.
y(), snappedPoint, 0 );
 
  259            if ( thisSegmentClosestDist < additionalTiePoints[ i ].mLength )
 
  263              info.
mLength = thisSegmentClosestDist;
 
  266              additionalTiePoints[ i ] = info;
 
  273        isFirstPoint = 
false;
 
  277      feedback->
setProgress( 100.0 * 
static_cast< double >( ++step ) / featureCount );
 
  281  QHash< QgsFeatureId, QList< int > > tiePointNetworkFeatures;
 
  285    tiePointNetworkFeatures[ info.mNetworkFeatureId ] << i;
 
  290  for ( 
int i = 0; i < snappedPoints.size(); ++i )
 
  293    const QgsPointXY point = snappedPoints.at( i );
 
  294    int ptIdx = findPointWithinTolerance( point );
 
  298      addPointToIndex( point, graphVertices.count() );
 
  299      graphVertices.push_back( point );
 
  304      snappedPoints[ i ] = graphVertices.at( ptIdx );
 
  308  for ( 
int i = 0; i < additionalTiePoints.count(); ++i )
 
  310    additionalTiePoints[ i ].mTiedPoint = snappedPoints.at( additionalTiePoints.at( i ).additionalPointId );
 
  319    for ( 
const QgsPointXY &point : graphVertices )
 
  332    Direction direction = directionForFeature( feature );
 
  345      bool isFirstPoint = 
true;
 
  349        int pPt2idx = findPointWithinTolerance( pt2 );
 
  350        Q_ASSERT_X( pPt2idx >= 0, 
"QgsVectorLayerDirectory::makeGraph", 
"encountered a vertex which was not present in graph" );
 
  351        pt2 = graphVertices.at( pPt2idx );
 
  355          QMap< double, QgsPointXY > pointsOnArc;
 
  356          pointsOnArc[ 0.0 ] = pt1;
 
  357          pointsOnArc[ pt1.
sqrDist( pt2 )] = pt2;
 
  359          const QList< int > tiePointsForCurrentFeature = tiePointNetworkFeatures.value( feature.
id() );
 
  360          for ( 
int tiePointIdx : tiePointsForCurrentFeature )
 
  362            const TiePointInfo &t = additionalTiePoints.at( tiePointIdx );
 
  373          bool isFirstPoint = 
true;
 
  374          for ( 
auto arcPointIt = pointsOnArc.constBegin(); arcPointIt != pointsOnArc.constEnd(); ++arcPointIt )
 
  376            arcPt2 = arcPointIt.value();
 
  378            pt2idx = findPointWithinTolerance( arcPt2 );
 
  379            Q_ASSERT_X( pt2idx >= 0, 
"QgsVectorLayerDirectory::makeGraph", 
"encountered a vertex which was not present in graph" );
 
  380            arcPt2 = graphVertices.at( pt2idx );
 
  382            if ( !isFirstPoint && arcPt1 != arcPt2 )
 
  385              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 );
 
@ MultiLineString
MultiLineString.
 
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)
 
This class wraps a request for features to a vector layer (or directly its vector data provider).
 
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...
 
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 SIP_HOLDGIL
Tells whether the operation has been canceled already.
 
void setProgress(double progress)
Sets the current progress for the feedback object.
 
Qgis::WkbType wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
 
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.
 
Determine 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
 
QgsNetworkStrategy defines strategy used for calculation of the edge cost.
 
A class to represent a 2D point.
 
double sqrDist(double x, double y) const SIP_HOLDGIL
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=DEFAULT_SEGMENT_EPSILON) const SIP_HOLDGIL
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...
 
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) SIP_HOLDGIL
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.
 
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