QGIS API Documentation 3.99.0-Master (09f76ad7019)
Loading...
Searching...
No Matches
qgsmultilinestring.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmultilinestring.cpp
3 -------------------------------------------------------------------
4Date : 28 Oct 2014
5Copyright : (C) 2014 by Marco Hugentobler
6email : marco.hugentobler at sourcepole dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgsmultilinestring.h"
17
18#include <nlohmann/json.hpp>
19
20#include "qgsabstractgeometry.h"
21#include "qgscurve.h"
22#include "qgsgeometryutils.h"
23#include "qgslinestring.h"
24#include "qgsmulticurve.h"
25
26#include <QJsonObject>
27#include <QString>
28
29using namespace Qt::StringLiterals;
30
35
36QgsMultiLineString::QgsMultiLineString( const QList<QgsLineString> &linestrings )
37{
38 if ( linestrings.empty() )
39 return;
40
41 mGeometries.reserve( linestrings.size() );
42 for ( const QgsLineString &line : linestrings )
43 {
44 mGeometries.append( line.clone() );
45 }
46
48}
49
50QgsMultiLineString::QgsMultiLineString( const QList<QgsLineString *> &linestrings )
51{
52 if ( linestrings.empty() )
53 return;
54
55 mGeometries.reserve( linestrings.size() );
56 for ( QgsLineString *line : linestrings )
57 {
58 mGeometries.append( line );
59 }
60
62}
63
68
73
75{
76 return u"MultiLineString"_s;
77}
78
80{
81 auto result = std::make_unique< QgsMultiLineString >();
82 result->mWkbType = mWkbType;
83 return result.release();
84}
85
87{
88 return new QgsMultiLineString( *this );
89}
90
96
97bool QgsMultiLineString::fromWkt( const QString &wkt )
98{
99 return fromCollectionWkt( wkt, {Qgis::WkbType::LineString }, u"LineString"_s );
100}
101
102QDomElement QgsMultiLineString::asGml2( QDomDocument &doc, int precision, const QString &ns, const AxisOrder axisOrder ) const
103{
104 QDomElement elemMultiLineString = doc.createElementNS( ns, u"MultiLineString"_s );
105
106 if ( isEmpty() )
107 return elemMultiLineString;
108
109 for ( const QgsAbstractGeometry *geom : mGeometries )
110 {
111 if ( const QgsLineString *lineString = qgsgeometry_cast<const QgsLineString *>( geom ) )
112 {
113 QDomElement elemLineStringMember = doc.createElementNS( ns, u"lineStringMember"_s );
114 elemLineStringMember.appendChild( lineString->asGml2( doc, precision, ns, axisOrder ) );
115 elemMultiLineString.appendChild( elemLineStringMember );
116 }
117 }
118
119 return elemMultiLineString;
120}
121
122QDomElement QgsMultiLineString::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
123{
124 QDomElement elemMultiCurve = doc.createElementNS( ns, u"MultiCurve"_s );
125
126 if ( isEmpty() )
127 return elemMultiCurve;
128
129 for ( const QgsAbstractGeometry *geom : mGeometries )
130 {
131 if ( const QgsLineString *lineString = qgsgeometry_cast<const QgsLineString *>( geom ) )
132 {
133 QDomElement elemCurveMember = doc.createElementNS( ns, u"curveMember"_s );
134 elemCurveMember.appendChild( lineString->asGml3( doc, precision, ns, axisOrder ) );
135 elemMultiCurve.appendChild( elemCurveMember );
136 }
137 }
138
139 return elemMultiCurve;
140}
141
142json QgsMultiLineString::asJsonObject( int precision ) const
143{
144 json coordinates( json::array( ) );
145 for ( const QgsAbstractGeometry *geom : mGeometries )
146 {
148 {
149 const QgsLineString *lineString = static_cast<const QgsLineString *>( geom );
151 lineString->points( pts );
152 coordinates.push_back( QgsGeometryUtils::pointsToJson( pts, precision ) );
153 }
154 }
155 return
156 {
157 { "type", "MultiLineString" },
158 { "coordinates", coordinates }
159 };
160}
161
163{
164 if ( !dynamic_cast<QgsLineString *>( g ) )
165 {
166 delete g;
167 return false;
168 }
169
170 if ( mGeometries.empty() )
171 {
173 }
174 if ( is3D() && !g->is3D() )
175 g->addZValue();
176 else if ( !is3D() && g->is3D() )
177 g->dropZValue();
178 if ( isMeasure() && !g->isMeasure() )
179 g->addMValue();
180 else if ( !isMeasure() && g->isMeasure() )
181 g->dropMValue();
182 return QgsGeometryCollection::addGeometry( g ); // NOLINT(bugprone-parent-virtual-call) clazy:exclude=skipped-base-method
183}
184
185bool QgsMultiLineString::addGeometries( const QVector<QgsAbstractGeometry *> &geometries )
186{
187 for ( QgsAbstractGeometry *g : geometries )
188 {
190 {
191 qDeleteAll( geometries );
192 return false;
193 }
194 }
195
196 if ( mGeometries.empty() && !geometries.empty() )
197 {
199 }
200 mGeometries.reserve( mGeometries.size() + geometries.size() );
201 for ( QgsAbstractGeometry *g : geometries )
202 {
203 if ( is3D() && !g->is3D() )
204 g->addZValue();
205 else if ( !is3D() && g->is3D() )
206 g->dropZValue();
207 if ( isMeasure() && !g->isMeasure() )
208 g->addMValue();
209 else if ( !isMeasure() && g->isMeasure() )
210 g->dropMValue();
211 mGeometries.append( g );
212 }
213
214 clearCache();
215 return true;
216}
217
219{
221 {
222 delete g;
223 return false;
224 }
225
226 return QgsMultiCurve::insertGeometry( g, index );
227}
228
230{
231 auto result = std::make_unique< QgsMultiLineString >();
232 result->reserve( mGeometries.size() );
233 for ( int i = 0; i < mGeometries.size(); ++i )
234 {
235 result->addGeometry( mGeometries.at( i )->simplifyByDistance( tolerance ) );
236 }
237 return result.release();
238}
239
241{
242 QgsMultiCurve *multiCurve = new QgsMultiCurve();
243 multiCurve->reserve( mGeometries.size() );
244 for ( int i = 0; i < mGeometries.size(); ++i )
245 {
246 multiCurve->addGeometry( mGeometries.at( i )->toCurveType() );
247 }
248 return multiCurve;
249}
250
252{
253 return true;
254}
255
256QgsMultiLineString *QgsMultiLineString::measuredLine( double start, double end ) const
257{
258 auto result = std::make_unique< QgsMultiLineString >();
259 if ( isEmpty() )
260 {
261 result->convertTo( QgsWkbTypes::addM( mWkbType ) );
262 return result.release();
263 }
264
265 /* Calculate the total length of the line */
266 const double length{this->length()};
267 const double range{end - start};
268 double lengthSoFar{0.0};
269
270 result->reserve( numGeometries() );
271 for ( int i = 0; i < numGeometries(); i++ )
272 {
273 const double subLength{geometryN( i )->length()};
274
275 const double subStart{ ( start + range *lengthSoFar / length ) };
276 const double subEnd{ ( start + range * ( lengthSoFar + subLength ) / length ) };
277
278 std::unique_ptr< QgsLineString > measuredLine = qgsgeometry_cast<const QgsLineString *>( geometryN( i ) )->measuredLine( subStart, subEnd );
279 result->addGeometry( measuredLine.release() );
280
281 lengthSoFar += subLength;
282 }
283
284 return result.release();
285}
@ LineString
LineString.
Definition qgis.h:283
@ MultiLineString
MultiLineString.
Definition qgis.h:287
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
virtual bool dropMValue()=0
Drops any measure values which exist in the geometry.
bool isMeasure() const
Returns true if the geometry contains m values.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
AxisOrder
Axis order for GML generation.
virtual bool addMValue(double mValue=0)=0
Adds a measure to the geometry, initialized to a preset value.
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
void setZMTypeFromSubGeometry(const QgsAbstractGeometry *subggeom, Qgis::WkbType baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
virtual double length() const
Returns the planar, 2-dimensional length of the geometry.
virtual bool dropZValue()=0
Drops any z-dimensions which exist in the geometry.
QgsAbstractGeometry()=default
QVector< QgsAbstractGeometry * > mGeometries
bool fromCollectionWkt(const QString &wkt, const QVector< Qgis::WkbType > &subtypes, const QString &defaultChildWkbType=QString())
Reads a collection from a WKT string.
void reserve(int size)
Attempts to allocate memory for at least size geometries.
void clearCache() const override
Clears any cached parameters associated with the geometry, e.g., bounding boxes.
bool isEmpty() const override
Returns true if the geometry is empty.
double length() const override
Returns the planar, 2-dimensional length of the geometry.
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
int numGeometries() const
Returns the number of geometries within the collection.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
static json pointsToJson(const QgsPointSequence &points, int precision)
Returns coordinates as json object.
Line string geometry type, with support for z-dimension and m-values.
void points(QgsPointSequence &pt) const override
Returns a list of points within the curve.
bool insertGeometry(QgsAbstractGeometry *g, int index) override
Inserts a geometry before a specified index and takes ownership.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
void clear() override
Clears the geometry, ie reset it to a null geometry.
void clear() override
Clears the geometry, ie reset it to a null geometry.
QString geometryType() const override
Returns a unique string representing the geometry type.
bool addGeometries(const QVector< QgsAbstractGeometry * > &geometries) final
Adds a list of geometries to the collection, transferring ownership to the collection.
QgsMultiCurve * toCurveType() const override
Returns the geometry converted to the more generic curve type QgsMultiCurve.
bool wktOmitChildType() const override
Returns whether child type names are omitted from Wkt representations of the collection.
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
bool insertGeometry(QgsAbstractGeometry *g, int index) override
Inserts a geometry before a specified index and takes ownership.
json asJsonObject(int precision=17) const override
Returns a json object representation of the geometry.
QDomElement asGml3(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const override
Returns a GML3 representation of the geometry.
QgsMultiLineString * measuredLine(double start, double end) const
Re-write the measure ordinate (or add one, if it isn't already there) interpolating the measure betwe...
QgsMultiLineString * clone() const override
Clones the geometry by performing a deep copy.
QgsMultiLineString * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
QgsMultiLineString()
Constructor for an empty multilinestring geometry.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
QgsMultiLineString * simplifyByDistance(double tolerance) const override
Simplifies the geometry by applying the Douglas Peucker simplification by distance algorithm.
QDomElement asGml2(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const override
Returns a GML2 representation of the geometry.
QgsLineString * lineStringN(int index)
Returns the line string with the specified index.
static Qgis::WkbType addM(Qgis::WkbType type)
Adds the m dimension to a WKB type and returns the new type.
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
T qgsgeometry_cast(QgsAbstractGeometry *geom)
QVector< QgsPoint > QgsPointSequence