Branch data Line data Source code
1 : : 2 : : /*************************************************************************** 3 : : qgsmultisurface.cpp 4 : : ------------------------------------------------------------------- 5 : : Date : 28 Oct 2014 6 : : Copyright : (C) 2014 by Marco Hugentobler 7 : : email : marco.hugentobler at sourcepole dot com 8 : : *************************************************************************** 9 : : * * 10 : : * This program is free software; you can redistribute it and/or modify * 11 : : * it under the terms of the GNU General Public License as published by * 12 : : * the Free Software Foundation; either version 2 of the License, or * 13 : : * (at your option) any later version. * 14 : : * * 15 : : ***************************************************************************/ 16 : : 17 : : #include "qgsmultisurface.h" 18 : : #include "qgsapplication.h" 19 : : #include "qgsgeometryutils.h" 20 : : #include "qgssurface.h" 21 : : #include "qgslinestring.h" 22 : : #include "qgspolygon.h" 23 : : #include "qgscurvepolygon.h" 24 : : #include "qgsmulticurve.h" 25 : : 26 : : #include <QJsonObject> 27 : : #include <nlohmann/json.hpp> 28 : : 29 : 1935 : QgsMultiSurface::QgsMultiSurface() 30 : 3870 : { 31 : 1935 : mWkbType = QgsWkbTypes::MultiSurface; 32 : 1935 : } 33 : : 34 : 0 : QgsSurface *QgsMultiSurface::surfaceN( int index ) 35 : : { 36 : 0 : return qgsgeometry_cast< QgsSurface * >( geometryN( index ) ); 37 : : } 38 : : 39 : 0 : const QgsSurface *QgsMultiSurface::surfaceN( int index ) const 40 : : { 41 : 0 : return qgsgeometry_cast< const QgsSurface * >( geometryN( index ) ); 42 : : } 43 : : 44 : 414 : QString QgsMultiSurface::geometryType() const 45 : : { 46 : 828 : return QStringLiteral( "MultiSurface" ); 47 : : } 48 : : 49 : 465 : void QgsMultiSurface::clear() 50 : : { 51 : 465 : QgsGeometryCollection::clear(); 52 : 465 : mWkbType = QgsWkbTypes::MultiSurface; 53 : 465 : } 54 : : 55 : 1 : QgsMultiSurface *QgsMultiSurface::createEmptyWithSameType() const 56 : : { 57 : 1 : auto result = std::make_unique< QgsMultiSurface >(); 58 : 1 : result->mWkbType = mWkbType; 59 : 1 : return result.release(); 60 : 1 : } 61 : : 62 : 3 : QgsMultiSurface *QgsMultiSurface::clone() const 63 : : { 64 : 3 : return new QgsMultiSurface( *this ); 65 : 0 : } 66 : : 67 : 1 : QgsMultiSurface *QgsMultiSurface::toCurveType() const 68 : : { 69 : 1 : return clone(); 70 : : } 71 : : 72 : 411 : bool QgsMultiSurface::fromWkt( const QString &wkt ) 73 : : { 74 : 822 : return fromCollectionWkt( wkt, 75 : 411 : QVector<QgsAbstractGeometry *>() << new QgsPolygon << new QgsCurvePolygon, 76 : 822 : QStringLiteral( "Polygon" ) ); 77 : 0 : } 78 : : 79 : 3 : QDomElement QgsMultiSurface::asGml2( QDomDocument &doc, int precision, const QString &ns, const AxisOrder axisOrder ) const 80 : : { 81 : : // GML2 does not support curves 82 : 6 : QDomElement elemMultiPolygon = doc.createElementNS( ns, QStringLiteral( "MultiPolygon" ) ); 83 : : 84 : 3 : if ( isEmpty() ) 85 : 1 : return elemMultiPolygon; 86 : : 87 : 5 : for ( const QgsAbstractGeometry *geom : mGeometries ) 88 : : { 89 : 3 : if ( qgsgeometry_cast<const QgsSurface *>( geom ) ) 90 : : { 91 : 3 : std::unique_ptr< QgsPolygon > polygon( static_cast<const QgsSurface *>( geom )->surfaceToPolygon() ); 92 : : 93 : 6 : QDomElement elemPolygonMember = doc.createElementNS( ns, QStringLiteral( "polygonMember" ) ); 94 : 3 : elemPolygonMember.appendChild( polygon->asGml2( doc, precision, ns, axisOrder ) ); 95 : 3 : elemMultiPolygon.appendChild( elemPolygonMember ); 96 : 3 : } 97 : : } 98 : : 99 : 2 : return elemMultiPolygon; 100 : 3 : } 101 : : 102 : 3 : QDomElement QgsMultiSurface::asGml3( QDomDocument &doc, int precision, const QString &ns, const AxisOrder axisOrder ) const 103 : : { 104 : 6 : QDomElement elemMultiSurface = doc.createElementNS( ns, QStringLiteral( "MultiSurface" ) ); 105 : : 106 : 3 : if ( isEmpty() ) 107 : 1 : return elemMultiSurface; 108 : : 109 : 5 : for ( const QgsAbstractGeometry *geom : mGeometries ) 110 : : { 111 : 3 : if ( qgsgeometry_cast<const QgsSurface *>( geom ) ) 112 : : { 113 : 6 : QDomElement elemSurfaceMember = doc.createElementNS( ns, QStringLiteral( "surfaceMember" ) ); 114 : 3 : elemSurfaceMember.appendChild( geom->asGml3( doc, precision, ns, axisOrder ) ); 115 : 3 : elemMultiSurface.appendChild( elemSurfaceMember ); 116 : 3 : } 117 : : } 118 : : 119 : 2 : return elemMultiSurface; 120 : 3 : } 121 : : 122 : : 123 : 4 : json QgsMultiSurface::asJsonObject( int precision ) const 124 : : { 125 : 4 : json polygons( json::array( ) ); 126 : 10 : for ( const QgsAbstractGeometry *geom : std::as_const( mGeometries ) ) 127 : : { 128 : 6 : if ( qgsgeometry_cast<const QgsSurface *>( geom ) ) 129 : : { 130 : 6 : json coordinates( json::array( ) ); 131 : 6 : std::unique_ptr< QgsPolygon >polygon( static_cast<const QgsSurface *>( geom )->surfaceToPolygon() ); 132 : 6 : std::unique_ptr< QgsLineString > exteriorLineString( polygon->exteriorRing()->curveToLine() ); 133 : 6 : QgsPointSequence exteriorPts; 134 : 6 : exteriorLineString->points( exteriorPts ); 135 : 6 : coordinates.push_back( QgsGeometryUtils::pointsToJson( exteriorPts, precision ) ); 136 : : 137 : 6 : std::unique_ptr< QgsLineString > interiorLineString; 138 : 7 : for ( int i = 0, n = polygon->numInteriorRings(); i < n; ++i ) 139 : : { 140 : 1 : interiorLineString.reset( polygon->interiorRing( i )->curveToLine() ); 141 : 1 : QgsPointSequence interiorPts; 142 : 1 : interiorLineString->points( interiorPts ); 143 : 1 : coordinates.push_back( QgsGeometryUtils::pointsToJson( interiorPts, precision ) ); 144 : 1 : } 145 : 6 : polygons.push_back( coordinates ); 146 : 6 : } 147 : : } 148 : 16 : return 149 : 12 : { 150 : 4 : { "type", "MultiPolygon" }, 151 : 4 : { "coordinates", polygons } 152 : : }; 153 : 4 : } 154 : : 155 : 55 : bool QgsMultiSurface::addGeometry( QgsAbstractGeometry *g ) 156 : : { 157 : 55 : if ( !qgsgeometry_cast<QgsSurface *>( g ) ) 158 : : { 159 : 2 : delete g; 160 : 2 : return false; 161 : : } 162 : : 163 : 53 : if ( mGeometries.empty() ) 164 : : { 165 : 26 : setZMTypeFromSubGeometry( g, QgsWkbTypes::MultiSurface ); 166 : 26 : } 167 : 53 : if ( is3D() && !g->is3D() ) 168 : 4 : g->addZValue(); 169 : 49 : else if ( !is3D() && g->is3D() ) 170 : 2 : g->dropZValue(); 171 : 53 : if ( isMeasure() && !g->isMeasure() ) 172 : 4 : g->addMValue(); 173 : 49 : else if ( !isMeasure() && g->isMeasure() ) 174 : 2 : g->dropMValue(); 175 : : 176 : 53 : return QgsGeometryCollection::addGeometry( g ); 177 : 55 : } 178 : : 179 : 6 : bool QgsMultiSurface::insertGeometry( QgsAbstractGeometry *g, int index ) 180 : : { 181 : 6 : if ( !g || !qgsgeometry_cast< QgsSurface * >( g ) ) 182 : : { 183 : 4 : delete g; 184 : 4 : return false; 185 : : } 186 : : 187 : 2 : return QgsGeometryCollection::insertGeometry( g, index ); 188 : 6 : } 189 : : 190 : 4 : QgsAbstractGeometry *QgsMultiSurface::boundary() const 191 : : { 192 : 4 : std::unique_ptr< QgsMultiCurve > multiCurve( new QgsMultiCurve() ); 193 : 4 : multiCurve->reserve( mGeometries.size() ); 194 : 9 : for ( int i = 0; i < mGeometries.size(); ++i ) 195 : : { 196 : 5 : if ( QgsSurface *surface = qgsgeometry_cast<QgsSurface *>( mGeometries.at( i ) ) ) 197 : : { 198 : 5 : multiCurve->addGeometry( surface->boundary() ); 199 : 5 : } 200 : 5 : } 201 : 4 : if ( multiCurve->numGeometries() == 0 ) 202 : : { 203 : 1 : return nullptr; 204 : : } 205 : 3 : return multiCurve.release(); 206 : 4 : }