【QGIS二次开发】地图编辑-05

系列目录:

【QGIS二次开发】地图显示与交互-01_qgis二次开发加载地图案例-优快云博客

【QGIS二次开发】地图显示与交互-02_setlayerlabeling-优快云博客

【QGIS二次开发】地图符号与色表-03-优快云博客

【QGIS二次开发】地图编辑-04-优快云博客


4.4 移动要素

首先在软件中添加任意数据,并选中数据开始编辑模式(示例中为点数据)。

图 41 移动要素

通过选择选取要素(可以直接按区域选择选取一片)。

图 42 框选需要移动的要素

左侧工具栏的移动选项。

图 43 移动按键

通过鼠标左键点击以及释放完成移动,将要素移动到自己想要的位置。

图 44 移动成功

实现核心代码如下,这段代码是基于QGIS插件的地图操作功能。在鼠标左键按下时,记录起始坐标,并找到选中要素上最近的点。在鼠标左键释放时,记录结束坐标,将选中要素上最近的点移动到该坐标,然后更新图层并刷新地图显示。整体实现了通过鼠标交互移动选中要素的功能。

void QgsMapToolMovePoint::canvasPressEvent(QgsMapMouseEvent* e)    
{    
    if (e->button() == Qt::LeftButton) {    
        double xc = e->x();    
        double yc = e->y();    
        // 得到当前坐标变换对象    
        const QgsMapToPixel* pTransform = m_mapCanvas->getCoordinateTransform();    
        // 转换成地图坐标并记录为起始坐标    
        startpoint.setX(pTransform->toMapCoordinates(xc, yc).x());    
        startpoint.setY(pTransform->toMapCoordinates(xc, yc).y());    
    
        QgsFeatureIterator selectedFeatureIt = m_currentlayer->getSelectedFeatures();    
        QgsFeature selectedFeature;    
        while (selectedFeatureIt.nextFeature(selectedFeature)) { // 只循环一次    
            QgsGeometry geom = selectedFeature.geometry();    
            double sqrDist; // 最近距离    
            QgsPointXY nearestPoint = geom.closestVertex(startpoint, closestVertexIndex, previousVertexIndex, nextVertexIndex, sqrDist);    
        }    
    }    
}    
    
void QgsMapToolMovePoint::canvasReleaseEvent(QgsMapMouseEvent* e)    
{    
    if (e->button() == Qt::LeftButton) {    
        double xc = e->x();    
        double yc = e->y();    
        // 得到当前坐标变换对象    
        const QgsMapToPixel* pTransform = m_mapCanvas->getCoordinateTransform();    
        // 转换成地图坐标    
        endpoint.setX(pTransform->toMapCoordinates(xc, yc).x());    
        endpoint.setY(pTransform->toMapCoordinates(xc, yc).y());    
    
        // 线上加点    
        QgsFeatureIterator selectedFeatureIt = m_currentlayer->getSelectedFeatures();    
        QgsFeature selectedFeature;    
    
        while (selectedFeatureIt.nextFeature(selectedFeature)) { // 只循环一次    
            QgsGeometry geom = selectedFeature.geometry();    
            geom.moveVertex(endpoint.x(), endpoint.y(), closestVertexIndex);    
    
            // 更新要素的几何体    
            m_currentlayer->startEditing();    
            selectedFeature.setGeometry(geom);    
            m_currentlayer->updateFeature(selectedFeature);    
            //m_currentlayer->commitChanges();    
        }    
        m_mapCanvas->refresh();    
        m_mapCanvas->refreshAllLayers();    
    }    
}    

4.5 删除要素

首先在软件中添加任意数据,并选中数据开始编辑模式(示例中为面数据)。

图 45 示例数据

通过选择选取要素(可以直接按区域选择选取一片),并可以通过打开属性表确定删除前共计113个要素。

图 46 选择要素

选择删除操作。

图 47 删除操作

操作完成,要素在图层中消失,且可以打开属性表开出现在共111个要素。

图 48 删除成功

核心代码如下,这段代码是QGIS插件中的一个地图编辑工具类,实现了删除选中要素的功能。在deleteFeature函数中,遍历选中图层的选中要素,通过编辑缓冲区删除这些要素的记录。最后,刷新地图显示,实现删除操作的更新效果。

QgsMapToolEditFeature::~QgsMapToolEditFeature() {};    
void QgsMapToolEditFeature::deleteFeature() {    
    QgsFeatureIterator selectedFeatureIt = m_currentlayer->getSelectedFeatures();    
    QgsFeature selectedFeature;    
    m_currentlayer->startEditing();    
    QgsVectorLayerEditBuffer* editBuffer = m_currentlayer->editBuffer();    
    
    if (!editBuffer) {    
        return;    
    }    
    while (selectedFeatureIt.nextFeature(selectedFeature)) {    
        editBuffer->deleteFeature(selectedFeature.id());    
    }    
    
    //m_currentlayer->commitChanges();    
    m_currentlayer->triggerRepaint();    
    m_mapCanvas->refresh();    
    m_mapCanvas->refreshAllLayers();    
}    

4.6 复制要素

首先在软件中添加任意数据,并选中数据开始编辑模式(示例中为线数据)。

图 49 示例数据

通过选择选取要素(可以直接按区域选择选取一片),并可以打开属性表看出现在共4个要素。

图 50 选择要素

选择复制操作。

图 51 复制按键

操作完成,复制出的新要素出现在图层正中(为了便于展示复制操作成功完成的特意设定),且可以打开属性表开出现在共6个要素。

图 52 复制成功

核心代码如下,这段代码是QGIS插件中的地图编辑工具类,实现了复制选中要素的功能。在copyFeature函数中,首先获取选中图层的选中要素,并计算选中要素中心点与当前地图中心点的偏移。然后遍历选中要素,复制其几何体并根据偏移添加到编辑缓冲区中,最后刷新地图显示,实现复制操作的更新效果。

void QgsMapToolEditFeature::copyFeature() {    
    QgsFeatureIterator selectedFeatureIt = m_currentlayer->getSelectedFeatures();    
    QgsFeature selectedFeature;    
    m_currentlayer->startEditing();    
    QgsVectorLayerEditBuffer* editBuffer = m_currentlayer->editBuffer();    
    if (!editBuffer) {    
        return;    
    }    
    
    QgsRectangle currentExtent = m_currentlayer->extent();    
    QgsFeature firstFeature;  // 记录第一个要素    
    
    if (selectedFeatureIt.nextFeature(firstFeature)) {    
        // 记录第一个要素的中心点和当前地图的中心点    
        QgsPointXY centerPointFirst = firstFeature.geometry().centroid().asPoint();    
        QgsPointXY centerPointMap = currentExtent.center();    
    
        // 计算移动方向和距离    
        double xOffset = centerPointMap.x() - centerPointFirst.x();    
        double yOffset = centerPointMap.y() - centerPointFirst.y();    
    
        selectedFeatureIt = m_currentlayer->getSelectedFeatures();  // 重新获取选中的要素    
    
        while (selectedFeatureIt.nextFeature(firstFeature)) {    
            QgsFeature newFeature(firstFeature);    
            QgsFeatureId id = firstFeature.id();    
            newFeature.setId(QgsFeatureId());    
    
    
            QgsGeometry geometry = newFeature.geometry();    
            geometry.translate(xOffset, yOffset);    
            editBuffer->changeGeometry(id, geometry);    
            editBuffer->addFeature(newFeature);    
        }    
    }    
    //m_currentlayer->commitChanges();    
    m_currentlayer->triggerRepaint();    
    m_mapCanvas->refresh();    
    m_mapCanvas->refreshAllLayers();    
}    

4.7 旋转要素

首先在软件中添加任意数据,并选中数据开始编辑模式(示例中为线数据)。

图 53 示例数据

通过选择选取要素(可以直接按区域选择选取一片)。

图 54 选择要素

选择旋转操作。

图 55 旋转操作

按下鼠标左键后通过鼠标的拖动实现完成要素的实时旋转效果(蓝色虚线框也是特设的效果)显示,松开鼠标后停止旋转。

图 56 旋转成功

核心代码如下,这段代码是一个QGIS插件的地图编辑工具,实现了通过鼠标拖动旋转选中要素的功能。鼠标左键按下时记录起始点和选中要素的几何图形,鼠标移动时计算旋转角度并更新要素的几何图形,鼠标释放时结束旋转。

void QgsMapToolTurn::canvasPressEvent(QgsMapMouseEvent* e) {    
    // 检查是否是鼠标左键点击事件    
    if (e->button() == Qt::LeftButton) {    
        m_startPoint = e->mapPoint().toQPointF();    
        m_dragging = true;    
    
        // 获取选中要素的几何图形    
        QgsFeatureIterator selectedFeatureIt = m_currentLayer->getSelectedFeatures();    
        QList<QgsGeometry> geometries;    
        QgsFeature selectedFeature;    
        while (selectedFeatureIt.nextFeature(selectedFeature)) {    
            geometries << selectedFeature.geometry();    
        }    
    
        // 计算旋转的中心    
        QgsRectangle boundingBox = geometries.at(0).boundingBox();    
        for (const QgsGeometry& geometry : geometries) {    
            boundingBox.combineExtentWith(geometry.boundingBox());    
        }    
        m_initialBoundingBox = boundingBox;  // 保存初始的外接矩形    
    
        m_BoundingBox = QgsGeometry::fromRect(m_initialBoundingBox);    
    
        // 绘制外包矩形    
        pRubBand->addGeometry(m_BoundingBox);    
    }    
    // 检查是否是鼠标右键点击事件    
    else if (e->button() == Qt::RightButton) {    
        m_dragging = false;    
    }    
}    
void QgsMapToolTurn::canvasReleaseEvent(QgsMapMouseEvent* e) {    
    
    if (m_dragging && e->button() == Qt::LeftButton) {    
        pRubBand->reset(QgsWkbTypes::NullGeometry);    
        m_dragging = false;  // 结束拖动    
    }    
}    
    
void QgsMapToolTurn::canvasMoveEvent(QgsMapMouseEvent* e) {    
    if (!m_currentLayer->isEditable()) {    
        m_currentLayer->startEditing();    
    }    
    
    if (m_dragging && e->buttons() & Qt::LeftButton) {    
        // 获取当前拖动的位置    
        QPointF currentPoint = e->mapPoint().toQPointF();    
    
        // 计算拖动的偏移量    
        QPointF offset = currentPoint - m_startPoint;    
    
        // 获取选中要素的几何图形    
        QgsFeatureIterator selectedFeatureIt = m_currentLayer->getSelectedFeatures();    
        QList<QgsGeometry> geometries;    
        QgsFeature selectedFeature;    
        while (selectedFeatureIt.nextFeature(selectedFeature)) {    
            geometries << selectedFeature.geometry();    
        }    
    
        QgsPointXY center = m_initialBoundingBox.center();    
        // 计算角度(以弧度为单位)    
        double offsetAngle = qAtan2(offset.y(), offset.x());    
        double rotationDelta = offsetAngle - qAtan2(center.y() - m_startPoint.y(), center.x() - m_startPoint.x());    
    
    
        // 绘制虚线框    
        pRubBand->reset(QgsWkbTypes::LineGeometry);    
        m_BoundingBox.rotate(rotationDelta, center);    
        pRubBand->addGeometry(m_BoundingBox);    
    
        // 旋转选中的要素    
        selectedFeatureIt = m_currentLayer->getSelectedFeatures();    
        while (selectedFeatureIt.nextFeature(selectedFeature)) {    
            QgsGeometry geometry = selectedFeature.geometry();    
    
            // 旋转    
            geometry.rotate(rotationDelta, center);    
    
    
            // 更新几何图形    
            m_currentLayer->changeGeometry(selectedFeature.id(), geometry);    
        }    
    
        m_mapCanvas->refresh();    
        m_startPoint = currentPoint;  // 更新起始点    
    }    
}    

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值