Branch data Line data Source code
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 : : 29 : 1509 : QgsMultiCurve::QgsMultiCurve() 30 : 3018 : { 31 : 1509 : mWkbType = QgsWkbTypes::MultiCurve; 32 : 1509 : } 33 : : 34 : 0 : QgsCurve *QgsMultiCurve::curveN( int index ) 35 : : { 36 : 0 : return qgsgeometry_cast< QgsCurve * >( geometryN( index ) ); 37 : : } 38 : : 39 : 0 : const QgsCurve *QgsMultiCurve::curveN( int index ) const 40 : : { 41 : 0 : return qgsgeometry_cast< const QgsCurve * >( geometryN( index ) ); 42 : : } 43 : : 44 : 414 : QString QgsMultiCurve::geometryType() const 45 : : { 46 : 828 : return QStringLiteral( "MultiCurve" ); 47 : : } 48 : : 49 : 1 : QgsMultiCurve *QgsMultiCurve::createEmptyWithSameType() const 50 : : { 51 : 1 : auto result = std::make_unique< QgsMultiCurve >(); 52 : 1 : result->mWkbType = mWkbType; 53 : 1 : return result.release(); 54 : 1 : } 55 : : 56 : 3 : QgsMultiCurve *QgsMultiCurve::clone() const 57 : : { 58 : 3 : return new QgsMultiCurve( *this ); 59 : 0 : } 60 : : 61 : 868 : void QgsMultiCurve::clear() 62 : : { 63 : 868 : QgsGeometryCollection::clear(); 64 : 868 : mWkbType = QgsWkbTypes::MultiCurve; 65 : 868 : } 66 : : 67 : 1 : QgsMultiCurve *QgsMultiCurve::toCurveType() const 68 : : { 69 : 1 : return clone(); 70 : : } 71 : : 72 : 411 : bool QgsMultiCurve::fromWkt( const QString &wkt ) 73 : : { 74 : 822 : return fromCollectionWkt( wkt, 75 : 411 : QVector<QgsAbstractGeometry *>() << new QgsLineString << new QgsCircularString << new QgsCompoundCurve, 76 : 822 : QStringLiteral( "LineString" ) ); 77 : 0 : } 78 : : 79 : 3 : QDomElement QgsMultiCurve::asGml2( QDomDocument &doc, int precision, const QString &ns, const AxisOrder axisOrder ) const 80 : : { 81 : : // GML2 does not support curves 82 : 6 : QDomElement elemMultiLineString = doc.createElementNS( ns, QStringLiteral( "MultiLineString" ) ); 83 : : 84 : 3 : if ( isEmpty() ) 85 : 1 : return elemMultiLineString; 86 : : 87 : 6 : for ( const QgsAbstractGeometry *geom : mGeometries ) 88 : : { 89 : 4 : if ( qgsgeometry_cast<const QgsCurve *>( geom ) ) 90 : : { 91 : 4 : std::unique_ptr< QgsLineString > lineString( static_cast<const QgsCurve *>( geom )->curveToLine() ); 92 : : 93 : 8 : QDomElement elemLineStringMember = doc.createElementNS( ns, QStringLiteral( "lineStringMember" ) ); 94 : 4 : elemLineStringMember.appendChild( lineString->asGml2( doc, precision, ns, axisOrder ) ); 95 : 4 : elemMultiLineString.appendChild( elemLineStringMember ); 96 : 4 : } 97 : : } 98 : : 99 : 2 : return elemMultiLineString; 100 : 3 : } 101 : : 102 : 3 : QDomElement QgsMultiCurve::asGml3( QDomDocument &doc, int precision, const QString &ns, const AxisOrder axisOrder ) const 103 : : { 104 : 6 : QDomElement elemMultiCurve = doc.createElementNS( ns, QStringLiteral( "MultiCurve" ) ); 105 : : 106 : 3 : if ( isEmpty() ) 107 : 1 : return elemMultiCurve; 108 : : 109 : 6 : for ( const QgsAbstractGeometry *geom : mGeometries ) 110 : : { 111 : 4 : if ( qgsgeometry_cast<const QgsCurve *>( geom ) ) 112 : : { 113 : 4 : const QgsCurve *curve = static_cast<const QgsCurve *>( geom ); 114 : : 115 : 8 : QDomElement elemCurveMember = doc.createElementNS( ns, QStringLiteral( "curveMember" ) ); 116 : 4 : elemCurveMember.appendChild( curve->asGml3( doc, precision, ns, axisOrder ) ); 117 : 4 : elemMultiCurve.appendChild( elemCurveMember ); 118 : 4 : } 119 : : } 120 : : 121 : 2 : return elemMultiCurve; 122 : 3 : } 123 : : 124 : 3 : json QgsMultiCurve::asJsonObject( int precision ) const 125 : : { 126 : 3 : json coordinates( json::array( ) ); 127 : 7 : for ( const QgsAbstractGeometry *geom : std::as_const( mGeometries ) ) 128 : : { 129 : 4 : if ( qgsgeometry_cast<const QgsCurve *>( geom ) ) 130 : : { 131 : 4 : std::unique_ptr< QgsLineString > lineString( static_cast<const QgsCurve *>( geom )->curveToLine() ); 132 : 4 : QgsPointSequence pts; 133 : 4 : lineString->points( pts ); 134 : 4 : coordinates.push_back( QgsGeometryUtils::pointsToJson( pts, precision ) ); 135 : 4 : } 136 : : } 137 : 12 : return 138 : 9 : { 139 : 3 : { "type", "MultiLineString" }, 140 : 3 : { "coordinates", coordinates } 141 : : }; 142 : 3 : } 143 : : 144 : 69 : bool QgsMultiCurve::addGeometry( QgsAbstractGeometry *g ) 145 : : { 146 : 69 : if ( !qgsgeometry_cast<QgsCurve *>( g ) ) 147 : : { 148 : 2 : delete g; 149 : 2 : return false; 150 : : } 151 : : 152 : 67 : if ( mGeometries.empty() ) 153 : : { 154 : 33 : setZMTypeFromSubGeometry( g, QgsWkbTypes::MultiCurve ); 155 : 33 : } 156 : 67 : if ( is3D() && !g->is3D() ) 157 : 4 : g->addZValue(); 158 : 63 : else if ( !is3D() && g->is3D() ) 159 : 2 : g->dropZValue(); 160 : 67 : if ( isMeasure() && !g->isMeasure() ) 161 : 4 : g->addMValue(); 162 : 63 : else if ( !isMeasure() && g->isMeasure() ) 163 : 2 : g->dropMValue(); 164 : : 165 : 67 : return QgsGeometryCollection::addGeometry( g ); 166 : 69 : } 167 : : 168 : 6 : bool QgsMultiCurve::insertGeometry( QgsAbstractGeometry *g, int index ) 169 : : { 170 : 6 : if ( !g || !qgsgeometry_cast<QgsCurve *>( g ) ) 171 : : { 172 : 4 : delete g; 173 : 4 : return false; 174 : : } 175 : : 176 : 2 : return QgsGeometryCollection::insertGeometry( g, index ); 177 : 6 : } 178 : : 179 : 2 : QgsMultiCurve *QgsMultiCurve::reversed() const 180 : : { 181 : 2 : QgsMultiCurve *reversedMultiCurve = new QgsMultiCurve(); 182 : 2 : reversedMultiCurve->reserve( mGeometries.size() ); 183 : 4 : for ( const QgsAbstractGeometry *geom : mGeometries ) 184 : : { 185 : 2 : if ( qgsgeometry_cast<const QgsCurve *>( geom ) ) 186 : : { 187 : 2 : reversedMultiCurve->addGeometry( static_cast<const QgsCurve *>( geom )->reversed() ); 188 : 2 : } 189 : : } 190 : 2 : return reversedMultiCurve; 191 : 0 : } 192 : : 193 : 10 : QgsAbstractGeometry *QgsMultiCurve::boundary() const 194 : : { 195 : 10 : std::unique_ptr< QgsMultiPoint > multiPoint( new QgsMultiPoint() ); 196 : 10 : multiPoint->reserve( mGeometries.size() * 2 ); 197 : 26 : for ( int i = 0; i < mGeometries.size(); ++i ) 198 : : { 199 : 16 : if ( QgsCurve *curve = qgsgeometry_cast<QgsCurve *>( mGeometries.at( i ) ) ) 200 : : { 201 : 16 : if ( !curve->isClosed() ) 202 : : { 203 : 14 : multiPoint->addGeometry( new QgsPoint( curve->startPoint() ) ); 204 : 14 : multiPoint->addGeometry( new QgsPoint( curve->endPoint() ) ); 205 : 14 : } 206 : 16 : } 207 : 16 : } 208 : 10 : if ( multiPoint->numGeometries() == 0 ) 209 : : { 210 : 2 : return nullptr; 211 : : } 212 : 8 : return multiPoint.release(); 213 : 10 : }