|
|
|
|
@ -8,7 +8,7 @@
|
|
|
|
|
|
|
|
|
|
#include "ZxPlot.h"
|
|
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include "zxGmyBase.h"
|
|
|
|
|
|
|
|
|
|
#include "nmObjLineCrack.h"
|
|
|
|
|
#include "nmDataFracture.h"
|
|
|
|
|
@ -19,9 +19,7 @@ nmObjDeleteTool::nmObjDeleteTool() : nmObjToolBase()
|
|
|
|
|
{
|
|
|
|
|
setText(tr("nObjDeleteTool"));
|
|
|
|
|
m_oNot = NMOT_Delete;
|
|
|
|
|
m_bShowDeleteIcon = false;
|
|
|
|
|
m_hoverObj = nullptr;
|
|
|
|
|
m_deleteIcon.load(ZxBaseUtil::getDirOf(s_Dir_Res, "Icon") + "nmTrash.png");
|
|
|
|
|
initDeleteCursor();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nmObjDeleteTool::nmObjDeleteTool(ZxPlot* pPlot)
|
|
|
|
|
@ -31,171 +29,192 @@ nmObjDeleteTool::nmObjDeleteTool(ZxPlot* pPlot)
|
|
|
|
|
setText(tr("nObjDeleteTool"));
|
|
|
|
|
m_oNot = NMOT_Delete;
|
|
|
|
|
nmDataLogFile::getInstance()->writeLog(" nmObjDeleteTool ++++++++ " + QString::number(m_oNot));
|
|
|
|
|
this->m_delObj.clear();
|
|
|
|
|
m_bShowDeleteIcon = false;
|
|
|
|
|
m_hoverObj = nullptr;
|
|
|
|
|
m_deleteIcon.load(ZxBaseUtil::getDirOf(s_Dir_Res, "Icon") + "nmTrash.png");
|
|
|
|
|
initDeleteCursor();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nmObjDeleteTool::~nmObjDeleteTool()
|
|
|
|
|
{
|
|
|
|
|
// 视口可能已销毁,由 QPointer 避免访问失效窗口。
|
|
|
|
|
resetDeleteCursor();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nmObjDeleteTool::initDeleteCursor()
|
|
|
|
|
{
|
|
|
|
|
m_hadExplicitCursor = false;
|
|
|
|
|
QPixmap icon(ZxBaseUtil::getDirOf(s_Dir_Res, "Icon") + "nmTrash.png");
|
|
|
|
|
QPixmap cursorPixmap(40, 40);
|
|
|
|
|
cursorPixmap.fill(Qt::transparent);
|
|
|
|
|
QPainter painter(&cursorPixmap);
|
|
|
|
|
|
|
|
|
|
// 仅显示小垃圾桶,以中心作为点击热点,大小不受画布缩放影响。
|
|
|
|
|
painter.drawPixmap(cursorPixmap.rect(), icon, icon.rect());
|
|
|
|
|
painter.end();
|
|
|
|
|
m_deleteCursor = QCursor(cursorPixmap, 20, 20);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool nmObjDeleteTool::updateDeleteCursor(const QPointF& pt)
|
|
|
|
|
{
|
|
|
|
|
// 与点击使用同一命中规则,仅在绘图视口内切换光标。
|
|
|
|
|
if (m_pObj != nullptr || QApplication::activeModalWidget() != nullptr ||
|
|
|
|
|
findNearestDeleteObj(pt) == nullptr) {
|
|
|
|
|
resetDeleteCursor();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
QWidget* viewport = getView()->viewport();
|
|
|
|
|
if (m_cursorViewport != viewport) {
|
|
|
|
|
resetDeleteCursor();
|
|
|
|
|
m_cursorViewport = viewport;
|
|
|
|
|
m_hadExplicitCursor = viewport->testAttribute(Qt::WA_SetCursor);
|
|
|
|
|
m_previousCursor = viewport->cursor();
|
|
|
|
|
}
|
|
|
|
|
viewport->setCursor(m_deleteCursor);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nmObjDeleteTool::resetDeleteCursor()
|
|
|
|
|
{
|
|
|
|
|
// 只恢复本工具设置的光标,不覆盖后来由其他工具设置的样式。
|
|
|
|
|
if (m_cursorViewport &&
|
|
|
|
|
m_cursorViewport->cursor().pixmap().cacheKey() == m_deleteCursor.pixmap().cacheKey()) {
|
|
|
|
|
if (m_hadExplicitCursor) {
|
|
|
|
|
m_cursorViewport->setCursor(m_previousCursor);
|
|
|
|
|
} else {
|
|
|
|
|
m_cursorViewport->unsetCursor();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
m_cursorViewport = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool nmObjDeleteTool::onMouseMove(const QPointF& pt)
|
|
|
|
|
{
|
|
|
|
|
if (m_pObj != nullptr) {
|
|
|
|
|
return nmObjToolBase::onMouseMove(pt);
|
|
|
|
|
}
|
|
|
|
|
// 命中时阻止图元自身的移动光标覆盖删除提示。
|
|
|
|
|
return updateDeleteCursor(pt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool nmObjDeleteTool::onRightDown(const QPointF& pt)
|
|
|
|
|
{
|
|
|
|
|
// 右键退出或打开菜单前恢复普通光标。
|
|
|
|
|
resetDeleteCursor();
|
|
|
|
|
return nmObjToolBase::onRightDown(pt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nmObjDeleteTool::onDeactivated()
|
|
|
|
|
{
|
|
|
|
|
// 切换活动工具时释放自定义光标。
|
|
|
|
|
resetDeleteCursor();
|
|
|
|
|
nmObjToolBase::onDeactivated();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool nmObjDeleteTool::onLeftDown(const QPointF& pt)
|
|
|
|
|
{
|
|
|
|
|
if (m_pObj != nullptr) {
|
|
|
|
|
return nmObjToolBase::onLeftDown(pt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 命中时接管按下事件,防止区域标记等图元的移动工具抢先处理抬起事件。
|
|
|
|
|
return findNearestDeleteObj(pt) != nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool nmObjDeleteTool::onLeftUp(const QPointF& pt)
|
|
|
|
|
{
|
|
|
|
|
if (NULL == m_pObj) //绘图对象尚未创建(鼠标选点ing)
|
|
|
|
|
{
|
|
|
|
|
//changeCursor(Qt::CrossCursor);
|
|
|
|
|
|
|
|
|
|
// 判断鼠标是否进入了要删除的对象上
|
|
|
|
|
if (!m_delObj.isEmpty())
|
|
|
|
|
{
|
|
|
|
|
int objCount = this->m_delObj.count();
|
|
|
|
|
for(int i = 0; i < objCount; i++) {
|
|
|
|
|
ZxObjBase* obj = this->m_delObj[i];
|
|
|
|
|
if (obj == NULL)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
if (m_pObj != nullptr) {
|
|
|
|
|
return nmObjToolBase::onLeftUp(pt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 按抬起位置重新命中,使用与悬停提示相同的对象筛选和距离规则。
|
|
|
|
|
ZxObjBase* obj = findNearestDeleteObj(pt);
|
|
|
|
|
if (obj != nullptr) {
|
|
|
|
|
// 弹出确认框之前恢复,确认或取消后都不残留删除光标。
|
|
|
|
|
resetDeleteCursor();
|
|
|
|
|
nmSingalCenter::getInstance()->emitSigDeleteOneObj(obj->getName(), (void*)this);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ZxObjBase* nmObjDeleteTool::findNearestDeleteObj(const QPointF& pt)
|
|
|
|
|
{
|
|
|
|
|
ZxRenderView* view = getView();
|
|
|
|
|
if (m_pPlot == nullptr || view == nullptr) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 转为视口坐标后按 16 像素判断,保持不同缩放下的点击容差一致。
|
|
|
|
|
const QPointF mousePos = view->mapFromScene(pt);
|
|
|
|
|
const double hitRadius = 16.0;
|
|
|
|
|
double nearestDistanceSquared = hitRadius * hitRadius;
|
|
|
|
|
ZxObjBase* nearestObj = nullptr;
|
|
|
|
|
zxGmyBase geometry;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < m_pPlot->getObjCount(); ++i) {
|
|
|
|
|
ZxObjBase* obj = m_pPlot->getObjByIndex(i);
|
|
|
|
|
if (obj == nullptr || !obj->isVisible()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const bool isFracture = _isSame("nObjLineFracture", obj->getTagName());
|
|
|
|
|
const bool isRegion = _isSame("nObjRegion", obj->getTagName());
|
|
|
|
|
if (!isFracture && !isRegion &&
|
|
|
|
|
!_isSame("nObjLineFault", obj->getTagName()) &&
|
|
|
|
|
!_isSame("nObjPointWell", obj->getTagName()) &&
|
|
|
|
|
!_isSame("nObjRegionMark", obj->getTagName())) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
QVector<QPointF> pts = obj->getAllPos();
|
|
|
|
|
|
|
|
|
|
// 井或区域标记
|
|
|
|
|
if (pts.count() == 1)
|
|
|
|
|
{
|
|
|
|
|
// 计算鼠标点击位置与井的中心点的距离
|
|
|
|
|
float distance = QLineF(pt, pts[0]).length();
|
|
|
|
|
if (distance <= 1.f * 5) // 如果距离在5像素范围内
|
|
|
|
|
{
|
|
|
|
|
if (obj != NULL)
|
|
|
|
|
{
|
|
|
|
|
nmSingalCenter::getInstance()->emitSigDeleteOneObj(obj->getName(), (void*)this);
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
// 保留原有规则:未绑定数据及 DFN 生成的裂缝不参与单独删除。
|
|
|
|
|
if (isFracture) {
|
|
|
|
|
nmObjLineCrack* fracture = dynamic_cast<nmObjLineCrack*>(obj);
|
|
|
|
|
nmPlotGraphicBinder* binder = fracture ? fracture->getGraphicBinder() : nullptr;
|
|
|
|
|
nmDataFracture* data = binder ? binder->getCrackDataFor(fracture) : nullptr;
|
|
|
|
|
if (data == nullptr || data->getFractureType().getValue() == tr("DFN")) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 线
|
|
|
|
|
for (int i = 0; i < pts.count(); i++)
|
|
|
|
|
{
|
|
|
|
|
int n1 = i;
|
|
|
|
|
int n2 = (i == pts.count() - 1 ? 0 : i + 1);
|
|
|
|
|
if (_isNearLine(pt, pts[n1], pts[n2], 1.f * 3))
|
|
|
|
|
{
|
|
|
|
|
if (obj != NULL)
|
|
|
|
|
{
|
|
|
|
|
nmSingalCenter::getInstance()->emitSigDeleteOneObj(obj->getName(),(void*) this);
|
|
|
|
|
return true;
|
|
|
|
|
QVector<QPointF> points = obj->getAllPos();
|
|
|
|
|
if (points.isEmpty()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
for (int j = 0; j < points.count(); ++j) {
|
|
|
|
|
points[j] = view->mapFromScene(points[j]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double distance = QLineF(mousePos, points[0]).length();
|
|
|
|
|
double distanceSquared = distance * distance;
|
|
|
|
|
// 裂缝、断层按开放折线计算,只有区域包含末点到首点的闭合边。
|
|
|
|
|
const int segmentCount = isRegion ? points.count() : points.count() - 1;
|
|
|
|
|
for (int j = 0; j < segmentCount; ++j) {
|
|
|
|
|
const QPointF& start = points[j];
|
|
|
|
|
const QPointF& end = points[(j + 1) % points.count()];
|
|
|
|
|
double segmentDistanceSquared;
|
|
|
|
|
if (start == end) {
|
|
|
|
|
// 重复节点按单点处理,避免零长度线段参与投影计算。
|
|
|
|
|
distance = QLineF(mousePos, start).length();
|
|
|
|
|
segmentDistanceSquared = distance * distance;
|
|
|
|
|
} else {
|
|
|
|
|
double t = 0.0;
|
|
|
|
|
segmentDistanceSquared = geometry.pointSegmentDistanceSquared2D(mousePos, start, end, t);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
distanceSquared = qMin(distanceSquared, segmentDistanceSquared);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return nmObjToolBase::onLeftUp(pt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else //业已绑定绘图对象
|
|
|
|
|
{
|
|
|
|
|
return nmObjToolBase::onLeftUp(pt);
|
|
|
|
|
}
|
|
|
|
|
// 范围内优先选择最近图元;距离相同时保留先命中的对象。
|
|
|
|
|
if (distanceSquared <= hitRadius * hitRadius &&
|
|
|
|
|
(nearestObj == nullptr || distanceSquared < nearestDistanceSquared)) {
|
|
|
|
|
nearestDistanceSquared = distanceSquared;
|
|
|
|
|
nearestObj = obj;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nearestObj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nmObjDeleteTool::onPaint(QPainter* painter, const ZxPaintParam& param)
|
|
|
|
|
{
|
|
|
|
|
nmObjDelete* pObj = dynamic_cast<nmObjDelete*>(m_pObj);
|
|
|
|
|
if (pObj == NULL) //绘图对象尚未创建(鼠标选点ing)
|
|
|
|
|
{
|
|
|
|
|
m_currentMousePos = getCurrentPos();
|
|
|
|
|
m_bShowDeleteIcon = false;
|
|
|
|
|
m_hoverObj = nullptr;
|
|
|
|
|
if (this->m_pPlot == NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理可删除对象列表
|
|
|
|
|
int objCount = this->m_pPlot->getObjCount();
|
|
|
|
|
for(int i = 0; i < objCount; i++) {
|
|
|
|
|
ZxObjBase* obj = this->m_pPlot->getObjByIndex(i);
|
|
|
|
|
if (obj == NULL) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(_isSame("nObjLineFracture", obj->getTagName()) || \
|
|
|
|
|
_isSame("nObjLineFault", obj->getTagName()) || \
|
|
|
|
|
_isSame("nObjRegion", obj->getTagName()) || \
|
|
|
|
|
_isSame("nObjPointWell", obj->getTagName()) || \
|
|
|
|
|
_isSame("nObjRegionMark", obj->getTagName()))
|
|
|
|
|
{
|
|
|
|
|
// 判断裂缝是不是裂缝
|
|
|
|
|
if(_isSame("nObjLineFracture", obj->getTagName())) {
|
|
|
|
|
nmObjLineCrack* pFractureObj = dynamic_cast<nmObjLineCrack*>(obj);
|
|
|
|
|
if (pFractureObj == NULL) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
nmPlotGraphicBinder* pBinder = pFractureObj->getGraphicBinder();
|
|
|
|
|
nmDataFracture* pFractureData = pBinder ? pBinder->getCrackDataFor(pFractureObj) : nullptr;
|
|
|
|
|
if (pFractureData == NULL) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
// 如果是DFN生成的裂缝,那么不做处理
|
|
|
|
|
if (pFractureData->getFractureType().getValue() == tr("DFN")) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isContain = false;
|
|
|
|
|
// 遍历 m_delObj,检查是否存在相同的指针
|
|
|
|
|
for (int j = 0; j < m_delObj.count(); j++) {
|
|
|
|
|
if (m_delObj[j] == obj) {
|
|
|
|
|
isContain = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!isContain)
|
|
|
|
|
{
|
|
|
|
|
m_delObj.append(obj);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查鼠标是否在此对象上
|
|
|
|
|
QVector<QPointF> pts = obj->getAllPos();
|
|
|
|
|
// 井或区域标记
|
|
|
|
|
if (pts.count() == 1)
|
|
|
|
|
{
|
|
|
|
|
float distance = QLineF(m_currentMousePos, pts[0]).length();
|
|
|
|
|
if (distance <= 1.f * 5) // 如果距离在5像素范围内
|
|
|
|
|
{
|
|
|
|
|
m_bShowDeleteIcon = true;
|
|
|
|
|
m_hoverObj = obj;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 线
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (int j = 0; j < pts.count(); j++)
|
|
|
|
|
{
|
|
|
|
|
int n1 = j;
|
|
|
|
|
int n2 = (j == pts.count() - 1 ? 0 : j + 1);
|
|
|
|
|
if (_isNearLine(m_currentMousePos, pts[n1], pts[n2], 1.f * 3))
|
|
|
|
|
{
|
|
|
|
|
m_bShowDeleteIcon = true;
|
|
|
|
|
m_hoverObj = obj;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果鼠标悬停在可删除对象上,绘制删除图标
|
|
|
|
|
if (m_bShowDeleteIcon && !m_deleteIcon.isNull()) {
|
|
|
|
|
// 在鼠标右侧绘制图标
|
|
|
|
|
QPointF iconPos = m_currentMousePos + QPointF(4, 2);
|
|
|
|
|
int iconSize = 10; // 图标尺寸
|
|
|
|
|
QRectF iconRect(iconPos.x(), iconPos.y(), iconSize, iconSize);
|
|
|
|
|
painter->drawPixmap(iconRect, m_deleteIcon, m_deleteIcon.rect());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else //业已绑定绘图对象
|
|
|
|
|
{
|
|
|
|
|
// paintTrackingRealObj(painter, param);
|
|
|
|
|
}
|
|
|
|
|
if (m_pObj == nullptr) {
|
|
|
|
|
// 缩放或图元变化后重新判断命中,不再在画布上绘制垃圾桶。
|
|
|
|
|
updateDeleteCursor(getCurrentPos());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|