void QgsMapMouseEvent::snapPoint() { if ( mSnappingMode == NoSnapping ) return; QgsSnappingUtils* snappingUtils = mMapTool->canvas()->snappingUtils(); QgsSnappingUtils::SnapToMapMode canvasMode = snappingUtils->snapToMapMode(); if ( mSnappingMode == SnapAllLayers ) { int type; double tolerance; QgsTolerance::UnitType unit; snappingUtils->defaultSettings( type, tolerance, unit ); snappingUtils->setSnapToMapMode( QgsSnappingUtils::SnapAllLayers ); snappingUtils->setDefaultSettings( QgsPointLocator::Vertex | QgsPointLocator::Edge, tolerance, unit ); mSnapMatch = snappingUtils->snapToMap( mMapPoint ); snappingUtils->setSnapToMapMode( canvasMode ); snappingUtils->setDefaultSettings( type, tolerance, unit ); } else { mSnapMatch = snappingUtils->snapToMap( mMapPoint ); } mMapPoint = mSnapMatch.isValid() ? mSnapMatch.point() : mOriginalPoint; }
void QgsMapToolOffsetCurve::canvasPressEvent( QMouseEvent* e ) { deleteRubberBandAndGeometry(); mGeometryModified = false; mForceCopy = false; if ( !mCanvas ) { return; } //get selected features or snap to nearest feature if no selection QgsVectorLayer* layer = currentVectorLayer(); if ( !layer ) { notifyNotVectorLayer(); return; } QgsSnappingUtils* snapping = mCanvas->snappingUtils(); // store previous settings int oldType; double oldSearchRadius; QgsTolerance::UnitType oldSearchRadiusUnit; QgsSnappingUtils::SnapToMapMode oldMode = snapping->snapToMapMode(); snapping->defaultSettings( oldType, oldSearchRadius, oldSearchRadiusUnit ); // setup new settings (temporary) QSettings settings; snapping->setSnapToMapMode( QgsSnappingUtils::SnapAllLayers ); snapping->setDefaultSettings( QgsPointLocator::Edge, settings.value( "/Qgis/digitizing/search_radius_vertex_edit", 10 ).toDouble(), ( QgsTolerance::UnitType ) settings.value( "/Qgis/digitizing/search_radius_vertex_edit_unit", QgsTolerance::Pixels ).toInt() ); QgsPointLocator::Match match = snapping->snapToMap( e->pos() ); // restore old settings snapping->setSnapToMapMode( oldMode ); snapping->setDefaultSettings( oldType, oldSearchRadius, oldSearchRadiusUnit ); if ( match.hasEdge() && match.layer() ) { mSourceLayerId = match.layer()->id(); QgsFeature fet; if ( match.layer()->getFeatures( QgsFeatureRequest( match.featureId() ) ).nextFeature( fet ) ) { mForceCopy = ( e->modifiers() & Qt::ControlModifier ); //no geometry modification if ctrl is pressed mOriginalGeometry = createOriginGeometry( match.layer(), match, fet ); mRubberBand = createRubberBand(); if ( mRubberBand ) { mRubberBand->setToGeometry( mOriginalGeometry, layer ); } mModifiedFeature = fet.id(); createDistanceItem(); } } }
void testSnapModeAll() { QgsMapSettings mapSettings; mapSettings.setOutputSize( QSize( 100, 100 ) ); mapSettings.setExtent( QgsRectangle( 0, 0, 1, 1 ) ); QVERIFY( mapSettings.hasValidSettings() ); QgsSnappingUtils u; QgsSnappingConfig snappingConfig = u.config(); u.setMapSettings( mapSettings ); snappingConfig.setMode( QgsSnappingConfig::AllLayers ); u.setConfig( snappingConfig ); // right now there are no layers in map settings - snapping will fail QgsPointLocator::Match m = u.snapToMap( QPoint( 100, 100 ) ); QVERIFY( !m.isValid() ); // now check with our layer mapSettings.setLayers( QStringList() << mVL->id() ); u.setMapSettings( mapSettings ); QgsPointLocator::Match m2 = u.snapToMap( QPoint( 100, 100 ) ); QVERIFY( m2.isValid() ); QCOMPARE( m2.point(), QgsPoint( 1, 0 ) ); }
QgsPoint QgsMapMouseEvent::snapPoint( SnappingMode snappingMode ) { // Use cached result if ( mSnappingMode == snappingMode ) return mMapPoint; mSnappingMode = snappingMode; if ( snappingMode == NoSnapping ) { mMapPoint = mOriginalMapPoint; mPixelPoint = pos(); return mMapPoint; } QgsSnappingUtils* snappingUtils = mMapCanvas->snappingUtils(); QgsSnappingUtils::SnapToMapMode canvasMode = snappingUtils->snapToMapMode(); if ( snappingMode == SnapAllLayers ) { int type; double tolerance; QgsTolerance::UnitType unit; snappingUtils->defaultSettings( type, tolerance, unit ); snappingUtils->setSnapToMapMode( QgsSnappingUtils::SnapAllLayers ); snappingUtils->setDefaultSettings( QgsPointLocator::Vertex | QgsPointLocator::Edge, tolerance, unit ); mSnapMatch = snappingUtils->snapToMap( mMapPoint ); snappingUtils->setSnapToMapMode( canvasMode ); snappingUtils->setDefaultSettings( type, tolerance, unit ); } else { mSnapMatch = snappingUtils->snapToMap( mMapPoint ); } if ( mSnapMatch.isValid() ) { mMapPoint = mSnapMatch.point(); mPixelPoint = mapToPixelCoordinates( mMapPoint ); } else { mMapPoint = mOriginalMapPoint; mPixelPoint = pos(); } return mMapPoint; }
QList<QgsPoint> QgsMapMouseEvent::snapSegment( SnappingMode snappingMode, bool* snapped , bool allLayers ) const { QList<QgsPoint> segment; QgsPoint pt1, pt2; // If there's a cached snapping result we use it if ( snappingMode == mSnappingMode && mSnapMatch.hasEdge() ) { mSnapMatch.edgePoints( pt1, pt2 ); segment << pt1 << pt2; } else if ( snappingMode != NoSnapping ) { QgsPointLocator::Match match; if ( snappingMode == SnapProjectConfig && !allLayers ) { // run snapToMap with only segments EdgesOnlyFilter filter; match = mMapCanvas->snappingUtils()->snapToMap( mOriginalMapPoint, &filter ); } else if ( snappingMode == SnapAllLayers || allLayers ) { // run snapToMap with only edges on all layers QgsSnappingUtils* snappingUtils = mMapCanvas->snappingUtils(); QgsSnappingUtils::SnapToMapMode canvasMode = snappingUtils->snapToMapMode(); int type; double tolerance; QgsTolerance::UnitType unit; snappingUtils->defaultSettings( type, tolerance, unit ); snappingUtils->setSnapToMapMode( QgsSnappingUtils::SnapAllLayers ); snappingUtils->setDefaultSettings( QgsPointLocator::Edge, tolerance, unit ); match = snappingUtils->snapToMap( mOriginalMapPoint ); snappingUtils->setSnapToMapMode( canvasMode ); snappingUtils->setDefaultSettings( type, tolerance, unit ); } if ( match.isValid() && match.hasEdge() ) { match.edgePoints( pt1, pt2 ); segment << pt1 << pt2; } } if ( snapped ) { *snapped = segment.count() == 2; } return segment; }
QList<QgsPointXY> QgsAdvancedDigitizingDockWidget::snapSegmentToAllLayers( const QgsPointXY &originalMapPoint, bool *snapped ) const { QList<QgsPointXY> segment; QgsPointXY pt1, pt2; QgsPointLocator::Match match; QgsSnappingUtils *snappingUtils = mMapCanvas->snappingUtils(); QgsSnappingConfig canvasConfig = snappingUtils->config(); QgsSnappingConfig localConfig = snappingUtils->config(); localConfig.setMode( QgsSnappingConfig::AllLayers ); localConfig.setType( QgsSnappingConfig::Segment ); snappingUtils->setConfig( localConfig ); match = snappingUtils->snapToMap( originalMapPoint ); snappingUtils->setConfig( canvasConfig ); if ( match.isValid() && match.hasEdge() ) { match.edgePoints( pt1, pt2 ); segment << pt1 << pt2; } if ( snapped ) { *snapped = segment.count() == 2; } return segment; }
void testSnapModeCurrent() { QgsMapSettings mapSettings; mapSettings.setOutputSize( QSize( 100, 100 ) ); mapSettings.setExtent( QgsRectangle( 0, 0, 1, 1 ) ); QVERIFY( mapSettings.hasValidSettings() ); QgsSnappingUtils u; u.setMapSettings( mapSettings ); u.setCurrentLayer( mVL ); // first try with no snapping enabled u.setDefaultSettings( 0, 10, QgsTolerance::Pixels ); QgsPointLocator::Match m0 = u.snapToMap( QPoint( 100, 100 ) ); QVERIFY( !m0.isValid() ); QVERIFY( !m0.hasVertex() ); // now enable snapping u.setDefaultSettings( QgsPointLocator::Vertex | QgsPointLocator::Edge, 10, QgsTolerance::Pixels ); QgsPointLocator::Match m = u.snapToMap( QPoint( 100, 100 ) ); QVERIFY( m.isValid() ); QVERIFY( m.hasVertex() ); QCOMPARE( m.point(), QgsPoint( 1, 0 ) ); QgsPointLocator::Match m2 = u.snapToMap( QPoint( 0, 100 ) ); QVERIFY( !m2.isValid() ); QVERIFY( !m2.hasVertex() ); // do not consider edges in the following test - on 32-bit platforms // result was an edge match very close to (1,0) instead of being exactly (1,0) u.setDefaultSettings( QgsPointLocator::Vertex, 10, QgsTolerance::Pixels ); // test with filtering FilterExcludePoint myFilter( QgsPoint( 1, 0 ) ); QgsPointLocator::Match m3 = u.snapToMap( QPoint( 100, 100 ), &myFilter ); QVERIFY( !m3.isValid() ); }
void testSnapOnIntersection() { // testing with a layer with two crossing linestrings // (0,1) x x (1,1) // \/ // /\ . // (0,0) x x (1,0) QgsVectorLayer* vl = new QgsVectorLayer( QStringLiteral( "LineString" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) ); QgsPolyline polyline1, polyline2; polyline1 << QgsPoint( 0, 0 ) << QgsPoint( 1, 1 ); polyline2 << QgsPoint( 1, 0 ) << QgsPoint( 0, 1 ); QgsFeature f1; QgsGeometry f1g = QgsGeometry::fromPolyline( polyline1 ) ; f1.setGeometry( f1g ); QgsFeature f2; QgsGeometry f2g = QgsGeometry::fromPolyline( polyline2 ); f2.setGeometry( f2g ); QgsFeatureList flist; flist << f1 << f2; vl->dataProvider()->addFeatures( flist ); QVERIFY( vl->dataProvider()->featureCount() == 2 ); QgsMapSettings mapSettings; mapSettings.setOutputSize( QSize( 100, 100 ) ); mapSettings.setExtent( QgsRectangle( 0, 0, 1, 1 ) ); QVERIFY( mapSettings.hasValidSettings() ); QgsSnappingUtils u; u.setMapSettings( mapSettings ); QgsSnappingConfig snappingConfig = u.config(); snappingConfig.setMode( QgsSnappingConfig::AdvancedConfiguration ); QgsSnappingConfig::IndividualLayerSettings layerSettings( true, QgsSnappingConfig::Vertex, 0.1, QgsTolerance::ProjectUnits ); snappingConfig.setIndividualLayerSettings( vl, layerSettings ); u.setConfig( snappingConfig ); // no snapping on intersections by default - should find nothing QgsPointLocator::Match m = u.snapToMap( QgsPoint( 0.45, 0.5 ) ); QVERIFY( !m.isValid() ); snappingConfig.setIntersectionSnapping( true ); u.setConfig( snappingConfig ); QgsPointLocator::Match m2 = u.snapToMap( QgsPoint( 0.45, 0.5 ) ); QVERIFY( m2.isValid() ); QCOMPARE( m2.type(), QgsPointLocator::Vertex ); QCOMPARE( m2.point(), QgsPoint( 0.5, 0.5 ) ); delete vl; }
void testSnapModeAdvanced() { QgsMapSettings mapSettings; mapSettings.setOutputSize( QSize( 100, 100 ) ); mapSettings.setExtent( QgsRectangle( 0, 0, 1, 1 ) ); QVERIFY( mapSettings.hasValidSettings() ); QgsSnappingUtils u; u.setMapSettings( mapSettings ); u.setSnapToMapMode( QgsSnappingUtils::SnapAdvanced ); QList<QgsSnappingUtils::LayerConfig> layers; layers << QgsSnappingUtils::LayerConfig( mVL, QgsPointLocator::Vertex, 10, QgsTolerance::Pixels ); u.setLayers( layers ); QgsPointLocator::Match m = u.snapToMap( QPoint( 100, 100 ) ); QVERIFY( m.isValid() ); QVERIFY( m.hasVertex() ); QCOMPARE( m.point(), QgsPoint( 1, 0 ) ); // test with filtering FilterExcludePoint myFilter( QgsPoint( 1, 0 ) ); QgsPointLocator::Match m2 = u.snapToMap( QPoint( 100, 100 ), &myFilter ); QVERIFY( !m2.isValid() ); }
void testSnapModeAdvanced() { QgsMapSettings mapSettings; mapSettings.setOutputSize( QSize( 100, 100 ) ); mapSettings.setExtent( QgsRectangle( 0, 0, 1, 1 ) ); QVERIFY( mapSettings.hasValidSettings() ); QgsSnappingUtils u; QgsSnappingConfig snappingConfig = u.config(); u.setMapSettings( mapSettings ); snappingConfig.setMode( QgsSnappingConfig::AdvancedConfiguration ); snappingConfig.setIndividualLayerSettings( mVL, QgsSnappingConfig::IndividualLayerSettings( true, QgsSnappingConfig::Vertex, 10, QgsTolerance::Pixels ) ); u.setConfig( snappingConfig ); QgsPointLocator::Match m = u.snapToMap( QPoint( 100, 100 ) ); QVERIFY( m.isValid() ); QVERIFY( m.hasVertex() ); QCOMPARE( m.point(), QgsPoint( 1, 0 ) ); // test with filtering FilterExcludePoint myFilter( QgsPoint( 1, 0 ) ); QgsPointLocator::Match m2 = u.snapToMap( QPoint( 100, 100 ), &myFilter ); QVERIFY( !m2.isValid() ); }