bpmn-elk-layout 1.0.2 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/bpmn-elk-layout.js +149 -4
- package/dist/bin/bpmn-elk-layout.js.map +1 -1
- package/dist/index.js +148 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +148 -3
- package/dist/index.mjs.map +1 -1
- package/dist/index.node.js +148 -3
- package/dist/index.node.js.map +1 -1
- package/dist/index.node.mjs +148 -3
- package/dist/index.node.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -44,13 +44,12 @@ function isDebugEnabled() {
|
|
|
44
44
|
if (cliMode) return false;
|
|
45
45
|
return typeof process !== "undefined" && process.env?.["DEBUG"] === "true";
|
|
46
46
|
}
|
|
47
|
-
var cliMode
|
|
47
|
+
var cliMode;
|
|
48
48
|
var init_debug = __esm({
|
|
49
49
|
"src/utils/debug.ts"() {
|
|
50
50
|
"use strict";
|
|
51
51
|
init_cjs_shims();
|
|
52
52
|
cliMode = false;
|
|
53
|
-
DEBUG = typeof process !== "undefined" && process.env?.["DEBUG"] === "true";
|
|
54
53
|
}
|
|
55
54
|
});
|
|
56
55
|
|
|
@@ -390,6 +389,10 @@ var init_edge_fixer = __esm({
|
|
|
390
389
|
const containerNodes = nodesByContainer.get(currentContainerId) ?? /* @__PURE__ */ new Map();
|
|
391
390
|
for (const edge of node.edges) {
|
|
392
391
|
if (edge.sections && edge.sections.length > 0) {
|
|
392
|
+
const hasPoolRelativeCoords = edge._poolRelativeCoords === true;
|
|
393
|
+
if (hasPoolRelativeCoords) {
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
393
396
|
this.fixEdgeIfCrossing(edge, containerNodes, containerOffsetX, containerOffsetY);
|
|
394
397
|
}
|
|
395
398
|
}
|
|
@@ -2564,7 +2567,15 @@ var init_lane_arranger = __esm({
|
|
|
2564
2567
|
const waypoints = [];
|
|
2565
2568
|
waypoints.push({ x: startX, y: startY });
|
|
2566
2569
|
if (Math.abs(startY - endY) > 10) {
|
|
2567
|
-
const midX = (
|
|
2570
|
+
const midX = this.findClearMidX(
|
|
2571
|
+
startX,
|
|
2572
|
+
endX,
|
|
2573
|
+
startY,
|
|
2574
|
+
endY,
|
|
2575
|
+
sourceId,
|
|
2576
|
+
targetId,
|
|
2577
|
+
nodePositions
|
|
2578
|
+
);
|
|
2568
2579
|
waypoints.push({ x: midX, y: startY });
|
|
2569
2580
|
waypoints.push({ x: midX, y: endY });
|
|
2570
2581
|
}
|
|
@@ -2582,6 +2593,109 @@ var init_lane_arranger = __esm({
|
|
|
2582
2593
|
}
|
|
2583
2594
|
}
|
|
2584
2595
|
}
|
|
2596
|
+
/**
|
|
2597
|
+
* Find a clear X position for vertical edge segment that avoids obstacles.
|
|
2598
|
+
* Checks all three segments of the L-shaped path:
|
|
2599
|
+
* 1. Horizontal from (startX, startY) to (midX, startY)
|
|
2600
|
+
* 2. Vertical from (midX, startY) to (midX, endY)
|
|
2601
|
+
* 3. Horizontal from (midX, endY) to (endX, endY)
|
|
2602
|
+
*/
|
|
2603
|
+
findClearMidX(startX, endX, startY, endY, sourceId, targetId, nodePositions) {
|
|
2604
|
+
const margin = 15;
|
|
2605
|
+
const minY = Math.min(startY, endY);
|
|
2606
|
+
const maxY = Math.max(startY, endY);
|
|
2607
|
+
const rangeMinX = Math.min(startX, endX);
|
|
2608
|
+
const rangeMaxX = Math.max(startX, endX);
|
|
2609
|
+
if (isDebugEnabled()) {
|
|
2610
|
+
console.log(`[BPMN] findClearMidX: startX=${startX}, endX=${endX}, startY=${startY}, endY=${endY}`);
|
|
2611
|
+
}
|
|
2612
|
+
const allObstacles = [];
|
|
2613
|
+
for (const [nodeId, pos] of nodePositions) {
|
|
2614
|
+
if (nodeId === sourceId || nodeId === targetId) continue;
|
|
2615
|
+
const nodeLeft = pos.x;
|
|
2616
|
+
const nodeRight = pos.x + pos.width;
|
|
2617
|
+
const nodeTop = pos.y;
|
|
2618
|
+
const nodeBottom = pos.y + pos.height;
|
|
2619
|
+
const xOverlap = nodeRight > rangeMinX && nodeLeft < rangeMaxX;
|
|
2620
|
+
const yOverlapVertical = nodeBottom > minY && nodeTop < maxY;
|
|
2621
|
+
const yContainsStartY = nodeTop <= startY && nodeBottom >= startY;
|
|
2622
|
+
const yContainsEndY = nodeTop <= endY && nodeBottom >= endY;
|
|
2623
|
+
if (xOverlap && (yOverlapVertical || yContainsStartY || yContainsEndY)) {
|
|
2624
|
+
allObstacles.push({
|
|
2625
|
+
x: nodeLeft,
|
|
2626
|
+
y: nodeTop,
|
|
2627
|
+
width: pos.width,
|
|
2628
|
+
height: pos.height,
|
|
2629
|
+
right: nodeRight,
|
|
2630
|
+
bottom: nodeBottom,
|
|
2631
|
+
id: nodeId
|
|
2632
|
+
});
|
|
2633
|
+
if (isDebugEnabled()) {
|
|
2634
|
+
console.log(`[BPMN] findClearMidX: obstacle ${nodeId}: x=[${nodeLeft}, ${nodeRight}], y=[${nodeTop}, ${nodeBottom}]`);
|
|
2635
|
+
}
|
|
2636
|
+
}
|
|
2637
|
+
}
|
|
2638
|
+
if (allObstacles.length === 0) {
|
|
2639
|
+
return (startX + endX) / 2;
|
|
2640
|
+
}
|
|
2641
|
+
const isValidMidX = (midX) => {
|
|
2642
|
+
for (const obs of allObstacles) {
|
|
2643
|
+
const seg1MinX = Math.min(startX, midX);
|
|
2644
|
+
const seg1MaxX = Math.max(startX, midX);
|
|
2645
|
+
if (obs.y <= startY && obs.bottom >= startY && // Y range contains startY
|
|
2646
|
+
obs.right > seg1MinX && obs.x < seg1MaxX) {
|
|
2647
|
+
return false;
|
|
2648
|
+
}
|
|
2649
|
+
if (obs.x <= midX && obs.right >= midX && // X range contains midX
|
|
2650
|
+
obs.bottom > minY && obs.y < maxY) {
|
|
2651
|
+
return false;
|
|
2652
|
+
}
|
|
2653
|
+
const seg2MinX = Math.min(midX, endX);
|
|
2654
|
+
const seg2MaxX = Math.max(midX, endX);
|
|
2655
|
+
if (obs.y <= endY && obs.bottom >= endY && // Y range contains endY
|
|
2656
|
+
obs.right > seg2MinX && obs.x < seg2MaxX) {
|
|
2657
|
+
return false;
|
|
2658
|
+
}
|
|
2659
|
+
}
|
|
2660
|
+
return true;
|
|
2661
|
+
};
|
|
2662
|
+
const candidates = [];
|
|
2663
|
+
candidates.push((startX + endX) / 2);
|
|
2664
|
+
candidates.push(startX + margin);
|
|
2665
|
+
candidates.push(endX - margin);
|
|
2666
|
+
for (const obs of allObstacles) {
|
|
2667
|
+
candidates.push(obs.x - margin);
|
|
2668
|
+
candidates.push(obs.right + margin);
|
|
2669
|
+
}
|
|
2670
|
+
const simpleMidX = (startX + endX) / 2;
|
|
2671
|
+
const validCandidates = candidates.filter((x) => x >= rangeMinX && x <= rangeMaxX).sort((a, b) => Math.abs(a - simpleMidX) - Math.abs(b - simpleMidX));
|
|
2672
|
+
for (const candidate of validCandidates) {
|
|
2673
|
+
if (isValidMidX(candidate)) {
|
|
2674
|
+
if (isDebugEnabled()) {
|
|
2675
|
+
console.log(`[BPMN] findClearMidX: found valid position ${candidate}`);
|
|
2676
|
+
}
|
|
2677
|
+
return candidate;
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
const leftMost = Math.min(...allObstacles.map((o) => o.x)) - margin;
|
|
2681
|
+
const rightMost = Math.max(...allObstacles.map((o) => o.right)) + margin;
|
|
2682
|
+
if (leftMost >= rangeMinX && isValidMidX(leftMost)) {
|
|
2683
|
+
if (isDebugEnabled()) {
|
|
2684
|
+
console.log(`[BPMN] findClearMidX: routing left of all obstacles at ${leftMost}`);
|
|
2685
|
+
}
|
|
2686
|
+
return leftMost;
|
|
2687
|
+
}
|
|
2688
|
+
if (rightMost <= rangeMaxX && isValidMidX(rightMost)) {
|
|
2689
|
+
if (isDebugEnabled()) {
|
|
2690
|
+
console.log(`[BPMN] findClearMidX: routing right of all obstacles at ${rightMost}`);
|
|
2691
|
+
}
|
|
2692
|
+
return rightMost;
|
|
2693
|
+
}
|
|
2694
|
+
if (isDebugEnabled()) {
|
|
2695
|
+
console.log(`[BPMN] findClearMidX: no valid route found, using midpoint ${simpleMidX}`);
|
|
2696
|
+
}
|
|
2697
|
+
return simpleMidX;
|
|
2698
|
+
}
|
|
2585
2699
|
};
|
|
2586
2700
|
}
|
|
2587
2701
|
});
|
|
@@ -2670,7 +2784,7 @@ var init_pool_arranger = __esm({
|
|
|
2670
2784
|
pool.y = currentY;
|
|
2671
2785
|
if (isBlackBox) {
|
|
2672
2786
|
pool.width = maxPoolWidth;
|
|
2673
|
-
pool.height =
|
|
2787
|
+
pool.height = 60;
|
|
2674
2788
|
} else if (hasLanes) {
|
|
2675
2789
|
pool.width = maxPoolWidth;
|
|
2676
2790
|
} else {
|
|
@@ -5305,6 +5419,7 @@ var init_diagram_builder = __esm({
|
|
|
5305
5419
|
}
|
|
5306
5420
|
}
|
|
5307
5421
|
}
|
|
5422
|
+
this.ensureOrthogonalWaypoints(waypoints);
|
|
5308
5423
|
const edgeModel = {
|
|
5309
5424
|
id: `${edge.id}_di`,
|
|
5310
5425
|
bpmnElement: edge.id,
|
|
@@ -5371,6 +5486,36 @@ var init_diagram_builder = __esm({
|
|
|
5371
5486
|
y: (lastPoint?.y ?? 0) - labelHeight - 4
|
|
5372
5487
|
};
|
|
5373
5488
|
}
|
|
5489
|
+
/**
|
|
5490
|
+
* Ensure all waypoint segments are orthogonal (horizontal or vertical)
|
|
5491
|
+
* If a diagonal segment is found, insert intermediate bend points to create
|
|
5492
|
+
* an L-shaped orthogonal path.
|
|
5493
|
+
*
|
|
5494
|
+
* Strategy: For diagonal segments, we use "horizontal first" - go horizontally
|
|
5495
|
+
* to the target X, then vertically to the target Y.
|
|
5496
|
+
*/
|
|
5497
|
+
ensureOrthogonalWaypoints(waypoints) {
|
|
5498
|
+
if (waypoints.length < 2) return;
|
|
5499
|
+
const tolerance = 1;
|
|
5500
|
+
let i = 0;
|
|
5501
|
+
while (i < waypoints.length - 1) {
|
|
5502
|
+
const current = waypoints[i];
|
|
5503
|
+
const next = waypoints[i + 1];
|
|
5504
|
+
if (!current || !next) {
|
|
5505
|
+
i++;
|
|
5506
|
+
continue;
|
|
5507
|
+
}
|
|
5508
|
+
const dx = Math.abs(next.x - current.x);
|
|
5509
|
+
const dy = Math.abs(next.y - current.y);
|
|
5510
|
+
if (dx > tolerance && dy > tolerance) {
|
|
5511
|
+
const bendPoint = { x: next.x, y: current.y };
|
|
5512
|
+
waypoints.splice(i + 1, 0, bendPoint);
|
|
5513
|
+
i++;
|
|
5514
|
+
} else {
|
|
5515
|
+
i++;
|
|
5516
|
+
}
|
|
5517
|
+
}
|
|
5518
|
+
}
|
|
5374
5519
|
};
|
|
5375
5520
|
}
|
|
5376
5521
|
});
|