33 #include <QtAlgorithms> 
   35 #include <spatialindex/SpatialIndex.h> 
   43     : additionalPointId( additionalPointId )
 
   44     , mNetworkFeatureId( featureId )
 
   45     , mFirstPoint( start )
 
   49   int additionalPointId = -1;
 
   51   double mLength = std::numeric_limits<double>::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 qgis::setToList( attrs );
 
   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 
  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 = std::numeric_limits<double>::max();
 
  251               thisSegmentClosestDist = additionalPoint.sqrDist( pt1 );
 
  257                                        pt2.
x(), pt2.
y(), snappedPoint, 0 );
 
  260             if ( thisSegmentClosestDist < additionalTiePoints[ i ].mLength )
 
  264               info.
mLength = thisSegmentClosestDist;
 
  267               additionalTiePoints[ i ] = info;
 
  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 )
 
  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;
 
  390                 prop.push_back( strategy->cost( distance, feature ) );
 
  393               if ( direction == Direction::DirectionForward ||
 
  394                    direction == Direction::DirectionBoth )
 
  396                 builder->
addEdge( pt1idx, arcPt1, pt2idx, arcPt2, prop );
 
  398               if ( direction == Direction::DirectionBackward ||
 
  399                    direction == Direction::DirectionBoth )
 
  401                 builder->
addEdge( pt2idx, arcPt2, pt1idx, arcPt1, prop );
 
  406             isFirstPoint = 
false;
 
  410         isFirstPoint = 
false;
 
  415       feedback->
setProgress( 100.0 * 
static_cast< double >( ++step ) / featureCount );
 
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.
QgsWkbTypes::Type 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.
bool coordinateTransformationEnabled()
Returns coordinate transformation enabled.
QgsCoordinateReferenceSystem destinationCrs() const
Returns destinaltion CRS.
virtual void addEdge(int pt1id, const QgsPointXY &pt1, int pt2id, const QgsPointXY &pt2, const QVector< QVariant > &strategies)
Add edge to the graph.
double topologyTolerance()
Returns topology tolerance.
QgsDistanceArea * distanceArea()
Returns measurement tool.
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 Type flatType(Type 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)