You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Qt的QPainterPath实现类似Revit的路径互穿断裂效果

问题:实现路径互穿后各自断裂独立的效果

我想要实现两条路径互相穿过时,各自断裂但仍保持独立的效果。使用以下代码尝试时:

QGraphicsView* viewer = new QGraphicsView(this);
this->setCentralWidget(viewer);
viewer->show();
QGraphicsScene* scene = new QGraphicsScene(viewer);
viewer->setScene(scene);
QGraphicsPathItem* item1 = new QGraphicsPathItem;
QGraphicsPathItem* item2 = new QGraphicsPathItem;
QGraphicsPathItem* item3 = new QGraphicsPathItem;

scene->setSceneRect(QRect(0,0, viewer->width(), viewer->height()));

const int kb = 80;
const int offset = kb/10;
QRectF br(0, 0, kb*2, offset);

QPainterPath pRect1;
pRect1.moveTo(br.left(), br.top());
pRect1.lineTo(br.right(), br.top());
pRect1.lineTo(br.right(), br.bottom());
pRect1.lineTo(br.left(), br.bottom());
pRect1.lineTo(br.left(), br.top());

QPainterPath pRect2;
pRect2.moveTo(br.left() + br.width()/2.0 - offset, br.top() - br.width());
pRect2.lineTo(br.left() + br.width()/2.0 + offset, br.top() - br.width());
pRect2.lineTo(br.left() + br.width()/2.0 + offset, br.bottom() + br.width());
pRect2.lineTo(br.left() + br.width()/2.0 - offset, br.bottom() + br.width());
pRect2.lineTo(br.left() + br.width()/2.0 - offset, br.top() - br.width());

QPainterPath shape = pRect1.united(pRect2);
shape.simplified();

item1->setPen(QPen(QColor(255,0,0)));
item1->setPos(0,50);
item1->setPath(pRect1);

item2->setPen(QPen(QColor(0,0,255)));
item2->setPos(0,50);
item2->setPath(pRect2);

item3->setPen(QPen(QColor(0,255,0)));
item3->setPos(250,50);
item3->setPath(shape);

scene->addItem(item1);
scene->addItem(item2);
scene->addItem(item3);

我用QPainterPath绘制了两条路径(红色为pRect1,蓝色为pRect2),调用simplified()合并后得到绿色路径,但这达不到我想要的效果。请问:

  • 能否用QPainterPath的现有方法实现需求?
  • 如果必须自定义算法,应该考虑哪种?
  • 有没有实现类似Revit中路径互穿后各自独立断裂效果的建议?

解答

1. QPainterPath现有方法的局限

QPainterPath的united()、simplified()这类方法核心是处理填充区域的合并或简化,而非分割路径线段使其在交叉处断裂并保持独立。因此仅靠内置方法无法直接实现你要的效果。

2. 自定义算法的核心思路

要实现路径互穿后各自断裂,需完成以下步骤:

  • 计算交点:遍历两条路径的所有线段,用向量叉积等几何算法检测并记录所有交点坐标。
  • 分割路径:以交点为分割点,将每条原路径拆分成多个连续的子路径段。
  • 筛选保留段:判断每个子路径段是否处于另一条路径的覆盖范围外,保留需要显示的子路径。

常用的基础算法包括:

  • 线段相交检测(基于叉积的快速判断)
  • 路径分割(按交点拆分路径的线段序列)

3. 类似Revit效果的实现建议

Revit的这类效果本质是针对线条的布尔切割运算,可参考以下方向:

  • 借助第三方几何库:比如Clipper2,它专门处理多边形/路径的布尔运算,支持直接对路径执行切割操作,生成断裂后的子路径。
  • 自定义切割逻辑:若不想引入第三方库,可自行实现交点计算和路径分割,注意处理路径的闭合/开放状态,以及交点处的路径连接正确性。
  • 独立绘制子路径:将切割后的子路径分别添加到QGraphicsPathItem中,保持各自的样式和交互独立性。

内容的提问来源于stack exchange,提问作者Z.Ju

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 19:07:15