26QString QgsShortestPathLayerToPointAlgorithm::name()
const
28 return QStringLiteral(
"shortestpathlayertopoint" );
31QString QgsShortestPathLayerToPointAlgorithm::displayName()
const
33 return QObject::tr(
"Shortest path (layer to point)" );
36QStringList QgsShortestPathLayerToPointAlgorithm::tags()
const
38 return QObject::tr(
"network,path,shortest,fastest" ).split(
',' );
41QString QgsShortestPathLayerToPointAlgorithm::shortHelpString()
const
43 return QObject::tr(
"This algorithm computes optimal (shortest or fastest) routes "
44 "from multiple start points defined by a vector layer and a given end point." );
47QString QgsShortestPathLayerToPointAlgorithm::shortDescription()
const
49 return QObject::tr(
"Computes optimal (shortest or fastest) routes "
50 "from multiple start points defined by a vector layer and a given end point." );
53QgsShortestPathLayerToPointAlgorithm *QgsShortestPathLayerToPointAlgorithm::createInstance()
const
55 return new QgsShortestPathLayerToPointAlgorithm();
58void QgsShortestPathLayerToPointAlgorithm::initAlgorithm(
const QVariantMap & )
64 std::unique_ptr<QgsProcessingParameterNumber> maxEndPointDistanceFromNetwork = std::make_unique<QgsProcessingParameterDistance>( QStringLiteral(
"POINT_TOLERANCE" ), QObject::tr(
"Maximum point distance from network" ), QVariant(), QStringLiteral(
"INPUT" ),
true, 0 );
66 maxEndPointDistanceFromNetwork->setHelp( QObject::tr(
"Specifies an optional limit on the distance from the start and end points to the network layer. If the start feature is further from the network than this distance it will be treated as non-routable. If the end point is further from the network than this distance an error will be raised." ) );
67 addParameter( maxEndPointDistanceFromNetwork.release() );
71 auto outputNonRoutable = std::make_unique<QgsProcessingParameterFeatureSink>( QStringLiteral(
"OUTPUT_NON_ROUTABLE" ), QObject::tr(
"Non-routable features" ),
Qgis::ProcessingSourceType::VectorPoint, QVariant(),
true );
72 outputNonRoutable->setHelp( QObject::tr(
"An optional output which will be used to store any input features which could not be routed (e.g. those which are too far from the network layer)." ) );
73 outputNonRoutable->setCreateByDefault(
false );
74 addParameter( outputNonRoutable.release() );
79 loadCommonParams( parameters, context, feedback );
81 const QgsPointXY endPoint = parameterAsPoint( parameters, QStringLiteral(
"END_POINT" ), context, mNetwork->sourceCrs() );
83 std::unique_ptr<QgsFeatureSource> startPoints( parameterAsSource( parameters, QStringLiteral(
"START_POINTS" ), context ) );
88 newFields.
append(
QgsField( QStringLiteral(
"start" ), QMetaType::Type::QString ) );
89 newFields.
append(
QgsField( QStringLiteral(
"end" ), QMetaType::Type::QString ) );
90 newFields.
append(
QgsField( QStringLiteral(
"cost" ), QMetaType::Type::Double ) );
94 std::unique_ptr<QgsFeatureSink> sink( parameterAsSink( parameters, QStringLiteral(
"OUTPUT" ), context, dest, fields,
Qgis::WkbType::LineString, mNetwork->sourceCrs() ) );
98 QString nonRoutableSinkId;
99 std::unique_ptr<QgsFeatureSink> nonRoutableSink( parameterAsSink( parameters, QStringLiteral(
"OUTPUT_NON_ROUTABLE" ), context, nonRoutableSinkId, startPoints->fields(),
Qgis::WkbType::Point, mNetwork->sourceCrs() ) );
101 const double pointDistanceThreshold = parameters.value( QStringLiteral(
"POINT_TOLERANCE" ) ).isValid() ? parameterAsDouble( parameters, QStringLiteral(
"POINT_TOLERANCE" ), context ) : -1;
103 QVector<QgsPointXY> points;
104 points.push_front( endPoint );
105 QHash<int, QgsAttributes> sourceAttributes;
106 loadPoints( startPoints.get(), points, sourceAttributes, context, feedback );
108 feedback->
pushInfo( QObject::tr(
"Building graph…" ) );
109 QVector<QgsPointXY> snappedPoints;
110 mDirector->makeGraph( mBuilder.get(), points, snappedPoints, feedback );
112 const QgsPointXY snappedEndPoint = snappedPoints[0];
114 if ( pointDistanceThreshold >= 0 )
116 double distanceEndPointToNetwork = 0;
119 distanceEndPointToNetwork = mBuilder->distanceArea()->measureLine( endPoint, snappedEndPoint );
126 if ( distanceEndPointToNetwork > pointDistanceThreshold )
128 throw QgsProcessingException( QObject::tr(
"End point is too far from the network layer (%1, maximum permitted is %2)" ).arg( distanceEndPointToNetwork ).arg( pointDistanceThreshold ) );
132 feedback->
pushInfo( QObject::tr(
"Calculating shortest paths…" ) );
133 std::unique_ptr<QgsGraph> graph( mBuilder->takeGraph() );
134 const int idxEnd = graph->findVertex( snappedEndPoint );
139 QVector<double> costs;
141 QVector<QgsPointXY> route;
148 const double step = points.size() > 0 ? 100.0 / points.size() : 1;
149 for (
int i = 1; i < points.size(); i++ )
156 const QgsPointXY snappedPoint = snappedPoints.at( i );
157 const QgsPointXY originalPoint = points.at( i );
159 if ( pointDistanceThreshold >= 0 )
161 double distancePointToNetwork = 0;
164 distancePointToNetwork = mBuilder->distanceArea()->measureLine( originalPoint, snappedPoint );
171 if ( distancePointToNetwork > pointDistanceThreshold )
173 feedback->
pushWarning( QObject::tr(
"Point is too far from the network layer (%1, maximum permitted is %2)" ).arg( distancePointToNetwork ).arg( pointDistanceThreshold ) );
174 if ( nonRoutableSink )
177 attributes = sourceAttributes.value( i );
180 throw QgsProcessingException( writeFeatureError( nonRoutableSink.get(), parameters, QStringLiteral(
"OUTPUT_NON_ROUTABLE" ) ) );
188 idxStart = graph->findVertex( snappedPoint );
191 if ( tree.at( idxEnd ) == -1 )
193 feedback->
reportError( QObject::tr(
"There is no route from start point (%1) to end point (%2)." )
196 attributes = sourceAttributes.value( i );
197 attributes.append( originalPoint.
toString() );
205 route.push_front( graph->vertex( idxEnd ).point() );
206 cost = costs.at( idxEnd );
208 while ( currentIdx != idxStart )
210 currentIdx = graph->edge( tree.at( currentIdx ) ).fromVertex();
211 route.push_front( graph->vertex( currentIdx ).point() );
217 attributes = sourceAttributes.value( i );
218 attributes.append( originalPoint.
toString() );
219 attributes.append( endPoint.
toString() );
220 attributes.append( cost / mMultiplier );
233 outputs.insert( QStringLiteral(
"OUTPUT" ), dest );
234 if ( nonRoutableSink )
236 nonRoutableSink->finalize();
237 outputs.insert( QStringLiteral(
"OUTPUT_NON_ROUTABLE" ), nonRoutableSinkId );
@ VectorPoint
Vector point layers.
@ VectorLine
Vector line layers.
@ Advanced
Parameter is an advanced parameter which should be hidden from users by default.
Custom exception class for Coordinate Reference System related exceptions.
@ FastInsert
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
void setFields(const QgsFields &fields, bool initAttributes=false)
Assigns a field map with the feature to allow attribute access by attribute name.
void clearGeometry()
Removes any geometry associated with the feature.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
bool isCanceled() const
Tells whether the operation has been canceled already.
void setProgress(double progress)
Sets the current progress for the feedback object.
Encapsulate a field in an attribute table or data source.
Container of fields for a vector layer.
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
A geometry is the spatial representation of a feature.
static QgsGeometry fromPolylineXY(const QgsPolylineXY &polyline)
Creates a new LineString geometry from a list of QgsPointXY points.
static QgsGeometry fromPointXY(const QgsPointXY &point)
Creates a new geometry from a QgsPointXY object.
static void dijkstra(const QgsGraph *source, int startVertexIdx, int criterionNum, QVector< int > *resultTree=nullptr, QVector< double > *resultCost=nullptr)
Solve shortest path problem using Dijkstra algorithm.
QString toString(int precision=-1) const
Returns a string representation of the point (x, y) with a preset precision.
Contains information about the context in which a processing algorithm is executed.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
virtual void pushInfo(const QString &info)
Pushes a general informational message from the algorithm.
virtual void pushWarning(const QString &warning)
Pushes a warning informational message from the algorithm.
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
A feature sink output for processing algorithms.
An input feature source (such as vector layers) parameter for processing algorithms.
A point parameter for processing algorithms.
static QgsFields combineFields(const QgsFields &fieldsA, const QgsFields &fieldsB, const QString &fieldsBPrefix=QString())
Combines two field lists, avoiding duplicate field names (in a case-insensitive manner).