Better routing
This commit is contained in:
parent
916965488c
commit
07e2fb4c5a
3 changed files with 99 additions and 27 deletions
|
|
@ -66,7 +66,17 @@ QPainterPath SquareConnectionPainter::orthogonalPath(
|
|||
constexpr double kNodePad = 15.0;
|
||||
|
||||
auto const cId = cgo.connectionId();
|
||||
double const spread = static_cast<double>(cId.outPortIndex) * kSpacing;
|
||||
|
||||
double spread = static_cast<double>(cId.outPortIndex) * kSpacing;
|
||||
auto *sceneForChannel = cgo.nodeScene();
|
||||
if (sceneForChannel) {
|
||||
auto *mdl = dynamic_cast<WarpGraphModel *>(&sceneForChannel->graphModel());
|
||||
if (mdl) {
|
||||
auto ch = mdl->connectionChannel(cId);
|
||||
spread = (static_cast<double>(ch.index) - (ch.count - 1) / 2.0)
|
||||
* kSpacing;
|
||||
}
|
||||
}
|
||||
|
||||
double const dy = in.y() - out.y();
|
||||
|
||||
|
|
@ -114,51 +124,52 @@ QPainterPath SquareConnectionPainter::orthogonalPath(
|
|||
// out -------+ seg 1 + corner 1
|
||||
//
|
||||
|
||||
double rightX = out.x() + kMinStub + spread;
|
||||
double leftX = in.x() - kMinStub - spread;
|
||||
double midY = (out.y() + in.y()) / 2.0;
|
||||
double railOffset = 0.0;
|
||||
if (sceneForChannel) {
|
||||
auto *mdl2 = dynamic_cast<WarpGraphModel *>(&sceneForChannel->graphModel());
|
||||
if (mdl2) {
|
||||
auto ch = mdl2->connectionChannel(cId);
|
||||
railOffset = static_cast<double>(ch.index) * kSpacing;
|
||||
}
|
||||
}
|
||||
|
||||
double rightX = out.x() + kMinStub + railOffset;
|
||||
double leftX = in.x() - kMinStub - railOffset;
|
||||
double midY = (out.y() + in.y()) / 2.0 + spread;
|
||||
|
||||
// Use actual node geometry when available so the path routes cleanly
|
||||
// around both nodes instead of cutting through them.
|
||||
auto *scene = cgo.nodeScene();
|
||||
if (scene) {
|
||||
auto *outNGO = scene->nodeGraphicsObject(cId.outNodeId);
|
||||
auto *inNGO = scene->nodeGraphicsObject(cId.inNodeId);
|
||||
if (outNGO && inNGO) {
|
||||
// Map node scene bounds into the CGO's local coordinate space
|
||||
// (endPoint() values live there too).
|
||||
QRectF const outRect =
|
||||
cgo.mapRectFromScene(outNGO->sceneBoundingRect());
|
||||
QRectF const inRect =
|
||||
cgo.mapRectFromScene(inNGO->sceneBoundingRect());
|
||||
|
||||
// Push vertical rails outside both nodes.
|
||||
double const rightEdge = std::max(outRect.right(), inRect.right());
|
||||
rightX = std::max(rightX, rightEdge + kNodePad + spread);
|
||||
rightX = std::max(rightX, rightEdge + kNodePad + railOffset);
|
||||
|
||||
double const leftEdge = std::min(outRect.left(), inRect.left());
|
||||
leftX = std::min(leftX, leftEdge - kNodePad - spread);
|
||||
leftX = std::min(leftX, leftEdge - kNodePad - railOffset);
|
||||
|
||||
// Place the horizontal crossover in the gap between nodes when
|
||||
// they don't overlap vertically; otherwise route above or below.
|
||||
double const topInner =
|
||||
std::min(outRect.bottom(), inRect.bottom());
|
||||
double const botInner =
|
||||
std::max(outRect.top(), inRect.top());
|
||||
|
||||
if (botInner > topInner + 2.0 * kNodePad) {
|
||||
// Vertical gap exists — clamp midY into the gap.
|
||||
midY = std::clamp(midY, topInner + kNodePad,
|
||||
botInner - kNodePad);
|
||||
} else {
|
||||
// Nodes overlap vertically — pick the shorter detour.
|
||||
double const above =
|
||||
std::min(outRect.top(), inRect.top()) - kNodePad;
|
||||
double const below =
|
||||
std::max(outRect.bottom(), inRect.bottom()) + kNodePad;
|
||||
midY = (std::abs(midY - above) < std::abs(midY - below))
|
||||
? above
|
||||
: below;
|
||||
double baseMidY = (out.y() + in.y()) / 2.0;
|
||||
midY = (std::abs(baseMidY - above) < std::abs(baseMidY - below))
|
||||
? above + spread
|
||||
: below + spread;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue