QgsGeometry QgsInternalGeometryEngine::densifyByDistance( double distance ) const { if ( !mGeometry ) { return QgsGeometry(); } if ( QgsWkbTypes::geometryType( mGeometry->wkbType() ) == QgsWkbTypes::PointGeometry ) { return QgsGeometry( mGeometry->clone() ); // point geometry, nothing to do } if ( const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) ) { int numGeom = gc->numGeometries(); QVector< QgsAbstractGeometry * > geometryList; geometryList.reserve( numGeom ); for ( int i = 0; i < numGeom; ++i ) { geometryList << densifyGeometry( gc->geometryN( i ), -1, distance ); } QgsGeometry first = QgsGeometry( geometryList.takeAt( 0 ) ); for ( QgsAbstractGeometry *g : qgis::as_const( geometryList ) ) { first.addPart( g ); } return first; } else { return QgsGeometry( densifyGeometry( mGeometry, -1, distance ) ); } }
QgsGeometry QgsGeometryAnalyzer::locateBetweenMeasures( double fromMeasure, double toMeasure, const QgsGeometry& lineGeom ) { if ( lineGeom.isEmpty() ) { return QgsGeometry(); } QgsMultiPolyline resultGeom; //need to go with WKB and z coordinate until QgsGeometry supports M values QByteArray wkb( lineGeom.exportToWkb() ); QgsConstWkbPtr wkbPtr( wkb ); wkbPtr.readHeader(); QgsWkbTypes::Type wkbType = lineGeom.wkbType(); if ( wkbType != QgsWkbTypes::LineString25D && wkbType != QgsWkbTypes::MultiLineString25D ) { return QgsGeometry(); } if ( wkbType == QgsWkbTypes::LineString25D ) { locateBetweenWkbString( wkbPtr, resultGeom, fromMeasure, toMeasure ); } else if ( wkbType == QgsWkbTypes::MultiLineString25D ) { int nLines; wkbPtr >> nLines; for ( int i = 0; i < nLines; ++i ) { wkbPtr.readHeader(); wkbPtr = locateBetweenWkbString( wkbPtr, resultGeom, fromMeasure, toMeasure ); } }
QgsGeometry QgsInternalGeometryEngine::orthogonalize( double tolerance, int maxIterations, double angleThreshold ) const { if ( !mGeometry || ( QgsWkbTypes::geometryType( mGeometry->wkbType() ) != QgsWkbTypes::LineGeometry && QgsWkbTypes::geometryType( mGeometry->wkbType() ) != QgsWkbTypes::PolygonGeometry ) ) { return QgsGeometry(); } double lowerThreshold = std::cos( ( 90 - angleThreshold ) * M_PI / 180.00 ); double upperThreshold = std::cos( angleThreshold * M_PI / 180.0 ); if ( const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) ) { int numGeom = gc->numGeometries(); QVector< QgsAbstractGeometry * > geometryList; geometryList.reserve( numGeom ); for ( int i = 0; i < numGeom; ++i ) { geometryList << orthogonalizeGeom( gc->geometryN( i ), maxIterations, tolerance, lowerThreshold, upperThreshold ); } QgsGeometry first = QgsGeometry( geometryList.takeAt( 0 ) ); for ( QgsAbstractGeometry *g : qgis::as_const( geometryList ) ) { first.addPart( g ); } return first; } else { return QgsGeometry( orthogonalizeGeom( mGeometry, maxIterations, tolerance, lowerThreshold, upperThreshold ) ); } }
static bool _check_intersecting_rings( const QgsPolygon &polygon ) { // At this point we assume that input polygons are valid according to the OGC definition. // This means e.g. no duplicate points, polygons are simple (no butterfly shaped polygon with self-intersection), // internal rings are inside exterior rings, rings do not cross each other, no dangles. // There is however an issue with polygons where rings touch: // +---+ // | | // | +-+-+ // | | | | // | +-+ | // | | // +-----+ // This is a valid polygon with one exterior and one interior ring that touch at one point, // but poly2tri library does not allow interior rings touch each other or exterior ring. // TODO: Handle the situation better - rather than just detecting the problem, try to fix // it by converting touching rings into one ring. if ( polygon.numInteriorRings() > 0 ) { QList<QgsGeometry> geomRings; geomRings << QgsGeometry( polygon.exteriorRing()->clone() ); for ( int i = 0; i < polygon.numInteriorRings(); ++i ) geomRings << QgsGeometry( polygon.interiorRing( i )->clone() ); for ( int i = 0; i < geomRings.count(); ++i ) for ( int j = i + 1; j < geomRings.count(); ++j ) { if ( geomRings[i].intersects( geomRings[j] ) ) return false; } } return true; }
//! Generalize the WKB-geometry using the BBOX of the original geometry static QgsGeometry generalizeWkbGeometryByBoundingBox( QgsWkbTypes::Type wkbType, const QgsAbstractGeometry& geometry, const QgsRectangle &envelope ) { unsigned int geometryType = QgsWkbTypes::singleType( QgsWkbTypes::flatType( wkbType ) ); // If the geometry is already minimal skip the generalization int minimumSize = geometryType == QgsWkbTypes::LineString ? 2 : 5; if ( geometry.nCoordinates() <= minimumSize ) { return QgsGeometry( geometry.clone() ); } const double x1 = envelope.xMinimum(); const double y1 = envelope.yMinimum(); const double x2 = envelope.xMaximum(); const double y2 = envelope.yMaximum(); // Write the generalized geometry if ( geometryType == QgsWkbTypes::LineString ) { QgsLineString* lineString = new QgsLineString(); lineString->addVertex( QgsPointV2( x1, y1 ) ); lineString->addVertex( QgsPointV2( x2, y2 ) ); return QgsGeometry( lineString ); } else { return QgsGeometry::fromRect( envelope ); } }
void QgsMapToolCapture::validateGeometry() { QgsSettings settings; if ( settings.value( QStringLiteral( "qgis/digitizing/validate_geometries" ), 1 ).toInt() == 0 ) return; if ( mValidator ) { mValidator->deleteLater(); mValidator = nullptr; } mGeomErrors.clear(); while ( !mGeomErrorMarkers.isEmpty() ) { delete mGeomErrorMarkers.takeFirst(); } QgsGeometry geom; switch ( mCaptureMode ) { case CaptureNone: case CapturePoint: return; case CaptureLine: if ( size() < 2 ) return; geom = QgsGeometry( mCaptureCurve.curveToLine() ); break; case CapturePolygon: if ( size() < 3 ) return; QgsLineString *exteriorRing = mCaptureCurve.curveToLine(); exteriorRing->close(); QgsPolygon *polygon = new QgsPolygon(); polygon->setExteriorRing( exteriorRing ); geom = QgsGeometry( polygon ); break; } if ( geom.isNull() ) return; QgsGeometry::ValidationMethod method = QgsGeometry::ValidatorQgisInternal; if ( settings.value( QStringLiteral( "qgis/digitizing/validate_geometries" ), 1 ).toInt() == 2 ) method = QgsGeometry::ValidatorGeos; mValidator = new QgsGeometryValidator( geom, nullptr, method ); connect( mValidator, &QgsGeometryValidator::errorFound, this, &QgsMapToolCapture::addError ); mValidator->start(); QgsDebugMsgLevel( QStringLiteral( "Validation started" ), 4 ); }
QgsGeometry QgsInternalGeometryEngine::extrude( double x, double y ) const { QVector<QgsLineString *> linesToProcess; const QgsMultiCurve *multiCurve = qgsgeometry_cast< const QgsMultiCurve * >( mGeometry ); if ( multiCurve ) { for ( int i = 0; i < multiCurve->partCount(); ++i ) { linesToProcess << static_cast<QgsLineString *>( multiCurve->geometryN( i )->clone() ); } } const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( mGeometry ); if ( curve ) { linesToProcess << static_cast<QgsLineString *>( curve->segmentize() ); } std::unique_ptr<QgsMultiPolygon> multipolygon( linesToProcess.size() > 1 ? new QgsMultiPolygon() : nullptr ); QgsPolygon *polygon = nullptr; if ( !linesToProcess.empty() ) { std::unique_ptr< QgsLineString > secondline; for ( QgsLineString *line : qgis::as_const( linesToProcess ) ) { QTransform transform = QTransform::fromTranslate( x, y ); secondline.reset( line->reversed() ); secondline->transform( transform ); line->append( secondline.get() ); line->addVertex( line->pointN( 0 ) ); polygon = new QgsPolygon(); polygon->setExteriorRing( line ); if ( multipolygon ) multipolygon->addGeometry( polygon ); } if ( multipolygon ) return QgsGeometry( multipolygon.release() ); else return QgsGeometry( polygon ); } return QgsGeometry(); }
QgsGeometry QgsTransectSample::closestMultilineElement( const QgsPoint& pt, const QgsGeometry& multiLine ) { if ( !multiLine || ( multiLine.wkbType() != QgsWkbTypes::MultiLineString && multiLine.wkbType() != QgsWkbTypes::MultiLineString25D ) ) { return QgsGeometry(); } double minDist = DBL_MAX; double currentDist = 0; QgsGeometry currentLine; QgsGeometry closestLine; QgsGeometry pointGeom = QgsGeometry::fromPoint( pt ); QgsMultiPolyline multiPolyline = multiLine.asMultiPolyline(); QgsMultiPolyline::const_iterator it = multiPolyline.constBegin(); for ( ; it != multiPolyline.constEnd(); ++it ) { currentLine = QgsGeometry::fromPolyline( *it ); currentDist = pointGeom.distance( currentLine ); if ( currentDist < minDist ) { minDist = currentDist; closestLine = currentLine; } } return closestLine; }
QVariantMap QgsDissolveAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) { return processCollection( parameters, context, feedback, [ & ]( const QVector< QgsGeometry > &parts )->QgsGeometry { QgsGeometry result( QgsGeometry::unaryUnion( parts ) ); if ( QgsWkbTypes::geometryType( result.wkbType() ) == QgsWkbTypes::LineGeometry ) result = result.mergeLines(); // Geos may fail in some cases, let's try a slower but safer approach // See: https://issues.qgis.org/issues/20591 - Dissolve tool failing to produce outputs if ( ! result.lastError().isEmpty() && parts.count() > 2 ) { if ( feedback->isCanceled() ) return result; feedback->pushDebugInfo( QObject::tr( "GEOS exception: taking the slower route ..." ) ); result = QgsGeometry(); for ( const auto &p : parts ) { result = QgsGeometry::unaryUnion( QVector< QgsGeometry >() << result << p ); if ( QgsWkbTypes::geometryType( result.wkbType() ) == QgsWkbTypes::LineGeometry ) result = result.mergeLines(); if ( feedback->isCanceled() ) return result; } } if ( ! result.lastError().isEmpty() ) { feedback->reportError( result.lastError(), true ); if ( result.isEmpty() ) throw QgsProcessingException( QObject::tr( "The algorithm returned no output." ) ); } return result; }, 10000 ); }
QgsAtlasComposition::QgsAtlasComposition( QgsComposition* composition ) : mComposition( composition ) , mEnabled( false ) , mHideCoverage( false ) , mFilenamePattern( "'output_'||$feature" ) , mCoverageLayer( 0 ) , mSingleFile( false ) , mSortFeatures( false ) , mSortAscending( true ) , mCurrentFeatureNo( 0 ) , mFilterFeatures( false ) { // declare special columns with a default value QgsExpression::setSpecialColumn( "$page", QVariant(( int )1 ) ); QgsExpression::setSpecialColumn( "$feature", QVariant(( int )0 ) ); QgsExpression::setSpecialColumn( "$numpages", QVariant(( int )1 ) ); QgsExpression::setSpecialColumn( "$numfeatures", QVariant(( int )0 ) ); QgsExpression::setSpecialColumn( "$atlasfeatureid", QVariant(( int )0 ) ); QgsExpression::setSpecialColumn( "$atlasfeature", QVariant::fromValue( QgsFeature() ) ); QgsExpression::setSpecialColumn( "$atlasgeometry", QVariant::fromValue( QgsGeometry() ) ); //listen out for layer removal connect( QgsMapLayerRegistry::instance(), SIGNAL( layersWillBeRemoved( QStringList ) ), this, SLOT( removeLayers( QStringList ) ) ); }
void QgsRelationEditorWidget::addFeature() { QgsAttributeMap keyAttrs; const QgsVectorLayerTools* vlTools = mEditorContext.vectorLayerTools(); if ( mNmRelation.isValid() ) { // n:m Relation: first let the user create a new feature on the other table // and autocreate a new linking feature. QgsFeature f; if ( vlTools->addFeature( mNmRelation.referencedLayer(), QgsAttributeMap(), QgsGeometry(), &f ) ) { QgsFeature flink( mRelation.referencingLayer()->fields() ); // Linking feature flink.setAttribute( mRelation.fieldPairs().at( 0 ).first, mFeature.attribute( mRelation.fieldPairs().at( 0 ).second ) ); flink.setAttribute( mNmRelation.referencingFields().at( 0 ), f.attribute( mNmRelation.referencedFields().at( 0 ) ) ); mRelation.referencingLayer()->addFeature( flink ); updateUi(); } } else { QgsFields fields = mRelation.referencingLayer()->fields(); Q_FOREACH ( const QgsRelation::FieldPair& fieldPair, mRelation.fieldPairs() ) { keyAttrs.insert( fields.indexFromName( fieldPair.referencingField() ), mFeature.attribute( fieldPair.referencedField() ) ); } vlTools->addFeature( mDualView->masterModel()->layer(), keyAttrs ); } }
QgsGeometry QgsAtlasComposition::currentGeometry( const QgsCoordinateReferenceSystem& crs ) const { if ( !mCoverageLayer || !mCurrentFeature.isValid() || !mCurrentFeature.hasGeometry() ) { return QgsGeometry(); } if ( !crs.isValid() ) { // no projection, return the native geometry return mCurrentFeature.geometry(); } QMap<long, QgsGeometry>::const_iterator it = mGeometryCache.constFind( crs.srsid() ); if ( it != mGeometryCache.constEnd() ) { // we have it in cache, return it return it.value(); } if ( mCoverageLayer->crs() == crs ) { return mCurrentFeature.geometry(); } QgsGeometry transformed = mCurrentFeature.geometry(); transformed.transform( QgsCoordinateTransformCache::instance()->transform( mCoverageLayer->crs().authid(), crs.authid() ) ); mGeometryCache[crs.srsid()] = transformed; return transformed; }
bool QgsGeometryCheckerResultTab::exportErrorsDo( const QString& file ) { QList< QPair<QString, QString> > attributes; attributes.append( qMakePair( QString( "FeatureID" ), QString( "String;10;" ) ) ); attributes.append( qMakePair( QString( "ErrorDesc" ), QString( "String;80;" ) ) ); QLibrary ogrLib( QgsProviderRegistry::instance()->library( "ogr" ) ); if ( !ogrLib.load() ) { return false; } typedef bool ( *createEmptyDataSourceProc )( const QString&, const QString&, const QString&, Qgis::WkbType, const QList< QPair<QString, QString> >&, const QgsCoordinateReferenceSystem& ); createEmptyDataSourceProc createEmptyDataSource = ( createEmptyDataSourceProc ) cast_to_fptr( ogrLib.resolve( "createEmptyDataSource" ) ); if ( !createEmptyDataSource ) { return false; } if ( !createEmptyDataSource( file, "ESRI Shapefile", mFeaturePool->getLayer()->dataProvider()->encoding(), Qgis::WKBPoint, attributes, mFeaturePool->getLayer()->crs() ) ) { return false; } QgsVectorLayer* layer = new QgsVectorLayer( file, QFileInfo( file ).baseName(), "ogr" ); if ( !layer->isValid() ) { delete layer; return false; } int fieldFeatureId = layer->fieldNameIndex( "FeatureID" ); int fieldErrDesc = layer->fieldNameIndex( "ErrorDesc" ); for ( int row = 0, nRows = ui.tableWidgetErrors->rowCount(); row < nRows; ++row ) { QgsGeometryCheckError* error = ui.tableWidgetErrors->item( row, 0 )->data( Qt::UserRole ).value<QgsGeometryCheckError*>(); QgsFeature f( layer->fields() ); f.setAttribute( fieldFeatureId, error->featureId() ); f.setAttribute( fieldErrDesc, error->description() ); f.setGeometry( QgsGeometry( error->location().clone() ) ); layer->dataProvider()->addFeatures( QgsFeatureList() << f ); } // Remove existing layer with same uri QStringList toRemove; Q_FOREACH ( QgsMapLayer* maplayer, QgsMapLayerRegistry::instance()->mapLayers() ) { if ( dynamic_cast<QgsVectorLayer*>( maplayer ) && static_cast<QgsVectorLayer*>( maplayer )->dataProvider()->dataSourceUri() == layer->dataProvider()->dataSourceUri() ) { toRemove.append( maplayer->id() ); } } if ( !toRemove.isEmpty() ) { QgsMapLayerRegistry::instance()->removeMapLayers( toRemove ); } QgsMapLayerRegistry::instance()->addMapLayers( QList<QgsMapLayer*>() << layer ); return true; }
Qt3DRender::QGeometryRenderer *QgsLine3DSymbolEntityNode::renderer( const Qgs3DMapSettings &map, const QgsLine3DSymbol &symbol, const QgsVectorLayer *layer, const QgsFeatureRequest &request ) { QgsPointXY origin( map.origin().x(), map.origin().y() ); // TODO: configurable int nSegments = 4; QgsGeometry::EndCapStyle endCapStyle = QgsGeometry::CapRound; QgsGeometry::JoinStyle joinStyle = QgsGeometry::JoinStyleRound; double mitreLimit = 0; QList<QgsPolygon *> polygons; QgsFeature f; QgsFeatureIterator fi = layer->getFeatures( request ); while ( fi.nextFeature( f ) ) { if ( f.geometry().isNull() ) continue; QgsGeometry geom = f.geometry(); // segmentize curved geometries if necessary if ( QgsWkbTypes::isCurvedType( geom.constGet()->wkbType() ) ) geom = QgsGeometry( geom.constGet()->segmentize() ); const QgsAbstractGeometry *g = geom.constGet(); QgsGeos engine( g ); QgsAbstractGeometry *buffered = engine.buffer( symbol.width() / 2., nSegments, endCapStyle, joinStyle, mitreLimit ); // factory if ( QgsWkbTypes::flatType( buffered->wkbType() ) == QgsWkbTypes::Polygon ) { QgsPolygon *polyBuffered = static_cast<QgsPolygon *>( buffered ); Qgs3DUtils::clampAltitudes( polyBuffered, symbol.altitudeClamping(), symbol.altitudeBinding(), symbol.height(), map ); polygons.append( polyBuffered ); } else if ( QgsWkbTypes::flatType( buffered->wkbType() ) == QgsWkbTypes::MultiPolygon ) { QgsMultiPolygon *mpolyBuffered = static_cast<QgsMultiPolygon *>( buffered ); for ( int i = 0; i < mpolyBuffered->numGeometries(); ++i ) { QgsAbstractGeometry *partBuffered = mpolyBuffered->geometryN( i ); Q_ASSERT( QgsWkbTypes::flatType( partBuffered->wkbType() ) == QgsWkbTypes::Polygon ); QgsPolygon *polyBuffered = static_cast<QgsPolygon *>( partBuffered )->clone(); // need to clone individual geometry parts Qgs3DUtils::clampAltitudes( polyBuffered, symbol.altitudeClamping(), symbol.altitudeBinding(), symbol.height(), map ); polygons.append( polyBuffered ); } delete buffered; } } mGeometry = new QgsTessellatedPolygonGeometry; mGeometry->setPolygons( polygons, origin, symbol.extrusionHeight() ); Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer; renderer->setGeometry( mGeometry ); return renderer; }
static bool _check_intersecting_rings( const QgsPolygon &polygon ) { QList<QgsGeometry> geomRings; geomRings << QgsGeometry( polygon.exteriorRing()->clone() ); for ( int i = 0; i < polygon.numInteriorRings(); ++i ) geomRings << QgsGeometry( polygon.interiorRing( i )->clone() ); // we need to make sure that the polygon has no rings with self-intersection: that may // crash the tessellator. The original geometry maybe have been valid and the self-intersection // was introduced when transforming to a new base (in a rare case when all points are not in the same plane) for ( int i = 0; i < geomRings.count(); ++i ) { if ( !geomRings[i].isSimple() ) return false; } // At this point we assume that input polygons are valid according to the OGC definition. // This means e.g. no duplicate points, polygons are simple (no butterfly shaped polygon with self-intersection), // internal rings are inside exterior rings, rings do not cross each other, no dangles. // There is however an issue with polygons where rings touch: // +---+ // | | // | +-+-+ // | | | | // | +-+ | // | | // +-----+ // This is a valid polygon with one exterior and one interior ring that touch at one point, // but poly2tri library does not allow interior rings touch each other or exterior ring. // TODO: Handle the situation better - rather than just detecting the problem, try to fix // it by converting touching rings into one ring. if ( polygon.numInteriorRings() > 0 ) { for ( int i = 0; i < geomRings.count(); ++i ) for ( int j = i + 1; j < geomRings.count(); ++j ) { if ( geomRings[i].intersects( geomRings[j] ) ) return false; } } return true; }
QgsGeometry QgsMeshCalculatorDialog::maskGeometry() const { QgsVectorLayer *mask_layer = qobject_cast<QgsVectorLayer *> ( cboLayerMask->currentLayer() ); if ( mask_layer ) { return maskGeometry( mask_layer ); } return QgsGeometry(); }
QgsGeometry QgsTransectSample::findBaselineGeometry( const QVariant& strataId ) { if ( !mBaselineLayer ) { return QgsGeometry(); } QgsFeatureIterator baseLineIt = mBaselineLayer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QStringList( mBaselineStrataId ), mBaselineLayer->fields() ) ); QgsFeature fet; while ( baseLineIt.nextFeature( fet ) ) //todo: cache this in case there are many baslines { if ( strataId == fet.attribute( mBaselineStrataId ) || mShareBaseline ) { return fet.geometry(); } } return QgsGeometry(); }
QgsGeometry QgsOgrUtils::ogrGeometryToQgsGeometry( OGRGeometryH geom ) { if ( !geom ) return QgsGeometry(); // get the wkb representation int memorySize = OGR_G_WkbSize( geom ); unsigned char *wkb = new unsigned char[memorySize]; OGR_G_ExportToWkb( geom, ( OGRwkbByteOrder ) QgsApplication::endian(), wkb ); QgsGeometry g; g.fromWkb( wkb, memorySize ); return g; }
void QgsZonalStatistics::statisticsFromPreciseIntersection( void* band, const QgsGeometry& poly, int pixelOffsetX, int pixelOffsetY, int nCellsX, int nCellsY, double cellSizeX, double cellSizeY, const QgsRectangle& rasterBBox, FeatureStats &stats ) { stats.reset(); double currentY = rasterBBox.yMaximum() - pixelOffsetY * cellSizeY - cellSizeY / 2; float* pixelData = ( float * ) CPLMalloc( sizeof( float ) ); QgsGeometry pixelRectGeometry; double hCellSizeX = cellSizeX / 2.0; double hCellSizeY = cellSizeY / 2.0; double pixelArea = cellSizeX * cellSizeY; double weight = 0; for ( int row = 0; row < nCellsY; ++row ) { double currentX = rasterBBox.xMinimum() + cellSizeX / 2.0 + pixelOffsetX * cellSizeX; for ( int col = 0; col < nCellsX; ++col ) { if ( GDALRasterIO( band, GF_Read, pixelOffsetX + col, pixelOffsetY + row, nCellsX, 1, pixelData, 1, 1, GDT_Float32, 0, 0 ) != CE_None ) { QgsDebugMsg( "Raster IO Error" ); } if ( !validPixel( *pixelData ) ) continue; pixelRectGeometry = QgsGeometry::fromRect( QgsRectangle( currentX - hCellSizeX, currentY - hCellSizeY, currentX + hCellSizeX, currentY + hCellSizeY ) ); if ( !pixelRectGeometry.isEmpty() ) { //intersection QgsGeometry intersectGeometry = pixelRectGeometry.intersection( poly ); if ( !intersectGeometry.isEmpty() ) { double intersectionArea = intersectGeometry.area(); if ( intersectionArea >= 0.0 ) { weight = intersectionArea / pixelArea; stats.addValue( *pixelData, weight ); } } pixelRectGeometry = QgsGeometry(); } currentX += cellSizeX; } currentY -= cellSizeY; } CPLFree( pixelData ); }
void QgsZonalStatistics::statisticsFromPreciseIntersection( const QgsGeometry &poly, int pixelOffsetX, int pixelOffsetY, int nCellsX, int nCellsY, double cellSizeX, double cellSizeY, const QgsRectangle &rasterBBox, FeatureStats &stats ) { stats.reset(); double currentY = rasterBBox.yMaximum() - pixelOffsetY * cellSizeY - cellSizeY / 2; QgsGeometry pixelRectGeometry; double hCellSizeX = cellSizeX / 2.0; double hCellSizeY = cellSizeY / 2.0; double pixelArea = cellSizeX * cellSizeY; double weight = 0; QgsRectangle featureBBox = poly.boundingBox().intersect( &rasterBBox ); QgsRectangle intersectBBox = rasterBBox.intersect( &featureBBox ); QgsRasterBlock *block = mRasterProvider->block( mRasterBand, intersectBBox, nCellsX, nCellsY ); for ( int i = 0; i < nCellsY; ++i ) { double currentX = rasterBBox.xMinimum() + cellSizeX / 2.0 + pixelOffsetX * cellSizeX; for ( int j = 0; j < nCellsX; ++j ) { if ( !validPixel( block->value( i, j ) ) ) { continue; } pixelRectGeometry = QgsGeometry::fromRect( QgsRectangle( currentX - hCellSizeX, currentY - hCellSizeY, currentX + hCellSizeX, currentY + hCellSizeY ) ); if ( !pixelRectGeometry.isNull() ) { //intersection QgsGeometry intersectGeometry = pixelRectGeometry.intersection( poly ); if ( !intersectGeometry.isNull() ) { double intersectionArea = intersectGeometry.area(); if ( intersectionArea >= 0.0 ) { weight = intersectionArea / pixelArea; stats.addValue( block->value( i, j ), weight ); } } pixelRectGeometry = QgsGeometry(); } currentX += cellSizeX; } currentY -= cellSizeY; } delete block; }
QgsVectorLayerUndoCommandChangeGeometry::QgsVectorLayerUndoCommandChangeGeometry( QgsVectorLayerEditBuffer *buffer, QgsFeatureId fid, const QgsGeometry &newGeom ) : QgsVectorLayerUndoCommand( buffer ) , mFid( fid ) , mNewGeom( newGeom ) { if ( FID_IS_NEW( mFid ) ) { QgsFeatureMap::const_iterator it = mBuffer->mAddedFeatures.constFind( mFid ); Q_ASSERT( it != mBuffer->mAddedFeatures.constEnd() ); mOldGeom = ( it.value().geometry() ); } else { mOldGeom = mBuffer->mChangedGeometries.value( mFid, QgsGeometry() ); } }
void QgsBufferedLine3DSymbolHandler::processFeature( QgsFeature &f, const Qgs3DRenderContext &context ) { if ( f.geometry().isNull() ) return; LineData &out = mSelectedIds.contains( f.id() ) ? outSelected : outNormal; QgsGeometry geom = f.geometry(); // segmentize curved geometries if necessary if ( QgsWkbTypes::isCurvedType( geom.constGet()->wkbType() ) ) geom = QgsGeometry( geom.constGet()->segmentize() ); const QgsAbstractGeometry *g = geom.constGet(); // TODO: configurable const int nSegments = 4; const QgsGeometry::EndCapStyle endCapStyle = QgsGeometry::CapRound; const QgsGeometry::JoinStyle joinStyle = QgsGeometry::JoinStyleRound; const double mitreLimit = 0; QgsGeos engine( g ); QgsAbstractGeometry *buffered = engine.buffer( mSymbol.width() / 2., nSegments, endCapStyle, joinStyle, mitreLimit ); // factory if ( QgsWkbTypes::flatType( buffered->wkbType() ) == QgsWkbTypes::Polygon ) { QgsPolygon *polyBuffered = static_cast<QgsPolygon *>( buffered ); Qgs3DUtils::clampAltitudes( polyBuffered, mSymbol.altitudeClamping(), mSymbol.altitudeBinding(), mSymbol.height(), context.map() ); out.polygons.append( polyBuffered ); out.fids.append( f.id() ); } else if ( QgsWkbTypes::flatType( buffered->wkbType() ) == QgsWkbTypes::MultiPolygon ) { QgsMultiPolygon *mpolyBuffered = static_cast<QgsMultiPolygon *>( buffered ); for ( int i = 0; i < mpolyBuffered->numGeometries(); ++i ) { QgsAbstractGeometry *partBuffered = mpolyBuffered->geometryN( i ); Q_ASSERT( QgsWkbTypes::flatType( partBuffered->wkbType() ) == QgsWkbTypes::Polygon ); QgsPolygon *polyBuffered = static_cast<QgsPolygon *>( partBuffered )->clone(); // need to clone individual geometry parts Qgs3DUtils::clampAltitudes( polyBuffered, mSymbol.altitudeClamping(), mSymbol.altitudeBinding(), mSymbol.height(), context.map() ); out.polygons.append( polyBuffered ); out.fids.append( f.id() ); } delete buffered; } }
QgsAtlasComposition::QgsAtlasComposition( QgsComposition* composition ) : mComposition( composition ), mEnabled( false ), mHideCoverage( false ), mFilenamePattern( "'output_'||$feature" ), mCoverageLayer( 0 ), mSingleFile( false ), mSortFeatures( false ), mSortAscending( true ), mCurrentFeatureNo( 0 ), mFilterFeatures( false ), mFeatureFilter( "" ) { // declare special columns with a default value QgsExpression::setSpecialColumn( "$page", QVariant(( int )1 ) ); QgsExpression::setSpecialColumn( "$feature", QVariant(( int )0 ) ); QgsExpression::setSpecialColumn( "$numpages", QVariant(( int )1 ) ); QgsExpression::setSpecialColumn( "$numfeatures", QVariant(( int )0 ) ); QgsExpression::setSpecialColumn( "$atlasfeatureid", QVariant(( int )0 ) ); QgsExpression::setSpecialColumn( "$atlasgeometry", QVariant::fromValue( QgsGeometry() ) ); }
bool QgsVectorLayerUndoCommandChangeGeometry::mergeWith( const QUndoCommand *other ) { if ( other->id() != id() ) return false; const QgsVectorLayerUndoCommandChangeGeometry *merge = dynamic_cast<const QgsVectorLayerUndoCommandChangeGeometry *>( other ); if ( !merge ) return false; if ( merge->mFid != mFid ) return false; mNewGeom = merge->mNewGeom; merge->mNewGeom = QgsGeometry(); return true; }
QgsGeometry QgsInternalGeometryEngine::poleOfInaccessibility( double precision, double *distanceFromBoundary ) const { if ( distanceFromBoundary ) *distanceFromBoundary = DBL_MAX; if ( !mGeometry || mGeometry->isEmpty() ) return QgsGeometry(); if ( precision <= 0 ) return QgsGeometry(); if ( const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) ) { int numGeom = gc->numGeometries(); double maxDist = 0; QgsPoint bestPoint; bool found = false; for ( int i = 0; i < numGeom; ++i ) { const QgsSurface *surface = qgsgeometry_cast< const QgsSurface * >( gc->geometryN( i ) ); if ( !surface ) continue; found = true; double dist = DBL_MAX; QgsPoint p = surfacePoleOfInaccessibility( surface, precision, dist ); if ( dist > maxDist ) { maxDist = dist; bestPoint = p; } } if ( !found ) return QgsGeometry(); if ( distanceFromBoundary ) *distanceFromBoundary = maxDist; return QgsGeometry( new QgsPoint( bestPoint ) ); } else { const QgsSurface *surface = qgsgeometry_cast< const QgsSurface * >( mGeometry ); if ( !surface ) return QgsGeometry(); double dist = DBL_MAX; QgsPoint p = surfacePoleOfInaccessibility( surface, precision, dist ); if ( distanceFromBoundary ) *distanceFromBoundary = dist; return QgsGeometry( new QgsPoint( p ) ); } }
QgsGeometry QgsDelimitedTextProvider::geomFromWkt( QString &sWkt, bool wktHasPrefixRegexp ) { QgsGeometry geom; try { if ( wktHasPrefixRegexp ) { sWkt.remove( WktPrefixRegexp ); } geom = QgsGeometry::fromWkt( sWkt ); } catch ( ... ) { geom = QgsGeometry(); } return geom; }
QgsVectorLayerUndoCommandChangeGeometry::QgsVectorLayerUndoCommandChangeGeometry( QgsVectorLayerEditBuffer* buffer, QgsFeatureId fid, const QgsGeometry& newGeom ) : QgsVectorLayerUndoCommand( buffer ) , mFid( fid ) , mNewGeom( newGeom ) { if ( FID_IS_NEW( mFid ) ) { QgsFeatureMap::const_iterator it = mBuffer->mAddedFeatures.constFind( mFid ); Q_ASSERT( it != mBuffer->mAddedFeatures.constEnd() ); mOldGeom = ( it.value().geometry() ); } else { bool changedAlready = mBuffer->mChangedGeometries.contains( mFid ); QgsGeometry geom; bool cachedGeom = cache()->geometry( mFid, geom ); mOldGeom = ( changedAlready && cachedGeom ) ? geom : QgsGeometry(); } }
void testNullGeometries() { QgsVectorLayer *vlNullGeom = new QgsVectorLayer( "Polygon", "x", "memory" ); QgsFeature ff( 0 ); ff.setGeometry( QgsGeometry() ); QgsFeatureList flist; flist << ff; vlNullGeom->dataProvider()->addFeatures( flist ); QgsPointLocator loc( vlNullGeom, QgsCoordinateReferenceSystem(), nullptr ); QgsPointLocator::Match m1 = loc.nearestVertex( QgsPointXY( 2, 2 ), std::numeric_limits<double>::max() ); QVERIFY( !m1.isValid() ); QgsPointLocator::Match m2 = loc.nearestEdge( QgsPointXY( 2, 2 ), std::numeric_limits<double>::max() ); QVERIFY( !m2.isValid() ); delete vlNullGeom; }
void QgsGeometryMultipartCheck::fixError( const QMap<QString, QgsFeaturePool *> &featurePools, QgsGeometryCheckError *error, int method, const QMap<QString, int> & /*mergeAttributeIndices*/, Changes &changes ) const { QgsFeaturePool *featurePool = featurePools[ error->layerId() ]; QgsFeature feature; if ( !featurePool->getFeature( error->featureId(), feature ) ) { error->setObsolete(); return; } QgsGeometry featureGeom = feature.geometry(); const QgsAbstractGeometry *geom = featureGeom.constGet(); // Check if error still applies if ( geom->partCount() > 1 || !QgsWkbTypes::isMultiType( geom->wkbType() ) ) { error->setObsolete(); return; } // Fix error if ( method == NoChange ) { error->setFixed( method ); } else if ( method == ConvertToSingle ) { feature.setGeometry( QgsGeometry( QgsGeometryCheckerUtils::getGeomPart( geom, 0 )->clone() ) ); featurePool->updateFeature( feature ); error->setFixed( method ); changes[error->layerId()][feature.id()].append( Change( ChangeFeature, ChangeChanged ) ); } else if ( method == RemoveObject ) { featurePool->deleteFeature( feature.id() ); error->setFixed( method ); changes[error->layerId()][feature.id()].append( Change( ChangeFeature, ChangeRemoved ) ); } else { error->setFixFailed( tr( "Unknown method" ) ); } }
void QgsGeometryCheck::replaceFeatureGeometryPart( const QString &layerId, QgsFeature &feature, int partIdx, QgsAbstractGeometry *newPartGeom, Changes &changes ) const { QgsFeaturePool *featurePool = mContext->featurePools[layerId]; QgsGeometry featureGeom = feature.geometry(); QgsAbstractGeometry *geom = featureGeom.get(); if ( QgsGeometryCollection *geomCollection = dynamic_cast< QgsGeometryCollection *>( geom ) ) { geomCollection->removeGeometry( partIdx ); geomCollection->addGeometry( newPartGeom ); changes[layerId][feature.id()].append( Change( ChangePart, ChangeRemoved, QgsVertexId( partIdx ) ) ); changes[layerId][feature.id()].append( Change( ChangePart, ChangeAdded, QgsVertexId( geomCollection->partCount() - 1 ) ) ); feature.setGeometry( featureGeom ); } else { feature.setGeometry( QgsGeometry( newPartGeom ) ); changes[layerId][feature.id()].append( Change( ChangeFeature, ChangeChanged ) ); } featurePool->updateFeature( feature ); }