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.js
CHANGED
|
@@ -298,7 +298,11 @@ function lineIntersection(p1, p2, p3, p4) {
|
|
|
298
298
|
}
|
|
299
299
|
|
|
300
300
|
// src/utils/debug.ts
|
|
301
|
-
var
|
|
301
|
+
var cliMode = false;
|
|
302
|
+
function isDebugEnabled() {
|
|
303
|
+
if (cliMode) return false;
|
|
304
|
+
return typeof process !== "undefined" && process.env?.["DEBUG"] === "true";
|
|
305
|
+
}
|
|
302
306
|
|
|
303
307
|
// src/layout/edge-routing/edge-fixer.ts
|
|
304
308
|
var EdgeFixer = class {
|
|
@@ -331,7 +335,7 @@ var EdgeFixer = class {
|
|
|
331
335
|
const isFlowNode = flowNodePatterns.some((pattern) => pattern.test(id));
|
|
332
336
|
const isPool = poolPatterns.some((pattern) => pattern.test(id));
|
|
333
337
|
const bpmn = node.bpmn;
|
|
334
|
-
if (
|
|
338
|
+
if (isDebugEnabled() && (id.includes("lane") || id.includes("pool") || id.includes("end_fast") || id.includes("gateway_fast"))) {
|
|
335
339
|
console.log(`[BPMN] EdgeFixer.collectNodePositions: id=${id}, offsetX=${offsetX}, offsetY=${offsetY}, bpmn=${JSON.stringify(bpmn)}`);
|
|
336
340
|
console.log(`[BPMN] node.x=${node.x}, node.y=${node.y}, isFlowNode=${isFlowNode}, isPool=${isPool}`);
|
|
337
341
|
}
|
|
@@ -369,6 +373,10 @@ var EdgeFixer = class {
|
|
|
369
373
|
const containerNodes = nodesByContainer.get(currentContainerId) ?? /* @__PURE__ */ new Map();
|
|
370
374
|
for (const edge of node.edges) {
|
|
371
375
|
if (edge.sections && edge.sections.length > 0) {
|
|
376
|
+
const hasPoolRelativeCoords = edge._poolRelativeCoords === true;
|
|
377
|
+
if (hasPoolRelativeCoords) {
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
372
380
|
this.fixEdgeIfCrossing(edge, containerNodes, containerOffsetX, containerOffsetY);
|
|
373
381
|
}
|
|
374
382
|
}
|
|
@@ -420,7 +428,7 @@ var EdgeFixer = class {
|
|
|
420
428
|
}
|
|
421
429
|
const targetPos = targetId ? nodePositions.get(targetId) : void 0;
|
|
422
430
|
const sourcePos = sourceId ? nodePositions.get(sourceId) : void 0;
|
|
423
|
-
if (
|
|
431
|
+
if (isDebugEnabled() && edge.id?.includes("back")) {
|
|
424
432
|
console.log(`[BPMN] Edge ${edge.id}: sourceId=${sourceId}, targetId=${targetId}`);
|
|
425
433
|
console.log(`[BPMN] Edge ${edge.id}: sourcePos=${JSON.stringify(sourcePos)}, targetPos=${JSON.stringify(targetPos)}`);
|
|
426
434
|
console.log(`[BPMN] Edge ${edge.id}: waypoints.length=${waypoints.length}`);
|
|
@@ -429,7 +437,7 @@ var EdgeFixer = class {
|
|
|
429
437
|
const lastWaypoint = waypoints[waypoints.length - 1];
|
|
430
438
|
const secondLastWaypoint = waypoints[waypoints.length - 2];
|
|
431
439
|
const isReturnEdge2 = targetPos.y + targetPos.height < sourcePos.y;
|
|
432
|
-
if (
|
|
440
|
+
if (isDebugEnabled() && edge.id?.includes("back")) {
|
|
433
441
|
console.log(`[BPMN] Edge ${edge.id}: isReturnEdge=${isReturnEdge2}`);
|
|
434
442
|
if (lastWaypoint) {
|
|
435
443
|
console.log(`[BPMN] Edge ${edge.id}: lastWaypoint=(${lastWaypoint.x},${lastWaypoint.y})`);
|
|
@@ -449,7 +457,7 @@ var EdgeFixer = class {
|
|
|
449
457
|
}
|
|
450
458
|
}
|
|
451
459
|
if (crossedNodes.length === 0) return;
|
|
452
|
-
if (
|
|
460
|
+
if (isDebugEnabled()) {
|
|
453
461
|
console.log(`[BPMN] Edge ${edge.id} crosses nodes: ${crossedNodes.join(", ")}`);
|
|
454
462
|
}
|
|
455
463
|
if (!sourcePos || !targetPos) return;
|
|
@@ -500,7 +508,7 @@ var EdgeFixer = class {
|
|
|
500
508
|
y: bp.y - containerOffsetY
|
|
501
509
|
}));
|
|
502
510
|
section.bendPoints = relativeBendPoints.length > 0 ? relativeBendPoints : void 0;
|
|
503
|
-
if (
|
|
511
|
+
if (isDebugEnabled()) {
|
|
504
512
|
console.log(`[BPMN] Fixed edge ${edge.id} with ${relativeBendPoints.length} bend points`);
|
|
505
513
|
}
|
|
506
514
|
}
|
|
@@ -1290,7 +1298,8 @@ function applyNodeMoves(graph, movedNodes) {
|
|
|
1290
1298
|
}
|
|
1291
1299
|
|
|
1292
1300
|
// src/layout/post-processing/boundary-event/edge-recalculator.ts
|
|
1293
|
-
function recalculateEdgesForMovedNodes(graph, movedNodes, boundaryEventInfo
|
|
1301
|
+
function recalculateEdgesForMovedNodes(graph, movedNodes, boundaryEventInfo) {
|
|
1302
|
+
const debug = isDebugEnabled();
|
|
1294
1303
|
const nodeMap = /* @__PURE__ */ new Map();
|
|
1295
1304
|
const buildNodeMap2 = (node) => {
|
|
1296
1305
|
nodeMap.set(node.id, node);
|
|
@@ -1367,7 +1376,8 @@ function recalculateEdgesForMovedNodes(graph, movedNodes, boundaryEventInfo, deb
|
|
|
1367
1376
|
};
|
|
1368
1377
|
processEdges(graph);
|
|
1369
1378
|
}
|
|
1370
|
-
function recalculateEdgeWithObstacleAvoidance(edge, source, target, obstacleIds, nodeMap
|
|
1379
|
+
function recalculateEdgeWithObstacleAvoidance(edge, source, target, obstacleIds, nodeMap) {
|
|
1380
|
+
const debug = isDebugEnabled();
|
|
1371
1381
|
const sx = source.x ?? 0;
|
|
1372
1382
|
const sy = source.y ?? 0;
|
|
1373
1383
|
const sw = source.width ?? 100;
|
|
@@ -1588,8 +1598,8 @@ var BoundaryEventHandler = class {
|
|
|
1588
1598
|
/**
|
|
1589
1599
|
* Recalculate edge waypoints for edges connected to moved nodes
|
|
1590
1600
|
*/
|
|
1591
|
-
recalculateEdgesForMovedNodes(graph, movedNodes, boundaryEventInfo
|
|
1592
|
-
recalculateEdgesForMovedNodes(graph, movedNodes, boundaryEventInfo
|
|
1601
|
+
recalculateEdgesForMovedNodes(graph, movedNodes, boundaryEventInfo) {
|
|
1602
|
+
recalculateEdgesForMovedNodes(graph, movedNodes, boundaryEventInfo);
|
|
1593
1603
|
}
|
|
1594
1604
|
};
|
|
1595
1605
|
|
|
@@ -2476,7 +2486,7 @@ var LaneArranger = class {
|
|
|
2476
2486
|
const targetId = edge.targets?.[0];
|
|
2477
2487
|
const sourcePos = sourceId ? nodePositions.get(sourceId) : void 0;
|
|
2478
2488
|
const targetPos = targetId ? nodePositions.get(targetId) : void 0;
|
|
2479
|
-
if (
|
|
2489
|
+
if (isDebugEnabled()) {
|
|
2480
2490
|
console.log(`[BPMN] recalculatePoolEdges ${edge.id}: source=${sourceId}, target=${targetId}`);
|
|
2481
2491
|
console.log(`[BPMN] sourcePos=${JSON.stringify(sourcePos)}`);
|
|
2482
2492
|
console.log(`[BPMN] targetPos=${JSON.stringify(targetPos)}`);
|
|
@@ -2486,18 +2496,26 @@ var LaneArranger = class {
|
|
|
2486
2496
|
const startY = sourcePos.y + sourcePos.height / 2;
|
|
2487
2497
|
const endX = targetPos.x;
|
|
2488
2498
|
const endY = targetPos.y + targetPos.height / 2;
|
|
2489
|
-
if (
|
|
2499
|
+
if (isDebugEnabled()) {
|
|
2490
2500
|
console.log(`[BPMN] startX=${startX}, startY=${startY}, endX=${endX}, endY=${endY}`);
|
|
2491
2501
|
}
|
|
2492
2502
|
const waypoints = [];
|
|
2493
2503
|
waypoints.push({ x: startX, y: startY });
|
|
2494
2504
|
if (Math.abs(startY - endY) > 10) {
|
|
2495
|
-
const midX = (
|
|
2505
|
+
const midX = this.findClearMidX(
|
|
2506
|
+
startX,
|
|
2507
|
+
endX,
|
|
2508
|
+
startY,
|
|
2509
|
+
endY,
|
|
2510
|
+
sourceId,
|
|
2511
|
+
targetId,
|
|
2512
|
+
nodePositions
|
|
2513
|
+
);
|
|
2496
2514
|
waypoints.push({ x: midX, y: startY });
|
|
2497
2515
|
waypoints.push({ x: midX, y: endY });
|
|
2498
2516
|
}
|
|
2499
2517
|
waypoints.push({ x: endX, y: endY });
|
|
2500
|
-
if (
|
|
2518
|
+
if (isDebugEnabled()) {
|
|
2501
2519
|
console.log(`[BPMN] waypoints=${JSON.stringify(waypoints)}`);
|
|
2502
2520
|
}
|
|
2503
2521
|
edge._poolRelativeCoords = true;
|
|
@@ -2510,6 +2528,109 @@ var LaneArranger = class {
|
|
|
2510
2528
|
}
|
|
2511
2529
|
}
|
|
2512
2530
|
}
|
|
2531
|
+
/**
|
|
2532
|
+
* Find a clear X position for vertical edge segment that avoids obstacles.
|
|
2533
|
+
* Checks all three segments of the L-shaped path:
|
|
2534
|
+
* 1. Horizontal from (startX, startY) to (midX, startY)
|
|
2535
|
+
* 2. Vertical from (midX, startY) to (midX, endY)
|
|
2536
|
+
* 3. Horizontal from (midX, endY) to (endX, endY)
|
|
2537
|
+
*/
|
|
2538
|
+
findClearMidX(startX, endX, startY, endY, sourceId, targetId, nodePositions) {
|
|
2539
|
+
const margin = 15;
|
|
2540
|
+
const minY = Math.min(startY, endY);
|
|
2541
|
+
const maxY = Math.max(startY, endY);
|
|
2542
|
+
const rangeMinX = Math.min(startX, endX);
|
|
2543
|
+
const rangeMaxX = Math.max(startX, endX);
|
|
2544
|
+
if (isDebugEnabled()) {
|
|
2545
|
+
console.log(`[BPMN] findClearMidX: startX=${startX}, endX=${endX}, startY=${startY}, endY=${endY}`);
|
|
2546
|
+
}
|
|
2547
|
+
const allObstacles = [];
|
|
2548
|
+
for (const [nodeId, pos] of nodePositions) {
|
|
2549
|
+
if (nodeId === sourceId || nodeId === targetId) continue;
|
|
2550
|
+
const nodeLeft = pos.x;
|
|
2551
|
+
const nodeRight = pos.x + pos.width;
|
|
2552
|
+
const nodeTop = pos.y;
|
|
2553
|
+
const nodeBottom = pos.y + pos.height;
|
|
2554
|
+
const xOverlap = nodeRight > rangeMinX && nodeLeft < rangeMaxX;
|
|
2555
|
+
const yOverlapVertical = nodeBottom > minY && nodeTop < maxY;
|
|
2556
|
+
const yContainsStartY = nodeTop <= startY && nodeBottom >= startY;
|
|
2557
|
+
const yContainsEndY = nodeTop <= endY && nodeBottom >= endY;
|
|
2558
|
+
if (xOverlap && (yOverlapVertical || yContainsStartY || yContainsEndY)) {
|
|
2559
|
+
allObstacles.push({
|
|
2560
|
+
x: nodeLeft,
|
|
2561
|
+
y: nodeTop,
|
|
2562
|
+
width: pos.width,
|
|
2563
|
+
height: pos.height,
|
|
2564
|
+
right: nodeRight,
|
|
2565
|
+
bottom: nodeBottom,
|
|
2566
|
+
id: nodeId
|
|
2567
|
+
});
|
|
2568
|
+
if (isDebugEnabled()) {
|
|
2569
|
+
console.log(`[BPMN] findClearMidX: obstacle ${nodeId}: x=[${nodeLeft}, ${nodeRight}], y=[${nodeTop}, ${nodeBottom}]`);
|
|
2570
|
+
}
|
|
2571
|
+
}
|
|
2572
|
+
}
|
|
2573
|
+
if (allObstacles.length === 0) {
|
|
2574
|
+
return (startX + endX) / 2;
|
|
2575
|
+
}
|
|
2576
|
+
const isValidMidX = (midX) => {
|
|
2577
|
+
for (const obs of allObstacles) {
|
|
2578
|
+
const seg1MinX = Math.min(startX, midX);
|
|
2579
|
+
const seg1MaxX = Math.max(startX, midX);
|
|
2580
|
+
if (obs.y <= startY && obs.bottom >= startY && // Y range contains startY
|
|
2581
|
+
obs.right > seg1MinX && obs.x < seg1MaxX) {
|
|
2582
|
+
return false;
|
|
2583
|
+
}
|
|
2584
|
+
if (obs.x <= midX && obs.right >= midX && // X range contains midX
|
|
2585
|
+
obs.bottom > minY && obs.y < maxY) {
|
|
2586
|
+
return false;
|
|
2587
|
+
}
|
|
2588
|
+
const seg2MinX = Math.min(midX, endX);
|
|
2589
|
+
const seg2MaxX = Math.max(midX, endX);
|
|
2590
|
+
if (obs.y <= endY && obs.bottom >= endY && // Y range contains endY
|
|
2591
|
+
obs.right > seg2MinX && obs.x < seg2MaxX) {
|
|
2592
|
+
return false;
|
|
2593
|
+
}
|
|
2594
|
+
}
|
|
2595
|
+
return true;
|
|
2596
|
+
};
|
|
2597
|
+
const candidates = [];
|
|
2598
|
+
candidates.push((startX + endX) / 2);
|
|
2599
|
+
candidates.push(startX + margin);
|
|
2600
|
+
candidates.push(endX - margin);
|
|
2601
|
+
for (const obs of allObstacles) {
|
|
2602
|
+
candidates.push(obs.x - margin);
|
|
2603
|
+
candidates.push(obs.right + margin);
|
|
2604
|
+
}
|
|
2605
|
+
const simpleMidX = (startX + endX) / 2;
|
|
2606
|
+
const validCandidates = candidates.filter((x) => x >= rangeMinX && x <= rangeMaxX).sort((a, b) => Math.abs(a - simpleMidX) - Math.abs(b - simpleMidX));
|
|
2607
|
+
for (const candidate of validCandidates) {
|
|
2608
|
+
if (isValidMidX(candidate)) {
|
|
2609
|
+
if (isDebugEnabled()) {
|
|
2610
|
+
console.log(`[BPMN] findClearMidX: found valid position ${candidate}`);
|
|
2611
|
+
}
|
|
2612
|
+
return candidate;
|
|
2613
|
+
}
|
|
2614
|
+
}
|
|
2615
|
+
const leftMost = Math.min(...allObstacles.map((o) => o.x)) - margin;
|
|
2616
|
+
const rightMost = Math.max(...allObstacles.map((o) => o.right)) + margin;
|
|
2617
|
+
if (leftMost >= rangeMinX && isValidMidX(leftMost)) {
|
|
2618
|
+
if (isDebugEnabled()) {
|
|
2619
|
+
console.log(`[BPMN] findClearMidX: routing left of all obstacles at ${leftMost}`);
|
|
2620
|
+
}
|
|
2621
|
+
return leftMost;
|
|
2622
|
+
}
|
|
2623
|
+
if (rightMost <= rangeMaxX && isValidMidX(rightMost)) {
|
|
2624
|
+
if (isDebugEnabled()) {
|
|
2625
|
+
console.log(`[BPMN] findClearMidX: routing right of all obstacles at ${rightMost}`);
|
|
2626
|
+
}
|
|
2627
|
+
return rightMost;
|
|
2628
|
+
}
|
|
2629
|
+
if (isDebugEnabled()) {
|
|
2630
|
+
console.log(`[BPMN] findClearMidX: no valid route found, using midpoint ${simpleMidX}`);
|
|
2631
|
+
}
|
|
2632
|
+
return simpleMidX;
|
|
2633
|
+
}
|
|
2513
2634
|
};
|
|
2514
2635
|
|
|
2515
2636
|
// src/layout/post-processing/pool-arranger.ts
|
|
@@ -2590,7 +2711,7 @@ var PoolArranger = class {
|
|
|
2590
2711
|
pool.y = currentY;
|
|
2591
2712
|
if (isBlackBox) {
|
|
2592
2713
|
pool.width = maxPoolWidth;
|
|
2593
|
-
pool.height =
|
|
2714
|
+
pool.height = 60;
|
|
2594
2715
|
} else if (hasLanes) {
|
|
2595
2716
|
pool.width = maxPoolWidth;
|
|
2596
2717
|
} else {
|
|
@@ -3005,7 +3126,7 @@ var GatewayEdgeAdjuster = class {
|
|
|
3005
3126
|
const gateways = /* @__PURE__ */ new Map();
|
|
3006
3127
|
this.collectGateways(layoutedGraph, originalGraph, gateways, 0, 0);
|
|
3007
3128
|
if (gateways.size === 0) return;
|
|
3008
|
-
if (
|
|
3129
|
+
if (isDebugEnabled()) {
|
|
3009
3130
|
console.log(`[BPMN] GatewayEdgeAdjuster: Found ${gateways.size} gateways`);
|
|
3010
3131
|
for (const [id, info] of gateways) {
|
|
3011
3132
|
console.log(`[BPMN] - ${id}: bounds=(${info.bounds.x},${info.bounds.y},${info.bounds.width},${info.bounds.height})`);
|
|
@@ -3092,7 +3213,7 @@ var GatewayEdgeAdjuster = class {
|
|
|
3092
3213
|
const section = edge.sections[0];
|
|
3093
3214
|
const sourceId = edge.sources?.[0];
|
|
3094
3215
|
const targetId = edge.targets?.[0];
|
|
3095
|
-
if (
|
|
3216
|
+
if (isDebugEnabled()) {
|
|
3096
3217
|
console.log(`[BPMN] GatewayEdgeAdjuster: Processing edge ${edge.id}, offset=(${offsetX},${offsetY})`);
|
|
3097
3218
|
console.log(`[BPMN] sourceId=${sourceId}, targetId=${targetId}`);
|
|
3098
3219
|
console.log(`[BPMN] startPoint=(${section.startPoint.x},${section.startPoint.y}), endPoint=(${section.endPoint.x},${section.endPoint.y})`);
|
|
@@ -3104,7 +3225,7 @@ var GatewayEdgeAdjuster = class {
|
|
|
3104
3225
|
}
|
|
3105
3226
|
const targetGateway = targetId ? gateways.get(targetId) : void 0;
|
|
3106
3227
|
if (targetGateway) {
|
|
3107
|
-
if (
|
|
3228
|
+
if (isDebugEnabled()) {
|
|
3108
3229
|
console.log(`[BPMN] target gateway: ${targetId}, bounds=(${targetGateway.bounds.x},${targetGateway.bounds.y})`);
|
|
3109
3230
|
console.log(`[BPMN] left corner: (${targetGateway.corners.left.x},${targetGateway.corners.left.y})`);
|
|
3110
3231
|
}
|
|
@@ -3175,7 +3296,7 @@ var GatewayEdgeAdjuster = class {
|
|
|
3175
3296
|
lastBend.x = newEnd.x;
|
|
3176
3297
|
}
|
|
3177
3298
|
}
|
|
3178
|
-
if (
|
|
3299
|
+
if (isDebugEnabled()) {
|
|
3179
3300
|
console.log(`[BPMN] GatewayEdgeAdjuster: Adjusted edge ${edge.id} endpoint from (${endX},${endY}) to (${targetCorner.x},${targetCorner.y})`);
|
|
3180
3301
|
}
|
|
3181
3302
|
} else {
|
|
@@ -3189,7 +3310,7 @@ var GatewayEdgeAdjuster = class {
|
|
|
3189
3310
|
x: intersectionPoint.x - offsetX,
|
|
3190
3311
|
y: intersectionPoint.y - offsetY
|
|
3191
3312
|
};
|
|
3192
|
-
if (
|
|
3313
|
+
if (isDebugEnabled()) {
|
|
3193
3314
|
console.log(`[BPMN] GatewayEdgeAdjuster: Adjusted edge ${edge.id} endpoint to diamond intersection (${intersectionPoint.x},${intersectionPoint.y})`);
|
|
3194
3315
|
}
|
|
3195
3316
|
}
|
|
@@ -3449,7 +3570,7 @@ var ElkGraphPreparer = class {
|
|
|
3449
3570
|
for (const startId of startEvents) {
|
|
3450
3571
|
traverseMainFlow(startId);
|
|
3451
3572
|
}
|
|
3452
|
-
if (
|
|
3573
|
+
if (isDebugEnabled()) {
|
|
3453
3574
|
console.log(`[BPMN] Main flow nodes: ${Array.from(mainFlowNodes).join(", ")}`);
|
|
3454
3575
|
}
|
|
3455
3576
|
return mainFlowNodes;
|
|
@@ -3784,7 +3905,7 @@ var ResultMerger = class {
|
|
|
3784
3905
|
return originalEdges.map((origEdge) => {
|
|
3785
3906
|
const layoutedEdge = layoutedEdgeMap.get(origEdge.id);
|
|
3786
3907
|
if (layoutedEdge) {
|
|
3787
|
-
if (
|
|
3908
|
+
if (isDebugEnabled() && layoutedEdge.sections?.[0]?.bendPoints?.length) {
|
|
3788
3909
|
console.log(`[BPMN] Merge ${origEdge.id}: bendPoints=${JSON.stringify(layoutedEdge.sections[0].bendPoints)}`);
|
|
3789
3910
|
}
|
|
3790
3911
|
const mergedEdge = {
|
|
@@ -3922,7 +4043,7 @@ var MainFlowNormalizer = class {
|
|
|
3922
4043
|
return;
|
|
3923
4044
|
}
|
|
3924
4045
|
const offsetY = currentMinY - TARGET_MAIN_FLOW_Y;
|
|
3925
|
-
if (
|
|
4046
|
+
if (isDebugEnabled()) {
|
|
3926
4047
|
console.log(`[BPMN] Normalizing main flow: currentMinY=${currentMinY}, offsetY=${offsetY}`);
|
|
3927
4048
|
console.log(`[BPMN] Upstream nodes: ${upstreamMainFlow.map((n) => n.id).join(", ")}`);
|
|
3928
4049
|
console.log(`[BPMN] Downstream nodes: ${downstreamMainFlow.map((n) => n.id).join(", ")}`);
|
|
@@ -3930,7 +4051,7 @@ var MainFlowNormalizer = class {
|
|
|
3930
4051
|
for (const node of otherUpstreamNodes) {
|
|
3931
4052
|
if (node.y !== void 0) {
|
|
3932
4053
|
node.y -= offsetY;
|
|
3933
|
-
if (
|
|
4054
|
+
if (isDebugEnabled()) {
|
|
3934
4055
|
console.log(`[BPMN] Shifted upstream ${node.id} to y=${node.y}`);
|
|
3935
4056
|
}
|
|
3936
4057
|
}
|
|
@@ -3943,14 +4064,14 @@ var MainFlowNormalizer = class {
|
|
|
3943
4064
|
const predecessorCenterY = predecessor.y + (predecessor.height ?? 80) / 2;
|
|
3944
4065
|
const endNodeCenterY = (endNode.height ?? 36) / 2;
|
|
3945
4066
|
endNode.y = predecessorCenterY - endNodeCenterY;
|
|
3946
|
-
if (
|
|
4067
|
+
if (isDebugEnabled()) {
|
|
3947
4068
|
console.log(`[BPMN] Aligned endEvent ${endNode.id} with predecessor ${predecessorId}: y=${endNode.y}`);
|
|
3948
4069
|
}
|
|
3949
4070
|
}
|
|
3950
4071
|
} else {
|
|
3951
4072
|
if (endNode.y !== void 0) {
|
|
3952
4073
|
endNode.y -= offsetY;
|
|
3953
|
-
if (
|
|
4074
|
+
if (isDebugEnabled()) {
|
|
3954
4075
|
console.log(`[BPMN] Shifted upstream ${endNode.id} to y=${endNode.y} (no predecessor found)`);
|
|
3955
4076
|
}
|
|
3956
4077
|
}
|
|
@@ -3978,7 +4099,7 @@ var MainFlowNormalizer = class {
|
|
|
3978
4099
|
const newY = prevBottom + MIN_SPACING;
|
|
3979
4100
|
currNode.y = newY;
|
|
3980
4101
|
adjustedEndEvents.set(currNode.id, newY);
|
|
3981
|
-
if (
|
|
4102
|
+
if (isDebugEnabled()) {
|
|
3982
4103
|
console.log(`[BPMN] Adjusted overlapping endEvent ${currNode.id} at x=${x}: y=${currNode.y}`);
|
|
3983
4104
|
}
|
|
3984
4105
|
}
|
|
@@ -4002,7 +4123,7 @@ var MainFlowNormalizer = class {
|
|
|
4002
4123
|
for (const node of downstreamMainFlow) {
|
|
4003
4124
|
if (node.y !== void 0) {
|
|
4004
4125
|
node.y -= downstreamOffsetY;
|
|
4005
|
-
if (
|
|
4126
|
+
if (isDebugEnabled()) {
|
|
4006
4127
|
console.log(`[BPMN] Shifted downstream ${node.id} to y=${node.y}`);
|
|
4007
4128
|
}
|
|
4008
4129
|
}
|
|
@@ -4184,20 +4305,20 @@ var MainFlowNormalizer = class {
|
|
|
4184
4305
|
lastBend.y = newTargetY;
|
|
4185
4306
|
section.endPoint.y = newTargetY;
|
|
4186
4307
|
edgesWithAdjustedEndpoint.add(edge.id);
|
|
4187
|
-
if (
|
|
4308
|
+
if (isDebugEnabled()) {
|
|
4188
4309
|
console.log(`[BPMN] Updated edge ${edge.id} last bendPoint and endpoint to y=${newTargetY}`);
|
|
4189
4310
|
}
|
|
4190
4311
|
} else {
|
|
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} endpoint to y=${newTargetY}`);
|
|
4195
4316
|
}
|
|
4196
4317
|
}
|
|
4197
4318
|
} else if (section.endPoint) {
|
|
4198
4319
|
section.endPoint.y = newTargetY;
|
|
4199
4320
|
edgesWithAdjustedEndpoint.add(edge.id);
|
|
4200
|
-
if (
|
|
4321
|
+
if (isDebugEnabled()) {
|
|
4201
4322
|
console.log(`[BPMN] Updated edge ${edge.id} endpoint to y=${newTargetY}`);
|
|
4202
4323
|
}
|
|
4203
4324
|
}
|
|
@@ -4311,7 +4432,7 @@ var GatewayPropagator = class {
|
|
|
4311
4432
|
offset: 0,
|
|
4312
4433
|
newX
|
|
4313
4434
|
});
|
|
4314
|
-
if (
|
|
4435
|
+
if (isDebugEnabled()) {
|
|
4315
4436
|
console.log(`[BPMN] Propagating gateway movement to ${targetId}: x ${currentX} -> ${newX}`);
|
|
4316
4437
|
}
|
|
4317
4438
|
this.propagateDownstreamX(targetId, newX, targetNode.width ?? 100, nodeMap, edgeMap, mainFlowNodes, gatewayMoves);
|
|
@@ -4339,7 +4460,7 @@ var GatewayPropagator = class {
|
|
|
4339
4460
|
offset: 0,
|
|
4340
4461
|
newX
|
|
4341
4462
|
});
|
|
4342
|
-
if (
|
|
4463
|
+
if (isDebugEnabled()) {
|
|
4343
4464
|
console.log(`[BPMN] Propagating X to ${targetId}: x ${currentX} -> ${newX}`);
|
|
4344
4465
|
}
|
|
4345
4466
|
this.propagateDownstreamX(targetId, newX, targetNode.width ?? 100, nodeMap, edgeMap, mainFlowNodes, moves);
|
|
@@ -4394,14 +4515,14 @@ var ElkLayouter = class {
|
|
|
4394
4515
|
const layoutedElkGraph = await this.elk.layout(elkGraph);
|
|
4395
4516
|
const mainFlowNodes = this.graphPreparer.identifyMainFlowNodes(sizedGraph, boundaryEventTargetIds);
|
|
4396
4517
|
this.mainFlowNormalizer.normalize(layoutedElkGraph, mainFlowNodes, boundaryEventTargetIds, sizedGraph);
|
|
4397
|
-
const movedNodes = this.boundaryEventHandler.identifyNodesToMove(layoutedElkGraph, boundaryEventInfo, sizedGraph,
|
|
4518
|
+
const movedNodes = this.boundaryEventHandler.identifyNodesToMove(layoutedElkGraph, boundaryEventInfo, sizedGraph, isDebugEnabled());
|
|
4398
4519
|
if (movedNodes.size > 0) {
|
|
4399
4520
|
this.boundaryEventHandler.applyNodeMoves(layoutedElkGraph, movedNodes);
|
|
4400
4521
|
const gatewayMoves = this.boundaryEventHandler.repositionConvergingGateways(
|
|
4401
4522
|
layoutedElkGraph,
|
|
4402
4523
|
movedNodes,
|
|
4403
4524
|
boundaryEventInfo,
|
|
4404
|
-
|
|
4525
|
+
isDebugEnabled()
|
|
4405
4526
|
);
|
|
4406
4527
|
if (gatewayMoves.size > 0) {
|
|
4407
4528
|
this.boundaryEventHandler.applyNodeMoves(layoutedElkGraph, gatewayMoves);
|
|
@@ -4410,7 +4531,7 @@ var ElkLayouter = class {
|
|
|
4410
4531
|
for (const [id, move] of gatewayMoves) {
|
|
4411
4532
|
movedNodes.set(id, move);
|
|
4412
4533
|
}
|
|
4413
|
-
this.boundaryEventHandler.recalculateEdgesForMovedNodes(layoutedElkGraph, movedNodes, boundaryEventInfo
|
|
4534
|
+
this.boundaryEventHandler.recalculateEdgesForMovedNodes(layoutedElkGraph, movedNodes, boundaryEventInfo);
|
|
4414
4535
|
}
|
|
4415
4536
|
this.artifactPositioner.reposition(layoutedElkGraph, artifactInfo);
|
|
4416
4537
|
this.laneArranger.rearrange(layoutedElkGraph, sizedGraph);
|
|
@@ -4684,7 +4805,7 @@ function adjustGatewayEndpoint(endpoint, adjacentPoint, gatewayBounds, isSource)
|
|
|
4684
4805
|
const gatewayCenterX = gatewayBounds.x + gatewayBounds.width / 2;
|
|
4685
4806
|
const gatewayCenterY = gatewayBounds.y + gatewayBounds.height / 2;
|
|
4686
4807
|
const tolerance = 1;
|
|
4687
|
-
if (
|
|
4808
|
+
if (isDebugEnabled()) {
|
|
4688
4809
|
console.log(`[BPMN] adjustGatewayEndpoint: isSource=${isSource}`);
|
|
4689
4810
|
console.log(` endpoint: (${endpoint.x}, ${endpoint.y})`);
|
|
4690
4811
|
console.log(` gatewayBounds: x=${gatewayBounds.x}, y=${gatewayBounds.y}, w=${gatewayBounds.width}, h=${gatewayBounds.height}`);
|
|
@@ -4696,22 +4817,22 @@ function adjustGatewayEndpoint(endpoint, adjacentPoint, gatewayBounds, isSource)
|
|
|
4696
4817
|
const topCorner = { x: gatewayCenterX, y: gatewayBounds.y };
|
|
4697
4818
|
const bottomCorner = { x: gatewayCenterX, y: gatewayBounds.y + gatewayBounds.height };
|
|
4698
4819
|
if (Math.abs(endpoint.x - gatewayBounds.x) < tolerance && Math.abs(endpoint.y - gatewayCenterY) < tolerance) {
|
|
4699
|
-
if (
|
|
4820
|
+
if (isDebugEnabled()) console.log(` -> Already at LEFT corner, no adjustment`);
|
|
4700
4821
|
return endpoint;
|
|
4701
4822
|
}
|
|
4702
4823
|
if (Math.abs(endpoint.x - (gatewayBounds.x + gatewayBounds.width)) < tolerance && Math.abs(endpoint.y - gatewayCenterY) < tolerance) {
|
|
4703
|
-
if (
|
|
4824
|
+
if (isDebugEnabled()) console.log(` -> Already at RIGHT corner, no adjustment`);
|
|
4704
4825
|
return endpoint;
|
|
4705
4826
|
}
|
|
4706
4827
|
if (Math.abs(endpoint.y - gatewayBounds.y) < tolerance && Math.abs(endpoint.x - gatewayCenterX) < tolerance) {
|
|
4707
|
-
if (
|
|
4828
|
+
if (isDebugEnabled()) console.log(` -> Already at TOP corner, no adjustment`);
|
|
4708
4829
|
return endpoint;
|
|
4709
4830
|
}
|
|
4710
4831
|
if (Math.abs(endpoint.y - (gatewayBounds.y + gatewayBounds.height)) < tolerance && Math.abs(endpoint.x - gatewayCenterX) < tolerance) {
|
|
4711
|
-
if (
|
|
4832
|
+
if (isDebugEnabled()) console.log(` -> Already at BOTTOM corner, no adjustment`);
|
|
4712
4833
|
return endpoint;
|
|
4713
4834
|
}
|
|
4714
|
-
if (
|
|
4835
|
+
if (isDebugEnabled()) {
|
|
4715
4836
|
console.log(` -> NOT at corner, will adjust`);
|
|
4716
4837
|
}
|
|
4717
4838
|
const result = calculateDiamondIntersection(
|
|
@@ -4722,7 +4843,7 @@ function adjustGatewayEndpoint(endpoint, adjacentPoint, gatewayBounds, isSource)
|
|
|
4722
4843
|
isSource,
|
|
4723
4844
|
adjacentPoint
|
|
4724
4845
|
);
|
|
4725
|
-
if (
|
|
4846
|
+
if (isDebugEnabled()) {
|
|
4726
4847
|
console.log(` -> Adjusted to: (${result.x}, ${result.y})`);
|
|
4727
4848
|
}
|
|
4728
4849
|
return result;
|
|
@@ -5027,7 +5148,7 @@ var DiagramBuilder = class {
|
|
|
5027
5148
|
const targetIsGateway = this.isGatewayType(targetNode?.type);
|
|
5028
5149
|
let waypoints = [];
|
|
5029
5150
|
const hasPreCalculatedSections = edge.sections && edge.sections.length > 0 && edge.sections[0]?.bendPoints && edge.sections[0].bendPoints.length > 0;
|
|
5030
|
-
if (
|
|
5151
|
+
if (isDebugEnabled() && bePosition) {
|
|
5031
5152
|
console.log(`[BPMN] buildEdge ${edge.id}: preCalculated=${hasPreCalculatedSections}`);
|
|
5032
5153
|
}
|
|
5033
5154
|
if (bePosition && targetPosition && !hasPreCalculatedSections) {
|
|
@@ -5102,6 +5223,7 @@ var DiagramBuilder = class {
|
|
|
5102
5223
|
}
|
|
5103
5224
|
}
|
|
5104
5225
|
}
|
|
5226
|
+
this.ensureOrthogonalWaypoints(waypoints);
|
|
5105
5227
|
const edgeModel = {
|
|
5106
5228
|
id: `${edge.id}_di`,
|
|
5107
5229
|
bpmnElement: edge.id,
|
|
@@ -5168,6 +5290,36 @@ var DiagramBuilder = class {
|
|
|
5168
5290
|
y: (lastPoint?.y ?? 0) - labelHeight - 4
|
|
5169
5291
|
};
|
|
5170
5292
|
}
|
|
5293
|
+
/**
|
|
5294
|
+
* Ensure all waypoint segments are orthogonal (horizontal or vertical)
|
|
5295
|
+
* If a diagonal segment is found, insert intermediate bend points to create
|
|
5296
|
+
* an L-shaped orthogonal path.
|
|
5297
|
+
*
|
|
5298
|
+
* Strategy: For diagonal segments, we use "horizontal first" - go horizontally
|
|
5299
|
+
* to the target X, then vertically to the target Y.
|
|
5300
|
+
*/
|
|
5301
|
+
ensureOrthogonalWaypoints(waypoints) {
|
|
5302
|
+
if (waypoints.length < 2) return;
|
|
5303
|
+
const tolerance = 1;
|
|
5304
|
+
let i = 0;
|
|
5305
|
+
while (i < waypoints.length - 1) {
|
|
5306
|
+
const current = waypoints[i];
|
|
5307
|
+
const next = waypoints[i + 1];
|
|
5308
|
+
if (!current || !next) {
|
|
5309
|
+
i++;
|
|
5310
|
+
continue;
|
|
5311
|
+
}
|
|
5312
|
+
const dx = Math.abs(next.x - current.x);
|
|
5313
|
+
const dy = Math.abs(next.y - current.y);
|
|
5314
|
+
if (dx > tolerance && dy > tolerance) {
|
|
5315
|
+
const bendPoint = { x: next.x, y: current.y };
|
|
5316
|
+
waypoints.splice(i + 1, 0, bendPoint);
|
|
5317
|
+
i++;
|
|
5318
|
+
} else {
|
|
5319
|
+
i++;
|
|
5320
|
+
}
|
|
5321
|
+
}
|
|
5322
|
+
}
|
|
5171
5323
|
};
|
|
5172
5324
|
|
|
5173
5325
|
// src/transform/model-builder.ts
|