1357 lines
43 KiB
C++
1357 lines
43 KiB
C++
|
|
#include "mygraphicsscene.h"
|
|||
|
|
#include <cmath>
|
|||
|
|
|
|||
|
|
MyGraphicsScene::MyGraphicsScene()
|
|||
|
|
{
|
|||
|
|
m_selectedBrush.setColor(Qt::red);
|
|||
|
|
m_defaultBrush.setColor(Qt::blue);
|
|||
|
|
|
|||
|
|
m_ellipseItemList.clear();
|
|||
|
|
m_lineItemList.clear();
|
|||
|
|
|
|||
|
|
m_draggingPoint = NULL;
|
|||
|
|
m_shapeType = -1;
|
|||
|
|
m_addOrder = 0;
|
|||
|
|
m_isAdsorption = false;
|
|||
|
|
m_ArcCount = 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
MyGraphicsScene::~MyGraphicsScene()
|
|||
|
|
{
|
|||
|
|
for(int i = 0; i < m_ellipseItemList.size(); i++)
|
|||
|
|
{
|
|||
|
|
if(m_ellipseItemList[i] != NULL)
|
|||
|
|
{
|
|||
|
|
delete m_ellipseItemList[i];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
for(int i = 0; i < m_lineItemList.size(); i++)
|
|||
|
|
{
|
|||
|
|
if(m_lineItemList[i].item != NULL)
|
|||
|
|
{
|
|||
|
|
delete m_lineItemList[i].item;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void MyGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|||
|
|
{
|
|||
|
|
if(m_draggingPoint)
|
|||
|
|
{
|
|||
|
|
m_draggingPoint->setPen(Qt::NoPen);
|
|||
|
|
m_draggingPoint->setBrush(Qt::blue);
|
|||
|
|
m_draggingPoint = NULL;
|
|||
|
|
emit siCurrentIndex(0);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool selectFlag = false;
|
|||
|
|
|
|||
|
|
if (event->button() != Qt::LeftButton)
|
|||
|
|
{
|
|||
|
|
return QGraphicsScene::mousePressEvent(event);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 找到被点击的点
|
|||
|
|
for (QGraphicsEllipseItem *point : m_ellipseItemList)
|
|||
|
|
{
|
|||
|
|
//rect是setpos之前的边框,所以要加上pos坐标值
|
|||
|
|
QRectF rect = point->boundingRect();
|
|||
|
|
rect.setLeft(rect.left() + point->x());
|
|||
|
|
rect.setRight(rect.right() + point->x());
|
|||
|
|
rect.setTop(rect.top() + point->y());
|
|||
|
|
rect.setBottom(rect.bottom() + point->y());
|
|||
|
|
|
|||
|
|
if (rect.contains(event->scenePos()))
|
|||
|
|
{
|
|||
|
|
if(m_draggingPoint)
|
|||
|
|
{
|
|||
|
|
m_draggingPoint->setPen(Qt::NoPen);
|
|||
|
|
m_draggingPoint->setBrush(Qt::blue);
|
|||
|
|
m_draggingPoint = NULL;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 选中点
|
|||
|
|
point->setPen(Qt::NoPen);
|
|||
|
|
point->setBrush(Qt::red);
|
|||
|
|
m_draggingPoint = point;
|
|||
|
|
|
|||
|
|
int index = m_ellipseItemList.indexOf(m_draggingPoint);
|
|||
|
|
//qDebug()<<"index"<<index;
|
|||
|
|
emit siCurrentIndex(index+1);
|
|||
|
|
|
|||
|
|
//qDebug()<<"m_draggingPoint->pos()"<<m_draggingPoint->pos();
|
|||
|
|
m_dragOffset = event->scenePos() - point->pos();
|
|||
|
|
selectFlag = true;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//选中点
|
|||
|
|
if(selectFlag == true)
|
|||
|
|
{
|
|||
|
|
return QGraphicsScene::mousePressEvent(event);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
QPointF pressPos = event->scenePos();
|
|||
|
|
//添加吸附判断
|
|||
|
|
if(m_isAdsorption)
|
|||
|
|
pressPos = m_grid->getClosestFocus(event->scenePos());
|
|||
|
|
|
|||
|
|
//画点 //重复点不要添加
|
|||
|
|
if((m_shapeType == TYPE_DRAG)
|
|||
|
|
|| (m_ellipseItemList.size() != 0
|
|||
|
|
&& pressPos == m_ellipseItemList.last()->pos()))
|
|||
|
|
return QGraphicsScene::mousePressEvent(event);
|
|||
|
|
|
|||
|
|
if(m_shapeType == TYPE_LINE)
|
|||
|
|
{
|
|||
|
|
if(m_ellipseItemList.size() <= 1)
|
|||
|
|
{
|
|||
|
|
//默认位置中心都是0
|
|||
|
|
QGraphicsEllipseItem *ellipse = this->addEllipse(0 - m_radius,
|
|||
|
|
0 - m_radius,
|
|||
|
|
2*m_radius,
|
|||
|
|
2*m_radius);
|
|||
|
|
ellipse->setPos(pressPos);
|
|||
|
|
ellipse->setPen(Qt::NoPen);
|
|||
|
|
ellipse->setBrush(Qt::blue);
|
|||
|
|
//point->setFlag(QGraphicsItem::ItemIsSelectable, true);
|
|||
|
|
ellipse->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
|
|||
|
|
m_ellipseItemList.append(ellipse);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
//先添加起点
|
|||
|
|
QGraphicsEllipseItem *pointPre = m_ellipseItemList[m_ellipseItemList.size()-1];
|
|||
|
|
QGraphicsEllipseItem *point = this->addEllipse(0 - m_radius,
|
|||
|
|
0 - m_radius,
|
|||
|
|
2*m_radius,
|
|||
|
|
2*m_radius);
|
|||
|
|
point->setPos(pointPre->pos());
|
|||
|
|
point->setPen(Qt::NoPen);
|
|||
|
|
point->setBrush(Qt::blue);
|
|||
|
|
//point->setFlag(QGraphicsItem::ItemIsSelectable, true);
|
|||
|
|
point->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
|
|||
|
|
m_ellipseItemList.append(point);
|
|||
|
|
|
|||
|
|
//默认位置中心都是0
|
|||
|
|
QGraphicsEllipseItem *ellipse = this->addEllipse(0 - m_radius,
|
|||
|
|
0 - m_radius,
|
|||
|
|
2*m_radius,
|
|||
|
|
2*m_radius);
|
|||
|
|
ellipse->setPos(pressPos);
|
|||
|
|
ellipse->setPen(Qt::NoPen);
|
|||
|
|
ellipse->setBrush(Qt::blue);
|
|||
|
|
//point->setFlag(QGraphicsItem::ItemIsSelectable, true);
|
|||
|
|
ellipse->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
|
|||
|
|
m_ellipseItemList.append(ellipse);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(m_ellipseItemList.size() <= 1)
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
m_addOrder++;
|
|||
|
|
QPointF start = m_ellipseItemList.at(m_ellipseItemList.size() - 2)->pos();
|
|||
|
|
QPointF end = pressPos;
|
|||
|
|
|
|||
|
|
QVector<QPointF> points;
|
|||
|
|
points.append(start);
|
|||
|
|
points.append(end);
|
|||
|
|
QGraphicsPolygonItem *line = this->addPolygon(QPolygonF(points));
|
|||
|
|
QPen pen;
|
|||
|
|
pen.setWidthF(1);
|
|||
|
|
pen.setCosmetic(true); // 设置为眉笔模式,线段在缩放时保证粗细不变
|
|||
|
|
pen.setColor(Qt::blue);
|
|||
|
|
line->setPen(pen);
|
|||
|
|
GLineItem item;
|
|||
|
|
item.order = m_addOrder;
|
|||
|
|
item.type = QUI_TYPE_LINE;
|
|||
|
|
item.item = line;
|
|||
|
|
item.points.append(start);
|
|||
|
|
item.points.append(end);
|
|||
|
|
m_lineItemList.append(item);
|
|||
|
|
}
|
|||
|
|
else if(m_shapeType == TYPE_ARC)
|
|||
|
|
{
|
|||
|
|
if(m_ellipseItemList.size() <= 2)
|
|||
|
|
{
|
|||
|
|
//默认位置中心都是0
|
|||
|
|
QGraphicsEllipseItem *ellipse = this->addEllipse(0 - m_radius,
|
|||
|
|
0 - m_radius,
|
|||
|
|
2*m_radius,
|
|||
|
|
2*m_radius);
|
|||
|
|
ellipse->setPos(pressPos);
|
|||
|
|
ellipse->setPen(Qt::NoPen);
|
|||
|
|
ellipse->setBrush(Qt::blue);
|
|||
|
|
//point->setFlag(QGraphicsItem::ItemIsSelectable, true);
|
|||
|
|
ellipse->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
|
|||
|
|
m_ellipseItemList.append(ellipse);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
if(m_ArcCount == 1)
|
|||
|
|
{
|
|||
|
|
//先添加起点
|
|||
|
|
QGraphicsEllipseItem *pointPre = m_ellipseItemList[m_ellipseItemList.size()-1];
|
|||
|
|
QGraphicsEllipseItem *point = this->addEllipse(0 - m_radius,
|
|||
|
|
0 - m_radius,
|
|||
|
|
2*m_radius,
|
|||
|
|
2*m_radius);
|
|||
|
|
point->setPos(pointPre->pos());
|
|||
|
|
point->setPen(Qt::NoPen);
|
|||
|
|
point->setBrush(Qt::blue);
|
|||
|
|
//point->setFlag(QGraphicsItem::ItemIsSelectable, true);
|
|||
|
|
point->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
|
|||
|
|
m_ellipseItemList.append(point);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//默认位置中心都是0
|
|||
|
|
QGraphicsEllipseItem *ellipse = this->addEllipse(0 - m_radius,
|
|||
|
|
0 - m_radius,
|
|||
|
|
2*m_radius,
|
|||
|
|
2*m_radius);
|
|||
|
|
ellipse->setPos(pressPos);
|
|||
|
|
ellipse->setPen(Qt::NoPen);
|
|||
|
|
ellipse->setBrush(Qt::blue);
|
|||
|
|
//point->setFlag(QGraphicsItem::ItemIsSelectable, true);
|
|||
|
|
ellipse->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
|
|||
|
|
m_ellipseItemList.append(ellipse);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
m_ArcCount++;
|
|||
|
|
|
|||
|
|
if(m_ArcCount < 3)//三点确定一条圆弧
|
|||
|
|
return QGraphicsScene::mousePressEvent(event);
|
|||
|
|
|
|||
|
|
QList<QPointF> points;
|
|||
|
|
points.clear();
|
|||
|
|
//第一个点默认为上一个点
|
|||
|
|
QPointF point1 = m_ellipseItemList.at(m_ellipseItemList.size() - 3)->pos();
|
|||
|
|
points.append(point1);
|
|||
|
|
QPointF point2 = m_ellipseItemList.at(m_ellipseItemList.size() - 2)->pos();
|
|||
|
|
points.append(point2);
|
|||
|
|
QPointF point3 = m_ellipseItemList.at(m_ellipseItemList.size() - 1)->pos();
|
|||
|
|
points.append(point3);
|
|||
|
|
|
|||
|
|
if(points.size() == 3)
|
|||
|
|
{
|
|||
|
|
m_addOrder++;
|
|||
|
|
double threex[3], threey[3];
|
|||
|
|
threex[0] = points[0].x();
|
|||
|
|
threex[1] = points[1].x();
|
|||
|
|
threex[2] = points[2].x();
|
|||
|
|
threey[0] = points[0].y();
|
|||
|
|
threey[1] = points[1].y();
|
|||
|
|
threey[2] = points[2].y();
|
|||
|
|
QGraphicsPathItem *arcItem = new QGraphicsPathItem();
|
|||
|
|
getArcItem(points,arcItem,threex,threey);
|
|||
|
|
|
|||
|
|
if(arcItem != NULL)
|
|||
|
|
{
|
|||
|
|
this->addItem(arcItem); // 添加到场景中以显示
|
|||
|
|
GPathItem item;
|
|||
|
|
item.order = m_addOrder;
|
|||
|
|
item.type = QUI_TYPE_ARC;
|
|||
|
|
item.item = arcItem;
|
|||
|
|
item.points = points;
|
|||
|
|
m_pathItemList.append(item);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#if(0)
|
|||
|
|
QList<QPointF> arcPoints;
|
|||
|
|
QPointF center;
|
|||
|
|
double radius;
|
|||
|
|
|
|||
|
|
// 计算圆心
|
|||
|
|
bool bl = findCircleCenter(point1, point2, point3,center,radius);
|
|||
|
|
if(bl == false)
|
|||
|
|
{
|
|||
|
|
qDebug()<<"findCircleCenter false";
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
double startAngle = atan2(point1.y() - center.y(), point1.x() - center.x());
|
|||
|
|
double endAngle = atan2(point3.y() - center.y(), point3.x() - center.x());
|
|||
|
|
// 生成圆弧上的点
|
|||
|
|
double angleSpan = fabs(endAngle - startAngle);
|
|||
|
|
double arcLength = radius * angleSpan;
|
|||
|
|
// 圆弧上的点数
|
|||
|
|
int segments = qMax(1, static_cast<int>(arcLength / (static_cast<double>(m_maxSegmentLength) / 10)));
|
|||
|
|
|
|||
|
|
QPointF v1 = point1 - center;
|
|||
|
|
QPointF v2 = point2 - center;
|
|||
|
|
QPointF v3 = point3 - center;
|
|||
|
|
// 叉积判断方向
|
|||
|
|
double cross = (v2.x() - v1.x()) * (v3.y() - v1.y()) - (v2.y() - v1.y()) * (v3.x() - v1.x());
|
|||
|
|
bool clockwise = (cross < 0); // true 为顺时针,false 为逆时针
|
|||
|
|
|
|||
|
|
if (!clockwise) {
|
|||
|
|
if (endAngle < startAngle) endAngle += 2 * M_PI;
|
|||
|
|
} else {
|
|||
|
|
if (endAngle > startAngle) endAngle -= 2 * M_PI;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
for (int i = 0; i <= segments; ++i)
|
|||
|
|
{
|
|||
|
|
double angle = startAngle + i * (endAngle - startAngle) / segments;
|
|||
|
|
QPointF point(center.x() + radius * cos(angle), center.y() + radius * sin(angle));
|
|||
|
|
arcPoints.append(point);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this->removeItem(m_ellipseItemList.last());
|
|||
|
|
m_ellipseItemList.removeLast();
|
|||
|
|
this->removeItem(m_ellipseItemList.last());
|
|||
|
|
m_ellipseItemList.removeLast();
|
|||
|
|
for(int i = 0; i < arcPoints.size()-1; i++)
|
|||
|
|
{
|
|||
|
|
QPointF start = arcPoints[i];
|
|||
|
|
QPointF end = arcPoints[i+1];
|
|||
|
|
|
|||
|
|
//默认位置中心都是0
|
|||
|
|
QGraphicsEllipseItem *point = this->addEllipse(0-m_radius,
|
|||
|
|
0-m_radius,
|
|||
|
|
2*m_radius,
|
|||
|
|
2*m_radius);
|
|||
|
|
point->setPen(Qt::NoPen);
|
|||
|
|
point->setBrush(Qt::blue);
|
|||
|
|
//point->setFlag(QGraphicsItem::ItemIsSelectable, true);
|
|||
|
|
point->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
|
|||
|
|
m_ellipseItemList.append(point);
|
|||
|
|
//调整椭圆的位置,使其中心位于 points[i]
|
|||
|
|
point->setPos(end.x(), end.y());
|
|||
|
|
|
|||
|
|
// QGraphicsLineItem *line = this->addLine(start.x(), start.y(), end.x(), end.y());
|
|||
|
|
// QPen pen;
|
|||
|
|
// pen.setWidthF(1);
|
|||
|
|
// pen.setCosmetic(true); // 设置为眉笔模式,线段在缩放时保证粗细不变
|
|||
|
|
// pen.setColor(Qt::blue);
|
|||
|
|
// line->setPen(pen);
|
|||
|
|
// GLineItem item;
|
|||
|
|
// item.type = QUI_TYPE_ARC;
|
|||
|
|
// item.item = line;
|
|||
|
|
// item.points.append(start);
|
|||
|
|
// item.points.append(end);
|
|||
|
|
// m_lineItemList.append(item);
|
|||
|
|
}
|
|||
|
|
#endif
|
|||
|
|
//移除前两个点
|
|||
|
|
m_ArcCount = 1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//未选中 默认最后一个点是选中点
|
|||
|
|
if(selectFlag == false && m_ellipseItemList.size() != 0)
|
|||
|
|
{
|
|||
|
|
setLastPointSelected();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return QGraphicsScene::mousePressEvent(event);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void MyGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|||
|
|
{
|
|||
|
|
//qDebug()<<"mouseMoveEvent";
|
|||
|
|
|
|||
|
|
if (event->buttons() & Qt::LeftButton && m_draggingPoint)
|
|||
|
|
{
|
|||
|
|
QPointF newPos = event->scenePos();
|
|||
|
|
// 更新相关的线段
|
|||
|
|
int relLine = getGLineItem(m_draggingPoint,newPos);
|
|||
|
|
//如果直线和圆弧共点(relLine和relArc都会 >0),则先处理直线的点,所以这个if的最后会return
|
|||
|
|
if(relLine > 0)
|
|||
|
|
{
|
|||
|
|
update();
|
|||
|
|
m_draggingPoint->setPos(newPos);
|
|||
|
|
return QGraphicsScene::mouseMoveEvent(event);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int relArc = getGPathItem(m_draggingPoint,newPos);
|
|||
|
|
if(relArc > 0)
|
|||
|
|
{
|
|||
|
|
update();
|
|||
|
|
m_draggingPoint->setPos(newPos);
|
|||
|
|
return QGraphicsScene::mouseMoveEvent(event);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return QGraphicsScene::mouseMoveEvent(event);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void MyGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
|||
|
|
{
|
|||
|
|
return QGraphicsScene::mouseReleaseEvent(event);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
QPointF MyGraphicsScene::midpoint(const QPointF &p1, const QPointF &p2)
|
|||
|
|
{
|
|||
|
|
return QPointF((p1.x() + p2.x()) / 2.0, (p1.y() + p2.y()) / 2.0);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
double MyGraphicsScene::slope(const QPointF &p1, const QPointF &p2)
|
|||
|
|
{
|
|||
|
|
if (p2.x() == p1.x()) return 1; // 避免除以零
|
|||
|
|
return (p2.y() - p1.y()) / (p2.x() - p1.x());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool MyGraphicsScene::findCircleCenter(const QPointF &p1, const QPointF &p2, const QPointF &p3, QPointF ¢er, double &radius)
|
|||
|
|
{
|
|||
|
|
//判断三点是否共线
|
|||
|
|
double x1 = p1.x();
|
|||
|
|
double y1 = p1.y();
|
|||
|
|
double x2 = p2.x();
|
|||
|
|
double y2 = p2.y();
|
|||
|
|
double x3 = p3.x();
|
|||
|
|
double y3 = p3.y();
|
|||
|
|
double val = (int)(y3 - y1) * (int)(x2 - x1) - (int)(y2 - y1) * (int)(x3 - x1);
|
|||
|
|
if(val == 0)//三点共线
|
|||
|
|
{
|
|||
|
|
return false;//三点共线
|
|||
|
|
}
|
|||
|
|
else//求圆心和半径
|
|||
|
|
{
|
|||
|
|
double a, b, c, d, e, f;
|
|||
|
|
double xc, yc;
|
|||
|
|
a = 2 * (x2-x1);
|
|||
|
|
b = 2 * (y2-y1);
|
|||
|
|
c = x2*x2 + y2*y2 - x1*x1 - y1*y1;
|
|||
|
|
d = 2 * (x3-x2);
|
|||
|
|
e = 2 * (y3-y2);
|
|||
|
|
f = x3*x3+ y3*y3 - x2*x2 - y2*y2;
|
|||
|
|
|
|||
|
|
//圆心
|
|||
|
|
xc = (b*f-e*c)/(b*d-e*a);
|
|||
|
|
yc = (d*c-a*f)/(b*d-e*a);
|
|||
|
|
center.setX(xc);
|
|||
|
|
center.setY(yc);
|
|||
|
|
|
|||
|
|
//半径
|
|||
|
|
radius = sqrt((xc-x1)*(xc-x1)+(yc-y1)*(yc-y1));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
double MyGraphicsScene::findRadius(const QPointF ¢er, const QPointF &point)
|
|||
|
|
{
|
|||
|
|
return QLineF(center, point).length();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
double MyGraphicsScene::distanceSquared(QPointF p1, QPointF p2)
|
|||
|
|
{
|
|||
|
|
return (p1.x() - p2.x()) * (p1.x() - p2.x()) + (p1.y() - p2.y()) * (p1.y() - p2.y());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void MyGraphicsScene::addItemToScene(QByteArray ary)
|
|||
|
|
{
|
|||
|
|
m_draggingPoint = NULL;
|
|||
|
|
ViewItem * pDispBuff = (ViewItem *)ary.data();
|
|||
|
|
|
|||
|
|
int size = ary.size();
|
|||
|
|
int stitchCount = size/sizeof(ViewItem);
|
|||
|
|
|
|||
|
|
if (stitchCount <= 0)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
double bx, by, ex, ey;
|
|||
|
|
bx = by = ex = ey = 0;
|
|||
|
|
|
|||
|
|
QList<QPointF> points;
|
|||
|
|
points.clear();
|
|||
|
|
|
|||
|
|
// 假设第一条线段的第一个点是起始点
|
|||
|
|
bx = pDispBuff[0].bx;
|
|||
|
|
by = pDispBuff[0].by;
|
|||
|
|
points.append(QPointF(bx, by));
|
|||
|
|
|
|||
|
|
for (int i = 0; i < stitchCount; i++)
|
|||
|
|
{
|
|||
|
|
ex = pDispBuff[i].ex;
|
|||
|
|
ey = pDispBuff[i].ey;
|
|||
|
|
points.append(QPointF(ex,ey));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//创建点和线段
|
|||
|
|
for(int i = 0; i < points.size(); i++)
|
|||
|
|
{
|
|||
|
|
//默认位置中心都是0
|
|||
|
|
QGraphicsEllipseItem *point = this->addEllipse(0-m_radius,
|
|||
|
|
0-m_radius,
|
|||
|
|
2*m_radius,
|
|||
|
|
2*m_radius);
|
|||
|
|
point->setPen(Qt::NoPen);
|
|||
|
|
point->setBrush(Qt::blue);
|
|||
|
|
//point->setFlag(QGraphicsItem::ItemIsSelectable, true);
|
|||
|
|
point->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
|
|||
|
|
m_ellipseItemList.append(point);
|
|||
|
|
|
|||
|
|
// 调整椭圆的位置,使其中心位于 points[i]
|
|||
|
|
point->setPos(points[i].x(), points[i].y());
|
|||
|
|
|
|||
|
|
if(i == points.size()-1)
|
|||
|
|
{
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
QPointF start = points[i];
|
|||
|
|
QPointF end = points[i+1];
|
|||
|
|
QVector<QPointF> vec;
|
|||
|
|
vec.append(start);
|
|||
|
|
vec.append(end);
|
|||
|
|
QGraphicsPolygonItem *line = this->addPolygon(QPolygonF(vec));
|
|||
|
|
QPen pen;
|
|||
|
|
pen.setWidthF(1);
|
|||
|
|
pen.setCosmetic(true); // 设置为眉笔模式,线段在缩放时保证粗细不变
|
|||
|
|
pen.setColor(Qt::blue);
|
|||
|
|
line->setPen(pen);
|
|||
|
|
GLineItem item;
|
|||
|
|
item.order = i;
|
|||
|
|
item.type = QUI_TYPE_LINE;
|
|||
|
|
item.item = line;
|
|||
|
|
item.points.append(start);
|
|||
|
|
item.points.append(end);
|
|||
|
|
m_lineItemList.append(item);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#if(0)
|
|||
|
|
// m_linesSeg = new MultiLineSegments(points,nullptr);
|
|||
|
|
// this->addItem(m_linesSeg);
|
|||
|
|
|
|||
|
|
// m_points.clear();
|
|||
|
|
// // 创建点
|
|||
|
|
// for (const auto &pointPos : points)
|
|||
|
|
// {
|
|||
|
|
// Endpoint *point = new Endpoint(pointPos.x(), pointPos.y(), 0.2, nullptr);
|
|||
|
|
// m_points.append(point);
|
|||
|
|
// this->addItem(point);
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
// // 创建线段
|
|||
|
|
// for (int i = 0; i < m_points.size() - 1; ++i)
|
|||
|
|
// {
|
|||
|
|
// Endpoint *start = m_points[i];
|
|||
|
|
// Endpoint *end = m_points[i + 1];
|
|||
|
|
// if(i == 0)
|
|||
|
|
// {
|
|||
|
|
// //end->setPos(QPointF(509.317,506.388));
|
|||
|
|
// }
|
|||
|
|
// LineSegment *line = new LineSegment(start, end, nullptr);
|
|||
|
|
// start->addLineItem(line);
|
|||
|
|
// end->addLineItem(line);
|
|||
|
|
// m_lines.append(line);
|
|||
|
|
// this->addItem(line);
|
|||
|
|
// }
|
|||
|
|
#endif
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void MyGraphicsScene::addItemListToScene(QList<drawItem> list)
|
|||
|
|
{
|
|||
|
|
m_draggingPoint = NULL;
|
|||
|
|
|
|||
|
|
QPen pen;
|
|||
|
|
pen.setWidthF(1);
|
|||
|
|
pen.setCosmetic(true); // 设置为眉笔模式,线段在缩放时保证粗细不变
|
|||
|
|
pen.setColor(Qt::blue);
|
|||
|
|
|
|||
|
|
for(int i = 0; i < list.size(); i++)
|
|||
|
|
{
|
|||
|
|
int num = list[i].points.size();
|
|||
|
|
|
|||
|
|
QList<QPointF> points;
|
|||
|
|
points.clear();
|
|||
|
|
|
|||
|
|
for(int j = 0; j < num; j++)
|
|||
|
|
{
|
|||
|
|
double x = list[i].points[j].x();
|
|||
|
|
double y = list[i].points[j].y();
|
|||
|
|
points.append(QPointF(x,y));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(list[i].type == QUI_TYPE_ARC)//三点圆弧
|
|||
|
|
{
|
|||
|
|
//创建点和线段
|
|||
|
|
for(int i = 0; i < points.size(); i++)
|
|||
|
|
{
|
|||
|
|
//默认位置中心都是0
|
|||
|
|
QGraphicsEllipseItem *point = this->addEllipse(0-m_radius,
|
|||
|
|
0-m_radius,
|
|||
|
|
2*m_radius,
|
|||
|
|
2*m_radius);
|
|||
|
|
point->setPen(Qt::NoPen);
|
|||
|
|
point->setBrush(Qt::blue);
|
|||
|
|
//point->setFlag(QGraphicsItem::ItemIsSelectable, true);
|
|||
|
|
point->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
|
|||
|
|
m_ellipseItemList.append(point);
|
|||
|
|
|
|||
|
|
//调整椭圆的位置,使其中心位于 points[i]
|
|||
|
|
point->setPos(points[i].x(), points[i].y());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(points.size() == 3)
|
|||
|
|
{
|
|||
|
|
double threex[3], threey[3];
|
|||
|
|
threex[0] = points[0].x();
|
|||
|
|
threex[1] = points[1].x();
|
|||
|
|
threex[2] = points[2].x();
|
|||
|
|
threey[0] = points[0].y();
|
|||
|
|
threey[1] = points[1].y();
|
|||
|
|
threey[2] = points[2].y();
|
|||
|
|
QGraphicsPathItem *arcItem = new QGraphicsPathItem();
|
|||
|
|
getArcItem(points,arcItem,threex,threey);
|
|||
|
|
|
|||
|
|
if(arcItem != NULL)
|
|||
|
|
{
|
|||
|
|
this->addItem(arcItem); // 添加到场景中以显示
|
|||
|
|
GPathItem item;
|
|||
|
|
item.order = i;
|
|||
|
|
item.type = QUI_TYPE_ARC;
|
|||
|
|
item.item = arcItem;
|
|||
|
|
item.points = points;
|
|||
|
|
m_pathItemList.append(item);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if(list[i].type == QUI_TYPE_BES)//贝塞尔
|
|||
|
|
{
|
|||
|
|
//创建点和线段
|
|||
|
|
for(int i = 0; i < points.size(); i++)
|
|||
|
|
{
|
|||
|
|
//默认位置中心都是0
|
|||
|
|
QGraphicsEllipseItem *point = this->addEllipse(0-m_radius,
|
|||
|
|
0-m_radius,
|
|||
|
|
2*m_radius,
|
|||
|
|
2*m_radius);
|
|||
|
|
point->setPen(Qt::NoPen);
|
|||
|
|
point->setBrush(Qt::blue);
|
|||
|
|
//point->setFlag(QGraphicsItem::ItemIsSelectable, true);
|
|||
|
|
point->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
|
|||
|
|
m_ellipseItemList.append(point);
|
|||
|
|
|
|||
|
|
//调整椭圆的位置,使其中心位于 points[i]
|
|||
|
|
point->setPos(points[i].x(), points[i].y());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(points.size() == 4)
|
|||
|
|
{
|
|||
|
|
// 创建 QPainterPath 并添加贝塞尔曲线
|
|||
|
|
QPainterPath path;
|
|||
|
|
path.moveTo(points[0]); // 移动到起始点
|
|||
|
|
path.cubicTo(points[1], points[2], points[3]); // 添加贝塞尔曲线
|
|||
|
|
// 创建 QGraphicsPathItem 并设置路径
|
|||
|
|
QGraphicsPathItem *cubItem = new QGraphicsPathItem(path);
|
|||
|
|
cubItem->setPen(pen); // 设置线条颜色和宽度
|
|||
|
|
this->addItem(cubItem); // 添加到场景中以显示
|
|||
|
|
GPathItem item;
|
|||
|
|
item.order = i;
|
|||
|
|
item.type = QUI_TYPE_BES;
|
|||
|
|
item.item = cubItem;
|
|||
|
|
item.points = points;
|
|||
|
|
m_pathItemList.append(item);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else//直线
|
|||
|
|
{
|
|||
|
|
//创建点和线段
|
|||
|
|
QVector<QPointF> pointsVec;
|
|||
|
|
pointsVec.clear();
|
|||
|
|
for(int m = 0; m < points.size(); m++)
|
|||
|
|
{
|
|||
|
|
//默认位置中心都是0
|
|||
|
|
QGraphicsEllipseItem *point = this->addEllipse(0-m_radius,
|
|||
|
|
0-m_radius,
|
|||
|
|
2*m_radius,
|
|||
|
|
2*m_radius);
|
|||
|
|
point->setPen(Qt::NoPen);
|
|||
|
|
point->setBrush(Qt::blue);
|
|||
|
|
//point->setFlag(QGraphicsItem::ItemIsSelectable, true);
|
|||
|
|
point->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
|
|||
|
|
m_ellipseItemList.append(point);
|
|||
|
|
|
|||
|
|
// 调整椭圆的位置,使其中心位于 points[i]
|
|||
|
|
point->setPos(points[m].x(), points[m].y());
|
|||
|
|
pointsVec.append(points[m]);
|
|||
|
|
}
|
|||
|
|
QGraphicsPolygonItem *poly = this->addPolygon(QPolygonF(pointsVec));
|
|||
|
|
if(list[i].type != QUI_TYPE_LINE)
|
|||
|
|
{
|
|||
|
|
pen.setColor(Qt::green);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
pen.setColor(Qt::blue);
|
|||
|
|
}
|
|||
|
|
poly->setPen(pen);
|
|||
|
|
GLineItem item;
|
|||
|
|
item.order = i;
|
|||
|
|
item.type = list[i].type;
|
|||
|
|
item.item = poly;
|
|||
|
|
item.points = list[i].points;
|
|||
|
|
m_lineItemList.append(item);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void MyGraphicsScene::addGrid(double gridSpacing, QRectF rect)
|
|||
|
|
{
|
|||
|
|
// m_gridSpacing = gridSpacing;
|
|||
|
|
// m_gridRect = rect;
|
|||
|
|
|
|||
|
|
m_grid = new MyGraphicsGridItem(gridSpacing, rect);
|
|||
|
|
this->addItem(m_grid);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void MyGraphicsScene::cleanScene()
|
|||
|
|
{
|
|||
|
|
m_shapeType = -1;
|
|||
|
|
m_draggingPoint = NULL;
|
|||
|
|
for(int i = 0 ; i < m_ellipseItemList.size(); i++)
|
|||
|
|
{
|
|||
|
|
this->removeItem(m_ellipseItemList[i]);
|
|||
|
|
}
|
|||
|
|
m_ellipseItemList.clear();
|
|||
|
|
|
|||
|
|
for(int i = 0 ; i < m_lineItemList.size(); i++)
|
|||
|
|
{
|
|||
|
|
this->removeItem(m_lineItemList[i].item);
|
|||
|
|
m_lineItemList[i].points.clear();
|
|||
|
|
}
|
|||
|
|
m_lineItemList.clear();
|
|||
|
|
|
|||
|
|
for(int i = 0 ; i < m_pathItemList.size(); i++)
|
|||
|
|
{
|
|||
|
|
this->removeItem(m_pathItemList[i].item);
|
|||
|
|
m_pathItemList[i].points.clear();
|
|||
|
|
}
|
|||
|
|
m_pathItemList.clear();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool MyGraphicsScene::getCurSelectState()
|
|||
|
|
{
|
|||
|
|
bool bl = false;
|
|||
|
|
|
|||
|
|
if(m_draggingPoint)
|
|||
|
|
{
|
|||
|
|
bl = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(m_ellipseItemList.size() <= 0)
|
|||
|
|
{
|
|||
|
|
bl = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return bl;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool MyGraphicsScene::initAPoint()
|
|||
|
|
{
|
|||
|
|
bool bl = false;
|
|||
|
|
|
|||
|
|
if(m_draggingPoint)
|
|||
|
|
{
|
|||
|
|
bl = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(m_draggingPoint == NULL)
|
|||
|
|
{
|
|||
|
|
if(m_ellipseItemList.size() > 0)
|
|||
|
|
{
|
|||
|
|
m_ellipseItemList[0]->setPen(Qt::NoPen);
|
|||
|
|
m_ellipseItemList[0]->setBrush(Qt::red);
|
|||
|
|
m_draggingPoint = m_ellipseItemList[0];
|
|||
|
|
emit siCurrentIndex(1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(m_ellipseItemList.size() <= 0)
|
|||
|
|
{
|
|||
|
|
bl = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return bl;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void MyGraphicsScene::forwardAndBackward(int idx)
|
|||
|
|
{
|
|||
|
|
int index = m_ellipseItemList.indexOf(m_draggingPoint);
|
|||
|
|
index += idx;
|
|||
|
|
if(index < 0 || index >= m_ellipseItemList.size())
|
|||
|
|
{
|
|||
|
|
if(index < 0)
|
|||
|
|
{
|
|||
|
|
index = 0;
|
|||
|
|
}
|
|||
|
|
if(index >= m_ellipseItemList.size())
|
|||
|
|
{
|
|||
|
|
index = m_ellipseItemList.size()-1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
m_draggingPoint->setPen(Qt::NoPen);
|
|||
|
|
m_draggingPoint->setBrush(Qt::blue);
|
|||
|
|
m_draggingPoint = NULL;
|
|||
|
|
|
|||
|
|
// 选中点
|
|||
|
|
m_ellipseItemList[index]->setPen(Qt::NoPen);
|
|||
|
|
m_ellipseItemList[index]->setBrush(Qt::red);
|
|||
|
|
m_draggingPoint = m_ellipseItemList[index];
|
|||
|
|
emit siCurrentIndex(index+1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void MyGraphicsScene::insertPoint(int dir)
|
|||
|
|
{
|
|||
|
|
int index = m_ellipseItemList.indexOf(m_draggingPoint);
|
|||
|
|
index += dir;
|
|||
|
|
if(index < 0 || index >= m_ellipseItemList.size())
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//默认位置中心都是0
|
|||
|
|
QGraphicsEllipseItem *point = this->addEllipse(0-m_radius,
|
|||
|
|
0-m_radius,
|
|||
|
|
2*m_radius,
|
|||
|
|
2*m_radius);
|
|||
|
|
point->setPen(Qt::NoPen);
|
|||
|
|
point->setBrush(Qt::blue);
|
|||
|
|
//point->setFlag(QGraphicsItem::ItemIsSelectable, true);
|
|||
|
|
point->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
|
|||
|
|
|
|||
|
|
QPointF a = m_draggingPoint->pos();
|
|||
|
|
QPointF b = m_ellipseItemList[index]->pos();
|
|||
|
|
|
|||
|
|
// 调整椭圆的位置
|
|||
|
|
QPointF m = QPointF((a.x()+b.x())/2.0,(a.y()+b.y())/2.0);
|
|||
|
|
point->setPos(m.x(), m.y());
|
|||
|
|
|
|||
|
|
QPen pen;
|
|||
|
|
pen.setWidthF(1);
|
|||
|
|
pen.setCosmetic(true); // 设置为眉笔模式,线段在缩放时保证粗细不变
|
|||
|
|
pen.setColor(Qt::blue);
|
|||
|
|
|
|||
|
|
//向前插入点和线
|
|||
|
|
if(dir < 0)
|
|||
|
|
{
|
|||
|
|
m_ellipseItemList.insert(index-dir,point);
|
|||
|
|
//插入线,先把原来的线段删除,再插入两端线段
|
|||
|
|
this->removeItem(m_lineItemList[index].item);
|
|||
|
|
m_lineItemList.removeAt(index);
|
|||
|
|
|
|||
|
|
//先插入后半段
|
|||
|
|
QPointF start = m;
|
|||
|
|
QPointF end = a;
|
|||
|
|
QVector<QPointF> vec;
|
|||
|
|
vec.append(start);
|
|||
|
|
vec.append(end);
|
|||
|
|
QGraphicsPolygonItem *line = this->addPolygon(QPolygonF(vec));
|
|||
|
|
line->setPen(pen);
|
|||
|
|
GLineItem item;
|
|||
|
|
item.item = line;
|
|||
|
|
item.points.append(start);
|
|||
|
|
item.points.append(end);
|
|||
|
|
m_lineItemList.insert(index,item);
|
|||
|
|
|
|||
|
|
//再插入前半段
|
|||
|
|
start = b;
|
|||
|
|
end = m;
|
|||
|
|
QVector<QPointF> vec1;
|
|||
|
|
vec1.append(start);
|
|||
|
|
vec1.append(end);
|
|||
|
|
QGraphicsPolygonItem *line1 = this->addPolygon(QPolygonF(vec1));
|
|||
|
|
line1->setPen(pen);
|
|||
|
|
GLineItem item1;
|
|||
|
|
item1.item = line1;
|
|||
|
|
item1.points.append(start);
|
|||
|
|
item1.points.append(end);
|
|||
|
|
m_lineItemList.insert(index,item1);
|
|||
|
|
emit siCurrentIndex(index-dir+2);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
m_ellipseItemList.insert(index,point);
|
|||
|
|
//插入线,先把原来的线段删除,再插入两端线段
|
|||
|
|
this->removeItem(m_lineItemList[index-dir].item);
|
|||
|
|
m_lineItemList.removeAt(index-dir);
|
|||
|
|
|
|||
|
|
//先插入后半段
|
|||
|
|
QPointF start = m;
|
|||
|
|
QPointF end = b;
|
|||
|
|
QVector<QPointF> vec;
|
|||
|
|
vec.append(start);
|
|||
|
|
vec.append(end);
|
|||
|
|
QGraphicsPolygonItem *line = this->addPolygon(QPolygonF(vec));
|
|||
|
|
line->setPen(pen);
|
|||
|
|
GLineItem item;
|
|||
|
|
item.item = line;
|
|||
|
|
item.points.append(start);
|
|||
|
|
item.points.append(end);
|
|||
|
|
m_lineItemList.insert(index-dir,item);
|
|||
|
|
|
|||
|
|
//再插入前半段
|
|||
|
|
start = a;
|
|||
|
|
end = m;
|
|||
|
|
QVector<QPointF> vec1;
|
|||
|
|
vec1.append(start);
|
|||
|
|
vec1.append(end);
|
|||
|
|
QGraphicsPolygonItem *line1 = this->addPolygon(QPolygonF(vec1));
|
|||
|
|
line1->setPen(pen);
|
|||
|
|
GLineItem item1;
|
|||
|
|
item1.item = line1;
|
|||
|
|
item1.points.append(start);
|
|||
|
|
item1.points.append(end);
|
|||
|
|
m_lineItemList.insert(index-dir,item1);
|
|||
|
|
emit siCurrentIndex(index);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void MyGraphicsScene::removeSelectPoint()
|
|||
|
|
{
|
|||
|
|
int index = m_ellipseItemList.indexOf(m_draggingPoint);
|
|||
|
|
|
|||
|
|
qDebug() << " m_ellipseItemList.indexOf " << index;
|
|||
|
|
if(m_ellipseItemList.size() > 1)
|
|||
|
|
{
|
|||
|
|
//将点相关的两条线段改为一条
|
|||
|
|
if(index == 0)
|
|||
|
|
{
|
|||
|
|
this->removeItem(m_lineItemList[0].item);
|
|||
|
|
m_lineItemList.removeFirst();
|
|||
|
|
}
|
|||
|
|
else if(index == m_ellipseItemList.size()-1)
|
|||
|
|
{
|
|||
|
|
this->removeItem(m_lineItemList[m_lineItemList.size()-1].item);
|
|||
|
|
m_lineItemList.removeLast();
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
this->removeItem(m_lineItemList[index-1].item);
|
|||
|
|
this->removeItem(m_lineItemList[index].item);
|
|||
|
|
m_lineItemList.removeAt(index-1);
|
|||
|
|
m_lineItemList.removeAt(index-1);
|
|||
|
|
|
|||
|
|
QPointF start = m_ellipseItemList[index-1]->pos();
|
|||
|
|
QPointF end = m_ellipseItemList[index+1]->pos();
|
|||
|
|
|
|||
|
|
QPen pen;
|
|||
|
|
pen.setWidthF(1);
|
|||
|
|
pen.setCosmetic(true); // 设置为眉笔模式,线段在缩放时保证粗细不变
|
|||
|
|
pen.setColor(Qt::blue);
|
|||
|
|
QVector<QPointF> vec;
|
|||
|
|
vec.append(start);
|
|||
|
|
vec.append(end);
|
|||
|
|
QGraphicsPolygonItem *line = this->addPolygon(QPolygonF(vec));
|
|||
|
|
line->setPen(pen);
|
|||
|
|
GLineItem item;
|
|||
|
|
item.item = line;
|
|||
|
|
item.points.append(start);
|
|||
|
|
item.points.append(end);
|
|||
|
|
m_lineItemList.insert(index-1,item);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
this->removeItem(m_draggingPoint);
|
|||
|
|
m_ellipseItemList.removeAt(index);
|
|||
|
|
setLastPointSelected();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void MyGraphicsScene::setShapeType(int type)
|
|||
|
|
{
|
|||
|
|
if(type == TYPE_LINE && m_shapeType == TYPE_ARC)
|
|||
|
|
{
|
|||
|
|
//上一次画直线或圆时,只画了一个点,要删除该点
|
|||
|
|
if(m_ArcCount == 2)
|
|||
|
|
{
|
|||
|
|
QGraphicsEllipseItem *item = m_ellipseItemList.last();
|
|||
|
|
this->removeItem(item);
|
|||
|
|
m_ellipseItemList.removeOne(item);
|
|||
|
|
m_ArcCount = 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
//切换到了圆
|
|||
|
|
else if(type == TYPE_ARC && m_shapeType == TYPE_LINE)
|
|||
|
|
{
|
|||
|
|
m_ArcCount = 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(type == TYPE_ARC && m_ellipseItemList.size() <= 0)
|
|||
|
|
{
|
|||
|
|
m_ArcCount = 0;
|
|||
|
|
}
|
|||
|
|
m_shapeType = type;
|
|||
|
|
setLastPointSelected();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void MyGraphicsScene::setAdsorption(bool adsorption)
|
|||
|
|
{
|
|||
|
|
m_isAdsorption = adsorption;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void MyGraphicsScene::setLastPointSelected()
|
|||
|
|
{
|
|||
|
|
if(m_ellipseItemList.size() == 0)
|
|||
|
|
{
|
|||
|
|
m_draggingPoint = NULL;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
if(m_draggingPoint != NULL)
|
|||
|
|
{
|
|||
|
|
m_draggingPoint->setPen(Qt::NoPen);
|
|||
|
|
m_draggingPoint->setBrush(Qt::blue);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
QGraphicsEllipseItem *point = m_ellipseItemList.last();
|
|||
|
|
// 选中点
|
|||
|
|
point->setPen(Qt::NoPen);
|
|||
|
|
point->setBrush(Qt::red);
|
|||
|
|
m_draggingPoint = point;
|
|||
|
|
emit siCurrentIndex(m_ellipseItemList.size());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void MyGraphicsScene::setMaxSegmentLength(int value)
|
|||
|
|
{
|
|||
|
|
m_maxSegmentLength = value;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int MyGraphicsScene::getMaxSegmentLength()
|
|||
|
|
{
|
|||
|
|
return m_maxSegmentLength;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int MyGraphicsScene::getArcItem(QList<QPointF> points, QGraphicsPathItem *item, double threex[], double threey[])
|
|||
|
|
{
|
|||
|
|
QPen pen;
|
|||
|
|
pen.setWidthF(1);
|
|||
|
|
pen.setCosmetic(true); // 设置为眉笔模式,线段在缩放时保证粗细不变
|
|||
|
|
pen.setColor(Qt::blue);
|
|||
|
|
|
|||
|
|
int val = isThreePointOnALine(threex, threey);
|
|||
|
|
if(val == 1 || val == 2)//三个点或两个点重合
|
|||
|
|
{
|
|||
|
|
QPainterPath path;
|
|||
|
|
path.moveTo(points[0]);
|
|||
|
|
|
|||
|
|
//线段
|
|||
|
|
for(int i = 1; i < points.size(); i++)
|
|||
|
|
{
|
|||
|
|
path.lineTo(points[i].x(),points[i].y());
|
|||
|
|
item->setPath(path);
|
|||
|
|
item->setPen(pen); // 设置线条颜色和宽度
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
double xc = 0;
|
|||
|
|
double yc = 0;
|
|||
|
|
double r = 0;
|
|||
|
|
getArcCenter(threex, threey, &xc, &yc, &r); //计算圆心和半径
|
|||
|
|
|
|||
|
|
QPointF center(xc,yc);
|
|||
|
|
// 创建一个 QPainterPath 并添加弧线
|
|||
|
|
// 2. 计算三个点的角度
|
|||
|
|
qreal startAngle = QLineF(center, points[0]).angle();
|
|||
|
|
qreal endAngle = QLineF(center, points[2]).angle();
|
|||
|
|
|
|||
|
|
// 3. 计算中间点角度,用于判断走哪一边
|
|||
|
|
qreal midAngle = QLineF(center, points[1]).angle();
|
|||
|
|
|
|||
|
|
// 辅助函数:将角度差归一化到 [-180, 180]
|
|||
|
|
auto normalizeDiff = [](qreal diff)
|
|||
|
|
{
|
|||
|
|
while (diff < -180) diff += 360;
|
|||
|
|
while (diff > 180) diff -= 360;
|
|||
|
|
return diff;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 计算从 start 到 end 的两种可能跨度
|
|||
|
|
qreal diff = normalizeDiff(endAngle - startAngle); // 最短角度差 [-180, 180]
|
|||
|
|
|
|||
|
|
qreal spanCCW, spanCW;
|
|||
|
|
if (diff >= 0)
|
|||
|
|
{
|
|||
|
|
spanCCW = diff; // 逆时针短弧
|
|||
|
|
spanCW = diff - 360; // 顺时针长弧
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
spanCCW = diff + 360; // 逆时针长弧
|
|||
|
|
spanCW = diff; // 顺时针短弧
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 判断中间点在哪段弧上
|
|||
|
|
auto isAngleInArc = [&](qreal angle, qreal span) -> bool
|
|||
|
|
{
|
|||
|
|
qreal rel = normalizeDiff(angle - startAngle); // 相对于起点的角度差
|
|||
|
|
if (span >= 0)
|
|||
|
|
{
|
|||
|
|
return (rel >= -1e-3 && rel <= span + 1e-3);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
return (rel <= 1e-3 && rel >= span - 1e-3);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
qreal finalSpan;
|
|||
|
|
if (isAngleInArc(midAngle, spanCCW))
|
|||
|
|
{
|
|||
|
|
finalSpan = spanCCW;
|
|||
|
|
}
|
|||
|
|
else if (isAngleInArc(midAngle, spanCW))
|
|||
|
|
{
|
|||
|
|
finalSpan = spanCW;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
// fallback: 选绝对值较小的(劣弧)
|
|||
|
|
finalSpan = (std::abs(spanCCW) <= std::abs(spanCW)) ? spanCCW : spanCW;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 创建路径
|
|||
|
|
QPainterPath path;
|
|||
|
|
path.moveTo(points[0]);
|
|||
|
|
path.arcTo(xc - r, yc - r, 2 * r, 2 * r, startAngle, finalSpan);
|
|||
|
|
|
|||
|
|
item->setPath(path);
|
|||
|
|
item->setPen(pen);
|
|||
|
|
}
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int MyGraphicsScene::getGLineItem(QGraphicsEllipseItem* p,QPointF p1)
|
|||
|
|
{
|
|||
|
|
int rel = 0;
|
|||
|
|
if(p)
|
|||
|
|
{
|
|||
|
|
QPointF position = p->pos();
|
|||
|
|
|
|||
|
|
for(int i = 0; i < m_lineItemList.size(); i++)
|
|||
|
|
{
|
|||
|
|
for(int j = 0; j < m_lineItemList[i].points.size(); j++)
|
|||
|
|
{
|
|||
|
|
if(position == m_lineItemList[i].points[j])
|
|||
|
|
{
|
|||
|
|
m_lineItemList[i].points[j] = p1;
|
|||
|
|
rel = 1;
|
|||
|
|
|
|||
|
|
QVector<QPointF> pointsVec;
|
|||
|
|
pointsVec.reserve(m_lineItemList[i].points.size());
|
|||
|
|
for (const QPointF &p : m_lineItemList[i].points)
|
|||
|
|
{
|
|||
|
|
pointsVec.append(p);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
QGraphicsPolygonItem *pLine = m_lineItemList[i].item;
|
|||
|
|
pLine->setPolygon(QPolygonF(pointsVec));
|
|||
|
|
return rel;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return rel;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int MyGraphicsScene::getGPathItem(QGraphicsEllipseItem* p,QPointF p1)
|
|||
|
|
{
|
|||
|
|
int rel = 0;
|
|||
|
|
if(p)
|
|||
|
|
{
|
|||
|
|
QPointF position = p->pos();
|
|||
|
|
|
|||
|
|
for(int i = 0; i < m_pathItemList.size(); i++)
|
|||
|
|
{
|
|||
|
|
for(int j = 0; j < m_pathItemList[i].points.size(); j++)
|
|||
|
|
{
|
|||
|
|
if(position == m_pathItemList[i].points[j])
|
|||
|
|
{
|
|||
|
|
if(m_pathItemList[i].points.size() == 3)//圆弧
|
|||
|
|
{
|
|||
|
|
rel = 1;
|
|||
|
|
m_pathItemList[i].points[j] = p1;
|
|||
|
|
QGraphicsPathItem *pPath = m_pathItemList[i].item;
|
|||
|
|
QList<QPointF> points = m_pathItemList[i].points;
|
|||
|
|
double threex[3], threey[3];
|
|||
|
|
threex[0] = points[0].x();
|
|||
|
|
threex[1] = points[1].x();
|
|||
|
|
threex[2] = points[2].x();
|
|||
|
|
threey[0] = points[0].y();
|
|||
|
|
threey[1] = points[1].y();
|
|||
|
|
threey[2] = points[2].y();
|
|||
|
|
getArcItem(points,pPath,threex,threey);
|
|||
|
|
return rel;
|
|||
|
|
}
|
|||
|
|
else if(m_pathItemList[i].points.size() == 4)//贝塞尔4个点
|
|||
|
|
{
|
|||
|
|
rel = 2;
|
|||
|
|
m_pathItemList[i].points[j] = p1;
|
|||
|
|
QGraphicsPathItem *pPath = m_pathItemList[i].item;
|
|||
|
|
|
|||
|
|
// 创建 QPainterPath 并添加贝塞尔曲线
|
|||
|
|
QPainterPath path;
|
|||
|
|
path.moveTo(m_pathItemList[i].points[0]); // 移动到起始点
|
|||
|
|
path.cubicTo(m_pathItemList[i].points[1], m_pathItemList[i].points[2], m_pathItemList[i].points[3]); // 添加贝塞尔曲线
|
|||
|
|
// 创建 QGraphicsPathItem 并设置路径
|
|||
|
|
pPath->setPath(path);
|
|||
|
|
QPen pen;
|
|||
|
|
pen.setWidthF(1);
|
|||
|
|
pen.setCosmetic(true); // 设置为眉笔模式,线段在缩放时保证粗细不变
|
|||
|
|
pen.setColor(Qt::blue);
|
|||
|
|
pPath->setPen(pen); // 设置线条颜色和宽度
|
|||
|
|
return rel;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return rel;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void MyGraphicsScene::setXYMove(double valX,double valY)
|
|||
|
|
{
|
|||
|
|
if(m_draggingPoint == NULL)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
QPointF newPos(m_draggingPoint->x()+valX,m_draggingPoint->y()+valY);
|
|||
|
|
int relLine = getGLineItem(m_draggingPoint,newPos);
|
|||
|
|
//如果直线和圆弧共点(relLine和relArc都会 > 0),则先处理直线的点,所以这个if的最后会return
|
|||
|
|
if(relLine > 0)
|
|||
|
|
{
|
|||
|
|
update();
|
|||
|
|
m_draggingPoint->setPos(newPos);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int relArc = getGPathItem(m_draggingPoint,newPos);
|
|||
|
|
if(relArc > 0)
|
|||
|
|
{
|
|||
|
|
update();
|
|||
|
|
m_draggingPoint->setPos(newPos);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//撤销最后一个图元
|
|||
|
|
void MyGraphicsScene::revokeLastItem()
|
|||
|
|
{
|
|||
|
|
if(m_ellipseItemList.size() <= 0)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int num = 0;//已删除的数量
|
|||
|
|
int pointsNum = 0;//总共的点的个数
|
|||
|
|
|
|||
|
|
int order = m_lineItemList.size() + m_pathItemList.size();
|
|||
|
|
for(int i = 0; i < m_lineItemList.size(); i++)
|
|||
|
|
{
|
|||
|
|
if(m_lineItemList[i].order == order)
|
|||
|
|
{
|
|||
|
|
//去掉两个点
|
|||
|
|
if(m_ellipseItemList.size() > 0)
|
|||
|
|
{
|
|||
|
|
this->removeItem(m_ellipseItemList[m_ellipseItemList.size()-1]);
|
|||
|
|
m_ellipseItemList.removeLast();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(m_ellipseItemList.size() > 0)
|
|||
|
|
{
|
|||
|
|
this->removeItem(m_ellipseItemList[m_ellipseItemList.size()-1]);
|
|||
|
|
m_ellipseItemList.removeLast();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(m_lineItemList.size() > i)
|
|||
|
|
{
|
|||
|
|
this->removeItem(m_lineItemList[i].item);
|
|||
|
|
m_lineItemList.removeAt(i);
|
|||
|
|
num++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
for(int i = 0; i < m_pathItemList.size(); i++)
|
|||
|
|
{
|
|||
|
|
if(m_pathItemList[i].order == order)
|
|||
|
|
{
|
|||
|
|
//去掉三个点
|
|||
|
|
if(m_ellipseItemList.size() > 0)
|
|||
|
|
{
|
|||
|
|
this->removeItem(m_ellipseItemList[m_ellipseItemList.size()-1]);
|
|||
|
|
m_ellipseItemList.removeLast();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(m_ellipseItemList.size() > 0)
|
|||
|
|
{
|
|||
|
|
this->removeItem(m_ellipseItemList[m_ellipseItemList.size()-1]);
|
|||
|
|
m_ellipseItemList.removeLast();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(m_ellipseItemList.size() > 0)
|
|||
|
|
{
|
|||
|
|
this->removeItem(m_ellipseItemList[m_ellipseItemList.size()-1]);
|
|||
|
|
m_ellipseItemList.removeLast();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(m_pathItemList.size() > i)
|
|||
|
|
{
|
|||
|
|
this->removeItem(m_pathItemList[i].item);
|
|||
|
|
m_pathItemList.removeAt(i);
|
|||
|
|
num++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
for(int i = 0; i < m_lineItemList.size(); i++)
|
|||
|
|
{
|
|||
|
|
pointsNum += m_lineItemList[i].points.size();
|
|||
|
|
}
|
|||
|
|
for(int i = 0; i < m_pathItemList.size(); i++)
|
|||
|
|
{
|
|||
|
|
pointsNum += m_pathItemList[i].points.size();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//如果图元点总和与m_ellipseItemList的数量不一致,要删除m_ellipseItemList多余点,因为很可能画圆弧画了一半
|
|||
|
|
if(pointsNum != m_ellipseItemList.size())
|
|||
|
|
{
|
|||
|
|
while(1)
|
|||
|
|
{
|
|||
|
|
if(m_ellipseItemList.size() > 0)
|
|||
|
|
{
|
|||
|
|
this->removeItem(m_ellipseItemList[m_ellipseItemList.size()-1]);
|
|||
|
|
m_ellipseItemList.removeLast();
|
|||
|
|
}
|
|||
|
|
if(pointsNum == m_ellipseItemList.size())
|
|||
|
|
{
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
m_addOrder -= num;
|
|||
|
|
m_shapeType = TYPE_DRAG;
|
|||
|
|
|
|||
|
|
setLastPointSelected();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
QList<QGraphicsEllipseItem *> MyGraphicsScene::getPointList()
|
|||
|
|
{
|
|||
|
|
return m_ellipseItemList;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
QList<GLineItem> MyGraphicsScene::getLineItemList()
|
|||
|
|
{
|
|||
|
|
return m_lineItemList;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
QList<GPathItem> MyGraphicsScene::getPathItemList()
|
|||
|
|
{
|
|||
|
|
return m_pathItemList;
|
|||
|
|
}
|