Skip to content

Commit 8d32bf7

Browse files
committed
Fix QgsGraphAnalyzer::dijkstra traverses through edges backwards
This means that it flips the direction of the graph edge, breaking route restrictions. Refs #17325
1 parent 57edec6 commit 8d32bf7

File tree

7 files changed

+286
-86
lines changed

7 files changed

+286
-86
lines changed

python/plugins/processing/algs/qgis/ShortestPathLayerToPoint.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ def processAlgorithm(self, parameters, context, feedback):
250250

251251
idxStart = graph.findVertex(snappedPoints[i])
252252

253-
tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
253+
tree, costs = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
254254

255255
if tree[idxEnd] == -1:
256256
msg = self.tr('There is no route from start point ({}) to end point ({}).'.format(points[i].toString(), endPoint.toString()))
@@ -266,9 +266,9 @@ def processAlgorithm(self, parameters, context, feedback):
266266
cost = 0.0
267267
current = idxEnd
268268
while current != idxStart:
269-
cost += graph.edge(tree[current]).cost(0)
270-
route.append(graph.vertex(graph.edge(tree[current]).fromVertex()).point())
271-
current = graph.edge(tree[current]).toVertex()
269+
cost += costs[current]
270+
current = graph.edge(tree[current]).fromVertex()
271+
route.append(graph.vertex(current).point())
272272

273273
route.append(snappedPoints[i])
274274
route.reverse()

python/plugins/processing/algs/qgis/ShortestPathPointToLayer.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,7 @@ def processAlgorithm(self, parameters, context, feedback):
241241
graph = builder.graph()
242242

243243
idxStart = graph.findVertex(snappedPoints[0])
244-
tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
245-
route = []
244+
tree, costs = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
246245

247246
nPoints = len(snappedPoints)
248247
total = 100.0 / nPoints if nPoints else 1
@@ -266,9 +265,9 @@ def processAlgorithm(self, parameters, context, feedback):
266265
cost = 0.0
267266
current = idxEnd
268267
while current != idxStart:
269-
cost += graph.edge(tree[current]).cost(0)
270-
route.append(graph.vertex(graph.edge(tree[current]).fromVertex()).point())
271-
current = graph.edge(tree[current]).toVertex()
268+
cost += costs[current]
269+
current = graph.edge(tree[current]).fromVertex()
270+
route.append(graph.vertex(current).point())
272271

273272
route.append(snappedPoints[0])
274273
route.reverse()

python/plugins/processing/algs/qgis/ShortestPathPointToPoint.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ def processAlgorithm(self, parameters, context, feedback):
217217
idxStart = graph.findVertex(snappedPoints[0])
218218
idxEnd = graph.findVertex(snappedPoints[1])
219219

220-
tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
220+
tree, costs = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
221221
if tree[idxEnd] == -1:
222222
raise QgsProcessingException(
223223
self.tr('There is no route from start point to end point.'))
@@ -226,9 +226,9 @@ def processAlgorithm(self, parameters, context, feedback):
226226
cost = 0.0
227227
current = idxEnd
228228
while current != idxStart:
229-
cost += graph.edge(tree[current]).cost(0)
230-
route.append(graph.vertex(graph.edge(tree[current]).fromVertex()).point())
231-
current = graph.edge(tree[current]).toVertex()
229+
cost += costs[current]
230+
current = graph.edge(tree[current]).fromVertex()
231+
route.append(graph.vertex(current).point())
232232

233233
route.append(snappedPoints[0])
234234
route.reverse()

src/analysis/network/qgsgraphanalyzer.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,21 +59,20 @@ void QgsGraphAnalyzer::dijkstra( const QgsGraph *source, int startPointIdx, int
5959
not_begin.erase( it );
6060

6161
// edge index list
62-
QgsGraphEdgeIds l = source->vertex( curVertex ).incomingEdges();
63-
QgsGraphEdgeIds::iterator arcIt;
64-
for ( arcIt = l.begin(); arcIt != l.end(); ++arcIt )
62+
const QgsGraphEdgeIds &outgoingEdges = source->vertex( curVertex ).outgoingEdges();
63+
for ( int edgeId : outgoingEdges )
6564
{
66-
const QgsGraphEdge arc = source->edge( *arcIt );
65+
const QgsGraphEdge &arc = source->edge( edgeId );
6766
double cost = arc.cost( criterionNum ).toDouble() + curCost;
6867

69-
if ( cost < ( *result )[ arc.fromVertex()] )
68+
if ( cost < ( *result )[ arc.toVertex()] )
7069
{
71-
( *result )[ arc.fromVertex()] = cost;
70+
( *result )[ arc.toVertex()] = cost;
7271
if ( resultTree )
7372
{
74-
( *resultTree )[ arc.fromVertex()] = *arcIt;
73+
( *resultTree )[ arc.toVertex()] = edgeId;
7574
}
76-
not_begin.insert( cost, arc.fromVertex() );
75+
not_begin.insert( cost, arc.toVertex() );
7776
}
7877
}
7978
}

src/analysis/network/qgsgraphbuilder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ void QgsGraphBuilder::addVertex( int, const QgsPointXY &pt )
4242

4343
void QgsGraphBuilder::addEdge( int pt1id, const QgsPointXY &, int pt2id, const QgsPointXY &, const QVector< QVariant > &prop )
4444
{
45-
mGraph->addEdge( pt2id, pt1id, prop );
45+
mGraph->addEdge( pt1id, pt2id, prop );
4646
}
4747

4848
QgsGraph *QgsGraphBuilder::graph()

src/analysis/network/qgsvectorlayerdirector.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,14 @@ using namespace SpatialIndex;
3939
struct TiePointInfo
4040
{
4141
TiePointInfo() = default;
42-
TiePointInfo( QgsFeatureId featureId, const QgsPointXY &start, const QgsPointXY &end )
43-
: mNetworkFeatureId( featureId )
42+
TiePointInfo( int additionalPointId, QgsFeatureId featureId, const QgsPointXY &start, const QgsPointXY &end )
43+
: additionalPointId( additionalPointId )
44+
, mNetworkFeatureId( featureId )
4445
, mFirstPoint( start )
4546
, mLastPoint( end )
4647
{}
4748

49+
int additionalPointId = -1;
4850
QgsPointXY mTiedPoint;
4951
double mLength = DBL_MAX;
5052
QgsFeatureId mNetworkFeatureId = -1;
@@ -255,7 +257,7 @@ void QgsVectorLayerDirector::makeGraph( QgsGraphBuilderInterface *builder, const
255257
if ( thisSegmentClosestDist < additionalTiePoints[ i ].mLength )
256258
{
257259
// found a closer segment for this additional point
258-
TiePointInfo info( feature.id(), pt1, pt2 );
260+
TiePointInfo info( i, feature.id(), pt1, pt2 );
259261
info.mLength = thisSegmentClosestDist;
260262
info.mTiedPoint = snappedPoint;
261263

@@ -300,8 +302,11 @@ void QgsVectorLayerDirector::makeGraph( QgsGraphBuilderInterface *builder, const
300302
snappedPoints[ i ] = graphVertices.at( ptIdx );
301303
}
302304
}
303-
304305
// also need to update tie points - they need to be matched for snapped points
306+
for ( int i = 0; i < additionalTiePoints.count(); ++i )
307+
{
308+
additionalTiePoints[ i ].mTiedPoint = snappedPoints.at( additionalTiePoints.at( i ).additionalPointId );
309+
}
305310

306311

307312
// begin graph construction
@@ -361,9 +366,9 @@ void QgsVectorLayerDirector::makeGraph( QgsGraphBuilderInterface *builder, const
361366
int pt1idx = -1;
362367
int pt2idx = -1;
363368
bool isFirstPoint = true;
364-
for ( const QgsPointXY &arcPoint : qgis::as_const( pointsOnArc ) )
369+
for ( auto arcPointIt = pointsOnArc.constBegin(); arcPointIt != pointsOnArc.constEnd(); ++arcPointIt )
365370
{
366-
pt2 = arcPoint;
371+
pt2 = arcPointIt.value();
367372

368373
pt2idx = findPointWithinTolerance( pt2 );
369374
Q_ASSERT_X( pt2idx >= 0, "QgsVectorLayerDirectory::makeGraph", "encountered a vertex which was not present in graph" );
@@ -372,10 +377,9 @@ void QgsVectorLayerDirector::makeGraph( QgsGraphBuilderInterface *builder, const
372377
{
373378
double distance = builder->distanceArea()->measureLine( pt1, pt2 );
374379
QVector< QVariant > prop;
375-
QList< QgsNetworkStrategy * >::const_iterator it;
376-
for ( it = mStrategies.begin(); it != mStrategies.end(); ++it )
380+
for ( QgsNetworkStrategy *strategy : mStrategies )
377381
{
378-
prop.push_back( ( *it )->cost( distance, feature ) );
382+
prop.push_back( strategy->cost( distance, feature ) );
379383
}
380384

381385
if ( direction == Direction::DirectionForward ||

0 commit comments

Comments
 (0)