circuit-json-to-connectivity-map 0.0.11 → 0.0.13
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 +24 -2
- package/dist/index.js +102 -5
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AnySoupElement } from '@tscircuit/soup';
|
|
1
|
+
import { AnySoupElement, AnyCircuitElement, PCBTrace, PCBPort } from '@tscircuit/soup';
|
|
2
2
|
|
|
3
3
|
type NodeId = string;
|
|
4
4
|
declare function findConnectedNetworks(connections: Array<NodeId[]>): Record<string, string[]>;
|
|
@@ -17,4 +17,26 @@ declare const getSourcePortConnectivityMapFromCircuitJson: (circuitJson: AnySoup
|
|
|
17
17
|
|
|
18
18
|
declare const getFullConnectivityMapFromCircuitJson: (circuitJson: AnySoupElement[]) => ConnectivityMap;
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
/**
|
|
21
|
+
* A PCB Connectivity Map is a connectivity map that has analyzed what traces and ports are actually connected on the
|
|
22
|
+
* PCB.
|
|
23
|
+
*
|
|
24
|
+
* This is useful for determining how to route a trace on the PCB. For example, you may want to determine where the
|
|
25
|
+
* nearest connected net point is to connect an unrouted pin.
|
|
26
|
+
*/
|
|
27
|
+
declare class PcbConnectivityMap {
|
|
28
|
+
circuitJson: AnyCircuitElement[];
|
|
29
|
+
traceIdToElm: Map<string, PCBTrace>;
|
|
30
|
+
portIdToElm: Map<string, PCBPort>;
|
|
31
|
+
connMap: ConnectivityMap;
|
|
32
|
+
constructor(circuitJson: AnyCircuitElement[]);
|
|
33
|
+
private _buildPortMap;
|
|
34
|
+
private _buildTraceMap;
|
|
35
|
+
private _buildTraceConnectivityMap;
|
|
36
|
+
_arePcbTracesConnected(trace1: PCBTrace, trace2: PCBTrace): boolean;
|
|
37
|
+
areTracesConnected(traceId1: string, traceId2: string): boolean;
|
|
38
|
+
getAllTracesConnectedToTrace(traceId: string): PCBTrace[];
|
|
39
|
+
getAllTracesConnectedToPort(portId: string): PCBTrace[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export { ConnectivityMap, PcbConnectivityMap, findConnectedNetworks, getFullConnectivityMapFromCircuitJson, getSourcePortConnectivityMapFromCircuitJson };
|
package/dist/index.js
CHANGED
|
@@ -100,11 +100,13 @@ var getFullConnectivityMapFromCircuitJson = (circuitJson) => {
|
|
|
100
100
|
const connections = [];
|
|
101
101
|
for (const element of circuitJson) {
|
|
102
102
|
if (element.type === "source_trace") {
|
|
103
|
-
connections.push(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
103
|
+
connections.push(
|
|
104
|
+
[
|
|
105
|
+
element.source_trace_id,
|
|
106
|
+
...element.connected_source_port_ids ?? [],
|
|
107
|
+
...element.connected_source_net_ids ?? []
|
|
108
|
+
].filter(Boolean)
|
|
109
|
+
);
|
|
108
110
|
} else if (element.type === "pcb_port") {
|
|
109
111
|
const { pcb_port_id, source_port_id } = element;
|
|
110
112
|
if (source_port_id && pcb_port_id) {
|
|
@@ -130,8 +132,103 @@ var getFullConnectivityMapFromCircuitJson = (circuitJson) => {
|
|
|
130
132
|
const netMap = findConnectedNetworks(connections);
|
|
131
133
|
return new ConnectivityMap(netMap);
|
|
132
134
|
};
|
|
135
|
+
|
|
136
|
+
// src/PcbConnectivityMap.ts
|
|
137
|
+
import { doesLineIntersectLine } from "@tscircuit/math-utils";
|
|
138
|
+
var PcbConnectivityMap = class {
|
|
139
|
+
circuitJson;
|
|
140
|
+
traceIdToElm;
|
|
141
|
+
portIdToElm;
|
|
142
|
+
connMap;
|
|
143
|
+
constructor(circuitJson) {
|
|
144
|
+
this.circuitJson = circuitJson;
|
|
145
|
+
this.traceIdToElm = /* @__PURE__ */ new Map();
|
|
146
|
+
this.portIdToElm = /* @__PURE__ */ new Map();
|
|
147
|
+
this._buildTraceMap();
|
|
148
|
+
this._buildPortMap();
|
|
149
|
+
this.connMap = this._buildTraceConnectivityMap();
|
|
150
|
+
}
|
|
151
|
+
_buildPortMap() {
|
|
152
|
+
for (const element of this.circuitJson) {
|
|
153
|
+
if (element.type === "pcb_port") {
|
|
154
|
+
this.portIdToElm.set(element.pcb_port_id, element);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
_buildTraceMap() {
|
|
159
|
+
for (const element of this.circuitJson) {
|
|
160
|
+
if (element.type === "pcb_trace") {
|
|
161
|
+
this.traceIdToElm.set(element.pcb_trace_id, element);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
_buildTraceConnectivityMap() {
|
|
166
|
+
const connections = [];
|
|
167
|
+
const traceIds = Array.from(this.traceIdToElm.keys());
|
|
168
|
+
for (let i = 0; i < traceIds.length; i++) {
|
|
169
|
+
for (let j = i + 1; j < traceIds.length; j++) {
|
|
170
|
+
const trace1 = this.traceIdToElm.get(traceIds[i]);
|
|
171
|
+
const trace2 = this.traceIdToElm.get(traceIds[j]);
|
|
172
|
+
if (this._arePcbTracesConnected(trace1, trace2)) {
|
|
173
|
+
connections.push([traceIds[i], traceIds[j]]);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
for (const port of this.portIdToElm.values()) {
|
|
178
|
+
for (const trace of this.traceIdToElm.values()) {
|
|
179
|
+
for (const rp of trace.route) {
|
|
180
|
+
if (rp.route_type === "wire") {
|
|
181
|
+
if (rp.start_pcb_port_id === port.pcb_port_id) {
|
|
182
|
+
connections.push([port.pcb_port_id, trace.pcb_trace_id]);
|
|
183
|
+
} else if (rp.end_pcb_port_id === port.pcb_port_id) {
|
|
184
|
+
connections.push([trace.pcb_trace_id, port.pcb_port_id]);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return new ConnectivityMap(findConnectedNetworks(connections));
|
|
191
|
+
}
|
|
192
|
+
_arePcbTracesConnected(trace1, trace2) {
|
|
193
|
+
for (let i = 0; i < trace1.route.length - 1; i++) {
|
|
194
|
+
const segment1A = trace1.route[i];
|
|
195
|
+
const segment1B = trace1.route[i + 1];
|
|
196
|
+
if (segment1A.route_type !== "wire") continue;
|
|
197
|
+
if (segment1B.route_type !== "wire") continue;
|
|
198
|
+
for (let j = 0; j < trace2.route.length - 1; j++) {
|
|
199
|
+
const segment2A = trace2.route[j];
|
|
200
|
+
const segment2B = trace2.route[j + 1];
|
|
201
|
+
if (segment2A.route_type !== "wire") continue;
|
|
202
|
+
if (segment2B.route_type !== "wire") continue;
|
|
203
|
+
const isOverlapping = doesLineIntersectLine(
|
|
204
|
+
[segment1A, segment1B],
|
|
205
|
+
[segment2A, segment2B],
|
|
206
|
+
{
|
|
207
|
+
lineThickness: (segment1A.width + segment2A.width) / 2
|
|
208
|
+
}
|
|
209
|
+
);
|
|
210
|
+
if (isOverlapping) {
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
areTracesConnected(traceId1, traceId2) {
|
|
218
|
+
return this.connMap.areIdsConnected(traceId1, traceId2);
|
|
219
|
+
}
|
|
220
|
+
getAllTracesConnectedToTrace(traceId) {
|
|
221
|
+
const netId = this.connMap.getNetConnectedToId(traceId);
|
|
222
|
+
return netId ? this.connMap.getIdsConnectedToNet(netId).filter((id) => this.traceIdToElm.has(id)).map((id) => this.traceIdToElm.get(id)) : [];
|
|
223
|
+
}
|
|
224
|
+
getAllTracesConnectedToPort(portId) {
|
|
225
|
+
const netId = this.connMap.getNetConnectedToId(portId);
|
|
226
|
+
return netId ? this.connMap.getIdsConnectedToNet(netId).filter((id) => this.traceIdToElm.has(id)).map((id) => this.traceIdToElm.get(id)) : [];
|
|
227
|
+
}
|
|
228
|
+
};
|
|
133
229
|
export {
|
|
134
230
|
ConnectivityMap,
|
|
231
|
+
PcbConnectivityMap,
|
|
135
232
|
findConnectedNetworks,
|
|
136
233
|
getFullConnectivityMapFromCircuitJson,
|
|
137
234
|
getSourcePortConnectivityMapFromCircuitJson
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/findConnectedNetworks.ts","../src/ConnectivityMap.ts","../src/getSourcePortConnectivityMapFromCircuitJson.ts","../src/getFullConnectivityMapFromCircuitJson.ts"],"sourcesContent":["type NodeId = string\n\nexport function findConnectedNetworks(\n connections: Array<NodeId[]>,\n): Record<string, string[]> {\n const networks: Map<string, Set<string>> = new Map()\n let netCounter = 0\n\n function getOrCreateNetwork(nodeId: string): Set<string> {\n for (const [, network] of networks) {\n if (network.has(nodeId)) {\n return network\n }\n }\n const newNetwork = new Set<string>()\n networks.set(`connectivity_net${netCounter++}`, newNetwork)\n return newNetwork\n }\n\n for (const connection of connections) {\n let network: Set<string> | null = null\n\n for (const nodeId of connection) {\n if (!network) {\n network = getOrCreateNetwork(nodeId)\n } else if (!network.has(nodeId)) {\n const existingNetwork = getOrCreateNetwork(nodeId)\n if (existingNetwork !== network) {\n // Merge networks\n for (const node of existingNetwork) {\n network.add(node)\n }\n networks.delete(\n Array.from(networks.entries()).find(\n ([, net]) => net === existingNetwork,\n )![0],\n )\n }\n }\n network.add(nodeId)\n }\n }\n\n return Object.fromEntries(\n Array.from(networks.entries()).map(([netId, connectedNodes]) => [\n netId,\n Array.from(connectedNodes),\n ]),\n )\n}\n","export class ConnectivityMap {\n netMap: Record<string, string[]>\n\n idToNetMap: Record<string, string>\n\n constructor(netMap: Record<string, string[]>) {\n this.netMap = netMap\n this.idToNetMap = {}\n for (const [netId, ids] of Object.entries(netMap)) {\n for (const id of ids) {\n this.idToNetMap[id] = netId\n }\n }\n }\n\n getIdsConnectedToNet(netId: string): string[] {\n return this.netMap[netId] || []\n }\n\n getNetConnectedToId(id: string): string | undefined {\n return this.idToNetMap[id]\n }\n\n areIdsConnected(id1: string, id2: string): boolean {\n const netId1 = this.getNetConnectedToId(id1)\n const netId2 = this.getNetConnectedToId(id2)\n return netId1 === netId2 || netId2 === id1 || netId2 === id1\n }\n\n areAllIdsConnected(ids: string[]): boolean {\n let netId = this.getNetConnectedToId(ids[0])\n for (const id of ids) {\n const nextNetId = this.getNetConnectedToId(id)\n if (nextNetId === undefined) {\n return false\n }\n if (nextNetId !== netId) {\n return false\n }\n }\n return true\n }\n}\n","import type { AnySoupElement } from \"@tscircuit/soup\"\nimport { findConnectedNetworks } from \"./findConnectedNetworks\"\nimport { ConnectivityMap } from \"./ConnectivityMap\"\n\nexport const getSourcePortConnectivityMapFromCircuitJson = (\n circuitJson: AnySoupElement[],\n) => {\n const connections: string[][] = []\n\n for (const element of circuitJson) {\n if (element.type === \"source_trace\") {\n connections.push([\n ...(element.connected_source_port_ids ?? []),\n ...(element.connected_source_net_ids ?? []),\n ])\n }\n }\n\n const netMap = findConnectedNetworks(connections)\n\n return new ConnectivityMap(netMap)\n}\n","import type { AnySoupElement } from \"@tscircuit/soup\"\nimport { findConnectedNetworks } from \"./findConnectedNetworks\"\nimport { ConnectivityMap } from \"./ConnectivityMap\"\n\nexport const getFullConnectivityMapFromCircuitJson = (\n circuitJson: AnySoupElement[],\n) => {\n const connections: string[][] = []\n\n for (const element of circuitJson) {\n if (element.type === \"source_trace\") {\n connections.push([\n element.source_trace_id,\n ...(element.connected_source_port_ids ?? []),\n ...(element.connected_source_net_ids ?? []),\n ].filter(Boolean))\n } else if (element.type === \"pcb_port\") {\n const { pcb_port_id, source_port_id } = element\n if (source_port_id && pcb_port_id) {\n connections.push([source_port_id, pcb_port_id])\n }\n } else if (element.type === \"pcb_smtpad\") {\n const { pcb_smtpad_id, pcb_port_id } = element\n if (pcb_port_id && pcb_smtpad_id) {\n connections.push([pcb_smtpad_id, pcb_port_id])\n }\n } else if (element.type === \"pcb_plated_hole\") {\n const { pcb_plated_hole_id, pcb_port_id } = element\n if (pcb_port_id && pcb_plated_hole_id) {\n connections.push([pcb_plated_hole_id, pcb_port_id])\n }\n } else if (element.type === \"pcb_trace\") {\n const { pcb_trace_id, source_trace_id } = element\n if (source_trace_id && pcb_trace_id) {\n connections.push([pcb_trace_id, source_trace_id])\n }\n }\n }\n\n const netMap = findConnectedNetworks(connections)\n\n return new ConnectivityMap(netMap)\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/findConnectedNetworks.ts","../src/ConnectivityMap.ts","../src/getSourcePortConnectivityMapFromCircuitJson.ts","../src/getFullConnectivityMapFromCircuitJson.ts","../src/PcbConnectivityMap.ts"],"sourcesContent":["type NodeId = string\n\nexport function findConnectedNetworks(\n connections: Array<NodeId[]>,\n): Record<string, string[]> {\n const networks: Map<string, Set<string>> = new Map()\n let netCounter = 0\n\n function getOrCreateNetwork(nodeId: string): Set<string> {\n for (const [, network] of networks) {\n if (network.has(nodeId)) {\n return network\n }\n }\n const newNetwork = new Set<string>()\n networks.set(`connectivity_net${netCounter++}`, newNetwork)\n return newNetwork\n }\n\n for (const connection of connections) {\n let network: Set<string> | null = null\n\n for (const nodeId of connection) {\n if (!network) {\n network = getOrCreateNetwork(nodeId)\n } else if (!network.has(nodeId)) {\n const existingNetwork = getOrCreateNetwork(nodeId)\n if (existingNetwork !== network) {\n // Merge networks\n for (const node of existingNetwork) {\n network.add(node)\n }\n networks.delete(\n Array.from(networks.entries()).find(\n ([, net]) => net === existingNetwork,\n )![0],\n )\n }\n }\n network.add(nodeId)\n }\n }\n\n return Object.fromEntries(\n Array.from(networks.entries()).map(([netId, connectedNodes]) => [\n netId,\n Array.from(connectedNodes),\n ]),\n )\n}\n","export class ConnectivityMap {\n netMap: Record<string, string[]>\n\n idToNetMap: Record<string, string>\n\n constructor(netMap: Record<string, string[]>) {\n this.netMap = netMap\n this.idToNetMap = {}\n for (const [netId, ids] of Object.entries(netMap)) {\n for (const id of ids) {\n this.idToNetMap[id] = netId\n }\n }\n }\n\n getIdsConnectedToNet(netId: string): string[] {\n return this.netMap[netId] || []\n }\n\n getNetConnectedToId(id: string): string | undefined {\n return this.idToNetMap[id]\n }\n\n areIdsConnected(id1: string, id2: string): boolean {\n const netId1 = this.getNetConnectedToId(id1)\n const netId2 = this.getNetConnectedToId(id2)\n return netId1 === netId2 || netId2 === id1 || netId2 === id1\n }\n\n areAllIdsConnected(ids: string[]): boolean {\n let netId = this.getNetConnectedToId(ids[0])\n for (const id of ids) {\n const nextNetId = this.getNetConnectedToId(id)\n if (nextNetId === undefined) {\n return false\n }\n if (nextNetId !== netId) {\n return false\n }\n }\n return true\n }\n}\n","import type { AnySoupElement } from \"@tscircuit/soup\"\nimport { findConnectedNetworks } from \"./findConnectedNetworks\"\nimport { ConnectivityMap } from \"./ConnectivityMap\"\n\nexport const getSourcePortConnectivityMapFromCircuitJson = (\n circuitJson: AnySoupElement[],\n) => {\n const connections: string[][] = []\n\n for (const element of circuitJson) {\n if (element.type === \"source_trace\") {\n connections.push([\n ...(element.connected_source_port_ids ?? []),\n ...(element.connected_source_net_ids ?? []),\n ])\n }\n }\n\n const netMap = findConnectedNetworks(connections)\n\n return new ConnectivityMap(netMap)\n}\n","import type { AnySoupElement } from \"@tscircuit/soup\"\nimport { findConnectedNetworks } from \"./findConnectedNetworks\"\nimport { ConnectivityMap } from \"./ConnectivityMap\"\n\nexport const getFullConnectivityMapFromCircuitJson = (\n circuitJson: AnySoupElement[],\n) => {\n const connections: string[][] = []\n\n for (const element of circuitJson) {\n if (element.type === \"source_trace\") {\n connections.push(\n [\n element.source_trace_id,\n ...(element.connected_source_port_ids ?? []),\n ...(element.connected_source_net_ids ?? []),\n ].filter(Boolean),\n )\n } else if (element.type === \"pcb_port\") {\n const { pcb_port_id, source_port_id } = element\n if (source_port_id && pcb_port_id) {\n connections.push([source_port_id, pcb_port_id])\n }\n } else if (element.type === \"pcb_smtpad\") {\n const { pcb_smtpad_id, pcb_port_id } = element\n if (pcb_port_id && pcb_smtpad_id) {\n connections.push([pcb_smtpad_id, pcb_port_id])\n }\n } else if (element.type === \"pcb_plated_hole\") {\n const { pcb_plated_hole_id, pcb_port_id } = element\n if (pcb_port_id && pcb_plated_hole_id) {\n connections.push([pcb_plated_hole_id, pcb_port_id])\n }\n } else if (element.type === \"pcb_trace\") {\n const { pcb_trace_id, source_trace_id } = element\n if (source_trace_id && pcb_trace_id) {\n connections.push([pcb_trace_id, source_trace_id])\n }\n }\n }\n\n const netMap = findConnectedNetworks(connections)\n\n return new ConnectivityMap(netMap)\n}\n","import type { AnyCircuitElement, PCBPort, PCBTrace } from \"@tscircuit/soup\"\nimport { ConnectivityMap } from \"./ConnectivityMap\"\nimport { doesLineIntersectLine } from \"@tscircuit/math-utils\"\nimport { findConnectedNetworks } from \"./findConnectedNetworks\"\n\n/**\n * A PCB Connectivity Map is a connectivity map that has analyzed what traces and ports are actually connected on the\n * PCB.\n *\n * This is useful for determining how to route a trace on the PCB. For example, you may want to determine where the\n * nearest connected net point is to connect an unrouted pin.\n */\nexport class PcbConnectivityMap {\n circuitJson: AnyCircuitElement[]\n traceIdToElm: Map<string, PCBTrace>\n portIdToElm: Map<string, PCBPort>\n connMap: ConnectivityMap\n\n constructor(circuitJson: AnyCircuitElement[]) {\n this.circuitJson = circuitJson\n this.traceIdToElm = new Map()\n this.portIdToElm = new Map()\n this._buildTraceMap()\n this._buildPortMap()\n this.connMap = this._buildTraceConnectivityMap()\n }\n\n private _buildPortMap() {\n for (const element of this.circuitJson) {\n if (element.type === \"pcb_port\") {\n this.portIdToElm.set(element.pcb_port_id, element as PCBPort)\n }\n }\n }\n\n private _buildTraceMap() {\n for (const element of this.circuitJson) {\n if (element.type === \"pcb_trace\") {\n this.traceIdToElm.set(element.pcb_trace_id, element as PCBTrace)\n }\n }\n }\n\n private _buildTraceConnectivityMap(): ConnectivityMap {\n const connections: string[][] = []\n const traceIds = Array.from(this.traceIdToElm.keys())\n\n for (let i = 0; i < traceIds.length; i++) {\n for (let j = i + 1; j < traceIds.length; j++) {\n const trace1 = this.traceIdToElm.get(traceIds[i])!\n const trace2 = this.traceIdToElm.get(traceIds[j])!\n if (this._arePcbTracesConnected(trace1, trace2)) {\n connections.push([traceIds[i], traceIds[j]])\n }\n }\n }\n\n for (const port of this.portIdToElm.values()) {\n for (const trace of this.traceIdToElm.values()) {\n for (const rp of trace.route) {\n if (rp.route_type === \"wire\") {\n if (rp.start_pcb_port_id === port.pcb_port_id) {\n connections.push([port.pcb_port_id, trace.pcb_trace_id])\n } else if (rp.end_pcb_port_id === port.pcb_port_id) {\n connections.push([trace.pcb_trace_id, port.pcb_port_id])\n }\n }\n }\n }\n }\n\n return new ConnectivityMap(findConnectedNetworks(connections))\n }\n\n _arePcbTracesConnected(trace1: PCBTrace, trace2: PCBTrace): boolean {\n for (let i = 0; i < trace1.route.length - 1; i++) {\n const segment1A = trace1.route[i]\n const segment1B = trace1.route[i + 1]\n if (segment1A.route_type !== \"wire\") continue\n if (segment1B.route_type !== \"wire\") continue\n for (let j = 0; j < trace2.route.length - 1; j++) {\n const segment2A = trace2.route[j]\n const segment2B = trace2.route[j + 1]\n\n if (segment2A.route_type !== \"wire\") continue\n if (segment2B.route_type !== \"wire\") continue\n\n // Check if lines are overlapping\n const isOverlapping = doesLineIntersectLine(\n [segment1A, segment1B],\n [segment2A, segment2B],\n {\n lineThickness: (segment1A.width + segment2A.width) / 2,\n },\n )\n if (isOverlapping) {\n return true\n }\n }\n }\n return false\n }\n\n areTracesConnected(traceId1: string, traceId2: string): boolean {\n return this.connMap.areIdsConnected(traceId1, traceId2)\n }\n\n getAllTracesConnectedToTrace(traceId: string): PCBTrace[] {\n const netId = this.connMap.getNetConnectedToId(traceId)\n return netId\n ? this.connMap\n .getIdsConnectedToNet(netId)\n .filter((id) => this.traceIdToElm.has(id))\n .map((id) => this.traceIdToElm.get(id) as PCBTrace)\n : []\n }\n\n getAllTracesConnectedToPort(portId: string): PCBTrace[] {\n const netId = this.connMap.getNetConnectedToId(portId)\n return netId\n ? this.connMap\n .getIdsConnectedToNet(netId)\n .filter((id) => this.traceIdToElm.has(id))\n .map((id) => this.traceIdToElm.get(id) as PCBTrace)\n : []\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "circuit-json-to-connectivity-map",
|
|
3
3
|
"main": "dist/index.js",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.13",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist"
|
|
8
8
|
],
|
|
@@ -13,11 +13,14 @@
|
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
15
|
"@biomejs/biome": "^1.9.0",
|
|
16
|
-
"@tscircuit/soup": "^0.0.
|
|
16
|
+
"@tscircuit/soup": "^0.0.70",
|
|
17
17
|
"@types/bun": "latest",
|
|
18
18
|
"tsup": "^8.2.4"
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|
|
21
21
|
"typescript": "^5.0.0"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@tscircuit/math-utils": "^0.0.2"
|
|
22
25
|
}
|
|
23
26
|
}
|