DiagramDesigner/diagramCavas/source/graphicsItem/electricConnectLineItem.cpp

987 lines
28 KiB
C++
Raw Normal View History

2024-12-07 17:24:36 +08:00
#include "graphicsItem/electricConnectLineItem.h"
#include <QGraphicsScene>
#include <QPainter>
#include <QStyleOptionGraphicsItem>
2024-12-07 17:24:36 +08:00
ElectricConnectLineItem::ElectricConnectLineItem(QGraphicsItem *parent)
: GraphicsProjectModelItem(parent)
2025-11-14 19:31:09 +08:00
{
initial();
}
ElectricConnectLineItem::ElectricConnectLineItem(const ElectricConnectLineItem& obj)
: GraphicsProjectModelItem(obj)
{
initial();
m_lstPoints = obj.m_lstPoints;
}
ElectricConnectLineItem::~ElectricConnectLineItem()
{
}
ElectricConnectLineItem* ElectricConnectLineItem::clone() const
{
return new ElectricConnectLineItem(*this);
}
void ElectricConnectLineItem::initial()
2024-12-07 17:24:36 +08:00
{
m_boundingRect = QRectF();
2024-12-07 17:24:36 +08:00
m_pen = QPen(Qt::black);
m_brush = QBrush(Qt::NoBrush);
setHandleVisible(false);
setFunctionHandleIfShow(false);
setFunctionHandleEnaable(false);
m_lstPoints.push_back(QPointF()); //起点
m_lstPoints.push_back(QPointF()); //终点
_curLine = QPoint();
2024-12-07 17:24:36 +08:00
}
void ElectricConnectLineItem::setStartPoint(const QPointF& p)
{
2026-03-02 20:15:22 +08:00
if (m_lstPoints.size() >= 2) {
// 保存终点
QPointF endPoint = m_lstPoints.last();
// 清空并设置新起点
m_lstPoints.clear();
m_lstPoints.append(p);
m_lstPoints.append(endPoint);
// 重新计算路径
calculatePath();
} else if (m_lstPoints.size() == 1) {
m_lstPoints[0] = p;
2026-03-02 20:15:22 +08:00
} else {
m_lstPoints.append(p);
}
2026-03-02 20:15:22 +08:00
update();
}
void ElectricConnectLineItem::setEndPoint(const QPointF& p)
{
2026-03-02 20:15:22 +08:00
if (m_lstPoints.size() >= 2) {
// 保存起点
QPointF startPoint = m_lstPoints.first();
// 清空并设置新终点
m_lstPoints.clear();
m_lstPoints.append(startPoint);
m_lstPoints.append(p);
// 重新计算路径
calculatePath();
} else if (m_lstPoints.size() == 1) {
m_lstPoints.append(p);
} else {
m_lstPoints.append(p);
}
update();
}
// 开始拖拽
void ElectricConnectLineItem::startDrag(const QPointF& scenePos)
{
qDebug() << "\n=== START DRAG ===";
// 重置状态
m_dragData.isActive = false;
m_dragData.segmentIndex = -1;
QPointF itemPos = mapFromScene(scenePos);
qDebug() << "Item pos:" << itemPos;
// 从路径提取点
QList<QPointF> points = extractPointsFromPath();
qDebug() << "Extracted" << points.size() << "points from path";
// 查找线段
int segmentIndex = findSegmentAt(points, itemPos);
if (segmentIndex >= 0) {
m_dragData.isActive = true;
m_dragData.segmentIndex = segmentIndex;
m_dragData.startScenePos = scenePos;
m_dragData.originalPath = m_points; // 保存原始路径
// 判断线段方向
if (segmentIndex < points.size() - 1) {
QPointF p1 = points[segmentIndex];
QPointF p2 = points[segmentIndex + 1];
m_dragData.isVertical = qFuzzyCompare(p1.x(), p2.x());
}
2026-03-02 20:15:22 +08:00
qDebug() << "✓ Dragging segment" << segmentIndex;
}
}
2026-03-02 20:15:22 +08:00
// 更新拖拽
void ElectricConnectLineItem::updateDrag(const QPointF& scenePos)
{
if (!m_dragData.isActive) {
return;
}
int idx = m_dragData.segmentIndex;
// 从原始路径提取点
QList<QPointF> points = extractPointsFromPath(m_dragData.originalPath);
// 安全检查
if (idx < 0 || idx >= points.size() - 1) {
qWarning() << "Invalid segment index:" << idx;
m_dragData.isActive = false;
return;
}
// 计算移动距离
QPointF startItemPos = mapFromScene(m_dragData.startScenePos);
QPointF currentItemPos = mapFromScene(scenePos);
QPointF delta = currentItemPos - startItemPos;
// 获取当前线段
QPointF& p1 = points[idx];
QPointF& p2 = points[idx + 1];
// 限制移动方向
if (m_dragData.isVertical) {
// 垂直线段:只能水平移动
delta.setY(0);
// 移动线段
p1.rx() += delta.x();
p2.rx() += delta.x();
} else {
// 水平线段:只能垂直移动
delta.setX(0);
p1.ry() += delta.y();
p2.ry() += delta.y();
}
// 修复连接
fixConnections(points, idx, m_dragData.isVertical);
// 更新拖拽起点
m_dragData.startScenePos = scenePos;
// 应用修改后的点
applyPointsToPath(points);
// 重新计算路径(调用原有的 calculatePath
calculatePath();
update();
}
// 结束拖拽
void ElectricConnectLineItem::endDrag()
{
qDebug() << "\n" << QString(50, '=');
qDebug() << "END DRAG";
qDebug() << QString(50, '=');
if (!m_dragData.isActive) {
qDebug() << "No active drag to end";
return;
}
qDebug() << "Drag was active on segment:" << m_dragData.segmentIndex;
// 验证和修复路径
validateAndFixPath();
// 重置状态
m_dragData.isActive = false;
m_dragData.segmentIndex = -1;
m_dragData.isVertical = false;
m_dragData.startScenePos = QPointF();
m_dragData.originalPath = QPainterPath();
// 恢复光标
setCursor(Qt::ArrowCursor);
// 确保场景更新
update();
qDebug() << "✓ Drag ended successfully";
qDebug() << QString(50, '=') << "\n";
}
void ElectricConnectLineItem::setLastPoint(const QPointF& point)
{
m_lastPoint = point;
}
void ElectricConnectLineItem::setPath(const QPainterPath& path)
{
qDebug() << "\n=== setPath ===";
if (m_points == path) {
return;
}
prepareGeometryChange();
m_points = path; // 使用已有的 m_points
updateBoundingRect();
update();
}
QPainterPath ElectricConnectLineItem::shape() const
2024-12-07 17:24:36 +08:00
{
2026-03-02 20:15:22 +08:00
// 使用路径的轮廓
if (m_points.isEmpty()) {
return QPainterPath();
}
QPainterPathStroker stroker;
stroker.setWidth(8.0); // 选择区域宽度
QPainterPath shape = stroker.createStroke(m_points);
return shape;
2024-12-07 17:24:36 +08:00
}
QRectF ElectricConnectLineItem::boundingRect() const
{
2026-03-02 20:15:22 +08:00
QRectF rect = shape().boundingRect();
// 如果shape为空使用路径边界
if (rect.isNull() && !m_points.isEmpty()) {
rect = m_points.boundingRect().adjusted(-5, -5, 5, 5);
}
return rect;
}
2024-12-07 17:24:36 +08:00
void ElectricConnectLineItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
if (option->state & QStyle::State_Selected)
{
painter->setPen(Qt::red);
}
else
{
2025-12-03 18:27:49 +08:00
if(_curMonitorStateEnable){ //当前状态被设置
painter->setPen(QPen(_curMonitorStateColor));
}
else
painter->setPen(m_pen);
}
2024-12-07 17:24:36 +08:00
painter->setBrush(m_brush);
painter->drawPath(m_points);
}
void ElectricConnectLineItem::calculatePath()
{
if (m_lstPoints.size() < 2) return;
QPointF start = m_lstPoints.first();
QPointF end = m_lstPoints.last();
qDebug() << "\n=== calculatePath ===";
qDebug() << "Start:" << start << "End:" << end;
// 创建新路径
m_points = QPainterPath();
m_points.moveTo(start);
qDebug() << "Initialized path, current position:" << m_points.currentPosition();
// 获取元件
2026-03-02 20:15:22 +08:00
QList<QRectF> components = getAllComponentRects();
qDebug() << "Found" << components.size() << "components";
// 检查起点终点距离
qDebug() << "Distance:" << QLineF(start, end).length();
// 如果距离很近,直接连接
if (QLineF(start, end).length() < 10) {
qDebug() << "Points are very close, direct connection";
m_points.lineTo(end);
} else {
// 生成路径
generateAvoidancePath(start, end, components);
}
// 验证路径
qDebug() << "After generation - Path element count:" << m_points.elementCount();
qDebug() << "After generation - Current position:" << m_points.currentPosition();
if (m_points.elementCount() <= 1) {
qWarning() << "Path has only" << m_points.elementCount() << "elements! Adding direct line";
m_points.lineTo(end);
}
// 确保路径结束于终点
if (m_points.currentPosition() != end) {
qWarning() << "Path does not end at destination! Adding final segment";
qDebug() << "Expected end:" << end << "Actual end:" << m_points.currentPosition();
m_points.lineTo(end);
}
update();
m_boundingRect = m_points.boundingRect();
prepareGeometryChange();
qDebug() << "Final path bounds:" << m_boundingRect;
qDebug() << "=== calculatePath end ===\n";
}
// 使用形状进行避障
void ElectricConnectLineItem::generateAvoidancePath(const QPointF& start, const QPointF& end,
const QList<QRectF>& components)
{
qDebug() << "=== generateAvoidancePath (rectilinear) ===";
m_points = QPainterPath();
m_points.moveTo(start);
// 生成候选路径列表,按长度排序
QMultiMap<double, QList<QPointF>> candidatePaths;
// 1. 收集所有可能的直角路径
collectRectilinearPaths(start, end, components, candidatePaths);
// 2. 选择最短的安全路径
for (auto it = candidatePaths.begin(); it != candidatePaths.end(); ++it) {
const QList<QPointF>& path = it.value();
if (isPathSafe(path, components)) {
qDebug() << " Selected path with length" << it.key() << ":" << path;
// 绘制路径
for (int i = 1; i < path.size(); i++) {
m_points.lineTo(path[i]);
}
return;
}
}
2024-12-07 17:24:36 +08:00
// 3. 所有路径都失败,使用强制绕行
qDebug() << " All rectilinear paths failed, using forced bypass";
generateForcedRectilinearBypass(start, end, components);
}
// 计算路径长度
double ElectricConnectLineItem::calculatePathLength(const QList<QPointF>& path)
{
double length = 0;
for (int i = 0; i < path.size() - 1; i++) {
length += QLineF(path[i], path[i+1]).length();
}
return length;
}
// 单一线段与矩形相交检测
2026-03-02 20:15:22 +08:00
bool ElectricConnectLineItem::lineIntersectsRect(const QLineF& line, const QRectF& rect) const
{
// 检查端点是否在矩形内
if (rect.contains(line.p1()) || rect.contains(line.p2())) {
return true;
}
// 检查是否与矩形的边相交
QLineF edges[4] = {
QLineF(rect.topLeft(), rect.topRight()),
QLineF(rect.topRight(), rect.bottomRight()),
QLineF(rect.bottomRight(), rect.bottomLeft()),
QLineF(rect.bottomLeft(), rect.topLeft())
};
QPointF intersection;
for (int i = 0; i < 4; i++) {
if (line.intersects(edges[i], &intersection) == QLineF::BoundedIntersection) {
return true;
}
}
return false;
}
// 辅助方法实现
bool ElectricConnectLineItem::isSegmentSafe(const QPointF& p1, const QPointF& p2,
const QList<QRectF>& components)
{
QLineF segment(p1, p2);
for (const QRectF& component : components) {
if (segmentPenetratesComponent(segment, component)) {
return false;
}
}
return true;
}
bool ElectricConnectLineItem::isPathSafe(const QList<QPointF>& path,
const QList<QRectF>& components)
{
for (int i = 0; i < path.size() - 1; i++) {
if (!isSegmentSafe(path[i], path[i+1], components)) {
return false;
}
}
return true;
}
// 检查线段是否穿透元件
bool ElectricConnectLineItem::segmentPenetratesComponent(const QLineF& segment,
const QRectF& component)
{
// 检查线段端点是否在元件内
bool p1Inside = component.contains(segment.p1());
bool p2Inside = component.contains(segment.p2());
if (p1Inside && p2Inside) {
// 线段完全在元件内
return true;
}
// 获取与元件的交点
int intersectionCount = 0;
QLineF edges[4] = {
QLineF(component.topLeft(), component.topRight()),
QLineF(component.topRight(), component.bottomRight()),
QLineF(component.bottomRight(), component.bottomLeft()),
QLineF(component.bottomLeft(), component.topLeft())
};
QPointF intersection;
for (int i = 0; i < 4; i++) {
if (segment.intersects(edges[i], &intersection) == QLineF::BoundedIntersection) {
intersectionCount++;
}
}
// 如果线段与元件有2个或更多交点说明穿透了元件
return intersectionCount >= 2;
}
// 获取所有元件的总边界
QRectF ElectricConnectLineItem::getTotalComponentsBounds(const QList<QRectF>& components)
{
if (components.isEmpty()) {
return QRectF();
}
QRectF total = components.first();
for (int i = 1; i < components.size(); i++) {
total = total.united(components[i]);
}
return total;
}
// 收集所有可能的直角路径
void ElectricConnectLineItem::collectRectilinearPaths(const QPointF& start, const QPointF& end,
const QList<QRectF>& components,
QMultiMap<double, QList<QPointF>>& paths)
{
// 2段路径
QPointF turn1(start.x(), end.y()); // 水平-垂直
QPointF turn2(end.x(), start.y()); // 垂直-水平
addPathIfRectilinear({start, turn1, end}, paths);
addPathIfRectilinear({start, turn2, end}, paths);
// 3段路径
double midX = (start.x() + end.x()) / 2;
double midY = (start.y() + end.y()) / 2;
// 水平-垂直-水平
addPathIfRectilinear({start,
QPointF(start.x(), midY),
QPointF(end.x(), midY),
end}, paths);
// 垂直-水平-垂直
addPathIfRectilinear({start,
QPointF(midX, start.y()),
QPointF(midX, end.y()),
end}, paths);
// 4段路径绕行
collectBypassPaths(start, end, components, paths);
}
// 添加路径(如果是直角)
void ElectricConnectLineItem::addPathIfRectilinear(const QList<QPointF>& path,
QMultiMap<double, QList<QPointF>>& paths)
{
// 检查是否所有线段都是水平或垂直
for (int i = 0; i < path.size() - 1; i++) {
if (path[i].x() != path[i+1].x() && path[i].y() != path[i+1].y()) {
return; // 不是直角
}
}
double length = calculatePathLength(path);
paths.insert(length, path);
}
// 收集绕行路径
void ElectricConnectLineItem::collectBypassPaths(const QPointF& start, const QPointF& end,
const QList<QRectF>& components,
QMultiMap<double, QList<QPointF>>& paths)
{
if (components.isEmpty()) return;
// 获取所有元件的总边界
QRectF totalBounds = getTotalComponentsBounds(components);
if (!totalBounds.isValid()) return;
const double clearance = 20.0;
QRectF expanded = totalBounds.adjusted(-clearance, -clearance, clearance, clearance);
// 从上方绕行
addPathIfRectilinear({start,
QPointF(start.x(), expanded.top()),
QPointF(end.x(), expanded.top()),
end}, paths);
// 从下方绕行
addPathIfRectilinear({start,
QPointF(start.x(), expanded.bottom()),
QPointF(end.x(), expanded.bottom()),
end}, paths);
// 从左方绕行
addPathIfRectilinear({start,
QPointF(expanded.left(), start.y()),
QPointF(expanded.left(), end.y()),
end}, paths);
// 从右方绕行
addPathIfRectilinear({start,
QPointF(expanded.right(), start.y()),
QPointF(expanded.right(), end.y()),
end}, paths);
2024-12-07 17:24:36 +08:00
}
// 强制直角绕行
void ElectricConnectLineItem::generateForcedRectilinearBypass(const QPointF& start, const QPointF& end,
const QList<QRectF>& components)
{
qDebug() << " In generateForcedRectilinearBypass";
// 找到阻挡的元件
QRectF blocking = findFirstBlockingComponent(start, end, components);
if (blocking.isValid()) {
qDebug() << " Blocking component:" << blocking;
// 从上方或下方绕过
const double clearance = 15.0;
double bypassY = (start.y() < blocking.center().y()) ?
blocking.top() - clearance : blocking.bottom() + clearance;
QList<QPointF> path = {start,
QPointF(start.x(), bypassY),
QPointF(end.x(), bypassY),
end};
qDebug() << " Forced bypass path:" << path;
for (int i = 1; i < path.size(); i++) {
m_points.lineTo(path[i]);
}
} else {
// 没有阻挡,使用简单的直角路径
qDebug() << " No blocking component, using simple orthogonal path";
QPointF turnPoint = (qAbs(start.x() - end.x()) < qAbs(start.y() - end.y())) ?
QPointF(end.x(), start.y()) : QPointF(start.x(), end.y());
m_points.lineTo(turnPoint);
m_points.lineTo(end);
}
}
// 找到第一个阻挡的元件
QRectF ElectricConnectLineItem::findFirstBlockingComponent(const QPointF& start, const QPointF& end,
const QList<QRectF>& components)
{
QLineF line(start, end);
for (const QRectF& rect : components) {
if (lineIntersectsRect(line, rect)) {
return rect;
}
}
return QRectF();
}
2026-03-02 20:15:22 +08:00
double ElectricConnectLineItem::distancePointToLine(const QLineF& line, const QPointF& point) const
{
// 向量法计算点到线段的最短距离
if (line.isNull()) {
return QLineF(point, line.p1()).length();
}
QPointF v = line.p2() - line.p1(); // 线段向量
QPointF w = point - line.p1(); // 点到线段起点的向量
// 计算点积
double c1 = w.x() * v.x() + w.y() * v.y(); // w·v
if (c1 <= 0.0) {
// 点在线段起点后方
return QLineF(point, line.p1()).length();
}
double c2 = v.x() * v.x() + v.y() * v.y(); // v·v
if (c2 <= c1) {
// 点在线段终点前方
return QLineF(point, line.p2()).length();
}
// 计算投影点
double b = c1 / c2;
QPointF projection = line.p1() + b * v;
return QLineF(point, projection).length();
}
void ElectricConnectLineItem::ensureEnoughPointsForDrag()
{
qDebug() << "\n=== ensureEnoughPointsForDrag ===";
qDebug() << "Current points:" << m_lstPoints.size();
if (m_lstPoints.size() < 2) {
qWarning() << "Not enough points!";
return;
}
// 如果是只有2个点的直线需要添加转折点
if (m_lstPoints.size() == 2) {
QPointF start = m_lstPoints[0];
QPointF end = m_lstPoints[1];
// 如果是斜线,添加转折点
if (start.x() != end.x() && start.y() != end.y()) {
QPointF turnPoint;
// 选择转折方式
if (qAbs(end.x() - start.x()) < qAbs(end.y() - start.y())) {
// 接近垂直,先水平
turnPoint = QPointF(end.x(), start.y());
} else {
// 接近水平,先垂直
turnPoint = QPointF(start.x(), end.y());
}
m_lstPoints.insert(1, turnPoint);
qDebug() << "Added turn point:" << turnPoint;
qDebug() << "Now have" << m_lstPoints.size() << "points";
// 重新计算路径
calculatePath();
}
}
}
void ElectricConnectLineItem::debugPathState(const QString& context) const
{
qDebug() << "\n=== Debug Path State:" << context << "===";
qDebug() << "m_lstPoints count:" << m_lstPoints.size();
qDebug() << "m_dragState.isDragging:" << m_dragData.isActive;
qDebug() << "m_dragState.segmentIndex:" << m_dragData.segmentIndex;
qDebug() << "m_dragState.isVertical:" << m_dragData.isVertical;
for (int i = 0; i < m_lstPoints.size(); i++) {
qDebug() << QString(" Point[%1]: (%2, %3)")
.arg(i)
.arg(m_lstPoints[i].x(), 0, 'f', 1)
.arg(m_lstPoints[i].y(), 0, 'f', 1);
}
// 检查每个线段
for (int i = 0; i < m_lstPoints.size() - 1; i++) {
QPointF p1 = m_lstPoints[i];
QPointF p2 = m_lstPoints[i + 1];
bool isVertical = qFuzzyCompare(p1.x(), p2.x());
bool isHorizontal = qFuzzyCompare(p1.y(), p2.y());
QString type = "DIAGONAL";
if (isVertical) type = "VERTICAL";
else if (isHorizontal) type = "HORIZONTAL";
qDebug() << QString(" Segment[%1]: %2, length=%3")
.arg(i)
.arg(type)
.arg(QLineF(p1, p2).length(), 0, 'f', 1);
}
}
QVector<QLineF> ElectricConnectLineItem::extractSegmentsFromPainterPath() const
{
QVector<QLineF> segments;
if (m_points.isEmpty()) {
return segments;
}
// 遍历QPainterPath的所有元素
QPointF lastPoint;
bool hasLastPoint = false;
for (int i = 0; i < m_points.elementCount(); i++) {
QPainterPath::Element elem = m_points.elementAt(i);
QPointF currentPoint(elem.x, elem.y);
switch (elem.type) {
case QPainterPath::MoveToElement:
lastPoint = currentPoint;
hasLastPoint = true;
break;
case QPainterPath::LineToElement:
if (hasLastPoint) {
segments.append(QLineF(lastPoint, currentPoint));
}
lastPoint = currentPoint;
hasLastPoint = true;
break;
case QPainterPath::CurveToElement:
// 处理曲线(如果需要)
break;
case QPainterPath::CurveToDataElement:
// 曲线数据
break;
}
}
return segments;
}
int ElectricConnectLineItem::findSegmentAt(const QList<QPointF>& points,
const QPointF& itemPos) const
{
if (points.size() < 2) {
return -1;
}
const double HIT_TOLERANCE = 10.0;
int bestSegment = -1;
double bestDistance = HIT_TOLERANCE;
for (int i = 0; i < points.size() - 1; i++) {
QLineF segment(points[i], points[i + 1]);
// 计算距离
double distance = distanceToSegment(segment, itemPos);
if (distance < bestDistance) {
bestDistance = distance;
bestSegment = i;
}
}
return bestSegment;
}
double ElectricConnectLineItem::distanceToSegment(const QLineF& segment, const QPointF& point) const
{
if (segment.isNull()) {
return std::numeric_limits<double>::max();
}
// 检查是否是正交线段
bool isHorizontal = qFuzzyCompare(segment.y1(), segment.y2());
bool isVertical = qFuzzyCompare(segment.x1(), segment.x2());
if (isHorizontal) {
// 水平线段
double minX = qMin(segment.x1(), segment.x2());
double maxX = qMax(segment.x1(), segment.x2());
double y = segment.y1();
if (point.x() >= minX && point.x() <= maxX) {
return qAbs(point.y() - y);
} else if (point.x() < minX) {
return QLineF(point, QPointF(minX, y)).length();
} else {
return QLineF(point, QPointF(maxX, y)).length();
}
}
else if (isVertical) {
// 垂直线段
double minY = qMin(segment.y1(), segment.y2());
double maxY = qMax(segment.y1(), segment.y2());
double x = segment.x1();
if (point.y() >= minY && point.y() <= maxY) {
return qAbs(point.x() - x);
} else if (point.y() < minY) {
return QLineF(point, QPointF(x, minY)).length();
} else {
return QLineF(point, QPointF(x, maxY)).length();
}
}
else {
// 斜线(理论上不应该出现)
return QLineF(segment.p1(), point).length();
}
}
QList<QPointF> ElectricConnectLineItem::extractPointsFromPath() const
{
QList<QPointF> points;
if (m_points.isEmpty()) {
return points;
}
// 从 QPainterPath 提取所有点
for (int i = 0; i < m_points.elementCount(); i++) {
QPainterPath::Element elem = m_points.elementAt(i);
if (elem.type == QPainterPath::MoveToElement ||
elem.type == QPainterPath::LineToElement) {
points.append(QPointF(elem.x, elem.y));
}
}
return points;
}
QList<QPointF> ElectricConnectLineItem::extractPointsFromPath(const QPainterPath& path) const
{
QList<QPointF> points;
if (path.isEmpty()) {
return points;
}
for (int i = 0; i < path.elementCount(); i++) {
QPainterPath::Element elem = path.elementAt(i);
if (elem.type == QPainterPath::MoveToElement ||
elem.type == QPainterPath::LineToElement) {
points.append(QPointF(elem.x, elem.y));
}
}
return points;
}
void ElectricConnectLineItem::applyPointsToPath(const QList<QPointF>& points)
{
if (points.size() < 2) {
m_points = QPainterPath();
return;
}
QPainterPath newPath;
newPath.moveTo(points.first());
for (int i = 1; i < points.size(); i++) {
newPath.lineTo(points[i]);
}
m_points = newPath;
setPath(m_points);
}
void ElectricConnectLineItem::fixConnections(QList<QPointF>& points,
int segmentIndex, bool isVertical)
{
int n = points.size();
if (n < 3) {
return;
}
if (isVertical) {
// 垂直线段移动
if (segmentIndex > 0) {
points[segmentIndex - 1].setX(points[segmentIndex].x());
}
if (segmentIndex + 2 < n) {
points[segmentIndex + 2].setX(points[segmentIndex + 1].x());
}
} else {
// 水平线段移动
if (segmentIndex > 0) {
points[segmentIndex - 1].setY(points[segmentIndex].y());
}
if (segmentIndex + 2 < n) {
points[segmentIndex + 2].setY(points[segmentIndex + 1].y());
}
}
}
void ElectricConnectLineItem::validateAndFixPath()
{
qDebug() << "Validating and fixing path...";
QList<QPointF> points = extractPointsFromPath();
if (points.size() < 2) {
qWarning() << "Path has less than 2 points";
return;
}
bool needsFix = false;
// 检查每个线段
for (int i = 0; i < points.size() - 1; i++) {
QPointF& p1 = points[i];
QPointF& p2 = points[i + 1];
// 检查是否正交
if (!qFuzzyCompare(p1.x(), p2.x()) && !qFuzzyCompare(p1.y(), p2.y())) {
qDebug() << "Fixing non-orthogonal segment" << i;
// 选择主要方向
double dx = qAbs(p2.x() - p1.x());
double dy = qAbs(p2.y() - p1.y());
if (dx < dy) {
p2.setX(p1.x()); // 改为垂直
} else {
p2.setY(p1.y()); // 改为水平
}
needsFix = true;
}
}
// 移除连续重复点
QList<QPointF> cleanedPoints;
cleanedPoints.append(points.first());
for (int i = 1; i < points.size(); i++) {
if (!points[i - 1].isNull() &&
qFuzzyCompare(points[i - 1].x(), points[i].x()) &&
qFuzzyCompare(points[i - 1].y(), points[i].y())) {
continue; // 跳过重复点
}
cleanedPoints.append(points[i]);
}
if (needsFix || cleanedPoints.size() != points.size()) {
qDebug() << "Applying fixes to path";
applyPointsToPath(cleanedPoints);
// 重新计算路径
calculatePath();
}
}
void ElectricConnectLineItem::updateBoundingRect()
{
if (m_points.isEmpty()) {
m_boundingRect = QRectF();
} else {
// 使用路径的边界
m_boundingRect = m_points.boundingRect();
// 添加一些边距
const qreal MARGIN = 2.0;
m_boundingRect.adjust(-MARGIN, -MARGIN, MARGIN, MARGIN);
}
qDebug() << "Updated bounds:" << m_boundingRect;
}