@tscircuit/core 0.0.1296 → 0.0.1298

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.
Files changed (2) hide show
  1. package/dist/index.js +166 -73
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2234,6 +2234,10 @@ function pairs(arr) {
2234
2234
  return result;
2235
2235
  }
2236
2236
 
2237
+ // lib/utils/gnd-power-net-regex.ts
2238
+ var GROUND_NET_REGEX = /^(GND|AGND|DGND|PGND|VSS)/i;
2239
+ var POWER_NET_REGEX = /^V(?!SS)|^\d+(?:[_.]\d+)?[Vv]/i;
2240
+
2237
2241
  // lib/components/primitive-components/Net.ts
2238
2242
  import { autoroute } from "@tscircuit/infgrid-ijump-astar";
2239
2243
  var Net = class extends PrimitiveComponent2 {
@@ -2251,8 +2255,8 @@ var Net = class extends PrimitiveComponent2 {
2251
2255
  doInitialSourceRender() {
2252
2256
  const { db } = this.root;
2253
2257
  const { _parsedProps: props } = this;
2254
- const isGround = props.isGroundNet ?? props.name.startsWith("GND");
2255
- const isPositiveVoltageSource = props.isPowerNet ?? props.name.startsWith("V");
2258
+ const isGround = props.isGroundNet ?? GROUND_NET_REGEX.test(props.name);
2259
+ const isPositiveVoltageSource = props.isPowerNet ?? POWER_NET_REGEX.test(props.name);
2256
2260
  const net = db.source_net.insert({
2257
2261
  name: props.name,
2258
2262
  member_source_group_ids: [],
@@ -13765,7 +13769,7 @@ import {
13765
13769
  groupProps
13766
13770
  } from "@tscircuit/props";
13767
13771
  import {
13768
- distance as distance10
13772
+ distance as distance11
13769
13773
  } from "circuit-json";
13770
13774
  import Debug14 from "debug";
13771
13775
 
@@ -14472,6 +14476,56 @@ var getUnbrokenCopperPourObstacles = ({
14472
14476
  return obstacles;
14473
14477
  };
14474
14478
 
14479
+ // lib/utils/autorouting/trimRouteEndsAtBreakoutPoints.ts
14480
+ import {
14481
+ distance as distance9,
14482
+ getUnitVectorFromPointAToB as getUnitVectorFromPointAToB2
14483
+ } from "@tscircuit/math-utils";
14484
+ var DEFAULT_BREAKOUT_HANDOFF_TRIM_MM = 0.6;
14485
+ var getPointXY = (routePoint) => {
14486
+ const { x, y } = routePoint;
14487
+ return typeof x === "number" && typeof y === "number" ? { x, y } : null;
14488
+ };
14489
+ var trimRouteEndsAtBreakoutPoints = ({
14490
+ route,
14491
+ breakoutPointPositions,
14492
+ trimMm = DEFAULT_BREAKOUT_HANDOFF_TRIM_MM
14493
+ }) => {
14494
+ if (breakoutPointPositions.length === 0 || route.length < 2) return route;
14495
+ const isAtBreakoutPoint = (point6) => breakoutPointPositions.some((bp) => distance9(bp, point6) < 0.05);
14496
+ const trimFront = (points) => {
14497
+ const out = [...points];
14498
+ let remaining = trimMm;
14499
+ while (out.length >= 2 && remaining > 1e-9) {
14500
+ const a = getPointXY(out[0]);
14501
+ const b = getPointXY(out[1]);
14502
+ if (!a || !b) break;
14503
+ const segmentLength = distance9(a, b);
14504
+ if (segmentLength <= remaining + 1e-9) {
14505
+ out.shift();
14506
+ remaining -= segmentLength;
14507
+ } else {
14508
+ const unit = getUnitVectorFromPointAToB2(a, b);
14509
+ out[0] = {
14510
+ ...out[0],
14511
+ x: a.x + unit.x * remaining,
14512
+ y: a.y + unit.y * remaining
14513
+ };
14514
+ remaining = 0;
14515
+ }
14516
+ }
14517
+ return out;
14518
+ };
14519
+ let trimmed = route;
14520
+ const first = getPointXY(trimmed[0]);
14521
+ if (first && isAtBreakoutPoint(first)) trimmed = trimFront(trimmed);
14522
+ const last = getPointXY(trimmed[trimmed.length - 1]);
14523
+ if (last && trimmed.length >= 2 && isAtBreakoutPoint(last)) {
14524
+ trimmed = trimFront([...trimmed].reverse()).reverse();
14525
+ }
14526
+ return trimmed;
14527
+ };
14528
+
14475
14529
  // lib/utils/autorouting/getSimpleRouteJsonFromCircuitJson.ts
14476
14530
  var getSimpleRouteJsonFromCircuitJson = ({
14477
14531
  db,
@@ -14510,6 +14564,7 @@ var getSimpleRouteJsonFromCircuitJson = ({
14510
14564
  (e) => !subcircuit_id || "subcircuit_id" in e && relevantSubcircuitIds.has(e.subcircuit_id)
14511
14565
  );
14512
14566
  let board = null;
14567
+ let subcircuitIsBoard = false;
14513
14568
  if (subcircuit_id) {
14514
14569
  const source_group_id = subcircuit_id.replace(/^subcircuit_/, "");
14515
14570
  const source_board = db.source_board.getWhere({ source_group_id });
@@ -14517,6 +14572,7 @@ var getSimpleRouteJsonFromCircuitJson = ({
14517
14572
  board = db.pcb_board.getWhere({
14518
14573
  source_board_id: source_board.source_board_id
14519
14574
  });
14575
+ if (board) subcircuitIsBoard = true;
14520
14576
  }
14521
14577
  }
14522
14578
  if (!board) {
@@ -14550,13 +14606,24 @@ var getSimpleRouteJsonFromCircuitJson = ({
14550
14606
  group: pcbGroup
14551
14607
  })
14552
14608
  );
14609
+ const breakoutPointPositions = breakoutPoints.map((bp) => ({
14610
+ x: bp.x,
14611
+ y: bp.y
14612
+ }));
14613
+ const breakoutHandoffTrimMm = (minViaPadDiameter ?? board?.min_via_pad_diameter ?? 0.3) + 2 * (minTraceWidth ?? board?.min_trace_width ?? 0.15) + (minTraceToPadEdgeClearance ?? board?.min_trace_to_pad_edge_clearance ?? 0.1);
14553
14614
  const descendantTraces = subcircuit_id ? db.pcb_trace.list().filter(
14554
14615
  (t) => t.subcircuit_id && t.subcircuit_id !== subcircuit_id && relevantSubcircuitIds.has(t.subcircuit_id)
14555
14616
  ).map((t) => ({
14556
14617
  type: "pcb_trace",
14557
14618
  pcb_trace_id: t.pcb_trace_id,
14558
- route: t.route
14559
- })) : [];
14619
+ source_trace_id: t.source_trace_id,
14620
+ connection_name: t.source_trace_id ?? t.connection_name ?? t.pcb_trace_id,
14621
+ route: trimRouteEndsAtBreakoutPoints({
14622
+ route: t.route,
14623
+ breakoutPointPositions,
14624
+ trimMm: breakoutHandoffTrimMm
14625
+ })
14626
+ })).filter((t) => t.route.length >= 2) : [];
14560
14627
  for (const obstacle of obstacles) {
14561
14628
  const additionalIds = obstacle.connectedTo.flatMap(
14562
14629
  (id) => connMap.getIdsConnectedToNet(id)
@@ -14620,7 +14687,15 @@ var getSimpleRouteJsonFromCircuitJson = ({
14620
14687
  }
14621
14688
  ]).concat(board?.outline ?? []);
14622
14689
  let bounds;
14623
- if (board && !board.outline) {
14690
+ const useGroupBoundsAsSrjBounds = !!(pcbGroup?.width && pcbGroup.height && subcircuit_id && !subcircuitIsBoard);
14691
+ if (useGroupBoundsAsSrjBounds) {
14692
+ bounds = {
14693
+ minX: pcbGroup.center.x - pcbGroup.width / 2,
14694
+ maxX: pcbGroup.center.x + pcbGroup.width / 2,
14695
+ minY: pcbGroup.center.y - pcbGroup.height / 2,
14696
+ maxY: pcbGroup.center.y + pcbGroup.height / 2
14697
+ };
14698
+ } else if (board && !board.outline) {
14624
14699
  bounds = {
14625
14700
  minX: board.center.x - board.width / 2,
14626
14701
  maxX: board.center.x + board.width / 2,
@@ -14635,7 +14710,7 @@ var getSimpleRouteJsonFromCircuitJson = ({
14635
14710
  maxY: Math.max(...allPoints.map((p) => p.y)) + 1
14636
14711
  };
14637
14712
  }
14638
- if (pcbGroup?.width && pcbGroup.height) {
14713
+ if (pcbGroup?.width && pcbGroup.height && !useGroupBoundsAsSrjBounds) {
14639
14714
  const groupBounds = {
14640
14715
  minX: pcbGroup.center.x - pcbGroup.width / 2,
14641
14716
  maxX: pcbGroup.center.x + pcbGroup.width / 2,
@@ -19684,7 +19759,7 @@ function addPortIdsToTracesAtJumperPads(segments, db) {
19684
19759
  }
19685
19760
 
19686
19761
  // lib/components/primitive-components/Group/get-source-trace-id-for-routed-trace.ts
19687
- import { distance as distance9, pointToSegmentDistance } from "@tscircuit/math-utils";
19762
+ import { distance as distance10, pointToSegmentDistance } from "@tscircuit/math-utils";
19688
19763
  import { ConnectivityMap as ConnectivityMap3 } from "circuit-json-to-connectivity-map";
19689
19764
  var POINT_EPSILON = 1e-6;
19690
19765
  function isPointOnWireSegment({
@@ -19706,7 +19781,7 @@ function isPointInSmtPad({
19706
19781
  return Math.abs(point6.x - pad.x) <= pad.width / 2 + traceWidth / 2 && Math.abs(point6.y - pad.y) <= pad.height / 2 + traceWidth / 2;
19707
19782
  }
19708
19783
  if (pad.shape === "circle") {
19709
- return distance9(point6, pad) <= pad.radius + traceWidth / 2;
19784
+ return distance10(point6, pad) <= pad.radius + traceWidth / 2;
19710
19785
  }
19711
19786
  return false;
19712
19787
  }
@@ -19715,7 +19790,7 @@ function isPointInPlatedHole({
19715
19790
  hole,
19716
19791
  traceWidth = 0
19717
19792
  }) {
19718
- return distance9(point6, hole) <= (hole.outer_diameter ?? hole.hole_diameter ?? 0) / 2 + traceWidth / 2;
19793
+ return distance10(point6, hole) <= (hole.outer_diameter ?? hole.hole_diameter ?? 0) / 2 + traceWidth / 2;
19719
19794
  }
19720
19795
  function getEndpointSourcePortIdsFromGeometry(db, trace) {
19721
19796
  const sourcePortIds = /* @__PURE__ */ new Set();
@@ -19726,7 +19801,7 @@ function getEndpointSourcePortIdsFromGeometry(db, trace) {
19726
19801
  for (const endpoint of endpoints) {
19727
19802
  for (const pcbPort of db.pcb_port.list()) {
19728
19803
  if (!pcbPort.source_port_id) continue;
19729
- if (distance9(endpoint, pcbPort) <= 0.01) {
19804
+ if (distance10(endpoint, pcbPort) <= 0.01) {
19730
19805
  sourcePortIds.add(pcbPort.source_port_id);
19731
19806
  }
19732
19807
  }
@@ -20352,8 +20427,8 @@ var Group5 = class extends NormalComponent3 {
20352
20427
  const groupProps2 = props;
20353
20428
  const hasOutline = groupProps2.outline && groupProps2.outline.length > 0;
20354
20429
  const numericOutline = hasOutline ? groupProps2.outline.map((point6) => ({
20355
- x: distance10.parse(point6.x),
20356
- y: distance10.parse(point6.y)
20430
+ x: distance11.parse(point6.x),
20431
+ y: distance11.parse(point6.y)
20357
20432
  })) : void 0;
20358
20433
  const ctx = this.props;
20359
20434
  const anchorPosition = this._getGlobalPcbPositionBeforeLayout();
@@ -20391,8 +20466,8 @@ var Group5 = class extends NormalComponent3 {
20391
20466
  const hasExplicitPositioning = this._parsedProps.pcbX !== void 0 || this._parsedProps.pcbY !== void 0;
20392
20467
  if (hasOutline) {
20393
20468
  const numericOutline = props.outline.map((point6) => ({
20394
- x: distance10.parse(point6.x),
20395
- y: distance10.parse(point6.y)
20469
+ x: distance11.parse(point6.x),
20470
+ y: distance11.parse(point6.y)
20396
20471
  }));
20397
20472
  const outlineBounds = getBoundsFromPoints4(numericOutline);
20398
20473
  if (!outlineBounds) return;
@@ -21426,13 +21501,13 @@ var Group5 = class extends NormalComponent3 {
21426
21501
  for (const nl of subtree.schematic_net_label.list()) {
21427
21502
  const net = subtree.source_net.get(nl.source_net_id);
21428
21503
  const text = nl.text || net?.name || "";
21429
- if (nl.anchor_side === "top" && /^gnd/i.test(text)) {
21504
+ if (nl.anchor_side === "top" && GROUND_NET_REGEX.test(text)) {
21430
21505
  subtree.schematic_net_label.update(nl.schematic_net_label_id, {
21431
21506
  symbol_name: "rail_down"
21432
21507
  });
21433
21508
  continue;
21434
21509
  }
21435
- if (nl.anchor_side === "bottom" && /^v/i.test(text)) {
21510
+ if (nl.anchor_side === "bottom" && POWER_NET_REGEX.test(text)) {
21436
21511
  subtree.schematic_net_label.update(nl.schematic_net_label_id, {
21437
21512
  symbol_name: "rail_up"
21438
21513
  });
@@ -22426,7 +22501,7 @@ import { identity as identity5 } from "transformation-matrix";
22426
22501
  var package_default = {
22427
22502
  name: "@tscircuit/core",
22428
22503
  type: "module",
22429
- version: "0.0.1295",
22504
+ version: "0.0.1297",
22430
22505
  types: "dist/index.d.ts",
22431
22506
  main: "dist/index.js",
22432
22507
  module: "dist/index.js",
@@ -23608,11 +23683,11 @@ var MountedBoard = class extends Subcircuit {
23608
23683
 
23609
23684
  // lib/components/normal-components/Panel.ts
23610
23685
  import { panelProps } from "@tscircuit/props";
23611
- import { distance as distance14 } from "circuit-json";
23686
+ import { distance as distance15 } from "circuit-json";
23612
23687
 
23613
23688
  // lib/components/normal-components/Subpanel.ts
23614
23689
  import { subpanelProps } from "@tscircuit/props";
23615
- import { distance as distance13 } from "circuit-json";
23690
+ import { distance as distance14 } from "circuit-json";
23616
23691
  import { compose as compose7, identity as identity6, translate as translate7 } from "transformation-matrix";
23617
23692
 
23618
23693
  // lib/utils/panels/generate-panel-tabs-and-mouse-bites.ts
@@ -23825,15 +23900,15 @@ function generatePanelTabsAndMouseBites(boards, options) {
23825
23900
  }
23826
23901
 
23827
23902
  // lib/utils/panels/pack-into-grid.ts
23828
- import { distance as distance12 } from "circuit-json";
23903
+ import { distance as distance13 } from "circuit-json";
23829
23904
 
23830
23905
  // lib/utils/panels/get-board-dimensions-from-props.ts
23831
23906
  import { getBoundsFromPoints as getBoundsFromPoints6 } from "@tscircuit/math-utils";
23832
- import { distance as distance11 } from "circuit-json";
23907
+ import { distance as distance12 } from "circuit-json";
23833
23908
  var getBoardDimensionsFromProps = (board) => {
23834
23909
  const props = board._parsedProps;
23835
- let width = props.width != null ? distance11.parse(props.width) : void 0;
23836
- let height = props.height != null ? distance11.parse(props.height) : void 0;
23910
+ let width = props.width != null ? distance12.parse(props.width) : void 0;
23911
+ let height = props.height != null ? distance12.parse(props.height) : void 0;
23837
23912
  if ((width === void 0 || height === void 0) && props.outline?.length) {
23838
23913
  const outlineBounds = getBoundsFromPoints6(props.outline);
23839
23914
  if (outlineBounds) {
@@ -23877,8 +23952,8 @@ function packIntoGrid({
23877
23952
  }
23878
23953
  let cols;
23879
23954
  let rows;
23880
- const minCellWidth = cellWidth ? distance12.parse(cellWidth) : 0;
23881
- const minCellHeight = cellHeight ? distance12.parse(cellHeight) : 0;
23955
+ const minCellWidth = cellWidth ? distance13.parse(cellWidth) : 0;
23956
+ const minCellHeight = cellHeight ? distance13.parse(cellHeight) : 0;
23882
23957
  if (col !== void 0) {
23883
23958
  cols = col;
23884
23959
  rows = row ?? Math.ceil(itemsWithDims.length / cols);
@@ -23977,8 +24052,8 @@ function getItemDimensions(item, db) {
23977
24052
  const props = subpanel._parsedProps;
23978
24053
  if (props.width !== void 0 && props.height !== void 0) {
23979
24054
  return {
23980
- width: distance12.parse(props.width),
23981
- height: distance12.parse(props.height)
24055
+ width: distance13.parse(props.width),
24056
+ height: distance13.parse(props.height)
23982
24057
  };
23983
24058
  }
23984
24059
  const directBoards = subpanel._getDirectBoardChildren();
@@ -24005,7 +24080,7 @@ function getItemDimensions(item, db) {
24005
24080
  return getBoardDimensionsFromProps(directBoards[0]);
24006
24081
  }
24007
24082
  if (subpanel._cachedGridWidth > 0 && subpanel._cachedGridHeight > 0) {
24008
- const edgePadding = distance12.parse(props.edgePadding ?? 5);
24083
+ const edgePadding = distance13.parse(props.edgePadding ?? 5);
24009
24084
  return {
24010
24085
  width: subpanel._cachedGridWidth + edgePadding * 2,
24011
24086
  height: subpanel._cachedGridHeight + edgePadding * 2
@@ -24163,17 +24238,17 @@ var Subpanel = class _Subpanel extends Group5 {
24163
24238
  edgePaddingTop: edgePaddingTopProp,
24164
24239
  edgePaddingBottom: edgePaddingBottomProp
24165
24240
  } = this._parsedProps;
24166
- const edgePadding = distance13.parse(edgePaddingProp ?? 5);
24167
- const edgePaddingLeft = distance13.parse(edgePaddingLeftProp ?? edgePadding);
24168
- const edgePaddingRight = distance13.parse(
24241
+ const edgePadding = distance14.parse(edgePaddingProp ?? 5);
24242
+ const edgePaddingLeft = distance14.parse(edgePaddingLeftProp ?? edgePadding);
24243
+ const edgePaddingRight = distance14.parse(
24169
24244
  edgePaddingRightProp ?? edgePadding
24170
24245
  );
24171
- const edgePaddingTop = distance13.parse(edgePaddingTopProp ?? edgePadding);
24172
- const edgePaddingBottom = distance13.parse(
24246
+ const edgePaddingTop = distance14.parse(edgePaddingTopProp ?? edgePadding);
24247
+ const edgePaddingBottom = distance14.parse(
24173
24248
  edgePaddingBottomProp ?? edgePadding
24174
24249
  );
24175
- const panelWidth = distance13.parse(this._parsedProps.width);
24176
- const panelHeight = distance13.parse(this._parsedProps.height);
24250
+ const panelWidth = distance14.parse(this._parsedProps.width);
24251
+ const panelHeight = distance14.parse(this._parsedProps.height);
24177
24252
  availablePanelWidth = panelWidth - edgePaddingLeft - edgePaddingRight;
24178
24253
  availablePanelHeight = panelHeight - edgePaddingTop - edgePaddingBottom;
24179
24254
  }
@@ -24248,8 +24323,8 @@ var Subpanel = class _Subpanel extends Group5 {
24248
24323
  if (!this.pcb_group_id) return;
24249
24324
  if (hasExplicitWidth && hasExplicitHeight) {
24250
24325
  db.pcb_group.update(this.pcb_group_id, {
24251
- width: distance13.parse(this._parsedProps.width),
24252
- height: distance13.parse(this._parsedProps.height)
24326
+ width: distance14.parse(this._parsedProps.width),
24327
+ height: distance14.parse(this._parsedProps.height)
24253
24328
  });
24254
24329
  } else if (gridWidth > 0 || gridHeight > 0) {
24255
24330
  const {
@@ -24259,18 +24334,18 @@ var Subpanel = class _Subpanel extends Group5 {
24259
24334
  edgePaddingTop: edgePaddingTopProp,
24260
24335
  edgePaddingBottom: edgePaddingBottomProp
24261
24336
  } = this._parsedProps;
24262
- const edgePadding = distance13.parse(edgePaddingProp ?? 5);
24263
- const edgePaddingLeft = distance13.parse(edgePaddingLeftProp ?? edgePadding);
24264
- const edgePaddingRight = distance13.parse(
24337
+ const edgePadding = distance14.parse(edgePaddingProp ?? 5);
24338
+ const edgePaddingLeft = distance14.parse(edgePaddingLeftProp ?? edgePadding);
24339
+ const edgePaddingRight = distance14.parse(
24265
24340
  edgePaddingRightProp ?? edgePadding
24266
24341
  );
24267
- const edgePaddingTop = distance13.parse(edgePaddingTopProp ?? edgePadding);
24268
- const edgePaddingBottom = distance13.parse(
24342
+ const edgePaddingTop = distance14.parse(edgePaddingTopProp ?? edgePadding);
24343
+ const edgePaddingBottom = distance14.parse(
24269
24344
  edgePaddingBottomProp ?? edgePadding
24270
24345
  );
24271
24346
  db.pcb_group.update(this.pcb_group_id, {
24272
- width: hasExplicitWidth ? distance13.parse(this._parsedProps.width) : gridWidth + edgePaddingLeft + edgePaddingRight,
24273
- height: hasExplicitHeight ? distance13.parse(this._parsedProps.height) : gridHeight + edgePaddingTop + edgePaddingBottom
24347
+ width: hasExplicitWidth ? distance14.parse(this._parsedProps.width) : gridWidth + edgePaddingLeft + edgePaddingRight,
24348
+ height: hasExplicitHeight ? distance14.parse(this._parsedProps.height) : gridHeight + edgePaddingTop + edgePaddingBottom
24274
24349
  });
24275
24350
  }
24276
24351
  }
@@ -24344,8 +24419,8 @@ var Panel = class extends Subpanel {
24344
24419
  const { db } = this.root;
24345
24420
  const props = this._parsedProps;
24346
24421
  const inserted = db.pcb_panel.insert({
24347
- width: props.width !== void 0 ? distance14.parse(props.width) : 0,
24348
- height: props.height !== void 0 ? distance14.parse(props.height) : 0,
24422
+ width: props.width !== void 0 ? distance15.parse(props.width) : 0,
24423
+ height: props.height !== void 0 ? distance15.parse(props.height) : 0,
24349
24424
  thickness: 1.6,
24350
24425
  center: this._getGlobalPcbPositionBeforeLayout(),
24351
24426
  covered_with_solder_mask: !(props.noSolderMask ?? false)
@@ -24364,8 +24439,8 @@ var Panel = class extends Subpanel {
24364
24439
  if (!this.pcb_panel_id) return;
24365
24440
  if (hasExplicitWidth && hasExplicitHeight) {
24366
24441
  db.pcb_panel.update(this.pcb_panel_id, {
24367
- width: distance14.parse(this._parsedProps.width),
24368
- height: distance14.parse(this._parsedProps.height)
24442
+ width: distance15.parse(this._parsedProps.width),
24443
+ height: distance15.parse(this._parsedProps.height)
24369
24444
  });
24370
24445
  } else if (gridWidth > 0 || gridHeight > 0) {
24371
24446
  const {
@@ -24375,18 +24450,18 @@ var Panel = class extends Subpanel {
24375
24450
  edgePaddingTop: edgePaddingTopProp,
24376
24451
  edgePaddingBottom: edgePaddingBottomProp
24377
24452
  } = this._parsedProps;
24378
- const edgePadding = distance14.parse(edgePaddingProp ?? 5);
24379
- const edgePaddingLeft = distance14.parse(edgePaddingLeftProp ?? edgePadding);
24380
- const edgePaddingRight = distance14.parse(
24453
+ const edgePadding = distance15.parse(edgePaddingProp ?? 5);
24454
+ const edgePaddingLeft = distance15.parse(edgePaddingLeftProp ?? edgePadding);
24455
+ const edgePaddingRight = distance15.parse(
24381
24456
  edgePaddingRightProp ?? edgePadding
24382
24457
  );
24383
- const edgePaddingTop = distance14.parse(edgePaddingTopProp ?? edgePadding);
24384
- const edgePaddingBottom = distance14.parse(
24458
+ const edgePaddingTop = distance15.parse(edgePaddingTopProp ?? edgePadding);
24459
+ const edgePaddingBottom = distance15.parse(
24385
24460
  edgePaddingBottomProp ?? edgePadding
24386
24461
  );
24387
24462
  db.pcb_panel.update(this.pcb_panel_id, {
24388
- width: hasExplicitWidth ? distance14.parse(this._parsedProps.width) : gridWidth + edgePaddingLeft + edgePaddingRight,
24389
- height: hasExplicitHeight ? distance14.parse(this._parsedProps.height) : gridHeight + edgePaddingTop + edgePaddingBottom
24463
+ width: hasExplicitWidth ? distance15.parse(this._parsedProps.width) : gridWidth + edgePaddingLeft + edgePaddingRight,
24464
+ height: hasExplicitHeight ? distance15.parse(this._parsedProps.height) : gridHeight + edgePaddingTop + edgePaddingBottom
24390
24465
  });
24391
24466
  }
24392
24467
  }
@@ -24397,8 +24472,8 @@ var Panel = class extends Subpanel {
24397
24472
  const props = this._parsedProps;
24398
24473
  const currentPanel = db.pcb_panel.get(this.pcb_panel_id);
24399
24474
  db.pcb_panel.update(this.pcb_panel_id, {
24400
- width: props.width !== void 0 ? distance14.parse(props.width) : currentPanel?.width,
24401
- height: props.height !== void 0 ? distance14.parse(props.height) : currentPanel?.height,
24475
+ width: props.width !== void 0 ? distance15.parse(props.width) : currentPanel?.width,
24476
+ height: props.height !== void 0 ? distance15.parse(props.height) : currentPanel?.height,
24402
24477
  center: this._getGlobalPcbPositionBeforeLayout(),
24403
24478
  covered_with_solder_mask: !(props.noSolderMask ?? false)
24404
24479
  });
@@ -25491,7 +25566,7 @@ import { BaseSolver } from "@tscircuit/solver-utils";
25491
25566
 
25492
25567
  // node_modules/@tscircuit/breakout-point-solver/lib/boundary/get-breakout-boundary-intersection.ts
25493
25568
  import {
25494
- distance as distance15,
25569
+ distance as distance16,
25495
25570
  getSegmentIntersection
25496
25571
  } from "@tscircuit/math-utils";
25497
25572
  var getBreakoutBoundaryIntersection = ({
@@ -25519,12 +25594,12 @@ var getBreakoutBoundaryIntersection = ({
25519
25594
  ]
25520
25595
  ];
25521
25596
  const candidates = boundarySegments.map(([start, end]) => getSegmentIntersection(from, to, start, end)).filter((point6) => point6 !== null);
25522
- candidates.sort((a, b) => distance15(from, a) - distance15(from, b));
25597
+ candidates.sort((a, b) => distance16(from, a) - distance16(from, b));
25523
25598
  return candidates[0] ?? null;
25524
25599
  };
25525
25600
 
25526
25601
  // node_modules/@tscircuit/breakout-point-solver/lib/boundary/get-available-breakout-boundary-point.ts
25527
- import { distance as distance16 } from "@tscircuit/math-utils";
25602
+ import { distance as distance17 } from "@tscircuit/math-utils";
25528
25603
 
25529
25604
  // node_modules/@tscircuit/breakout-point-solver/lib/pad/breakout-pad-collisions.ts
25530
25605
  import {
@@ -25626,7 +25701,7 @@ var isInsideRequiredSpacing = ({
25626
25701
  candidate,
25627
25702
  usedPoint,
25628
25703
  boundaryPointSpacing
25629
- }) => distance16(usedPoint, candidate) < boundaryPointSpacing - BOUNDARY_POINT_DISTANCE_TOLERANCE;
25704
+ }) => distance17(usedPoint, candidate) < boundaryPointSpacing - BOUNDARY_POINT_DISTANCE_TOLERANCE;
25630
25705
  var getBoundsEdge = (point6, bounds) => {
25631
25706
  if (Math.abs(point6.x - bounds.minX) < BOUNDARY_POINT_DISTANCE_TOLERANCE)
25632
25707
  return "left";
@@ -25817,7 +25892,7 @@ var getAvailableBreakoutBoundaryPoint = ({
25817
25892
  step
25818
25893
  });
25819
25894
  edgeCandidates.sort(
25820
- (a, b) => distance16(a, idealPoint) - distance16(b, idealPoint)
25895
+ (a, b) => distance17(a, idealPoint) - distance17(b, idealPoint)
25821
25896
  );
25822
25897
  for (const candidate of edgeCandidates) {
25823
25898
  if (isCandidateAvailable({
@@ -25833,7 +25908,7 @@ var getAvailableBreakoutBoundaryPoint = ({
25833
25908
  }
25834
25909
  }
25835
25910
  const candidates = getAllBoundsCandidates({ bounds, step });
25836
- candidates.sort((a, b) => distance16(a, idealPoint) - distance16(b, idealPoint));
25911
+ candidates.sort((a, b) => distance17(a, idealPoint) - distance17(b, idealPoint));
25837
25912
  for (const candidate of candidates) {
25838
25913
  if (isCandidateAvailable({
25839
25914
  candidate,
@@ -25883,7 +25958,7 @@ var getAvailableBreakoutBoundaryPointForOutsidePorts = ({
25883
25958
  if (!edge) continue;
25884
25959
  const edgeCandidates = getBoundsEdgeCandidates({ edge, bounds, step });
25885
25960
  edgeCandidates.sort(
25886
- (a, b) => distance16(a, idealPoint) - distance16(b, idealPoint)
25961
+ (a, b) => distance17(a, idealPoint) - distance17(b, idealPoint)
25887
25962
  );
25888
25963
  for (const candidate of edgeCandidates) {
25889
25964
  if (isCandidateAvailableForOutsidePorts({
@@ -25903,7 +25978,7 @@ var getAvailableBreakoutBoundaryPointForOutsidePorts = ({
25903
25978
  }
25904
25979
  for (const idealPoint of idealPoints) {
25905
25980
  const candidates = getAllBoundsCandidates({ bounds, step });
25906
- candidates.sort((a, b) => distance16(a, idealPoint) - distance16(b, idealPoint));
25981
+ candidates.sort((a, b) => distance17(a, idealPoint) - distance17(b, idealPoint));
25907
25982
  for (const candidate of candidates) {
25908
25983
  if (isCandidateAvailableForOutsidePorts({
25909
25984
  candidate,
@@ -26423,6 +26498,11 @@ var createBreakoutPointSolverInput = (breakout) => {
26423
26498
  label: component.pcb_component_id
26424
26499
  }));
26425
26500
  const usedBoundaryPoints = db.pcb_breakout_point.list().filter((point6) => point6.pcb_group_id === breakout.pcb_group_id).map((point6) => ({ x: point6.x, y: point6.y }));
26501
+ const board = db.pcb_board.list()[0];
26502
+ const traceWidth = board?.min_trace_width ?? 0.15;
26503
+ const clearance = board?.min_trace_to_pad_edge_clearance ?? 0.2;
26504
+ const viaPadDiameter = board?.min_via_pad_diameter ?? 0.3;
26505
+ const boundaryPointSpacing = viaPadDiameter + 2 * (traceWidth + clearance);
26426
26506
  return {
26427
26507
  bounds: {
26428
26508
  minX: boundsMinX,
@@ -26430,7 +26510,7 @@ var createBreakoutPointSolverInput = (breakout) => {
26430
26510
  minY: boundsMinY,
26431
26511
  maxY: boundsMaxY
26432
26512
  },
26433
- boundaryPointSpacing: 0.5,
26513
+ boundaryPointSpacing,
26434
26514
  traces,
26435
26515
  pads,
26436
26516
  components,
@@ -26498,15 +26578,28 @@ var Breakout = class extends Group5 {
26498
26578
  const autoBreakoutPoints = this.children.filter(
26499
26579
  (c) => c instanceof AutoplacedBreakoutPoint
26500
26580
  );
26581
+ const BOUNDARY_INSET_MM = 1e-4;
26582
+ const { bounds } = solverInput;
26583
+ const insetWithinBounds = (x, y) => ({
26584
+ x: Math.max(
26585
+ bounds.minX + BOUNDARY_INSET_MM,
26586
+ Math.min(bounds.maxX - BOUNDARY_INSET_MM, x)
26587
+ ),
26588
+ y: Math.max(
26589
+ bounds.minY + BOUNDARY_INSET_MM,
26590
+ Math.min(bounds.maxY - BOUNDARY_INSET_MM, y)
26591
+ )
26592
+ });
26501
26593
  for (const solvedPoint of output.breakoutPoints) {
26502
26594
  const matchingBreakoutPoint = autoBreakoutPoints.find(
26503
26595
  (child) => child.matchedPort?.source_port_id === solvedPoint.sourcePortId
26504
26596
  );
26505
26597
  if (matchingBreakoutPoint) {
26506
26598
  matchingBreakoutPoint.matchedSourceTraceId = solvedPoint.sourceTraceId;
26599
+ const insetPoint = insetWithinBounds(solvedPoint.x, solvedPoint.y);
26507
26600
  matchingBreakoutPoint._setPositionFromLayout({
26508
- x: solvedPoint.x,
26509
- y: solvedPoint.y
26601
+ x: insetPoint.x,
26602
+ y: insetPoint.y
26510
26603
  });
26511
26604
  }
26512
26605
  }
@@ -26732,7 +26825,7 @@ var NetLabel = class extends PrimitiveComponent2 {
26732
26825
 
26733
26826
  // lib/components/primitive-components/Fiducial.ts
26734
26827
  import "zod";
26735
- import { distance as distance17 } from "circuit-json";
26828
+ import { distance as distance18 } from "circuit-json";
26736
26829
  import { fiducialProps } from "@tscircuit/props";
26737
26830
  var Fiducial = class extends PrimitiveComponent2 {
26738
26831
  pcb_smtpad_id = null;
@@ -26757,15 +26850,15 @@ var Fiducial = class extends PrimitiveComponent2 {
26757
26850
  shape: "circle",
26758
26851
  x: position.x,
26759
26852
  y: position.y,
26760
- radius: distance17.parse(props.padDiameter) / 2,
26761
- soldermask_margin: props.soldermaskPullback ? distance17.parse(props.soldermaskPullback) : distance17.parse(props.padDiameter) / 2,
26853
+ radius: distance18.parse(props.padDiameter) / 2,
26854
+ soldermask_margin: props.soldermaskPullback ? distance18.parse(props.soldermaskPullback) : distance18.parse(props.padDiameter) / 2,
26762
26855
  is_covered_with_solder_mask: true
26763
26856
  });
26764
26857
  this.pcb_smtpad_id = pcb_smtpad.pcb_smtpad_id;
26765
26858
  }
26766
26859
  getPcbSize() {
26767
26860
  const { _parsedProps: props } = this;
26768
- const d = distance17.parse(props.padDiameter);
26861
+ const d = distance18.parse(props.padDiameter);
26769
26862
  return { width: d, height: d };
26770
26863
  }
26771
26864
  _setPositionFromLayout(newCenter) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.1296",
4
+ "version": "0.0.1298",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",