Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgsmultipolygon.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 "qgsmultipolygon.h" 17 : : #include "qgsapplication.h" 18 : : #include "qgsgeometryutils.h" 19 : : #include "qgssurface.h" 20 : : #include "qgslinestring.h" 21 : : #include "qgspolygon.h" 22 : : #include "qgscurvepolygon.h" 23 : : #include "qgsmultilinestring.h" 24 : : 25 : : #include <QJsonObject> 26 : : #include <nlohmann/json.hpp> 27 : : 28 : 1285 : QgsMultiPolygon::QgsMultiPolygon() 29 : 2570 : { 30 : 1285 : mWkbType = QgsWkbTypes::MultiPolygon; 31 : 1285 : } 32 : : 33 : 0 : QgsPolygon *QgsMultiPolygon::polygonN( int index ) 34 : : { 35 : 0 : return qgsgeometry_cast< QgsPolygon * >( geometryN( index ) ); 36 : : } 37 : : 38 : 2 : const QgsPolygon *QgsMultiPolygon::polygonN( int index ) const 39 : : { 40 : 2 : return qgsgeometry_cast< const QgsPolygon * >( geometryN( index ) ); 41 : : } 42 : : 43 : 20 : QString QgsMultiPolygon::geometryType() const 44 : : { 45 : 40 : return QStringLiteral( "MultiPolygon" ); 46 : : } 47 : : 48 : 38 : void QgsMultiPolygon::clear() 49 : : { 50 : 38 : QgsMultiSurface::clear(); 51 : 38 : mWkbType = QgsWkbTypes::MultiPolygon; 52 : 38 : } 53 : : 54 : 1 : QgsMultiPolygon *QgsMultiPolygon::createEmptyWithSameType() const 55 : : { 56 : 1 : auto result = std::make_unique< QgsMultiPolygon >(); 57 : 1 : result->mWkbType = mWkbType; 58 : 1 : return result.release(); 59 : 1 : } 60 : : 61 : 57 : QgsMultiPolygon *QgsMultiPolygon::clone() const 62 : : { 63 : 57 : return new QgsMultiPolygon( *this ); 64 : 0 : } 65 : : 66 : 22 : bool QgsMultiPolygon::fromWkt( const QString &wkt ) 67 : : { 68 : 44 : return fromCollectionWkt( wkt, QVector<QgsAbstractGeometry *>() << new QgsPolygon, QStringLiteral( "Polygon" ) ); 69 : 0 : } 70 : : 71 : 3 : QDomElement QgsMultiPolygon::asGml2( QDomDocument &doc, int precision, const QString &ns, const AxisOrder axisOrder ) const 72 : : { 73 : : // GML2 does not support curves 74 : 6 : QDomElement elemMultiPolygon = doc.createElementNS( ns, QStringLiteral( "MultiPolygon" ) ); 75 : : 76 : 3 : if ( isEmpty() ) 77 : 1 : return elemMultiPolygon; 78 : : 79 : 6 : for ( const QgsAbstractGeometry *geom : mGeometries ) 80 : : { 81 : 4 : if ( qgsgeometry_cast<const QgsPolygon *>( geom ) ) 82 : : { 83 : 8 : QDomElement elemPolygonMember = doc.createElementNS( ns, QStringLiteral( "polygonMember" ) ); 84 : 4 : elemPolygonMember.appendChild( geom->asGml2( doc, precision, ns, axisOrder ) ); 85 : 4 : elemMultiPolygon.appendChild( elemPolygonMember ); 86 : 4 : } 87 : : } 88 : : 89 : 2 : return elemMultiPolygon; 90 : 3 : } 91 : : 92 : 3 : QDomElement QgsMultiPolygon::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const 93 : : { 94 : 6 : QDomElement elemMultiSurface = doc.createElementNS( ns, QStringLiteral( "MultiPolygon" ) ); 95 : : 96 : 3 : if ( isEmpty() ) 97 : 1 : return elemMultiSurface; 98 : : 99 : 6 : for ( const QgsAbstractGeometry *geom : mGeometries ) 100 : : { 101 : 4 : if ( qgsgeometry_cast<const QgsPolygon *>( geom ) ) 102 : : { 103 : 8 : QDomElement elemSurfaceMember = doc.createElementNS( ns, QStringLiteral( "polygonMember" ) ); 104 : 4 : elemSurfaceMember.appendChild( geom->asGml3( doc, precision, ns, axisOrder ) ); 105 : 4 : elemMultiSurface.appendChild( elemSurfaceMember ); 106 : 4 : } 107 : : } 108 : : 109 : 2 : return elemMultiSurface; 110 : 3 : } 111 : : 112 : 4 : json QgsMultiPolygon::asJsonObject( int precision ) const 113 : : { 114 : 4 : json polygons( json::array( ) ); 115 : 13 : for ( const QgsAbstractGeometry *geom : std::as_const( mGeometries ) ) 116 : : { 117 : 9 : if ( qgsgeometry_cast<const QgsPolygon *>( geom ) ) 118 : : { 119 : 9 : json coordinates( json::array( ) ); 120 : 9 : const QgsPolygon *polygon = static_cast<const QgsPolygon *>( geom ); 121 : : 122 : 9 : std::unique_ptr< QgsLineString > exteriorLineString( polygon->exteriorRing()->curveToLine() ); 123 : 9 : QgsPointSequence exteriorPts; 124 : 9 : exteriorLineString->points( exteriorPts ); 125 : 9 : coordinates.push_back( QgsGeometryUtils::pointsToJson( exteriorPts, precision ) ); 126 : : 127 : 9 : std::unique_ptr< QgsLineString > interiorLineString; 128 : 10 : for ( int i = 0, n = polygon->numInteriorRings(); i < n; ++i ) 129 : : { 130 : 1 : interiorLineString.reset( polygon->interiorRing( i )->curveToLine() ); 131 : 1 : QgsPointSequence interiorPts; 132 : 1 : interiorLineString->points( interiorPts ); 133 : 1 : coordinates.push_back( QgsGeometryUtils::pointsToJson( interiorPts, precision ) ); 134 : 1 : } 135 : 9 : polygons.push_back( coordinates ); 136 : 9 : } 137 : : } 138 : 16 : return 139 : 12 : { 140 : 4 : { "type", "MultiPolygon" }, 141 : 4 : { "coordinates", polygons } 142 : : }; 143 : 4 : } 144 : : 145 : 967 : bool QgsMultiPolygon::addGeometry( QgsAbstractGeometry *g ) 146 : : { 147 : 967 : if ( !qgsgeometry_cast<QgsPolygon *>( g ) ) 148 : : { 149 : 2 : delete g; 150 : 2 : return false; 151 : : } 152 : : 153 : 965 : if ( mGeometries.empty() ) 154 : : { 155 : 857 : setZMTypeFromSubGeometry( g, QgsWkbTypes::MultiPolygon ); 156 : 857 : } 157 : 965 : if ( is3D() && !g->is3D() ) 158 : 4 : g->addZValue(); 159 : 961 : else if ( !is3D() && g->is3D() ) 160 : 2 : g->dropZValue(); 161 : 965 : if ( isMeasure() && !g->isMeasure() ) 162 : 4 : g->addMValue(); 163 : 961 : else if ( !isMeasure() && g->isMeasure() ) 164 : 2 : g->dropMValue(); 165 : : 166 : 965 : return QgsGeometryCollection::addGeometry( g ); // clazy:exclude=skipped-base-method 167 : 967 : } 168 : : 169 : 5 : bool QgsMultiPolygon::insertGeometry( QgsAbstractGeometry *g, int index ) 170 : : { 171 : 5 : if ( !g || !qgsgeometry_cast< QgsPolygon * >( g ) ) 172 : : { 173 : 4 : delete g; 174 : 4 : return false; 175 : : } 176 : : 177 : 1 : return QgsMultiSurface::insertGeometry( g, index ); 178 : 5 : } 179 : : 180 : 1 : QgsMultiSurface *QgsMultiPolygon::toCurveType() const 181 : : { 182 : 1 : QgsMultiSurface *multiSurface = new QgsMultiSurface(); 183 : 1 : multiSurface->reserve( mGeometries.size() ); 184 : 3 : for ( int i = 0; i < mGeometries.size(); ++i ) 185 : : { 186 : 2 : multiSurface->addGeometry( mGeometries.at( i )->clone() ); 187 : 2 : } 188 : 1 : return multiSurface; 189 : 0 : } 190 : : 191 : 3 : QgsAbstractGeometry *QgsMultiPolygon::boundary() const 192 : : { 193 : 3 : std::unique_ptr< QgsMultiLineString > multiLine( new QgsMultiLineString() ); 194 : 3 : multiLine->reserve( mGeometries.size() ); 195 : 6 : for ( int i = 0; i < mGeometries.size(); ++i ) 196 : : { 197 : 3 : if ( QgsPolygon *polygon = qgsgeometry_cast<QgsPolygon *>( mGeometries.at( i ) ) ) 198 : : { 199 : 3 : QgsAbstractGeometry *polygonBoundary = polygon->boundary(); 200 : : 201 : 3 : if ( QgsLineString *lineStringBoundary = qgsgeometry_cast< QgsLineString * >( polygonBoundary ) ) 202 : : { 203 : 2 : multiLine->addGeometry( lineStringBoundary ); 204 : 2 : } 205 : 1 : else if ( QgsMultiLineString *multiLineStringBoundary = qgsgeometry_cast< QgsMultiLineString * >( polygonBoundary ) ) 206 : : { 207 : 4 : for ( int j = 0; j < multiLineStringBoundary->numGeometries(); ++j ) 208 : : { 209 : 3 : multiLine->addGeometry( multiLineStringBoundary->geometryN( j )->clone() ); 210 : 3 : } 211 : 1 : delete multiLineStringBoundary; 212 : 1 : } 213 : : else 214 : : { 215 : 0 : delete polygonBoundary; 216 : : } 217 : 3 : } 218 : 3 : } 219 : 3 : if ( multiLine->numGeometries() == 0 ) 220 : : { 221 : 1 : return nullptr; 222 : : } 223 : 2 : return multiLine.release(); 224 : 3 : } 225 : : 226 : 14 : bool QgsMultiPolygon::wktOmitChildType() const 227 : : { 228 : 14 : return true; 229 : : }