double QgsDistanceArea::measurePerimeter( const QgsGeometry* geometry ) const { if ( !geometry ) return 0.0; const QgsAbstractGeometryV2* geomV2 = geometry->geometry(); if ( !geomV2 || geomV2->dimension() < 2 ) { return 0.0; } if ( !mEllipsoidalMode ) { return geomV2->length(); } //create list with (single) surfaces QList< const QgsSurfaceV2* > surfaces; const QgsSurfaceV2* surf = dynamic_cast<const QgsSurfaceV2*>( geomV2 ); if ( surf ) { surfaces.append( surf ); } const QgsMultiSurfaceV2* multiSurf = dynamic_cast<const QgsMultiSurfaceV2*>( geomV2 ); if ( multiSurf ) { for ( int i = 0; i < multiSurf->numGeometries(); ++i ) { surfaces.append( static_cast<const QgsSurfaceV2*>( multiSurf->geometryN( i ) ) ); } } double length = 0; QList<QgsPointV2> pointList; QList<const QgsSurfaceV2*>::const_iterator surfaceIt = surfaces.constBegin(); for ( ; surfaceIt != surfaces.constEnd(); ++surfaceIt ) { if ( !*surfaceIt ) { continue; } QgsPolygonV2* poly = ( *surfaceIt )->surfaceToPolygon(); const QgsCurveV2* outerRing = poly->exteriorRing(); if ( outerRing ) { length += measure( outerRing ); } int nInnerRings = poly->numInteriorRings(); for ( int i = 0; i < nInnerRings; ++i ) { length += measure( poly->interiorRing( i ) ); } delete poly; } return length; }
// Make sure all rings are closed and have > 3 points. static bool lwpoly_make_geos_friendly( QgsPolygonV2 &poly ) { // If the polygon has no rings there's nothing to do // TODO: in qgis representation there always is exterior ring //if ( ! poly->nrings ) return true; // All rings must be closed and have > 3 points for ( int i = 0; i < poly.numInteriorRings(); i++ ) { if ( !ring_make_geos_friendly( *const_cast<QgsCurve *>( poly.interiorRing( i ) ) ) ) return false; } return true; }
QString QgsMultiSurface::asJSON( int precision ) const { // GeoJSON does not support curves QString json = QStringLiteral( "{\"type\": \"MultiPolygon\", \"coordinates\": [" ); Q_FOREACH ( const QgsAbstractGeometry *geom, mGeometries ) { if ( dynamic_cast<const QgsSurface*>( geom ) ) { json += '['; QgsPolygonV2* polygon = static_cast<const QgsSurface*>( geom )->surfaceToPolygon(); QgsLineString* exteriorLineString = polygon->exteriorRing()->curveToLine(); QgsPointSequence exteriorPts; exteriorLineString->points( exteriorPts ); json += QgsGeometryUtils::pointsToJSON( exteriorPts, precision ) + ", "; delete exteriorLineString; for ( int i = 0, n = polygon->numInteriorRings(); i < n; ++i ) { QgsLineString* interiorLineString = polygon->interiorRing( i )->curveToLine(); QgsPointSequence interiorPts; interiorLineString->points( interiorPts ); json += QgsGeometryUtils::pointsToJSON( interiorPts, precision ) + ", "; delete interiorLineString; } if ( json.endsWith( QLatin1String( ", " ) ) ) { json.chop( 2 ); // Remove last ", " } delete polygon; json += QLatin1String( "], " ); } } if ( json.endsWith( QLatin1String( ", " ) ) ) { json.chop( 2 ); // Remove last ", " } json += QLatin1String( "] }" ); return json; }
double QgsDistanceArea::measure( const QgsAbstractGeometryV2* geomV2, MeasureType type ) const { if ( !geomV2 ) { return 0.0; } int geomDimension = geomV2->dimension(); if ( geomDimension <= 0 ) { return 0.0; } MeasureType measureType = type; if ( measureType == Default ) { measureType = ( geomDimension == 1 ? Length : Area ); } if ( !mEllipsoidalMode || mEllipsoid == GEO_NONE ) { //no transform required if ( measureType == Length ) { return geomV2->length(); } else { return geomV2->area(); } } else { //multigeom is sum of measured parts const QgsGeometryCollectionV2* collection = dynamic_cast<const QgsGeometryCollectionV2*>( geomV2 ); if ( collection ) { double sum = 0; for ( int i = 0; i < collection->numGeometries(); ++i ) { sum += measure( collection->geometryN( i ), measureType ); } return sum; } if ( measureType == Length ) { const QgsCurveV2* curve = dynamic_cast<const QgsCurveV2*>( geomV2 ); if ( !curve ) { return 0.0; } QgsLineStringV2* lineString = curve->curveToLine(); double length = measureLine( lineString ); delete lineString; return length; } else { const QgsSurfaceV2* surface = dynamic_cast<const QgsSurfaceV2*>( geomV2 ); if ( !surface ) return 0.0; QgsPolygonV2* polygon = surface->surfaceToPolygon(); double area = 0; const QgsCurveV2* outerRing = polygon->exteriorRing(); area += measurePolygon( outerRing ); for ( int i = 0; i < polygon->numInteriorRings(); ++i ) { const QgsCurveV2* innerRing = polygon->interiorRing( i ); area -= measurePolygon( innerRing ); } delete polygon; return area; } } }