DiagramDesigner/diagramCavas/source/graphicsItem/electricConnectLineItem.cpp

987 lines
28 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "graphicsItem/electricConnectLineItem.h"
#include <QGraphicsScene>
#include <QPainter>
#include <QStyleOptionGraphicsItem>
ElectricConnectLineItem::ElectricConnectLineItem(QGraphicsItem *parent)
: GraphicsProjectModelItem(parent)
{
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()
{
m_boundingRect = QRectF();
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();
}
void ElectricConnectLineItem::setStartPoint(const QPointF& p)
{
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;
} else {
m_lstPoints.append(p);
}
update();
}
void ElectricConnectLineItem::setEndPoint(const QPointF& p)
{
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());
}
qDebug() << "✓ Dragging segment" << segmentIndex;
}
}
// 更新拖拽
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
{
// 使用路径的轮廓
if (m_points.isEmpty()) {
return QPainterPath();
}
QPainterPathStroker stroker;
stroker.setWidth(8.0); // 选择区域宽度
QPainterPath shape = stroker.createStroke(m_points);
return shape;
}
QRectF ElectricConnectLineItem::boundingRect() const
{
QRectF rect = shape().boundingRect();
// 如果shape为空使用路径边界
if (rect.isNull() && !m_points.isEmpty()) {
rect = m_points.boundingRect().adjusted(-5, -5, 5, 5);
}
return rect;
}
void ElectricConnectLineItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
if (option->state & QStyle::State_Selected)
{
painter->setPen(Qt::red);
}
else
{
if(_curMonitorStateEnable){ //当前状态被设置
painter->setPen(QPen(_curMonitorStateColor));
}
else
painter->setPen(m_pen);
}
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();
// 获取元件
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;
}
}
// 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;
}
// 单一线段与矩形相交检测
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);
}
// 强制直角绕行
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();
}
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;
}