bpmn-elk-layout 1.0.1 → 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 +5631 -5166
- package/dist/bin/bpmn-elk-layout.js.map +1 -1
- package/dist/index.js +196 -44
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +196 -44
- package/dist/index.mjs.map +1 -1
- package/dist/index.node.js +196 -44
- package/dist/index.node.js.map +1 -1
- package/dist/index.node.mjs +196 -44
- package/dist/index.node.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.node.js
CHANGED
|
@@ -304,7 +304,11 @@ function lineIntersection(p1, p2, p3, p4) {
|
|
|
304
304
|
}
|
|
305
305
|
|
|
306
306
|
// src/utils/debug.ts
|
|
307
|
-
var
|
|
307
|
+
var cliMode = false;
|
|
308
|
+
function isDebugEnabled() {
|
|
309
|
+
if (cliMode) return false;
|
|
310
|
+
return typeof process !== "undefined" && process.env?.["DEBUG"] === "true";
|
|
311
|
+
}
|
|
308
312
|
|
|
309
313
|
// src/layout/edge-routing/edge-fixer.ts
|
|
310
314
|
var EdgeFixer = class {
|
|
@@ -337,7 +341,7 @@ var EdgeFixer = class {
|
|
|
337
341
|
const isFlowNode = flowNodePatterns.some((pattern) => pattern.test(id));
|
|
338
342
|
const isPool = poolPatterns.some((pattern) => pattern.test(id));
|
|
339
343
|
const bpmn = node.bpmn;
|
|
340
|
-
if (
|
|
344
|
+
if (isDebugEnabled() && (id.includes("lane") || id.includes("pool") || id.includes("end_fast") || id.includes("gateway_fast"))) {
|
|
341
345
|
console.log(`[BPMN] EdgeFixer.collectNodePositions: id=${id}, offsetX=${offsetX}, offsetY=${offsetY}, bpmn=${JSON.stringify(bpmn)}`);
|
|
342
346
|
console.log(`[BPMN] node.x=${node.x}, node.y=${node.y}, isFlowNode=${isFlowNode}, isPool=${isPool}`);
|
|
343
347
|
}
|
|
@@ -375,6 +379,10 @@ var EdgeFixer = class {
|
|
|
375
379
|
const containerNodes = nodesByContainer.get(currentContainerId) ?? /* @__PURE__ */ new Map();
|
|
376
380
|
for (const edge of node.edges) {
|
|
377
381
|
if (edge.sections && edge.sections.length > 0) {
|
|
382
|
+
const hasPoolRelativeCoords = edge._poolRelativeCoords === true;
|
|
383
|
+
if (hasPoolRelativeCoords) {
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
378
386
|
this.fixEdgeIfCrossing(edge, containerNodes, containerOffsetX, containerOffsetY);
|
|
379
387
|
}
|
|
380
388
|
}
|
|
@@ -426,7 +434,7 @@ var EdgeFixer = class {
|
|
|
426
434
|
}
|
|
427
435
|
const targetPos = targetId ? nodePositions.get(targetId) : void 0;
|
|
428
436
|
const sourcePos = sourceId ? nodePositions.get(sourceId) : void 0;
|
|
429
|
-
if (
|
|
437
|
+
if (isDebugEnabled() && edge.id?.includes("back")) {
|
|
430
438
|
console.log(`[BPMN] Edge ${edge.id}: sourceId=${sourceId}, targetId=${targetId}`);
|
|
431
439
|
console.log(`[BPMN] Edge ${edge.id}: sourcePos=${JSON.stringify(sourcePos)}, targetPos=${JSON.stringify(targetPos)}`);
|
|
432
440
|
console.log(`[BPMN] Edge ${edge.id}: waypoints.length=${waypoints.length}`);
|
|
@@ -435,7 +443,7 @@ var EdgeFixer = class {
|
|
|
435
443
|
const lastWaypoint = waypoints[waypoints.length - 1];
|
|
436
444
|
const secondLastWaypoint = waypoints[waypoints.length - 2];
|
|
437
445
|
const isReturnEdge2 = targetPos.y + targetPos.height < sourcePos.y;
|
|
438
|
-
if (
|
|
446
|
+
if (isDebugEnabled() && edge.id?.includes("back")) {
|
|
439
447
|
console.log(`[BPMN] Edge ${edge.id}: isReturnEdge=${isReturnEdge2}`);
|
|
440
448
|
if (lastWaypoint) {
|
|
441
449
|
console.log(`[BPMN] Edge ${edge.id}: lastWaypoint=(${lastWaypoint.x},${lastWaypoint.y})`);
|
|
@@ -455,7 +463,7 @@ var EdgeFixer = class {
|
|
|
455
463
|
}
|
|
456
464
|
}
|
|
457
465
|
if (crossedNodes.length === 0) return;
|
|
458
|
-
if (
|
|
466
|
+
if (isDebugEnabled()) {
|
|
459
467
|
console.log(`[BPMN] Edge ${edge.id} crosses nodes: ${crossedNodes.join(", ")}`);
|
|
460
468
|
}
|
|
461
469
|
if (!sourcePos || !targetPos) return;
|
|
@@ -506,7 +514,7 @@ var EdgeFixer = class {
|
|
|
506
514
|
y: bp.y - containerOffsetY
|
|
507
515
|
}));
|
|
508
516
|
section.bendPoints = relativeBendPoints.length > 0 ? relativeBendPoints : void 0;
|
|
509
|
-
if (
|
|
517
|
+
if (isDebugEnabled()) {
|
|
510
518
|
console.log(`[BPMN] Fixed edge ${edge.id} with ${relativeBendPoints.length} bend points`);
|
|
511
519
|
}
|
|
512
520
|
}
|
|
@@ -1296,7 +1304,8 @@ function applyNodeMoves(graph, movedNodes) {
|
|
|
1296
1304
|
}
|
|
1297
1305
|
|
|
1298
1306
|
// src/layout/post-processing/boundary-event/edge-recalculator.ts
|
|
1299
|
-
function recalculateEdgesForMovedNodes(graph, movedNodes, boundaryEventInfo
|
|
1307
|
+
function recalculateEdgesForMovedNodes(graph, movedNodes, boundaryEventInfo) {
|
|
1308
|
+
const debug = isDebugEnabled();
|
|
1300
1309
|
const nodeMap = /* @__PURE__ */ new Map();
|
|
1301
1310
|
const buildNodeMap2 = (node) => {
|
|
1302
1311
|
nodeMap.set(node.id, node);
|
|
@@ -1373,7 +1382,8 @@ function recalculateEdgesForMovedNodes(graph, movedNodes, boundaryEventInfo, deb
|
|
|
1373
1382
|
};
|
|
1374
1383
|
processEdges(graph);
|
|
1375
1384
|
}
|
|
1376
|
-
function recalculateEdgeWithObstacleAvoidance(edge, source, target, obstacleIds, nodeMap
|
|
1385
|
+
function recalculateEdgeWithObstacleAvoidance(edge, source, target, obstacleIds, nodeMap) {
|
|
1386
|
+
const debug = isDebugEnabled();
|
|
1377
1387
|
const sx = source.x ?? 0;
|
|
1378
1388
|
const sy = source.y ?? 0;
|
|
1379
1389
|
const sw = source.width ?? 100;
|
|
@@ -1594,8 +1604,8 @@ var BoundaryEventHandler = class {
|
|
|
1594
1604
|
/**
|
|
1595
1605
|
* Recalculate edge waypoints for edges connected to moved nodes
|
|
1596
1606
|
*/
|
|
1597
|
-
recalculateEdgesForMovedNodes(graph, movedNodes, boundaryEventInfo
|
|
1598
|
-
recalculateEdgesForMovedNodes(graph, movedNodes, boundaryEventInfo
|
|
1607
|
+
recalculateEdgesForMovedNodes(graph, movedNodes, boundaryEventInfo) {
|
|
1608
|
+
recalculateEdgesForMovedNodes(graph, movedNodes, boundaryEventInfo);
|
|
1599
1609
|
}
|
|
1600
1610
|
};
|
|
1601
1611
|
|
|
@@ -2482,7 +2492,7 @@ var LaneArranger = class {
|
|
|
2482
2492
|
const targetId = edge.targets?.[0];
|
|
2483
2493
|
const sourcePos = sourceId ? nodePositions.get(sourceId) : void 0;
|
|
2484
2494
|
const targetPos = targetId ? nodePositions.get(targetId) : void 0;
|
|
2485
|
-
if (
|
|
2495
|
+
if (isDebugEnabled()) {
|
|
2486
2496
|
console.log(`[BPMN] recalculatePoolEdges ${edge.id}: source=${sourceId}, target=${targetId}`);
|
|
2487
2497
|
console.log(`[BPMN] sourcePos=${JSON.stringify(sourcePos)}`);
|
|
2488
2498
|
console.log(`[BPMN] targetPos=${JSON.stringify(targetPos)}`);
|
|
@@ -2492,18 +2502,26 @@ var LaneArranger = class {
|
|
|
2492
2502
|
const startY = sourcePos.y + sourcePos.height / 2;
|
|
2493
2503
|
const endX = targetPos.x;
|
|
2494
2504
|
const endY = targetPos.y + targetPos.height / 2;
|
|
2495
|
-
if (
|
|
2505
|
+
if (isDebugEnabled()) {
|
|
2496
2506
|
console.log(`[BPMN] startX=${startX}, startY=${startY}, endX=${endX}, endY=${endY}`);
|
|
2497
2507
|
}
|
|
2498
2508
|
const waypoints = [];
|
|
2499
2509
|
waypoints.push({ x: startX, y: startY });
|
|
2500
2510
|
if (Math.abs(startY - endY) > 10) {
|
|
2501
|
-
const midX = (
|
|
2511
|
+
const midX = this.findClearMidX(
|
|
2512
|
+
startX,
|
|
2513
|
+
endX,
|
|
2514
|
+
startY,
|
|
2515
|
+
endY,
|
|
2516
|
+
sourceId,
|
|
2517
|
+
targetId,
|
|
2518
|
+
nodePositions
|
|
2519
|
+
);
|
|
2502
2520
|
waypoints.push({ x: midX, y: startY });
|
|
2503
2521
|
waypoints.push({ x: midX, y: endY });
|
|
2504
2522
|
}
|
|
2505
2523
|
waypoints.push({ x: endX, y: endY });
|
|
2506
|
-
if (
|
|
2524
|
+
if (isDebugEnabled()) {
|
|
2507
2525
|
console.log(`[BPMN] waypoints=${JSON.stringify(waypoints)}`);
|
|
2508
2526
|
}
|
|
2509
2527
|
edge._poolRelativeCoords = true;
|
|
@@ -2516,6 +2534,109 @@ var LaneArranger = class {
|
|
|
2516
2534
|
}
|
|
2517
2535
|
}
|
|
2518
2536
|
}
|
|
2537
|
+
/**
|
|
2538
|
+
* Find a clear X position for vertical edge segment that avoids obstacles.
|
|
2539
|
+
* Checks all three segments of the L-shaped path:
|
|
2540
|
+
* 1. Horizontal from (startX, startY) to (midX, startY)
|
|
2541
|
+
* 2. Vertical from (midX, startY) to (midX, endY)
|
|
2542
|
+
* 3. Horizontal from (midX, endY) to (endX, endY)
|
|
2543
|
+
*/
|
|
2544
|
+
findClearMidX(startX, endX, startY, endY, sourceId, targetId, nodePositions) {
|
|
2545
|
+
const margin = 15;
|
|
2546
|
+
const minY = Math.min(startY, endY);
|
|
2547
|
+
const maxY = Math.max(startY, endY);
|
|
2548
|
+
const rangeMinX = Math.min(startX, endX);
|
|
2549
|
+
const rangeMaxX = Math.max(startX, endX);
|
|
2550
|
+
if (isDebugEnabled()) {
|
|
2551
|
+
console.log(`[BPMN] findClearMidX: startX=${startX}, endX=${endX}, startY=${startY}, endY=${endY}`);
|
|
2552
|
+
}
|
|
2553
|
+
const allObstacles = [];
|
|
2554
|
+
for (const [nodeId, pos] of nodePositions) {
|
|
2555
|
+
if (nodeId === sourceId || nodeId === targetId) continue;
|
|
2556
|
+
const nodeLeft = pos.x;
|
|
2557
|
+
const nodeRight = pos.x + pos.width;
|
|
2558
|
+
const nodeTop = pos.y;
|
|
2559
|
+
const nodeBottom = pos.y + pos.height;
|
|
2560
|
+
const xOverlap = nodeRight > rangeMinX && nodeLeft < rangeMaxX;
|
|
2561
|
+
const yOverlapVertical = nodeBottom > minY && nodeTop < maxY;
|
|
2562
|
+
const yContainsStartY = nodeTop <= startY && nodeBottom >= startY;
|
|
2563
|
+
const yContainsEndY = nodeTop <= endY && nodeBottom >= endY;
|
|
2564
|
+
if (xOverlap && (yOverlapVertical || yContainsStartY || yContainsEndY)) {
|
|
2565
|
+
allObstacles.push({
|
|
2566
|
+
x: nodeLeft,
|
|
2567
|
+
y: nodeTop,
|
|
2568
|
+
width: pos.width,
|
|
2569
|
+
height: pos.height,
|
|
2570
|
+
right: nodeRight,
|
|
2571
|
+
bottom: nodeBottom,
|
|
2572
|
+
id: nodeId
|
|
2573
|
+
});
|
|
2574
|
+
if (isDebugEnabled()) {
|
|
2575
|
+
console.log(`[BPMN] findClearMidX: obstacle ${nodeId}: x=[${nodeLeft}, ${nodeRight}], y=[${nodeTop}, ${nodeBottom}]`);
|
|
2576
|
+
}
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
if (allObstacles.length === 0) {
|
|
2580
|
+
return (startX + endX) / 2;
|
|
2581
|
+
}
|
|
2582
|
+
const isValidMidX = (midX) => {
|
|
2583
|
+
for (const obs of allObstacles) {
|
|
2584
|
+
const seg1MinX = Math.min(startX, midX);
|
|
2585
|
+
const seg1MaxX = Math.max(startX, midX);
|
|
2586
|
+
if (obs.y <= startY && obs.bottom >= startY && // Y range contains startY
|
|
2587
|
+
obs.right > seg1MinX && obs.x < seg1MaxX) {
|
|
2588
|
+
return false;
|
|
2589
|
+
}
|
|
2590
|
+
if (obs.x <= midX && obs.right >= midX && // X range contains midX
|
|
2591
|
+
obs.bottom > minY && obs.y < maxY) {
|
|
2592
|
+
return false;
|
|
2593
|
+
}
|
|
2594
|
+
const seg2MinX = Math.min(midX, endX);
|
|
2595
|
+
const seg2MaxX = Math.max(midX, endX);
|
|
2596
|
+
if (obs.y <= endY && obs.bottom >= endY && // Y range contains endY
|
|
2597
|
+
obs.right > seg2MinX && obs.x < seg2MaxX) {
|
|
2598
|
+
return false;
|
|
2599
|
+
}
|
|
2600
|
+
}
|
|
2601
|
+
return true;
|
|
2602
|
+
};
|
|
2603
|
+
const candidates = [];
|
|
2604
|
+
candidates.push((startX + endX) / 2);
|
|
2605
|
+
candidates.push(startX + margin);
|
|
2606
|
+
candidates.push(endX - margin);
|
|
2607
|
+
for (const obs of allObstacles) {
|
|
2608
|
+
candidates.push(obs.x - margin);
|
|
2609
|
+
candidates.push(obs.right + margin);
|
|
2610
|
+
}
|
|
2611
|
+
const simpleMidX = (startX + endX) / 2;
|
|
2612
|
+
const validCandidates = candidates.filter((x) => x >= rangeMinX && x <= rangeMaxX).sort((a, b) => Math.abs(a - simpleMidX) - Math.abs(b - simpleMidX));
|
|
2613
|
+
for (const candidate of validCandidates) {
|
|
2614
|
+
if (isValidMidX(candidate)) {
|
|
2615
|
+
if (isDebugEnabled()) {
|
|
2616
|
+
console.log(`[BPMN] findClearMidX: found valid position ${candidate}`);
|
|
2617
|
+
}
|
|
2618
|
+
return candidate;
|
|
2619
|
+
}
|
|
2620
|
+
}
|
|
2621
|
+
const leftMost = Math.min(...allObstacles.map((o) => o.x)) - margin;
|
|
2622
|
+
const rightMost = Math.max(...allObstacles.map((o) => o.right)) + margin;
|
|
2623
|
+
if (leftMost >= rangeMinX && isValidMidX(leftMost)) {
|
|
2624
|
+
if (isDebugEnabled()) {
|
|
2625
|
+
console.log(`[BPMN] findClearMidX: routing left of all obstacles at ${leftMost}`);
|
|
2626
|
+
}
|
|
2627
|
+
return leftMost;
|
|
2628
|
+
}
|
|
2629
|
+
if (rightMost <= rangeMaxX && isValidMidX(rightMost)) {
|
|
2630
|
+
if (isDebugEnabled()) {
|
|
2631
|
+
console.log(`[BPMN] findClearMidX: routing right of all obstacles at ${rightMost}`);
|
|
2632
|
+
}
|
|
2633
|
+
return rightMost;
|
|
2634
|
+
}
|
|
2635
|
+
if (isDebugEnabled()) {
|
|
2636
|
+
console.log(`[BPMN] findClearMidX: no valid route found, using midpoint ${simpleMidX}`);
|
|
2637
|
+
}
|
|
2638
|
+
return simpleMidX;
|
|
2639
|
+
}
|
|
2519
2640
|
};
|
|
2520
2641
|
|
|
2521
2642
|
// src/layout/post-processing/pool-arranger.ts
|
|
@@ -2596,7 +2717,7 @@ var PoolArranger = class {
|
|
|
2596
2717
|
pool.y = currentY;
|
|
2597
2718
|
if (isBlackBox) {
|
|
2598
2719
|
pool.width = maxPoolWidth;
|
|
2599
|
-
pool.height =
|
|
2720
|
+
pool.height = 60;
|
|
2600
2721
|
} else if (hasLanes) {
|
|
2601
2722
|
pool.width = maxPoolWidth;
|
|
2602
2723
|
} else {
|
|
@@ -3011,7 +3132,7 @@ var GatewayEdgeAdjuster = class {
|
|
|
3011
3132
|
const gateways = /* @__PURE__ */ new Map();
|
|
3012
3133
|
this.collectGateways(layoutedGraph, originalGraph, gateways, 0, 0);
|
|
3013
3134
|
if (gateways.size === 0) return;
|
|
3014
|
-
if (
|
|
3135
|
+
if (isDebugEnabled()) {
|
|
3015
3136
|
console.log(`[BPMN] GatewayEdgeAdjuster: Found ${gateways.size} gateways`);
|
|
3016
3137
|
for (const [id, info] of gateways) {
|
|
3017
3138
|
console.log(`[BPMN] - ${id}: bounds=(${info.bounds.x},${info.bounds.y},${info.bounds.width},${info.bounds.height})`);
|
|
@@ -3098,7 +3219,7 @@ var GatewayEdgeAdjuster = class {
|
|
|
3098
3219
|
const section = edge.sections[0];
|
|
3099
3220
|
const sourceId = edge.sources?.[0];
|
|
3100
3221
|
const targetId = edge.targets?.[0];
|
|
3101
|
-
if (
|
|
3222
|
+
if (isDebugEnabled()) {
|
|
3102
3223
|
console.log(`[BPMN] GatewayEdgeAdjuster: Processing edge ${edge.id}, offset=(${offsetX},${offsetY})`);
|
|
3103
3224
|
console.log(`[BPMN] sourceId=${sourceId}, targetId=${targetId}`);
|
|
3104
3225
|
console.log(`[BPMN] startPoint=(${section.startPoint.x},${section.startPoint.y}), endPoint=(${section.endPoint.x},${section.endPoint.y})`);
|
|
@@ -3110,7 +3231,7 @@ var GatewayEdgeAdjuster = class {
|
|
|
3110
3231
|
}
|
|
3111
3232
|
const targetGateway = targetId ? gateways.get(targetId) : void 0;
|
|
3112
3233
|
if (targetGateway) {
|
|
3113
|
-
if (
|
|
3234
|
+
if (isDebugEnabled()) {
|
|
3114
3235
|
console.log(`[BPMN] target gateway: ${targetId}, bounds=(${targetGateway.bounds.x},${targetGateway.bounds.y})`);
|
|
3115
3236
|
console.log(`[BPMN] left corner: (${targetGateway.corners.left.x},${targetGateway.corners.left.y})`);
|
|
3116
3237
|
}
|
|
@@ -3181,7 +3302,7 @@ var GatewayEdgeAdjuster = class {
|
|
|
3181
3302
|
lastBend.x = newEnd.x;
|
|
3182
3303
|
}
|
|
3183
3304
|
}
|
|
3184
|
-
if (
|
|
3305
|
+
if (isDebugEnabled()) {
|
|
3185
3306
|
console.log(`[BPMN] GatewayEdgeAdjuster: Adjusted edge ${edge.id} endpoint from (${endX},${endY}) to (${targetCorner.x},${targetCorner.y})`);
|
|
3186
3307
|
}
|
|
3187
3308
|
} else {
|
|
@@ -3195,7 +3316,7 @@ var GatewayEdgeAdjuster = class {
|
|
|
3195
3316
|
x: intersectionPoint.x - offsetX,
|
|
3196
3317
|
y: intersectionPoint.y - offsetY
|
|
3197
3318
|
};
|
|
3198
|
-
if (
|
|
3319
|
+
if (isDebugEnabled()) {
|
|
3199
3320
|
console.log(`[BPMN] GatewayEdgeAdjuster: Adjusted edge ${edge.id} endpoint to diamond intersection (${intersectionPoint.x},${intersectionPoint.y})`);
|
|
3200
3321
|
}
|
|
3201
3322
|
}
|
|
@@ -3455,7 +3576,7 @@ var ElkGraphPreparer = class {
|
|
|
3455
3576
|
for (const startId of startEvents) {
|
|
3456
3577
|
traverseMainFlow(startId);
|
|
3457
3578
|
}
|
|
3458
|
-
if (
|
|
3579
|
+
if (isDebugEnabled()) {
|
|
3459
3580
|
console.log(`[BPMN] Main flow nodes: ${Array.from(mainFlowNodes).join(", ")}`);
|
|
3460
3581
|
}
|
|
3461
3582
|
return mainFlowNodes;
|
|
@@ -3790,7 +3911,7 @@ var ResultMerger = class {
|
|
|
3790
3911
|
return originalEdges.map((origEdge) => {
|
|
3791
3912
|
const layoutedEdge = layoutedEdgeMap.get(origEdge.id);
|
|
3792
3913
|
if (layoutedEdge) {
|
|
3793
|
-
if (
|
|
3914
|
+
if (isDebugEnabled() && layoutedEdge.sections?.[0]?.bendPoints?.length) {
|
|
3794
3915
|
console.log(`[BPMN] Merge ${origEdge.id}: bendPoints=${JSON.stringify(layoutedEdge.sections[0].bendPoints)}`);
|
|
3795
3916
|
}
|
|
3796
3917
|
const mergedEdge = {
|
|
@@ -3928,7 +4049,7 @@ var MainFlowNormalizer = class {
|
|
|
3928
4049
|
return;
|
|
3929
4050
|
}
|
|
3930
4051
|
const offsetY = currentMinY - TARGET_MAIN_FLOW_Y;
|
|
3931
|
-
if (
|
|
4052
|
+
if (isDebugEnabled()) {
|
|
3932
4053
|
console.log(`[BPMN] Normalizing main flow: currentMinY=${currentMinY}, offsetY=${offsetY}`);
|
|
3933
4054
|
console.log(`[BPMN] Upstream nodes: ${upstreamMainFlow.map((n) => n.id).join(", ")}`);
|
|
3934
4055
|
console.log(`[BPMN] Downstream nodes: ${downstreamMainFlow.map((n) => n.id).join(", ")}`);
|
|
@@ -3936,7 +4057,7 @@ var MainFlowNormalizer = class {
|
|
|
3936
4057
|
for (const node of otherUpstreamNodes) {
|
|
3937
4058
|
if (node.y !== void 0) {
|
|
3938
4059
|
node.y -= offsetY;
|
|
3939
|
-
if (
|
|
4060
|
+
if (isDebugEnabled()) {
|
|
3940
4061
|
console.log(`[BPMN] Shifted upstream ${node.id} to y=${node.y}`);
|
|
3941
4062
|
}
|
|
3942
4063
|
}
|
|
@@ -3949,14 +4070,14 @@ var MainFlowNormalizer = class {
|
|
|
3949
4070
|
const predecessorCenterY = predecessor.y + (predecessor.height ?? 80) / 2;
|
|
3950
4071
|
const endNodeCenterY = (endNode.height ?? 36) / 2;
|
|
3951
4072
|
endNode.y = predecessorCenterY - endNodeCenterY;
|
|
3952
|
-
if (
|
|
4073
|
+
if (isDebugEnabled()) {
|
|
3953
4074
|
console.log(`[BPMN] Aligned endEvent ${endNode.id} with predecessor ${predecessorId}: y=${endNode.y}`);
|
|
3954
4075
|
}
|
|
3955
4076
|
}
|
|
3956
4077
|
} else {
|
|
3957
4078
|
if (endNode.y !== void 0) {
|
|
3958
4079
|
endNode.y -= offsetY;
|
|
3959
|
-
if (
|
|
4080
|
+
if (isDebugEnabled()) {
|
|
3960
4081
|
console.log(`[BPMN] Shifted upstream ${endNode.id} to y=${endNode.y} (no predecessor found)`);
|
|
3961
4082
|
}
|
|
3962
4083
|
}
|
|
@@ -3984,7 +4105,7 @@ var MainFlowNormalizer = class {
|
|
|
3984
4105
|
const newY = prevBottom + MIN_SPACING;
|
|
3985
4106
|
currNode.y = newY;
|
|
3986
4107
|
adjustedEndEvents.set(currNode.id, newY);
|
|
3987
|
-
if (
|
|
4108
|
+
if (isDebugEnabled()) {
|
|
3988
4109
|
console.log(`[BPMN] Adjusted overlapping endEvent ${currNode.id} at x=${x}: y=${currNode.y}`);
|
|
3989
4110
|
}
|
|
3990
4111
|
}
|
|
@@ -4008,7 +4129,7 @@ var MainFlowNormalizer = class {
|
|
|
4008
4129
|
for (const node of downstreamMainFlow) {
|
|
4009
4130
|
if (node.y !== void 0) {
|
|
4010
4131
|
node.y -= downstreamOffsetY;
|
|
4011
|
-
if (
|
|
4132
|
+
if (isDebugEnabled()) {
|
|
4012
4133
|
console.log(`[BPMN] Shifted downstream ${node.id} to y=${node.y}`);
|
|
4013
4134
|
}
|
|
4014
4135
|
}
|
|
@@ -4190,20 +4311,20 @@ var MainFlowNormalizer = class {
|
|
|
4190
4311
|
lastBend.y = newTargetY;
|
|
4191
4312
|
section.endPoint.y = newTargetY;
|
|
4192
4313
|
edgesWithAdjustedEndpoint.add(edge.id);
|
|
4193
|
-
if (
|
|
4314
|
+
if (isDebugEnabled()) {
|
|
4194
4315
|
console.log(`[BPMN] Updated edge ${edge.id} last bendPoint and endpoint to y=${newTargetY}`);
|
|
4195
4316
|
}
|
|
4196
4317
|
} else {
|
|
4197
4318
|
section.endPoint.y = newTargetY;
|
|
4198
4319
|
edgesWithAdjustedEndpoint.add(edge.id);
|
|
4199
|
-
if (
|
|
4320
|
+
if (isDebugEnabled()) {
|
|
4200
4321
|
console.log(`[BPMN] Updated edge ${edge.id} endpoint to y=${newTargetY}`);
|
|
4201
4322
|
}
|
|
4202
4323
|
}
|
|
4203
4324
|
} else if (section.endPoint) {
|
|
4204
4325
|
section.endPoint.y = newTargetY;
|
|
4205
4326
|
edgesWithAdjustedEndpoint.add(edge.id);
|
|
4206
|
-
if (
|
|
4327
|
+
if (isDebugEnabled()) {
|
|
4207
4328
|
console.log(`[BPMN] Updated edge ${edge.id} endpoint to y=${newTargetY}`);
|
|
4208
4329
|
}
|
|
4209
4330
|
}
|
|
@@ -4317,7 +4438,7 @@ var GatewayPropagator = class {
|
|
|
4317
4438
|
offset: 0,
|
|
4318
4439
|
newX
|
|
4319
4440
|
});
|
|
4320
|
-
if (
|
|
4441
|
+
if (isDebugEnabled()) {
|
|
4321
4442
|
console.log(`[BPMN] Propagating gateway movement to ${targetId}: x ${currentX} -> ${newX}`);
|
|
4322
4443
|
}
|
|
4323
4444
|
this.propagateDownstreamX(targetId, newX, targetNode.width ?? 100, nodeMap, edgeMap, mainFlowNodes, gatewayMoves);
|
|
@@ -4345,7 +4466,7 @@ var GatewayPropagator = class {
|
|
|
4345
4466
|
offset: 0,
|
|
4346
4467
|
newX
|
|
4347
4468
|
});
|
|
4348
|
-
if (
|
|
4469
|
+
if (isDebugEnabled()) {
|
|
4349
4470
|
console.log(`[BPMN] Propagating X to ${targetId}: x ${currentX} -> ${newX}`);
|
|
4350
4471
|
}
|
|
4351
4472
|
this.propagateDownstreamX(targetId, newX, targetNode.width ?? 100, nodeMap, edgeMap, mainFlowNodes, moves);
|
|
@@ -4400,14 +4521,14 @@ var ElkLayouter = class {
|
|
|
4400
4521
|
const layoutedElkGraph = await this.elk.layout(elkGraph);
|
|
4401
4522
|
const mainFlowNodes = this.graphPreparer.identifyMainFlowNodes(sizedGraph, boundaryEventTargetIds);
|
|
4402
4523
|
this.mainFlowNormalizer.normalize(layoutedElkGraph, mainFlowNodes, boundaryEventTargetIds, sizedGraph);
|
|
4403
|
-
const movedNodes = this.boundaryEventHandler.identifyNodesToMove(layoutedElkGraph, boundaryEventInfo, sizedGraph,
|
|
4524
|
+
const movedNodes = this.boundaryEventHandler.identifyNodesToMove(layoutedElkGraph, boundaryEventInfo, sizedGraph, isDebugEnabled());
|
|
4404
4525
|
if (movedNodes.size > 0) {
|
|
4405
4526
|
this.boundaryEventHandler.applyNodeMoves(layoutedElkGraph, movedNodes);
|
|
4406
4527
|
const gatewayMoves = this.boundaryEventHandler.repositionConvergingGateways(
|
|
4407
4528
|
layoutedElkGraph,
|
|
4408
4529
|
movedNodes,
|
|
4409
4530
|
boundaryEventInfo,
|
|
4410
|
-
|
|
4531
|
+
isDebugEnabled()
|
|
4411
4532
|
);
|
|
4412
4533
|
if (gatewayMoves.size > 0) {
|
|
4413
4534
|
this.boundaryEventHandler.applyNodeMoves(layoutedElkGraph, gatewayMoves);
|
|
@@ -4416,7 +4537,7 @@ var ElkLayouter = class {
|
|
|
4416
4537
|
for (const [id, move] of gatewayMoves) {
|
|
4417
4538
|
movedNodes.set(id, move);
|
|
4418
4539
|
}
|
|
4419
|
-
this.boundaryEventHandler.recalculateEdgesForMovedNodes(layoutedElkGraph, movedNodes, boundaryEventInfo
|
|
4540
|
+
this.boundaryEventHandler.recalculateEdgesForMovedNodes(layoutedElkGraph, movedNodes, boundaryEventInfo);
|
|
4420
4541
|
}
|
|
4421
4542
|
this.artifactPositioner.reposition(layoutedElkGraph, artifactInfo);
|
|
4422
4543
|
this.laneArranger.rearrange(layoutedElkGraph, sizedGraph);
|
|
@@ -4690,7 +4811,7 @@ function adjustGatewayEndpoint(endpoint, adjacentPoint, gatewayBounds, isSource)
|
|
|
4690
4811
|
const gatewayCenterX = gatewayBounds.x + gatewayBounds.width / 2;
|
|
4691
4812
|
const gatewayCenterY = gatewayBounds.y + gatewayBounds.height / 2;
|
|
4692
4813
|
const tolerance = 1;
|
|
4693
|
-
if (
|
|
4814
|
+
if (isDebugEnabled()) {
|
|
4694
4815
|
console.log(`[BPMN] adjustGatewayEndpoint: isSource=${isSource}`);
|
|
4695
4816
|
console.log(` endpoint: (${endpoint.x}, ${endpoint.y})`);
|
|
4696
4817
|
console.log(` gatewayBounds: x=${gatewayBounds.x}, y=${gatewayBounds.y}, w=${gatewayBounds.width}, h=${gatewayBounds.height}`);
|
|
@@ -4702,22 +4823,22 @@ function adjustGatewayEndpoint(endpoint, adjacentPoint, gatewayBounds, isSource)
|
|
|
4702
4823
|
const topCorner = { x: gatewayCenterX, y: gatewayBounds.y };
|
|
4703
4824
|
const bottomCorner = { x: gatewayCenterX, y: gatewayBounds.y + gatewayBounds.height };
|
|
4704
4825
|
if (Math.abs(endpoint.x - gatewayBounds.x) < tolerance && Math.abs(endpoint.y - gatewayCenterY) < tolerance) {
|
|
4705
|
-
if (
|
|
4826
|
+
if (isDebugEnabled()) console.log(` -> Already at LEFT corner, no adjustment`);
|
|
4706
4827
|
return endpoint;
|
|
4707
4828
|
}
|
|
4708
4829
|
if (Math.abs(endpoint.x - (gatewayBounds.x + gatewayBounds.width)) < tolerance && Math.abs(endpoint.y - gatewayCenterY) < tolerance) {
|
|
4709
|
-
if (
|
|
4830
|
+
if (isDebugEnabled()) console.log(` -> Already at RIGHT corner, no adjustment`);
|
|
4710
4831
|
return endpoint;
|
|
4711
4832
|
}
|
|
4712
4833
|
if (Math.abs(endpoint.y - gatewayBounds.y) < tolerance && Math.abs(endpoint.x - gatewayCenterX) < tolerance) {
|
|
4713
|
-
if (
|
|
4834
|
+
if (isDebugEnabled()) console.log(` -> Already at TOP corner, no adjustment`);
|
|
4714
4835
|
return endpoint;
|
|
4715
4836
|
}
|
|
4716
4837
|
if (Math.abs(endpoint.y - (gatewayBounds.y + gatewayBounds.height)) < tolerance && Math.abs(endpoint.x - gatewayCenterX) < tolerance) {
|
|
4717
|
-
if (
|
|
4838
|
+
if (isDebugEnabled()) console.log(` -> Already at BOTTOM corner, no adjustment`);
|
|
4718
4839
|
return endpoint;
|
|
4719
4840
|
}
|
|
4720
|
-
if (
|
|
4841
|
+
if (isDebugEnabled()) {
|
|
4721
4842
|
console.log(` -> NOT at corner, will adjust`);
|
|
4722
4843
|
}
|
|
4723
4844
|
const result = calculateDiamondIntersection(
|
|
@@ -4728,7 +4849,7 @@ function adjustGatewayEndpoint(endpoint, adjacentPoint, gatewayBounds, isSource)
|
|
|
4728
4849
|
isSource,
|
|
4729
4850
|
adjacentPoint
|
|
4730
4851
|
);
|
|
4731
|
-
if (
|
|
4852
|
+
if (isDebugEnabled()) {
|
|
4732
4853
|
console.log(` -> Adjusted to: (${result.x}, ${result.y})`);
|
|
4733
4854
|
}
|
|
4734
4855
|
return result;
|
|
@@ -5033,7 +5154,7 @@ var DiagramBuilder = class {
|
|
|
5033
5154
|
const targetIsGateway = this.isGatewayType(targetNode?.type);
|
|
5034
5155
|
let waypoints = [];
|
|
5035
5156
|
const hasPreCalculatedSections = edge.sections && edge.sections.length > 0 && edge.sections[0]?.bendPoints && edge.sections[0].bendPoints.length > 0;
|
|
5036
|
-
if (
|
|
5157
|
+
if (isDebugEnabled() && bePosition) {
|
|
5037
5158
|
console.log(`[BPMN] buildEdge ${edge.id}: preCalculated=${hasPreCalculatedSections}`);
|
|
5038
5159
|
}
|
|
5039
5160
|
if (bePosition && targetPosition && !hasPreCalculatedSections) {
|
|
@@ -5108,6 +5229,7 @@ var DiagramBuilder = class {
|
|
|
5108
5229
|
}
|
|
5109
5230
|
}
|
|
5110
5231
|
}
|
|
5232
|
+
this.ensureOrthogonalWaypoints(waypoints);
|
|
5111
5233
|
const edgeModel = {
|
|
5112
5234
|
id: `${edge.id}_di`,
|
|
5113
5235
|
bpmnElement: edge.id,
|
|
@@ -5174,6 +5296,36 @@ var DiagramBuilder = class {
|
|
|
5174
5296
|
y: (lastPoint?.y ?? 0) - labelHeight - 4
|
|
5175
5297
|
};
|
|
5176
5298
|
}
|
|
5299
|
+
/**
|
|
5300
|
+
* Ensure all waypoint segments are orthogonal (horizontal or vertical)
|
|
5301
|
+
* If a diagonal segment is found, insert intermediate bend points to create
|
|
5302
|
+
* an L-shaped orthogonal path.
|
|
5303
|
+
*
|
|
5304
|
+
* Strategy: For diagonal segments, we use "horizontal first" - go horizontally
|
|
5305
|
+
* to the target X, then vertically to the target Y.
|
|
5306
|
+
*/
|
|
5307
|
+
ensureOrthogonalWaypoints(waypoints) {
|
|
5308
|
+
if (waypoints.length < 2) return;
|
|
5309
|
+
const tolerance = 1;
|
|
5310
|
+
let i = 0;
|
|
5311
|
+
while (i < waypoints.length - 1) {
|
|
5312
|
+
const current = waypoints[i];
|
|
5313
|
+
const next = waypoints[i + 1];
|
|
5314
|
+
if (!current || !next) {
|
|
5315
|
+
i++;
|
|
5316
|
+
continue;
|
|
5317
|
+
}
|
|
5318
|
+
const dx = Math.abs(next.x - current.x);
|
|
5319
|
+
const dy = Math.abs(next.y - current.y);
|
|
5320
|
+
if (dx > tolerance && dy > tolerance) {
|
|
5321
|
+
const bendPoint = { x: next.x, y: current.y };
|
|
5322
|
+
waypoints.splice(i + 1, 0, bendPoint);
|
|
5323
|
+
i++;
|
|
5324
|
+
} else {
|
|
5325
|
+
i++;
|
|
5326
|
+
}
|
|
5327
|
+
}
|
|
5328
|
+
}
|
|
5177
5329
|
};
|
|
5178
5330
|
|
|
5179
5331
|
// src/transform/model-builder.ts
|