@tscircuit/core 0.0.841 → 0.0.842

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
@@ -24638,21 +24638,21 @@ declare class CopperPour extends PrimitiveComponent<typeof copperPourProps> {
24638
24638
  isPcbPrimitive: boolean;
24639
24639
  get config(): {
24640
24640
  componentName: string;
24641
- zodProps: z.ZodObject<{
24642
- name: z.ZodOptional<z.ZodString>;
24643
- layer: z.ZodEffects<z.ZodUnion<[z.ZodEnum<["top", "bottom", "inner1", "inner2", "inner3", "inner4", "inner5", "inner6"]>, z.ZodObject<{
24644
- name: z.ZodEnum<["top", "bottom", "inner1", "inner2", "inner3", "inner4", "inner5", "inner6"]>;
24645
- }, "strip", z.ZodTypeAny, {
24641
+ zodProps: zod.ZodObject<{
24642
+ name: zod.ZodOptional<zod.ZodString>;
24643
+ layer: zod.ZodEffects<zod.ZodUnion<[zod.ZodEnum<["top", "bottom", "inner1", "inner2", "inner3", "inner4", "inner5", "inner6"]>, zod.ZodObject<{
24644
+ name: zod.ZodEnum<["top", "bottom", "inner1", "inner2", "inner3", "inner4", "inner5", "inner6"]>;
24645
+ }, "strip", zod.ZodTypeAny, {
24646
24646
  name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6";
24647
24647
  }, {
24648
24648
  name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6";
24649
24649
  }>]>, "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6", "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | {
24650
24650
  name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6";
24651
24651
  }>;
24652
- connectsTo: z.ZodString;
24653
- padMargin: z.ZodOptional<z.ZodEffects<z.ZodUnion<[z.ZodString, z.ZodNumber]>, number, string | number>>;
24654
- traceMargin: z.ZodOptional<z.ZodEffects<z.ZodUnion<[z.ZodString, z.ZodNumber]>, number, string | number>>;
24655
- }, "strip", z.ZodTypeAny, {
24652
+ connectsTo: zod.ZodString;
24653
+ padMargin: zod.ZodOptional<zod.ZodEffects<zod.ZodUnion<[zod.ZodString, zod.ZodNumber]>, number, string | number>>;
24654
+ traceMargin: zod.ZodOptional<zod.ZodEffects<zod.ZodUnion<[zod.ZodString, zod.ZodNumber]>, number, string | number>>;
24655
+ }, "strip", zod.ZodTypeAny, {
24656
24656
  layer: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6";
24657
24657
  connectsTo: string;
24658
24658
  name?: string | undefined;
package/dist/index.js CHANGED
@@ -16302,11 +16302,218 @@ var Via = class extends PrimitiveComponent2 {
16302
16302
  }
16303
16303
  };
16304
16304
 
16305
- // lib/components/primitive-components/CopperPour.ts
16305
+ // lib/components/primitive-components/CopperPour/CopperPour.ts
16306
16306
  import { copperPourProps } from "@tscircuit/props";
16307
- import "zod";
16308
- import Flatten from "@flatten-js/core";
16309
16307
  import { getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson4 } from "circuit-json-to-connectivity-map";
16308
+ import Flatten4 from "@flatten-js/core";
16309
+
16310
+ // lib/components/primitive-components/CopperPour/utils/get-board-polygon.ts
16311
+ import Flatten from "@flatten-js/core";
16312
+ var getBoardPolygon = (board) => {
16313
+ if (board.outline && board.outline.length > 0) {
16314
+ return new Flatten.Polygon(
16315
+ board.outline.map((p) => Flatten.point(p.x, p.y))
16316
+ );
16317
+ }
16318
+ return new Flatten.Polygon(
16319
+ new Flatten.Box(
16320
+ board.center.x - board.width / 2,
16321
+ board.center.y - board.height / 2,
16322
+ board.center.x + board.width / 2,
16323
+ board.center.y + board.height / 2
16324
+ ).toPoints()
16325
+ );
16326
+ };
16327
+
16328
+ // lib/components/primitive-components/CopperPour/utils/get-trace-obstacles.ts
16329
+ var getTraceObstacles = (db, layer) => {
16330
+ const traceObstacles = [];
16331
+ for (const pcb_trace of db.pcb_trace.list()) {
16332
+ if (!pcb_trace.route) continue;
16333
+ const source_trace = pcb_trace.source_trace_id ? db.source_trace.get(pcb_trace.source_trace_id) : null;
16334
+ const connectedToIds = /* @__PURE__ */ new Set();
16335
+ if (pcb_trace.source_trace_id) {
16336
+ connectedToIds.add(pcb_trace.source_trace_id);
16337
+ }
16338
+ if (source_trace) {
16339
+ for (const id of source_trace.connected_source_net_ids)
16340
+ connectedToIds.add(id);
16341
+ for (const id of source_trace.connected_source_port_ids)
16342
+ connectedToIds.add(id);
16343
+ }
16344
+ for (const pt of pcb_trace.route) {
16345
+ if (pt.route_type === "wire") {
16346
+ if (pt.start_pcb_port_id) {
16347
+ const pcb_port = db.pcb_port.get(pt.start_pcb_port_id);
16348
+ if (pcb_port?.source_port_id)
16349
+ connectedToIds.add(pcb_port.source_port_id);
16350
+ }
16351
+ if (pt.end_pcb_port_id) {
16352
+ const pcb_port = db.pcb_port.get(pt.end_pcb_port_id);
16353
+ if (pcb_port?.source_port_id)
16354
+ connectedToIds.add(pcb_port.source_port_id);
16355
+ }
16356
+ }
16357
+ }
16358
+ const connectedTo = Array.from(connectedToIds);
16359
+ for (let i = 0; i < pcb_trace.route.length - 1; i++) {
16360
+ const p1 = pcb_trace.route[i];
16361
+ const p2 = pcb_trace.route[i + 1];
16362
+ if (p1.route_type !== "wire" || p2.route_type !== "wire") continue;
16363
+ if (p1.layer !== layer) continue;
16364
+ const segmentWidth = p1.width;
16365
+ if (segmentWidth === 0) continue;
16366
+ const segmentLength = Math.hypot(p1.x - p2.x, p1.y - p2.y);
16367
+ if (segmentLength === 0) continue;
16368
+ const centerX = (p1.x + p2.x) / 2;
16369
+ const centerY = (p1.y + p2.y) / 2;
16370
+ const rotationDeg = Math.atan2(p2.y - p1.y, p2.x - p1.x) * 180 / Math.PI;
16371
+ const rotatedRect = {
16372
+ center: { x: centerX, y: centerY },
16373
+ width: segmentLength,
16374
+ height: segmentWidth,
16375
+ rotation: rotationDeg
16376
+ };
16377
+ const approximatingRects = generateApproximatingRects(rotatedRect);
16378
+ for (const rect of approximatingRects) {
16379
+ traceObstacles.push({
16380
+ type: "rect",
16381
+ layers: [p1.layer],
16382
+ center: rect.center,
16383
+ width: rect.width,
16384
+ height: rect.height,
16385
+ connectedTo,
16386
+ obstacle_type: "trace"
16387
+ });
16388
+ }
16389
+ }
16390
+ }
16391
+ return traceObstacles;
16392
+ };
16393
+
16394
+ // lib/components/primitive-components/CopperPour/utils/process-obstacles.ts
16395
+ import Flatten2 from "@flatten-js/core";
16396
+ var processObstaclesForPour = (obstacles, connMap, net, margins) => {
16397
+ const rectObstaclesToSubtract = [];
16398
+ const circularObstacles = [];
16399
+ const { traceMargin, padMargin } = margins;
16400
+ for (const obs of obstacles) {
16401
+ const isOnNet = obs.connectedTo.some(
16402
+ (id) => connMap.areIdsConnected(id, net.source_net_id)
16403
+ );
16404
+ if (isOnNet) {
16405
+ continue;
16406
+ }
16407
+ if (obs.type === "oval" && obs.width === obs.height) {
16408
+ const radius = obs.width / 2 + padMargin;
16409
+ circularObstacles.push({
16410
+ center: obs.center,
16411
+ radius
16412
+ });
16413
+ continue;
16414
+ }
16415
+ if (obs.type === "rect" && obs.width === obs.height && obs.connectedTo.length === 0) {
16416
+ const radius = obs.width / 2;
16417
+ circularObstacles.push({
16418
+ center: obs.center,
16419
+ radius
16420
+ });
16421
+ continue;
16422
+ }
16423
+ const margin = traceMargin;
16424
+ const b = new Flatten2.Box(
16425
+ obs.center.x - obs.width / 2 - margin,
16426
+ obs.center.y - obs.height / 2 - margin,
16427
+ obs.center.x + obs.width / 2 + margin,
16428
+ obs.center.y + obs.height / 2 + margin
16429
+ );
16430
+ rectObstaclesToSubtract.push(new Flatten2.Polygon(b.toPoints()));
16431
+ }
16432
+ return { rectObstaclesToSubtract, circularObstacles };
16433
+ };
16434
+
16435
+ // lib/components/primitive-components/CopperPour/utils/generate-and-insert-brep.ts
16436
+ import Flatten3 from "@flatten-js/core";
16437
+ var faceToVertices = (face) => face.edges.map((e) => {
16438
+ const pt = {
16439
+ x: e.start.x,
16440
+ y: e.start.y
16441
+ };
16442
+ if (e.isArc) {
16443
+ const bulge = Math.tan(e.shape.sweep / 4);
16444
+ if (Math.abs(bulge) > 1e-9) {
16445
+ pt.bulge = bulge;
16446
+ }
16447
+ }
16448
+ return pt;
16449
+ });
16450
+ var generateAndInsertBRep = (pourPolygons, circularObstacles, {
16451
+ db,
16452
+ copperPour
16453
+ }) => {
16454
+ const props = copperPour._parsedProps;
16455
+ const net = copperPour.getSubcircuit().selectOne(props.connectsTo);
16456
+ const subcircuit = copperPour.getSubcircuit();
16457
+ const polygons = Array.isArray(pourPolygons) ? pourPolygons : [pourPolygons];
16458
+ for (const p of polygons) {
16459
+ const islands = p.splitToIslands();
16460
+ for (const island of islands) {
16461
+ if (island.isEmpty()) continue;
16462
+ const faces = [...island.faces];
16463
+ const outer_face_ccw = faces.find(
16464
+ (f) => f.orientation() === Flatten3.ORIENTATION.CCW
16465
+ );
16466
+ const inner_faces_cw = faces.filter(
16467
+ (f) => f.orientation() === Flatten3.ORIENTATION.CW
16468
+ );
16469
+ if (!outer_face_ccw) continue;
16470
+ if (!db.pcb_copper_pour) {
16471
+ copperPour.renderError(
16472
+ "db.pcb_copper_pour not found. The database schema may be outdated."
16473
+ );
16474
+ return;
16475
+ }
16476
+ outer_face_ccw.reverse();
16477
+ const outer_ring_vertices = faceToVertices(outer_face_ccw);
16478
+ const inner_rings = inner_faces_cw.map((f) => {
16479
+ f.reverse();
16480
+ return { vertices: faceToVertices(f) };
16481
+ });
16482
+ for (const circle of circularObstacles) {
16483
+ const centerPoint = Flatten3.point(circle.center.x, circle.center.y);
16484
+ const isContained = island.contains(centerPoint);
16485
+ if (isContained) {
16486
+ inner_rings.push({
16487
+ vertices: [
16488
+ {
16489
+ x: circle.center.x,
16490
+ y: circle.center.y - circle.radius,
16491
+ bulge: 1
16492
+ },
16493
+ {
16494
+ x: circle.center.x,
16495
+ y: circle.center.y + circle.radius,
16496
+ bulge: 1
16497
+ }
16498
+ ]
16499
+ });
16500
+ }
16501
+ }
16502
+ db.pcb_copper_pour.insert({
16503
+ shape: "brep",
16504
+ layer: props.layer,
16505
+ brep_shape: {
16506
+ outer_ring: { vertices: outer_ring_vertices },
16507
+ inner_rings
16508
+ },
16509
+ source_net_id: net.source_net_id,
16510
+ subcircuit_id: subcircuit?.subcircuit_id ?? void 0
16511
+ });
16512
+ }
16513
+ }
16514
+ };
16515
+
16516
+ // lib/components/primitive-components/CopperPour/CopperPour.ts
16310
16517
  var CopperPour = class extends PrimitiveComponent2 {
16311
16518
  isPcbPrimitive = true;
16312
16519
  get config() {
@@ -16333,180 +16540,33 @@ var CopperPour = class extends PrimitiveComponent2 {
16333
16540
  this.renderError("No board found for copper pour");
16334
16541
  return;
16335
16542
  }
16336
- let boardPolygon;
16337
- if (board.outline && board.outline.length > 0) {
16338
- boardPolygon = new Flatten.Polygon(
16339
- board.outline.map((p) => Flatten.point(p.x, p.y))
16340
- );
16341
- } else {
16342
- boardPolygon = new Flatten.Polygon(
16343
- new Flatten.Box(
16344
- board.center.x - board.width / 2,
16345
- board.center.y - board.height / 2,
16346
- board.center.x + board.width / 2,
16347
- board.center.y + board.height / 2
16348
- ).toPoints()
16349
- );
16350
- }
16543
+ const boardPolygon = getBoardPolygon(board);
16351
16544
  const connMap = getFullConnectivityMapFromCircuitJson4(db.toArray());
16352
16545
  const obstaclesRaw = getObstaclesFromCircuitJson(
16353
16546
  db.toArray(),
16354
16547
  connMap
16355
16548
  ).filter((o) => o.layers.includes(props.layer));
16356
- for (const pcb_trace of db.pcb_trace.list()) {
16357
- if (!pcb_trace.route) continue;
16358
- for (let i = 0; i < pcb_trace.route.length - 1; i++) {
16359
- const p1 = pcb_trace.route[i];
16360
- const p2 = pcb_trace.route[i + 1];
16361
- if (p1.route_type !== "wire" || p2.route_type !== "wire") continue;
16362
- if (p1.layer !== props.layer) continue;
16363
- const segmentWidth = p1.width;
16364
- if (segmentWidth === 0) continue;
16365
- const segmentLength = Math.hypot(p1.x - p2.x, p1.y - p2.y);
16366
- if (segmentLength === 0) continue;
16367
- const centerX = (p1.x + p2.x) / 2;
16368
- const centerY = (p1.y + p2.y) / 2;
16369
- const rotationDeg = Math.atan2(p2.y - p1.y, p2.x - p1.x) * 180 / Math.PI;
16370
- const rotatedRect = {
16371
- center: { x: centerX, y: centerY },
16372
- width: segmentLength,
16373
- height: segmentWidth,
16374
- rotation: rotationDeg
16375
- };
16376
- const approximatingRects = generateApproximatingRects(rotatedRect);
16377
- for (const rect of approximatingRects) {
16378
- obstaclesRaw.push({
16379
- type: "rect",
16380
- layers: [p1.layer],
16381
- center: rect.center,
16382
- width: rect.width,
16383
- height: rect.height,
16384
- connectedTo: pcb_trace.source_trace_id ? [pcb_trace.source_trace_id] : [],
16385
- obstacle_type: "trace"
16386
- });
16387
- }
16388
- }
16389
- }
16390
- const rectObstaclesToSubtract = [];
16391
- const circularObstacles = [];
16392
- const traceMargin = props.traceMargin ?? 0.2;
16393
- const padMargin = props.padMargin ?? 0.2;
16394
- for (const obs of obstaclesRaw) {
16395
- const isOnNet = obs.connectedTo.some(
16396
- (id) => connMap.areIdsConnected(id, net.source_net_id)
16397
- );
16398
- if (isOnNet) {
16399
- continue;
16400
- }
16401
- if (obs.type === "oval" && obs.width === obs.height) {
16402
- const radius = obs.width / 2 + padMargin;
16403
- circularObstacles.push({
16404
- center: obs.center,
16405
- radius
16406
- });
16407
- continue;
16408
- }
16409
- if (obs.type === "rect" && obs.width === obs.height && obs.connectedTo.length === 0) {
16410
- const radius = obs.width / 2;
16411
- circularObstacles.push({
16412
- center: obs.center,
16413
- radius
16414
- });
16415
- continue;
16416
- }
16417
- const margin = traceMargin;
16418
- const b = new Flatten.Box(
16419
- obs.center.x - obs.width / 2 - margin,
16420
- obs.center.y - obs.height / 2 - margin,
16421
- obs.center.x + obs.width / 2 + margin,
16422
- obs.center.y + obs.height / 2 + margin
16423
- );
16424
- rectObstaclesToSubtract.push(new Flatten.Polygon(b.toPoints()));
16425
- }
16549
+ obstaclesRaw.push(...getTraceObstacles(db, props.layer));
16550
+ const { rectObstaclesToSubtract, circularObstacles } = processObstaclesForPour(obstaclesRaw, connMap, net, {
16551
+ traceMargin: props.traceMargin ?? 0.2,
16552
+ padMargin: props.padMargin ?? 0.2
16553
+ });
16426
16554
  let pourPolygons = boardPolygon;
16427
16555
  if (rectObstaclesToSubtract.length > 0) {
16428
16556
  const obstacleUnion = rectObstaclesToSubtract.reduce(
16429
- (acc, p) => Flatten.BooleanOperations.unify(acc, p)
16557
+ (acc, p) => Flatten4.BooleanOperations.unify(acc, p)
16430
16558
  );
16431
16559
  if (obstacleUnion && !obstacleUnion.isEmpty()) {
16432
- pourPolygons = Flatten.BooleanOperations.subtract(
16560
+ pourPolygons = Flatten4.BooleanOperations.subtract(
16433
16561
  boardPolygon,
16434
16562
  obstacleUnion
16435
16563
  );
16436
16564
  }
16437
16565
  }
16438
- if (!Array.isArray(pourPolygons)) {
16439
- pourPolygons = [pourPolygons];
16440
- }
16441
- for (const p of pourPolygons) {
16442
- const islands = p.splitToIslands();
16443
- for (const island of islands) {
16444
- if (island.isEmpty()) continue;
16445
- const faces = [...island.faces];
16446
- const outer_face_ccw = faces.find(
16447
- (f) => f.orientation() === Flatten.ORIENTATION.CCW
16448
- );
16449
- const inner_faces_cw = faces.filter(
16450
- (f) => f.orientation() === Flatten.ORIENTATION.CW
16451
- );
16452
- if (!outer_face_ccw) continue;
16453
- if (!db.pcb_copper_pour) {
16454
- this.renderError(
16455
- "db.pcb_copper_pour not found. The database schema may be outdated."
16456
- );
16457
- return;
16458
- }
16459
- const faceToVertices = (face) => face.edges.map((e) => {
16460
- const pt = {
16461
- x: e.start.x,
16462
- y: e.start.y
16463
- };
16464
- if (e.isArc) {
16465
- const bulge = Math.tan(e.shape.sweep / 4);
16466
- if (Math.abs(bulge) > 1e-9) {
16467
- pt.bulge = bulge;
16468
- }
16469
- }
16470
- return pt;
16471
- });
16472
- outer_face_ccw.reverse();
16473
- const outer_ring_vertices = faceToVertices(outer_face_ccw);
16474
- const inner_rings = inner_faces_cw.map((f) => {
16475
- f.reverse();
16476
- return { vertices: faceToVertices(f) };
16477
- });
16478
- for (const circle of circularObstacles) {
16479
- const centerPoint = Flatten.point(circle.center.x, circle.center.y);
16480
- const isContained = island.contains(centerPoint);
16481
- if (isContained) {
16482
- inner_rings.push({
16483
- vertices: [
16484
- {
16485
- x: circle.center.x,
16486
- y: circle.center.y - circle.radius,
16487
- bulge: 1
16488
- },
16489
- {
16490
- x: circle.center.x,
16491
- y: circle.center.y + circle.radius,
16492
- bulge: 1
16493
- }
16494
- ]
16495
- });
16496
- }
16497
- }
16498
- db.pcb_copper_pour.insert({
16499
- shape: "brep",
16500
- layer: props.layer,
16501
- brep_shape: {
16502
- outer_ring: { vertices: outer_ring_vertices },
16503
- inner_rings
16504
- },
16505
- source_net_id: net.source_net_id,
16506
- subcircuit_id: this.getSubcircuit()?.subcircuit_id ?? void 0
16507
- });
16508
- }
16509
- }
16566
+ generateAndInsertBRep(pourPolygons, circularObstacles, {
16567
+ db,
16568
+ copperPour: this
16569
+ });
16510
16570
  });
16511
16571
  }
16512
16572
  };
@@ -17749,7 +17809,7 @@ import { identity as identity6 } from "transformation-matrix";
17749
17809
  var package_default = {
17750
17810
  name: "@tscircuit/core",
17751
17811
  type: "module",
17752
- version: "0.0.840",
17812
+ version: "0.0.841",
17753
17813
  types: "dist/index.d.ts",
17754
17814
  main: "dist/index.js",
17755
17815
  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.841",
4
+ "version": "0.0.842",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",