@crazyhappyone/auto-graph 0.1.0 → 0.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/cli/index.cjs +352 -31
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +352 -31
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +353 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -2
- package/dist/index.d.ts +16 -2
- package/dist/index.js +353 -32
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2071,7 +2071,7 @@ function point(value) {
|
|
|
2071
2071
|
return { x: value.x, y: value.y };
|
|
2072
2072
|
}
|
|
2073
2073
|
var directionSchema = zod.z.enum(["TB", "LR", "BT", "RL"]);
|
|
2074
|
-
var routeKindSchema = zod.z.enum(["orthogonal", "straight"]);
|
|
2074
|
+
var routeKindSchema = zod.z.enum(["orthogonal", "straight", "obstacle-avoiding"]);
|
|
2075
2075
|
var outputFormatSchema = zod.z.enum(["svg", "excalidraw"]);
|
|
2076
2076
|
var edgeStrokeStyleSchema = zod.z.enum(["solid", "dashed"]);
|
|
2077
2077
|
var edgeArrowheadSchema = zod.z.enum(["triangle", "hollowTriangle"]);
|
|
@@ -3750,6 +3750,15 @@ function indent(value) {
|
|
|
3750
3750
|
function indentLines(values) {
|
|
3751
3751
|
return values.map(indent);
|
|
3752
3752
|
}
|
|
3753
|
+
|
|
3754
|
+
// src/ir/diagnostics.ts
|
|
3755
|
+
var DELIVERABILITY_DIAGNOSTIC_CODES = /* @__PURE__ */ new Set([
|
|
3756
|
+
"constraints.locked-target-not-moved",
|
|
3757
|
+
"routing.evidence.crossing_forbidden",
|
|
3758
|
+
"routing.obstacle.unavoidable",
|
|
3759
|
+
"route_obstacle_fallback",
|
|
3760
|
+
"routing.text-clearance.unresolved"
|
|
3761
|
+
]);
|
|
3753
3762
|
var DEFAULT_OPTIONS = {
|
|
3754
3763
|
nodesep: 80,
|
|
3755
3764
|
ranksep: 100,
|
|
@@ -3948,6 +3957,51 @@ function routeEdge(input) {
|
|
|
3948
3957
|
)
|
|
3949
3958
|
);
|
|
3950
3959
|
if (hardClearCandidate !== void 0) {
|
|
3960
|
+
let bestPoints2 = hardClearCandidate.points;
|
|
3961
|
+
if (input.kind === "obstacle-avoiding") {
|
|
3962
|
+
const allObstacles = [...softObstacles, ...hardObstacles];
|
|
3963
|
+
for (const candidate of candidateRoutes) {
|
|
3964
|
+
if (routeCrossesBoxes(candidate.points, hardObstacles) || routeIntersectsEndpointInteriors(
|
|
3965
|
+
candidate.points,
|
|
3966
|
+
candidate.endpointObstacles
|
|
3967
|
+
)) {
|
|
3968
|
+
continue;
|
|
3969
|
+
}
|
|
3970
|
+
const rerouted2 = greedyRerouteAroundObstacles(
|
|
3971
|
+
candidate.points,
|
|
3972
|
+
allObstacles,
|
|
3973
|
+
3
|
|
3974
|
+
);
|
|
3975
|
+
if (!routeCrossesBoxes(rerouted2, allObstacles) && !routeIntersectsEndpointInteriors(
|
|
3976
|
+
rerouted2,
|
|
3977
|
+
candidate.endpointObstacles
|
|
3978
|
+
)) {
|
|
3979
|
+
return {
|
|
3980
|
+
points: finalizeRoute(
|
|
3981
|
+
rerouted2,
|
|
3982
|
+
softObstacles,
|
|
3983
|
+
hardObstacles,
|
|
3984
|
+
diagnostics
|
|
3985
|
+
),
|
|
3986
|
+
diagnostics
|
|
3987
|
+
};
|
|
3988
|
+
}
|
|
3989
|
+
}
|
|
3990
|
+
const rerouted = greedyRerouteAroundObstacles(
|
|
3991
|
+
bestPoints2,
|
|
3992
|
+
allObstacles,
|
|
3993
|
+
3
|
|
3994
|
+
);
|
|
3995
|
+
const reroutedAvoidsEndpointInteriors = !routeIntersectsEndpointInteriors(
|
|
3996
|
+
rerouted,
|
|
3997
|
+
hardClearCandidate.endpointObstacles
|
|
3998
|
+
);
|
|
3999
|
+
if (reroutedAvoidsEndpointInteriors) {
|
|
4000
|
+
if (routeCrossesBoxes(rerouted, hardObstacles) && !routeCrossesBoxes(bestPoints2, hardObstacles)) ; else {
|
|
4001
|
+
bestPoints2 = rerouted;
|
|
4002
|
+
}
|
|
4003
|
+
}
|
|
4004
|
+
}
|
|
3951
4005
|
diagnostics.push({
|
|
3952
4006
|
severity: "warning",
|
|
3953
4007
|
code: "routing.obstacle.unavoidable",
|
|
@@ -3955,7 +4009,7 @@ function routeEdge(input) {
|
|
|
3955
4009
|
});
|
|
3956
4010
|
return {
|
|
3957
4011
|
points: finalizeRoute(
|
|
3958
|
-
|
|
4012
|
+
bestPoints2,
|
|
3959
4013
|
softObstacles,
|
|
3960
4014
|
hardObstacles,
|
|
3961
4015
|
diagnostics
|
|
@@ -3964,6 +4018,33 @@ function routeEdge(input) {
|
|
|
3964
4018
|
};
|
|
3965
4019
|
}
|
|
3966
4020
|
if (hardObstacles.length > 0) {
|
|
4021
|
+
let bestPoints2 = candidateRoutes[0]?.points ?? fallbackRoute(input, defaultAnchors);
|
|
4022
|
+
if (input.kind === "obstacle-avoiding") {
|
|
4023
|
+
const allObstacles = [...softObstacles, ...hardObstacles];
|
|
4024
|
+
for (const candidate of candidateRoutes) {
|
|
4025
|
+
const rerouted = greedyRerouteAroundObstacles(
|
|
4026
|
+
candidate.points,
|
|
4027
|
+
allObstacles,
|
|
4028
|
+
5
|
|
4029
|
+
);
|
|
4030
|
+
if (!routeCrossesBoxes(rerouted, allObstacles)) {
|
|
4031
|
+
return {
|
|
4032
|
+
points: finalizeRoute(
|
|
4033
|
+
rerouted,
|
|
4034
|
+
softObstacles,
|
|
4035
|
+
hardObstacles,
|
|
4036
|
+
diagnostics
|
|
4037
|
+
),
|
|
4038
|
+
diagnostics
|
|
4039
|
+
};
|
|
4040
|
+
}
|
|
4041
|
+
}
|
|
4042
|
+
bestPoints2 = greedyRerouteAroundObstacles(
|
|
4043
|
+
candidateRoutes[0]?.points ?? fallbackRoute(input, defaultAnchors),
|
|
4044
|
+
allObstacles,
|
|
4045
|
+
5
|
|
4046
|
+
);
|
|
4047
|
+
}
|
|
3967
4048
|
diagnostics.push({
|
|
3968
4049
|
severity: "error",
|
|
3969
4050
|
code: "routing.evidence.crossing_forbidden",
|
|
@@ -3971,7 +4052,7 @@ function routeEdge(input) {
|
|
|
3971
4052
|
});
|
|
3972
4053
|
return {
|
|
3973
4054
|
points: finalizeRoute(
|
|
3974
|
-
|
|
4055
|
+
bestPoints2,
|
|
3975
4056
|
softObstacles,
|
|
3976
4057
|
hardObstacles,
|
|
3977
4058
|
diagnostics
|
|
@@ -3979,6 +4060,33 @@ function routeEdge(input) {
|
|
|
3979
4060
|
diagnostics
|
|
3980
4061
|
};
|
|
3981
4062
|
}
|
|
4063
|
+
let bestPoints = candidateRoutes[0]?.points ?? fallbackRoute(input, defaultAnchors);
|
|
4064
|
+
if (input.kind === "obstacle-avoiding") {
|
|
4065
|
+
const allObstacles = [...softObstacles, ...hardObstacles];
|
|
4066
|
+
for (const candidate of candidateRoutes) {
|
|
4067
|
+
const rerouted = greedyRerouteAroundObstacles(
|
|
4068
|
+
candidate.points,
|
|
4069
|
+
allObstacles,
|
|
4070
|
+
5
|
|
4071
|
+
);
|
|
4072
|
+
if (!routeCrossesBoxes(rerouted, allObstacles)) {
|
|
4073
|
+
return {
|
|
4074
|
+
points: finalizeRoute(
|
|
4075
|
+
rerouted,
|
|
4076
|
+
softObstacles,
|
|
4077
|
+
hardObstacles,
|
|
4078
|
+
diagnostics
|
|
4079
|
+
),
|
|
4080
|
+
diagnostics
|
|
4081
|
+
};
|
|
4082
|
+
}
|
|
4083
|
+
}
|
|
4084
|
+
bestPoints = greedyRerouteAroundObstacles(
|
|
4085
|
+
candidateRoutes[0]?.points ?? fallbackRoute(input, defaultAnchors),
|
|
4086
|
+
allObstacles,
|
|
4087
|
+
5
|
|
4088
|
+
);
|
|
4089
|
+
}
|
|
3982
4090
|
diagnostics.push({
|
|
3983
4091
|
severity: "warning",
|
|
3984
4092
|
code: "routing.obstacle.unavoidable",
|
|
@@ -3986,7 +4094,7 @@ function routeEdge(input) {
|
|
|
3986
4094
|
});
|
|
3987
4095
|
return {
|
|
3988
4096
|
points: finalizeRoute(
|
|
3989
|
-
|
|
4097
|
+
bestPoints,
|
|
3990
4098
|
softObstacles,
|
|
3991
4099
|
hardObstacles,
|
|
3992
4100
|
diagnostics
|
|
@@ -3996,21 +4104,29 @@ function routeEdge(input) {
|
|
|
3996
4104
|
}
|
|
3997
4105
|
function finalizeRoute(points, softObstacles, hardObstacles, diagnostics) {
|
|
3998
4106
|
const simplified = simplifyRoute(points);
|
|
4107
|
+
if (simplified.length >= 3) {
|
|
4108
|
+
return simplified;
|
|
4109
|
+
}
|
|
3999
4110
|
const crossesHardObstacles = routeCrossesBoxes(simplified, hardObstacles);
|
|
4000
4111
|
const crossesSoftObstacles = routeCrossesBoxes(simplified, softObstacles);
|
|
4001
|
-
if (
|
|
4112
|
+
if (!crossesHardObstacles && !crossesSoftObstacles) {
|
|
4113
|
+
return simplified;
|
|
4114
|
+
}
|
|
4115
|
+
const expanded = expandFallbackRoute(simplified, [
|
|
4116
|
+
...softObstacles,
|
|
4117
|
+
...hardObstacles
|
|
4118
|
+
]);
|
|
4119
|
+
const expandedCrossesHard = routeCrossesBoxes(expanded, hardObstacles);
|
|
4120
|
+
const expandedCrossesSoft = routeCrossesBoxes(expanded, softObstacles);
|
|
4121
|
+
if (expandedCrossesHard || expandedCrossesSoft) {
|
|
4002
4122
|
diagnostics.push({
|
|
4003
|
-
severity:
|
|
4123
|
+
severity: expandedCrossesHard ? "error" : "warning",
|
|
4004
4124
|
code: "route_obstacle_fallback",
|
|
4005
4125
|
message: "Obstacle-aware routing fell back to fewer than three route points.",
|
|
4006
4126
|
detail: { pointCount: simplified.length }
|
|
4007
4127
|
});
|
|
4008
|
-
return expandFallbackRoute(simplified, [
|
|
4009
|
-
...softObstacles,
|
|
4010
|
-
...hardObstacles
|
|
4011
|
-
]);
|
|
4012
4128
|
}
|
|
4013
|
-
return
|
|
4129
|
+
return expanded;
|
|
4014
4130
|
}
|
|
4015
4131
|
function expandFallbackRoute(points, obstacles) {
|
|
4016
4132
|
if (points.length !== 2) {
|
|
@@ -4041,12 +4157,12 @@ function expandFallbackRoute(points, obstacles) {
|
|
|
4041
4157
|
const hv = diagonalDetourHV(source, target, obstacles);
|
|
4042
4158
|
const vh = diagonalDetourVH(source, target, obstacles);
|
|
4043
4159
|
const viable = [hv, vh].filter((c) => !routeCrossesBoxes(c, obstacles));
|
|
4044
|
-
|
|
4160
|
+
const [firstViable, ...remainingViable] = viable;
|
|
4161
|
+
if (firstViable !== void 0) {
|
|
4045
4162
|
const directLen = Math.hypot(target.x - source.x, target.y - source.y);
|
|
4046
|
-
let best =
|
|
4047
|
-
for (
|
|
4048
|
-
|
|
4049
|
-
if (cand !== void 0 && pathLength(cand) - directLen < pathLength(best) - directLen) {
|
|
4163
|
+
let best = firstViable;
|
|
4164
|
+
for (const cand of remainingViable) {
|
|
4165
|
+
if (pathLength(cand) - directLen < pathLength(best) - directLen) {
|
|
4050
4166
|
best = cand;
|
|
4051
4167
|
}
|
|
4052
4168
|
}
|
|
@@ -4136,6 +4252,70 @@ function insetBox(box, margin) {
|
|
|
4136
4252
|
height: box.height - margin * 2
|
|
4137
4253
|
};
|
|
4138
4254
|
}
|
|
4255
|
+
function greedyRerouteAroundObstacles(points, obstacles, maxIterations) {
|
|
4256
|
+
let current = [...points];
|
|
4257
|
+
for (let iter = 0; iter < maxIterations; iter++) {
|
|
4258
|
+
const improved = pushRouteAwayFromObstacles(current, obstacles);
|
|
4259
|
+
if (improved === null) {
|
|
4260
|
+
break;
|
|
4261
|
+
}
|
|
4262
|
+
current = improved;
|
|
4263
|
+
if (!routeCrossesBoxes(current, obstacles)) {
|
|
4264
|
+
break;
|
|
4265
|
+
}
|
|
4266
|
+
}
|
|
4267
|
+
return current;
|
|
4268
|
+
}
|
|
4269
|
+
function pushRouteAwayFromObstacles(points, obstacles) {
|
|
4270
|
+
const result = [];
|
|
4271
|
+
let improved = false;
|
|
4272
|
+
for (let i = 0; i < points.length - 1; i++) {
|
|
4273
|
+
const a = points[i];
|
|
4274
|
+
const b = points[i + 1];
|
|
4275
|
+
if (a === void 0 || b === void 0) {
|
|
4276
|
+
result.push(a ?? b ?? { x: 0, y: 0 });
|
|
4277
|
+
continue;
|
|
4278
|
+
}
|
|
4279
|
+
result.push(a);
|
|
4280
|
+
const intersectors = obstacles.filter(
|
|
4281
|
+
(obs) => segmentIntersectsBox(a, b, obs)
|
|
4282
|
+
);
|
|
4283
|
+
if (intersectors.length === 0) {
|
|
4284
|
+
continue;
|
|
4285
|
+
}
|
|
4286
|
+
const mx = (a.x + b.x) / 2;
|
|
4287
|
+
const my = (a.y + b.y) / 2;
|
|
4288
|
+
const isHorizontal = a.y === b.y;
|
|
4289
|
+
const margin = 12;
|
|
4290
|
+
let bestWaypoint = null;
|
|
4291
|
+
let bestDist = Infinity;
|
|
4292
|
+
for (const obs of intersectors) {
|
|
4293
|
+
const candidates = isHorizontal ? [
|
|
4294
|
+
{ x: mx, y: obs.y - margin },
|
|
4295
|
+
{ x: mx, y: obs.y + obs.height + margin }
|
|
4296
|
+
] : [
|
|
4297
|
+
{ x: obs.x - margin, y: my },
|
|
4298
|
+
{ x: obs.x + obs.width + margin, y: my }
|
|
4299
|
+
];
|
|
4300
|
+
for (const wp of candidates) {
|
|
4301
|
+
const dist = Math.hypot(wp.x - mx, wp.y - my);
|
|
4302
|
+
if (dist < bestDist) {
|
|
4303
|
+
bestDist = dist;
|
|
4304
|
+
bestWaypoint = wp;
|
|
4305
|
+
}
|
|
4306
|
+
}
|
|
4307
|
+
}
|
|
4308
|
+
if (bestWaypoint !== null) {
|
|
4309
|
+
result.push(bestWaypoint);
|
|
4310
|
+
improved = true;
|
|
4311
|
+
}
|
|
4312
|
+
}
|
|
4313
|
+
const last = points[points.length - 1];
|
|
4314
|
+
if (last !== void 0) {
|
|
4315
|
+
result.push(last);
|
|
4316
|
+
}
|
|
4317
|
+
return improved ? result : null;
|
|
4318
|
+
}
|
|
4139
4319
|
function fallbackRoute(input, defaultAnchors) {
|
|
4140
4320
|
return [
|
|
4141
4321
|
getEdgePort(
|
|
@@ -4632,6 +4812,7 @@ function solveDiagram(diagram, options = {}) {
|
|
|
4632
4812
|
];
|
|
4633
4813
|
const initialContentBounds = layoutBoxes.length === 0 ? { x: 0, y: 0, width: 0} : unionBoxes(layoutBoxes);
|
|
4634
4814
|
placeEvidenceBlocks(
|
|
4815
|
+
options.obstacleMargin ?? 0,
|
|
4635
4816
|
[
|
|
4636
4817
|
...coordinatedMatrices,
|
|
4637
4818
|
...coordinatedTables,
|
|
@@ -4698,17 +4879,35 @@ function solveDiagram(diagram, options = {}) {
|
|
|
4698
4879
|
...baseTextAnnotations.filter(isPreRouteTextObstacle),
|
|
4699
4880
|
...frameTextAnnotation.filter(isPreRouteTextObstacle)
|
|
4700
4881
|
];
|
|
4882
|
+
const margin = options.obstacleMargin ?? 0;
|
|
4883
|
+
const softObstacles = [
|
|
4884
|
+
...coordinatedTables.map((table) => expandBox(table.box, margin)),
|
|
4885
|
+
...coordinatedEvidencePanels.map((panel) => expandBox(panel.box, margin))
|
|
4886
|
+
];
|
|
4887
|
+
const hardObstacles = coordinatedMatrices.map(
|
|
4888
|
+
(matrix) => expandBox(matrix.box, margin)
|
|
4889
|
+
);
|
|
4890
|
+
const titleBarObstacles = [];
|
|
4891
|
+
if (frame !== void 0) {
|
|
4892
|
+
titleBarObstacles.push(expandBox(frame.titleBox, margin));
|
|
4893
|
+
}
|
|
4894
|
+
for (const swimlane of coordinatedSwimlanes) {
|
|
4895
|
+
for (const lane of swimlane.lanes) {
|
|
4896
|
+
if (lane.headerBox !== void 0 && lane.headerBox.width > 0 && lane.headerBox.height > 0) {
|
|
4897
|
+
titleBarObstacles.push(expandBox(lane.headerBox, margin));
|
|
4898
|
+
}
|
|
4899
|
+
}
|
|
4900
|
+
}
|
|
4701
4901
|
const coordinatedEdges = coordinateEdges(
|
|
4702
4902
|
styledEdges,
|
|
4703
4903
|
nodeGeometryById,
|
|
4704
4904
|
coordinatedNodes,
|
|
4705
|
-
[...nodeGeometryById.values()].map(
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
],
|
|
4905
|
+
[...nodeGeometryById.values()].map(
|
|
4906
|
+
(geometry) => options.routingGutter === void 0 ? geometry.obstacleBox : expandBox(geometry.obstacleBox, options.routingGutter)
|
|
4907
|
+
),
|
|
4908
|
+
[...softObstacles, ...titleBarObstacles],
|
|
4710
4909
|
routingTextObstacles,
|
|
4711
|
-
|
|
4910
|
+
hardObstacles,
|
|
4712
4911
|
diagram.direction,
|
|
4713
4912
|
options,
|
|
4714
4913
|
diagnostics
|
|
@@ -4743,6 +4942,16 @@ function solveDiagram(diagram, options = {}) {
|
|
|
4743
4942
|
options.pageBounds
|
|
4744
4943
|
)
|
|
4745
4944
|
);
|
|
4945
|
+
let degraded = false;
|
|
4946
|
+
const resultDiagnostics = diagnostics.map((diagnostic) => {
|
|
4947
|
+
if (DELIVERABILITY_DIAGNOSTIC_CODES.has(diagnostic.code)) {
|
|
4948
|
+
degraded = true;
|
|
4949
|
+
if (options.strict) {
|
|
4950
|
+
return { ...diagnostic, severity: "error" };
|
|
4951
|
+
}
|
|
4952
|
+
}
|
|
4953
|
+
return diagnostic;
|
|
4954
|
+
});
|
|
4746
4955
|
return {
|
|
4747
4956
|
id: diagram.id,
|
|
4748
4957
|
...diagram.title === void 0 ? {} : { title: diagram.title },
|
|
@@ -4754,7 +4963,8 @@ function solveDiagram(diagram, options = {}) {
|
|
|
4754
4963
|
...coordinatedMatrices.length === 0 ? {} : { matrices: coordinatedMatrices },
|
|
4755
4964
|
...coordinatedTables.length === 0 ? {} : { tables: coordinatedTables },
|
|
4756
4965
|
...coordinatedEvidencePanels.length === 0 ? {} : { evidencePanels: coordinatedEvidencePanels },
|
|
4757
|
-
diagnostics,
|
|
4966
|
+
diagnostics: resultDiagnostics,
|
|
4967
|
+
degraded,
|
|
4758
4968
|
bounds: frame === void 0 ? unionBoxes(boundsBase) : unionBoxes([...boundsBase, frame.box, frame.titleBox]),
|
|
4759
4969
|
...frame === void 0 ? {} : { frame },
|
|
4760
4970
|
...textAnnotations.length === 0 ? {} : { textAnnotations },
|
|
@@ -6143,16 +6353,25 @@ function blockBox(block, defaultSize) {
|
|
|
6143
6353
|
height: block.size?.height ?? defaultSize.height
|
|
6144
6354
|
};
|
|
6145
6355
|
}
|
|
6146
|
-
function placeEvidenceBlocks(blocks, contentBounds) {
|
|
6356
|
+
function placeEvidenceBlocks(obstacleMargin, blocks, contentBounds) {
|
|
6357
|
+
const margin = normalizeInsets(obstacleMargin);
|
|
6358
|
+
const horizontalGap = Math.max(
|
|
6359
|
+
DEFAULT_EVIDENCE_BLOCK_GAP,
|
|
6360
|
+
margin.right + margin.left
|
|
6361
|
+
);
|
|
6362
|
+
const verticalGap = Math.max(
|
|
6363
|
+
DEFAULT_EVIDENCE_BLOCK_GAP,
|
|
6364
|
+
margin.bottom + margin.top
|
|
6365
|
+
);
|
|
6147
6366
|
let nextY = contentBounds.y;
|
|
6148
|
-
const x = contentBounds.x + contentBounds.width +
|
|
6367
|
+
const x = contentBounds.x + contentBounds.width + horizontalGap;
|
|
6149
6368
|
for (const block of blocks) {
|
|
6150
6369
|
if (block.position !== void 0) {
|
|
6151
6370
|
continue;
|
|
6152
6371
|
}
|
|
6153
6372
|
block.box.x = x;
|
|
6154
6373
|
block.box.y = nextY;
|
|
6155
|
-
nextY += block.box.height +
|
|
6374
|
+
nextY += block.box.height + verticalGap;
|
|
6156
6375
|
}
|
|
6157
6376
|
}
|
|
6158
6377
|
function columnXOffsets(table, box) {
|
|
@@ -7008,9 +7227,7 @@ function edgeLabelAnchorCandidates(points, placement, layout2) {
|
|
|
7008
7227
|
{ x: placement.x, y: placement.y + offset }
|
|
7009
7228
|
);
|
|
7010
7229
|
}
|
|
7011
|
-
|
|
7012
|
-
}
|
|
7013
|
-
if (segment.start.x === segment.end.x) {
|
|
7230
|
+
} else if (segment.start.x === segment.end.x) {
|
|
7014
7231
|
const needed = layout2.box.width / 2 + EDGE_LABEL_CLEARANCE;
|
|
7015
7232
|
const maxSteps = Math.max(12, Math.ceil(needed / EDGE_LABEL_CLEARANCE));
|
|
7016
7233
|
for (let step = 1; step <= maxSteps; step += 1) {
|
|
@@ -7020,7 +7237,83 @@ function edgeLabelAnchorCandidates(points, placement, layout2) {
|
|
|
7020
7237
|
{ x: placement.x - offset, y: placement.y }
|
|
7021
7238
|
);
|
|
7022
7239
|
}
|
|
7023
|
-
|
|
7240
|
+
} else {
|
|
7241
|
+
const dx = segment.end.x - segment.start.x;
|
|
7242
|
+
const dy = segment.end.y - segment.start.y;
|
|
7243
|
+
const segLen = Math.hypot(dx, dy);
|
|
7244
|
+
if (segLen > 0) {
|
|
7245
|
+
const nx = -dy / segLen;
|
|
7246
|
+
const ny = dx / segLen;
|
|
7247
|
+
const needed = (Math.abs(nx) * layout2.box.width + Math.abs(ny) * layout2.box.height) / 2 + EDGE_LABEL_CLEARANCE;
|
|
7248
|
+
const maxSteps = Math.max(12, Math.ceil(needed / EDGE_LABEL_CLEARANCE));
|
|
7249
|
+
for (let step = 1; step <= maxSteps; step += 1) {
|
|
7250
|
+
const offset = EDGE_LABEL_CLEARANCE * step;
|
|
7251
|
+
candidates.push(
|
|
7252
|
+
{ x: placement.x + nx * offset, y: placement.y + ny * offset },
|
|
7253
|
+
{ x: placement.x - nx * offset, y: placement.y - ny * offset }
|
|
7254
|
+
);
|
|
7255
|
+
}
|
|
7256
|
+
}
|
|
7257
|
+
}
|
|
7258
|
+
const totalLen = points.reduce((sum, p, idx) => {
|
|
7259
|
+
if (idx === 0) return 0;
|
|
7260
|
+
const prev = points[idx - 1];
|
|
7261
|
+
return sum + Math.hypot((p?.x ?? 0) - (prev?.x ?? 0), (p?.y ?? 0) - (prev?.y ?? 0));
|
|
7262
|
+
}, 0);
|
|
7263
|
+
if (totalLen > 200) {
|
|
7264
|
+
for (const ratio of [0.25, 0.75]) {
|
|
7265
|
+
const qp = labelPlacementAtRatio(points, ratio, totalLen);
|
|
7266
|
+
if (qp !== void 0) {
|
|
7267
|
+
candidates.push(qp);
|
|
7268
|
+
const qTargetDist = totalLen * ratio;
|
|
7269
|
+
let qTravelled = 0;
|
|
7270
|
+
let seg;
|
|
7271
|
+
for (let si = 1; si < points.length; si++) {
|
|
7272
|
+
const sp = points[si - 1];
|
|
7273
|
+
const sc = points[si];
|
|
7274
|
+
if (sp === void 0 || sc === void 0) continue;
|
|
7275
|
+
const sl = Math.hypot(sc.x - sp.x, sc.y - sp.y);
|
|
7276
|
+
if (sl <= 0) continue;
|
|
7277
|
+
if (qTravelled + sl >= qTargetDist) {
|
|
7278
|
+
seg = { start: sp, end: sc, length: sl };
|
|
7279
|
+
break;
|
|
7280
|
+
}
|
|
7281
|
+
qTravelled += sl;
|
|
7282
|
+
}
|
|
7283
|
+
if (seg !== void 0) {
|
|
7284
|
+
const segLen = Math.hypot(
|
|
7285
|
+
seg.end.x - seg.start.x,
|
|
7286
|
+
seg.end.y - seg.start.y
|
|
7287
|
+
);
|
|
7288
|
+
const qpNeeded = seg.start.y === seg.end.y ? layout2.box.height / 2 + EDGE_LABEL_CLEARANCE : seg.start.x === seg.end.x ? layout2.box.width / 2 + EDGE_LABEL_CLEARANCE : (Math.abs(seg.start.y - seg.end.y) * layout2.box.width + Math.abs(seg.end.x - seg.start.x) * layout2.box.height) / (2 * segLen) + EDGE_LABEL_CLEARANCE;
|
|
7289
|
+
const qpMaxSteps = Math.max(
|
|
7290
|
+
12,
|
|
7291
|
+
Math.ceil(qpNeeded / EDGE_LABEL_CLEARANCE)
|
|
7292
|
+
);
|
|
7293
|
+
for (let step = 1; step <= qpMaxSteps; step += 1) {
|
|
7294
|
+
const offset = EDGE_LABEL_CLEARANCE * step;
|
|
7295
|
+
if (seg.start.y === seg.end.y) {
|
|
7296
|
+
candidates.push(
|
|
7297
|
+
{ x: qp.x, y: qp.y - offset },
|
|
7298
|
+
{ x: qp.x, y: qp.y + offset }
|
|
7299
|
+
);
|
|
7300
|
+
} else if (seg.start.x === seg.end.x) {
|
|
7301
|
+
candidates.push(
|
|
7302
|
+
{ x: qp.x - offset, y: qp.y },
|
|
7303
|
+
{ x: qp.x + offset, y: qp.y }
|
|
7304
|
+
);
|
|
7305
|
+
} else {
|
|
7306
|
+
const nx = -(seg.end.y - seg.start.y) / segLen;
|
|
7307
|
+
const ny = (seg.end.x - seg.start.x) / segLen;
|
|
7308
|
+
candidates.push(
|
|
7309
|
+
{ x: qp.x + nx * offset, y: qp.y + ny * offset },
|
|
7310
|
+
{ x: qp.x - nx * offset, y: qp.y - ny * offset }
|
|
7311
|
+
);
|
|
7312
|
+
}
|
|
7313
|
+
}
|
|
7314
|
+
}
|
|
7315
|
+
}
|
|
7316
|
+
}
|
|
7024
7317
|
}
|
|
7025
7318
|
return candidates;
|
|
7026
7319
|
}
|
|
@@ -7077,6 +7370,34 @@ function nonZeroSegments2(points) {
|
|
|
7077
7370
|
}
|
|
7078
7371
|
return segments;
|
|
7079
7372
|
}
|
|
7373
|
+
function labelPlacementAtRatio(points, ratio, totalLength) {
|
|
7374
|
+
if (points.length < 2 || ratio < 0 || ratio > 1) {
|
|
7375
|
+
return void 0;
|
|
7376
|
+
}
|
|
7377
|
+
const targetDist = totalLength * ratio;
|
|
7378
|
+
let travelled = 0;
|
|
7379
|
+
for (let idx = 1; idx < points.length; idx++) {
|
|
7380
|
+
const prev = points[idx - 1];
|
|
7381
|
+
const curr = points[idx];
|
|
7382
|
+
if (prev === void 0 || curr === void 0) {
|
|
7383
|
+
continue;
|
|
7384
|
+
}
|
|
7385
|
+
const segLen = Math.hypot(curr.x - prev.x, curr.y - prev.y);
|
|
7386
|
+
if (segLen <= 0) {
|
|
7387
|
+
continue;
|
|
7388
|
+
}
|
|
7389
|
+
if (travelled + segLen >= targetDist) {
|
|
7390
|
+
const t = (targetDist - travelled) / segLen;
|
|
7391
|
+
const offset = labelOffset2({ start: prev, end: curr, length: segLen });
|
|
7392
|
+
return {
|
|
7393
|
+
x: prev.x + (curr.x - prev.x) * t + offset.x,
|
|
7394
|
+
y: prev.y + (curr.y - prev.y) * t + offset.y
|
|
7395
|
+
};
|
|
7396
|
+
}
|
|
7397
|
+
travelled += segLen;
|
|
7398
|
+
}
|
|
7399
|
+
return void 0;
|
|
7400
|
+
}
|
|
7080
7401
|
function labelOffset2(segment) {
|
|
7081
7402
|
const offset = 10;
|
|
7082
7403
|
const dx = segment.end.x - segment.start.x;
|
|
@@ -7191,7 +7512,7 @@ function renderDiagramDsl(source, options = {}) {
|
|
|
7191
7512
|
return { diagnostics };
|
|
7192
7513
|
}
|
|
7193
7514
|
const solved = solveDiagram(normalized.diagram, {
|
|
7194
|
-
routeKind: normalized.diagram.metadata?.routeKind === "straight" ? "straight" : "orthogonal",
|
|
7515
|
+
routeKind: normalized.diagram.metadata?.routeKind === "straight" ? "straight" : normalized.diagram.metadata?.routeKind === "obstacle-avoiding" ? "obstacle-avoiding" : "orthogonal",
|
|
7195
7516
|
...solvePortShiftingOption(normalized.diagram.metadata?.portShifting),
|
|
7196
7517
|
...options.textMeasurer === void 0 ? {} : { textMeasurer: options.textMeasurer }
|
|
7197
7518
|
});
|
|
@@ -7383,6 +7704,7 @@ function isPointLikeRecord(value) {
|
|
|
7383
7704
|
|
|
7384
7705
|
exports.DEFAULT_CANONICAL_PRECISION = DEFAULT_CANONICAL_PRECISION;
|
|
7385
7706
|
exports.DEFAULT_DSL_MAX_BYTES = DEFAULT_DSL_MAX_BYTES;
|
|
7707
|
+
exports.DELIVERABILITY_DIAGNOSTIC_CODES = DELIVERABILITY_DIAGNOSTIC_CODES;
|
|
7386
7708
|
exports.DeterministicTextMeasurer = DeterministicTextMeasurer;
|
|
7387
7709
|
exports.LabelFitter = LabelFitter;
|
|
7388
7710
|
exports.PretextTextMeasurer = PretextTextMeasurer;
|