|
|
#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;
|
|
|
}
|
|
|
|