@tscircuit/core 0.0.1428 → 0.0.1430

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 +124 -80
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -2546,51 +2546,29 @@ var isRouteOutsideBoard = ({
2546
2546
  );
2547
2547
  };
2548
2548
 
2549
- // lib/utils/obstacles/getObstaclesFromRoute.ts
2550
- var isCloseTo = (a, b) => Math.abs(a - b) < 1e-4;
2551
- var getObstaclesFromRoute = (route, source_trace_id, { viaDiameter = 0.5 } = {}) => {
2552
- const obstacles = [];
2553
- for (let i = 0; i < route.length - 1; i++) {
2554
- const [start, end] = [route[i], route[i + 1]];
2555
- const prev = i - 1 >= 0 ? route[i - 1] : null;
2556
- const isHorz = isCloseTo(start.y, end.y);
2557
- const isVert = isCloseTo(start.x, end.x);
2558
- if (!isHorz && !isVert) {
2559
- throw new Error(
2560
- `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})`
2561
- );
2562
- }
2563
- const obstacle = {
2564
- type: "rect",
2565
- layers: [start.layer],
2566
- center: {
2567
- x: (start.x + end.x) / 2,
2568
- y: (start.y + end.y) / 2
2569
- },
2570
- width: isHorz ? Math.abs(start.x - end.x) : 0.1,
2571
- // TODO use route width
2572
- height: isVert ? Math.abs(start.y - end.y) : 0.1,
2573
- // TODO use route width
2574
- connectedTo: [source_trace_id]
2575
- };
2576
- obstacles.push(obstacle);
2577
- if (prev && prev.layer === start.layer && start.layer !== end.layer) {
2578
- const via = {
2579
- type: "rect",
2580
- layers: [start.layer, end.layer],
2549
+ // lib/utils/obstacles/fillCircleWithRects.ts
2550
+ function fillCircleWithRects(circle, options = {}) {
2551
+ const { center, radius } = circle;
2552
+ const { rectHeight = 0.1 } = options;
2553
+ const rects = [];
2554
+ const numSlices = Math.ceil(radius * 2 / rectHeight);
2555
+ for (let i = 0; i < numSlices; i++) {
2556
+ const y = center.y - radius + (i + 0.5) * rectHeight;
2557
+ const dy = y - center.y;
2558
+ const halfWidth = Math.sqrt(radius * radius - dy * dy);
2559
+ if (halfWidth > 0) {
2560
+ rects.push({
2581
2561
  center: {
2582
- x: start.x,
2583
- y: start.y
2562
+ x: center.x,
2563
+ y
2584
2564
  },
2585
- connectedTo: [source_trace_id],
2586
- width: viaDiameter,
2587
- height: viaDiameter
2588
- };
2589
- obstacles.push(via);
2565
+ width: halfWidth * 2,
2566
+ height: rectHeight
2567
+ });
2590
2568
  }
2591
2569
  }
2592
- return obstacles;
2593
- };
2570
+ return rects;
2571
+ }
2594
2572
 
2595
2573
  // lib/utils/obstacles/fillPolygonWithRects.ts
2596
2574
  function fillPolygonWithRects(polygon, options = {}) {
@@ -2633,29 +2611,88 @@ function fillPolygonWithRects(polygon, options = {}) {
2633
2611
  return rects;
2634
2612
  }
2635
2613
 
2636
- // lib/utils/obstacles/fillCircleWithRects.ts
2637
- function fillCircleWithRects(circle, options = {}) {
2638
- const { center, radius } = circle;
2639
- const { rectHeight = 0.1 } = options;
2640
- const rects = [];
2641
- const numSlices = Math.ceil(radius * 2 / rectHeight);
2642
- for (let i = 0; i < numSlices; i++) {
2643
- const y = center.y - radius + (i + 0.5) * rectHeight;
2644
- const dy = y - center.y;
2645
- const halfWidth = Math.sqrt(radius * radius - dy * dy);
2646
- if (halfWidth > 0) {
2647
- rects.push({
2614
+ // lib/utils/obstacles/getAxisAlignedRectFromPolygon.ts
2615
+ var AXIS_ALIGNED_RECT_TOLERANCE_MM = 1e-3;
2616
+ var getAxisAlignedRectFromPolygon = (points) => {
2617
+ const isCloseTo2 = (a, b) => Math.abs(a - b) <= AXIS_ALIGNED_RECT_TOLERANCE_MM;
2618
+ const normalizedPoints = points.filter(
2619
+ (point6, index) => index === 0 || !isCloseTo2(point6.x, points[index - 1].x) || !isCloseTo2(point6.y, points[index - 1].y)
2620
+ );
2621
+ if (normalizedPoints.length > 1 && isCloseTo2(normalizedPoints[0].x, normalizedPoints.at(-1).x) && isCloseTo2(normalizedPoints[0].y, normalizedPoints.at(-1).y)) {
2622
+ normalizedPoints.pop();
2623
+ }
2624
+ if (normalizedPoints.length < 4) return null;
2625
+ const minX = Math.min(...normalizedPoints.map((point6) => point6.x));
2626
+ const maxX = Math.max(...normalizedPoints.map((point6) => point6.x));
2627
+ const minY = Math.min(...normalizedPoints.map((point6) => point6.y));
2628
+ const maxY = Math.max(...normalizedPoints.map((point6) => point6.y));
2629
+ const expectedCorners = [
2630
+ { x: minX, y: minY },
2631
+ { x: minX, y: maxY },
2632
+ { x: maxX, y: minY },
2633
+ { x: maxX, y: maxY }
2634
+ ];
2635
+ if (!normalizedPoints.every(
2636
+ (point6) => isCloseTo2(point6.x, minX) || isCloseTo2(point6.x, maxX) || isCloseTo2(point6.y, minY) || isCloseTo2(point6.y, maxY)
2637
+ ) || !expectedCorners.every(
2638
+ (corner) => normalizedPoints.some(
2639
+ (point6) => isCloseTo2(point6.x, corner.x) && isCloseTo2(point6.y, corner.y)
2640
+ )
2641
+ )) {
2642
+ return null;
2643
+ }
2644
+ return {
2645
+ center: { x: (minX + maxX) / 2, y: (minY + maxY) / 2 },
2646
+ width: maxX - minX,
2647
+ height: maxY - minY
2648
+ };
2649
+ };
2650
+
2651
+ // lib/utils/obstacles/getObstaclesFromRoute.ts
2652
+ var isCloseTo = (a, b) => Math.abs(a - b) < 1e-4;
2653
+ var getObstaclesFromRoute = (route, source_trace_id, { viaDiameter = 0.5 } = {}) => {
2654
+ const obstacles = [];
2655
+ for (let i = 0; i < route.length - 1; i++) {
2656
+ const [start, end] = [route[i], route[i + 1]];
2657
+ const prev = i - 1 >= 0 ? route[i - 1] : null;
2658
+ const isHorz = isCloseTo(start.y, end.y);
2659
+ const isVert = isCloseTo(start.x, end.x);
2660
+ if (!isHorz && !isVert) {
2661
+ throw new Error(
2662
+ `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})`
2663
+ );
2664
+ }
2665
+ const obstacle = {
2666
+ type: "rect",
2667
+ layers: [start.layer],
2668
+ center: {
2669
+ x: (start.x + end.x) / 2,
2670
+ y: (start.y + end.y) / 2
2671
+ },
2672
+ width: isHorz ? Math.abs(start.x - end.x) : 0.1,
2673
+ // TODO use route width
2674
+ height: isVert ? Math.abs(start.y - end.y) : 0.1,
2675
+ // TODO use route width
2676
+ connectedTo: [source_trace_id]
2677
+ };
2678
+ obstacles.push(obstacle);
2679
+ if (prev && prev.layer === start.layer && start.layer !== end.layer) {
2680
+ const via = {
2681
+ type: "rect",
2682
+ layers: [start.layer, end.layer],
2648
2683
  center: {
2649
- x: center.x,
2650
- y
2684
+ x: start.x,
2685
+ y: start.y
2651
2686
  },
2652
- width: halfWidth * 2,
2653
- height: rectHeight
2654
- });
2687
+ connectedTo: [source_trace_id],
2688
+ width: viaDiameter,
2689
+ height: viaDiameter
2690
+ };
2691
+ obstacles.push(via);
2655
2692
  }
2656
2693
  }
2657
- return rects;
2658
- }
2694
+ return obstacles;
2695
+ };
2659
2696
 
2660
2697
  // lib/utils/obstacles/getObstaclesFromCircuitJson.ts
2661
2698
  var EVERY_LAYER = ["top", "inner1", "inner2", "bottom"];
@@ -2729,7 +2766,7 @@ var getObstaclesFromCircuitJson = (circuitJson, connMap) => {
2729
2766
  center: rect.center,
2730
2767
  width: rect.width,
2731
2768
  height: rect.height,
2732
- ccwRotationDegrees: element.ccw_rotation,
2769
+ ccwRotationDegrees: axisAlignedRect ? void 0 : element.ccw_rotation,
2733
2770
  connectedTo: withNetId([element.pcb_smtpad_id])
2734
2771
  });
2735
2772
  } else if (element.shape === "pill" || element.shape === "rotated_pill") {
@@ -2747,24 +2784,31 @@ var getObstaclesFromCircuitJson = (circuitJson, connMap) => {
2747
2784
  connectedTo: withNetId([element.pcb_smtpad_id])
2748
2785
  });
2749
2786
  } else if (element.shape === "polygon") {
2750
- const xs = element.points.map((point6) => point6.x);
2751
- const ys = element.points.map((point6) => point6.y);
2752
- const minX = Math.min(...xs);
2753
- const maxX = Math.max(...xs);
2754
- const minY = Math.min(...ys);
2755
- const maxY = Math.max(...ys);
2756
- obstacles.push({
2757
- componentId: pcbComponentId,
2758
- type: "rect",
2759
- layers: [element.layer],
2760
- center: {
2761
- x: (minX + maxX) / 2,
2762
- y: (minY + maxY) / 2
2763
- },
2764
- width: maxX - minX,
2765
- height: maxY - minY,
2766
- connectedTo: withNetId([element.pcb_smtpad_id])
2787
+ const axisAlignedRect = getAxisAlignedRectFromPolygon(element.points);
2788
+ if (axisAlignedRect) {
2789
+ obstacles.push({
2790
+ componentId: pcbComponentId,
2791
+ type: "rect",
2792
+ layers: [element.layer],
2793
+ ...axisAlignedRect,
2794
+ connectedTo: withNetId([element.pcb_smtpad_id])
2795
+ });
2796
+ continue;
2797
+ }
2798
+ const approximatingRects = fillPolygonWithRects(element.points, {
2799
+ rectHeight: 0.1
2767
2800
  });
2801
+ for (const rect of approximatingRects) {
2802
+ obstacles.push({
2803
+ componentId: pcbComponentId,
2804
+ type: "rect",
2805
+ layers: [element.layer],
2806
+ center: rect.center,
2807
+ width: rect.width,
2808
+ height: rect.height,
2809
+ connectedTo: withNetId([element.pcb_smtpad_id])
2810
+ });
2811
+ }
2768
2812
  }
2769
2813
  } else if (element.type === "pcb_keepout") {
2770
2814
  if (element.shape === "circle") {
@@ -22352,7 +22396,7 @@ function Group_getRoutingPhasePlans(group) {
22352
22396
  var package_default = {
22353
22397
  name: "@tscircuit/core",
22354
22398
  type: "module",
22355
- version: "0.0.1427",
22399
+ version: "0.0.1429",
22356
22400
  types: "dist/index.d.ts",
22357
22401
  main: "dist/index.js",
22358
22402
  module: "dist/index.js",
@@ -22397,7 +22441,7 @@ var package_default = {
22397
22441
  "@tscircuit/jlcpcb-manufacturing-specs": "git+https://github.com/tscircuit/jlcpcb-manufacturing-specs#e08af159db01a37db007e33f0a7268d0e4a279a5",
22398
22442
  "@tscircuit/krt-wasm": "^0.1.1",
22399
22443
  "@tscircuit/log-soup": "^1.0.2",
22400
- "@tscircuit/matchpack": "^0.0.33",
22444
+ "@tscircuit/matchpack": "^0.0.34",
22401
22445
  "@tscircuit/math-utils": "^0.0.36",
22402
22446
  "@tscircuit/miniflex": "^0.0.4",
22403
22447
  "@tscircuit/ngspice-spice-engine": "^0.0.19",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.1428",
4
+ "version": "0.0.1430",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
@@ -46,7 +46,7 @@
46
46
  "@tscircuit/jlcpcb-manufacturing-specs": "git+https://github.com/tscircuit/jlcpcb-manufacturing-specs#e08af159db01a37db007e33f0a7268d0e4a279a5",
47
47
  "@tscircuit/krt-wasm": "^0.1.1",
48
48
  "@tscircuit/log-soup": "^1.0.2",
49
- "@tscircuit/matchpack": "^0.0.33",
49
+ "@tscircuit/matchpack": "^0.0.34",
50
50
  "@tscircuit/math-utils": "^0.0.36",
51
51
  "@tscircuit/miniflex": "^0.0.4",
52
52
  "@tscircuit/ngspice-spice-engine": "^0.0.19",