int QgsMapToolCapture::addVertex( const QPoint &p ) { QgsPoint layerPoint; QgsPoint mapPoint; if ( mode() == CaptureNone ) { QgsDebugMsg( "invalid capture mode" ); return 2; } int res = nextPoint( p, layerPoint, mapPoint ); if ( res != 0 ) { QgsDebugMsg( "nextPoint failed: " + QString::number( res ) ); return res; } if ( !mRubberBand ) { mRubberBand = createRubberBand( mCaptureMode == CapturePolygon ? QGis::Polygon : QGis::Line ); } mRubberBand->addPoint( mapPoint ); mCaptureList.append( layerPoint ); if ( !mTempRubberBand ) { mTempRubberBand = createRubberBand( mCaptureMode == CapturePolygon ? QGis::Polygon : QGis::Line , true ); } else { mTempRubberBand->reset( mCaptureMode == CapturePolygon ? true : false ); } if ( mCaptureMode == CaptureLine ) { mTempRubberBand->addPoint( mapPoint ); } else if ( mCaptureMode == CapturePolygon ) { const QgsPoint *firstPoint = mRubberBand->getPoint( 0 , 0 ); mTempRubberBand->addPoint( *firstPoint ); mTempRubberBand->movePoint( mapPoint ); mTempRubberBand->addPoint( mapPoint ); } validateGeometry(); return 0; }
void QgsMapToolDeletePart::canvasPressEvent( QgsMapMouseEvent *e ) { mPressedFid = -1; mPressedPartNum = -1; delete mRubberBand; mRubberBand = nullptr; QgsMapLayer *currentLayer = mCanvas->currentLayer(); if ( !currentLayer ) return; vlayer = qobject_cast<QgsVectorLayer *>( currentLayer ); if ( !vlayer ) { notifyNotVectorLayer(); return; } if ( !vlayer->isEditable() ) { notifyNotEditableLayer(); return; } QgsGeometry geomPart = partUnderPoint( e->pos(), mPressedFid, mPressedPartNum ); if ( mPressedFid != -1 ) { mRubberBand = createRubberBand( vlayer->geometryType() ); mRubberBand->setToGeometry( geomPart, vlayer ); mRubberBand->show(); } }
void QgsMapToolMeasureAngle::canvasReleaseEvent( QMouseEvent * e ) { //add points until we have three if ( mAnglePoints.size() == 3 ) { mAnglePoints.clear(); } if ( mAnglePoints.size() < 1 ) { if ( mResultDisplay == NULL ) { mResultDisplay = new QgsDisplayAngle( this, Qt::WindowStaysOnTopHint ); QObject::connect( mResultDisplay, SIGNAL( rejected() ), this, SLOT( stopMeasuring() ) ); } configureDistanceArea(); createRubberBand(); } if ( mAnglePoints.size() < 3 ) { QgsPoint newPoint = snapPoint( e->pos() ); mAnglePoints.push_back( newPoint ); mRubberBand->addPoint( newPoint ); } }
void QgsMapToolCapture::canvasMapMoveEvent( QgsMapMouseEvent * e ) { bool snapped = e->isSnapped(); QgsPoint point = e->mapPoint(); if ( !snapped ) { delete mSnappingMarker; mSnappingMarker = 0; } else { if ( !mSnappingMarker ) { mSnappingMarker = new QgsVertexMarker( mCanvas ); mSnappingMarker->setIconType( QgsVertexMarker::ICON_CROSS ); mSnappingMarker->setColor( Qt::magenta ); mSnappingMarker->setPenWidth( 3 ); } mSnappingMarker->setCenter( point ); } if ( !mTempRubberBand && mCaptureCurve.numPoints() > 0 ) { mTempRubberBand = createRubberBand( mCaptureMode == CapturePolygon ? QGis::Polygon : QGis::Line, true ); QgsPointV2 pt = mCaptureCurve.endPoint(); mTempRubberBand->addPoint( QgsPoint( pt.x(), pt.y() ) ); mTempRubberBand->addPoint( point ); } if ( mCaptureMode != CapturePoint && mTempRubberBand && mCapturing ) { mTempRubberBand->movePoint( point ); } } // mouseMoveEvent
void QgsGPSInformationWidget::addVertex() { QgsDebugMsg( "Adding Vertex" ); if ( !mpRubberBand ) { createRubberBand(); } // we store the capture list in wgs84 and then transform to layer crs when // calling close feature mCaptureList.push_back( mLastGpsPosition ); // we store the rubber band points in map canvas CRS so transform to map crs // potential problem with transform errors and wrong coordinates if map CRS is changed after points are stored - SLM // should catch map CRS change and transform the points QgsPointXY myPoint; if ( mpCanvas ) { QgsCoordinateTransform t( mWgs84CRS, mpCanvas->mapSettings().destinationCrs() ); myPoint = t.transform( mLastGpsPosition ); } else { myPoint = mLastGpsPosition; } mpRubberBand->addPoint( myPoint ); }
int QgsMapToolCapture::addVertex( const QgsPoint& point ) { if ( mode() == CaptureNone ) { QgsDebugMsg( "invalid capture mode" ); return 2; } int res; QgsPoint layerPoint; res = nextPoint( point, layerPoint ); if ( res != 0 ) { return res; } if ( !mRubberBand ) { mRubberBand = createRubberBand( mCaptureMode == CapturePolygon ? QGis::Polygon : QGis::Line ); } mRubberBand->addPoint( point ); mCaptureCurve.addVertex( QgsPointV2( layerPoint.x(), layerPoint.y() ) ); if ( !mTempRubberBand ) { mTempRubberBand = createRubberBand( mCaptureMode == CapturePolygon ? QGis::Polygon : QGis::Line, true ); } else { mTempRubberBand->reset( mCaptureMode == CapturePolygon ? true : false ); } if ( mCaptureMode == CaptureLine ) { mTempRubberBand->addPoint( point ); } else if ( mCaptureMode == CapturePolygon ) { const QgsPoint *firstPoint = mRubberBand->getPoint( 0, 0 ); mTempRubberBand->addPoint( *firstPoint ); mTempRubberBand->movePoint( point ); mTempRubberBand->addPoint( point ); } validateGeometry(); return 0; }
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(); } } }
int QgsMapToolCapture::addCurve( QgsCurve *c ) { if ( !c ) { return 1; } if ( !mRubberBand ) { mRubberBand = createRubberBand( mCaptureMode == CapturePolygon ? QgsWkbTypes::PolygonGeometry : QgsWkbTypes::LineGeometry ); } QgsLineString *lineString = c->curveToLine(); QgsPointSequence linePoints; lineString->points( linePoints ); delete lineString; QgsPointSequence::const_iterator ptIt = linePoints.constBegin(); for ( ; ptIt != linePoints.constEnd(); ++ptIt ) { mRubberBand->addPoint( QgsPointXY( ptIt->x(), ptIt->y() ) ); } if ( !mTempRubberBand ) { mTempRubberBand = createRubberBand( mCaptureMode == CapturePolygon ? QgsWkbTypes::PolygonGeometry : QgsWkbTypes::LineGeometry, true ); } else { mTempRubberBand->reset(); } QgsPoint endPt = c->endPoint(); mTempRubberBand->addPoint( QgsPointXY( endPt.x(), endPt.y() ) ); //add last point of c //transform back to layer CRS in case map CRS and layer CRS are different QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() ); QgsCoordinateTransform ct = mCanvas->mapSettings().layerTransform( vlayer ); if ( ct.isValid() ) { c->transform( ct, QgsCoordinateTransform::ReverseTransform ); } mCaptureCurve.addCurve( c ); for ( int i = 0; i < c->length(); ++i ) mSnappingMatches.append( QgsPointLocator::Match() ); return 0; }
int QgsMapToolCapture::addCurve( QgsCurveV2* c ) { if ( !c ) { return 1; } if ( !mRubberBand ) { mRubberBand = createRubberBand( mCaptureMode == CapturePolygon ? QGis::Polygon : QGis::Line ); } QgsLineStringV2* lineString = c->curveToLine(); QList<QgsPointV2> linePoints; lineString->points( linePoints ); delete lineString; QList<QgsPointV2>::const_iterator ptIt = linePoints.constBegin(); for ( ; ptIt != linePoints.constEnd(); ++ptIt ) { mRubberBand->addPoint( QgsPoint( ptIt->x(), ptIt->y() ) ); } if ( !mTempRubberBand ) { mTempRubberBand = createRubberBand( mCaptureMode == CapturePolygon ? QGis::Polygon : QGis::Line, true ); } else { mTempRubberBand->reset(); } QgsPointV2 endPt = c->endPoint(); mTempRubberBand->addPoint( QgsPoint( endPt.x(), endPt.y() ) ); //add last point of c //transform back to layer CRS in case map CRS and layer CRS are different QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() ); const QgsCoordinateTransform* ct = mCanvas->mapSettings().layerTransform( vlayer ); if ( ct ) { c->transform( *ct, QgsCoordinateTransform::ReverseTransform ); } mCaptureCurve.addCurve( c ); return 0; }
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; } QgsMapRenderer* renderer = mCanvas->mapRenderer(); QgsSnapper snapper( renderer ); configureSnapper( snapper ); QList<QgsSnappingResult> snapResults; snapper.snapPoint( e->pos(), snapResults ); if ( snapResults.size() > 0 ) { QgsFeature fet; const QgsSnappingResult& snapResult = snapResults.at( 0 ); if ( snapResult.layer ) { mSourceLayerId = snapResult.layer->id(); QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( mSourceLayerId ) ); if ( vl && vl->getFeatures( QgsFeatureRequest().setFilterFid( snapResult.snappedAtGeometry ) ).nextFeature( fet ) ) { mForceCopy = ( e->modifiers() & Qt::ControlModifier ); //no geometry modification if ctrl is pressed mOriginalGeometry = createOriginGeometry( vl, snapResult, fet ); mRubberBand = createRubberBand(); if ( mRubberBand ) { mRubberBand->setToGeometry( mOriginalGeometry, layer ); } mModifiedFeature = fet.id(); createDistanceItem(); } } } }
void QgsMapToolDeleteRing::canvasPressEvent( QgsMapMouseEvent* e ) { delete mRubberBand; mRubberBand = 0; mPressedFid = -1; mPressedPartNum = -1; mPressedRingNum = -1; QgsMapLayer* currentLayer = mCanvas->currentLayer(); if ( !currentLayer ) return; vlayer = qobject_cast<QgsVectorLayer *>( currentLayer ); if ( !vlayer ) { notifyNotVectorLayer(); return; } if ( vlayer->geometryType() != QGis::Polygon ) { emit messageEmitted( tr( "Delete ring can only be used in a polygon layer." ) ); return; } if ( !vlayer->isEditable() ) { notifyNotEditableLayer(); return; } QgsPoint p = toLayerCoordinates( vlayer, e->pos() ); QgsGeometry* ringGeom = ringUnderPoint( p, mPressedFid, mPressedPartNum, mPressedRingNum ); if ( mPressedFid != -1 ) { QgsFeature f; vlayer->getFeatures( QgsFeatureRequest().setFilterFid( mPressedFid ) ).nextFeature( f ); mRubberBand = createRubberBand( vlayer->geometryType() ); mRubberBand->setToGeometry( ringGeom, vlayer ); mRubberBand->show(); } delete ringGeom; ringGeom = 0; }
void QgsMapToolCapture::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { QgsMapToolAdvancedDigitizing::cadCanvasMoveEvent( e ); QgsPointXY point = e->mapPoint(); mSnapIndicator->setMatch( e->mapPointMatch() ); if ( !mTempRubberBand && mCaptureCurve.numPoints() > 0 ) { mTempRubberBand = createRubberBand( mCaptureMode == CapturePolygon ? QgsWkbTypes::PolygonGeometry : QgsWkbTypes::LineGeometry, true ); QgsPoint pt = mCaptureCurve.endPoint(); mTempRubberBand->addPoint( QgsPointXY( pt.x(), pt.y() ) ); mTempRubberBand->addPoint( point ); } if ( mCaptureMode != CapturePoint && mTempRubberBand && mCapturing ) { bool hasTrace = false; if ( tracingEnabled() && mCaptureCurve.numPoints() != 0 ) { hasTrace = tracingMouseMove( e ); } if ( !hasTrace ) { if ( mCaptureCurve.numPoints() > 0 ) { // fix temporary rubber band after tracing which may have added multiple points mTempRubberBand->reset( mCaptureMode == CapturePolygon ? QgsWkbTypes::PolygonGeometry : QgsWkbTypes::LineGeometry ); if ( mCaptureMode == CapturePolygon ) mTempRubberBand->addPoint( *mRubberBand->getPoint( 0, 0 ), false ); QgsPoint pt = mCaptureCurve.endPoint(); QgsPointXY mapPt = toMapCoordinates( qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() ), QgsPointXY( pt.x(), pt.y() ) ); mTempRubberBand->addPoint( mapPt ); mTempRubberBand->addPoint( point ); // fix existing rubber band after tracing - the last point may have been moved if using offset if ( mRubberBand->numberOfVertices() ) mRubberBand->movePoint( mapPt ); } else mTempRubberBand->movePoint( point ); } } } // mouseMoveEvent
void QgsMapToolMeasureAngle::canvasReleaseEvent( QMouseEvent * e ) { //add points until we have three if ( mAnglePoints.size() == 3 ) { mAnglePoints.clear(); } if ( mAnglePoints.size() < 1 ) { createRubberBand(); } if ( mAnglePoints.size() < 3 ) { QgsPoint newPoint = snapPoint( e->pos() ); mAnglePoints.push_back( newPoint ); mRubberBand->addPoint( newPoint ); } }
void QgsMapToolMoveFeature::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { QgsVectorLayer *vlayer = currentVectorLayer(); if ( !vlayer || !vlayer->isEditable() ) { delete mRubberBand; mRubberBand = nullptr; mSnapIndicator->setMatch( QgsPointLocator::Match() ); cadDockWidget()->clear(); notifyNotEditableLayer(); return; } if ( !mRubberBand ) { //find first geometry under mouse cursor and store iterator to it QgsPointXY layerCoords = toLayerCoordinates( vlayer, e->mapPoint() ); double searchRadius = QgsTolerance::vertexSearchRadius( mCanvas->currentLayer(), mCanvas->mapSettings() ); QgsRectangle selectRect( layerCoords.x() - searchRadius, layerCoords.y() - searchRadius, layerCoords.x() + searchRadius, layerCoords.y() + searchRadius ); if ( vlayer->selectedFeatureCount() == 0 ) { QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( selectRect ).setNoAttributes() ); //find the closest feature QgsGeometry pointGeometry = QgsGeometry::fromPointXY( layerCoords ); if ( pointGeometry.isNull() ) { cadDockWidget()->clear(); return; } double minDistance = std::numeric_limits<double>::max(); QgsFeature cf; QgsFeature f; while ( fit.nextFeature( f ) ) { if ( f.hasGeometry() ) { double currentDistance = pointGeometry.distance( f.geometry() ); if ( currentDistance < minDistance ) { minDistance = currentDistance; cf = f; } } } if ( minDistance == std::numeric_limits<double>::max() ) { cadDockWidget()->clear(); return; } mMovedFeatures.clear(); mMovedFeatures << cf.id(); //todo: take the closest feature, not the first one... mRubberBand = createRubberBand( vlayer->geometryType() ); mRubberBand->setToGeometry( cf.geometry(), vlayer ); } else { mMovedFeatures = vlayer->selectedFeatureIds(); mRubberBand = createRubberBand( vlayer->geometryType() ); QgsFeature feat; QgsFeatureIterator it = vlayer->getSelectedFeatures( QgsFeatureRequest().setNoAttributes() ); bool allFeaturesInView = true; QgsRectangle viewRect = mCanvas->mapSettings().mapToLayerCoordinates( vlayer, mCanvas->extent() ); while ( it.nextFeature( feat ) ) { mRubberBand->addGeometry( feat.geometry(), vlayer ); if ( allFeaturesInView && !viewRect.intersects( feat.geometry().boundingBox() ) ) allFeaturesInView = false; } if ( !allFeaturesInView ) { // for extra safety to make sure we are not modifying geometries by accident int res = QMessageBox::warning( mCanvas, tr( "Move features" ), tr( "Some of the selected features are outside of the current map view. Would you still like to continue?" ), QMessageBox::Yes | QMessageBox::No ); if ( res != QMessageBox::Yes ) { mMovedFeatures.clear(); delete mRubberBand; mRubberBand = nullptr; mSnapIndicator->setMatch( QgsPointLocator::Match() ); return; } } } mStartPointMapCoords = e->mapPoint(); mRubberBand->show(); } else { // copy and move mode if ( e->button() != Qt::LeftButton ) { cadDockWidget()->clear(); delete mRubberBand; mRubberBand = nullptr; mSnapIndicator->setMatch( QgsPointLocator::Match() ); return; } QgsPointXY startPointLayerCoords = toLayerCoordinates( ( QgsMapLayer * )vlayer, mStartPointMapCoords ); QgsPointXY stopPointLayerCoords = toLayerCoordinates( ( QgsMapLayer * )vlayer, e->mapPoint() ); double dx = stopPointLayerCoords.x() - startPointLayerCoords.x(); double dy = stopPointLayerCoords.y() - startPointLayerCoords.y(); vlayer->beginEditCommand( mMode == Move ? tr( "Feature moved" ) : tr( "Feature copied and moved" ) ); switch ( mMode ) { case Move: Q_FOREACH ( QgsFeatureId id, mMovedFeatures ) { vlayer->translateFeature( id, dx, dy ); } delete mRubberBand; mRubberBand = nullptr; mSnapIndicator->setMatch( QgsPointLocator::Match() ); cadDockWidget()->clear(); break; case CopyMove: QgsFeatureRequest request; request.setFilterFids( mMovedFeatures ); QString *errorMsg = new QString(); if ( !QgisApp::instance()->vectorLayerTools()->copyMoveFeatures( vlayer, request, dx, dy, errorMsg ) ) { emit messageEmitted( *errorMsg, Qgis::Critical ); delete mRubberBand; mRubberBand = nullptr; mSnapIndicator->setMatch( QgsPointLocator::Match() ); } break; } vlayer->endEditCommand(); vlayer->triggerRepaint(); }
void QgsMapToolOffsetCurve::canvasReleaseEvent( QgsMapMouseEvent *e ) { mCtrlHeldOnFirstClick = false; if ( e->button() == Qt::RightButton ) { cancel(); return; } if ( mOriginalGeometry.isNull() ) { // first click, get feature to modify deleteRubberBandAndGeometry(); mGeometryModified = false; QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToCurrentLayer( e->pos(), QgsPointLocator::Types( QgsPointLocator::Edge | QgsPointLocator::Area ) ); if ( ( match.hasEdge() || match.hasArea() ) && match.layer() ) { mLayer = match.layer(); QgsFeature fet; if ( match.layer()->getFeatures( QgsFeatureRequest( match.featureId() ) ).nextFeature( fet ) ) { mCtrlHeldOnFirstClick = ( e->modifiers() & Qt::ControlModifier ); //no geometry modification if ctrl is pressed prepareGeometry( match, fet ); mRubberBand = createRubberBand(); if ( mRubberBand ) { mRubberBand->setToGeometry( mManipulatedGeometry, match.layer() ); } mModifiedFeature = fet.id(); createUserInputWidget(); bool hasZ = QgsWkbTypes::hasZ( mLayer->wkbType() ); bool hasM = QgsWkbTypes::hasZ( mLayer->wkbType() ); if ( hasZ || hasM ) { emit messageEmitted( QStringLiteral( "layer %1 has %2%3%4 geometry. %2%3%4 values be set to 0 when using offset tool." ) .arg( mLayer->name() ) .arg( hasZ ? "Z" : "" ) .arg( hasZ && hasM ? "/" : "" ) .arg( hasM ? "M" : "" ) , Qgis::Warning ); } } } if ( mOriginalGeometry.isNull() ) { emit messageEmitted( tr( "Could not find a nearby feature in any vector layer." ) ); cancel(); notifyNotVectorLayer(); } } else { // second click - apply changes double offset = calculateOffset( e->snapPoint() ); applyOffset( offset, e->modifiers() ); } }
void QgsMapToolRotateFeature::canvasReleaseEvent( QgsMapMouseEvent *e ) { if ( !mCanvas ) { return; } QgsVectorLayer *vlayer = currentVectorLayer(); if ( !vlayer ) { deleteRotationWidget(); deleteRubberband(); notifyNotVectorLayer(); return; } if ( e->button() == Qt::RightButton ) { cancel(); return; } // place anchor point on CTRL + click if ( e->modifiers() & Qt::ControlModifier ) { if ( !mAnchorPoint ) { return; } mAnchorPoint->setCenter( toMapCoordinates( e->pos() ) ); mStartPointMapCoords = toMapCoordinates( e->pos() ); mStPoint = e->pos(); return; } deleteRotationWidget(); // Initialize rotation if not yet active if ( !mRotationActive ) { mRotation = 0; mRotationOffset = 0; deleteRubberband(); mInitialPos = e->pos(); if ( !vlayer->isEditable() ) { notifyNotEditableLayer(); return; } QgsPointXY layerCoords = toLayerCoordinates( vlayer, e->pos() ); double searchRadius = QgsTolerance::vertexSearchRadius( mCanvas->currentLayer(), mCanvas->mapSettings() ); QgsRectangle selectRect( layerCoords.x() - searchRadius, layerCoords.y() - searchRadius, layerCoords.x() + searchRadius, layerCoords.y() + searchRadius ); if ( vlayer->selectedFeatureCount() == 0 ) { QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( selectRect ).setNoAttributes() ); //find the closest feature QgsGeometry pointGeometry = QgsGeometry::fromPointXY( layerCoords ); if ( pointGeometry.isNull() ) { return; } double minDistance = std::numeric_limits<double>::max(); QgsFeature cf; QgsFeature f; while ( fit.nextFeature( f ) ) { if ( f.hasGeometry() ) { double currentDistance = pointGeometry.distance( f.geometry() ); if ( currentDistance < minDistance ) { minDistance = currentDistance; cf = f; } } } if ( minDistance == std::numeric_limits<double>::max() ) { emit messageEmitted( tr( "Could not find a nearby feature in the current layer." ) ); return; } QgsRectangle bound = cf.geometry().boundingBox(); mStartPointMapCoords = toMapCoordinates( vlayer, bound.center() ); if ( !mAnchorPoint ) { mAnchorPoint = qgis::make_unique<QgsVertexMarker>( mCanvas ); } mAnchorPoint->setIconType( QgsVertexMarker::ICON_CROSS ); mAnchorPoint->setCenter( mStartPointMapCoords ); mStPoint = toCanvasCoordinates( mStartPointMapCoords ); mRotatedFeatures.clear(); mRotatedFeatures << cf.id(); //todo: take the closest feature, not the first one... mRubberBand = createRubberBand( vlayer->geometryType() ); mRubberBand->setToGeometry( cf.geometry(), vlayer ); } else { mRotatedFeatures = vlayer->selectedFeatureIds(); mRubberBand = createRubberBand( vlayer->geometryType() ); QgsFeature feat; QgsFeatureIterator it = vlayer->getSelectedFeatures(); while ( it.nextFeature( feat ) ) { mRubberBand->addGeometry( feat.geometry(), vlayer ); } } mRubberBand->show(); double XDistance = mInitialPos.x() - mAnchorPoint->x(); double YDistance = mInitialPos.y() - mAnchorPoint->y(); mRotationOffset = std::atan2( YDistance, XDistance ) * ( 180 / M_PI ); createRotationWidget(); if ( e->modifiers() & Qt::ShiftModifier ) { if ( mRotationWidget ) { mRotationWidget->setMagnet( 45 ); } } mRotationActive = true; return; } applyRotation( mRotation ); }
void QgsMapToolMoveFeature::canvasPressEvent( QgsMapMouseEvent* e ) { delete mRubberBand; mRubberBand = nullptr; QgsVectorLayer* vlayer = currentVectorLayer(); if ( !vlayer ) { notifyNotVectorLayer(); return; } if ( !vlayer->isEditable() ) { notifyNotEditableLayer(); return; } //find first geometry under mouse cursor and store iterator to it QgsPoint layerCoords = toLayerCoordinates( vlayer, e->pos() ); QSettings settings; double searchRadius = QgsTolerance::vertexSearchRadius( mCanvas->currentLayer(), mCanvas->mapSettings() ); QgsRectangle selectRect( layerCoords.x() - searchRadius, layerCoords.y() - searchRadius, layerCoords.x() + searchRadius, layerCoords.y() + searchRadius ); if ( vlayer->selectedFeatureCount() == 0 ) { QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( selectRect ).setSubsetOfAttributes( QgsAttributeList() ) ); //find the closest feature QgsGeometry* pointGeometry = QgsGeometry::fromPoint( layerCoords ); if ( !pointGeometry ) { return; } double minDistance = std::numeric_limits<double>::max(); QgsFeature cf; QgsFeature f; while ( fit.nextFeature( f ) ) { if ( f.constGeometry() ) { double currentDistance = pointGeometry->distance( *f.constGeometry() ); if ( currentDistance < minDistance ) { minDistance = currentDistance; cf = f; } } } delete pointGeometry; if ( minDistance == std::numeric_limits<double>::max() ) { return; } mMovedFeatures.clear(); mMovedFeatures << cf.id(); //todo: take the closest feature, not the first one... mRubberBand = createRubberBand( vlayer->geometryType() ); mRubberBand->setToGeometry( cf.constGeometry(), vlayer ); } else { mMovedFeatures = vlayer->selectedFeaturesIds(); mRubberBand = createRubberBand( vlayer->geometryType() ); QgsFeature feat; QgsFeatureIterator it = vlayer->selectedFeaturesIterator( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ) ); while ( it.nextFeature( feat ) ) { mRubberBand->addGeometry( feat.constGeometry(), vlayer ); } } mStartPointMapCoords = toMapCoordinates( e->pos() ); mRubberBand->setColor( QColor( 255, 0, 0, 65 ) ); mRubberBand->setWidth( 2 ); mRubberBand->show(); }
void QgsMapToolRotateFeature::canvasPressEvent( QMouseEvent * e ) { mRotation = 0; if ( mCtrl ) { return; } delete mRubberBand; mRubberBand = 0; mInitialPos = e->pos(); QgsVectorLayer* vlayer = currentVectorLayer(); if ( !vlayer ) { notifyNotVectorLayer(); return; } if ( !vlayer->isEditable() ) { notifyNotEditableLayer(); return; } QgsPoint layerCoords = toLayerCoordinates( vlayer, e->pos() ); double searchRadius = QgsTolerance::vertexSearchRadius( mCanvas->currentLayer(), mCanvas->mapSettings() ); QgsRectangle selectRect( layerCoords.x() - searchRadius, layerCoords.y() - searchRadius, layerCoords.x() + searchRadius, layerCoords.y() + searchRadius ); if ( vlayer->selectedFeatureCount() == 0 ) { QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( selectRect ).setSubsetOfAttributes( QgsAttributeList() ) ); //find the closest feature QgsGeometry* pointGeometry = QgsGeometry::fromPoint( layerCoords ); if ( !pointGeometry ) { return; } double minDistance = std::numeric_limits<double>::max(); QgsFeature cf; QgsFeature f; while ( fit.nextFeature( f ) ) { if ( f.geometry() ) { double currentDistance = pointGeometry->distance( *f.geometry() ); if ( currentDistance < minDistance ) { minDistance = currentDistance; cf = f; } } } delete pointGeometry; if ( minDistance == std::numeric_limits<double>::max() ) { return; } QgsRectangle bound = cf.geometry()->boundingBox(); mStartPointMapCoords = toMapCoordinates( vlayer, bound.center() ); if ( !mAnchorPoint ) { mAnchorPoint = new QgsVertexMarker( mCanvas ); } mAnchorPoint->setIconType( QgsVertexMarker::ICON_CROSS ); mAnchorPoint->setCenter( mStartPointMapCoords ); mStPoint = toCanvasCoordinates( mStartPointMapCoords ); mRotatedFeatures.clear(); mRotatedFeatures << cf.id(); //todo: take the closest feature, not the first one... mRubberBand = createRubberBand( vlayer->geometryType() ); mRubberBand->setToGeometry( cf.geometry(), vlayer ); } else { mRotatedFeatures = vlayer->selectedFeaturesIds(); mRubberBand = createRubberBand( vlayer->geometryType() ); QgsFeature feat; QgsFeatureIterator it = vlayer->selectedFeaturesIterator(); while ( it.nextFeature( feat ) ) { mRubberBand->addGeometry( feat.geometry(), vlayer ); } } mRubberBand->setColor( QColor( 255, 0, 0, 65 ) ); mRubberBand->setWidth( 2 ); mRubberBand->show(); double XDistance = mInitialPos.x() - mAnchorPoint->x(); double YDistance = mInitialPos.y() - mAnchorPoint->y() ; mRotationOffset = atan2( YDistance, XDistance ) * ( 180 / PI ); }
int QgsMapToolCapture::addVertex( const QgsPointXY &point, const QgsPointLocator::Match &match ) { if ( mode() == CaptureNone ) { QgsDebugMsg( QStringLiteral( "invalid capture mode" ) ); return 2; } int res; QgsPoint layerPoint; res = fetchLayerPoint( match, layerPoint ); if ( res != 0 ) { res = nextPoint( QgsPoint( point ), layerPoint ); if ( res != 0 ) { return res; } } if ( !mRubberBand ) { mRubberBand = createRubberBand( mCaptureMode == CapturePolygon ? QgsWkbTypes::PolygonGeometry : QgsWkbTypes::LineGeometry ); } if ( !mTempRubberBand ) { mTempRubberBand = createRubberBand( mCaptureMode == CapturePolygon ? QgsWkbTypes::PolygonGeometry : QgsWkbTypes::LineGeometry, true ); } else { mTempRubberBand->reset( mCaptureMode == CapturePolygon ? QgsWkbTypes::PolygonGeometry : QgsWkbTypes::LineGeometry ); } bool traceCreated = false; if ( tracingEnabled() ) { traceCreated = tracingAddVertex( point ); } // keep new tracing start point if we created a trace. This is useful when tracing with // offset so that the user stays "snapped" mTracingStartPoint = traceCreated ? point : QgsPointXY(); if ( !traceCreated ) { // ordinary digitizing mRubberBand->addPoint( point ); mCaptureCurve.addVertex( layerPoint ); mSnappingMatches.append( match ); } if ( mCaptureMode == CaptureLine ) { mTempRubberBand->addPoint( point ); } else if ( mCaptureMode == CapturePolygon ) { const QgsPointXY *firstPoint = mRubberBand->getPoint( 0, 0 ); mTempRubberBand->addPoint( *firstPoint ); mTempRubberBand->movePoint( point ); mTempRubberBand->addPoint( point ); } validateGeometry(); return 0; }