OGR根据FID删除矢量中的某个要素(多边形)

本文介绍了一个函数,该函数通过OGR库实现复制矢量文件并删除指定FID的要素。输入参数包括源矢量文件 DataSource、目标输出文件名、待删除FID的数组以及结果文件格式。

这是一个函数,实现复制原来的矢量文件,然后删除掉FID与对应数组pFID中相等的要素,参数1为原来的矢量文件DataSource指针,参数2为输出的矢量文件名,参数3为存储要删除的FID的数组,参数4为结果矢量的格式。

bool CreateResultSHP (OGRDataSource  *poSrcDs ,std ::string outputFileName ,vector < int >  *pFID , const  char * pszFormat )
{
  //创建输出矢量文件
 OGRSFDriver  *poDriver ;
  if  (pszFormat  ==  NULL )
  {
  pszFormat  =  "ESRI Shapefile" ;
  }

 poDriver  = OGRSFDriverRegistrar ::GetRegistrar ()->GetDriverByName ( pszFormat  );
  if  (poDriver  ==  NULL )&
<think>我们被要求在不使用QgsMapToolAddFeature类的情况下实现矢量要素的新增绘制功能。这意味着我们需要手动处理地图画布上的鼠标事件,并在画布上实时勾勒用户绘制的几何图形。解决方案思路:1.自定义地图工具(继承自QgsMapTool):我们将创建一个自定义地图工具类,用于捕获鼠标事件并绘制临时几何图形。2.根据图层类型(点、线、面)实现不同的绘制逻辑:-点:单击即可创建点要素-线:通过多个点形成线,双击结束绘制-面:通过多个点形成面,双击结束绘制(首点自动闭合)3.在绘制过程中,使用RubberBand(橡皮筋)在画布上实时显示正在绘制的几何图形。步骤:1.创建自定义地图工具类(如CustomMapTool),并重写以下事件:-canvasPressEvent:鼠标按下事件-canvasMoveEvent:鼠标移动事件(用于显示橡皮筋的临时点)-canvasReleaseEvent:鼠标释放事件(用于添加点)-canvasDoubleClickEvent:双击事件(结束绘制线或面)2.在工具中根据当前图层的几何类型执行不同的绘制逻辑。3.完成绘制后,将橡皮筋的几何对象转换为要素并添加到图层。注意:要支持复制和剪切等操作,我们需要维护一个剪贴板(可以使用QList<QgsFeature>作为内存中的剪贴板)。下面我们逐步实现这些功能。一、自定义地图工具类(CustomMapTool):我们创建一个继承自QgsMapTool的自定义工具类,用于处理绘制。二、实现其他编辑功能(删除、移动、复制、剪切):这些功能可以通过选择要素后调用相应的函数来实现,不依赖于特定的地图工具。三、移动功能:我们也需要自定义一个移动工具,同样使用橡皮筋来显示移动过程。由于代码较长,我们将分部分展示关键代码:首先,我们实现自定义绘制工具(CustomMapTool)的框架:</think> ### C++ QGIS 二次开发:手动实现矢量编辑功能(无 `QgsMapToolAddFeature`) 以下是基于 QGIS C++ API 实现矢量编辑功能的完整方案,通过手动处理鼠标事件实现绘制逻辑,不依赖 `QgsMapToolAddFeature` 类。 --- ### 一、基础环境设置 初始化 QGIS 环境并加载矢量图层: ```cpp #include <qgsapplication.h> #include <qgsmapcanvas.h> #include <qgsvectorlayer.h> #include <qgsproject.h> #include <qgsrubberband.h> int main(int argc, char *argv[]) { QgsApplication app(argc, argv, true); QgsApplication::setPrefixPath("/path/to/qgis/installation", true); QgsApplication::initQgis(); // 创建主窗口和地图画布 QMainWindow mainWindow; QgsMapCanvas* canvas = new QgsMapCanvas(&mainWindow); canvas->setCanvasColor(Qt::white); // 加载矢量图层 [^1][^3] QgsVectorLayer* layer = new QgsVectorLayer("path/to/shapefile.shp", "Editable Layer", "ogr"); if (layer->isValid()) { QgsProject::instance()->addMapLayer(layer); canvas->setLayers({layer}); canvas->setExtent(layer->extent()); } mainWindow.setCentralWidget(canvas); mainWindow.show(); return app.exec(); } ``` --- ### 二、自定义矢量绘制工具 实现鼠标事件处理逻辑,支持点/线/面绘制: ```cpp class CustomDrawingTool : public QgsMapTool { Q_OBJECT public: CustomDrawingTool(QgsMapCanvas* canvas, QgsVectorLayer* layer) : QgsMapTool(canvas), mCanvas(canvas), mLayer(layer) { // 创建橡皮筋用于实时预览 mRubberBand = new QgsRubberBand(mCanvas, QgsWkbTypes::LineGeometry); mRubberBand->setColor(Qt::red); mRubberBand->setWidth(2); } ~CustomDrawingTool() { delete mRubberBand; } protected: // 鼠标按下事件 void canvasPressEvent(QgsMapMouseEvent* e) override { QgsPointXY mapPoint = toMapCoordinates(e->pos()); if (mLayer->geometryType() == QgsWkbTypes::PointGeometry) { // 点图层:直接创建要素 createPointFeature(mapPoint); } else { // 线/面:添加到临时点集 mPoints.append(mapPoint); if (mPoints.size() > 1) { // 绘制线段预览 QgsPointXY lastPoint = mPoints[mPoints.size() - 2]; mRubberBand->addPoint(mapPoint); } } } // 鼠标移动事件(线/面实时预览) void canvasMoveEvent(QgsMapMouseEvent* e) override { if (mPoints.isEmpty()) return; QgsPointXY currentPoint = toMapCoordinates(e->pos()); QgsPointXY lastPoint = mPoints.last(); // 更新临时预览线 mRubberBand->movePoint(mRubberBand->numberOfVertices() - 1, currentPoint); } // 鼠标释放事件(面/线完成绘制) void canvasReleaseEvent(QgsMapMouseEvent* e) override { if (e->button() == Qt::RightButton) { if (mPoints.size() >= 2) { // 双击完成绘制 createGeometryFeature(); } resetDrawing(); } } private: // 创建点要素 void createPointFeature(const QgsPointXY& point) { QgsFeature feature; feature.setGeometry(QgsGeometry::fromPointXY(point)); mLayer->startEditing(); mLayer->addFeature(feature); mLayer->commitChanges(); mCanvas->refresh(); } // 创建线/面要素 void createGeometryFeature() { if (mPoints.size() < 2) return; QgsGeometry geometry; switch (mLayer->geometryType()) { case QgsWkbTypes::LineGeometry: geometry = QgsGeometry::fromPolylineXY(mPoints); break; case QgsWkbTypes::PolygonGeometry: // 多边形首尾闭合 mPoints.append(mPoints.first()); geometry = QgsGeometry::fromPolygonXY({mPoints}); break; default: return; } mLayer->startEditing(); QgsFeature feature; feature.setGeometry(geometry); mLayer->addFeature(feature); mLayer->commitChanges(); mCanvas->refresh(); } // 重置绘制状态 void resetDrawing() { mPoints.clear(); mRubberBand->reset(); } private: QgsMapCanvas* mCanvas; QgsVectorLayer* mLayer; QgsRubberBand* mRubberBand; QVector<QgsPointXY> mPoints; }; ``` --- ### 三、核心编辑功能实现 #### 1. 删除要素 ```cpp void deleteSelectedFeatures(QgsVectorLayer* layer) { if (!layer) return; layer->startEditing(); QgsFeatureIds ids = layer->selectedFeatureIds(); if (!ids.isEmpty()) { layer->deleteFeatures(ids); layer->commitChanges(); } } ``` #### 2. 移动要素 ```cpp class MoveTool : public QgsMapTool { Q_OBJECT public: MoveTool(QgsMapCanvas* canvas, QgsVectorLayer* layer) : QgsMapTool(canvas), mLayer(layer) {} protected: void canvasPressEvent(QgsMapMouseEvent* e) override { // 获取被点击的要素 QgsPointXY point = toMapCoordinates(e->pos()); QgsFeature feature; if (!mLayer->getFeatures(QgsFeatureRequest() .setFilterRect(QgsRectangle(point.x()-0.1, point.y()-0.1, point.x()+0.1, point.y()+0.1))) .nextFeature(feature)) return; mSelectedFeature = feature; mStartPoint = point; } void canvasMoveEvent(QgsMapMouseEvent* e) override { if (mSelectedFeature.isNull()) return; // 计算位移向量 QgsVector v = toMapCoordinates(e->pos()) - mStartPoint; // 应用位移 QgsGeometry geometry = mSelectedFeature.geometry(); geometry.translate(v.x(), v.y()); mLayer->startEditing(); mSelectedFeature.setGeometry(geometry); mLayer->updateFeature(mSelectedFeature); mLayer->commitChanges(); canvas()->refresh(); } private: QgsVectorLayer* mLayer; QgsFeature mSelectedFeature; QgsPointXY mStartPoint; }; ``` #### 3. 复制与剪切 ```cpp // 复制(到内存剪贴板) QList<QgsFeature> copyBuffer; void copySelectedFeatures(QgsVectorLayer* layer) { QgsFeatureIterator it = layer->getSelectedFeatures(); copyBuffer.clear(); QgsFeature feature; while (it.nextFeature(feature)) { // 克隆要素(去除ID) QgsFeature cloned = feature; cloned.setId(FID_NULL); copyBuffer.append(cloned); } } // 粘贴 void pasteFeatures(QgsVectorLayer* layer) { if (copyBuffer.isEmpty()) return; layer->startEditing(); for (QgsFeature& feature : copyBuffer) { layer->addFeature(feature); } layer->commitChanges(); } // 剪切 = 复制 + 删除 void cutFeatures(QgsVectorLayer* layer) { copySelectedFeatures(layer); deleteSelectedFeatures(layer); } ``` --- ### 四、图层类型适配器 ```cpp enum EditAction { Delete, Move, Copy, Cut }; void executeEditAction(QgsVectorLayer* layer, EditAction action) { if (!layer->isValid()) return; switch (layer->geometryType()) { case QgsWkbTypes::PointGeometry: case QgsWkbTypes::LineGeometry: case QgsWkbTypes::PolygonGeometry: // 所有类型支持的操作 switch (action) { case Delete: deleteSelectedFeatures(layer); break; case Copy: copySelectedFeatures(layer); break; case Cut: cutFeatures(layer); break; } break; } } ``` --- ### 五、使用示例 ```cpp // 在主窗口初始化工具 CustomDrawingTool* drawingTool = new CustomDrawingTool(canvas, layer); MoveTool* moveTool = new MoveTool(canvas, layer); // 切换工具 canvas->setMapTool(drawingTool); // 绘制模式 canvas->setMapTool(moveTool); // 移动模式 // 执行命令按钮 QPushButton* btnDelete = new QPushButton("删除"); connect(btnDelete, &QPushButton::clicked, [layer](){ executeEditAction(layer, EditAction::Delete); }); ``` --- ### 关键技术点 1. **手动几何构造**:使用 `QgsGeometry::fromPointXY()/fromPolylineXY()/fromPolygonXY()` 直接创建几何对象 2. **橡皮筋预览**:通过 `QgsRubberBand` 实现绘制过程中的实时可视化[^3] 3. **位移计算**:`QgsVector` 处理要素移动的几何变换 4. **图层适配**:根据 `geometryType()` 自动匹配几何操作 5. **内存剪贴板**:`QList<QgsFeature>` 作为临时缓冲区实现复制/粘贴功能 这种方法避免了直接依赖 `QgsMapToolAddFeature`,提供了更底层的几何操作控制,同时保持了绘制的实时可视化效果[^1]。
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值