25QString QgsServiceAreaFromLayerAlgorithm::name()
const
27 return QStringLiteral(
"serviceareafromlayer" );
30QString QgsServiceAreaFromLayerAlgorithm::displayName()
const
32 return QObject::tr(
"Service area (from layer)" );
35QStringList QgsServiceAreaFromLayerAlgorithm::tags()
const
37 return QObject::tr(
"network,service,area,shortest,fastest" ).split(
',' );
40QString QgsServiceAreaFromLayerAlgorithm::shortHelpString()
const
42 return QObject::tr(
"This algorithm creates a new vector with all the edges or parts of "
43 "edges of a network line layer that can be reached within a distance "
44 "or a time, starting from features of a point layer. The distance and "
45 "the time (both referred to as \"travel cost\") must be specified "
46 "respectively in the network layer units or in hours." );
49QgsServiceAreaFromLayerAlgorithm *QgsServiceAreaFromLayerAlgorithm::createInstance()
const
51 return new QgsServiceAreaFromLayerAlgorithm();
54void QgsServiceAreaFromLayerAlgorithm::initAlgorithm(
const QVariantMap & )
59 std::unique_ptr< QgsProcessingParameterNumber > travelCost = std::make_unique< QgsProcessingParameterNumber >( QStringLiteral(
"TRAVEL_COST" ), QObject::tr(
"Travel cost (distance for 'Shortest', time for 'Fastest')" ),
QgsProcessingParameterNumber::Double, 0,
true, 0 );
61 addParameter( travelCost.release() );
63 addParameter(
new QgsProcessingParameterNumber( QStringLiteral(
"TRAVEL_COST2" ), QObject::tr(
"Travel cost (distance for 'Shortest', time for 'Fastest')" ),
66 std::unique_ptr< QgsProcessingParameterBoolean > includeBounds = std::make_unique< QgsProcessingParameterBoolean >( QStringLiteral(
"INCLUDE_BOUNDS" ), QObject::tr(
"Include upper/lower bound points" ),
false,
true );
68 addParameter( includeBounds.release() );
70 std::unique_ptr< QgsProcessingParameterFeatureSink > outputLines = std::make_unique< QgsProcessingParameterFeatureSink >( QStringLiteral(
"OUTPUT_LINES" ), QObject::tr(
"Service area (lines)" ),
72 outputLines->setCreateByDefault(
true );
73 addParameter( outputLines.release() );
75 std::unique_ptr< QgsProcessingParameterFeatureSink > outputPoints = std::make_unique< QgsProcessingParameterFeatureSink >( QStringLiteral(
"OUTPUT" ), QObject::tr(
"Service area (boundary nodes)" ),
77 outputPoints->setCreateByDefault(
false );
78 addParameter( outputPoints.release() );
83 loadCommonParams( parameters, context, feedback );
85 std::unique_ptr< QgsFeatureSource > startPoints( parameterAsSource( parameters, QStringLiteral(
"START_POINTS" ), context ) );
90 const bool useOldTravelCost = parameters.value( QStringLiteral(
"TRAVEL_COST" ) ).isValid();
91 double travelCost = parameterAsDouble( parameters, useOldTravelCost ? QStringLiteral(
"TRAVEL_COST" ) : QStringLiteral(
"TRAVEL_COST2" ), context );
93 int strategy = parameterAsInt( parameters, QStringLiteral(
"STRATEGY" ), context );
94 if ( strategy && !useOldTravelCost )
95 travelCost *= mMultiplier;
97 bool includeBounds =
true;
98 if ( parameters.contains( QStringLiteral(
"INCLUDE_BOUNDS" ) ) )
100 includeBounds = parameterAsBool( parameters, QStringLiteral(
"INCLUDE_BOUNDS" ), context );
103 QVector< QgsPointXY > points;
104 QHash< int, QgsAttributes > sourceAttributes;
105 loadPoints( startPoints.get(), points, sourceAttributes, context, feedback );
107 feedback->
pushInfo( QObject::tr(
"Building graph…" ) );
108 QVector< QgsPointXY > snappedPoints;
109 mDirector->makeGraph( mBuilder.get(), points, snappedPoints, feedback );
111 feedback->
pushInfo( QObject::tr(
"Calculating service areas…" ) );
112 std::unique_ptr< QgsGraph > graph( mBuilder->takeGraph() );
114 QgsFields fields = startPoints->fields();
115 fields.
append(
QgsField( QStringLiteral(
"type" ), QVariant::String ) );
116 fields.
append(
QgsField( QStringLiteral(
"start" ), QVariant::String ) );
118 QString pointsSinkId;
119 std::unique_ptr< QgsFeatureSink > pointsSink( parameterAsSink( parameters, QStringLiteral(
"OUTPUT" ), context, pointsSinkId, fields,
123 std::unique_ptr< QgsFeatureSink > linesSink( parameterAsSink( parameters, QStringLiteral(
"OUTPUT_LINES" ), context, linesSinkId, fields,
129 QVector< double > costs;
131 int inboundEdgeIndex;
132 double startVertexCost, endVertexCost;
139 const double step = snappedPoints.size() > 0 ? 100.0 / snappedPoints.size() : 1;
140 for (
int i = 0; i < snappedPoints.size(); i++ )
147 idxStart = graph->findVertex( snappedPoints.at( i ) );
148 origPoint = points.at( i ).toString();
154 QSet< int > vertices;
156 for (
int j = 0; j < costs.size(); j++ )
158 inboundEdgeIndex = tree.at( j );
160 if ( inboundEdgeIndex == -1 && j != idxStart )
166 startVertexCost = costs.at( j );
167 if ( startVertexCost > travelCost )
173 vertices.insert( j );
174 startPoint = graph->vertex( j ).point();
177 const QList< int > outgoingEdges = graph->vertex( j ).outgoingEdges() ;
178 for (
int edgeId : outgoingEdges )
180 edge = graph->edge( edgeId );
181 endVertexCost = startVertexCost + edge.
cost( 0 ).toDouble();
182 endPoint = graph->vertex( edge.
toVertex() ).point();
183 if ( endVertexCost <= travelCost )
187 lines.push_back(
QgsPolylineXY() << startPoint << endPoint );
193 endPoint.
x(), endPoint.
y(), endVertexCost, travelCost );
195 areaPoints.push_back( interpolatedEndPoint );
196 lines.push_back(
QgsPolylineXY() << startPoint << interpolatedEndPoint );
202 QList< int > verticesList = qgis::setToList( vertices );
203 areaPoints.reserve( verticesList.size() );
204 std::sort( verticesList.begin(), verticesList.end() );
205 for (
int v : verticesList )
207 areaPoints.push_back( graph->vertex( v ).point() );
214 attributes = sourceAttributes.value( i + 1 );
215 attributes << QStringLiteral(
"within" ) << origPoint;
218 throw QgsProcessingException( writeFeatureError( pointsSink.get(), parameters, QStringLiteral(
"OUTPUT" ) ) );
223 QVector< int > nodes;
224 nodes.reserve( costs.size() );
227 for (
int v = 0; v < costs.size(); v++ )
229 if ( costs.at( v ) > travelCost && tree.at( v ) != -1 )
231 vertexId = graph->edge( tree.at( v ) ).fromVertex();
232 if ( costs.at( vertexId ) <= travelCost )
234 nodes.push_back( v );
239 upperBoundary.reserve( nodes.size() );
240 lowerBoundary.reserve( nodes.size() );
241 for (
int n : std::as_const( nodes ) )
243 upperBoundary.push_back( graph->vertex( graph->edge( tree.at( n ) ).toVertex() ).point() );
244 lowerBoundary.push_back( graph->vertex( graph->edge( tree.at( n ) ).fromVertex() ).point() );
251 attributes = sourceAttributes.value( i + 1 );
252 attributes << QStringLiteral(
"upper" ) << origPoint;
255 throw QgsProcessingException( writeFeatureError( pointsSink.get(), parameters, QStringLiteral(
"OUTPUT" ) ) );
258 attributes = sourceAttributes.value( i + 1 );
259 attributes << QStringLiteral(
"lower" ) << origPoint;
262 throw QgsProcessingException( writeFeatureError( pointsSink.get(), parameters, QStringLiteral(
"OUTPUT" ) ) );
270 attributes = sourceAttributes.value( i + 1 );
271 attributes << QStringLiteral(
"lines" ) << origPoint;
274 throw QgsProcessingException( writeFeatureError( linesSink.get(), parameters, QStringLiteral(
"OUTPUT_LINES" ) ) );
283 outputs.insert( QStringLiteral(
"OUTPUT" ), pointsSinkId );
287 outputs.insert( QStringLiteral(
"OUTPUT_LINES" ), linesSinkId );
@ MultiLineString
MultiLineString.
@ 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 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, FieldOrigin origin=OriginProvider, int originIndex=-1)
Appends a field. The field must have unique name, otherwise it is rejected (returns false)
static QgsPointXY interpolatePointOnLineByValue(double x1, double y1, double v1, double x2, double y2, double v2, double value)
Interpolates the position of a point along the line from (x1, y1) to (x2, y2).
A geometry is the spatial representation of a feature.
static QgsGeometry fromMultiPolylineXY(const QgsMultiPolylineXY &multiline)
Creates a new geometry from a QgsMultiPolylineXY object.
static QgsGeometry fromMultiPointXY(const QgsMultiPointXY &multipoint)
Creates a new geometry from a QgsMultiPointXY 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.
This class implements a graph edge.
int toVertex() const
Returns the index of the vertex at the end of this edge.
QVariant cost(int strategyIndex) const
Returns edge cost calculated using specified strategy.
A class to represent a 2D point.
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.
@ FlagAdvanced
Parameter is an advanced parameter which should be hidden from users by default.
@ FlagHidden
Parameter is hidden and should not be shown to users.
An input feature source (such as vector layers) parameter for processing algorithms.
A numeric parameter for processing algorithms.
@ Double
Double/float values.
@ TypeVectorLine
Vector line layers.
@ TypeVectorPoint
Vector point layers.
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
QVector< QgsPointXY > QgsMultiPointXY
A collection of QgsPoints that share a common collection of attributes.
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.