Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsalgorithmnetworkanalysisbase.cpp
3 : : ---------------------
4 : : begin : July 2018
5 : : copyright : (C) 2018 by Alexander Bruy
6 : : email : alexander dot bruy at gmail dot com
7 : : ***************************************************************************/
8 : :
9 : : /***************************************************************************
10 : : * *
11 : : * This program is free software; you can redistribute it and/or modify *
12 : : * it under the terms of the GNU General Public License as published by *
13 : : * the Free Software Foundation; either version 2 of the License, or *
14 : : * (at your option) any later version. *
15 : : * *
16 : : ***************************************************************************/
17 : :
18 : : #include "qgsalgorithmnetworkanalysisbase.h"
19 : :
20 : : #include "qgsgraphanalyzer.h"
21 : : #include "qgsnetworkspeedstrategy.h"
22 : : #include "qgsnetworkdistancestrategy.h"
23 : :
24 : : ///@cond PRIVATE
25 : :
26 : : //
27 : : // QgsNetworkAnalysisAlgorithmBase
28 : : //
29 : :
30 : 0 : QString QgsNetworkAnalysisAlgorithmBase::group() const
31 : : {
32 : 0 : return QObject::tr( "Network analysis" );
33 : : }
34 : :
35 : 0 : QString QgsNetworkAnalysisAlgorithmBase::groupId() const
36 : : {
37 : 0 : return QStringLiteral( "networkanalysis" );
38 : : }
39 : :
40 : 0 : QgsProcessingAlgorithm::Flags QgsNetworkAnalysisAlgorithmBase::flags() const
41 : : {
42 : : // TODO -- remove the dependency on the project from these algorithms, it shouldn't be required
43 : 0 : return QgsProcessingAlgorithm::flags() | FlagRequiresProject;
44 : : }
45 : :
46 : 0 : void QgsNetworkAnalysisAlgorithmBase::addCommonParams()
47 : : {
48 : 0 : addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Vector layer representing network" ), QList< int >() << QgsProcessing::TypeVectorLine ) );
49 : 0 : addParameter( new QgsProcessingParameterEnum( QStringLiteral( "STRATEGY" ), QObject::tr( "Path type to calculate" ), QStringList() << QObject::tr( "Shortest" ) << QObject::tr( "Fastest" ), false, 0 ) );
50 : :
51 : 0 : std::unique_ptr< QgsProcessingParameterField > directionField = std::make_unique< QgsProcessingParameterField >( QStringLiteral( "DIRECTION_FIELD" ),
52 : 0 : QObject::tr( "Direction field" ), QVariant(), QStringLiteral( "INPUT" ), QgsProcessingParameterField::Any, false, true );
53 : 0 : directionField->setFlags( directionField->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
54 : 0 : addParameter( directionField.release() );
55 : :
56 : 0 : std::unique_ptr< QgsProcessingParameterString > forwardValue = std::make_unique< QgsProcessingParameterString >( QStringLiteral( "VALUE_FORWARD" ),
57 : 0 : QObject::tr( "Value for forward direction" ), QVariant(), false, true );
58 : 0 : forwardValue->setFlags( forwardValue->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
59 : 0 : addParameter( forwardValue.release() );
60 : :
61 : 0 : std::unique_ptr< QgsProcessingParameterString > backwardValue = std::make_unique< QgsProcessingParameterString >( QStringLiteral( "VALUE_BACKWARD" ),
62 : 0 : QObject::tr( "Value for backward direction" ), QVariant(), false, true );
63 : 0 : backwardValue->setFlags( backwardValue->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
64 : 0 : addParameter( backwardValue.release() );
65 : :
66 : 0 : std::unique_ptr< QgsProcessingParameterString > bothValue = std::make_unique< QgsProcessingParameterString >( QStringLiteral( "VALUE_BOTH" ),
67 : 0 : QObject::tr( "Value for both directions" ), QVariant(), false, true );
68 : 0 : bothValue->setFlags( bothValue->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
69 : 0 : addParameter( bothValue.release() );
70 : :
71 : 0 : std::unique_ptr< QgsProcessingParameterEnum > directionValue = std::make_unique< QgsProcessingParameterEnum >( QStringLiteral( "DEFAULT_DIRECTION" ),
72 : 0 : QObject::tr( "Default direction" ), QStringList() << QObject::tr( "Forward direction" ) << QObject::tr( "Backward direction" ) << QObject::tr( "Both directions" ), false, 2 );
73 : 0 : directionValue->setFlags( directionValue->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
74 : 0 : addParameter( directionValue.release() );
75 : :
76 : 0 : std::unique_ptr< QgsProcessingParameterField > speedField = std::make_unique< QgsProcessingParameterField >( QStringLiteral( "SPEED_FIELD" ),
77 : 0 : QObject::tr( "Speed field" ), QVariant(), QStringLiteral( "INPUT" ), QgsProcessingParameterField::Numeric, false, true );
78 : 0 : speedField->setFlags( speedField->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
79 : 0 : addParameter( speedField.release() );
80 : :
81 : 0 : std::unique_ptr< QgsProcessingParameterNumber > speed = std::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "DEFAULT_SPEED" ), QObject::tr( "Default speed (km/h)" ), QgsProcessingParameterNumber::Double, 50, false, 0 );
82 : 0 : speed->setFlags( speed->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
83 : 0 : addParameter( speed.release() );
84 : :
85 : 0 : std::unique_ptr< QgsProcessingParameterNumber > tolerance = std::make_unique < QgsProcessingParameterDistance >( QStringLiteral( "TOLERANCE" ), QObject::tr( "Topology tolerance" ), 0, QStringLiteral( "INPUT" ), false, 0 );
86 : 0 : tolerance->setFlags( tolerance->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
87 : 0 : addParameter( tolerance.release() );
88 : 0 : }
89 : :
90 : 0 : void QgsNetworkAnalysisAlgorithmBase::loadCommonParams( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
91 : : {
92 : : Q_UNUSED( feedback )
93 : :
94 : 0 : mNetwork.reset( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
95 : 0 : if ( !mNetwork )
96 : 0 : throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
97 : :
98 : 0 : int strategy = parameterAsInt( parameters, QStringLiteral( "STRATEGY" ), context );
99 : 0 : QString directionFieldName = parameterAsString( parameters, QStringLiteral( "DIRECTION_FIELD" ), context );
100 : 0 : QString forwardValue = parameterAsString( parameters, QStringLiteral( "VALUE_FORWARD" ), context );
101 : 0 : QString backwardValue = parameterAsString( parameters, QStringLiteral( "VALUE_BACKWARD" ), context );
102 : 0 : QString bothValue = parameterAsString( parameters, QStringLiteral( "VALUE_BOTH" ), context );
103 : 0 : QgsVectorLayerDirector::Direction defaultDirection = static_cast< QgsVectorLayerDirector::Direction>( parameterAsInt( parameters, QStringLiteral( "DEFAULT_DIRECTION" ), context ) );
104 : 0 : QString speedFieldName = parameterAsString( parameters, QStringLiteral( "SPEED_FIELD" ), context );
105 : 0 : double defaultSpeed = parameterAsDouble( parameters, QStringLiteral( "DEFAULT_SPEED" ), context );
106 : 0 : double tolerance = parameterAsDouble( parameters, QStringLiteral( "TOLERANCE" ), context );
107 : :
108 : 0 : int directionField = -1;
109 : 0 : if ( !directionFieldName.isEmpty() )
110 : : {
111 : 0 : directionField = mNetwork->fields().lookupField( directionFieldName );
112 : 0 : }
113 : :
114 : 0 : int speedField = -1;
115 : 0 : if ( !speedFieldName.isEmpty() )
116 : : {
117 : 0 : speedField = mNetwork->fields().lookupField( speedFieldName );
118 : 0 : }
119 : :
120 : 0 : mDirector = new QgsVectorLayerDirector( mNetwork.get(), directionField, forwardValue, backwardValue, bothValue, defaultDirection );
121 : :
122 : 0 : QgsUnitTypes::DistanceUnit distanceUnits = context.project()->crs().mapUnits();
123 : 0 : mMultiplier = QgsUnitTypes::fromUnitToUnitFactor( distanceUnits, QgsUnitTypes::DistanceMeters );
124 : :
125 : 0 : if ( strategy )
126 : : {
127 : 0 : mDirector->addStrategy( new QgsNetworkSpeedStrategy( speedField, defaultSpeed, mMultiplier * 1000.0 / 3600.0 ) );
128 : 0 : mMultiplier = 3600;
129 : 0 : }
130 : : else
131 : : {
132 : 0 : mDirector->addStrategy( new QgsNetworkDistanceStrategy() );
133 : : }
134 : :
135 : 0 : mBuilder = std::make_unique< QgsGraphBuilder >( mNetwork->sourceCrs(), true, tolerance );
136 : 0 : }
137 : :
138 : 0 : void QgsNetworkAnalysisAlgorithmBase::loadPoints( QgsFeatureSource *source, QVector< QgsPointXY > &points, QHash< int, QgsAttributes > &attributes, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
139 : : {
140 : 0 : feedback->pushInfo( QObject::tr( "Loading points…" ) );
141 : :
142 : 0 : QgsFeature feat;
143 : 0 : int i = 0;
144 : 0 : int pointId = 1;
145 : 0 : double step = source->featureCount() > 0 ? 100.0 / source->featureCount() : 0;
146 : 0 : QgsFeatureIterator features = source->getFeatures( QgsFeatureRequest().setDestinationCrs( mNetwork->sourceCrs(), context.transformContext() ) );
147 : :
148 : 0 : while ( features.nextFeature( feat ) )
149 : : {
150 : 0 : i++;
151 : 0 : if ( feedback->isCanceled() )
152 : : {
153 : 0 : break;
154 : : }
155 : :
156 : 0 : feedback->setProgress( i * step );
157 : 0 : if ( !feat.hasGeometry() )
158 : 0 : continue;
159 : :
160 : 0 : QgsGeometry geom = feat.geometry();
161 : 0 : QgsAbstractGeometry::vertex_iterator it = geom.vertices_begin();
162 : 0 : while ( it != geom.vertices_end() )
163 : : {
164 : 0 : points.push_back( QgsPointXY( *it ) );
165 : 0 : attributes.insert( pointId, feat.attributes() );
166 : 0 : it++;
167 : 0 : pointId++;
168 : : }
169 : 0 : }
170 : 0 : }
171 : :
172 : : ///@endcond
|