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++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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