@tscircuit/core 0.0.840 → 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 +14 -9
- package/dist/index.js +274 -171
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -139,6 +139,7 @@ type Obstacle = {
|
|
|
139
139
|
width: number;
|
|
140
140
|
height: number;
|
|
141
141
|
connectedTo: string[];
|
|
142
|
+
netIsAssignable?: boolean;
|
|
142
143
|
};
|
|
143
144
|
interface SimpleRouteConnection {
|
|
144
145
|
name: string;
|
|
@@ -1304,6 +1305,7 @@ declare class Group<Props extends z.ZodType<any, any, any> = typeof groupProps>
|
|
|
1304
1305
|
maxY: number;
|
|
1305
1306
|
};
|
|
1306
1307
|
_getAutorouterConfig(): AutorouterConfig;
|
|
1308
|
+
_isLaserPrefabAutorouter(autorouterConfig?: AutorouterConfig): boolean;
|
|
1307
1309
|
_getSubcircuitLayerCount(): number;
|
|
1308
1310
|
/**
|
|
1309
1311
|
* Trace-by-trace autorouting is where each trace routes itself in a well-known
|
|
@@ -24505,6 +24507,7 @@ declare class Via extends PrimitiveComponent<typeof viaProps> {
|
|
|
24505
24507
|
holeDiameter: z.ZodEffects<z.ZodUnion<[z.ZodString, z.ZodNumber]>, number, string | number>;
|
|
24506
24508
|
outerDiameter: z.ZodEffects<z.ZodUnion<[z.ZodString, z.ZodNumber]>, number, string | number>;
|
|
24507
24509
|
connectsTo: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
|
|
24510
|
+
netIsAssignable: z.ZodOptional<z.ZodBoolean>;
|
|
24508
24511
|
}, "strip", z.ZodTypeAny, {
|
|
24509
24512
|
holeDiameter: number;
|
|
24510
24513
|
outerDiameter: number;
|
|
@@ -24548,6 +24551,7 @@ declare class Via extends PrimitiveComponent<typeof viaProps> {
|
|
|
24548
24551
|
schRelative?: boolean | undefined;
|
|
24549
24552
|
name?: string | undefined;
|
|
24550
24553
|
connectsTo?: string | string[] | undefined;
|
|
24554
|
+
netIsAssignable?: boolean | undefined;
|
|
24551
24555
|
}, {
|
|
24552
24556
|
holeDiameter: string | number;
|
|
24553
24557
|
outerDiameter: string | number;
|
|
@@ -24597,6 +24601,7 @@ declare class Via extends PrimitiveComponent<typeof viaProps> {
|
|
|
24597
24601
|
schRelative?: boolean | undefined;
|
|
24598
24602
|
name?: string | undefined;
|
|
24599
24603
|
connectsTo?: string | string[] | undefined;
|
|
24604
|
+
netIsAssignable?: boolean | undefined;
|
|
24600
24605
|
}>;
|
|
24601
24606
|
};
|
|
24602
24607
|
getAvailablePcbLayers(): string[];
|
|
@@ -24633,21 +24638,21 @@ declare class CopperPour extends PrimitiveComponent<typeof copperPourProps> {
|
|
|
24633
24638
|
isPcbPrimitive: boolean;
|
|
24634
24639
|
get config(): {
|
|
24635
24640
|
componentName: string;
|
|
24636
|
-
zodProps:
|
|
24637
|
-
name:
|
|
24638
|
-
layer:
|
|
24639
|
-
name:
|
|
24640
|
-
}, "strip",
|
|
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, {
|
|
24641
24646
|
name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6";
|
|
24642
24647
|
}, {
|
|
24643
24648
|
name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6";
|
|
24644
24649
|
}>]>, "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6", "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | {
|
|
24645
24650
|
name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6";
|
|
24646
24651
|
}>;
|
|
24647
|
-
connectsTo:
|
|
24648
|
-
padMargin:
|
|
24649
|
-
traceMargin:
|
|
24650
|
-
}, "strip",
|
|
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, {
|
|
24651
24656
|
layer: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6";
|
|
24652
24657
|
connectsTo: string;
|
|
24653
24658
|
name?: string | undefined;
|
package/dist/index.js
CHANGED
|
@@ -5447,6 +5447,9 @@ var getObstaclesFromCircuitJson = (soup, connMap) => {
|
|
|
5447
5447
|
);
|
|
5448
5448
|
obstacles.push(...traceObstacles);
|
|
5449
5449
|
} else if (element.type === "pcb_via") {
|
|
5450
|
+
const netIsAssignable = Boolean(
|
|
5451
|
+
element.net_is_assignable ?? element.netIsAssignable
|
|
5452
|
+
);
|
|
5450
5453
|
obstacles.push({
|
|
5451
5454
|
type: "rect",
|
|
5452
5455
|
layers: element.layers,
|
|
@@ -5457,7 +5460,8 @@ var getObstaclesFromCircuitJson = (soup, connMap) => {
|
|
|
5457
5460
|
connectedTo: [],
|
|
5458
5461
|
// TODO we can associate source_ports with this via
|
|
5459
5462
|
width: element.outer_diameter,
|
|
5460
|
-
height: element.outer_diameter
|
|
5463
|
+
height: element.outer_diameter,
|
|
5464
|
+
netIsAssignable: netIsAssignable || void 0
|
|
5461
5465
|
});
|
|
5462
5466
|
}
|
|
5463
5467
|
}
|
|
@@ -8843,7 +8847,7 @@ import {
|
|
|
8843
8847
|
} from "@tscircuit/props";
|
|
8844
8848
|
|
|
8845
8849
|
// lib/utils/autorouting/CapacityMeshAutorouter.ts
|
|
8846
|
-
import
|
|
8850
|
+
import * as CapacityAutorouter from "@tscircuit/capacity-autorouter";
|
|
8847
8851
|
var CapacityMeshAutorouter = class {
|
|
8848
8852
|
input;
|
|
8849
8853
|
isRouting = false;
|
|
@@ -8858,8 +8862,18 @@ var CapacityMeshAutorouter = class {
|
|
|
8858
8862
|
timeoutId;
|
|
8859
8863
|
constructor(input, options = {}) {
|
|
8860
8864
|
this.input = input;
|
|
8861
|
-
const {
|
|
8862
|
-
|
|
8865
|
+
const {
|
|
8866
|
+
capacityDepth,
|
|
8867
|
+
targetMinCapacity,
|
|
8868
|
+
stepDelay = 0,
|
|
8869
|
+
useAssignableViaSolver = false
|
|
8870
|
+
} = options;
|
|
8871
|
+
const {
|
|
8872
|
+
AutoroutingPipelineSolver,
|
|
8873
|
+
AssignableViaAutoroutingPipelineSolver
|
|
8874
|
+
} = CapacityAutorouter;
|
|
8875
|
+
const SolverClass = useAssignableViaSolver ? AssignableViaAutoroutingPipelineSolver : AutoroutingPipelineSolver;
|
|
8876
|
+
this.solver = new SolverClass(input, {
|
|
8863
8877
|
capacityDepth,
|
|
8864
8878
|
targetMinCapacity,
|
|
8865
8879
|
cacheProvider: null
|
|
@@ -11072,6 +11086,20 @@ function getPresetAutoroutingConfig(autorouterConfig) {
|
|
|
11072
11086
|
...rest
|
|
11073
11087
|
};
|
|
11074
11088
|
}
|
|
11089
|
+
case "laser-prefab": {
|
|
11090
|
+
const {
|
|
11091
|
+
preset: _preset,
|
|
11092
|
+
local: _local,
|
|
11093
|
+
groupMode: _groupMode,
|
|
11094
|
+
...rest
|
|
11095
|
+
} = providedConfig;
|
|
11096
|
+
return {
|
|
11097
|
+
local: true,
|
|
11098
|
+
groupMode: "subcircuit",
|
|
11099
|
+
preset: "laser_prefab",
|
|
11100
|
+
...rest
|
|
11101
|
+
};
|
|
11102
|
+
}
|
|
11075
11103
|
default:
|
|
11076
11104
|
return {
|
|
11077
11105
|
local: true,
|
|
@@ -13188,6 +13216,7 @@ var Group6 = class extends NormalComponent3 {
|
|
|
13188
13216
|
const debug11 = Debug13("tscircuit:core:_runLocalAutorouting");
|
|
13189
13217
|
debug11(`[${this.getString()}] starting local autorouting`);
|
|
13190
13218
|
const autorouterConfig = this._getAutorouterConfig();
|
|
13219
|
+
const isLaserPrefabPreset = this._isLaserPrefabAutorouter(autorouterConfig);
|
|
13191
13220
|
const { simpleRouteJson } = getSimpleRouteJsonFromCircuitJson({
|
|
13192
13221
|
db,
|
|
13193
13222
|
minTraceWidth: this.props.autorouter?.minTraceWidth ?? 0.15,
|
|
@@ -13219,7 +13248,8 @@ var Group6 = class extends NormalComponent3 {
|
|
|
13219
13248
|
autorouter = new CapacityMeshAutorouter(simpleRouteJson, {
|
|
13220
13249
|
// Optional configuration parameters
|
|
13221
13250
|
capacityDepth: this.props.autorouter?.capacityDepth,
|
|
13222
|
-
targetMinCapacity: this.props.autorouter?.targetMinCapacity
|
|
13251
|
+
targetMinCapacity: this.props.autorouter?.targetMinCapacity,
|
|
13252
|
+
useAssignableViaSolver: isLaserPrefabPreset
|
|
13223
13253
|
});
|
|
13224
13254
|
}
|
|
13225
13255
|
const routingPromise = new Promise(
|
|
@@ -13578,6 +13608,18 @@ var Group6 = class extends NormalComponent3 {
|
|
|
13578
13608
|
const autorouter = this._parsedProps.autorouter || this.getInheritedProperty("autorouter");
|
|
13579
13609
|
return getPresetAutoroutingConfig(autorouter);
|
|
13580
13610
|
}
|
|
13611
|
+
_isLaserPrefabAutorouter(autorouterConfig = this._getAutorouterConfig()) {
|
|
13612
|
+
const autorouterProp = this.props.autorouter;
|
|
13613
|
+
const normalize = (value) => value?.replace(/-/g, "_") ?? value;
|
|
13614
|
+
if (autorouterConfig.preset === "laser_prefab") return true;
|
|
13615
|
+
if (typeof autorouterProp === "string") {
|
|
13616
|
+
return normalize(autorouterProp) === "laser_prefab";
|
|
13617
|
+
}
|
|
13618
|
+
if (typeof autorouterProp === "object" && autorouterProp) {
|
|
13619
|
+
return normalize(autorouterProp.preset) === "laser_prefab";
|
|
13620
|
+
}
|
|
13621
|
+
return false;
|
|
13622
|
+
}
|
|
13581
13623
|
_getSubcircuitLayerCount() {
|
|
13582
13624
|
const layers = this.getInheritedProperty("layers");
|
|
13583
13625
|
return typeof layers === "number" ? layers : 2;
|
|
@@ -16253,17 +16295,225 @@ var Via = class extends PrimitiveComponent2 {
|
|
|
16253
16295
|
from_layer: props.fromLayer || "bottom",
|
|
16254
16296
|
to_layer: props.toLayer || "top",
|
|
16255
16297
|
subcircuit_id: subcircuit?.subcircuit_id ?? void 0,
|
|
16256
|
-
pcb_group_id: this.getGroup()?.pcb_group_id ?? void 0
|
|
16298
|
+
pcb_group_id: this.getGroup()?.pcb_group_id ?? void 0,
|
|
16299
|
+
net_is_assignable: props.netIsAssignable ?? void 0
|
|
16257
16300
|
});
|
|
16258
16301
|
this.pcb_via_id = pcb_via.pcb_via_id;
|
|
16259
16302
|
}
|
|
16260
16303
|
};
|
|
16261
16304
|
|
|
16262
|
-
// lib/components/primitive-components/CopperPour.ts
|
|
16305
|
+
// lib/components/primitive-components/CopperPour/CopperPour.ts
|
|
16263
16306
|
import { copperPourProps } from "@tscircuit/props";
|
|
16264
|
-
import "zod";
|
|
16265
|
-
import Flatten from "@flatten-js/core";
|
|
16266
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
|
|
16267
16517
|
var CopperPour = class extends PrimitiveComponent2 {
|
|
16268
16518
|
isPcbPrimitive = true;
|
|
16269
16519
|
get config() {
|
|
@@ -16290,180 +16540,33 @@ var CopperPour = class extends PrimitiveComponent2 {
|
|
|
16290
16540
|
this.renderError("No board found for copper pour");
|
|
16291
16541
|
return;
|
|
16292
16542
|
}
|
|
16293
|
-
|
|
16294
|
-
if (board.outline && board.outline.length > 0) {
|
|
16295
|
-
boardPolygon = new Flatten.Polygon(
|
|
16296
|
-
board.outline.map((p) => Flatten.point(p.x, p.y))
|
|
16297
|
-
);
|
|
16298
|
-
} else {
|
|
16299
|
-
boardPolygon = new Flatten.Polygon(
|
|
16300
|
-
new Flatten.Box(
|
|
16301
|
-
board.center.x - board.width / 2,
|
|
16302
|
-
board.center.y - board.height / 2,
|
|
16303
|
-
board.center.x + board.width / 2,
|
|
16304
|
-
board.center.y + board.height / 2
|
|
16305
|
-
).toPoints()
|
|
16306
|
-
);
|
|
16307
|
-
}
|
|
16543
|
+
const boardPolygon = getBoardPolygon(board);
|
|
16308
16544
|
const connMap = getFullConnectivityMapFromCircuitJson4(db.toArray());
|
|
16309
16545
|
const obstaclesRaw = getObstaclesFromCircuitJson(
|
|
16310
16546
|
db.toArray(),
|
|
16311
16547
|
connMap
|
|
16312
16548
|
).filter((o) => o.layers.includes(props.layer));
|
|
16313
|
-
|
|
16314
|
-
|
|
16315
|
-
|
|
16316
|
-
|
|
16317
|
-
|
|
16318
|
-
if (p1.route_type !== "wire" || p2.route_type !== "wire") continue;
|
|
16319
|
-
if (p1.layer !== props.layer) continue;
|
|
16320
|
-
const segmentWidth = p1.width;
|
|
16321
|
-
if (segmentWidth === 0) continue;
|
|
16322
|
-
const segmentLength = Math.hypot(p1.x - p2.x, p1.y - p2.y);
|
|
16323
|
-
if (segmentLength === 0) continue;
|
|
16324
|
-
const centerX = (p1.x + p2.x) / 2;
|
|
16325
|
-
const centerY = (p1.y + p2.y) / 2;
|
|
16326
|
-
const rotationDeg = Math.atan2(p2.y - p1.y, p2.x - p1.x) * 180 / Math.PI;
|
|
16327
|
-
const rotatedRect = {
|
|
16328
|
-
center: { x: centerX, y: centerY },
|
|
16329
|
-
width: segmentLength,
|
|
16330
|
-
height: segmentWidth,
|
|
16331
|
-
rotation: rotationDeg
|
|
16332
|
-
};
|
|
16333
|
-
const approximatingRects = generateApproximatingRects(rotatedRect);
|
|
16334
|
-
for (const rect of approximatingRects) {
|
|
16335
|
-
obstaclesRaw.push({
|
|
16336
|
-
type: "rect",
|
|
16337
|
-
layers: [p1.layer],
|
|
16338
|
-
center: rect.center,
|
|
16339
|
-
width: rect.width,
|
|
16340
|
-
height: rect.height,
|
|
16341
|
-
connectedTo: pcb_trace.source_trace_id ? [pcb_trace.source_trace_id] : [],
|
|
16342
|
-
obstacle_type: "trace"
|
|
16343
|
-
});
|
|
16344
|
-
}
|
|
16345
|
-
}
|
|
16346
|
-
}
|
|
16347
|
-
const rectObstaclesToSubtract = [];
|
|
16348
|
-
const circularObstacles = [];
|
|
16349
|
-
const traceMargin = props.traceMargin ?? 0.2;
|
|
16350
|
-
const padMargin = props.padMargin ?? 0.2;
|
|
16351
|
-
for (const obs of obstaclesRaw) {
|
|
16352
|
-
const isOnNet = obs.connectedTo.some(
|
|
16353
|
-
(id) => connMap.areIdsConnected(id, net.source_net_id)
|
|
16354
|
-
);
|
|
16355
|
-
if (isOnNet) {
|
|
16356
|
-
continue;
|
|
16357
|
-
}
|
|
16358
|
-
if (obs.type === "oval" && obs.width === obs.height) {
|
|
16359
|
-
const radius = obs.width / 2 + padMargin;
|
|
16360
|
-
circularObstacles.push({
|
|
16361
|
-
center: obs.center,
|
|
16362
|
-
radius
|
|
16363
|
-
});
|
|
16364
|
-
continue;
|
|
16365
|
-
}
|
|
16366
|
-
if (obs.type === "rect" && obs.width === obs.height && obs.connectedTo.length === 0) {
|
|
16367
|
-
const radius = obs.width / 2;
|
|
16368
|
-
circularObstacles.push({
|
|
16369
|
-
center: obs.center,
|
|
16370
|
-
radius
|
|
16371
|
-
});
|
|
16372
|
-
continue;
|
|
16373
|
-
}
|
|
16374
|
-
const margin = traceMargin;
|
|
16375
|
-
const b = new Flatten.Box(
|
|
16376
|
-
obs.center.x - obs.width / 2 - margin,
|
|
16377
|
-
obs.center.y - obs.height / 2 - margin,
|
|
16378
|
-
obs.center.x + obs.width / 2 + margin,
|
|
16379
|
-
obs.center.y + obs.height / 2 + margin
|
|
16380
|
-
);
|
|
16381
|
-
rectObstaclesToSubtract.push(new Flatten.Polygon(b.toPoints()));
|
|
16382
|
-
}
|
|
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
|
+
});
|
|
16383
16554
|
let pourPolygons = boardPolygon;
|
|
16384
16555
|
if (rectObstaclesToSubtract.length > 0) {
|
|
16385
16556
|
const obstacleUnion = rectObstaclesToSubtract.reduce(
|
|
16386
|
-
(acc, p) =>
|
|
16557
|
+
(acc, p) => Flatten4.BooleanOperations.unify(acc, p)
|
|
16387
16558
|
);
|
|
16388
16559
|
if (obstacleUnion && !obstacleUnion.isEmpty()) {
|
|
16389
|
-
pourPolygons =
|
|
16560
|
+
pourPolygons = Flatten4.BooleanOperations.subtract(
|
|
16390
16561
|
boardPolygon,
|
|
16391
16562
|
obstacleUnion
|
|
16392
16563
|
);
|
|
16393
16564
|
}
|
|
16394
16565
|
}
|
|
16395
|
-
|
|
16396
|
-
|
|
16397
|
-
|
|
16398
|
-
|
|
16399
|
-
const islands = p.splitToIslands();
|
|
16400
|
-
for (const island of islands) {
|
|
16401
|
-
if (island.isEmpty()) continue;
|
|
16402
|
-
const faces = [...island.faces];
|
|
16403
|
-
const outer_face_ccw = faces.find(
|
|
16404
|
-
(f) => f.orientation() === Flatten.ORIENTATION.CCW
|
|
16405
|
-
);
|
|
16406
|
-
const inner_faces_cw = faces.filter(
|
|
16407
|
-
(f) => f.orientation() === Flatten.ORIENTATION.CW
|
|
16408
|
-
);
|
|
16409
|
-
if (!outer_face_ccw) continue;
|
|
16410
|
-
if (!db.pcb_copper_pour) {
|
|
16411
|
-
this.renderError(
|
|
16412
|
-
"db.pcb_copper_pour not found. The database schema may be outdated."
|
|
16413
|
-
);
|
|
16414
|
-
return;
|
|
16415
|
-
}
|
|
16416
|
-
const faceToVertices = (face) => face.edges.map((e) => {
|
|
16417
|
-
const pt = {
|
|
16418
|
-
x: e.start.x,
|
|
16419
|
-
y: e.start.y
|
|
16420
|
-
};
|
|
16421
|
-
if (e.isArc) {
|
|
16422
|
-
const bulge = Math.tan(e.shape.sweep / 4);
|
|
16423
|
-
if (Math.abs(bulge) > 1e-9) {
|
|
16424
|
-
pt.bulge = bulge;
|
|
16425
|
-
}
|
|
16426
|
-
}
|
|
16427
|
-
return pt;
|
|
16428
|
-
});
|
|
16429
|
-
outer_face_ccw.reverse();
|
|
16430
|
-
const outer_ring_vertices = faceToVertices(outer_face_ccw);
|
|
16431
|
-
const inner_rings = inner_faces_cw.map((f) => {
|
|
16432
|
-
f.reverse();
|
|
16433
|
-
return { vertices: faceToVertices(f) };
|
|
16434
|
-
});
|
|
16435
|
-
for (const circle of circularObstacles) {
|
|
16436
|
-
const centerPoint = Flatten.point(circle.center.x, circle.center.y);
|
|
16437
|
-
const isContained = island.contains(centerPoint);
|
|
16438
|
-
if (isContained) {
|
|
16439
|
-
inner_rings.push({
|
|
16440
|
-
vertices: [
|
|
16441
|
-
{
|
|
16442
|
-
x: circle.center.x,
|
|
16443
|
-
y: circle.center.y - circle.radius,
|
|
16444
|
-
bulge: 1
|
|
16445
|
-
},
|
|
16446
|
-
{
|
|
16447
|
-
x: circle.center.x,
|
|
16448
|
-
y: circle.center.y + circle.radius,
|
|
16449
|
-
bulge: 1
|
|
16450
|
-
}
|
|
16451
|
-
]
|
|
16452
|
-
});
|
|
16453
|
-
}
|
|
16454
|
-
}
|
|
16455
|
-
db.pcb_copper_pour.insert({
|
|
16456
|
-
shape: "brep",
|
|
16457
|
-
layer: props.layer,
|
|
16458
|
-
brep_shape: {
|
|
16459
|
-
outer_ring: { vertices: outer_ring_vertices },
|
|
16460
|
-
inner_rings
|
|
16461
|
-
},
|
|
16462
|
-
source_net_id: net.source_net_id,
|
|
16463
|
-
subcircuit_id: this.getSubcircuit()?.subcircuit_id ?? void 0
|
|
16464
|
-
});
|
|
16465
|
-
}
|
|
16466
|
-
}
|
|
16566
|
+
generateAndInsertBRep(pourPolygons, circularObstacles, {
|
|
16567
|
+
db,
|
|
16568
|
+
copperPour: this
|
|
16569
|
+
});
|
|
16467
16570
|
});
|
|
16468
16571
|
}
|
|
16469
16572
|
};
|
|
@@ -17706,7 +17809,7 @@ import { identity as identity6 } from "transformation-matrix";
|
|
|
17706
17809
|
var package_default = {
|
|
17707
17810
|
name: "@tscircuit/core",
|
|
17708
17811
|
type: "module",
|
|
17709
|
-
version: "0.0.
|
|
17812
|
+
version: "0.0.841",
|
|
17710
17813
|
types: "dist/index.d.ts",
|
|
17711
17814
|
main: "dist/index.js",
|
|
17712
17815
|
module: "dist/index.js",
|
|
@@ -17737,7 +17840,7 @@ var package_default = {
|
|
|
17737
17840
|
devDependencies: {
|
|
17738
17841
|
"@biomejs/biome": "^1.8.3",
|
|
17739
17842
|
"@resvg/resvg-js": "^2.6.2",
|
|
17740
|
-
"@tscircuit/capacity-autorouter": "^0.0.
|
|
17843
|
+
"@tscircuit/capacity-autorouter": "^0.0.140",
|
|
17741
17844
|
"@tscircuit/checks": "^0.0.85",
|
|
17742
17845
|
"@tscircuit/circuit-json-util": "^0.0.72",
|
|
17743
17846
|
"@tscircuit/common": "^0.0.14",
|
|
@@ -17749,7 +17852,7 @@ var package_default = {
|
|
|
17749
17852
|
"@tscircuit/math-utils": "^0.0.29",
|
|
17750
17853
|
"@tscircuit/miniflex": "^0.0.4",
|
|
17751
17854
|
"@tscircuit/ngspice-spice-engine": "^0.0.2",
|
|
17752
|
-
"@tscircuit/props": "^0.0.
|
|
17855
|
+
"@tscircuit/props": "^0.0.390",
|
|
17753
17856
|
"@tscircuit/schematic-autolayout": "^0.0.6",
|
|
17754
17857
|
"@tscircuit/schematic-match-adapt": "^0.0.16",
|
|
17755
17858
|
"@tscircuit/schematic-trace-solver": "^0.0.43",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tscircuit/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.842",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@biomejs/biome": "^1.8.3",
|
|
34
34
|
"@resvg/resvg-js": "^2.6.2",
|
|
35
|
-
"@tscircuit/capacity-autorouter": "^0.0.
|
|
35
|
+
"@tscircuit/capacity-autorouter": "^0.0.140",
|
|
36
36
|
"@tscircuit/checks": "^0.0.85",
|
|
37
37
|
"@tscircuit/circuit-json-util": "^0.0.72",
|
|
38
38
|
"@tscircuit/common": "^0.0.14",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@tscircuit/math-utils": "^0.0.29",
|
|
45
45
|
"@tscircuit/miniflex": "^0.0.4",
|
|
46
46
|
"@tscircuit/ngspice-spice-engine": "^0.0.2",
|
|
47
|
-
"@tscircuit/props": "^0.0.
|
|
47
|
+
"@tscircuit/props": "^0.0.390",
|
|
48
48
|
"@tscircuit/schematic-autolayout": "^0.0.6",
|
|
49
49
|
"@tscircuit/schematic-match-adapt": "^0.0.16",
|
|
50
50
|
"@tscircuit/schematic-trace-solver": "^0.0.43",
|