@tscircuit/core 0.0.480 → 0.0.482

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 +287 -8
  2. package/package.json +1 -1
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,289 @@ 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 === "circular_hole_with_rect_pad") {
4533
+ obstacles.push({
4534
+ // @ts-ignore
4535
+ type: "rect",
4536
+ layers: EVERY_LAYER,
4537
+ center: {
4538
+ x: element.x,
4539
+ y: element.y
4540
+ },
4541
+ width: element.rect_pad_width,
4542
+ height: element.rect_pad_height,
4543
+ connectedTo: withNetId([element.pcb_plated_hole_id])
4544
+ });
4545
+ } else if (element.shape === "oval" || element.shape === "pill") {
4546
+ obstacles.push({
4547
+ // @ts-ignore
4548
+ type: "oval",
4549
+ layers: EVERY_LAYER,
4550
+ center: {
4551
+ x: element.x,
4552
+ y: element.y
4553
+ },
4554
+ width: element.outer_width,
4555
+ height: element.outer_height,
4556
+ connectedTo: withNetId([element.pcb_plated_hole_id])
4557
+ });
4558
+ }
4559
+ } else if (element.type === "pcb_trace") {
4560
+ const traceObstacles = getObstaclesFromRoute(
4561
+ element.route.map((rp) => ({
4562
+ x: rp.x,
4563
+ y: rp.y,
4564
+ layer: "layer" in rp ? rp.layer : rp.from_layer
4565
+ })),
4566
+ element.source_trace_id
4567
+ );
4568
+ obstacles.push(...traceObstacles);
4569
+ } else if (element.type === "pcb_via") {
4570
+ obstacles.push({
4571
+ type: "rect",
4572
+ layers: element.layers,
4573
+ center: {
4574
+ x: element.x,
4575
+ y: element.y
4576
+ },
4577
+ connectedTo: [],
4578
+ // TODO we can associate source_ports with this via
4579
+ width: element.outer_diameter,
4580
+ height: element.outer_diameter
4581
+ });
4582
+ }
4583
+ }
4584
+ return obstacles;
4585
+ };
4586
+
4307
4587
  // lib/components/primitive-components/Trace/Trace.ts
4308
4588
  var portToObjective = (port) => {
4309
4589
  const portPosition = port._getGlobalPcbPositionAfterLayout();
@@ -4613,7 +4893,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
4613
4893
  this.root.db.toArray()
4614
4894
  );
4615
4895
  const [obstacles, errGettingObstacles] = tryNow(
4616
- () => getObstaclesFromSoup(this.root.db.toArray())
4896
+ () => getObstaclesFromCircuitJson(this.root.db.toArray())
4617
4897
  // Remove as any when autorouting-dataset gets updated
4618
4898
  );
4619
4899
  if (errGettingObstacles) {
@@ -6310,7 +6590,6 @@ var applyEditEvents = ({
6310
6590
  };
6311
6591
 
6312
6592
  // lib/utils/autorouting/getSimpleRouteJsonFromCircuitJson.ts
6313
- import { getObstaclesFromSoup as getObstaclesFromSoup2 } from "@tscircuit/infgrid-ijump-astar";
6314
6593
  import { su as su4 } from "@tscircuit/circuit-json-util";
6315
6594
  import {
6316
6595
  getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson2
@@ -6365,7 +6644,7 @@ var getSimpleRouteJsonFromCircuitJson = ({
6365
6644
  const board = db.pcb_board.list()[0];
6366
6645
  db = su4(subcircuitElements);
6367
6646
  const connMap = getFullConnectivityMapFromCircuitJson2(subcircuitElements);
6368
- const obstacles = getObstaclesFromSoup2(
6647
+ const obstacles = getObstaclesFromCircuitJson(
6369
6648
  [
6370
6649
  ...db.pcb_component.list(),
6371
6650
  ...db.pcb_smtpad.list(),
@@ -9898,7 +10177,7 @@ import { identity as identity4 } from "transformation-matrix";
9898
10177
  var package_default = {
9899
10178
  name: "@tscircuit/core",
9900
10179
  type: "module",
9901
- version: "0.0.479",
10180
+ version: "0.0.481",
9902
10181
  types: "dist/index.d.ts",
9903
10182
  main: "dist/index.js",
9904
10183
  module: "dist/index.js",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.480",
4
+ "version": "0.0.482",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",