mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
Fix QgsGraphAnalyzer::dijkstra traverses through edges backwards
This means that it flips the direction of the graph edge, breaking route restrictions. Refs #17325
This commit is contained in:
parent
57edec668e
commit
8d32bf729e
@ -250,7 +250,7 @@ class ShortestPathLayerToPoint(QgisAlgorithm):
|
||||
|
||||
idxStart = graph.findVertex(snappedPoints[i])
|
||||
|
||||
tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
|
||||
tree, costs = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
|
||||
|
||||
if tree[idxEnd] == -1:
|
||||
msg = self.tr('There is no route from start point ({}) to end point ({}).'.format(points[i].toString(), endPoint.toString()))
|
||||
@ -266,9 +266,9 @@ class ShortestPathLayerToPoint(QgisAlgorithm):
|
||||
cost = 0.0
|
||||
current = idxEnd
|
||||
while current != idxStart:
|
||||
cost += graph.edge(tree[current]).cost(0)
|
||||
route.append(graph.vertex(graph.edge(tree[current]).fromVertex()).point())
|
||||
current = graph.edge(tree[current]).toVertex()
|
||||
cost += costs[current]
|
||||
current = graph.edge(tree[current]).fromVertex()
|
||||
route.append(graph.vertex(current).point())
|
||||
|
||||
route.append(snappedPoints[i])
|
||||
route.reverse()
|
||||
|
@ -241,8 +241,7 @@ class ShortestPathPointToLayer(QgisAlgorithm):
|
||||
graph = builder.graph()
|
||||
|
||||
idxStart = graph.findVertex(snappedPoints[0])
|
||||
tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
|
||||
route = []
|
||||
tree, costs = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
|
||||
|
||||
nPoints = len(snappedPoints)
|
||||
total = 100.0 / nPoints if nPoints else 1
|
||||
@ -266,9 +265,9 @@ class ShortestPathPointToLayer(QgisAlgorithm):
|
||||
cost = 0.0
|
||||
current = idxEnd
|
||||
while current != idxStart:
|
||||
cost += graph.edge(tree[current]).cost(0)
|
||||
route.append(graph.vertex(graph.edge(tree[current]).fromVertex()).point())
|
||||
current = graph.edge(tree[current]).toVertex()
|
||||
cost += costs[current]
|
||||
current = graph.edge(tree[current]).fromVertex()
|
||||
route.append(graph.vertex(current).point())
|
||||
|
||||
route.append(snappedPoints[0])
|
||||
route.reverse()
|
||||
|
@ -217,7 +217,7 @@ class ShortestPathPointToPoint(QgisAlgorithm):
|
||||
idxStart = graph.findVertex(snappedPoints[0])
|
||||
idxEnd = graph.findVertex(snappedPoints[1])
|
||||
|
||||
tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
|
||||
tree, costs = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
|
||||
if tree[idxEnd] == -1:
|
||||
raise QgsProcessingException(
|
||||
self.tr('There is no route from start point to end point.'))
|
||||
@ -226,9 +226,9 @@ class ShortestPathPointToPoint(QgisAlgorithm):
|
||||
cost = 0.0
|
||||
current = idxEnd
|
||||
while current != idxStart:
|
||||
cost += graph.edge(tree[current]).cost(0)
|
||||
route.append(graph.vertex(graph.edge(tree[current]).fromVertex()).point())
|
||||
current = graph.edge(tree[current]).toVertex()
|
||||
cost += costs[current]
|
||||
current = graph.edge(tree[current]).fromVertex()
|
||||
route.append(graph.vertex(current).point())
|
||||
|
||||
route.append(snappedPoints[0])
|
||||
route.reverse()
|
||||
|
@ -59,21 +59,20 @@ void QgsGraphAnalyzer::dijkstra( const QgsGraph *source, int startPointIdx, int
|
||||
not_begin.erase( it );
|
||||
|
||||
// edge index list
|
||||
QgsGraphEdgeIds l = source->vertex( curVertex ).incomingEdges();
|
||||
QgsGraphEdgeIds::iterator arcIt;
|
||||
for ( arcIt = l.begin(); arcIt != l.end(); ++arcIt )
|
||||
const QgsGraphEdgeIds &outgoingEdges = source->vertex( curVertex ).outgoingEdges();
|
||||
for ( int edgeId : outgoingEdges )
|
||||
{
|
||||
const QgsGraphEdge arc = source->edge( *arcIt );
|
||||
const QgsGraphEdge &arc = source->edge( edgeId );
|
||||
double cost = arc.cost( criterionNum ).toDouble() + curCost;
|
||||
|
||||
if ( cost < ( *result )[ arc.fromVertex()] )
|
||||
if ( cost < ( *result )[ arc.toVertex()] )
|
||||
{
|
||||
( *result )[ arc.fromVertex()] = cost;
|
||||
( *result )[ arc.toVertex()] = cost;
|
||||
if ( resultTree )
|
||||
{
|
||||
( *resultTree )[ arc.fromVertex()] = *arcIt;
|
||||
( *resultTree )[ arc.toVertex()] = edgeId;
|
||||
}
|
||||
not_begin.insert( cost, arc.fromVertex() );
|
||||
not_begin.insert( cost, arc.toVertex() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ void QgsGraphBuilder::addVertex( int, const QgsPointXY &pt )
|
||||
|
||||
void QgsGraphBuilder::addEdge( int pt1id, const QgsPointXY &, int pt2id, const QgsPointXY &, const QVector< QVariant > &prop )
|
||||
{
|
||||
mGraph->addEdge( pt2id, pt1id, prop );
|
||||
mGraph->addEdge( pt1id, pt2id, prop );
|
||||
}
|
||||
|
||||
QgsGraph *QgsGraphBuilder::graph()
|
||||
|
@ -39,12 +39,14 @@ using namespace SpatialIndex;
|
||||
struct TiePointInfo
|
||||
{
|
||||
TiePointInfo() = default;
|
||||
TiePointInfo( QgsFeatureId featureId, const QgsPointXY &start, const QgsPointXY &end )
|
||||
: mNetworkFeatureId( featureId )
|
||||
TiePointInfo( int additionalPointId, QgsFeatureId featureId, const QgsPointXY &start, const QgsPointXY &end )
|
||||
: additionalPointId( additionalPointId )
|
||||
, mNetworkFeatureId( featureId )
|
||||
, mFirstPoint( start )
|
||||
, mLastPoint( end )
|
||||
{}
|
||||
|
||||
int additionalPointId = -1;
|
||||
QgsPointXY mTiedPoint;
|
||||
double mLength = DBL_MAX;
|
||||
QgsFeatureId mNetworkFeatureId = -1;
|
||||
@ -255,7 +257,7 @@ void QgsVectorLayerDirector::makeGraph( QgsGraphBuilderInterface *builder, const
|
||||
if ( thisSegmentClosestDist < additionalTiePoints[ i ].mLength )
|
||||
{
|
||||
// found a closer segment for this additional point
|
||||
TiePointInfo info( feature.id(), pt1, pt2 );
|
||||
TiePointInfo info( i, feature.id(), pt1, pt2 );
|
||||
info.mLength = thisSegmentClosestDist;
|
||||
info.mTiedPoint = snappedPoint;
|
||||
|
||||
@ -300,8 +302,11 @@ void QgsVectorLayerDirector::makeGraph( QgsGraphBuilderInterface *builder, const
|
||||
snappedPoints[ i ] = graphVertices.at( ptIdx );
|
||||
}
|
||||
}
|
||||
|
||||
// also need to update tie points - they need to be matched for snapped points
|
||||
for ( int i = 0; i < additionalTiePoints.count(); ++i )
|
||||
{
|
||||
additionalTiePoints[ i ].mTiedPoint = snappedPoints.at( additionalTiePoints.at( i ).additionalPointId );
|
||||
}
|
||||
|
||||
|
||||
// begin graph construction
|
||||
@ -361,9 +366,9 @@ void QgsVectorLayerDirector::makeGraph( QgsGraphBuilderInterface *builder, const
|
||||
int pt1idx = -1;
|
||||
int pt2idx = -1;
|
||||
bool isFirstPoint = true;
|
||||
for ( const QgsPointXY &arcPoint : qgis::as_const( pointsOnArc ) )
|
||||
for ( auto arcPointIt = pointsOnArc.constBegin(); arcPointIt != pointsOnArc.constEnd(); ++arcPointIt )
|
||||
{
|
||||
pt2 = arcPoint;
|
||||
pt2 = arcPointIt.value();
|
||||
|
||||
pt2idx = findPointWithinTolerance( pt2 );
|
||||
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
|
||||
{
|
||||
double distance = builder->distanceArea()->measureLine( pt1, pt2 );
|
||||
QVector< QVariant > prop;
|
||||
QList< QgsNetworkStrategy * >::const_iterator it;
|
||||
for ( it = mStrategies.begin(); it != mStrategies.end(); ++it )
|
||||
for ( QgsNetworkStrategy *strategy : mStrategies )
|
||||
{
|
||||
prop.push_back( ( *it )->cost( distance, feature ) );
|
||||
prop.push_back( strategy->cost( distance, feature ) );
|
||||
}
|
||||
|
||||
if ( direction == Direction::DirectionForward ||
|
||||
|
@ -24,6 +24,7 @@ Email : nyall dot dawson at gmail dot com
|
||||
#include "qgsnetworkdistancestrategy.h"
|
||||
#include "qgsgraphbuilder.h"
|
||||
#include "qgsgraph.h"
|
||||
#include "qgsgraphanalyzer.h"
|
||||
|
||||
class TestQgsNetworkAnalysis : public QObject
|
||||
{
|
||||
@ -39,6 +40,7 @@ class TestQgsNetworkAnalysis : public QObject
|
||||
void testGraph();
|
||||
void testBuild();
|
||||
void testBuildTolerance();
|
||||
void dijkkjkjkskkjsktra();
|
||||
|
||||
private:
|
||||
std::unique_ptr< QgsVectorLayer > buildNetwork();
|
||||
@ -46,6 +48,18 @@ class TestQgsNetworkAnalysis : public QObject
|
||||
|
||||
};
|
||||
|
||||
class TestNetworkStrategy : public QgsNetworkStrategy
|
||||
{
|
||||
QSet< int > requiredAttributes() const override
|
||||
{
|
||||
return QSet< int >() << 0;
|
||||
}
|
||||
QVariant cost( double, const QgsFeature &f ) const override
|
||||
{
|
||||
return f.attribute( 0 );
|
||||
}
|
||||
};
|
||||
|
||||
void TestQgsNetworkAnalysis::initTestCase()
|
||||
{
|
||||
//
|
||||
@ -117,11 +131,12 @@ void TestQgsNetworkAnalysis::testGraph()
|
||||
|
||||
std::unique_ptr<QgsVectorLayer> TestQgsNetworkAnalysis::buildNetwork()
|
||||
{
|
||||
std::unique_ptr< QgsVectorLayer > l = qgis::make_unique< QgsVectorLayer >( QStringLiteral( "LineString?crs=epsg:4326" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
|
||||
std::unique_ptr< QgsVectorLayer > l = qgis::make_unique< QgsVectorLayer >( QStringLiteral( "LineString?crs=epsg:4326&field=cost:int" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
|
||||
|
||||
QgsFeature ff( 0 );
|
||||
QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(0 0, 10 0, 10 10)" ) );
|
||||
ff.setGeometry( refGeom );
|
||||
ff.setAttributes( QgsAttributes() << 1 );
|
||||
QgsFeatureList flist;
|
||||
flist << ff;
|
||||
l->dataProvider()->addFeatures( flist );
|
||||
@ -146,22 +161,22 @@ void TestQgsNetworkAnalysis::testBuild()
|
||||
QCOMPARE( graph->vertexCount(), 3 );
|
||||
QCOMPARE( graph->edgeCount(), 4 );
|
||||
QCOMPARE( graph->vertex( 0 ).point(), QgsPointXY( 0, 0 ) );
|
||||
QCOMPARE( graph->vertex( 0 ).outgoingEdges(), QList< int >() << 1 );
|
||||
QCOMPARE( graph->edge( 1 ).fromVertex(), 0 );
|
||||
QCOMPARE( graph->edge( 1 ).toVertex(), 1 );
|
||||
QCOMPARE( graph->vertex( 0 ).incomingEdges(), QList< int >() << 0 );
|
||||
QCOMPARE( graph->edge( 0 ).fromVertex(), 1 );
|
||||
QCOMPARE( graph->edge( 0 ).toVertex(), 0 );
|
||||
QCOMPARE( graph->vertex( 0 ).outgoingEdges(), QList< int >() << 0 );
|
||||
QCOMPARE( graph->edge( 0 ).fromVertex(), 0 );
|
||||
QCOMPARE( graph->edge( 0 ).toVertex(), 1 );
|
||||
QCOMPARE( graph->vertex( 0 ).incomingEdges(), QList< int >() << 1 );
|
||||
QCOMPARE( graph->edge( 1 ).fromVertex(), 1 );
|
||||
QCOMPARE( graph->edge( 1 ).toVertex(), 0 );
|
||||
QCOMPARE( graph->vertex( 1 ).point(), QgsPointXY( 10, 0 ) );
|
||||
QCOMPARE( graph->vertex( 1 ).outgoingEdges(), QList< int >() << 0 << 3 );
|
||||
QCOMPARE( graph->vertex( 1 ).incomingEdges(), QList< int >() << 1 << 2 );
|
||||
QCOMPARE( graph->edge( 2 ).fromVertex(), 2 );
|
||||
QCOMPARE( graph->edge( 2 ).toVertex(), 1 );
|
||||
QCOMPARE( graph->edge( 3 ).fromVertex(), 1 );
|
||||
QCOMPARE( graph->edge( 3 ).toVertex(), 2 );
|
||||
QCOMPARE( graph->vertex( 1 ).outgoingEdges(), QList< int >() << 1 << 2 );
|
||||
QCOMPARE( graph->vertex( 1 ).incomingEdges(), QList< int >() << 0 << 3 );
|
||||
QCOMPARE( graph->edge( 3 ).fromVertex(), 2 );
|
||||
QCOMPARE( graph->edge( 3 ).toVertex(), 1 );
|
||||
QCOMPARE( graph->edge( 2 ).fromVertex(), 1 );
|
||||
QCOMPARE( graph->edge( 2 ).toVertex(), 2 );
|
||||
QCOMPARE( graph->vertex( 2 ).point(), QgsPointXY( 10, 10 ) );
|
||||
QCOMPARE( graph->vertex( 2 ).outgoingEdges(), QList< int >() << 2 );
|
||||
QCOMPARE( graph->vertex( 2 ).incomingEdges(), QList< int >() << 3 );
|
||||
QCOMPARE( graph->vertex( 2 ).outgoingEdges(), QList< int >() << 3 );
|
||||
QCOMPARE( graph->vertex( 2 ).incomingEdges(), QList< int >() << 2 );
|
||||
|
||||
builder = qgis::make_unique< QgsGraphBuilder > ( network->sourceCrs(), true, 0 );
|
||||
director->makeGraph( builder.get(), QVector<QgsPointXY>() << QgsPointXY( 10, 0 ) << QgsPointXY( 10, 10 ), snapped );
|
||||
@ -205,30 +220,30 @@ void TestQgsNetworkAnalysis::testBuildTolerance()
|
||||
QCOMPARE( graph->vertexCount(), 5 );
|
||||
QCOMPARE( graph->edgeCount(), 6 );
|
||||
QCOMPARE( graph->vertex( 0 ).point(), QgsPointXY( 0, 0 ) );
|
||||
QCOMPARE( graph->vertex( 0 ).outgoingEdges(), QList< int >() << 1 );
|
||||
QCOMPARE( graph->edge( 1 ).fromVertex(), 0 );
|
||||
QCOMPARE( graph->edge( 1 ).toVertex(), 1 );
|
||||
QCOMPARE( graph->vertex( 0 ).incomingEdges(), QList< int >() << 0 );
|
||||
QCOMPARE( graph->edge( 0 ).fromVertex(), 1 );
|
||||
QCOMPARE( graph->edge( 0 ).toVertex(), 0 );
|
||||
QCOMPARE( graph->vertex( 0 ).outgoingEdges(), QList< int >() << 0 );
|
||||
QCOMPARE( graph->edge( 0 ).fromVertex(), 0 );
|
||||
QCOMPARE( graph->edge( 0 ).toVertex(), 1 );
|
||||
QCOMPARE( graph->vertex( 0 ).incomingEdges(), QList< int >() << 1 );
|
||||
QCOMPARE( graph->edge( 1 ).fromVertex(), 1 );
|
||||
QCOMPARE( graph->edge( 1 ).toVertex(), 0 );
|
||||
QCOMPARE( graph->vertex( 1 ).point(), QgsPointXY( 10, 0 ) );
|
||||
QCOMPARE( graph->vertex( 1 ).outgoingEdges(), QList< int >() << 0 << 3 );
|
||||
QCOMPARE( graph->vertex( 1 ).incomingEdges(), QList< int >() << 1 << 2 );
|
||||
QCOMPARE( graph->edge( 2 ).fromVertex(), 2 );
|
||||
QCOMPARE( graph->edge( 2 ).toVertex(), 1 );
|
||||
QCOMPARE( graph->edge( 3 ).fromVertex(), 1 );
|
||||
QCOMPARE( graph->edge( 3 ).toVertex(), 2 );
|
||||
QCOMPARE( graph->vertex( 1 ).outgoingEdges(), QList< int >() << 1 << 2 );
|
||||
QCOMPARE( graph->vertex( 1 ).incomingEdges(), QList< int >() << 0 << 3 );
|
||||
QCOMPARE( graph->edge( 3 ).fromVertex(), 2 );
|
||||
QCOMPARE( graph->edge( 3 ).toVertex(), 1 );
|
||||
QCOMPARE( graph->edge( 2 ).fromVertex(), 1 );
|
||||
QCOMPARE( graph->edge( 2 ).toVertex(), 2 );
|
||||
QCOMPARE( graph->vertex( 2 ).point(), QgsPointXY( 10, 10 ) );
|
||||
QCOMPARE( graph->vertex( 2 ).outgoingEdges(), QList< int >() << 2 );
|
||||
QCOMPARE( graph->vertex( 2 ).incomingEdges(), QList< int >() << 3 );
|
||||
QCOMPARE( graph->vertex( 2 ).outgoingEdges(), QList< int >() << 3 );
|
||||
QCOMPARE( graph->vertex( 2 ).incomingEdges(), QList< int >() << 2 );
|
||||
QCOMPARE( graph->vertex( 3 ).point(), QgsPointXY( 10.1, 10 ) );
|
||||
QCOMPARE( graph->vertex( 3 ).outgoingEdges(), QList< int >() << 5 );
|
||||
QCOMPARE( graph->vertex( 3 ).incomingEdges(), QList< int >() << 4 );
|
||||
QCOMPARE( graph->vertex( 3 ).outgoingEdges(), QList< int >() << 4 );
|
||||
QCOMPARE( graph->vertex( 3 ).incomingEdges(), QList< int >() << 5 );
|
||||
QCOMPARE( graph->vertex( 4 ).point(), QgsPointXY( 20, 10 ) );
|
||||
QCOMPARE( graph->edge( 4 ).fromVertex(), 4 );
|
||||
QCOMPARE( graph->edge( 4 ).toVertex(), 3 );
|
||||
QCOMPARE( graph->edge( 5 ).fromVertex(), 3 );
|
||||
QCOMPARE( graph->edge( 5 ).toVertex(), 4 );
|
||||
QCOMPARE( graph->edge( 5 ).fromVertex(), 4 );
|
||||
QCOMPARE( graph->edge( 5 ).toVertex(), 3 );
|
||||
QCOMPARE( graph->edge( 4 ).fromVertex(), 3 );
|
||||
QCOMPARE( graph->edge( 4 ).toVertex(), 4 );
|
||||
|
||||
// with tolerance
|
||||
double tolerance = 0.11;
|
||||
@ -239,29 +254,212 @@ void TestQgsNetworkAnalysis::testBuildTolerance()
|
||||
QCOMPARE( graph->vertexCount(), 4 );
|
||||
QCOMPARE( graph->edgeCount(), 6 );
|
||||
QCOMPARE( graph->vertex( 0 ).point(), QgsPointXY( 0, 0 ) );
|
||||
QCOMPARE( graph->vertex( 0 ).outgoingEdges(), QList< int >() << 1 );
|
||||
QCOMPARE( graph->edge( 1 ).fromVertex(), 0 );
|
||||
QCOMPARE( graph->edge( 1 ).toVertex(), 1 );
|
||||
QCOMPARE( graph->vertex( 0 ).incomingEdges(), QList< int >() << 0 );
|
||||
QCOMPARE( graph->edge( 0 ).fromVertex(), 1 );
|
||||
QCOMPARE( graph->edge( 0 ).toVertex(), 0 );
|
||||
QCOMPARE( graph->vertex( 0 ).outgoingEdges(), QList< int >() << 0 );
|
||||
QCOMPARE( graph->edge( 0 ).fromVertex(), 0 );
|
||||
QCOMPARE( graph->edge( 0 ).toVertex(), 1 );
|
||||
QCOMPARE( graph->vertex( 0 ).incomingEdges(), QList< int >() << 1 );
|
||||
QCOMPARE( graph->edge( 1 ).fromVertex(), 1 );
|
||||
QCOMPARE( graph->edge( 1 ).toVertex(), 0 );
|
||||
QCOMPARE( graph->vertex( 1 ).point(), QgsPointXY( 10, 0 ) );
|
||||
QCOMPARE( graph->vertex( 1 ).outgoingEdges(), QList< int >() << 0 << 3 );
|
||||
QCOMPARE( graph->vertex( 1 ).incomingEdges(), QList< int >() << 1 << 2 );
|
||||
QCOMPARE( graph->edge( 2 ).fromVertex(), 2 );
|
||||
QCOMPARE( graph->edge( 2 ).toVertex(), 1 );
|
||||
QCOMPARE( graph->edge( 3 ).fromVertex(), 1 );
|
||||
QCOMPARE( graph->edge( 3 ).toVertex(), 2 );
|
||||
QCOMPARE( graph->vertex( 1 ).outgoingEdges(), QList< int >() << 1 << 2 );
|
||||
QCOMPARE( graph->vertex( 1 ).incomingEdges(), QList< int >() << 0 << 3 );
|
||||
QCOMPARE( graph->edge( 3 ).fromVertex(), 2 );
|
||||
QCOMPARE( graph->edge( 3 ).toVertex(), 1 );
|
||||
QCOMPARE( graph->edge( 2 ).fromVertex(), 1 );
|
||||
QCOMPARE( graph->edge( 2 ).toVertex(), 2 );
|
||||
QCOMPARE( graph->vertex( 2 ).point(), QgsPointXY( 10, 10 ) );
|
||||
QCOMPARE( graph->vertex( 2 ).outgoingEdges(), QList< int >() << 2 << 5 );
|
||||
QCOMPARE( graph->vertex( 2 ).incomingEdges(), QList< int >() << 3 << 4 );
|
||||
QCOMPARE( graph->vertex( 2 ).outgoingEdges(), QList< int >() << 3 << 4 );
|
||||
QCOMPARE( graph->vertex( 2 ).incomingEdges(), QList< int >() << 2 << 5 );
|
||||
QCOMPARE( graph->vertex( 3 ).point(), QgsPointXY( 20, 10 ) );
|
||||
QCOMPARE( graph->vertex( 3 ).outgoingEdges(), QList< int >() << 4 );
|
||||
QCOMPARE( graph->vertex( 3 ).incomingEdges(), QList< int >() << 5 );
|
||||
QCOMPARE( graph->edge( 4 ).fromVertex(), 3 );
|
||||
QCOMPARE( graph->edge( 4 ).toVertex(), 2 );
|
||||
QCOMPARE( graph->edge( 5 ).fromVertex(), 2 );
|
||||
QCOMPARE( graph->edge( 5 ).toVertex(), 3 );
|
||||
QCOMPARE( graph->vertex( 3 ).outgoingEdges(), QList< int >() << 5 );
|
||||
QCOMPARE( graph->vertex( 3 ).incomingEdges(), QList< int >() << 4 );
|
||||
QCOMPARE( graph->edge( 5 ).fromVertex(), 3 );
|
||||
QCOMPARE( graph->edge( 5 ).toVertex(), 2 );
|
||||
QCOMPARE( graph->edge( 4 ).fromVertex(), 2 );
|
||||
QCOMPARE( graph->edge( 4 ).toVertex(), 3 );
|
||||
}
|
||||
|
||||
void TestQgsNetworkAnalysis::dijkkjkjkskkjsktra()
|
||||
{
|
||||
std::unique_ptr<QgsVectorLayer> network = buildNetwork();
|
||||
// has already a linestring LineString(0 0, 10 0, 10 10)
|
||||
|
||||
// add some more lines to network
|
||||
QgsFeature ff( 0 );
|
||||
QgsFeatureList flist;
|
||||
|
||||
ff.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "LineString(10 10, 20 10 )" ) ) );
|
||||
ff.setAttributes( QgsAttributes() << 2 );
|
||||
flist << ff;
|
||||
ff.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "LineString(10 20, 10 10 )" ) ) );
|
||||
ff.setAttributes( QgsAttributes() << 3 );
|
||||
flist << ff;
|
||||
ff.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "LineString(20 -10, 20 10 )" ) ) );
|
||||
ff.setAttributes( QgsAttributes() << 4 );
|
||||
flist << ff;
|
||||
network->dataProvider()->addFeatures( flist );
|
||||
|
||||
/*
|
||||
Out network is:
|
||||
Numbers in brackets are cost for segment
|
||||
|
||||
20 o
|
||||
|
|
||||
v (3)
|
||||
| (2)
|
||||
10 o---->----o
|
||||
| |
|
||||
(1) ^ ^
|
||||
(1) | |
|
||||
0 o---->-----. |(4)
|
||||
|
|
||||
^
|
||||
|
|
||||
-10 o
|
||||
|
||||
0 10 20
|
||||
|
||||
*/
|
||||
|
||||
// build graph
|
||||
std::unique_ptr< QgsVectorLayerDirector > director = qgis::make_unique< QgsVectorLayerDirector > ( network.get(),
|
||||
-1, QString(), QString(), QString(), QgsVectorLayerDirector::DirectionBoth );
|
||||
std::unique_ptr< QgsNetworkStrategy > strategy = qgis::make_unique< TestNetworkStrategy >();
|
||||
director->addStrategy( strategy.release() );
|
||||
std::unique_ptr< QgsGraphBuilder > builder = qgis::make_unique< QgsGraphBuilder > ( network->sourceCrs(), true, 0 );
|
||||
|
||||
QVector<QgsPointXY > snapped;
|
||||
director->makeGraph( builder.get(), QVector<QgsPointXY>(), snapped );
|
||||
std::unique_ptr< QgsGraph > graph( builder->graph() );
|
||||
|
||||
int startVertexIdx = graph->findVertex( QgsPointXY( 20, -10 ) );
|
||||
QVERIFY( startVertexIdx != -1 );
|
||||
|
||||
// both directions
|
||||
QVector<int> resultTree;
|
||||
QVector<double> resultCost;
|
||||
QgsGraphAnalyzer::dijkstra( graph.get(), startVertexIdx, 0, &resultTree, &resultCost );
|
||||
|
||||
int point_0_0_idx = graph->findVertex( QgsPointXY( 0, 0 ) );
|
||||
QVERIFY( point_0_0_idx != -1 );
|
||||
int point_10_0_idx = graph->findVertex( QgsPointXY( 10, 0 ) );
|
||||
QVERIFY( point_10_0_idx != -1 );
|
||||
int point_10_10_idx = graph->findVertex( QgsPointXY( 10, 10 ) );
|
||||
QVERIFY( point_10_10_idx != -1 );
|
||||
int point_10_20_idx = graph->findVertex( QgsPointXY( 10, 20 ) );
|
||||
QVERIFY( point_10_20_idx != -1 );
|
||||
int point_20_10_idx = graph->findVertex( QgsPointXY( 20, 10 ) );
|
||||
QVERIFY( point_20_10_idx != -1 );
|
||||
|
||||
QCOMPARE( resultTree.at( startVertexIdx ), -1 );
|
||||
QCOMPARE( resultCost.at( startVertexIdx ), 0.0 );
|
||||
|
||||
QVERIFY( resultTree.at( point_20_10_idx ) != -1 );
|
||||
QCOMPARE( resultCost.at( point_20_10_idx ), 4.0 );
|
||||
QCOMPARE( graph->edge( resultTree.at( point_20_10_idx ) ).fromVertex(), startVertexIdx );
|
||||
QCOMPARE( graph->edge( resultTree.at( point_20_10_idx ) ).toVertex(), point_20_10_idx );
|
||||
QVERIFY( resultTree.at( point_10_10_idx ) != -1 );
|
||||
QCOMPARE( resultCost.at( point_10_10_idx ), 6.0 );
|
||||
QCOMPARE( graph->edge( resultTree.at( point_10_10_idx ) ).fromVertex(), point_20_10_idx );
|
||||
QCOMPARE( graph->edge( resultTree.at( point_10_10_idx ) ).toVertex(), point_10_10_idx );
|
||||
QVERIFY( resultTree.at( point_10_20_idx ) != -1 );
|
||||
QCOMPARE( resultCost.at( point_10_20_idx ), 9.0 );
|
||||
QCOMPARE( graph->edge( resultTree.at( point_10_20_idx ) ).fromVertex(), point_10_10_idx );
|
||||
QCOMPARE( graph->edge( resultTree.at( point_10_20_idx ) ).toVertex(), point_10_20_idx );
|
||||
QVERIFY( resultTree.at( point_10_0_idx ) != -1 );
|
||||
QCOMPARE( resultCost.at( point_10_0_idx ), 7.0 );
|
||||
QCOMPARE( graph->edge( resultTree.at( point_10_0_idx ) ).fromVertex(), point_10_10_idx );
|
||||
QCOMPARE( graph->edge( resultTree.at( point_10_0_idx ) ).toVertex(), point_10_0_idx );
|
||||
QVERIFY( resultTree.at( point_0_0_idx ) != -1 );
|
||||
QCOMPARE( resultCost.at( point_0_0_idx ), 8.0 );
|
||||
QCOMPARE( graph->edge( resultTree.at( point_0_0_idx ) ).fromVertex(), point_10_0_idx );
|
||||
QCOMPARE( graph->edge( resultTree.at( point_0_0_idx ) ).toVertex(), point_0_0_idx );
|
||||
|
||||
// forward direction
|
||||
director = qgis::make_unique< QgsVectorLayerDirector > ( network.get(),
|
||||
-1, QString(), QString(), QString(), QgsVectorLayerDirector::DirectionForward );
|
||||
strategy = qgis::make_unique< TestNetworkStrategy >();
|
||||
director->addStrategy( strategy.release() );
|
||||
builder = qgis::make_unique< QgsGraphBuilder > ( network->sourceCrs(), true, 0 );
|
||||
director->makeGraph( builder.get(), QVector<QgsPointXY>(), snapped );
|
||||
graph.reset( builder->graph() );
|
||||
startVertexIdx = graph->findVertex( QgsPointXY( 0, 0 ) );
|
||||
QVERIFY( startVertexIdx != -1 );
|
||||
resultTree.clear();
|
||||
resultCost.clear();
|
||||
QgsGraphAnalyzer::dijkstra( graph.get(), startVertexIdx, 0, &resultTree, &resultCost );
|
||||
point_0_0_idx = graph->findVertex( QgsPointXY( 0, 0 ) );
|
||||
QVERIFY( point_0_0_idx != -1 );
|
||||
point_10_0_idx = graph->findVertex( QgsPointXY( 10, 0 ) );
|
||||
QVERIFY( point_10_0_idx != -1 );
|
||||
point_10_10_idx = graph->findVertex( QgsPointXY( 10, 10 ) );
|
||||
QVERIFY( point_10_10_idx != -1 );
|
||||
point_10_20_idx = graph->findVertex( QgsPointXY( 10, 20 ) );
|
||||
QVERIFY( point_10_20_idx != -1 );
|
||||
point_20_10_idx = graph->findVertex( QgsPointXY( 20, 10 ) );
|
||||
QVERIFY( point_20_10_idx != -1 );
|
||||
int point_20_n10_idx = graph->findVertex( QgsPointXY( 20, -10 ) );
|
||||
QVERIFY( point_20_n10_idx != -1 );
|
||||
|
||||
QCOMPARE( resultTree.at( startVertexIdx ), -1 );
|
||||
QCOMPARE( resultCost.at( startVertexIdx ), 0.0 );
|
||||
QVERIFY( resultTree.at( point_10_0_idx ) != -1 );
|
||||
QCOMPARE( resultCost.at( point_10_0_idx ), 1.0 );
|
||||
QCOMPARE( graph->edge( resultTree.at( point_10_0_idx ) ).fromVertex(), startVertexIdx );
|
||||
QCOMPARE( graph->edge( resultTree.at( point_10_0_idx ) ).toVertex(), point_10_0_idx );
|
||||
QVERIFY( resultTree.at( point_10_10_idx ) != -1 );
|
||||
QCOMPARE( resultCost.at( point_10_10_idx ), 2.0 );
|
||||
QCOMPARE( graph->edge( resultTree.at( point_10_10_idx ) ).fromVertex(), point_10_0_idx );
|
||||
QCOMPARE( graph->edge( resultTree.at( point_10_10_idx ) ).toVertex(), point_10_10_idx );
|
||||
QCOMPARE( resultTree.at( point_10_20_idx ), -1 ); // unreachable
|
||||
QVERIFY( resultTree.at( point_20_10_idx ) != -1 );
|
||||
QCOMPARE( resultCost.at( point_20_10_idx ), 4.0 );
|
||||
QCOMPARE( graph->edge( resultTree.at( point_20_10_idx ) ).fromVertex(), point_10_10_idx );
|
||||
QCOMPARE( graph->edge( resultTree.at( point_20_10_idx ) ).toVertex(), point_20_10_idx );
|
||||
QCOMPARE( resultTree.at( point_20_n10_idx ), -1 ); // unreachable
|
||||
|
||||
// backward direction
|
||||
director = qgis::make_unique< QgsVectorLayerDirector > ( network.get(),
|
||||
-1, QString(), QString(), QString(), QgsVectorLayerDirector::DirectionBackward );
|
||||
strategy = qgis::make_unique< TestNetworkStrategy >();
|
||||
director->addStrategy( strategy.release() );
|
||||
builder = qgis::make_unique< QgsGraphBuilder > ( network->sourceCrs(), true, 0 );
|
||||
director->makeGraph( builder.get(), QVector<QgsPointXY>(), snapped );
|
||||
graph.reset( builder->graph() );
|
||||
startVertexIdx = graph->findVertex( QgsPointXY( 10, 10 ) );
|
||||
QVERIFY( startVertexIdx != -1 );
|
||||
resultTree.clear();
|
||||
resultCost.clear();
|
||||
QgsGraphAnalyzer::dijkstra( graph.get(), startVertexIdx, 0, &resultTree, &resultCost );
|
||||
point_0_0_idx = graph->findVertex( QgsPointXY( 0, 0 ) );
|
||||
QVERIFY( point_0_0_idx != -1 );
|
||||
point_10_0_idx = graph->findVertex( QgsPointXY( 10, 0 ) );
|
||||
QVERIFY( point_10_0_idx != -1 );
|
||||
point_10_10_idx = graph->findVertex( QgsPointXY( 10, 10 ) );
|
||||
QVERIFY( point_10_10_idx != -1 );
|
||||
point_10_20_idx = graph->findVertex( QgsPointXY( 10, 20 ) );
|
||||
QVERIFY( point_10_20_idx != -1 );
|
||||
point_20_10_idx = graph->findVertex( QgsPointXY( 20, 10 ) );
|
||||
QVERIFY( point_20_10_idx != -1 );
|
||||
point_20_n10_idx = graph->findVertex( QgsPointXY( 20, -10 ) );
|
||||
QVERIFY( point_20_n10_idx != -1 );
|
||||
|
||||
QCOMPARE( resultTree.at( startVertexIdx ), -1 );
|
||||
QCOMPARE( resultCost.at( startVertexIdx ), 0.0 );
|
||||
QCOMPARE( resultTree.at( point_20_10_idx ), -1 );
|
||||
QCOMPARE( resultTree.at( point_20_n10_idx ), -1 );
|
||||
QVERIFY( resultTree.at( point_10_20_idx ) != -1 );
|
||||
QCOMPARE( resultCost.at( point_10_20_idx ), 3.0 );
|
||||
QCOMPARE( graph->edge( resultTree.at( point_10_20_idx ) ).fromVertex(), startVertexIdx );
|
||||
QCOMPARE( graph->edge( resultTree.at( point_10_20_idx ) ).toVertex(), point_10_20_idx );
|
||||
QVERIFY( resultTree.at( point_10_0_idx ) != -1 );
|
||||
QCOMPARE( resultCost.at( point_10_0_idx ), 1.0 );
|
||||
QCOMPARE( graph->edge( resultTree.at( point_10_0_idx ) ).fromVertex(), startVertexIdx );
|
||||
QCOMPARE( graph->edge( resultTree.at( point_10_0_idx ) ).toVertex(), point_10_0_idx );
|
||||
QVERIFY( resultTree.at( point_0_0_idx ) != -1 );
|
||||
QCOMPARE( resultCost.at( point_0_0_idx ), 2.0 );
|
||||
QCOMPARE( graph->edge( resultTree.at( point_0_0_idx ) ).fromVertex(), point_10_0_idx );
|
||||
QCOMPARE( graph->edge( resultTree.at( point_0_0_idx ) ).toVertex(), point_0_0_idx );
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user