void QgsGeometryAnalyzer::convexFeature( QgsFeature& f, int nProcessedFeatures, QgsGeometry** dissolveGeometry ) { QgsGeometry* featureGeometry = f.geometry(); QgsGeometry* tmpGeometry = 0; QgsGeometry* convexGeometry = 0; if ( !featureGeometry ) { return; } convexGeometry = featureGeometry->convexHull(); if ( nProcessedFeatures == 0 ) { *dissolveGeometry = convexGeometry; } else { tmpGeometry = *dissolveGeometry; *dissolveGeometry = ( *dissolveGeometry )->combine( convexGeometry ); delete tmpGeometry; delete convexGeometry; } }
void QgsGeometryAnalyzer::convexFeature( QgsFeature& f, int nProcessedFeatures, QgsGeometry& dissolveGeometry ) { if ( !f.hasGeometry() ) { return; } QgsGeometry featureGeometry = f.geometry(); QgsGeometry convexGeometry = featureGeometry.convexHull(); if ( nProcessedFeatures == 0 ) { dissolveGeometry = convexGeometry; } else { dissolveGeometry = dissolveGeometry.combine( convexGeometry ); } }
bool QgsGeometryAnalyzer::convexHull( QgsVectorLayer* layer, const QString& shapefileName, bool onlySelectedFeatures, int uniqueIdField, QProgressDialog* p ) { if ( !layer ) { return false; } QgsVectorDataProvider* dp = layer->dataProvider(); if ( !dp ) { return false; } bool useField = false; if ( uniqueIdField == -1 ) { uniqueIdField = 0; } else { useField = true; } QgsFields fields; fields.append( QgsField( QStringLiteral( "UID" ), QVariant::String ) ); fields.append( QgsField( QStringLiteral( "AREA" ), QVariant::Double ) ); fields.append( QgsField( QStringLiteral( "PERIM" ), QVariant::Double ) ); QgsWkbTypes::Type outputType = QgsWkbTypes::Polygon; QgsCoordinateReferenceSystem crs = layer->crs(); QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), fields, outputType, crs ); QgsFeature currentFeature; QgsGeometry dissolveGeometry; //dissolve geometry QMultiMap<QString, QgsFeatureId> map; if ( onlySelectedFeatures ) { //use QgsVectorLayer::featureAtId const QgsFeatureIds selection = layer->selectedFeaturesIds(); QgsFeatureIds::const_iterator it = selection.constBegin(); for ( ; it != selection.constEnd(); ++it ) { #if 0 if ( p ) { p->setValue( processedFeatures ); } if ( p && p->wasCanceled() ) { // break; // it may be better to do something else here? return false; } #endif if ( !layer->getFeatures( QgsFeatureRequest().setFilterFid( *it ) ).nextFeature( currentFeature ) ) { continue; } map.insert( currentFeature.attribute( uniqueIdField ).toString(), currentFeature.id() ); } } else { QgsFeatureIterator fit = layer->getFeatures(); while ( fit.nextFeature( currentFeature ) ) { #if 0 if ( p ) { p->setValue( processedFeatures ); } if ( p && p->wasCanceled() ) { // break; // it may be better to do something else here? return false; } #endif map.insert( currentFeature.attribute( uniqueIdField ).toString(), currentFeature.id() ); } } QMultiMap<QString, QgsFeatureId>::const_iterator jt = map.constBegin(); while ( jt != map.constEnd() ) { QString currentKey = jt.key(); int processedFeatures = 0; //take only selection if ( onlySelectedFeatures ) { //use QgsVectorLayer::featureAtId const QgsFeatureIds selection = layer->selectedFeaturesIds(); if ( p ) { p->setMaximum( selection.size() ); } processedFeatures = 0; while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) ) { if ( p && p->wasCanceled() ) { break; } if ( selection.contains( jt.value() ) ) { if ( p ) { p->setValue( processedFeatures ); } if ( !layer->getFeatures( QgsFeatureRequest().setFilterFid( jt.value() ) ).nextFeature( currentFeature ) ) { continue; } convexFeature( currentFeature, processedFeatures, dissolveGeometry ); ++processedFeatures; } ++jt; } QList<double> values; if ( dissolveGeometry.isEmpty() ) { QgsDebugMsg( "no dissolved geometry - should not happen" ); return false; } dissolveGeometry = dissolveGeometry.convexHull(); values = simpleMeasure( dissolveGeometry ); QgsAttributes attributes( 3 ); attributes[0] = QVariant( currentKey ); attributes[1] = values.at( 0 ); attributes[2] = values.at( 1 ); QgsFeature dissolveFeature; dissolveFeature.setAttributes( attributes ); dissolveFeature.setGeometry( dissolveGeometry ); vWriter.addFeature( dissolveFeature ); } //take all features else { int featureCount = layer->featureCount(); if ( p ) { p->setMaximum( featureCount ); } processedFeatures = 0; while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) ) { if ( p ) { p->setValue( processedFeatures ); } if ( p && p->wasCanceled() ) { break; } if ( !layer->getFeatures( QgsFeatureRequest().setFilterFid( jt.value() ) ).nextFeature( currentFeature ) ) { continue; } convexFeature( currentFeature, processedFeatures, dissolveGeometry ); ++processedFeatures; ++jt; } QList<double> values; if ( dissolveGeometry.isEmpty() ) { QgsDebugMsg( "no dissolved geometry - should not happen" ); return false; } dissolveGeometry = dissolveGeometry.convexHull(); // values = simpleMeasure( tmpGeometry ); values = simpleMeasure( dissolveGeometry ); QgsAttributes attributes; attributes[0] = QVariant( currentKey ); attributes[1] = QVariant( values[ 0 ] ); attributes[2] = QVariant( values[ 1 ] ); QgsFeature dissolveFeature; dissolveFeature.setAttributes( attributes ); dissolveFeature.setGeometry( dissolveGeometry ); vWriter.addFeature( dissolveFeature ); } } return true; }
void eval_geometry_method_data() { QTest::addColumn<QString>( "string" ); QTest::addColumn<void*>( "geomptr" ); QTest::addColumn<bool>( "evalError" ); QTest::addColumn<bool>( "needGeom" ); QTest::addColumn<void*>( "resultptr" ); QgsPolyline polygon_ring; polygon_ring << QgsPoint( 0, 0 ) << QgsPoint( 10, 10 ) << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ); QgsPolygon polygon; polygon << polygon_ring; QgsGeometry* geom = QgsGeometry::fromPolygon( polygon ); QTest::newRow( "buffer" ) << "buffer( $geometry, 1.0, 3)" << ( void* ) geom << false << true << ( void* ) geom->buffer( 1.0, 3 ); geom = QgsGeometry::fromPolygon( polygon ); QTest::newRow( "buffer" ) << "buffer( $geometry, 2.0)" << ( void* ) geom << false << true << ( void* ) geom->buffer( 2.0, 8 ); QgsPoint point1( 10, 20 ); QgsPoint point2( 30, 20 ); QgsGeometry* pnt1 = QgsGeometry::fromPoint( point1 ); QgsGeometry* pnt2 = QgsGeometry::fromPoint( point2 ); QTest::newRow( "union" ) << "union( $geometry, geomFromWKT('" + pnt2->exportToWkt() + "') )" << ( void* ) pnt1 << false << true << ( void* ) pnt1->combine( pnt2 ); geom = QgsGeometry::fromPolygon( polygon ); QTest::newRow( "intersection" ) << "intersection( $geometry, geomFromWKT('POLYGON((0 0, 0 10, 10 0, 0 0))') )" << ( void* ) geom << false << true << ( void* ) QgsGeometry::fromWkt( "POLYGON ((0 0,5 5,10 0,0 0))" ); geom = QgsGeometry::fromPolygon( polygon ); QTest::newRow( "difference" ) << "difference( $geometry, geomFromWKT('POLYGON((0 0, 0 10, 10 0, 0 0))') )" << ( void* ) geom << false << true << ( void* ) QgsGeometry::fromWkt( "POLYGON ((5 5,10 10,10 0,5 5))" ); geom = QgsGeometry::fromPolygon( polygon ); QTest::newRow( "symDifference" ) << "symDifference( $geometry, geomFromWKT('POLYGON((0 0, 0 10, 10 0, 0 0))') )" << ( void* ) geom << false << true << ( void* ) QgsGeometry::fromWkt( "MULTIPOLYGON(((5 5,0 0,0 10,5 5)),((5 5,10 10,10 0,5 5)))" ); geom = QgsGeometry::fromPolygon( polygon ); QTest::newRow( "centroid polygon" ) << "centroid( $geometry )" << ( void* ) geom << false << true << ( void* ) geom->centroid(); geom = QgsGeometry::fromPolygon( polygon ); QTest::newRow( "centroid self intersecting polygon" ) << "centroid( geomFromWKT('POLYGON((0 0, 0 2, 2 -0.1, 2 2.1, 0 0))') )" << ( void* ) geom << false << false << ( void* ) QgsGeometry::fromWkt( "POINT (8.0 1.0)" ); geom = QgsGeometry::fromPolygon( polygon ); QTest::newRow( "centroid multi polygon" ) << "centroid( geomFromWKT('MULTIPOLYGON(((0 0,0 1,1 1,1 0,0 0)),((2 0,2 1,3 1,3 0,2 0)))') )" << ( void* ) geom << false << false << ( void* ) QgsGeometry::fromWkt( "POINT (1.5 0.5)" ); geom = QgsGeometry::fromPolygon( polygon ); QTest::newRow( "convexHull simple" ) << "convexHull( $geometry )" << ( void* ) geom << false << true << ( void* ) geom->convexHull(); geom = QgsGeometry::fromPolygon( polygon ); QTest::newRow( "convexHull multi" ) << "convexHull( geomFromWKT('GEOMETRYCOLLECTION(POINT(0 1), POINT(0 0), POINT(1 0), POINT(1 1))') )" << ( void* ) geom << false << false << ( void* ) QgsGeometry::fromWkt( "POLYGON ((0 0,0 1,1 1,1 0,0 0))" ); }