@tscircuit/core 0.0.958 → 0.0.960

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 CHANGED
@@ -11,7 +11,7 @@ import { symbols, SchSymbol, BaseSymbolName } from 'schematic-symbols';
11
11
  import { Matrix } from 'transformation-matrix';
12
12
  import { CircuitJsonUtilObjects } from '@tscircuit/circuit-json-util';
13
13
  import { PackSolver2 } from 'calculate-packing';
14
- import { AutoroutingPipelineSolver, AssignableAutoroutingPipeline2 } from '@tscircuit/capacity-autorouter';
14
+ import { AutoroutingPipelineSolver, AssignableAutoroutingPipeline2, AssignableAutoroutingPipeline3 } from '@tscircuit/capacity-autorouter';
15
15
  import { CopperPourPipelineSolver } from '@tscircuit/copper-pour-solver';
16
16
  import { ConnectivityMap } from 'circuit-json-to-connectivity-map';
17
17
  import { GraphicsObject } from 'graphics-debug';
@@ -128,6 +128,7 @@ declare const SOLVERS: {
128
128
  PackSolver2: typeof PackSolver2;
129
129
  AutoroutingPipelineSolver: typeof AutoroutingPipelineSolver;
130
130
  AssignableAutoroutingPipeline2: typeof AssignableAutoroutingPipeline2;
131
+ AssignableAutoroutingPipeline3: typeof AssignableAutoroutingPipeline3;
131
132
  CopperPourPipelineSolver: typeof CopperPourPipelineSolver;
132
133
  };
133
134
  type SolverName = keyof typeof SOLVERS;
@@ -148,6 +149,18 @@ type SimplifiedPcbTrace = {
148
149
  y: number;
149
150
  to_layer: string;
150
151
  from_layer: string;
152
+ } | {
153
+ route_type: "jumper";
154
+ start: {
155
+ x: number;
156
+ y: number;
157
+ };
158
+ end: {
159
+ x: number;
160
+ y: number;
161
+ };
162
+ footprint: "0603" | "1206" | "1206x4_pair";
163
+ layer: string;
151
164
  }>;
152
165
  };
153
166
  type Obstacle = {
@@ -194,6 +207,7 @@ interface SimpleRouteJson {
194
207
  y: number;
195
208
  }>;
196
209
  traces?: SimplifiedPcbTrace[];
210
+ allowJumpers?: boolean;
197
211
  }
198
212
 
199
213
  type RootCircuitEventName = "asyncEffect:start" | "asyncEffect:end" | "renderable:renderLifecycle:anyEvent" | `renderable:renderLifecycle:${RenderPhase}:start` | `renderable:renderLifecycle:${RenderPhase}:end` | `board:renderPhaseStarted` | "external:evalError" | "autorouting:start" | "autorouting:end" | "autorouting:error" | "autorouting:progress" | "packing:start" | "packing:end" | "packing:error" | "solver:started" | "renderComplete" | "debug:logOutput";
@@ -336,6 +350,7 @@ interface ISubcircuit extends PrimitiveComponent {
336
350
  _shouldUseTraceByTraceRouting(): boolean;
337
351
  _parsedProps: z.infer<typeof subcircuitGroupProps>;
338
352
  _getAutorouterConfig(): AutorouterConfig;
353
+ _isAutoJumperAutorouter(autorouterConfig?: AutorouterConfig): boolean;
339
354
  getNextAvailableName(elm: PrimitiveComponent): string;
340
355
  _getSubcircuitLayerCount(): number;
341
356
  subcircuit_id: string | null;
@@ -1352,6 +1367,23 @@ declare class Group<Props extends z.ZodType<any, any, any> = typeof groupProps>
1352
1367
  _asyncAutoroutingResult: {
1353
1368
  output_simple_route_json?: SimpleRouteJson;
1354
1369
  output_pcb_traces?: (PcbTrace$1 | PcbVia)[];
1370
+ output_jumpers?: Array<{
1371
+ jumper_footprint: string;
1372
+ center: {
1373
+ x: number;
1374
+ y: number;
1375
+ };
1376
+ orientation: string;
1377
+ pads: Array<{
1378
+ center: {
1379
+ x: number;
1380
+ y: number;
1381
+ };
1382
+ width: number;
1383
+ height: number;
1384
+ layer: string;
1385
+ }>;
1386
+ }>;
1355
1387
  } | null;
1356
1388
  get config(): {
1357
1389
  zodProps: Props;
@@ -1413,6 +1445,7 @@ declare class Group<Props extends z.ZodType<any, any, any> = typeof groupProps>
1413
1445
  };
1414
1446
  _getAutorouterConfig(): AutorouterConfig;
1415
1447
  _isLaserPrefabAutorouter(autorouterConfig?: AutorouterConfig): boolean;
1448
+ _isAutoJumperAutorouter(autorouterConfig?: AutorouterConfig): boolean;
1416
1449
  _getSubcircuitLayerCount(): number;
1417
1450
  /**
1418
1451
  * Trace-by-trace autorouting is where each trace routes itself in a well-known
package/dist/index.js CHANGED
@@ -6742,10 +6742,13 @@ var Trace_doInitialSchematicTraceRender = (trace) => {
6742
6742
  }
6743
6743
  const [{ route }] = results;
6744
6744
  edges = [];
6745
- for (let i = 0; i < route.length - 1; i++) {
6745
+ const wireAndViaRoutes = route.filter(
6746
+ (r) => r.route_type === "wire" || r.route_type === "via"
6747
+ );
6748
+ for (let i = 0; i < wireAndViaRoutes.length - 1; i++) {
6746
6749
  edges.push({
6747
- from: route[i],
6748
- to: route[i + 1]
6750
+ from: wireAndViaRoutes[i],
6751
+ to: wireAndViaRoutes[i + 1]
6749
6752
  });
6750
6753
  }
6751
6754
  }
@@ -9708,13 +9711,15 @@ import "@tscircuit/capacity-autorouter";
9708
9711
  import { PackSolver2 } from "calculate-packing";
9709
9712
  import {
9710
9713
  AutoroutingPipelineSolver,
9711
- AssignableAutoroutingPipeline2
9714
+ AssignableAutoroutingPipeline2,
9715
+ AssignableAutoroutingPipeline3
9712
9716
  } from "@tscircuit/capacity-autorouter";
9713
9717
  import { CopperPourPipelineSolver } from "@tscircuit/copper-pour-solver";
9714
9718
  var SOLVERS = {
9715
9719
  PackSolver2,
9716
9720
  AutoroutingPipelineSolver,
9717
9721
  AssignableAutoroutingPipeline2,
9722
+ AssignableAutoroutingPipeline3,
9718
9723
  CopperPourPipelineSolver
9719
9724
  };
9720
9725
 
@@ -9738,9 +9743,17 @@ var TscircuitAutorouter = class {
9738
9743
  targetMinCapacity,
9739
9744
  stepDelay = 0,
9740
9745
  useAssignableSolver = false,
9746
+ useAutoJumperSolver = false,
9741
9747
  onSolverStarted
9742
9748
  } = options;
9743
- const solverName = useAssignableSolver ? "AssignableAutoroutingPipeline2" : "AutoroutingPipelineSolver";
9749
+ let solverName;
9750
+ if (useAutoJumperSolver) {
9751
+ solverName = "AssignableAutoroutingPipeline3";
9752
+ } else if (useAssignableSolver) {
9753
+ solverName = "AssignableAutoroutingPipeline2";
9754
+ } else {
9755
+ solverName = "AutoroutingPipelineSolver";
9756
+ }
9744
9757
  const SolverClass = SOLVERS[solverName];
9745
9758
  this.solver = new SolverClass(input, {
9746
9759
  capacityDepth,
@@ -12083,6 +12096,20 @@ function getPresetAutoroutingConfig(autorouterConfig) {
12083
12096
  ...rest
12084
12097
  };
12085
12098
  }
12099
+ case "auto-jumper": {
12100
+ const {
12101
+ preset: _preset,
12102
+ local: _local,
12103
+ groupMode: _groupMode,
12104
+ ...rest
12105
+ } = providedConfig;
12106
+ return {
12107
+ local: true,
12108
+ groupMode: "subcircuit",
12109
+ preset: "auto_jumper",
12110
+ ...rest
12111
+ };
12112
+ }
12086
12113
  default:
12087
12114
  return {
12088
12115
  local: true,
@@ -13974,6 +14001,97 @@ function computeCenterFromAnchorPosition(anchorPosition, ctx) {
13974
14001
  }
13975
14002
  }
13976
14003
 
14004
+ // lib/components/primitive-components/Group/insert-autoplaced-jumpers.ts
14005
+ function insertAutoplacedJumpers(params) {
14006
+ const { db, output_jumpers, subcircuit_id } = params;
14007
+ for (let jumperIndex = 0; jumperIndex < output_jumpers.length; jumperIndex++) {
14008
+ const jumper = output_jumpers[jumperIndex];
14009
+ const sourceComponent = db.source_component.insert({
14010
+ ftype: "simple_chip",
14011
+ // Use internal naming convention to avoid conflicts with user-specified names
14012
+ name: `__autoplaced_jumper_${jumperIndex}`,
14013
+ supplier_part_numbers: {}
14014
+ });
14015
+ const rotation4 = jumper.orientation === "horizontal" ? 0 : 90;
14016
+ const firstPadLayer = jumper.pads[0]?.layer || jumper.pads[0]?.layers?.[0] || "top";
14017
+ const pcbComponent = db.pcb_component.insert({
14018
+ source_component_id: sourceComponent.source_component_id,
14019
+ center: jumper.center,
14020
+ rotation: rotation4,
14021
+ layer: firstPadLayer,
14022
+ width: jumper.width || 0,
14023
+ height: jumper.height || 0,
14024
+ obstructs_within_bounds: false
14025
+ });
14026
+ for (const pad of jumper.pads) {
14027
+ const padLayer = pad.layer || pad.layers?.[0] || "top";
14028
+ db.pcb_smtpad.insert({
14029
+ pcb_component_id: pcbComponent.pcb_component_id,
14030
+ shape: "rect",
14031
+ x: pad.center.x,
14032
+ y: pad.center.y,
14033
+ width: pad.width,
14034
+ height: pad.height,
14035
+ layer: padLayer
14036
+ });
14037
+ }
14038
+ }
14039
+ }
14040
+
14041
+ // lib/components/primitive-components/Group/split-pcb-traces-on-jumper-segments.ts
14042
+ function splitPcbTracesOnJumperSegments(route) {
14043
+ const jumperRoutes = route.filter(
14044
+ (p) => p.route_type === "jumper"
14045
+ );
14046
+ const wireAndViaRoutes = route.filter((p) => p.route_type !== "jumper");
14047
+ if (jumperRoutes.length === 0) {
14048
+ return null;
14049
+ }
14050
+ const splitRanges = [];
14051
+ for (const jumperRoute of jumperRoutes) {
14052
+ const jumperStart = jumperRoute.start;
14053
+ const jumperEnd = jumperRoute.end;
14054
+ let startIdx = -1;
14055
+ let endIdx = -1;
14056
+ let minStartDist = Infinity;
14057
+ let minEndDist = Infinity;
14058
+ for (let i = 0; i < wireAndViaRoutes.length; i++) {
14059
+ const p = wireAndViaRoutes[i];
14060
+ if (p.route_type !== "wire") continue;
14061
+ const distToStart = Math.hypot(p.x - jumperStart.x, p.y - jumperStart.y);
14062
+ const distToEnd = Math.hypot(p.x - jumperEnd.x, p.y - jumperEnd.y);
14063
+ if (distToStart < minStartDist) {
14064
+ minStartDist = distToStart;
14065
+ startIdx = i;
14066
+ }
14067
+ if (distToEnd < minEndDist) {
14068
+ minEndDist = distToEnd;
14069
+ endIdx = i;
14070
+ }
14071
+ }
14072
+ if (startIdx > endIdx) {
14073
+ ;
14074
+ [startIdx, endIdx] = [endIdx, startIdx];
14075
+ }
14076
+ if (startIdx >= 0 && endIdx >= 0 && startIdx !== endIdx) {
14077
+ splitRanges.push({ startIdx, endIdx });
14078
+ }
14079
+ }
14080
+ splitRanges.sort((a, b) => a.startIdx - b.startIdx);
14081
+ const segments = [];
14082
+ let currentStart = 0;
14083
+ for (const range of splitRanges) {
14084
+ if (currentStart < range.startIdx) {
14085
+ segments.push(wireAndViaRoutes.slice(currentStart, range.startIdx + 1));
14086
+ }
14087
+ currentStart = range.endIdx;
14088
+ }
14089
+ if (currentStart < wireAndViaRoutes.length) {
14090
+ segments.push(wireAndViaRoutes.slice(currentStart));
14091
+ }
14092
+ return segments;
14093
+ }
14094
+
13977
14095
  // lib/components/primitive-components/Group/Group.ts
13978
14096
  var Group6 = class extends NormalComponent3 {
13979
14097
  pcb_group_id = null;
@@ -14309,6 +14427,7 @@ var Group6 = class extends NormalComponent3 {
14309
14427
  debug11(`[${this.getString()}] starting local autorouting`);
14310
14428
  const autorouterConfig = this._getAutorouterConfig();
14311
14429
  const isLaserPrefabPreset = this._isLaserPrefabAutorouter(autorouterConfig);
14430
+ const isAutoJumperPreset = this._isAutoJumperAutorouter(autorouterConfig);
14312
14431
  const isSingleLayerBoard = this._getSubcircuitLayerCount() === 1;
14313
14432
  const { simpleRouteJson } = getSimpleRouteJsonFromCircuitJson({
14314
14433
  db,
@@ -14316,6 +14435,9 @@ var Group6 = class extends NormalComponent3 {
14316
14435
  nominalTraceWidth: this.props.nominalTraceWidth,
14317
14436
  subcircuit_id: this.subcircuit_id
14318
14437
  });
14438
+ if (isAutoJumperPreset) {
14439
+ simpleRouteJson.allowJumpers = true;
14440
+ }
14319
14441
  if (debug11.enabled) {
14320
14442
  ;
14321
14443
  global.debugOutputArray?.push({
@@ -14344,6 +14466,7 @@ var Group6 = class extends NormalComponent3 {
14344
14466
  capacityDepth: this.props.autorouter?.capacityDepth,
14345
14467
  targetMinCapacity: this.props.autorouter?.targetMinCapacity,
14346
14468
  useAssignableSolver: isLaserPrefabPreset || isSingleLayerBoard,
14469
+ useAutoJumperSolver: isAutoJumperPreset,
14347
14470
  onSolverStarted: ({ solverName, solverParams }) => this.root?.emit("solver:started", {
14348
14471
  type: "solver:started",
14349
14472
  solverName,
@@ -14385,8 +14508,14 @@ var Group6 = class extends NormalComponent3 {
14385
14508
  subcircuit_id: this.subcircuit_id
14386
14509
  });
14387
14510
  }
14511
+ let outputJumpers = [];
14512
+ const solver = autorouter.solver;
14513
+ if (solver?.getOutputJumpers) {
14514
+ outputJumpers = solver.getOutputJumpers() || [];
14515
+ }
14388
14516
  this._asyncAutoroutingResult = {
14389
- output_pcb_traces: traces
14517
+ output_pcb_traces: traces,
14518
+ output_jumpers: outputJumpers
14390
14519
  };
14391
14520
  this._markDirty("PcbTraceRender");
14392
14521
  } catch (error) {
@@ -14489,11 +14618,18 @@ var Group6 = class extends NormalComponent3 {
14489
14618
  }
14490
14619
  }
14491
14620
  _updatePcbTraceRenderFromPcbTraces() {
14492
- const { output_pcb_traces } = this._asyncAutoroutingResult;
14621
+ const { output_pcb_traces, output_jumpers } = this._asyncAutoroutingResult;
14493
14622
  if (!output_pcb_traces) return;
14494
14623
  const { db } = this.root;
14495
14624
  const pcbStyle = this.getInheritedMergedProperty("pcbStyle");
14496
14625
  const { holeDiameter, padDiameter } = getViaDiameterDefaults(pcbStyle);
14626
+ if (output_jumpers && output_jumpers.length > 0) {
14627
+ insertAutoplacedJumpers({
14628
+ db,
14629
+ output_jumpers,
14630
+ subcircuit_id: this.subcircuit_id
14631
+ });
14632
+ }
14497
14633
  for (const pcb_trace of output_pcb_traces) {
14498
14634
  if (pcb_trace.type !== "pcb_trace") continue;
14499
14635
  pcb_trace.subcircuit_id = this.subcircuit_id;
@@ -14501,7 +14637,19 @@ var Group6 = class extends NormalComponent3 {
14501
14637
  const sourceTraceId = pcb_trace.connection_name;
14502
14638
  pcb_trace.source_trace_id = sourceTraceId;
14503
14639
  }
14504
- db.pcb_trace.insert(pcb_trace);
14640
+ const segments = splitPcbTracesOnJumperSegments(pcb_trace.route);
14641
+ if (segments === null) {
14642
+ db.pcb_trace.insert(pcb_trace);
14643
+ continue;
14644
+ }
14645
+ for (const segment2 of segments) {
14646
+ if (segment2.length > 0) {
14647
+ db.pcb_trace.insert({
14648
+ ...pcb_trace,
14649
+ route: segment2
14650
+ });
14651
+ }
14652
+ }
14505
14653
  }
14506
14654
  for (const pcb_trace of output_pcb_traces) {
14507
14655
  if (pcb_trace.type === "pcb_via") {
@@ -14748,6 +14896,18 @@ var Group6 = class extends NormalComponent3 {
14748
14896
  }
14749
14897
  return false;
14750
14898
  }
14899
+ _isAutoJumperAutorouter(autorouterConfig = this._getAutorouterConfig()) {
14900
+ const autorouterProp = this.props.autorouter;
14901
+ const normalize = (value) => value?.replace(/-/g, "_") ?? value;
14902
+ if (autorouterConfig.preset === "auto_jumper") return true;
14903
+ if (typeof autorouterProp === "string") {
14904
+ return normalize(autorouterProp) === "auto_jumper";
14905
+ }
14906
+ if (typeof autorouterProp === "object" && autorouterProp) {
14907
+ return normalize(autorouterProp.preset) === "auto_jumper";
14908
+ }
14909
+ return false;
14910
+ }
14751
14911
  _getSubcircuitLayerCount() {
14752
14912
  const layers = this.getInheritedProperty("layers");
14753
14913
  return typeof layers === "number" ? layers : 2;
@@ -20376,7 +20536,7 @@ import { identity as identity5 } from "transformation-matrix";
20376
20536
  var package_default = {
20377
20537
  name: "@tscircuit/core",
20378
20538
  type: "module",
20379
- version: "0.0.957",
20539
+ version: "0.0.959",
20380
20540
  types: "dist/index.d.ts",
20381
20541
  main: "dist/index.js",
20382
20542
  module: "dist/index.js",
@@ -20407,7 +20567,7 @@ var package_default = {
20407
20567
  devDependencies: {
20408
20568
  "@biomejs/biome": "^1.8.3",
20409
20569
  "@resvg/resvg-js": "^2.6.2",
20410
- "@tscircuit/capacity-autorouter": "^0.0.223",
20570
+ "@tscircuit/capacity-autorouter": "^0.0.247",
20411
20571
  "@tscircuit/checks": "^0.0.87",
20412
20572
  "@tscircuit/circuit-json-util": "^0.0.73",
20413
20573
  "@tscircuit/common": "^0.0.20",
@@ -20419,7 +20579,7 @@ var package_default = {
20419
20579
  "@tscircuit/math-utils": "^0.0.29",
20420
20580
  "@tscircuit/miniflex": "^0.0.4",
20421
20581
  "@tscircuit/ngspice-spice-engine": "^0.0.8",
20422
- "@tscircuit/props": "^0.0.440",
20582
+ "@tscircuit/props": "^0.0.441",
20423
20583
  "@tscircuit/schematic-match-adapt": "^0.0.16",
20424
20584
  "@tscircuit/schematic-trace-solver": "^v0.0.45",
20425
20585
  "@tscircuit/solver-utils": "^0.0.3",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.958",
4
+ "version": "0.0.960",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
@@ -32,7 +32,7 @@
32
32
  "devDependencies": {
33
33
  "@biomejs/biome": "^1.8.3",
34
34
  "@resvg/resvg-js": "^2.6.2",
35
- "@tscircuit/capacity-autorouter": "^0.0.223",
35
+ "@tscircuit/capacity-autorouter": "^0.0.247",
36
36
  "@tscircuit/checks": "^0.0.87",
37
37
  "@tscircuit/circuit-json-util": "^0.0.73",
38
38
  "@tscircuit/common": "^0.0.20",
@@ -44,7 +44,7 @@
44
44
  "@tscircuit/math-utils": "^0.0.29",
45
45
  "@tscircuit/miniflex": "^0.0.4",
46
46
  "@tscircuit/ngspice-spice-engine": "^0.0.8",
47
- "@tscircuit/props": "^0.0.440",
47
+ "@tscircuit/props": "^0.0.441",
48
48
  "@tscircuit/schematic-match-adapt": "^0.0.16",
49
49
  "@tscircuit/schematic-trace-solver": "^v0.0.45",
50
50
  "@tscircuit/solver-utils": "^0.0.3",