如何通过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
相关产品推荐
相关产品推荐

