1 /***************************************************************************
2                         qgsmultilinestring.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 "qgsmultilinestring.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 "qgsmulticurve.h"
24 
25 #include <nlohmann/json.hpp>
26 #include <QJsonObject>
27 
QgsMultiLineString()28 QgsMultiLineString::QgsMultiLineString()
29 {
30   mWkbType = QgsWkbTypes::MultiLineString;
31 }
32 
lineStringN(int index)33 QgsLineString *QgsMultiLineString::lineStringN( int index )
34 {
35   return qgsgeometry_cast< QgsLineString * >( geometryN( index ) );
36 }
37 
lineStringN(int index) const38 const QgsLineString *QgsMultiLineString::lineStringN( int index ) const
39 {
40   return qgsgeometry_cast< const QgsLineString * >( geometryN( index ) );
41 }
42 
geometryType() const43 QString QgsMultiLineString::geometryType() const
44 {
45   return QStringLiteral( "MultiLineString" );
46 }
47 
createEmptyWithSameType() const48 QgsMultiLineString *QgsMultiLineString::createEmptyWithSameType() const
49 {
50   auto result = qgis::make_unique< QgsMultiLineString >();
51   result->mWkbType = mWkbType;
52   return result.release();
53 }
54 
clone() const55 QgsMultiLineString *QgsMultiLineString::clone() const
56 {
57   return new QgsMultiLineString( *this );
58 }
59 
clear()60 void QgsMultiLineString::clear()
61 {
62   QgsMultiCurve::clear();
63   mWkbType = QgsWkbTypes::MultiLineString;
64 }
65 
fromWkt(const QString & wkt)66 bool QgsMultiLineString::fromWkt( const QString &wkt )
67 {
68   return fromCollectionWkt( wkt, QVector<QgsAbstractGeometry *>() << new QgsLineString, QStringLiteral( "LineString" ) );
69 }
70 
asGml2(QDomDocument & doc,int precision,const QString & ns,const AxisOrder axisOrder) const71 QDomElement QgsMultiLineString::asGml2( QDomDocument &doc, int precision, const QString &ns, const AxisOrder axisOrder ) const
72 {
73   QDomElement elemMultiLineString = doc.createElementNS( ns, QStringLiteral( "MultiLineString" ) );
74 
75   if ( isEmpty() )
76     return elemMultiLineString;
77 
78   for ( const QgsAbstractGeometry *geom : mGeometries )
79   {
80     if ( const QgsLineString *lineString = qgsgeometry_cast<const QgsLineString *>( geom ) )
81     {
82       QDomElement elemLineStringMember = doc.createElementNS( ns, QStringLiteral( "lineStringMember" ) );
83       elemLineStringMember.appendChild( lineString->asGml2( doc, precision, ns, axisOrder ) );
84       elemMultiLineString.appendChild( elemLineStringMember );
85     }
86   }
87 
88   return elemMultiLineString;
89 }
90 
asGml3(QDomDocument & doc,int precision,const QString & ns,const QgsAbstractGeometry::AxisOrder axisOrder) const91 QDomElement QgsMultiLineString::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
92 {
93   QDomElement elemMultiCurve = doc.createElementNS( ns, QStringLiteral( "MultiCurve" ) );
94 
95   if ( isEmpty() )
96     return elemMultiCurve;
97 
98   for ( const QgsAbstractGeometry *geom : mGeometries )
99   {
100     if ( const QgsLineString *lineString = qgsgeometry_cast<const QgsLineString *>( geom ) )
101     {
102       QDomElement elemCurveMember = doc.createElementNS( ns, QStringLiteral( "curveMember" ) );
103       elemCurveMember.appendChild( lineString->asGml3( doc, precision, ns, axisOrder ) );
104       elemMultiCurve.appendChild( elemCurveMember );
105     }
106   }
107 
108   return elemMultiCurve;
109 }
110 
asJsonObject(int precision) const111 json QgsMultiLineString::asJsonObject( int precision ) const
112 {
113   json coordinates( json::array( ) );
114   for ( const QgsAbstractGeometry *geom : mGeometries )
115   {
116     if ( qgsgeometry_cast<const QgsCurve *>( geom ) )
117     {
118       const QgsLineString *lineString = static_cast<const QgsLineString *>( geom );
119       QgsPointSequence pts;
120       lineString->points( pts );
121       coordinates.push_back( QgsGeometryUtils::pointsToJson( pts, precision ) );
122     }
123   }
124   return
125   {
126     { "type",  "MultiLineString" },
127     { "coordinates", coordinates }
128   };
129 }
130 
addGeometry(QgsAbstractGeometry * g)131 bool QgsMultiLineString::addGeometry( QgsAbstractGeometry *g )
132 {
133   if ( !dynamic_cast<QgsLineString *>( g ) )
134   {
135     delete g;
136     return false;
137   }
138 
139   if ( mGeometries.empty() )
140   {
141     setZMTypeFromSubGeometry( g, QgsWkbTypes::MultiLineString );
142   }
143   if ( is3D() && !g->is3D() )
144     g->addZValue();
145   else if ( !is3D() && g->is3D() )
146     g->dropZValue();
147   if ( isMeasure() && !g->isMeasure() )
148     g->addMValue();
149   else if ( !isMeasure() && g->isMeasure() )
150     g->dropMValue();
151   return QgsGeometryCollection::addGeometry( g ); // clazy:exclude=skipped-base-method
152 }
153 
insertGeometry(QgsAbstractGeometry * g,int index)154 bool QgsMultiLineString::insertGeometry( QgsAbstractGeometry *g, int index )
155 {
156   if ( !g || QgsWkbTypes::flatType( g->wkbType() ) != QgsWkbTypes::LineString )
157   {
158     delete g;
159     return false;
160   }
161 
162   return QgsMultiCurve::insertGeometry( g, index ); // clazy:exclude=skipped-base-method
163 }
164 
toCurveType() const165 QgsMultiCurve *QgsMultiLineString::toCurveType() const
166 {
167   QgsMultiCurve *multiCurve = new QgsMultiCurve();
168   multiCurve->reserve( mGeometries.size() );
169   for ( int i = 0; i < mGeometries.size(); ++i )
170   {
171     multiCurve->addGeometry( mGeometries.at( i )->toCurveType() );
172   }
173   return multiCurve;
174 }
175 
wktOmitChildType() const176 bool QgsMultiLineString::wktOmitChildType() const
177 {
178   return true;
179 }
180 
181