QGIS API Documentation  3.21.0-Master (909859188c)
qgsmulticurve.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmulticurve.cpp
3  -------------------------------------------------------------------
4 Date : 28 Oct 2014
5 Copyright : (C) 2014 by Marco Hugentobler
6 email : 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 "qgsmulticurve.h"
17 #include "qgsapplication.h"
18 #include "qgscurve.h"
19 #include "qgscircularstring.h"
20 #include "qgscompoundcurve.h"
21 #include "qgsgeometryutils.h"
22 #include "qgslinestring.h"
23 #include "qgsmultipoint.h"
24 
25 #include <QJsonObject>
26 #include <memory>
27 #include <nlohmann/json.hpp>
28 
30 {
32 }
33 
35 {
36  return qgsgeometry_cast< QgsCurve * >( geometryN( index ) );
37 }
38 
39 const QgsCurve *QgsMultiCurve::curveN( int index ) const
40 {
41  return qgsgeometry_cast< const QgsCurve * >( geometryN( index ) );
42 }
43 
45 {
46  return QStringLiteral( "MultiCurve" );
47 }
48 
50 {
51  auto result = std::make_unique< QgsMultiCurve >();
52  result->mWkbType = mWkbType;
53  return result.release();
54 }
55 
57 {
58  return new QgsMultiCurve( *this );
59 }
60 
62 {
65 }
66 
68 {
69  return clone();
70 }
71 
72 bool QgsMultiCurve::fromWkt( const QString &wkt )
73 {
74  return fromCollectionWkt( wkt,
75  QVector<QgsAbstractGeometry *>() << new QgsLineString << new QgsCircularString << new QgsCompoundCurve,
76  QStringLiteral( "LineString" ) );
77 }
78 
79 QDomElement QgsMultiCurve::asGml2( QDomDocument &doc, int precision, const QString &ns, const AxisOrder axisOrder ) const
80 {
81  // GML2 does not support curves
82  QDomElement elemMultiLineString = doc.createElementNS( ns, QStringLiteral( "MultiLineString" ) );
83 
84  if ( isEmpty() )
85  return elemMultiLineString;
86 
87  for ( const QgsAbstractGeometry *geom : mGeometries )
88  {
89  if ( qgsgeometry_cast<const QgsCurve *>( geom ) )
90  {
91  std::unique_ptr< QgsLineString > lineString( static_cast<const QgsCurve *>( geom )->curveToLine() );
92 
93  QDomElement elemLineStringMember = doc.createElementNS( ns, QStringLiteral( "lineStringMember" ) );
94  elemLineStringMember.appendChild( lineString->asGml2( doc, precision, ns, axisOrder ) );
95  elemMultiLineString.appendChild( elemLineStringMember );
96  }
97  }
98 
99  return elemMultiLineString;
100 }
101 
102 QDomElement QgsMultiCurve::asGml3( QDomDocument &doc, int precision, const QString &ns, const AxisOrder axisOrder ) const
103 {
104  QDomElement elemMultiCurve = doc.createElementNS( ns, QStringLiteral( "MultiCurve" ) );
105 
106  if ( isEmpty() )
107  return elemMultiCurve;
108 
109  for ( const QgsAbstractGeometry *geom : mGeometries )
110  {
111  if ( qgsgeometry_cast<const QgsCurve *>( geom ) )
112  {
113  const QgsCurve *curve = static_cast<const QgsCurve *>( geom );
114 
115  QDomElement elemCurveMember = doc.createElementNS( ns, QStringLiteral( "curveMember" ) );
116  elemCurveMember.appendChild( curve->asGml3( doc, precision, ns, axisOrder ) );
117  elemMultiCurve.appendChild( elemCurveMember );
118  }
119  }
120 
121  return elemMultiCurve;
122 }
123 
125 {
126  json coordinates( json::array( ) );
127  for ( const QgsAbstractGeometry *geom : std::as_const( mGeometries ) )
128  {
129  if ( qgsgeometry_cast<const QgsCurve *>( geom ) )
130  {
131  std::unique_ptr< QgsLineString > lineString( static_cast<const QgsCurve *>( geom )->curveToLine() );
132  QgsPointSequence pts;
133  lineString->points( pts );
134  coordinates.push_back( QgsGeometryUtils::pointsToJson( pts, precision ) );
135  }
136  }
137  return
138  {
139  { "type", "MultiLineString" },
140  { "coordinates", coordinates }
141  };
142 }
143 
145 {
146  if ( !qgsgeometry_cast<QgsCurve *>( g ) )
147  {
148  delete g;
149  return false;
150  }
151 
152  if ( mGeometries.empty() )
153  {
155  }
156  if ( is3D() && !g->is3D() )
157  g->addZValue();
158  else if ( !is3D() && g->is3D() )
159  g->dropZValue();
160  if ( isMeasure() && !g->isMeasure() )
161  g->addMValue();
162  else if ( !isMeasure() && g->isMeasure() )
163  g->dropMValue();
164 
166 }
167 
169 {
170  if ( !g || !qgsgeometry_cast<QgsCurve *>( g ) )
171  {
172  delete g;
173  return false;
174  }
175 
176  return QgsGeometryCollection::insertGeometry( g, index );
177 }
178 
180 {
181  QgsMultiCurve *reversedMultiCurve = new QgsMultiCurve();
182  reversedMultiCurve->reserve( mGeometries.size() );
183  for ( const QgsAbstractGeometry *geom : mGeometries )
184  {
185  if ( qgsgeometry_cast<const QgsCurve *>( geom ) )
186  {
187  reversedMultiCurve->addGeometry( static_cast<const QgsCurve *>( geom )->reversed() );
188  }
189  }
190  return reversedMultiCurve;
191 }
192 
194 {
195  std::unique_ptr< QgsMultiPoint > multiPoint( new QgsMultiPoint() );
196  multiPoint->reserve( mGeometries.size() * 2 );
197  for ( int i = 0; i < mGeometries.size(); ++i )
198  {
199  if ( QgsCurve *curve = qgsgeometry_cast<QgsCurve *>( mGeometries.at( i ) ) )
200  {
201  if ( !curve->isClosed() )
202  {
203  multiPoint->addGeometry( new QgsPoint( curve->startPoint() ) );
204  multiPoint->addGeometry( new QgsPoint( curve->endPoint() ) );
205  }
206  }
207  }
208  if ( multiPoint->numGeometries() == 0 )
209  {
210  return nullptr;
211  }
212  return multiPoint.release();
213 }
Abstract base class for all geometries.
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 is3D() const SIP_HOLDGIL
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.
virtual QDomElement asGml3(QDomDocument &doc, int precision=17, const QString &ns="gml", AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const =0
Returns a GML3 representation of the geometry.
virtual bool dropZValue()=0
Drops any z-dimensions which exist in the geometry.
QgsWkbTypes::Type mWkbType
bool isMeasure() const SIP_HOLDGIL
Returns true if the geometry contains m values.
void setZMTypeFromSubGeometry(const QgsAbstractGeometry *subggeom, QgsWkbTypes::Type baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
Circular string geometry type.
Compound curve geometry type.
Abstract base class for curved geometry type.
Definition: qgscurve.h:36
bool isEmpty() const override SIP_HOLDGIL
Returns true if the geometry is empty.
QVector< QgsAbstractGeometry * > mGeometries
void clear() override
Clears the geometry, ie reset it to a null geometry.
virtual bool insertGeometry(QgsAbstractGeometry *g, int index)
Inserts a geometry before a specified index and takes ownership.
void reserve(int size) SIP_HOLDGIL
Attempts to allocate memory for at least size geometries.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
bool fromCollectionWkt(const QString &wkt, const QVector< QgsAbstractGeometry * > &subtypes, const QString &defaultChildWkbType=QString())
Reads a collection from a WKT string.
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.
Definition: qgslinestring.h:44
Multi curve geometry collection.
Definition: qgsmulticurve.h:30
QgsMultiCurve * reversed() const
Returns a copy of the multi curve, where each component curve has had its line direction reversed.
QString geometryType() const override SIP_HOLDGIL
Returns a unique string representing the geometry type.
json asJsonObject(int precision=17) const override
Returns a json object representation of the geometry.
QgsMultiCurve * toCurveType() const override
Returns the geometry converted to the more generic curve type.
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.
QgsAbstractGeometry * boundary() const override
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
bool insertGeometry(QgsAbstractGeometry *g, int index) override
Inserts a geometry before a specified index and takes ownership.
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.
QgsMultiCurve * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
QgsMultiCurve * clone() const override
Clones the geometry by performing a deep copy.
void clear() override
Clears the geometry, ie reset it to a null geometry.
QgsCurve * curveN(int index)
Returns the curve with the specified index.
Multi point geometry collection.
Definition: qgsmultipoint.h:30
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
QVector< QgsPoint > QgsPointSequence
int precision