QGIS API Documentation  3.0.2-Girona (307d082)
qgsalgorithmtransect.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsalgorithmtransect.cpp
3  -------------------------
4  begin : October 2017
5  copyright : (C) 2017 by Loïc Bartoletti
6  email : lbartoletti at tuxfamily dot org
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 "qgsalgorithmtransect.h"
19 #include "qgsmultilinestring.h"
20 #include "qgslinestring.h"
21 
23 
24 QString QgsTransectAlgorithm::name() const
25 {
26  return QStringLiteral( "transect" );
27 }
28 
29 QString QgsTransectAlgorithm::displayName() const
30 {
31  return QObject::tr( "Transect" );
32 }
33 
34 QStringList QgsTransectAlgorithm::tags() const
35 {
36  return QObject::tr( "transect,station,lines,extend," ).split( ',' );
37 }
38 
39 QString QgsTransectAlgorithm::group() const
40 {
41  return QObject::tr( "Vector geometry" );
42 }
43 
44 QString QgsTransectAlgorithm::groupId() const
45 {
46  return QStringLiteral( "vectorgeometry" );
47 }
48 
49 void QgsTransectAlgorithm::initAlgorithm( const QVariantMap & )
50 {
51  addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ),
52  QObject::tr( "Input layer" ), QList< int >() << QgsProcessing::TypeVectorLine ) );
53  addParameter( new QgsProcessingParameterNumber( QStringLiteral( "LENGTH" ), QObject::tr( "Length of the transect " ), QgsProcessingParameterNumber::Double,
54  5.0, false, 0 ) );
55  addParameter( new QgsProcessingParameterNumber( QStringLiteral( "ANGLE" ), QObject::tr( "Angle in degrees from the original line at the vertices" ), QgsProcessingParameterNumber::Double,
56  90.0, false, 0, 360 ) );
57  addParameter( new QgsProcessingParameterEnum( QStringLiteral( "SIDE" ), QObject::tr( "Side to create the transects" ), QStringList() << QObject::tr( "Left" ) << QObject::tr( "Right" ) << QObject::tr( "Both" ), false ) );
58  addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Transect" ), QgsProcessing::TypeVectorLine ) );
59 
60 }
61 
62 QString QgsTransectAlgorithm::shortHelpString() const
63 {
64 
65  return QObject::tr( "This algorithm creates transects on vertices for (multi)linestring.\n" ) +
66  QObject::tr( "A transect is a line oriented from an angle (by default perpendicular) to the input polylines (at vertices)." ) +
67  QStringLiteral( "\n\n" ) +
68  QObject::tr( "Field(s) from feature(s) are returned in the transect with these new fields:\n" ) +
69  QObject::tr( "- TR_FID: ID of the original feature\n" ) +
70  QObject::tr( "- TR_ID: ID of the transect. Each transect have an unique ID\n" ) +
71  QObject::tr( "- TR_SEGMENT: ID of the segment of the linestring\n" ) +
72  QObject::tr( "- TR_ANGLE: Angle in degrees from the original line at the vertex\n" ) +
73  QObject::tr( "- TR_LENGTH: Total length of the transect returned\n" ) +
74  QObject::tr( "- TR_ORIENT: Side of the transect (only on the left or right of the line, or both side)\n" );
75 
76 }
77 
78 QgsTransectAlgorithm *QgsTransectAlgorithm::createInstance() const
79 {
80  return new QgsTransectAlgorithm();
81 }
82 
83 QVariantMap QgsTransectAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
84 {
85  Side orientation = static_cast< QgsTransectAlgorithm::Side >( parameterAsInt( parameters, QStringLiteral( "SIDE" ), context ) );
86  double angle = fabs( parameterAsDouble( parameters, QStringLiteral( "ANGLE" ), context ) );
87  double length = parameterAsDouble( parameters, QStringLiteral( "LENGTH" ), context );
88 
89  if ( orientation == QgsTransectAlgorithm::Both )
90  length /= 2.0;
91 
92  std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
93  if ( !source )
94  throw QgsProcessingException( QObject::tr( "Could not load source layer for INPUT" ) );
95 
96  QgsFields fields = source->fields();
97 
98  fields.append( QgsField( QStringLiteral( "TR_FID" ), QVariant::Int, QString(), 20 ) );
99  fields.append( QgsField( QStringLiteral( "TR_ID" ), QVariant::Int, QString(), 20 ) );
100  fields.append( QgsField( QStringLiteral( "TR_SEGMENT" ), QVariant::Int, QString(), 20 ) );
101  fields.append( QgsField( QStringLiteral( "TR_ANGLE" ), QVariant::Double, QString(), 5, 2 ) );
102  fields.append( QgsField( QStringLiteral( "TR_LENGTH" ), QVariant::Double, QString(), 20, 6 ) );
103  fields.append( QgsField( QStringLiteral( "TR_ORIENT" ), QVariant::Int, QString(), 1 ) );
104 
106  if ( QgsWkbTypes::hasZ( source->wkbType() ) )
107  outputWkb = QgsWkbTypes::addZ( outputWkb );
108  if ( QgsWkbTypes::hasM( source->wkbType() ) )
109  outputWkb = QgsWkbTypes::addM( outputWkb );
110 
111  QString dest;
112  std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields,
113  outputWkb, source->sourceCrs() ) );
114  if ( !sink )
115  throw QgsProcessingException( QObject::tr( "Could not create destination layer for OUTPUT" ) );;
116 
117  QgsFeatureIterator features = source->getFeatures( );
118 
119  int current = -1;
120  int number = 0;
121  double step = source->featureCount() > 0 ? 100.0 / source->featureCount() : 1;
122  QgsFeature feat;
123 
124 
125  while ( features.nextFeature( feat ) )
126  {
127  current++;
128  if ( feedback->isCanceled() )
129  {
130  break;
131  }
132 
133  feedback->setProgress( current * step );
134  if ( !feat.hasGeometry() )
135  continue;
136 
137  QgsGeometry inputGeometry = feat.geometry();
138 
139  inputGeometry.convertToMultiType();
140  const QgsMultiLineString *multiLine = static_cast< const QgsMultiLineString * >( inputGeometry.constGet() );
141  for ( int id = 0; id < multiLine->numGeometries(); ++id )
142  {
143  const QgsLineString *line = static_cast< const QgsLineString * >( multiLine->geometryN( id ) );
145  while ( it != line->vertices_end() )
146  {
147  QgsVertexId vertexId = it.vertexId();
148  int i = vertexId.vertex;
149  QgsFeature outFeat;
150  QgsAttributes attrs = feat.attributes();
151  attrs << current << number << i + 1 << angle <<
152  ( ( orientation == QgsTransectAlgorithm::Both ) ? length * 2 : length ) <<
153  orientation;
154  outFeat.setAttributes( attrs );
155  double angleAtVertex = line->vertexAngle( vertexId );
156  outFeat.setGeometry( calcTransect( *it, angleAtVertex, length, orientation, angle ) );
157  sink->addFeature( outFeat, QgsFeatureSink::FastInsert );
158  number++;
159  it++;
160  }
161  }
162  }
163 
164  QVariantMap outputs;
165  outputs.insert( QStringLiteral( "OUTPUT" ), dest );
166  return outputs;
167 }
168 
169 
170 QgsGeometry QgsTransectAlgorithm::calcTransect( const QgsPoint &point, const double angleAtVertex, const double length, const QgsTransectAlgorithm::Side orientation, const double angle )
171 {
172  QgsPoint pLeft; // left point of the line
173  QgsPoint pRight; // right point of the line
174 
175  QgsPolyline line;
176 
177  if ( ( orientation == QgsTransectAlgorithm::Right ) || ( orientation == QgsTransectAlgorithm::Both ) )
178  {
179  pLeft = point.project( length, angle + 180.0 / M_PI * angleAtVertex );
180  if ( orientation != QgsTransectAlgorithm::Both )
181  pRight = point;
182  }
183 
184  if ( ( orientation == QgsTransectAlgorithm::Left ) || ( orientation == QgsTransectAlgorithm::Both ) )
185  {
186  pRight = point.project( -length, angle + 180.0 / M_PI * angleAtVertex );
187  if ( orientation != QgsTransectAlgorithm::Both )
188  pLeft = point;
189  }
190 
191  line.append( pLeft );
192  line.append( pRight );
193 
194  return QgsGeometry::fromPolyline( line );
195 }
196 
Wrapper for iterator of features from vector data provider or vector layer.
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
Base class for providing feedback from a processing algorithm.
static QgsGeometry fromPolyline(const QgsPolyline &polyline)
Creates a new LineString geometry from a list of QgsPoint points.
QVector< QgsPoint > QgsPolyline
Polyline as represented as a vector of points.
Definition: qgsgeometry.h:69
QgsVertexId vertexId() const
Returns vertex ID of the current item.
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:63
Multi line string geometry collection.
Container of fields for a vector layer.
Definition: qgsfields.h:42
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:111
void setAttributes(const QgsAttributes &attrs)
Sets the feature&#39;s attributes.
Definition: qgsfeature.cpp:127
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:62
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:190
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:768
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
Definition: MathUtils.cpp:786
A feature sink output for processing algorithms.
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:67
static Type addM(Type type)
Adds the m dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:889
An enum based parameter for processing algorithms, allowing for selection from predefined values...
Utility class for identifying a unique vertex within a geometry.
vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry...
static Type addZ(Type type)
Adds the z dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:864
Custom exception class for processing related exceptions.
Definition: qgsexception.h:82
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Append a field. The field must have unique name, otherwise it is rejected (returns false) ...
Definition: qgsfields.cpp:59
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:48
QgsGeometry geometry() const
Returns the geometry associated with this feature.
Definition: qgsfeature.cpp:101
The vertex_iterator class provides STL-style iterator for vertices.
QgsPoint project(double distance, double azimuth, double inclination=90.0) const
Returns a new point which correspond to this point projected by a specified distance with specified a...
Definition: qgspoint.cpp:662
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
A numeric parameter for processing algorithms.
int numGeometries() const
Returns the number of geometries within the collection.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
An input feature source (such as vector layers) parameter for processing algorithms.
double vertexAngle(QgsVertexId vertex) const override
Returns approximate angle at a vertex.
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:41
Vector line layers.
Definition: qgsprocessing.h:50
void setGeometry(const QgsGeometry &geometry)
Set the feature&#39;s geometry.
Definition: qgsfeature.cpp:137
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:818
vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
bool nextFeature(QgsFeature &f)
A vector of attributes.
Definition: qgsattributes.h:58
Contains information about the context in which a processing algorithm is executed.
QgsAttributes attributes
Definition: qgsfeature.h:72