@tscircuit/core 0.0.479 → 0.0.481

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 +281 -13
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -3565,10 +3565,7 @@ var getNumericSchPinStyle = (pinStyles, pinLabels) => {
3565
3565
  };
3566
3566
 
3567
3567
  // lib/components/primitive-components/Trace/Trace.ts
3568
- import {
3569
- MultilayerIjump,
3570
- getObstaclesFromSoup
3571
- } from "@tscircuit/infgrid-ijump-astar";
3568
+ import { MultilayerIjump } from "@tscircuit/infgrid-ijump-astar";
3572
3569
  import { traceProps } from "@tscircuit/props";
3573
3570
  import "circuit-json";
3574
3571
  import { getFullConnectivityMapFromCircuitJson } from "circuit-json-to-connectivity-map";
@@ -4304,6 +4301,276 @@ var isRouteOutsideBoard = (mergedRoute, { db }) => {
4304
4301
  return outsideBoard;
4305
4302
  };
4306
4303
 
4304
+ // lib/utils/obstacles/getObstaclesFromRoute.ts
4305
+ var isCloseTo = (a, b) => Math.abs(a - b) < 1e-4;
4306
+ var getObstaclesFromRoute = (route, source_trace_id, { viaDiameter = 0.5 } = {}) => {
4307
+ const obstacles = [];
4308
+ for (let i = 0; i < route.length - 1; i++) {
4309
+ const [start, end] = [route[i], route[i + 1]];
4310
+ const prev = i - 1 >= 0 ? route[i - 1] : null;
4311
+ const isHorz = isCloseTo(start.y, end.y);
4312
+ const isVert = isCloseTo(start.x, end.x);
4313
+ if (!isHorz && !isVert) {
4314
+ throw new Error(
4315
+ `getObstaclesFromTrace currently only supports horizontal and vertical traces (not diagonals) Conflicting trace: ${source_trace_id}, start: (${start.x}, ${start.y}), end: (${end.x}, ${end.y})`
4316
+ );
4317
+ }
4318
+ const obstacle = {
4319
+ type: "rect",
4320
+ layers: [start.layer],
4321
+ center: {
4322
+ x: (start.x + end.x) / 2,
4323
+ y: (start.y + end.y) / 2
4324
+ },
4325
+ width: isHorz ? Math.abs(start.x - end.x) : 0.1,
4326
+ // TODO use route width
4327
+ height: isVert ? Math.abs(start.y - end.y) : 0.1,
4328
+ // TODO use route width
4329
+ connectedTo: [source_trace_id]
4330
+ };
4331
+ obstacles.push(obstacle);
4332
+ if (prev && prev.layer === start.layer && start.layer !== end.layer) {
4333
+ const via = {
4334
+ type: "rect",
4335
+ layers: [start.layer, end.layer],
4336
+ center: {
4337
+ x: start.x,
4338
+ y: start.y
4339
+ },
4340
+ connectedTo: [source_trace_id],
4341
+ width: viaDiameter,
4342
+ height: viaDiameter
4343
+ };
4344
+ obstacles.push(via);
4345
+ }
4346
+ }
4347
+ return obstacles;
4348
+ };
4349
+
4350
+ // lib/utils/obstacles/generateApproximatingRects.ts
4351
+ function generateApproximatingRects(rotatedRect, numRects = 4) {
4352
+ const { center, width, height, rotation: rotation2 } = rotatedRect;
4353
+ const rects = [];
4354
+ const angleRad = rotation2 * Math.PI / 180;
4355
+ const cosAngle = Math.cos(angleRad);
4356
+ const sinAngle = Math.sin(angleRad);
4357
+ const normalizedRotation = (rotation2 % 360 + 360) % 360;
4358
+ const sliceAlongWidth = height <= width ? normalizedRotation >= 45 && normalizedRotation < 135 || normalizedRotation >= 225 && normalizedRotation < 315 : normalizedRotation >= 135 && normalizedRotation < 225 || normalizedRotation >= 315 || normalizedRotation < 45;
4359
+ if (sliceAlongWidth) {
4360
+ const sliceWidth = width / numRects;
4361
+ for (let i = 0; i < numRects; i++) {
4362
+ const x = (i - numRects / 2 + 0.5) * sliceWidth;
4363
+ const rotatedX = -x * cosAngle;
4364
+ const rotatedY = -x * sinAngle;
4365
+ const coverageWidth = sliceWidth * 1.1;
4366
+ const coverageHeight = Math.abs(height * cosAngle) + Math.abs(sliceWidth * sinAngle);
4367
+ rects.push({
4368
+ center: {
4369
+ x: center.x + rotatedX,
4370
+ y: center.y + rotatedY
4371
+ },
4372
+ width: coverageWidth,
4373
+ height: coverageHeight
4374
+ });
4375
+ }
4376
+ } else {
4377
+ const sliceHeight = height / numRects;
4378
+ for (let i = 0; i < numRects; i++) {
4379
+ const y = (i - numRects / 2 + 0.5) * sliceHeight;
4380
+ const rotatedX = -y * sinAngle;
4381
+ const rotatedY = y * cosAngle;
4382
+ const coverageWidth = Math.abs(width * cosAngle) + Math.abs(sliceHeight * sinAngle);
4383
+ const coverageHeight = sliceHeight * 1.1;
4384
+ rects.push({
4385
+ center: {
4386
+ x: center.x + rotatedX,
4387
+ y: center.y + rotatedY
4388
+ },
4389
+ width: coverageWidth,
4390
+ height: coverageHeight
4391
+ });
4392
+ }
4393
+ }
4394
+ return rects;
4395
+ }
4396
+
4397
+ // lib/utils/obstacles/getObstaclesFromCircuitJson.ts
4398
+ var EVERY_LAYER = ["top", "inner1", "inner2", "bottom"];
4399
+ var getObstaclesFromCircuitJson = (soup, connMap) => {
4400
+ const withNetId = (idList) => connMap ? idList.concat(
4401
+ idList.map((id) => connMap?.getNetConnectedToId(id)).filter(Boolean)
4402
+ ) : idList;
4403
+ const obstacles = [];
4404
+ for (const element of soup) {
4405
+ if (element.type === "pcb_smtpad") {
4406
+ if (element.shape === "circle") {
4407
+ obstacles.push({
4408
+ // @ts-ignore
4409
+ type: "oval",
4410
+ layers: [element.layer],
4411
+ center: {
4412
+ x: element.x,
4413
+ y: element.y
4414
+ },
4415
+ width: element.radius * 2,
4416
+ height: element.radius * 2,
4417
+ connectedTo: withNetId([element.pcb_smtpad_id])
4418
+ });
4419
+ } else if (element.shape === "rect") {
4420
+ obstacles.push({
4421
+ type: "rect",
4422
+ layers: [element.layer],
4423
+ center: {
4424
+ x: element.x,
4425
+ y: element.y
4426
+ },
4427
+ width: element.width,
4428
+ height: element.height,
4429
+ connectedTo: withNetId([element.pcb_smtpad_id])
4430
+ });
4431
+ } else if (element.shape === "rotated_rect") {
4432
+ const rotatedRect = {
4433
+ center: { x: element.x, y: element.y },
4434
+ width: element.width,
4435
+ height: element.height,
4436
+ rotation: element.ccw_rotation
4437
+ };
4438
+ const approximatingRects = generateApproximatingRects(rotatedRect);
4439
+ for (const rect of approximatingRects) {
4440
+ obstacles.push({
4441
+ type: "rect",
4442
+ layers: [element.layer],
4443
+ center: rect.center,
4444
+ width: rect.width,
4445
+ height: rect.height,
4446
+ connectedTo: withNetId([element.pcb_smtpad_id])
4447
+ });
4448
+ }
4449
+ }
4450
+ } else if (element.type === "pcb_keepout") {
4451
+ if (element.shape === "circle") {
4452
+ obstacles.push({
4453
+ // @ts-ignore
4454
+ type: "oval",
4455
+ layers: element.layers,
4456
+ center: {
4457
+ x: element.center.x,
4458
+ y: element.center.y
4459
+ },
4460
+ width: element.radius * 2,
4461
+ height: element.radius * 2,
4462
+ connectedTo: []
4463
+ });
4464
+ } else if (element.shape === "rect") {
4465
+ obstacles.push({
4466
+ type: "rect",
4467
+ layers: element.layers,
4468
+ center: {
4469
+ x: element.center.x,
4470
+ y: element.center.y
4471
+ },
4472
+ width: element.width,
4473
+ height: element.height,
4474
+ connectedTo: []
4475
+ });
4476
+ }
4477
+ } else if (element.type === "pcb_hole") {
4478
+ if (element.hole_shape === "oval") {
4479
+ obstacles.push({
4480
+ // @ts-ignore
4481
+ type: "oval",
4482
+ center: {
4483
+ x: element.x,
4484
+ y: element.y
4485
+ },
4486
+ width: element.hole_width,
4487
+ height: element.hole_height,
4488
+ connectedTo: []
4489
+ });
4490
+ } else if (element.hole_shape === "square") {
4491
+ obstacles.push({
4492
+ type: "rect",
4493
+ layers: EVERY_LAYER,
4494
+ center: {
4495
+ x: element.x,
4496
+ y: element.y
4497
+ },
4498
+ width: element.hole_diameter,
4499
+ height: element.hole_diameter,
4500
+ connectedTo: []
4501
+ });
4502
+ } else if (
4503
+ // @ts-ignore
4504
+ element.hole_shape === "round" || element.hole_shape === "circle"
4505
+ ) {
4506
+ obstacles.push({
4507
+ type: "rect",
4508
+ layers: EVERY_LAYER,
4509
+ center: {
4510
+ x: element.x,
4511
+ y: element.y
4512
+ },
4513
+ width: element.hole_diameter,
4514
+ height: element.hole_diameter,
4515
+ connectedTo: []
4516
+ });
4517
+ }
4518
+ } else if (element.type === "pcb_plated_hole") {
4519
+ if (element.shape === "circle") {
4520
+ obstacles.push({
4521
+ // @ts-ignore
4522
+ type: "oval",
4523
+ layers: EVERY_LAYER,
4524
+ center: {
4525
+ x: element.x,
4526
+ y: element.y
4527
+ },
4528
+ width: element.outer_diameter,
4529
+ height: element.outer_diameter,
4530
+ connectedTo: withNetId([element.pcb_plated_hole_id])
4531
+ });
4532
+ } else if (element.shape === "oval" || element.shape === "pill") {
4533
+ obstacles.push({
4534
+ // @ts-ignore
4535
+ type: "oval",
4536
+ layers: EVERY_LAYER,
4537
+ center: {
4538
+ x: element.x,
4539
+ y: element.y
4540
+ },
4541
+ width: element.outer_width,
4542
+ height: element.outer_height,
4543
+ connectedTo: withNetId([element.pcb_plated_hole_id])
4544
+ });
4545
+ }
4546
+ } else if (element.type === "pcb_trace") {
4547
+ const traceObstacles = getObstaclesFromRoute(
4548
+ element.route.map((rp) => ({
4549
+ x: rp.x,
4550
+ y: rp.y,
4551
+ layer: "layer" in rp ? rp.layer : rp.from_layer
4552
+ })),
4553
+ element.source_trace_id
4554
+ );
4555
+ obstacles.push(...traceObstacles);
4556
+ } else if (element.type === "pcb_via") {
4557
+ obstacles.push({
4558
+ type: "rect",
4559
+ layers: element.layers,
4560
+ center: {
4561
+ x: element.x,
4562
+ y: element.y
4563
+ },
4564
+ connectedTo: [],
4565
+ // TODO we can associate source_ports with this via
4566
+ width: element.outer_diameter,
4567
+ height: element.outer_diameter
4568
+ });
4569
+ }
4570
+ }
4571
+ return obstacles;
4572
+ };
4573
+
4307
4574
  // lib/components/primitive-components/Trace/Trace.ts
4308
4575
  var portToObjective = (port) => {
4309
4576
  const portPosition = port._getGlobalPcbPositionAfterLayout();
@@ -4613,7 +4880,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
4613
4880
  this.root.db.toArray()
4614
4881
  );
4615
4882
  const [obstacles, errGettingObstacles] = tryNow(
4616
- () => getObstaclesFromSoup(this.root.db.toArray())
4883
+ () => getObstaclesFromCircuitJson(this.root.db.toArray())
4617
4884
  // Remove as any when autorouting-dataset gets updated
4618
4885
  );
4619
4886
  if (errGettingObstacles) {
@@ -6310,7 +6577,6 @@ var applyEditEvents = ({
6310
6577
  };
6311
6578
 
6312
6579
  // lib/utils/autorouting/getSimpleRouteJsonFromCircuitJson.ts
6313
- import { getObstaclesFromSoup as getObstaclesFromSoup2 } from "@tscircuit/infgrid-ijump-astar";
6314
6580
  import { su as su4 } from "@tscircuit/circuit-json-util";
6315
6581
  import {
6316
6582
  getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson2
@@ -6365,7 +6631,7 @@ var getSimpleRouteJsonFromCircuitJson = ({
6365
6631
  const board = db.pcb_board.list()[0];
6366
6632
  db = su4(subcircuitElements);
6367
6633
  const connMap = getFullConnectivityMapFromCircuitJson2(subcircuitElements);
6368
- const obstacles = getObstaclesFromSoup2(
6634
+ const obstacles = getObstaclesFromCircuitJson(
6369
6635
  [
6370
6636
  ...db.pcb_component.list(),
6371
6637
  ...db.pcb_smtpad.list(),
@@ -7816,18 +8082,20 @@ var Group = class extends NormalComponent {
7816
8082
  }
7817
8083
  doInitialSchematicReplaceNetLabelsWithSymbols() {
7818
8084
  if (this.root?.schematicDisabled) return;
8085
+ if (!this.isSubcircuit) return;
7819
8086
  const { db } = this.root;
7820
- for (const nl of db.schematic_net_label.list()) {
7821
- const net = db.source_net.get(nl.source_net_id);
8087
+ const subtree = db;
8088
+ for (const nl of subtree.schematic_net_label.list()) {
8089
+ const net = subtree.source_net.get(nl.source_net_id);
7822
8090
  const text = nl.text || net?.name || "";
7823
8091
  if (nl.anchor_side === "top" && /^gnd/i.test(text)) {
7824
- db.schematic_net_label.update(nl.schematic_net_label_id, {
8092
+ subtree.schematic_net_label.update(nl.schematic_net_label_id, {
7825
8093
  symbol_name: "ground_down"
7826
8094
  });
7827
8095
  continue;
7828
8096
  }
7829
8097
  if (nl.anchor_side === "bottom" && /^v/i.test(text)) {
7830
- db.schematic_net_label.update(nl.schematic_net_label_id, {
8098
+ subtree.schematic_net_label.update(nl.schematic_net_label_id, {
7831
8099
  symbol_name: "vcc_up"
7832
8100
  });
7833
8101
  }
@@ -9896,7 +10164,7 @@ import { identity as identity4 } from "transformation-matrix";
9896
10164
  var package_default = {
9897
10165
  name: "@tscircuit/core",
9898
10166
  type: "module",
9899
- version: "0.0.478",
10167
+ version: "0.0.480",
9900
10168
  types: "dist/index.d.ts",
9901
10169
  main: "dist/index.js",
9902
10170
  module: "dist/index.js",
@@ -9921,7 +10189,7 @@ var package_default = {
9921
10189
  "@biomejs/biome": "^1.8.3",
9922
10190
  "@tscircuit/capacity-autorouter": "^0.0.75",
9923
10191
  "@tscircuit/checks": "^0.0.52",
9924
- "@tscircuit/circuit-json-util": "^0.0.47",
10192
+ "@tscircuit/circuit-json-util": "^0.0.49",
9925
10193
  "@tscircuit/footprinter": "^0.0.177",
9926
10194
  "@tscircuit/import-snippet": "^0.0.4",
9927
10195
  "@tscircuit/infgrid-ijump-astar": "^0.0.33",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.479",
4
+ "version": "0.0.481",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
@@ -26,7 +26,7 @@
26
26
  "@biomejs/biome": "^1.8.3",
27
27
  "@tscircuit/capacity-autorouter": "^0.0.75",
28
28
  "@tscircuit/checks": "^0.0.52",
29
- "@tscircuit/circuit-json-util": "^0.0.47",
29
+ "@tscircuit/circuit-json-util": "^0.0.49",
30
30
  "@tscircuit/footprinter": "^0.0.177",
31
31
  "@tscircuit/import-snippet": "^0.0.4",
32
32
  "@tscircuit/infgrid-ijump-astar": "^0.0.33",