void QgsMapToolOffsetCurve::setOffsetForRubberBand( double offset, bool leftSide ) { // need at least geos 3.3 for OffsetCurve tool #if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \ ((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3))) if ( !mRubberBand || !mOriginalGeometry ) { return; } QgsVectorLayer* sourceLayer = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( mSourceLayerId ) ); if ( !sourceLayer ) { return; } QgsGeometry geomCopy( *mOriginalGeometry ); const GEOSGeometry* geosGeom = geomCopy.asGeos(); if ( geosGeom ) { QSettings s; int joinStyle = s.value( "/Qgis/digitizing/offset_join_style", 0 ).toInt(); int quadSegments = s.value( "/Qgis/digitizing/offset_quad_seg", 8 ).toInt(); double mitreLimit = s.value( "/Qgis/digitizing/offset_miter_limit", 5.0 ).toDouble(); GEOSGeometry* offsetGeom = GEOSOffsetCurve_r( QgsGeometry::getGEOSHandler(), geosGeom, leftSide ? offset : -offset, quadSegments, joinStyle, mitreLimit ); if ( !offsetGeom ) { deleteRubberBandAndGeometry(); deleteDistanceItem(); delete mSnapVertexMarker; mSnapVertexMarker = 0; mForceCopy = false; mGeometryModified = false; deleteDistanceItem(); emit messageEmitted( tr( "Creating offset geometry failed" ), QgsMessageBar::CRITICAL ); return; } if ( offsetGeom ) { mModifiedGeometry.fromGeos( offsetGeom ); mRubberBand->setToGeometry( &mModifiedGeometry, sourceLayer ); } } #else //GEOS_VERSION>=3.3 Q_UNUSED( offset ); Q_UNUSED( leftSide ); #endif //GEOS_VERSION>=3.3 }
QgsGeometry QgsGeometryAnalyzer::createOffsetGeometry( const QgsGeometry& geom, const QgsGeometry& lineGeom, double offset ) { if ( !geom || lineGeom.isEmpty() ) { return QgsGeometry(); } QList<QgsGeometry> inputGeomList; if ( geom.isMultipart() ) { inputGeomList = geom.asGeometryCollection(); } else { inputGeomList.push_back( geom ); } QList<GEOSGeometry*> outputGeomList; QList<QgsGeometry>::const_iterator inputGeomIt = inputGeomList.constBegin(); GEOSContextHandle_t geosctxt = QgsGeometry::getGEOSHandler(); for ( ; inputGeomIt != inputGeomList.constEnd(); ++inputGeomIt ) { if ( geom.type() == QgsWkbTypes::LineGeometry ) { GEOSGeometry* inputGeomItGeos = inputGeomIt->exportToGeos(); GEOSGeometry* offsetGeom = GEOSOffsetCurve_r( geosctxt, inputGeomItGeos, -offset, 8 /*quadSegments*/, 0 /*joinStyle*/, 5.0 /*mitreLimit*/ ); GEOSGeom_destroy_r( geosctxt, inputGeomItGeos ); if ( !offsetGeom || !GEOSisValid_r( geosctxt, offsetGeom ) ) { return QgsGeometry(); } if ( !GEOSisValid_r( geosctxt, offsetGeom ) || GEOSGeomTypeId_r( geosctxt, offsetGeom ) != GEOS_LINESTRING || GEOSGeomGetNumPoints_r( geosctxt, offsetGeom ) < 1 ) { GEOSGeom_destroy_r( geosctxt, offsetGeom ); return QgsGeometry(); } outputGeomList.push_back( offsetGeom ); } else if ( geom.type() == QgsWkbTypes::PointGeometry ) { QgsPoint p = ( *inputGeomIt ).asPoint(); p = createPointOffset( p.x(), p.y(), offset, lineGeom ); GEOSCoordSequence* ptSeq = GEOSCoordSeq_create_r( geosctxt, 1, 2 ); GEOSCoordSeq_setX_r( geosctxt, ptSeq, 0, p.x() ); GEOSCoordSeq_setY_r( geosctxt, ptSeq, 0, p.y() ); GEOSGeometry* geosPt = GEOSGeom_createPoint_r( geosctxt, ptSeq ); outputGeomList.push_back( geosPt ); } } QgsGeometry outGeometry; if ( !geom.isMultipart() ) { GEOSGeometry* outputGeom = outputGeomList.at( 0 ); if ( outputGeom ) { outGeometry.fromGeos( outputGeom ); } } else { GEOSGeometry** geomArray = new GEOSGeometry*[outputGeomList.size()]; for ( int i = 0; i < outputGeomList.size(); ++i ) { geomArray[i] = outputGeomList.at( i ); } GEOSGeometry* collection = nullptr; if ( geom.type() == QgsWkbTypes::PointGeometry ) { collection = GEOSGeom_createCollection_r( geosctxt, GEOS_MULTIPOINT, geomArray, outputGeomList.size() ); } else if ( geom.type() == QgsWkbTypes::LineGeometry ) { collection = GEOSGeom_createCollection_r( geosctxt, GEOS_MULTILINESTRING, geomArray, outputGeomList.size() ); } outGeometry.fromGeos( collection ); delete[] geomArray; } return outGeometry; }
bool QgsGeometryAnalyzer::createOffsetGeometry( QgsGeometry* geom, QgsGeometry* lineGeom, double offset ) { if ( !geom || !lineGeom ) { return false; } QList<QgsGeometry*> inputGeomList; if ( geom->isMultipart() ) { inputGeomList = geom->asGeometryCollection(); } else { inputGeomList.push_back( geom ); } QList<GEOSGeometry*> outputGeomList; QList<QgsGeometry*>::const_iterator inputGeomIt = inputGeomList.constBegin(); GEOSContextHandle_t geosctxt = QgsGeometry::getGEOSHandler(); for ( ; inputGeomIt != inputGeomList.constEnd(); ++inputGeomIt ) { if ( geom->type() == QGis::Line ) { //geos 3.3 needed for line offsets #if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \ ((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3))) GEOSGeometry* offsetGeom = GEOSOffsetCurve_r( geosctxt, ( *inputGeomIt )->asGeos(), -offset, 8 /*quadSegments*/, 0 /*joinStyle*/, 5.0 /*mitreLimit*/ ); if ( !offsetGeom || !GEOSisValid_r( geosctxt, offsetGeom ) ) { return false; } if ( !GEOSisValid_r( geosctxt, offsetGeom ) || GEOSGeomTypeId_r( geosctxt, offsetGeom ) != GEOS_LINESTRING || GEOSGeomGetNumPoints_r( geosctxt, offsetGeom ) < 1 ) { GEOSGeom_destroy_r( geosctxt, offsetGeom ); return false; } outputGeomList.push_back( offsetGeom ); #else outputGeomList.push_back( GEOSGeom_clone_r( geosctxt, ( *inputGeomIt )->asGeos() ) ); #endif } else if ( geom->type() == QGis::Point ) { QgsPoint p = ( *inputGeomIt )->asPoint(); p = createPointOffset( p.x(), p.y(), offset, lineGeom ); GEOSCoordSequence* ptSeq = GEOSCoordSeq_create_r( geosctxt, 1, 2 ); GEOSCoordSeq_setX_r( geosctxt, ptSeq, 0, p.x() ); GEOSCoordSeq_setY_r( geosctxt, ptSeq, 0, p.y() ); GEOSGeometry* geosPt = GEOSGeom_createPoint_r( geosctxt, ptSeq ); outputGeomList.push_back( geosPt ); } } if ( !geom->isMultipart() ) { GEOSGeometry* outputGeom = outputGeomList.at( 0 ); if ( outputGeom ) { geom->fromGeos( outputGeom ); } } else { GEOSGeometry** geomArray = new GEOSGeometry*[outputGeomList.size()]; for ( int i = 0; i < outputGeomList.size(); ++i ) { geomArray[i] = outputGeomList.at( i ); } GEOSGeometry* collection = 0; if ( geom->type() == QGis::Point ) { collection = GEOSGeom_createCollection_r( geosctxt, GEOS_MULTIPOINT, geomArray, outputGeomList.size() ); } else if ( geom->type() == QGis::Line ) { collection = GEOSGeom_createCollection_r( geosctxt, GEOS_MULTILINESTRING, geomArray, outputGeomList.size() ); } geom->fromGeos( collection ); delete[] geomArray; } return true; }