@tscircuit/schematic-trace-solver 0.0.198 → 0.0.200

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.js CHANGED
@@ -10274,7 +10274,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
10274
10274
  result.selected = true;
10275
10275
  return result;
10276
10276
  }
10277
- if (stopOnTraceCollision && result.status === "trace-collision") break;
10277
+ if (stopOnTraceCollision && result.status === "trace-collision" && (!projectedConnectorSource || orientation !== "y-" || !this.isGroundLabel(label)))
10278
+ break;
10278
10279
  }
10279
10280
  return null;
10280
10281
  }
@@ -13242,6 +13243,52 @@ var getUnconnectedPins = ({
13242
13243
  );
13243
13244
  return connectionPair.pins.filter((pin) => !connectedPinIds.has(pin.pinId));
13244
13245
  };
13246
+ var pathsIntersect = (firstPath, secondPath) => {
13247
+ for (let firstIndex = 0; firstIndex < firstPath.length - 1; firstIndex++) {
13248
+ for (let secondIndex = 0; secondIndex < secondPath.length - 1; secondIndex++) {
13249
+ if (doSegmentsIntersect3(
13250
+ firstPath[firstIndex],
13251
+ firstPath[firstIndex + 1],
13252
+ secondPath[secondIndex],
13253
+ secondPath[secondIndex + 1]
13254
+ )) {
13255
+ return true;
13256
+ }
13257
+ }
13258
+ }
13259
+ return false;
13260
+ };
13261
+ var connectionPairPinsAreAlreadyConnected = ({
13262
+ connectionPair,
13263
+ sameNetTraces
13264
+ }) => {
13265
+ const [firstPin, secondPin] = connectionPair.pins;
13266
+ const connectedTraceIndexes = new Set(
13267
+ sameNetTraces.flatMap(
13268
+ (trace, index) => trace.pinIds.includes(firstPin.pinId) ? [index] : []
13269
+ )
13270
+ );
13271
+ let previousSize = -1;
13272
+ while (connectedTraceIndexes.size !== previousSize) {
13273
+ previousSize = connectedTraceIndexes.size;
13274
+ for (let traceIndex = 0; traceIndex < sameNetTraces.length; traceIndex++) {
13275
+ if (connectedTraceIndexes.has(traceIndex)) continue;
13276
+ const trace = sameNetTraces[traceIndex];
13277
+ const connectsToComponent = [...connectedTraceIndexes].some(
13278
+ (connectedTraceIndex) => {
13279
+ const connectedTrace = sameNetTraces[connectedTraceIndex];
13280
+ return trace.pinIds.some(
13281
+ (pinId) => connectedTrace.pinIds.includes(pinId)
13282
+ ) || pathsIntersect(trace.tracePath, connectedTrace.tracePath);
13283
+ }
13284
+ );
13285
+ if (connectsToComponent) connectedTraceIndexes.add(traceIndex);
13286
+ }
13287
+ }
13288
+ return [...connectedTraceIndexes].some(
13289
+ (traceIndex) => sameNetTraces[traceIndex].pinIds.includes(secondPin.pinId)
13290
+ );
13291
+ };
13245
13292
  var getJunctionCandidates = ({
13246
13293
  connectionPair,
13247
13294
  sameNetTraces,
@@ -13506,6 +13553,12 @@ var UnroutedTraceRecoverySolver = class extends BaseSolver {
13506
13553
  const sameNetTraces = existingTraces.filter(
13507
13554
  (trace) => trace.globalConnNetId === connectionPair.globalConnNetId
13508
13555
  );
13556
+ if (connectionPairPinsAreAlreadyConnected({
13557
+ connectionPair,
13558
+ sameNetTraces
13559
+ })) {
13560
+ return;
13561
+ }
13509
13562
  const junctionCandidates = getJunctionCandidates({
13510
13563
  connectionPair,
13511
13564
  sameNetTraces,
@@ -14518,7 +14571,7 @@ var getAlignedAttachedLabelConnectorPath = ({
14518
14571
  const reverseCandidate = findCandidate([...forwardPath].reverse());
14519
14572
  return reverseCandidate ? reverseCandidate.reverse() : null;
14520
14573
  };
14521
- var pathsIntersect = (firstPath, secondPath) => {
14574
+ var pathsIntersect2 = (firstPath, secondPath) => {
14522
14575
  if (firstPath.some((point) => tracePathContainsPoint(secondPath, point)) || secondPath.some((point) => tracePathContainsPoint(firstPath, point))) {
14523
14576
  return true;
14524
14577
  }
@@ -14545,7 +14598,7 @@ var preserveAttachedTraceJunctions = ({
14545
14598
  (trace) => trace.mspPairId === originalTrace.mspPairId ? candidateTrace : trace
14546
14599
  );
14547
14600
  for (const connector of traces) {
14548
- if (connector.mspPairId === originalTrace.mspPairId || connector.globalConnNetId !== originalTrace.globalConnNetId || !pathsIntersect(originalTrace.tracePath, connector.tracePath) || pathsIntersect(candidateTrace.tracePath, connector.tracePath)) {
14601
+ if (connector.mspPairId === originalTrace.mspPairId || connector.globalConnNetId !== originalTrace.globalConnNetId || !pathsIntersect2(originalTrace.tracePath, connector.tracePath) || pathsIntersect2(candidateTrace.tracePath, connector.tracePath)) {
14549
14602
  continue;
14550
14603
  }
14551
14604
  const endpointIndex = [0, connector.tracePath.length - 1].find(
@@ -14578,7 +14631,7 @@ var preserveAttachedTraceJunctions = ({
14578
14631
  (point, index) => index === endpointIndex ? movedJunction : point
14579
14632
  )
14580
14633
  };
14581
- if (!pathsIntersect(candidateTrace.tracePath, movedConnector.tracePath)) {
14634
+ if (!pathsIntersect2(candidateTrace.tracePath, movedConnector.tracePath)) {
14582
14635
  return null;
14583
14636
  }
14584
14637
  outputTraces = outputTraces.map(
@@ -1172,7 +1172,16 @@ export class AvailableNetOrientationSolver extends BaseSolver {
1172
1172
  result.selected = true
1173
1173
  return result
1174
1174
  }
1175
- if (stopOnTraceCollision && result.status === "trace-collision") break
1175
+ // A downward ground branch projected onto its existing trace can reach a
1176
+ // clear position below a crossing trace.
1177
+ if (
1178
+ stopOnTraceCollision &&
1179
+ result.status === "trace-collision" &&
1180
+ (!projectedConnectorSource ||
1181
+ orientation !== "y-" ||
1182
+ !this.isGroundLabel(label))
1183
+ )
1184
+ break
1176
1185
  }
1177
1186
 
1178
1187
  return null
@@ -204,6 +204,67 @@ const getUnconnectedPins = ({
204
204
  return connectionPair.pins.filter((pin) => !connectedPinIds.has(pin.pinId))
205
205
  }
206
206
 
207
+ const pathsIntersect = (firstPath: Point[], secondPath: Point[]): boolean => {
208
+ for (let firstIndex = 0; firstIndex < firstPath.length - 1; firstIndex++) {
209
+ for (
210
+ let secondIndex = 0;
211
+ secondIndex < secondPath.length - 1;
212
+ secondIndex++
213
+ ) {
214
+ if (
215
+ doSegmentsIntersect(
216
+ firstPath[firstIndex]!,
217
+ firstPath[firstIndex + 1]!,
218
+ secondPath[secondIndex]!,
219
+ secondPath[secondIndex + 1]!,
220
+ )
221
+ ) {
222
+ return true
223
+ }
224
+ }
225
+ }
226
+ return false
227
+ }
228
+
229
+ const connectionPairPinsAreAlreadyConnected = ({
230
+ connectionPair,
231
+ sameNetTraces,
232
+ }: {
233
+ connectionPair: MspConnectionPair
234
+ sameNetTraces: SolvedTracePath[]
235
+ }): boolean => {
236
+ const [firstPin, secondPin] = connectionPair.pins
237
+ const connectedTraceIndexes = new Set(
238
+ sameNetTraces.flatMap((trace, index) =>
239
+ trace.pinIds.includes(firstPin.pinId) ? [index] : [],
240
+ ),
241
+ )
242
+
243
+ let previousSize = -1
244
+ while (connectedTraceIndexes.size !== previousSize) {
245
+ previousSize = connectedTraceIndexes.size
246
+ for (let traceIndex = 0; traceIndex < sameNetTraces.length; traceIndex++) {
247
+ if (connectedTraceIndexes.has(traceIndex)) continue
248
+ const trace = sameNetTraces[traceIndex]!
249
+ const connectsToComponent = [...connectedTraceIndexes].some(
250
+ (connectedTraceIndex) => {
251
+ const connectedTrace = sameNetTraces[connectedTraceIndex]!
252
+ return (
253
+ trace.pinIds.some((pinId) =>
254
+ connectedTrace.pinIds.includes(pinId),
255
+ ) || pathsIntersect(trace.tracePath, connectedTrace.tracePath)
256
+ )
257
+ },
258
+ )
259
+ if (connectsToComponent) connectedTraceIndexes.add(traceIndex)
260
+ }
261
+ }
262
+
263
+ return [...connectedTraceIndexes].some((traceIndex) =>
264
+ sameNetTraces[traceIndex]!.pinIds.includes(secondPin.pinId),
265
+ )
266
+ }
267
+
207
268
  const getJunctionCandidates = ({
208
269
  connectionPair,
209
270
  sameNetTraces,
@@ -552,6 +613,14 @@ export class UnroutedTraceRecoverySolver extends BaseSolver {
552
613
  const sameNetTraces = existingTraces.filter(
553
614
  (trace) => trace.globalConnNetId === connectionPair.globalConnNetId,
554
615
  )
616
+ if (
617
+ connectionPairPinsAreAlreadyConnected({
618
+ connectionPair,
619
+ sameNetTraces,
620
+ })
621
+ ) {
622
+ return
623
+ }
555
624
  const junctionCandidates = getJunctionCandidates({
556
625
  connectionPair,
557
626
  sameNetTraces,
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "url": "https://github.com/tscircuit/schematic-trace-solver.git"
6
6
  },
7
7
  "main": "dist/index.js",
8
- "version": "0.0.198",
8
+ "version": "0.0.200",
9
9
  "type": "module",
10
10
  "scripts": {
11
11
  "start": "cosmos",
@@ -0,0 +1,4 @@
1
+ import { PipelineDebugger } from "site/components/PipelineDebugger"
2
+ import inputProblem from "../../tests/bug-reports/bug-report-20260916T054012Z/bug-report-20260916T054012Z.json"
3
+
4
+ export default () => <PipelineDebugger inputProblem={inputProblem as any} />