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/nmObjRound.cpp

449 lines
12 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 "ZxSerializer.h"
#include "IxPtyPano.h"
#include "ZxSubAxisX.h"
#include "ZxSubAxisY.h"
#include "nmObjRoundTool.h"
#include "nmObjRound.h"
#include "nmDataAnalyzeManager.h"
ZX_DEFINE_DYNAMIC(nObjRound, nmObjRound)
nmObjRound::nmObjRound() {
m_sObjTag = "nObjRound";
nmObjRound::init("", NULL, NULL);
}
nmObjRound::nmObjRound(const QString& sName, \
ZxSubAxisX* pAxisX, \
ZxSubAxisY* pAxisY) {
m_sObjTag = "nObjRound";
nmObjRound::init(sName, pAxisX, pAxisY);
}
nmObjRound::~nmObjRound() {
}
// 初始化矩形对象对应的笔和填充颜色
void nmObjRound::init(const QString& sName, \
ZxSubAxisX* pAxisX, \
ZxSubAxisY* pAxisY) {
nmObjBase::init(sName, pAxisX, pAxisY);
nmObjRound::initFlags();
m_oPen = QPen(QBrush(QColor(0, 0, 0)), \
0.5f, Qt::SolidLine);
m_clrBackgrd = QColor(255, 170, 255, 100);
loadTempl();
}
// 初始化绘制圆形的工具
void nmObjRound::initTools() {
m_pTool = new nmObjRoundTool();
nmObjBase::initTools();
}
void nmObjRound::initFlags() {
setLockPos(false);
setLockSize(false);
setReadOnly(false);
}
QColor nmObjRound::getBackgrdColor() const {
//if (m_nLineIndex)
//return m_vecPresType[m_nLineIndex]
return m_clrBackgrd;
}
void nmObjRound::setBackgrdColor(QColor color) {
if (m_clrBackgrd != color) {
//m_vecPresType[m_nLineIndex] =
m_clrBackgrd = color;
update();
}
}
bool nmObjRound::hitTest(const QPointF& pt) {
return nmObjBase::hitTest(pt);
}
bool nmObjRound::_runHitTest(const QPointF& pt, int& nOption, int& nSubIndex) {
if (!nmObjBase::_runHitTest(pt, nOption, nSubIndex)) {
return false;
}
nOption = -1;
nSubIndex = 0;
if (NULL == m_pAxisX || NULL == m_pAxisY) {
return false;
}
QVector<QPointF> pts = getPosOf(m_vecPoints);
// 判断半径是否相同,不相同先修改半径相同
if (pts[1].x() != pts[1].y())
{
double radius = qAbs(pts[0].y() - pts[2].y());
pts[1] = QPointF(radius, radius);
// 重新计算圆上的四个点
QPointF center = pts[0]; // 圆心
// 上点 (x, y - radius)
pts[2] = QPointF(center.x(), center.y() - radius);
// 右点 (x + radius, y)
pts[3] = QPointF(center.x() + radius, center.y());
// 下点 (x, y + radius)
pts[4] = QPointF(center.x(), center.y() + radius);
// 左点 (x - radius, y)
pts[5] = QPointF(center.x() - radius, center.y());
}
// 点
double r = 1.f;
QPointF p1;//p1:击中的点p2:圆心
bool isInitialized = false;
for (int i = 2; i < pts.count(); i++) { //下标从2开始
QPointF ptTopLeft = QPointF(pts[i].x() - r,
pts[i].y() - r);
QSizeF sz = QSizeF(r * 2.f, r * 2.f);
QRectF rt = QRectF(ptTopLeft, sz);
bool b = rt.contains(pt);
if (b) {
// 击中了这个点,记录该点的位置
p1 = pts[i];
nSubIndex = i;
isInitialized = true;
break;
}
}
QPointF p2 = pts[0];
//判断该点所在的位置,与圆心作比较
if (isInitialized) {
if(p1.x() == p2.x() && p1.y() < p2.y()) { //上
nOption = (int)OHO_Point;
} else if (p1.x() > p2.x() && p1.y() == p2.y()) { //右
nOption = (int)OHO_Point;
} else if (p1.x() == p2.x () && p1.y() > p2.y()) { //下
nOption = (int)OHO_Point;
} else if(p1.x() < p2.x() && p1.y() == p2.y()) {
nOption = (int)OHO_Point;//左
}
return true;
}
// 判断线所在的位置
qreal distance = QLineF(pts[0], pt).length();
qreal radius = pts[1].x();
// 允许误差范围
qreal epsilon = 2.0;
// 判断鼠标是否位于圆的边界(即圆的线)上
if (fabs(distance - radius) <= epsilon) {
nOption = (int)OHO_Bound;
return true;
}
// 内部
QPainterPath oPath;
// 添加圆形路径
oPath.addEllipse(pts[0], pts[1].x(), pts[1].y());
if (oPath.contains(pt) && isSelected()) {
nOption = (int)OHO_Inner;
nSubIndex = 0;
return true;
} else {
nOption = (int)OHO_None;
}
return false;
}
bool nmObjRound::runMove(const QPointF& pt1,
const QPointF& pt2) {
if (isLockPos()) {
return false;
}
if (NULL == m_pAxisX || NULL == m_pAxisY) {
return false;
}
int nCount = m_vecPoints.count();
QVector<QPointF> vecPts = getPosOf(m_vecPoints); //屏幕值
// 判断半径是否相同,不相同先修改半径相同
if (vecPts[1].x() != vecPts[1].y())
{
double radius = qAbs(vecPts[0].y() - vecPts[2].y());
vecPts[1] = QPointF(radius, radius);
// 重新计算圆上的四个点
QPointF center = vecPts[0]; // 圆心
// 上点 (x, y - radius)
vecPts[2] = QPointF(center.x(), center.y() - radius);
// 右点 (x + radius, y)
vecPts[3] = QPointF(center.x() + radius, center.y());
// 下点 (x, y + radius)
vecPts[4] = QPointF(center.x(), center.y() + radius);
// 左点 (x - radius, y)
vecPts[5] = QPointF(center.x() - radius, center.y());
}
if (m_oHitOption == OHO_Point) { //击中上下边
// x不变
QPointF p1 = pt2;
p1.setX(pt1.x());
//计算偏移量
qreal offset = pt1.y() - pt2.y();
// 判断是上边还是下边
if (m_nHitIndex == 2) { // 上边
// 更新半径
vecPts[1].setX(vecPts[1].x() + offset);
vecPts[1].setY(vecPts[1].y() + offset);
// 更新四个点
vecPts[2].setY(vecPts[2].y() - offset);
vecPts[4].setY(vecPts[4].y() + offset);
vecPts[5].setX(vecPts[5].x() - offset); //左
vecPts[3].setX(vecPts[3].x() + offset); //右
} else if (m_nHitIndex == 4) { // 下边
offset = pt2.y() - pt1.y();
// 更新半径
vecPts[1].setX(vecPts[1].x() + offset);
vecPts[1].setY(vecPts[1].y() + offset);
// 下边
vecPts[4].setY(vecPts[4].y() + offset);
vecPts[2].setY(vecPts[2].y() - offset);
vecPts[3].setX(vecPts[3].x() + offset);
vecPts[5].setX(vecPts[5].x() - offset);
}else if (m_nHitIndex == 3) { // 右边
offset = pt2.x() - pt1.x();
// 更新半径
vecPts[1].setX(vecPts[1].x() + offset);
vecPts[1].setY(vecPts[1].y() + offset);
// 右边
vecPts[3].setX(vecPts[3].x() + offset);
vecPts[5].setX(vecPts[5].x() - offset);
vecPts[2].setY(vecPts[2].y() - offset); // 上
vecPts[4].setY(vecPts[4].y() + offset); // 下
} else if (m_nHitIndex == 5) { // 左边
offset = pt1.x() - pt2.x();
// 更新半径
vecPts[1].setX(vecPts[1].x() + offset);
vecPts[1].setY(vecPts[1].y() + offset);
// 左边
vecPts[5].setX(vecPts[5].x() - offset);
vecPts[3].setX(vecPts[3].x() + offset);
vecPts[2].setY(vecPts[2].y() - offset); // 上
vecPts[4].setY(vecPts[4].y() + offset); // 下
}
nmDataAnalyzeManager::getCurrentInstance()->notifyDataChanged();
return moveToPos(vecPts);
} else if (m_oHitOption == OHO_Bound) { //左右两边
// y不变
QPointF p1 = pt2;
p1.setY(pt1.y());
//计算偏移量
qreal offset = pt2.x() - pt1.x();
// 判断是上边还是下边
if (m_nHitIndex == 3) { // 右边
// 更新半径
vecPts[1].setX(vecPts[1].x() + offset);
vecPts[1].setY(vecPts[1].y() + offset);
// 更新四个点
vecPts[3].setX(vecPts[3].x() + offset); //右
vecPts[5].setX(vecPts[5].x() - offset); //左
vecPts[2].setY(vecPts[2].y() - offset); // 上
vecPts[4].setY(vecPts[4].y() + offset); //下
} else if (m_nHitIndex == 5) { // 左边
offset = pt1.x() - pt2.x();
// 更新半径
vecPts[1].setX(vecPts[1].x() + offset);
vecPts[1].setY(vecPts[1].y() + offset);
// 更新四个点
vecPts[3].setX(vecPts[3].x() + offset); //右
vecPts[5].setX(vecPts[5].x() - offset); //左
vecPts[2].setY(vecPts[2].y() - offset); // 上
vecPts[4].setY(vecPts[4].y() + offset); //下
}
nmDataAnalyzeManager::getCurrentInstance()->notifyDataChanged();
return moveToPos(vecPts);
}
if (m_oHitOption == OHO_Inner) {
// 更新圆点
vecPts[0] = offsetPoint(vecPts[0], pt1, pt2);
m_dOffsetX = pt2.x() - pt1.x();
m_dOffsetY = pt2.y() - pt1.y();
// 更新上下左右四个点
for (int i = 2; i < vecPts.count(); i++) {
vecPts[i] = offsetPoint(vecPts[i], pt1, pt2);
}
nmDataAnalyzeManager::getCurrentInstance()->notifyDataChanged();
return moveToPos(vecPts);
} else {
return false;
}
return true;
}
void nmObjRound::fillPtyPano(IxPtyPano* sheet) {
nmObjBase::fillPtyPano(sheet);
ZX_PROP("ObjPolygon.Pen", getPen, setPen);
ZX_PROP("ObjPolygon.BackgrdColor", getBackgrdColor, setBackgrdColor);
}
void nmObjRound::paintBack(QPainter* painter, const ZxPaintParam& param) {
// 判断当前坐标轴是否有效
if (NULL == m_pAxisX || NULL == m_pAxisY || \
m_pAxisX->getRangeMin() == m_pAxisX->getRangeMax() || \
m_pAxisY->getRangeMin() == m_pAxisY->getRangeMax()) {
return;
}
painter->save();
//QVector<QPointF> pts = getPosOf(m_vecPoints); //获取当前对象的原点的坐标
//QRectF bound = getBounds(); //获取图元基础边框(位置)
// 判断半径是否相同,不相同先修改半径相同
if (m_vecPoints[1].x() != m_vecPoints[1].y())
{
// 重新计算半径
// 计算半径(绝对值)
double radius = qAbs(m_vecPoints[0].y() - m_vecPoints[2].y());
// 更新 vecConvertPoints[1] 为 (radius, radius)
m_vecPoints[1] = QPointF(radius, radius);
}
QVector<QPointF> pts = getPosOf(m_vecPoints);
// 判断半径是否相同,不相同先修改半径相同,重新计算上下左右四个点的坐标
if (pts[1].x() != pts[1].y())
{
double radius = qAbs(pts[0].y() - pts[2].y());
pts[1] = QPointF(radius, radius);
// 重新计算圆上的四个点
QPointF center = pts[0]; // 圆心
// 上点 (x, y - radius)
pts[2] = QPointF(center.x(), center.y() - radius);
// 右点 (x + radius, y)
pts[3] = QPointF(center.x() + radius, center.y());
// 下点 (x, y + radius)
pts[4] = QPointF(center.x(), center.y() + radius);
// 左点 (x - radius, y)
pts[5] = QPointF(center.x() - radius, center.y());
}
if (!pts.empty()) { //圆存在
// 填充
QPainterPath oPath;
// 添加圆形路径
oPath.addEllipse(pts[0], pts[1].x(), pts[1].y());
// m_clrBackgrd.setAlpha(100);
painter->fillPath(oPath, QBrush(m_clrBackgrd));
// 边界
QPen pen = m_oPen;
painter->setPen(pen);
painter->drawEllipse(pts[0], pts[1].x(), pts[1].y());
// 获取圆心和半径
QPointF center = pts[0];
qreal radius = pts[1].x();
// 计算边界框的左上角和右下角坐标
QPointF topLeft = center - QPointF(radius, radius);
QPointF bottomRight = center + QPointF(radius, radius);
// 创建QRectF对象
QRectF bound(topLeft, bottomRight);
// 绘制名称文字
painter->setFont(QFont("Arial", 8, QFont::Normal));
painter->setPen(Qt::black);
ZxDrawHelper::drawText(painter,
bound,
Qt::AlignCenter | Qt::AlignVCenter,
m_sName);
}
//选中状态下的圆形形状
if (isSelected()) {
QPen pen(QBrush(Qt::black), 0.0f, Qt::DotLine);
painter->setPen(pen);
painter->drawEllipse(pts[0], pts[1].x(), pts[1].y());
for (int i = 2; i < pts.count(); i++) {
double w = 2.2f;
QPointF pt = pts[i];
QRectF rect(pt.x() - w * 0.5f, pt.y() - w * 0.5f, w, w); //每个点周围画小矩形边框
// 击中四个点
if (m_nHitIndex == i && (m_oHitOption == OHO_Point || m_oHitOption == OHO_Bound)) {
QBrush br(Qt::red);
painter->fillRect(rect, br);
} else {
painter->setPen(QColor(0, 0, 128));
painter->drawRect(rect);
}
}
}
painter->restore();
}