25 QString QgsServiceAreaFromPointAlgorithm::name()
const
27 return QStringLiteral(
"serviceareafrompoint" );
30 QString QgsServiceAreaFromPointAlgorithm::displayName()
const
32 return QObject::tr(
"Service area (from point)" );
35 QStringList QgsServiceAreaFromPointAlgorithm::tags()
const
37 return QObject::tr(
"network,service,area,shortest,fastest" ).split(
',' );
40 QString QgsServiceAreaFromPointAlgorithm::shortHelpString()
const
42 return QObject::tr(
"This algorithm creates a new vector with all the edges or parts of edges "
43 "of a network line layer that can be reached within a distance or a time, "
44 "starting from a point feature. The distance and the time (both referred to "
45 "as \"travel cost\") must be specified respectively in the network layer "
46 "units or in hours." );
49 QgsServiceAreaFromPointAlgorithm *QgsServiceAreaFromPointAlgorithm::createInstance()
const
51 return new QgsServiceAreaFromPointAlgorithm();
54 void QgsServiceAreaFromPointAlgorithm::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 const QgsPointXY startPoint = parameterAsPoint( parameters, QStringLiteral(
"START_POINT" ), context, mNetwork->sourceCrs() );
88 const bool useOldTravelCost = parameters.value( QStringLiteral(
"TRAVEL_COST" ) ).isValid();
89 double travelCost = parameterAsDouble( parameters, useOldTravelCost ? QStringLiteral(
"TRAVEL_COST" ) : QStringLiteral(
"TRAVEL_COST2" ), context );
91 const int strategy = parameterAsInt( parameters, QStringLiteral(
"STRATEGY" ), context );
92 if ( strategy && !useOldTravelCost )
93 travelCost *= mMultiplier;
95 bool includeBounds =
true;
96 if ( parameters.contains( QStringLiteral(
"INCLUDE_BOUNDS" ) ) )
98 includeBounds = parameterAsBool( parameters, QStringLiteral(
"INCLUDE_BOUNDS" ), context );
101 feedback->
pushInfo( QObject::tr(
"Building graph…" ) );
102 QVector< QgsPointXY > snappedPoints;
103 mDirector->makeGraph( mBuilder.get(), QVector< QgsPointXY >() << startPoint, snappedPoints, feedback );
105 feedback->
pushInfo( QObject::tr(
"Calculating service area…" ) );
106 std::unique_ptr< QgsGraph> graph( mBuilder->takeGraph() );
107 const int idxStart = graph->findVertex( snappedPoints[0] );
110 QVector< double > costs;
115 QSet< int > vertices;
117 int inboundEdgeIndex;
118 double startVertexCost, endVertexCost;
122 for (
int i = 0; i < costs.size(); i++ )
124 inboundEdgeIndex = tree.at( i );
125 if ( inboundEdgeIndex == -1 && i != idxStart )
131 startVertexCost = costs.at( i );
132 if ( startVertexCost > travelCost )
138 vertices.insert( i );
139 edgeStart = graph->vertex( i ).point();
142 const QList< int > outgoingEdges = graph->vertex( i ).outgoingEdges() ;
143 for (
const int edgeId : outgoingEdges )
145 edge = graph->edge( edgeId );
146 endVertexCost = startVertexCost + edge.
cost( 0 ).toDouble();
147 edgeEnd = graph->vertex( edge.
toVertex() ).point();
148 if ( endVertexCost <= travelCost )
158 edgeEnd.
x(), edgeEnd.
y(), endVertexCost, travelCost );
160 points.push_back( interpolatedEndPoint );
161 lines.push_back(
QgsPolylineXY() << edgeStart << interpolatedEndPoint );
167 QList< int > verticesList = qgis::setToList( vertices );
168 points.reserve( verticesList.size() );
169 std::sort( verticesList.begin(), verticesList.end() );
170 for (
const int v : verticesList )
172 points.push_back( graph->vertex( v ).point() );
175 feedback->
pushInfo( QObject::tr(
"Writing results…" ) );
180 fields.
append(
QgsField( QStringLiteral(
"type" ), QVariant::String ) );
181 fields.
append(
QgsField( QStringLiteral(
"start" ), QVariant::String ) );
186 QString pointsSinkId;
187 std::unique_ptr< QgsFeatureSink > pointsSink( parameterAsSink( parameters, QStringLiteral(
"OUTPUT" ), context, pointsSinkId, fields,
192 outputs.insert( QStringLiteral(
"OUTPUT" ), pointsSinkId );
198 throw QgsProcessingException( writeFeatureError( pointsSink.get(), parameters, QStringLiteral(
"OUTPUT" ) ) );
203 QVector< int > nodes;
206 for (
int i = 0; i < costs.size(); i++ )
208 if ( costs.at( i ) > travelCost && tree.at( i ) != -1 )
210 vertexId = graph->edge( tree.at( i ) ).fromVertex();
211 if ( costs.at( vertexId ) <= travelCost )
213 nodes.push_back( i );
218 upperBoundary.reserve( nodes.size() );
219 lowerBoundary.reserve( nodes.size() );
220 for (
const int i : nodes )
222 upperBoundary.push_back( graph->vertex( graph->edge( tree.at( i ) ).toVertex() ).point() );
223 lowerBoundary.push_back( graph->vertex( graph->edge( tree.at( i ) ).fromVertex() ).point() );
232 throw QgsProcessingException( writeFeatureError( pointsSink.get(), parameters, QStringLiteral(
"OUTPUT" ) ) );
237 throw QgsProcessingException( writeFeatureError( pointsSink.get(), parameters, QStringLiteral(
"OUTPUT" ) ) );
242 std::unique_ptr< QgsFeatureSink > linesSink( parameterAsSink( parameters, QStringLiteral(
"OUTPUT_LINES" ), context, linesSinkId, fields,
247 outputs.insert( QStringLiteral(
"OUTPUT_LINES" ), linesSinkId );
252 throw QgsProcessingException( writeFeatureError( linesSink.get(), parameters, QStringLiteral(
"OUTPUT_LINES" ) ) );