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.mjs
CHANGED
|
@@ -249,7 +249,11 @@ function lineIntersection(p1, p2, p3, p4) {
|
|
|
249
249
|
}
|
|
250
250
|
|
|
251
251
|
// src/utils/debug.ts
|
|
252
|
-
var
|
|
252
|
+
var cliMode = false;
|
|
253
|
+
function isDebugEnabled() {
|
|
254
|
+
if (cliMode) return false;
|
|
255
|
+
return typeof process !== "undefined" && process.env?.["DEBUG"] === "true";
|
|
256
|
+
}
|
|
253
257
|
|
|
254
258
|
// src/layout/edge-routing/edge-fixer.ts
|
|
255
259
|
var EdgeFixer = class {
|
|
@@ -282,7 +286,7 @@ var EdgeFixer = class {
|
|
|
282
286
|
const isFlowNode = flowNodePatterns.some((pattern) => pattern.test(id));
|
|
283
287
|
const isPool = poolPatterns.some((pattern) => pattern.test(id));
|
|
284
288
|
const bpmn = node.bpmn;
|
|
285
|
-
if (
|
|
289
|
+
if (isDebugEnabled() && (id.includes("lane") || id.includes("pool") || id.includes("end_fast") || id.includes("gateway_fast"))) {
|
|
286
290
|
console.log(`[BPMN] EdgeFixer.collectNodePositions: id=${id}, offsetX=${offsetX}, offsetY=${offsetY}, bpmn=${JSON.stringify(bpmn)}`);
|
|
287
291
|
console.log(`[BPMN] node.x=${node.x}, node.y=${node.y}, isFlowNode=${isFlowNode}, isPool=${isPool}`);
|
|
288
292
|
}
|
|
@@ -320,6 +324,10 @@ var EdgeFixer = class {
|
|
|
320
324
|
const containerNodes = nodesByContainer.get(currentContainerId) ?? /* @__PURE__ */ new Map();
|
|
321
325
|
for (const edge of node.edges) {
|
|
322
326
|
if (edge.sections && edge.sections.length > 0) {
|
|
327
|
+
const hasPoolRelativeCoords = edge._poolRelativeCoords === true;
|
|
328
|
+
if (hasPoolRelativeCoords) {
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
323
331
|
this.fixEdgeIfCrossing(edge, containerNodes, containerOffsetX, containerOffsetY);
|
|
324
332
|
}
|
|
325
333
|
}
|
|
@@ -371,7 +379,7 @@ var EdgeFixer = class {
|
|
|
371
379
|
}
|
|
372
380
|
const targetPos = targetId ? nodePositions.get(targetId) : void 0;
|
|
373
381
|
const sourcePos = sourceId ? nodePositions.get(sourceId) : void 0;
|
|
374
|
-
if (
|
|
382
|
+
if (isDebugEnabled() && edge.id?.includes("back")) {
|
|
375
383
|
console.log(`[BPMN] Edge ${edge.id}: sourceId=${sourceId}, targetId=${targetId}`);
|
|
376
384
|
console.log(`[BPMN] Edge ${edge.id}: sourcePos=${JSON.stringify(sourcePos)}, targetPos=${JSON.stringify(targetPos)}`);
|
|
377
385
|
console.log(`[BPMN] Edge ${edge.id}: waypoints.length=${waypoints.length}`);
|
|
@@ -380,7 +388,7 @@ var EdgeFixer = class {
|
|
|
380
388
|
const lastWaypoint = waypoints[waypoints.length - 1];
|
|
381
389
|
const secondLastWaypoint = waypoints[waypoints.length - 2];
|
|
382
390
|
const isReturnEdge2 = targetPos.y + targetPos.height < sourcePos.y;
|
|
383
|
-
if (
|
|
391
|
+
if (isDebugEnabled() && edge.id?.includes("back")) {
|
|
384
392
|
console.log(`[BPMN] Edge ${edge.id}: isReturnEdge=${isReturnEdge2}`);
|
|
385
393
|
if (lastWaypoint) {
|
|
386
394
|
console.log(`[BPMN] Edge ${edge.id}: lastWaypoint=(${lastWaypoint.x},${lastWaypoint.y})`);
|
|
@@ -400,7 +408,7 @@ var EdgeFixer = class {
|
|
|
400
408
|
}
|
|
401
409
|
}
|
|
402
410
|
if (crossedNodes.length === 0) return;
|
|
403
|
-
if (
|
|
411
|
+
if (isDebugEnabled()) {
|
|
404
412
|
console.log(`[BPMN] Edge ${edge.id} crosses nodes: ${crossedNodes.join(", ")}`);
|
|
405
413
|
}
|
|
406
414
|
if (!sourcePos || !targetPos) return;
|
|
@@ -451,7 +459,7 @@ var EdgeFixer = class {
|
|
|
451
459
|
y: bp.y - containerOffsetY
|
|
452
460
|
}));
|
|
453
461
|
section.bendPoints = relativeBendPoints.length > 0 ? relativeBendPoints : void 0;
|
|
454
|
-
if (
|
|
462
|
+
if (isDebugEnabled()) {
|
|
455
463
|
console.log(`[BPMN] Fixed edge ${edge.id} with ${relativeBendPoints.length} bend points`);
|
|
456
464
|
}
|
|
457
465
|
}
|
|
@@ -1241,7 +1249,8 @@ function applyNodeMoves(graph, movedNodes) {
|
|
|
1241
1249
|
}
|
|
1242
1250
|
|
|
1243
1251
|
// src/layout/post-processing/boundary-event/edge-recalculator.ts
|
|
1244
|
-
function recalculateEdgesForMovedNodes(graph, movedNodes, boundaryEventInfo
|
|
1252
|
+
function recalculateEdgesForMovedNodes(graph, movedNodes, boundaryEventInfo) {
|
|
1253
|
+
const debug = isDebugEnabled();
|
|
1245
1254
|
const nodeMap = /* @__PURE__ */ new Map();
|
|
1246
1255
|
const buildNodeMap2 = (node) => {
|
|
1247
1256
|
nodeMap.set(node.id, node);
|
|
@@ -1318,7 +1327,8 @@ function recalculateEdgesForMovedNodes(graph, movedNodes, boundaryEventInfo, deb
|
|
|
1318
1327
|
};
|
|
1319
1328
|
processEdges(graph);
|
|
1320
1329
|
}
|
|
1321
|
-
function recalculateEdgeWithObstacleAvoidance(edge, source, target, obstacleIds, nodeMap
|
|
1330
|
+
function recalculateEdgeWithObstacleAvoidance(edge, source, target, obstacleIds, nodeMap) {
|
|
1331
|
+
const debug = isDebugEnabled();
|
|
1322
1332
|
const sx = source.x ?? 0;
|
|
1323
1333
|
const sy = source.y ?? 0;
|
|
1324
1334
|
const sw = source.width ?? 100;
|
|
@@ -1539,8 +1549,8 @@ var BoundaryEventHandler = class {
|
|
|
1539
1549
|
/**
|
|
1540
1550
|
* Recalculate edge waypoints for edges connected to moved nodes
|
|
1541
1551
|
*/
|
|
1542
|
-
recalculateEdgesForMovedNodes(graph, movedNodes, boundaryEventInfo
|
|
1543
|
-
recalculateEdgesForMovedNodes(graph, movedNodes, boundaryEventInfo
|
|
1552
|
+
recalculateEdgesForMovedNodes(graph, movedNodes, boundaryEventInfo) {
|
|
1553
|
+
recalculateEdgesForMovedNodes(graph, movedNodes, boundaryEventInfo);
|
|
1544
1554
|
}
|
|
1545
1555
|
};
|
|
1546
1556
|
|
|
@@ -2427,7 +2437,7 @@ var LaneArranger = class {
|
|
|
2427
2437
|
const targetId = edge.targets?.[0];
|
|
2428
2438
|
const sourcePos = sourceId ? nodePositions.get(sourceId) : void 0;
|
|
2429
2439
|
const targetPos = targetId ? nodePositions.get(targetId) : void 0;
|
|
2430
|
-
if (
|
|
2440
|
+
if (isDebugEnabled()) {
|
|
2431
2441
|
console.log(`[BPMN] recalculatePoolEdges ${edge.id}: source=${sourceId}, target=${targetId}`);
|
|
2432
2442
|
console.log(`[BPMN] sourcePos=${JSON.stringify(sourcePos)}`);
|
|
2433
2443
|
console.log(`[BPMN] targetPos=${JSON.stringify(targetPos)}`);
|
|
@@ -2437,18 +2447,26 @@ var LaneArranger = class {
|
|
|
2437
2447
|
const startY = sourcePos.y + sourcePos.height / 2;
|
|
2438
2448
|
const endX = targetPos.x;
|
|
2439
2449
|
const endY = targetPos.y + targetPos.height / 2;
|
|
2440
|
-
if (
|
|
2450
|
+
if (isDebugEnabled()) {
|
|
2441
2451
|
console.log(`[BPMN] startX=${startX}, startY=${startY}, endX=${endX}, endY=${endY}`);
|
|
2442
2452
|
}
|
|
2443
2453
|
const waypoints = [];
|
|
2444
2454
|
waypoints.push({ x: startX, y: startY });
|
|
2445
2455
|
if (Math.abs(startY - endY) > 10) {
|
|
2446
|
-
const midX = (
|
|
2456
|
+
const midX = this.findClearMidX(
|
|
2457
|
+
startX,
|
|
2458
|
+
endX,
|
|
2459
|
+
startY,
|
|
2460
|
+
endY,
|
|
2461
|
+
sourceId,
|
|
2462
|
+
targetId,
|
|
2463
|
+
nodePositions
|
|
2464
|
+
);
|
|
2447
2465
|
waypoints.push({ x: midX, y: startY });
|
|
2448
2466
|
waypoints.push({ x: midX, y: endY });
|
|
2449
2467
|
}
|
|
2450
2468
|
waypoints.push({ x: endX, y: endY });
|
|
2451
|
-
if (
|
|
2469
|
+
if (isDebugEnabled()) {
|
|
2452
2470
|
console.log(`[BPMN] waypoints=${JSON.stringify(waypoints)}`);
|
|
2453
2471
|
}
|
|
2454
2472
|
edge._poolRelativeCoords = true;
|
|
@@ -2461,6 +2479,109 @@ var LaneArranger = class {
|
|
|
2461
2479
|
}
|
|
2462
2480
|
}
|
|
2463
2481
|
}
|
|
2482
|
+
/**
|
|
2483
|
+
* Find a clear X position for vertical edge segment that avoids obstacles.
|
|
2484
|
+
* Checks all three segments of the L-shaped path:
|
|
2485
|
+
* 1. Horizontal from (startX, startY) to (midX, startY)
|
|
2486
|
+
* 2. Vertical from (midX, startY) to (midX, endY)
|
|
2487
|
+
* 3. Horizontal from (midX, endY) to (endX, endY)
|
|
2488
|
+
*/
|
|
2489
|
+
findClearMidX(startX, endX, startY, endY, sourceId, targetId, nodePositions) {
|
|
2490
|
+
const margin = 15;
|
|
2491
|
+
const minY = Math.min(startY, endY);
|
|
2492
|
+
const maxY = Math.max(startY, endY);
|
|
2493
|
+
const rangeMinX = Math.min(startX, endX);
|
|
2494
|
+
const rangeMaxX = Math.max(startX, endX);
|
|
2495
|
+
if (isDebugEnabled()) {
|
|
2496
|
+
console.log(`[BPMN] findClearMidX: startX=${startX}, endX=${endX}, startY=${startY}, endY=${endY}`);
|
|
2497
|
+
}
|
|
2498
|
+
const allObstacles = [];
|
|
2499
|
+
for (const [nodeId, pos] of nodePositions) {
|
|
2500
|
+
if (nodeId === sourceId || nodeId === targetId) continue;
|
|
2501
|
+
const nodeLeft = pos.x;
|
|
2502
|
+
const nodeRight = pos.x + pos.width;
|
|
2503
|
+
const nodeTop = pos.y;
|
|
2504
|
+
const nodeBottom = pos.y + pos.height;
|
|
2505
|
+
const xOverlap = nodeRight > rangeMinX && nodeLeft < rangeMaxX;
|
|
2506
|
+
const yOverlapVertical = nodeBottom > minY && nodeTop < maxY;
|
|
2507
|
+
const yContainsStartY = nodeTop <= startY && nodeBottom >= startY;
|
|
2508
|
+
const yContainsEndY = nodeTop <= endY && nodeBottom >= endY;
|
|
2509
|
+
if (xOverlap && (yOverlapVertical || yContainsStartY || yContainsEndY)) {
|
|
2510
|
+
allObstacles.push({
|
|
2511
|
+
x: nodeLeft,
|
|
2512
|
+
y: nodeTop,
|
|
2513
|
+
width: pos.width,
|
|
2514
|
+
height: pos.height,
|
|
2515
|
+
right: nodeRight,
|
|
2516
|
+
bottom: nodeBottom,
|
|
2517
|
+
id: nodeId
|
|
2518
|
+
});
|
|
2519
|
+
if (isDebugEnabled()) {
|
|
2520
|
+
console.log(`[BPMN] findClearMidX: obstacle ${nodeId}: x=[${nodeLeft}, ${nodeRight}], y=[${nodeTop}, ${nodeBottom}]`);
|
|
2521
|
+
}
|
|
2522
|
+
}
|
|
2523
|
+
}
|
|
2524
|
+
if (allObstacles.length === 0) {
|
|
2525
|
+
return (startX + endX) / 2;
|
|
2526
|
+
}
|
|
2527
|
+
const isValidMidX = (midX) => {
|
|
2528
|
+
for (const obs of allObstacles) {
|
|
2529
|
+
const seg1MinX = Math.min(startX, midX);
|
|
2530
|
+
const seg1MaxX = Math.max(startX, midX);
|
|
2531
|
+
if (obs.y <= startY && obs.bottom >= startY && // Y range contains startY
|
|
2532
|
+
obs.right > seg1MinX && obs.x < seg1MaxX) {
|
|
2533
|
+
return false;
|
|
2534
|
+
}
|
|
2535
|
+
if (obs.x <= midX && obs.right >= midX && // X range contains midX
|
|
2536
|
+
obs.bottom > minY && obs.y < maxY) {
|
|
2537
|
+
return false;
|
|
2538
|
+
}
|
|
2539
|
+
const seg2MinX = Math.min(midX, endX);
|
|
2540
|
+
const seg2MaxX = Math.max(midX, endX);
|
|
2541
|
+
if (obs.y <= endY && obs.bottom >= endY && // Y range contains endY
|
|
2542
|
+
obs.right > seg2MinX && obs.x < seg2MaxX) {
|
|
2543
|
+
return false;
|
|
2544
|
+
}
|
|
2545
|
+
}
|
|
2546
|
+
return true;
|
|
2547
|
+
};
|
|
2548
|
+
const candidates = [];
|
|
2549
|
+
candidates.push((startX + endX) / 2);
|
|
2550
|
+
candidates.push(startX + margin);
|
|
2551
|
+
candidates.push(endX - margin);
|
|
2552
|
+
for (const obs of allObstacles) {
|
|
2553
|
+
candidates.push(obs.x - margin);
|
|
2554
|
+
candidates.push(obs.right + margin);
|
|
2555
|
+
}
|
|
2556
|
+
const simpleMidX = (startX + endX) / 2;
|
|
2557
|
+
const validCandidates = candidates.filter((x) => x >= rangeMinX && x <= rangeMaxX).sort((a, b) => Math.abs(a - simpleMidX) - Math.abs(b - simpleMidX));
|
|
2558
|
+
for (const candidate of validCandidates) {
|
|
2559
|
+
if (isValidMidX(candidate)) {
|
|
2560
|
+
if (isDebugEnabled()) {
|
|
2561
|
+
console.log(`[BPMN] findClearMidX: found valid position ${candidate}`);
|
|
2562
|
+
}
|
|
2563
|
+
return candidate;
|
|
2564
|
+
}
|
|
2565
|
+
}
|
|
2566
|
+
const leftMost = Math.min(...allObstacles.map((o) => o.x)) - margin;
|
|
2567
|
+
const rightMost = Math.max(...allObstacles.map((o) => o.right)) + margin;
|
|
2568
|
+
if (leftMost >= rangeMinX && isValidMidX(leftMost)) {
|
|
2569
|
+
if (isDebugEnabled()) {
|
|
2570
|
+
console.log(`[BPMN] findClearMidX: routing left of all obstacles at ${leftMost}`);
|
|
2571
|
+
}
|
|
2572
|
+
return leftMost;
|
|
2573
|
+
}
|
|
2574
|
+
if (rightMost <= rangeMaxX && isValidMidX(rightMost)) {
|
|
2575
|
+
if (isDebugEnabled()) {
|
|
2576
|
+
console.log(`[BPMN] findClearMidX: routing right of all obstacles at ${rightMost}`);
|
|
2577
|
+
}
|
|
2578
|
+
return rightMost;
|
|
2579
|
+
}
|
|
2580
|
+
if (isDebugEnabled()) {
|
|
2581
|
+
console.log(`[BPMN] findClearMidX: no valid route found, using midpoint ${simpleMidX}`);
|
|
2582
|
+
}
|
|
2583
|
+
return simpleMidX;
|
|
2584
|
+
}
|
|
2464
2585
|
};
|
|
2465
2586
|
|
|
2466
2587
|
// src/layout/post-processing/pool-arranger.ts
|
|
@@ -2541,7 +2662,7 @@ var PoolArranger = class {
|
|
|
2541
2662
|
pool.y = currentY;
|
|
2542
2663
|
if (isBlackBox) {
|
|
2543
2664
|
pool.width = maxPoolWidth;
|
|
2544
|
-
pool.height =
|
|
2665
|
+
pool.height = 60;
|
|
2545
2666
|
} else if (hasLanes) {
|
|
2546
2667
|
pool.width = maxPoolWidth;
|
|
2547
2668
|
} else {
|
|
@@ -2956,7 +3077,7 @@ var GatewayEdgeAdjuster = class {
|
|
|
2956
3077
|
const gateways = /* @__PURE__ */ new Map();
|
|
2957
3078
|
this.collectGateways(layoutedGraph, originalGraph, gateways, 0, 0);
|
|
2958
3079
|
if (gateways.size === 0) return;
|
|
2959
|
-
if (
|
|
3080
|
+
if (isDebugEnabled()) {
|
|
2960
3081
|
console.log(`[BPMN] GatewayEdgeAdjuster: Found ${gateways.size} gateways`);
|
|
2961
3082
|
for (const [id, info] of gateways) {
|
|
2962
3083
|
console.log(`[BPMN] - ${id}: bounds=(${info.bounds.x},${info.bounds.y},${info.bounds.width},${info.bounds.height})`);
|
|
@@ -3043,7 +3164,7 @@ var GatewayEdgeAdjuster = class {
|
|
|
3043
3164
|
const section = edge.sections[0];
|
|
3044
3165
|
const sourceId = edge.sources?.[0];
|
|
3045
3166
|
const targetId = edge.targets?.[0];
|
|
3046
|
-
if (
|
|
3167
|
+
if (isDebugEnabled()) {
|
|
3047
3168
|
console.log(`[BPMN] GatewayEdgeAdjuster: Processing edge ${edge.id}, offset=(${offsetX},${offsetY})`);
|
|
3048
3169
|
console.log(`[BPMN] sourceId=${sourceId}, targetId=${targetId}`);
|
|
3049
3170
|
console.log(`[BPMN] startPoint=(${section.startPoint.x},${section.startPoint.y}), endPoint=(${section.endPoint.x},${section.endPoint.y})`);
|
|
@@ -3055,7 +3176,7 @@ var GatewayEdgeAdjuster = class {
|
|
|
3055
3176
|
}
|
|
3056
3177
|
const targetGateway = targetId ? gateways.get(targetId) : void 0;
|
|
3057
3178
|
if (targetGateway) {
|
|
3058
|
-
if (
|
|
3179
|
+
if (isDebugEnabled()) {
|
|
3059
3180
|
console.log(`[BPMN] target gateway: ${targetId}, bounds=(${targetGateway.bounds.x},${targetGateway.bounds.y})`);
|
|
3060
3181
|
console.log(`[BPMN] left corner: (${targetGateway.corners.left.x},${targetGateway.corners.left.y})`);
|
|
3061
3182
|
}
|
|
@@ -3126,7 +3247,7 @@ var GatewayEdgeAdjuster = class {
|
|
|
3126
3247
|
lastBend.x = newEnd.x;
|
|
3127
3248
|
}
|
|
3128
3249
|
}
|
|
3129
|
-
if (
|
|
3250
|
+
if (isDebugEnabled()) {
|
|
3130
3251
|
console.log(`[BPMN] GatewayEdgeAdjuster: Adjusted edge ${edge.id} endpoint from (${endX},${endY}) to (${targetCorner.x},${targetCorner.y})`);
|
|
3131
3252
|
}
|
|
3132
3253
|
} else {
|
|
@@ -3140,7 +3261,7 @@ var GatewayEdgeAdjuster = class {
|
|
|
3140
3261
|
x: intersectionPoint.x - offsetX,
|
|
3141
3262
|
y: intersectionPoint.y - offsetY
|
|
3142
3263
|
};
|
|
3143
|
-
if (
|
|
3264
|
+
if (isDebugEnabled()) {
|
|
3144
3265
|
console.log(`[BPMN] GatewayEdgeAdjuster: Adjusted edge ${edge.id} endpoint to diamond intersection (${intersectionPoint.x},${intersectionPoint.y})`);
|
|
3145
3266
|
}
|
|
3146
3267
|
}
|
|
@@ -3400,7 +3521,7 @@ var ElkGraphPreparer = class {
|
|
|
3400
3521
|
for (const startId of startEvents) {
|
|
3401
3522
|
traverseMainFlow(startId);
|
|
3402
3523
|
}
|
|
3403
|
-
if (
|
|
3524
|
+
if (isDebugEnabled()) {
|
|
3404
3525
|
console.log(`[BPMN] Main flow nodes: ${Array.from(mainFlowNodes).join(", ")}`);
|
|
3405
3526
|
}
|
|
3406
3527
|
return mainFlowNodes;
|
|
@@ -3735,7 +3856,7 @@ var ResultMerger = class {
|
|
|
3735
3856
|
return originalEdges.map((origEdge) => {
|
|
3736
3857
|
const layoutedEdge = layoutedEdgeMap.get(origEdge.id);
|
|
3737
3858
|
if (layoutedEdge) {
|
|
3738
|
-
if (
|
|
3859
|
+
if (isDebugEnabled() && layoutedEdge.sections?.[0]?.bendPoints?.length) {
|
|
3739
3860
|
console.log(`[BPMN] Merge ${origEdge.id}: bendPoints=${JSON.stringify(layoutedEdge.sections[0].bendPoints)}`);
|
|
3740
3861
|
}
|
|
3741
3862
|
const mergedEdge = {
|
|
@@ -3873,7 +3994,7 @@ var MainFlowNormalizer = class {
|
|
|
3873
3994
|
return;
|
|
3874
3995
|
}
|
|
3875
3996
|
const offsetY = currentMinY - TARGET_MAIN_FLOW_Y;
|
|
3876
|
-
if (
|
|
3997
|
+
if (isDebugEnabled()) {
|
|
3877
3998
|
console.log(`[BPMN] Normalizing main flow: currentMinY=${currentMinY}, offsetY=${offsetY}`);
|
|
3878
3999
|
console.log(`[BPMN] Upstream nodes: ${upstreamMainFlow.map((n) => n.id).join(", ")}`);
|
|
3879
4000
|
console.log(`[BPMN] Downstream nodes: ${downstreamMainFlow.map((n) => n.id).join(", ")}`);
|
|
@@ -3881,7 +4002,7 @@ var MainFlowNormalizer = class {
|
|
|
3881
4002
|
for (const node of otherUpstreamNodes) {
|
|
3882
4003
|
if (node.y !== void 0) {
|
|
3883
4004
|
node.y -= offsetY;
|
|
3884
|
-
if (
|
|
4005
|
+
if (isDebugEnabled()) {
|
|
3885
4006
|
console.log(`[BPMN] Shifted upstream ${node.id} to y=${node.y}`);
|
|
3886
4007
|
}
|
|
3887
4008
|
}
|
|
@@ -3894,14 +4015,14 @@ var MainFlowNormalizer = class {
|
|
|
3894
4015
|
const predecessorCenterY = predecessor.y + (predecessor.height ?? 80) / 2;
|
|
3895
4016
|
const endNodeCenterY = (endNode.height ?? 36) / 2;
|
|
3896
4017
|
endNode.y = predecessorCenterY - endNodeCenterY;
|
|
3897
|
-
if (
|
|
4018
|
+
if (isDebugEnabled()) {
|
|
3898
4019
|
console.log(`[BPMN] Aligned endEvent ${endNode.id} with predecessor ${predecessorId}: y=${endNode.y}`);
|
|
3899
4020
|
}
|
|
3900
4021
|
}
|
|
3901
4022
|
} else {
|
|
3902
4023
|
if (endNode.y !== void 0) {
|
|
3903
4024
|
endNode.y -= offsetY;
|
|
3904
|
-
if (
|
|
4025
|
+
if (isDebugEnabled()) {
|
|
3905
4026
|
console.log(`[BPMN] Shifted upstream ${endNode.id} to y=${endNode.y} (no predecessor found)`);
|
|
3906
4027
|
}
|
|
3907
4028
|
}
|
|
@@ -3929,7 +4050,7 @@ var MainFlowNormalizer = class {
|
|
|
3929
4050
|
const newY = prevBottom + MIN_SPACING;
|
|
3930
4051
|
currNode.y = newY;
|
|
3931
4052
|
adjustedEndEvents.set(currNode.id, newY);
|
|
3932
|
-
if (
|
|
4053
|
+
if (isDebugEnabled()) {
|
|
3933
4054
|
console.log(`[BPMN] Adjusted overlapping endEvent ${currNode.id} at x=${x}: y=${currNode.y}`);
|
|
3934
4055
|
}
|
|
3935
4056
|
}
|
|
@@ -3953,7 +4074,7 @@ var MainFlowNormalizer = class {
|
|
|
3953
4074
|
for (const node of downstreamMainFlow) {
|
|
3954
4075
|
if (node.y !== void 0) {
|
|
3955
4076
|
node.y -= downstreamOffsetY;
|
|
3956
|
-
if (
|
|
4077
|
+
if (isDebugEnabled()) {
|
|
3957
4078
|
console.log(`[BPMN] Shifted downstream ${node.id} to y=${node.y}`);
|
|
3958
4079
|
}
|
|
3959
4080
|
}
|
|
@@ -4135,20 +4256,20 @@ var MainFlowNormalizer = class {
|
|
|
4135
4256
|
lastBend.y = newTargetY;
|
|
4136
4257
|
section.endPoint.y = newTargetY;
|
|
4137
4258
|
edgesWithAdjustedEndpoint.add(edge.id);
|
|
4138
|
-
if (
|
|
4259
|
+
if (isDebugEnabled()) {
|
|
4139
4260
|
console.log(`[BPMN] Updated edge ${edge.id} last bendPoint and endpoint to y=${newTargetY}`);
|
|
4140
4261
|
}
|
|
4141
4262
|
} else {
|
|
4142
4263
|
section.endPoint.y = newTargetY;
|
|
4143
4264
|
edgesWithAdjustedEndpoint.add(edge.id);
|
|
4144
|
-
if (
|
|
4265
|
+
if (isDebugEnabled()) {
|
|
4145
4266
|
console.log(`[BPMN] Updated edge ${edge.id} endpoint to y=${newTargetY}`);
|
|
4146
4267
|
}
|
|
4147
4268
|
}
|
|
4148
4269
|
} else if (section.endPoint) {
|
|
4149
4270
|
section.endPoint.y = newTargetY;
|
|
4150
4271
|
edgesWithAdjustedEndpoint.add(edge.id);
|
|
4151
|
-
if (
|
|
4272
|
+
if (isDebugEnabled()) {
|
|
4152
4273
|
console.log(`[BPMN] Updated edge ${edge.id} endpoint to y=${newTargetY}`);
|
|
4153
4274
|
}
|
|
4154
4275
|
}
|
|
@@ -4262,7 +4383,7 @@ var GatewayPropagator = class {
|
|
|
4262
4383
|
offset: 0,
|
|
4263
4384
|
newX
|
|
4264
4385
|
});
|
|
4265
|
-
if (
|
|
4386
|
+
if (isDebugEnabled()) {
|
|
4266
4387
|
console.log(`[BPMN] Propagating gateway movement to ${targetId}: x ${currentX} -> ${newX}`);
|
|
4267
4388
|
}
|
|
4268
4389
|
this.propagateDownstreamX(targetId, newX, targetNode.width ?? 100, nodeMap, edgeMap, mainFlowNodes, gatewayMoves);
|
|
@@ -4290,7 +4411,7 @@ var GatewayPropagator = class {
|
|
|
4290
4411
|
offset: 0,
|
|
4291
4412
|
newX
|
|
4292
4413
|
});
|
|
4293
|
-
if (
|
|
4414
|
+
if (isDebugEnabled()) {
|
|
4294
4415
|
console.log(`[BPMN] Propagating X to ${targetId}: x ${currentX} -> ${newX}`);
|
|
4295
4416
|
}
|
|
4296
4417
|
this.propagateDownstreamX(targetId, newX, targetNode.width ?? 100, nodeMap, edgeMap, mainFlowNodes, moves);
|
|
@@ -4345,14 +4466,14 @@ var ElkLayouter = class {
|
|
|
4345
4466
|
const layoutedElkGraph = await this.elk.layout(elkGraph);
|
|
4346
4467
|
const mainFlowNodes = this.graphPreparer.identifyMainFlowNodes(sizedGraph, boundaryEventTargetIds);
|
|
4347
4468
|
this.mainFlowNormalizer.normalize(layoutedElkGraph, mainFlowNodes, boundaryEventTargetIds, sizedGraph);
|
|
4348
|
-
const movedNodes = this.boundaryEventHandler.identifyNodesToMove(layoutedElkGraph, boundaryEventInfo, sizedGraph,
|
|
4469
|
+
const movedNodes = this.boundaryEventHandler.identifyNodesToMove(layoutedElkGraph, boundaryEventInfo, sizedGraph, isDebugEnabled());
|
|
4349
4470
|
if (movedNodes.size > 0) {
|
|
4350
4471
|
this.boundaryEventHandler.applyNodeMoves(layoutedElkGraph, movedNodes);
|
|
4351
4472
|
const gatewayMoves = this.boundaryEventHandler.repositionConvergingGateways(
|
|
4352
4473
|
layoutedElkGraph,
|
|
4353
4474
|
movedNodes,
|
|
4354
4475
|
boundaryEventInfo,
|
|
4355
|
-
|
|
4476
|
+
isDebugEnabled()
|
|
4356
4477
|
);
|
|
4357
4478
|
if (gatewayMoves.size > 0) {
|
|
4358
4479
|
this.boundaryEventHandler.applyNodeMoves(layoutedElkGraph, gatewayMoves);
|
|
@@ -4361,7 +4482,7 @@ var ElkLayouter = class {
|
|
|
4361
4482
|
for (const [id, move] of gatewayMoves) {
|
|
4362
4483
|
movedNodes.set(id, move);
|
|
4363
4484
|
}
|
|
4364
|
-
this.boundaryEventHandler.recalculateEdgesForMovedNodes(layoutedElkGraph, movedNodes, boundaryEventInfo
|
|
4485
|
+
this.boundaryEventHandler.recalculateEdgesForMovedNodes(layoutedElkGraph, movedNodes, boundaryEventInfo);
|
|
4365
4486
|
}
|
|
4366
4487
|
this.artifactPositioner.reposition(layoutedElkGraph, artifactInfo);
|
|
4367
4488
|
this.laneArranger.rearrange(layoutedElkGraph, sizedGraph);
|
|
@@ -4635,7 +4756,7 @@ function adjustGatewayEndpoint(endpoint, adjacentPoint, gatewayBounds, isSource)
|
|
|
4635
4756
|
const gatewayCenterX = gatewayBounds.x + gatewayBounds.width / 2;
|
|
4636
4757
|
const gatewayCenterY = gatewayBounds.y + gatewayBounds.height / 2;
|
|
4637
4758
|
const tolerance = 1;
|
|
4638
|
-
if (
|
|
4759
|
+
if (isDebugEnabled()) {
|
|
4639
4760
|
console.log(`[BPMN] adjustGatewayEndpoint: isSource=${isSource}`);
|
|
4640
4761
|
console.log(` endpoint: (${endpoint.x}, ${endpoint.y})`);
|
|
4641
4762
|
console.log(` gatewayBounds: x=${gatewayBounds.x}, y=${gatewayBounds.y}, w=${gatewayBounds.width}, h=${gatewayBounds.height}`);
|
|
@@ -4647,22 +4768,22 @@ function adjustGatewayEndpoint(endpoint, adjacentPoint, gatewayBounds, isSource)
|
|
|
4647
4768
|
const topCorner = { x: gatewayCenterX, y: gatewayBounds.y };
|
|
4648
4769
|
const bottomCorner = { x: gatewayCenterX, y: gatewayBounds.y + gatewayBounds.height };
|
|
4649
4770
|
if (Math.abs(endpoint.x - gatewayBounds.x) < tolerance && Math.abs(endpoint.y - gatewayCenterY) < tolerance) {
|
|
4650
|
-
if (
|
|
4771
|
+
if (isDebugEnabled()) console.log(` -> Already at LEFT corner, no adjustment`);
|
|
4651
4772
|
return endpoint;
|
|
4652
4773
|
}
|
|
4653
4774
|
if (Math.abs(endpoint.x - (gatewayBounds.x + gatewayBounds.width)) < tolerance && Math.abs(endpoint.y - gatewayCenterY) < tolerance) {
|
|
4654
|
-
if (
|
|
4775
|
+
if (isDebugEnabled()) console.log(` -> Already at RIGHT corner, no adjustment`);
|
|
4655
4776
|
return endpoint;
|
|
4656
4777
|
}
|
|
4657
4778
|
if (Math.abs(endpoint.y - gatewayBounds.y) < tolerance && Math.abs(endpoint.x - gatewayCenterX) < tolerance) {
|
|
4658
|
-
if (
|
|
4779
|
+
if (isDebugEnabled()) console.log(` -> Already at TOP corner, no adjustment`);
|
|
4659
4780
|
return endpoint;
|
|
4660
4781
|
}
|
|
4661
4782
|
if (Math.abs(endpoint.y - (gatewayBounds.y + gatewayBounds.height)) < tolerance && Math.abs(endpoint.x - gatewayCenterX) < tolerance) {
|
|
4662
|
-
if (
|
|
4783
|
+
if (isDebugEnabled()) console.log(` -> Already at BOTTOM corner, no adjustment`);
|
|
4663
4784
|
return endpoint;
|
|
4664
4785
|
}
|
|
4665
|
-
if (
|
|
4786
|
+
if (isDebugEnabled()) {
|
|
4666
4787
|
console.log(` -> NOT at corner, will adjust`);
|
|
4667
4788
|
}
|
|
4668
4789
|
const result = calculateDiamondIntersection(
|
|
@@ -4673,7 +4794,7 @@ function adjustGatewayEndpoint(endpoint, adjacentPoint, gatewayBounds, isSource)
|
|
|
4673
4794
|
isSource,
|
|
4674
4795
|
adjacentPoint
|
|
4675
4796
|
);
|
|
4676
|
-
if (
|
|
4797
|
+
if (isDebugEnabled()) {
|
|
4677
4798
|
console.log(` -> Adjusted to: (${result.x}, ${result.y})`);
|
|
4678
4799
|
}
|
|
4679
4800
|
return result;
|
|
@@ -4978,7 +5099,7 @@ var DiagramBuilder = class {
|
|
|
4978
5099
|
const targetIsGateway = this.isGatewayType(targetNode?.type);
|
|
4979
5100
|
let waypoints = [];
|
|
4980
5101
|
const hasPreCalculatedSections = edge.sections && edge.sections.length > 0 && edge.sections[0]?.bendPoints && edge.sections[0].bendPoints.length > 0;
|
|
4981
|
-
if (
|
|
5102
|
+
if (isDebugEnabled() && bePosition) {
|
|
4982
5103
|
console.log(`[BPMN] buildEdge ${edge.id}: preCalculated=${hasPreCalculatedSections}`);
|
|
4983
5104
|
}
|
|
4984
5105
|
if (bePosition && targetPosition && !hasPreCalculatedSections) {
|
|
@@ -5053,6 +5174,7 @@ var DiagramBuilder = class {
|
|
|
5053
5174
|
}
|
|
5054
5175
|
}
|
|
5055
5176
|
}
|
|
5177
|
+
this.ensureOrthogonalWaypoints(waypoints);
|
|
5056
5178
|
const edgeModel = {
|
|
5057
5179
|
id: `${edge.id}_di`,
|
|
5058
5180
|
bpmnElement: edge.id,
|
|
@@ -5119,6 +5241,36 @@ var DiagramBuilder = class {
|
|
|
5119
5241
|
y: (lastPoint?.y ?? 0) - labelHeight - 4
|
|
5120
5242
|
};
|
|
5121
5243
|
}
|
|
5244
|
+
/**
|
|
5245
|
+
* Ensure all waypoint segments are orthogonal (horizontal or vertical)
|
|
5246
|
+
* If a diagonal segment is found, insert intermediate bend points to create
|
|
5247
|
+
* an L-shaped orthogonal path.
|
|
5248
|
+
*
|
|
5249
|
+
* Strategy: For diagonal segments, we use "horizontal first" - go horizontally
|
|
5250
|
+
* to the target X, then vertically to the target Y.
|
|
5251
|
+
*/
|
|
5252
|
+
ensureOrthogonalWaypoints(waypoints) {
|
|
5253
|
+
if (waypoints.length < 2) return;
|
|
5254
|
+
const tolerance = 1;
|
|
5255
|
+
let i = 0;
|
|
5256
|
+
while (i < waypoints.length - 1) {
|
|
5257
|
+
const current = waypoints[i];
|
|
5258
|
+
const next = waypoints[i + 1];
|
|
5259
|
+
if (!current || !next) {
|
|
5260
|
+
i++;
|
|
5261
|
+
continue;
|
|
5262
|
+
}
|
|
5263
|
+
const dx = Math.abs(next.x - current.x);
|
|
5264
|
+
const dy = Math.abs(next.y - current.y);
|
|
5265
|
+
if (dx > tolerance && dy > tolerance) {
|
|
5266
|
+
const bendPoint = { x: next.x, y: current.y };
|
|
5267
|
+
waypoints.splice(i + 1, 0, bendPoint);
|
|
5268
|
+
i++;
|
|
5269
|
+
} else {
|
|
5270
|
+
i++;
|
|
5271
|
+
}
|
|
5272
|
+
}
|
|
5273
|
+
}
|
|
5122
5274
|
};
|
|
5123
5275
|
|
|
5124
5276
|
// src/transform/model-builder.ts
|