You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/Src/nmNum/nmPlot/nmObjRoundTool.cpp

284 lines
6.9 KiB
C++

#include <QPainter>
#include "ZxBaseUtil.h"
#include "nmObjRound.h"
#include "nmObjRoundTool.h"
#include <vector>
nmObjRoundTool::nmObjRoundTool() : nmObjToolBase()
{
setText(tr("nObjRoundTool"));
m_oNot = NMOT_Round;
}
bool nmObjRoundTool::onLeftDown(const QPointF& pt)
{
if (NULL == m_pObj) // 绘图对象尚未创建(鼠标选点ing)
{
m_bTracking = true;
m_ptStart = pt;
changeCursor(Qt::CrossCursor);
// 对于正在创建选择的工具,需要保持光标
getView()->setCursorKeeping(true);
//m_vecPoints.push_back(pt);
return true;
}
else // 已绑定绘图对象
{
return nmObjToolBase::onLeftDown(pt);
}
}
bool nmObjRoundTool::onMouseMove(const QPointF& pt)
{
if (NULL == m_pObj) // 绘图对象尚未创建(鼠标选点ing)
{
m_ptMove = pt;
if (m_bTracking)
{
// 更新渲染区域
updateLastMoveArea(true);
}
return true;
}
else // 已绑定绘图对象
{
return nmObjToolBase::onMouseMove(pt);
}
}
bool nmObjRoundTool::onLeftUp(const QPointF& pt)
{
if (NULL == m_pObj) // 绘图对象尚未创建(鼠标选点ing)
{
// 鼠标抬起说明创建已经完成
getView()->setCursorKeeping(false);
changeCursor(Qt::ArrowCursor);
// 圆形依赖拖拽成形,起点和终点过近时取消本次创建,避免双击或误点生成零尺寸图元。
double dDistance = 2.2f;
if ((qAbs(m_ptStart.x() - pt.x()) < dDistance) &&
(qAbs(m_ptStart.y() - pt.y()) < dDistance)) {
m_vecPoints.clear();
m_bTracking = false;
return true;
}
// 计算圆心的位置
m_ptMove = pt;
QPointF m_ptCenter((m_ptStart.x() + m_ptMove.x()) / 2,(m_ptStart.y() + m_ptMove.y()) / 2);
// 计算半径
qreal dx = m_ptMove.x() - m_ptStart.x();
qreal dy = m_ptMove.y() - m_ptStart.y();
qreal radius = sqrt(pow(dx, 2) + pow(dy, 2)) / 2;
//根据半径和圆心计算圆上的四个关键点
QPointF m_ptTop(m_ptCenter.x(),m_ptCenter.y()-radius),\
m_ptRight(m_ptCenter.x() + radius,m_ptCenter.y()),\
m_ptBottom(m_ptCenter.x(),m_ptCenter.y() + radius),\
m_ptLeft(m_ptCenter.x() - radius,m_ptCenter.y());
// 保存圆心和半径
m_vecPoints.push_back(m_ptCenter); //vector[0]
QPointF m_ptRadius(radius,radius);
// 将半径以点的方式保存
m_vecPoints.push_back(m_ptRadius);//vector[1]
// 按顺序保存四个关键点
m_vecPoints.push_back(m_ptTop); //vector[2]
m_vecPoints.push_back(m_ptRight); // vector[3]
m_vecPoints.push_back(m_ptBottom); //vector[4]
m_vecPoints.push_back(m_ptLeft); // //vector[5]
emit sigPtsFinished(m_vecPoints); // 注意这个信号执行后会被nmObjRoundTool的View detach
m_vecPoints.clear();
m_bTracking = false;
return true;
}
else // 已绑定绘图对象
{
return nmObjToolBase::onLeftUp(pt);
}
}
bool nmObjRoundTool::onLeftDoubleClick(const QPointF& pt)
{
if(NULL == m_pObj) { // 绘图对象尚未创建(鼠标选点ing
// 圆形创建不依赖双击收尾,创建态直接吞掉双击事件。
return true;
} else { // 已绑定绘图对象
// 双击内部,取消选中状态
if (m_pObj->m_oHitOption == OHO_Inner) {
m_pObj->setSelected(false);
return true;
}
return nmObjToolBase::onLeftDoubleClick(pt);
}
}
void nmObjRoundTool::onPaint(QPainter* painter, const ZxPaintParam& param)
{
nmObjRound* pObj = dynamic_cast<nmObjRound*>(m_pObj);
if (pObj == NULL) // 绘图对象尚未创建(鼠标选点ing)
{
Qt::CursorShape o = Qt::CrossCursor;
changeCursor(o);
paintTrackingVirtualObj(painter, param);
}
else // 已绑定绘图对象
{
paintTrackingRealObj(painter, param);
}
}
void nmObjRoundTool::paintTrackingVirtualObj(QPainter* painter, const ZxPaintParam& param)
{
painter->save();
// 当前正在创建的点
if (m_bTracking || !m_vecPoints.isEmpty())
{
QPen pen(Qt::DashLine);
painter->setPen(pen);
// 计算圆心的位置
QPointF m_ptCenter((m_ptStart.x() + m_ptMove.x()) / 2,(m_ptStart.y() + m_ptMove.y()) / 2);
// 计算半径
qreal dx = m_ptMove.x() - m_ptStart.x();
qreal dy = m_ptMove.y() - m_ptStart.y();
qreal radius = sqrt(pow(dx, 2) + pow(dy, 2)) / 2;
// 绘制圆
painter->drawEllipse(m_ptCenter,radius,radius);
}
painter->restore();
}
void nmObjRoundTool::paintTrackingRealObj(QPainter* painter, const ZxPaintParam& param)
{
if (!m_bTracking) {
return;
}
nmObjRound* pObj = dynamic_cast<nmObjRound*>(m_pObj);
Q_ASSERT(pObj != nullptr);
if (nullptr == pObj)
{
return; // 如果pObj为nullptr直接返回
}
// 获取当前命中位置和光标形状
Qt::CursorShape cursor = getCursorBy(static_cast<int>(m_oHitOption), pObj->m_nHitIndex);
QVector<QPointF> vec = pObj->getAllPos();
// 判断半径是否相同,不相同先修改半径相同
if (vec[1].x() != vec[1].y())
{
double radius = qAbs(vec[0].y() - vec[2].y());
vec[1] = QPointF(radius, radius);
}
QPointF ptOld = m_ptStart; // 拖动起始点
QPointF ptNew = getCurrentPos(); // 当前鼠标位置
QPointF& center = vec[0]; // 圆心
QPointF& radiusPoint = vec[1]; // 半径x和y相同因为是正圆
// 根据命中位置调整圆形
switch (m_oHitOption) {
case OHO_Point: // 边缘点拖动:调整半径
{
// 计算新半径(圆心到当前鼠标位置的距离)
qreal newRadius = QLineF(center, ptNew).length();
// 更新半径保持x和y相同
radiusPoint.setX(newRadius);
radiusPoint.setY(newRadius);
// 更新四个边缘点位置
vec[2] = QPointF(center.x(), center.y() - newRadius); // 上
vec[3] = QPointF(center.x() + newRadius, center.y()); // 右
vec[4] = QPointF(center.x(), center.y() + newRadius); // 下
vec[5] = QPointF(center.x() - newRadius, center.y()); // 左
break;
}
case OHO_Inner: // 内部拖动:移动整个圆
{
QPointF offset = ptNew - ptOld;
center += offset;
// 更新所有边缘点
qreal radius = radiusPoint.x();
vec[2] += offset; // 上
vec[3] += offset; // 右
vec[4] += offset; // 下
vec[5] += offset; // 左
break;
}
default:
return; // 其他情况不处理
}
// 绘制圆形
painter->save();
QPen pen(Qt::DashLine);
painter->setPen(pen);
// 绘制圆形路径并填充半透明背景
QPainterPath path;
path.addEllipse(center, radiusPoint.x(), radiusPoint.y());
QColor bgColor = pObj->getBackgrdColor();
bgColor.setAlpha(128); // 设置透明度
painter->fillPath(path, bgColor);
painter->drawPath(path);
// 更新光标形状
changeCursor(cursor);
painter->restore();
}
Qt::CursorShape nmObjRoundTool::getCursorBy(const int& nOption,
const int& nSubIndex)
{
if (nOption < 0)
{
return Qt::ArrowCursor;
}
// 选择状态下起作用
if (!m_pObj->isSelected()) {
return Qt::ArrowCursor;
}
ObjHitOption oHitOption = (ObjHitOption)nOption;
if(oHitOption == OHO_Point)
{
return (Qt::CrossCursor);
}
else if(oHitOption == OHO_Bound)
{
return (Qt::ArrowCursor);
}
else if (oHitOption == OHO_Inner)
{
return (Qt::PointingHandCursor);
}
return Qt::ArrowCursor;
}