void QgsMapToolCapture::canvasMoveEvent( QMouseEvent * e ) { QgsPoint mapPoint; QList<QgsSnappingResult> snapResults; if ( mSnapper.snapToBackgroundLayers( e->pos(), snapResults ) == 0 ) { if ( snapResults.isEmpty() ) { 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( snapResults.constBegin()->snappedVertex ); } if ( mCaptureMode != CapturePoint && mTempRubberBand && mCapturing ) { mapPoint = snapPointFromResults( snapResults, e->pos() ); mTempRubberBand->movePoint( mapPoint ); } } } // mouseMoveEvent
int QgsMapToolCapture::nextPoint( const QPoint &p, QgsPoint &layerPoint, QgsPoint &mapPoint ) { QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() ); if ( !vlayer ) { QgsDebugMsg( "no vector layer" ); return 1; } QgsPoint digitisedPoint; try { digitisedPoint = toLayerCoordinates( vlayer, p ); } catch ( QgsCsException &cse ) { Q_UNUSED( cse ); QgsDebugMsg( "transformation to layer coordinate failed" ); return 2; } QList<QgsSnappingResult> snapResults; if ( mSnapper.snapToBackgroundLayers( p, snapResults ) == 0 ) { mapPoint = snapPointFromResults( snapResults, p ); try { layerPoint = toLayerCoordinates( vlayer, mapPoint ); //transform snapped point back to layer crs } catch ( QgsCsException &cse ) { Q_UNUSED( cse ); QgsDebugMsg( "transformation to layer coordinate failed" ); return 2; } } return 0; }
void QgsMapToolAddFeature::canvasReleaseEvent( QMouseEvent * e ) { QgsDebugMsg( "entered." ); QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() ); if ( !vlayer ) { notifyNotVectorLayer(); return; } QGis::WkbType layerWKBType = vlayer->wkbType(); QgsVectorDataProvider* provider = vlayer->dataProvider(); if ( !( provider->capabilities() & QgsVectorDataProvider::AddFeatures ) ) { QMessageBox::information( 0, tr( "Layer cannot be added to" ), tr( "The data provider for this layer does not support the addition of features." ) ); return; } if ( !vlayer->isEditable() ) { notifyNotEditableLayer(); return; } // POINT CAPTURING if ( mode() == CapturePoint ) { //check we only use this tool for point/multipoint layers if ( vlayer->geometryType() != QGis::Point ) { QMessageBox::information( 0, tr( "Wrong editing tool" ), tr( "Cannot apply the 'capture point' tool on this vector layer" ) ); return; } QgsPoint idPoint; //point in map coordinates QList<QgsSnappingResult> snapResults; QgsPoint savePoint; //point in layer coordinates if ( mSnapper.snapToBackgroundLayers( e->pos(), snapResults ) == 0 ) { idPoint = snapPointFromResults( snapResults, e->pos() ); try { savePoint = toLayerCoordinates( vlayer, idPoint ); QgsDebugMsg( "savePoint = " + savePoint.toString() ); } catch ( QgsCsException &cse ) { Q_UNUSED( cse ); QMessageBox::information( 0, tr( "Coordinate transform error" ), tr( "Cannot transform the point to the layers coordinate system" ) ); return; } } //only do the rest for provider with feature addition support //note that for the grass provider, this will return false since //grass provider has its own mechanism of feature addition if ( provider->capabilities() & QgsVectorDataProvider::AddFeatures ) { QgsFeature* f = new QgsFeature( 0, "WKBPoint" ); QgsGeometry *g = 0; if ( layerWKBType == QGis::WKBPoint || layerWKBType == QGis::WKBPoint25D ) { g = QgsGeometry::fromPoint( savePoint ); } else if ( layerWKBType == QGis::WKBMultiPoint || layerWKBType == QGis::WKBMultiPoint25D ) { g = QgsGeometry::fromMultiPoint( QgsMultiPoint() << savePoint ); } f->setGeometry( g ); vlayer->beginEditCommand( tr( "Feature added" ) ); if ( addFeature( vlayer, f ) ) { vlayer->endEditCommand(); } else { delete f; vlayer->destroyEditCommand(); } mCanvas->refresh(); } } else if ( mode() == CaptureLine || mode() == CapturePolygon ) { //check we only use the line tool for line/multiline layers if ( mode() == CaptureLine && vlayer->geometryType() != QGis::Line ) { QMessageBox::information( 0, tr( "Wrong editing tool" ), tr( "Cannot apply the 'capture line' tool on this vector layer" ) ); return; } //check we only use the polygon tool for polygon/multipolygon layers if ( mode() == CapturePolygon && vlayer->geometryType() != QGis::Polygon ) { QMessageBox::information( 0, tr( "Wrong editing tool" ), tr( "Cannot apply the 'capture polygon' tool on this vector layer" ) ); return; } //add point to list and to rubber band int error = addVertex( e->pos() ); if ( error == 1 ) { //current layer is not a vector layer return; } else if ( error == 2 ) { //problem with coordinate transformation QMessageBox::information( 0, tr( "Coordinate transform error" ), tr( "Cannot transform the point to the layers coordinate system" ) ); return; } if ( e->button() == Qt::LeftButton ) { startCapturing(); } else if ( e->button() == Qt::RightButton ) { // End of string //lines: bail out if there are not at least two vertices if ( mode() == CaptureLine && size() < 2 ) { stopCapturing(); return; } //polygons: bail out if there are not at least two vertices if ( mode() == CapturePolygon && size() < 3 ) { stopCapturing(); return; } //create QgsFeature with wkb representation QgsFeature* f = new QgsFeature( 0, "WKBLineString" ); QgsGeometry *g; if ( mode() == CaptureLine ) { if ( layerWKBType == QGis::WKBLineString || layerWKBType == QGis::WKBLineString25D ) { g = QgsGeometry::fromPolyline( points().toVector() ); } else if ( layerWKBType == QGis::WKBMultiLineString || layerWKBType == QGis::WKBMultiLineString25D ) { g = QgsGeometry::fromMultiPolyline( QgsMultiPolyline() << points().toVector() ); } else { QMessageBox::critical( 0, tr( "Error" ), tr( "Cannot add feature. Unknown WKB type" ) ); stopCapturing(); return; //unknown wkbtype } f->setGeometry( g ); } else // polygon { if ( layerWKBType == QGis::WKBPolygon || layerWKBType == QGis::WKBPolygon25D ) { g = QgsGeometry::fromPolygon( QgsPolygon() << points().toVector() ); } else if ( layerWKBType == QGis::WKBMultiPolygon || layerWKBType == QGis::WKBMultiPolygon25D ) { g = QgsGeometry::fromMultiPolygon( QgsMultiPolygon() << ( QgsPolygon() << points().toVector() ) ); } else { QMessageBox::critical( 0, tr( "Error" ), tr( "Cannot add feature. Unknown WKB type" ) ); stopCapturing(); return; //unknown wkbtype } if ( !g ) { stopCapturing(); delete f; return; // invalid geometry; one possibility is from duplicate points } f->setGeometry( g ); int avoidIntersectionsReturn = f->geometry()->avoidIntersections(); if ( avoidIntersectionsReturn == 1 ) { //not a polygon type. Impossible to get there } #if 0 else if ( avoidIntersectionsReturn == 2 ) //MH120131: disable this error message until there is a better way to cope with the single type / multi type problem { //bail out... QMessageBox::critical( 0, tr( "Error" ), tr( "The feature could not be added because removing the polygon intersections would change the geometry type" ) ); delete f; stopCapturing(); return; } #endif else if ( avoidIntersectionsReturn == 3 ) { QMessageBox::critical( 0, tr( "Error" ), tr( "An error was reported during intersection removal" ) ); } } vlayer->beginEditCommand( tr( "Feature added" ) ); if ( addFeature( vlayer, f ) ) { //add points to other features to keep topology up-to-date int topologicalEditing = QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 ); if ( topologicalEditing ) { vlayer->addTopologicalPoints( f->geometry() ); } vlayer->endEditCommand(); } else { delete f; vlayer->destroyEditCommand(); } stopCapturing(); } } }
void QgsMapToolNodeTool::canvasMoveEvent( QMouseEvent * e ) { if ( !mSelectedFeature || !mClicked ) return; QgsVectorLayer* vlayer = mSelectedFeature->vlayer(); Q_ASSERT( vlayer ); mSelectAnother = false; if ( mMoving ) { // create rubberband, if none exists if ( mRubberBands.empty() ) { if ( mIsPoint ) { QList<QgsVertexEntry*> &vertexMap = mSelectedFeature->vertexMap(); for ( int i = 0; i < vertexMap.size(); i++ ) { if ( vertexMap[i]->isSelected() ) { QgsRubberBand* rb = createRubberBandMarker( vertexMap[i]->point(), vlayer ); mRubberBands.append( rb ); } } } createMovingRubberBands(); QList<QgsSnappingResult> snapResults; QgsPoint posMapCoord = snapPointFromResults( snapResults, e->pos() ); mPosMapCoordBackup = posMapCoord; } else { // move rubberband QList<QgsSnappingResult> snapResults; mSnapper.snapToBackgroundLayers( e->pos(), snapResults, QList<QgsPoint>() << mClosestMapVertex ); // get correct coordinates to move to QgsPoint posMapCoord = snapPointFromResults( snapResults, e->pos() ); QgsPoint pressMapCoords; if ( snapResults.size() > 0 ) { pressMapCoords = mClosestMapVertex; } else { pressMapCoords = toMapCoordinates( mPressCoordinates ); } QgsVector offset = posMapCoord - pressMapCoords; // handle points if ( mIsPoint ) { for ( int i = 0; i < mRubberBands.size(); i++ ) { mRubberBands[i]->setTranslationOffset( offset.x(), offset.y() ); } return; } // move points QList<QgsVertexEntry*> &vertexMap = mSelectedFeature->vertexMap(); for ( int i = 0; i < vertexMap.size(); i++ ) { if ( !vertexMap[i]->isSelected() ) continue; QgsPoint p = toMapCoordinates( vlayer, vertexMap[i]->point() ) + offset; mRubberBands[vertexMap[i]->rubberBandNr()]->movePoint( vertexMap[i]->rubberBandIndex(), p ); if ( vertexMap[i]->rubberBandIndex() == 0 ) { mRubberBands[vertexMap[i]->rubberBandNr()]->movePoint( 0, p ); } } // topological editing offset = posMapCoord - mPosMapCoordBackup; for ( int i = 0; i < mTopologyRubberBand.size(); i++ ) { for ( int pointIndex = 0; pointIndex < mTopologyRubberBand[i]->numberOfVertices(); pointIndex++ ) { if ( mTopologyRubberBandVertexes[i]->contains( pointIndex ) ) { const QgsPoint* point = mTopologyRubberBand[i]->getPoint( 0, pointIndex ); if ( point == 0 ) { break; } mTopologyRubberBand[i]->movePoint( pointIndex, *point + offset ); } } } mPosMapCoordBackup = posMapCoord; } } else { if ( !mSelectionRectangle ) { mSelectionRectangle = true; mSelectionRubberBand = new QRubberBand( QRubberBand::Rectangle, mCanvas ); mRect = new QRect(); mRect->setTopLeft( mPressCoordinates ); } mRect->setBottomRight( e->pos() ); QRect normalizedRect = mRect->normalized(); mSelectionRubberBand->setGeometry( normalizedRect ); mSelectionRubberBand->show(); } }
{ if ( vertexEntry->isSelected() ) mMoveVertices[mSelectedFeature->featureId()].append( qMakePair( vertexEntry->vertexId(), toMapCoordinates( vlayer, vertexEntry->point() ) ) ); } if ( QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 ) ) { createTopologyRubberBands(); } } else { // move rubberband QList<QgsSnappingResult> snapResults; mSnapper.snapToBackgroundLayers( e->pos(), snapResults, QList<QgsPoint>() << mClosestMapVertex ); QgsPoint curPos = snapPointFromResults( snapResults, e->pos() ); QgsPoint pressPos = snapResults.size() > 0 ? mClosestMapVertex : toMapCoordinates( mPressCoordinates ); double deltaX = curPos.x() - pressPos.x(); double deltaY = curPos.y() - pressPos.y(); foreach ( const QgsFeatureId& fid, mMoveRubberBands.keys() ) { typedef QPair<QgsVertexId, QgsPointV2> MoveVertex; foreach ( const MoveVertex& pair, mMoveVertices[fid] ) { QgsPointV2 newPos( pair.second.x() + deltaX, pair.second.y() + deltaY ); mMoveRubberBands.value( fid )->moveVertex( pair.first, newPos ); } } } }
void QgsMapToolNodeTool::canvasReleaseEvent( QMouseEvent * e ) { if ( !mSelectedFeature ) return; removeRubberBands(); QgsVectorLayer *vlayer = mSelectedFeature->vlayer(); Q_ASSERT( vlayer ); mClicked = false; mSelectionRectangle = false; if ( mSelectionRubberBand ) { mSelectionRubberBand->close(); delete mSelectionRubberBand; mSelectionRubberBand = 0; } if ( mPressCoordinates == e->pos() ) { if ( mSelectAnother ) { // select another feature mSelectedFeature->setSelectedFeature( mAnother, vlayer, mCanvas ); mIsPoint = vlayer->geometryType() == QGis::Point; mSelectAnother = false; } } else { if ( mMoving ) { mMoving = false; QList<QgsSnappingResult> snapResults; mSnapper.snapToBackgroundLayers( e->pos(), snapResults, QList<QgsPoint>() << mClosestMapVertex ); QgsPoint releaseLayerCoords = toLayerCoordinates( vlayer, snapPointFromResults( snapResults, e->pos() ) ); QgsPoint pressLayerCoords; if ( snapResults.size() > 0 ) { pressLayerCoords = toLayerCoordinates( vlayer, mClosestMapVertex ); int topologicalEditing = QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 ); if ( topologicalEditing ) { insertSegmentVerticesForSnap( snapResults, vlayer ); } } else { pressLayerCoords = toLayerCoordinates( vlayer, mPressCoordinates ); } mSelectedFeature->moveSelectedVertexes( releaseLayerCoords - pressLayerCoords ); mCanvas->refresh(); } else // selecting vertexes by rubberband { // coordinates has to be coordinates from layer not canvas QgsRectangle r( toLayerCoordinates( vlayer, mPressCoordinates ), toLayerCoordinates( vlayer, e->pos() ) ); QList<QgsVertexEntry*> &vertexMap = mSelectedFeature->vertexMap(); if ( !mCtrl ) { mSelectedFeature->deselectAllVertexes(); } for ( int i = 0; i < vertexMap.size(); i++ ) { if ( r.contains( vertexMap[i]->point() ) ) { // inverting selection is enough because all were deselected if ctrl is not pressed mSelectedFeature->invertVertexSelection( i, false ); } } } } mMoving = false; if ( mDeselectOnRelease != -1 ) { if ( mCtrl ) { mSelectedFeature->invertVertexSelection( mDeselectOnRelease ); } else { mSelectedFeature->deselectAllVertexes(); mSelectedFeature->selectVertex( mDeselectOnRelease ); } mDeselectOnRelease = -1; } mRecentSnappingResults.clear(); mExcludePoint.clear(); }