@tscircuit/schematic-trace-solver 0.0.148 → 0.0.149
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/index.d.ts +3 -1
- package/dist/index.js +101 -42
- package/lib/solvers/InlineNetLabelSolver/InlineNetLabelSolver.ts +101 -2
- package/package.json +1 -1
- package/site/examples/example51.page.tsx +4 -0
- package/tests/assets/example51.json +5102 -0
- package/tests/examples/__snapshots__/example51.snap.svg +367 -0
- package/tests/examples/example51.test.ts +12 -0
- package/tests/repros/__snapshots__/repro-core-tb67s579ftg-inline-label-routing.snap.svg +235 -0
- package/tests/repros/assets/repro-core-tb67s579ftg-inline-label-routing.input.json +900 -0
- package/tests/repros/repro-core-tb67s579ftg-inline-label-routing.test.ts +40 -0
- package/tests/solvers/InlineNetLabelSolver/__snapshots__/terminal-stub-trace-clearance.snap.svg +53 -0
- package/tests/solvers/InlineNetLabelSolver/terminal-stub-trace-clearance.test.ts +102 -0
package/dist/index.d.ts
CHANGED
|
@@ -1186,6 +1186,8 @@ declare const DEFAULT_INLINE_NET_LABEL_HEIGHT = 0.18;
|
|
|
1186
1186
|
* Gap between the trace and the near edge of the inline label text.
|
|
1187
1187
|
*/
|
|
1188
1188
|
declare const INLINE_NET_LABEL_TRACE_MARGIN = 0.05;
|
|
1189
|
+
/** Clearance between a generated terminal stub and an unrelated trace. */
|
|
1190
|
+
declare const INLINE_NET_LABEL_STUB_TRACE_CLEARANCE = 0.05;
|
|
1189
1191
|
/**
|
|
1190
1192
|
* Largest perpendicular deviation a route may have and still be labeled as one
|
|
1191
1193
|
* span. A route that is straight except for elbow jogs up to this size reads
|
|
@@ -1361,4 +1363,4 @@ declare class SchematicTracePipelineSolver extends BaseSolver {
|
|
|
1361
1363
|
preview(): GraphicsObject;
|
|
1362
1364
|
}
|
|
1363
1365
|
|
|
1364
|
-
export { type ChipId, DEFAULT_INLINE_NET_LABEL_HEIGHT, INLINE_NET_LABEL_MAX_SPAN_JOG, INLINE_NET_LABEL_TRACE_MARGIN, type InlineNetLabelPlacement, InlineNetLabelSolver, type InputChip, type InputDirectConnection, type InputNetConnection, type InputPin, type InputProblem, type NetId, type NetLabelPlacement, type PinId, SchematicTracePipelineSolver, SchematicTraceSingleLineSolver2, type SectionId, type TextBoxes, estimateInlineNetLabelWidth };
|
|
1366
|
+
export { type ChipId, DEFAULT_INLINE_NET_LABEL_HEIGHT, INLINE_NET_LABEL_MAX_SPAN_JOG, INLINE_NET_LABEL_STUB_TRACE_CLEARANCE, INLINE_NET_LABEL_TRACE_MARGIN, type InlineNetLabelPlacement, InlineNetLabelSolver, type InputChip, type InputDirectConnection, type InputNetConnection, type InputPin, type InputProblem, type NetId, type NetLabelPlacement, type PinId, SchematicTracePipelineSolver, SchematicTraceSingleLineSolver2, type SectionId, type TextBoxes, estimateInlineNetLabelWidth };
|
package/dist/index.js
CHANGED
|
@@ -12678,47 +12678,6 @@ var TraceElbowTransitionSimplificationSolver = class extends BaseSolver {
|
|
|
12678
12678
|
}
|
|
12679
12679
|
};
|
|
12680
12680
|
|
|
12681
|
-
// lib/solvers/InlineNetLabelSolver/getAxisAlignedSegments.ts
|
|
12682
|
-
var getAxisAlignedSegments = (path, epsilon = 1e-6) => {
|
|
12683
|
-
const segments = [];
|
|
12684
|
-
let runStart = null;
|
|
12685
|
-
let runAxis = null;
|
|
12686
|
-
let runSign = 0;
|
|
12687
|
-
const closeRun = (runEnd) => {
|
|
12688
|
-
if (runStart && runAxis) {
|
|
12689
|
-
const length = runAxis === "x" ? Math.abs(runEnd.x - runStart.x) : Math.abs(runEnd.y - runStart.y);
|
|
12690
|
-
if (length > epsilon) {
|
|
12691
|
-
segments.push({ start: runStart, end: runEnd, axis: runAxis, length });
|
|
12692
|
-
}
|
|
12693
|
-
}
|
|
12694
|
-
runStart = null;
|
|
12695
|
-
runAxis = null;
|
|
12696
|
-
runSign = 0;
|
|
12697
|
-
};
|
|
12698
|
-
for (let i = 0; i < path.length - 1; i++) {
|
|
12699
|
-
const a = path[i];
|
|
12700
|
-
const b = path[i + 1];
|
|
12701
|
-
const dx = b.x - a.x;
|
|
12702
|
-
const dy = b.y - a.y;
|
|
12703
|
-
if (Math.abs(dx) <= epsilon && Math.abs(dy) <= epsilon) continue;
|
|
12704
|
-
const axis = Math.abs(dy) <= epsilon ? "x" : Math.abs(dx) <= epsilon ? "y" : null;
|
|
12705
|
-
if (!axis) {
|
|
12706
|
-
closeRun(a);
|
|
12707
|
-
continue;
|
|
12708
|
-
}
|
|
12709
|
-
const sign = Math.sign(axis === "x" ? dx : dy);
|
|
12710
|
-
if (runStart && runAxis === axis && runSign === sign) continue;
|
|
12711
|
-
closeRun(a);
|
|
12712
|
-
runStart = a;
|
|
12713
|
-
runAxis = axis;
|
|
12714
|
-
runSign = sign;
|
|
12715
|
-
}
|
|
12716
|
-
if (path.length >= 2) {
|
|
12717
|
-
closeRun(path[path.length - 1]);
|
|
12718
|
-
}
|
|
12719
|
-
return segments.sort((a, b) => b.length - a.length);
|
|
12720
|
-
};
|
|
12721
|
-
|
|
12722
12681
|
// lib/solvers/InlineNetLabelSolver/alignPortOnlyInlineNetLabelStubs.ts
|
|
12723
12682
|
var getStubDirection = (path) => {
|
|
12724
12683
|
const [start, end] = path;
|
|
@@ -12867,6 +12826,47 @@ var alignPortOnlyInlineNetLabelStubs = ({
|
|
|
12867
12826
|
return alignedPlacements;
|
|
12868
12827
|
};
|
|
12869
12828
|
|
|
12829
|
+
// lib/solvers/InlineNetLabelSolver/getAxisAlignedSegments.ts
|
|
12830
|
+
var getAxisAlignedSegments = (path, epsilon = 1e-6) => {
|
|
12831
|
+
const segments = [];
|
|
12832
|
+
let runStart = null;
|
|
12833
|
+
let runAxis = null;
|
|
12834
|
+
let runSign = 0;
|
|
12835
|
+
const closeRun = (runEnd) => {
|
|
12836
|
+
if (runStart && runAxis) {
|
|
12837
|
+
const length = runAxis === "x" ? Math.abs(runEnd.x - runStart.x) : Math.abs(runEnd.y - runStart.y);
|
|
12838
|
+
if (length > epsilon) {
|
|
12839
|
+
segments.push({ start: runStart, end: runEnd, axis: runAxis, length });
|
|
12840
|
+
}
|
|
12841
|
+
}
|
|
12842
|
+
runStart = null;
|
|
12843
|
+
runAxis = null;
|
|
12844
|
+
runSign = 0;
|
|
12845
|
+
};
|
|
12846
|
+
for (let i = 0; i < path.length - 1; i++) {
|
|
12847
|
+
const a = path[i];
|
|
12848
|
+
const b = path[i + 1];
|
|
12849
|
+
const dx = b.x - a.x;
|
|
12850
|
+
const dy = b.y - a.y;
|
|
12851
|
+
if (Math.abs(dx) <= epsilon && Math.abs(dy) <= epsilon) continue;
|
|
12852
|
+
const axis = Math.abs(dy) <= epsilon ? "x" : Math.abs(dx) <= epsilon ? "y" : null;
|
|
12853
|
+
if (!axis) {
|
|
12854
|
+
closeRun(a);
|
|
12855
|
+
continue;
|
|
12856
|
+
}
|
|
12857
|
+
const sign = Math.sign(axis === "x" ? dx : dy);
|
|
12858
|
+
if (runStart && runAxis === axis && runSign === sign) continue;
|
|
12859
|
+
closeRun(a);
|
|
12860
|
+
runStart = a;
|
|
12861
|
+
runAxis = axis;
|
|
12862
|
+
runSign = sign;
|
|
12863
|
+
}
|
|
12864
|
+
if (path.length >= 2) {
|
|
12865
|
+
closeRun(path[path.length - 1]);
|
|
12866
|
+
}
|
|
12867
|
+
return segments.sort((a, b) => b.length - a.length);
|
|
12868
|
+
};
|
|
12869
|
+
|
|
12870
12870
|
// lib/solvers/InlineNetLabelSolver/pushAnchoredNetLabelsAwayFromInlineLabels.ts
|
|
12871
12871
|
var LABEL_CLEARANCE2 = 0.05;
|
|
12872
12872
|
var POINT_EPSILON = 1e-6;
|
|
@@ -13229,6 +13229,7 @@ var pushAnchoredNetLabelsAwayFromInlineLabels = ({
|
|
|
13229
13229
|
// lib/solvers/InlineNetLabelSolver/InlineNetLabelSolver.ts
|
|
13230
13230
|
var DEFAULT_INLINE_NET_LABEL_HEIGHT = 0.18;
|
|
13231
13231
|
var INLINE_NET_LABEL_TRACE_MARGIN = 0.05;
|
|
13232
|
+
var INLINE_NET_LABEL_STUB_TRACE_CLEARANCE = 0.05;
|
|
13232
13233
|
var INLINE_NET_LABEL_MAX_SPAN_JOG = 0.4;
|
|
13233
13234
|
var getPinPairKey2 = (pinIds) => [...pinIds].sort().join("::");
|
|
13234
13235
|
var InlineNetLabelSolver = class extends BaseSolver {
|
|
@@ -13329,7 +13330,15 @@ var InlineNetLabelSolver = class extends BaseSolver {
|
|
|
13329
13330
|
const stubLength = Math.max(width + 0.2, 0.6);
|
|
13330
13331
|
const start = inputPin ? { x: inputPin.x, y: inputPin.y } : anchoredPlacement.anchorPoint;
|
|
13331
13332
|
const direction = inputPin && inputChip ? inputPin._facingDirection ?? getPinDirection(inputPin, inputChip) : anchoredPlacement.orientation;
|
|
13332
|
-
const
|
|
13333
|
+
const intendedEnd = direction === "x+" ? { x: start.x + stubLength, y: start.y } : direction === "x-" ? { x: start.x - stubLength, y: start.y } : direction === "y+" ? { x: start.x, y: start.y + stubLength } : { x: start.x, y: start.y - stubLength };
|
|
13334
|
+
const end = getCollisionLimitedTerminalStubEnd({
|
|
13335
|
+
start,
|
|
13336
|
+
intendedEnd,
|
|
13337
|
+
minimumLength: width + 2 * INLINE_NET_LABEL_TRACE_MARGIN,
|
|
13338
|
+
traces: this.traces,
|
|
13339
|
+
ownGlobalConnNetId: anchoredPlacement.globalConnNetId
|
|
13340
|
+
});
|
|
13341
|
+
if (!end) return null;
|
|
13333
13342
|
const axis = direction === "x+" || direction === "x-" ? "x" : "y";
|
|
13334
13343
|
const side = axis === "x" ? "y+" : "x-";
|
|
13335
13344
|
const anchorPoint = {
|
|
@@ -13681,6 +13690,55 @@ var doesPathIntersectBounds2 = (path, bounds) => {
|
|
|
13681
13690
|
}
|
|
13682
13691
|
return false;
|
|
13683
13692
|
};
|
|
13693
|
+
var GEOMETRY_EPSILON = 1e-6;
|
|
13694
|
+
var getCollisionLimitedTerminalStubEnd = ({
|
|
13695
|
+
start,
|
|
13696
|
+
intendedEnd,
|
|
13697
|
+
minimumLength,
|
|
13698
|
+
traces,
|
|
13699
|
+
ownGlobalConnNetId
|
|
13700
|
+
}) => {
|
|
13701
|
+
const isHorizontal4 = Math.abs(intendedEnd.x - start.x) >= Math.abs(intendedEnd.y - start.y);
|
|
13702
|
+
const alongAxis = isHorizontal4 ? "x" : "y";
|
|
13703
|
+
const acrossAxis = isHorizontal4 ? "y" : "x";
|
|
13704
|
+
const direction = Math.sign(intendedEnd[alongAxis] - start[alongAxis]) || 1;
|
|
13705
|
+
const intendedLength = Math.abs(intendedEnd[alongAxis] - start[alongAxis]);
|
|
13706
|
+
let availableLength = intendedLength;
|
|
13707
|
+
for (const trace of traces) {
|
|
13708
|
+
if (trace.globalConnNetId === ownGlobalConnNetId) continue;
|
|
13709
|
+
for (let segmentIndex = 0; segmentIndex < trace.tracePath.length - 1; segmentIndex++) {
|
|
13710
|
+
const segmentStart = trace.tracePath[segmentIndex];
|
|
13711
|
+
const segmentEnd = trace.tracePath[segmentIndex + 1];
|
|
13712
|
+
const startAlong = (segmentStart[alongAxis] - start[alongAxis]) * direction;
|
|
13713
|
+
const endAlong = (segmentEnd[alongAxis] - start[alongAxis]) * direction;
|
|
13714
|
+
const startAcross = segmentStart[acrossAxis] - start[acrossAxis];
|
|
13715
|
+
const endAcross = segmentEnd[acrossAxis] - start[acrossAxis];
|
|
13716
|
+
const minAlong = Math.min(startAlong, endAlong);
|
|
13717
|
+
const maxAlong = Math.max(startAlong, endAlong);
|
|
13718
|
+
const minAcross = Math.min(startAcross, endAcross);
|
|
13719
|
+
const maxAcross = Math.max(startAcross, endAcross);
|
|
13720
|
+
let collisionDistance;
|
|
13721
|
+
const isCollinear = Math.abs(startAcross) <= GEOMETRY_EPSILON && Math.abs(endAcross) <= GEOMETRY_EPSILON;
|
|
13722
|
+
if (isCollinear && maxAlong >= -GEOMETRY_EPSILON && minAlong <= intendedLength + GEOMETRY_EPSILON) {
|
|
13723
|
+
collisionDistance = Math.max(0, minAlong);
|
|
13724
|
+
} else {
|
|
13725
|
+
const crossesStubAxis = minAcross <= GEOMETRY_EPSILON && maxAcross >= -GEOMETRY_EPSILON;
|
|
13726
|
+
const perpendicularAlong = (startAlong + endAlong) / 2;
|
|
13727
|
+
if (crossesStubAxis && Math.abs(startAlong - endAlong) <= GEOMETRY_EPSILON && perpendicularAlong >= -GEOMETRY_EPSILON && perpendicularAlong <= intendedLength + GEOMETRY_EPSILON) {
|
|
13728
|
+
collisionDistance = Math.max(0, perpendicularAlong);
|
|
13729
|
+
}
|
|
13730
|
+
}
|
|
13731
|
+
if (collisionDistance !== void 0) {
|
|
13732
|
+
availableLength = Math.min(
|
|
13733
|
+
availableLength,
|
|
13734
|
+
collisionDistance - INLINE_NET_LABEL_STUB_TRACE_CLEARANCE
|
|
13735
|
+
);
|
|
13736
|
+
}
|
|
13737
|
+
}
|
|
13738
|
+
}
|
|
13739
|
+
if (availableLength + GEOMETRY_EPSILON < minimumLength) return null;
|
|
13740
|
+
return isHorizontal4 ? { x: start.x + direction * availableLength, y: start.y } : { x: start.x, y: start.y + direction * availableLength };
|
|
13741
|
+
};
|
|
13684
13742
|
|
|
13685
13743
|
// lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver.ts
|
|
13686
13744
|
function definePipelineStep(solverName, solverClass, getConstructorParams, opts = {}) {
|
|
@@ -14246,6 +14304,7 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
|
|
|
14246
14304
|
export {
|
|
14247
14305
|
DEFAULT_INLINE_NET_LABEL_HEIGHT,
|
|
14248
14306
|
INLINE_NET_LABEL_MAX_SPAN_JOG,
|
|
14307
|
+
INLINE_NET_LABEL_STUB_TRACE_CLEARANCE,
|
|
14249
14308
|
INLINE_NET_LABEL_TRACE_MARGIN,
|
|
14250
14309
|
InlineNetLabelSolver,
|
|
14251
14310
|
SchematicTracePipelineSolver,
|
|
@@ -13,11 +13,11 @@ import type {
|
|
|
13
13
|
} from "lib/types/InputProblem"
|
|
14
14
|
import { getColorFromString } from "lib/utils/getColorFromString"
|
|
15
15
|
import { boundsOverlap, getTextBoxBounds } from "lib/utils/textBoxBounds"
|
|
16
|
+
import { alignPortOnlyInlineNetLabelStubs } from "./alignPortOnlyInlineNetLabelStubs"
|
|
16
17
|
import {
|
|
17
18
|
type AxisAlignedSegment,
|
|
18
19
|
getAxisAlignedSegments,
|
|
19
20
|
} from "./getAxisAlignedSegments"
|
|
20
|
-
import { alignPortOnlyInlineNetLabelStubs } from "./alignPortOnlyInlineNetLabelStubs"
|
|
21
21
|
import { pushAnchoredNetLabelsAwayFromInlineLabels } from "./pushAnchoredNetLabelsAwayFromInlineLabels"
|
|
22
22
|
|
|
23
23
|
export const DEFAULT_INLINE_NET_LABEL_HEIGHT = 0.18
|
|
@@ -27,6 +27,9 @@ export const DEFAULT_INLINE_NET_LABEL_HEIGHT = 0.18
|
|
|
27
27
|
*/
|
|
28
28
|
export const INLINE_NET_LABEL_TRACE_MARGIN = 0.05
|
|
29
29
|
|
|
30
|
+
/** Clearance between a generated terminal stub and an unrelated trace. */
|
|
31
|
+
export const INLINE_NET_LABEL_STUB_TRACE_CLEARANCE = 0.05
|
|
32
|
+
|
|
30
33
|
/**
|
|
31
34
|
* Largest perpendicular deviation a route may have and still be labeled as one
|
|
32
35
|
* span. A route that is straight except for elbow jogs up to this size reads
|
|
@@ -248,7 +251,7 @@ export class InlineNetLabelSolver extends BaseSolver {
|
|
|
248
251
|
inputPin && inputChip
|
|
249
252
|
? (inputPin._facingDirection ?? getPinDirection(inputPin, inputChip))
|
|
250
253
|
: anchoredPlacement.orientation
|
|
251
|
-
const
|
|
254
|
+
const intendedEnd: Point =
|
|
252
255
|
direction === "x+"
|
|
253
256
|
? { x: start.x + stubLength, y: start.y }
|
|
254
257
|
: direction === "x-"
|
|
@@ -257,6 +260,15 @@ export class InlineNetLabelSolver extends BaseSolver {
|
|
|
257
260
|
? { x: start.x, y: start.y + stubLength }
|
|
258
261
|
: { x: start.x, y: start.y - stubLength }
|
|
259
262
|
|
|
263
|
+
const end = getCollisionLimitedTerminalStubEnd({
|
|
264
|
+
start,
|
|
265
|
+
intendedEnd,
|
|
266
|
+
minimumLength: width + 2 * INLINE_NET_LABEL_TRACE_MARGIN,
|
|
267
|
+
traces: this.traces,
|
|
268
|
+
ownGlobalConnNetId: anchoredPlacement.globalConnNetId,
|
|
269
|
+
})
|
|
270
|
+
if (!end) return null
|
|
271
|
+
|
|
260
272
|
const axis: InlineNetLabelPlacement["axis"] =
|
|
261
273
|
direction === "x+" || direction === "x-" ? "x" : "y"
|
|
262
274
|
const side: InlineNetLabelPlacement["side"] = axis === "x" ? "y+" : "x-"
|
|
@@ -777,3 +789,90 @@ const doesPathIntersectBounds = (path: Point[], bounds: Bounds): boolean => {
|
|
|
777
789
|
}
|
|
778
790
|
return false
|
|
779
791
|
}
|
|
792
|
+
|
|
793
|
+
const GEOMETRY_EPSILON = 1e-6
|
|
794
|
+
|
|
795
|
+
/**
|
|
796
|
+
* Shortens an axis-aligned terminal stub before the first unrelated trace.
|
|
797
|
+
* Coordinates are schematic-world millimetres with +x right and +y up.
|
|
798
|
+
*/
|
|
799
|
+
const getCollisionLimitedTerminalStubEnd = ({
|
|
800
|
+
start,
|
|
801
|
+
intendedEnd,
|
|
802
|
+
minimumLength,
|
|
803
|
+
traces,
|
|
804
|
+
ownGlobalConnNetId,
|
|
805
|
+
}: {
|
|
806
|
+
start: Point
|
|
807
|
+
intendedEnd: Point
|
|
808
|
+
minimumLength: number
|
|
809
|
+
traces: SolvedTracePath[]
|
|
810
|
+
ownGlobalConnNetId: string
|
|
811
|
+
}): Point | null => {
|
|
812
|
+
const isHorizontal =
|
|
813
|
+
Math.abs(intendedEnd.x - start.x) >= Math.abs(intendedEnd.y - start.y)
|
|
814
|
+
const alongAxis = isHorizontal ? "x" : "y"
|
|
815
|
+
const acrossAxis = isHorizontal ? "y" : "x"
|
|
816
|
+
const direction = Math.sign(intendedEnd[alongAxis] - start[alongAxis]) || 1
|
|
817
|
+
const intendedLength = Math.abs(intendedEnd[alongAxis] - start[alongAxis])
|
|
818
|
+
let availableLength = intendedLength
|
|
819
|
+
|
|
820
|
+
for (const trace of traces) {
|
|
821
|
+
if (trace.globalConnNetId === ownGlobalConnNetId) continue
|
|
822
|
+
|
|
823
|
+
for (
|
|
824
|
+
let segmentIndex = 0;
|
|
825
|
+
segmentIndex < trace.tracePath.length - 1;
|
|
826
|
+
segmentIndex++
|
|
827
|
+
) {
|
|
828
|
+
const segmentStart = trace.tracePath[segmentIndex]!
|
|
829
|
+
const segmentEnd = trace.tracePath[segmentIndex + 1]!
|
|
830
|
+
const startAlong =
|
|
831
|
+
(segmentStart[alongAxis] - start[alongAxis]) * direction
|
|
832
|
+
const endAlong = (segmentEnd[alongAxis] - start[alongAxis]) * direction
|
|
833
|
+
const startAcross = segmentStart[acrossAxis] - start[acrossAxis]
|
|
834
|
+
const endAcross = segmentEnd[acrossAxis] - start[acrossAxis]
|
|
835
|
+
const minAlong = Math.min(startAlong, endAlong)
|
|
836
|
+
const maxAlong = Math.max(startAlong, endAlong)
|
|
837
|
+
const minAcross = Math.min(startAcross, endAcross)
|
|
838
|
+
const maxAcross = Math.max(startAcross, endAcross)
|
|
839
|
+
|
|
840
|
+
let collisionDistance: number | undefined
|
|
841
|
+
const isCollinear =
|
|
842
|
+
Math.abs(startAcross) <= GEOMETRY_EPSILON &&
|
|
843
|
+
Math.abs(endAcross) <= GEOMETRY_EPSILON
|
|
844
|
+
if (
|
|
845
|
+
isCollinear &&
|
|
846
|
+
maxAlong >= -GEOMETRY_EPSILON &&
|
|
847
|
+
minAlong <= intendedLength + GEOMETRY_EPSILON
|
|
848
|
+
) {
|
|
849
|
+
collisionDistance = Math.max(0, minAlong)
|
|
850
|
+
} else {
|
|
851
|
+
const crossesStubAxis =
|
|
852
|
+
minAcross <= GEOMETRY_EPSILON && maxAcross >= -GEOMETRY_EPSILON
|
|
853
|
+
const perpendicularAlong = (startAlong + endAlong) / 2
|
|
854
|
+
if (
|
|
855
|
+
crossesStubAxis &&
|
|
856
|
+
Math.abs(startAlong - endAlong) <= GEOMETRY_EPSILON &&
|
|
857
|
+
perpendicularAlong >= -GEOMETRY_EPSILON &&
|
|
858
|
+
perpendicularAlong <= intendedLength + GEOMETRY_EPSILON
|
|
859
|
+
) {
|
|
860
|
+
collisionDistance = Math.max(0, perpendicularAlong)
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
if (collisionDistance !== undefined) {
|
|
865
|
+
availableLength = Math.min(
|
|
866
|
+
availableLength,
|
|
867
|
+
collisionDistance - INLINE_NET_LABEL_STUB_TRACE_CLEARANCE,
|
|
868
|
+
)
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
if (availableLength + GEOMETRY_EPSILON < minimumLength) return null
|
|
874
|
+
|
|
875
|
+
return isHorizontal
|
|
876
|
+
? { x: start.x + direction * availableLength, y: start.y }
|
|
877
|
+
: { x: start.x, y: start.y + direction * availableLength }
|
|
878
|
+
}
|
package/package.json
CHANGED