circuit-to-svg 0.0.305 → 0.0.307
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.js +394 -212
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// lib/pcb/convert-circuit-json-to-pcb-svg.ts
|
|
2
|
-
import
|
|
2
|
+
import "circuit-json";
|
|
3
3
|
import { stringify } from "svgson";
|
|
4
4
|
import {
|
|
5
5
|
applyToPoint as applyToPoint37,
|
|
@@ -3834,10 +3834,10 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
|
|
|
3834
3834
|
maskPoints = points.map(([px, py]) => {
|
|
3835
3835
|
const dx = px - centroidX;
|
|
3836
3836
|
const dy = py - centroidY;
|
|
3837
|
-
const
|
|
3838
|
-
if (
|
|
3839
|
-
const normalizedDx = dx /
|
|
3840
|
-
const normalizedDy = dy /
|
|
3837
|
+
const distance5 = Math.sqrt(dx * dx + dy * dy);
|
|
3838
|
+
if (distance5 === 0) return [px, py];
|
|
3839
|
+
const normalizedDx = dx / distance5;
|
|
3840
|
+
const normalizedDy = dy / distance5;
|
|
3841
3841
|
return [
|
|
3842
3842
|
px + normalizedDx * soldermaskMargin,
|
|
3843
3843
|
py + normalizedDy * soldermaskMargin
|
|
@@ -4043,11 +4043,11 @@ function createAnchorOffsetIndicators(params) {
|
|
|
4043
4043
|
function getTrimmedConnectorLine(x1, y1, x2, y2) {
|
|
4044
4044
|
const dx = x2 - x1;
|
|
4045
4045
|
const dy = y2 - y1;
|
|
4046
|
-
const
|
|
4046
|
+
const distance5 = Math.hypot(dx, dy);
|
|
4047
4047
|
const totalTrim = CONNECTOR_GROUP_GAP_PX + CONNECTOR_COMPONENT_GAP_PX;
|
|
4048
|
-
if (!(
|
|
4049
|
-
const ux = dx /
|
|
4050
|
-
const uy = dy /
|
|
4048
|
+
if (!(distance5 > totalTrim)) return { x1, y1, x2, y2 };
|
|
4049
|
+
const ux = dx / distance5;
|
|
4050
|
+
const uy = dy / distance5;
|
|
4051
4051
|
return {
|
|
4052
4052
|
x1: x1 + ux * CONNECTOR_GROUP_GAP_PX,
|
|
4053
4053
|
y1: y1 + uy * CONNECTOR_GROUP_GAP_PX,
|
|
@@ -5004,9 +5004,9 @@ var findNearestPointInNet = (sourcePoint, netId, connectivity, circuitJson) => {
|
|
|
5004
5004
|
if (pos) {
|
|
5005
5005
|
const dx = sourcePoint.x - pos.x;
|
|
5006
5006
|
const dy = sourcePoint.y - pos.y;
|
|
5007
|
-
const
|
|
5008
|
-
if (
|
|
5009
|
-
minDistance =
|
|
5007
|
+
const distance5 = Math.sqrt(dx * dx + dy * dy);
|
|
5008
|
+
if (distance5 > 0 && distance5 < minDistance) {
|
|
5009
|
+
minDistance = distance5;
|
|
5010
5010
|
nearestPoint = pos;
|
|
5011
5011
|
}
|
|
5012
5012
|
}
|
|
@@ -5884,7 +5884,7 @@ function getSoftwareUsedString(circuitJson) {
|
|
|
5884
5884
|
var package_default = {
|
|
5885
5885
|
name: "circuit-to-svg",
|
|
5886
5886
|
type: "module",
|
|
5887
|
-
version: "0.0.
|
|
5887
|
+
version: "0.0.306",
|
|
5888
5888
|
description: "Convert Circuit JSON to SVG",
|
|
5889
5889
|
main: "dist/index.js",
|
|
5890
5890
|
files: [
|
|
@@ -6066,49 +6066,9 @@ function createErrorTextOverlay(circuitJson, dataType = "error_text_overlay") {
|
|
|
6066
6066
|
return textBlock;
|
|
6067
6067
|
}
|
|
6068
6068
|
|
|
6069
|
-
// lib/pcb/
|
|
6070
|
-
|
|
6071
|
-
|
|
6072
|
-
const layer = options?.layer;
|
|
6073
|
-
const colorOverrides = options?.colorOverrides;
|
|
6074
|
-
const copperColors = {
|
|
6075
|
-
...DEFAULT_PCB_COLOR_MAP.copper
|
|
6076
|
-
};
|
|
6077
|
-
if (colorOverrides?.copper) {
|
|
6078
|
-
for (const [layerName, color] of Object.entries(colorOverrides.copper)) {
|
|
6079
|
-
if (color !== void 0) {
|
|
6080
|
-
copperColors[layerName] = color;
|
|
6081
|
-
}
|
|
6082
|
-
}
|
|
6083
|
-
}
|
|
6084
|
-
const colorMap2 = {
|
|
6085
|
-
copper: copperColors,
|
|
6086
|
-
drill: colorOverrides?.drill ?? DEFAULT_PCB_COLOR_MAP.drill,
|
|
6087
|
-
silkscreen: {
|
|
6088
|
-
top: colorOverrides?.silkscreen?.top ?? DEFAULT_PCB_COLOR_MAP.silkscreen.top,
|
|
6089
|
-
bottom: colorOverrides?.silkscreen?.bottom ?? DEFAULT_PCB_COLOR_MAP.silkscreen.bottom
|
|
6090
|
-
},
|
|
6091
|
-
boardOutline: colorOverrides?.boardOutline ?? DEFAULT_PCB_COLOR_MAP.boardOutline,
|
|
6092
|
-
soldermask: {
|
|
6093
|
-
top: colorOverrides?.soldermask?.top ?? DEFAULT_PCB_COLOR_MAP.soldermask.top,
|
|
6094
|
-
bottom: colorOverrides?.soldermask?.bottom ?? DEFAULT_PCB_COLOR_MAP.soldermask.bottom
|
|
6095
|
-
},
|
|
6096
|
-
soldermaskOverCopper: {
|
|
6097
|
-
top: colorOverrides?.soldermaskOverCopper?.top ?? DEFAULT_PCB_COLOR_MAP.soldermaskOverCopper.top,
|
|
6098
|
-
bottom: colorOverrides?.soldermaskOverCopper?.bottom ?? DEFAULT_PCB_COLOR_MAP.soldermaskOverCopper.bottom
|
|
6099
|
-
},
|
|
6100
|
-
soldermaskWithCopperUnderneath: {
|
|
6101
|
-
top: colorOverrides?.soldermaskWithCopperUnderneath?.top ?? DEFAULT_PCB_COLOR_MAP.soldermaskWithCopperUnderneath.top,
|
|
6102
|
-
bottom: colorOverrides?.soldermaskWithCopperUnderneath?.bottom ?? DEFAULT_PCB_COLOR_MAP.soldermaskWithCopperUnderneath.bottom
|
|
6103
|
-
},
|
|
6104
|
-
substrate: colorOverrides?.substrate ?? DEFAULT_PCB_COLOR_MAP.substrate,
|
|
6105
|
-
courtyard: colorOverrides?.courtyard ?? DEFAULT_PCB_COLOR_MAP.courtyard,
|
|
6106
|
-
keepout: colorOverrides?.keepout ?? DEFAULT_PCB_COLOR_MAP.keepout,
|
|
6107
|
-
debugComponent: {
|
|
6108
|
-
fill: colorOverrides?.debugComponent?.fill ?? DEFAULT_PCB_COLOR_MAP.debugComponent.fill,
|
|
6109
|
-
stroke: colorOverrides?.debugComponent?.stroke ?? DEFAULT_PCB_COLOR_MAP.debugComponent.stroke
|
|
6110
|
-
}
|
|
6111
|
-
};
|
|
6069
|
+
// lib/pcb/get-pcb-bounds-from-circuit-json.ts
|
|
6070
|
+
import { distance as distance2 } from "circuit-json";
|
|
6071
|
+
function getPcbBoundsFromCircuitJson(circuitJson) {
|
|
6112
6072
|
let minX = Number.POSITIVE_INFINITY;
|
|
6113
6073
|
let minY = Number.POSITIVE_INFINITY;
|
|
6114
6074
|
let maxX = Number.NEGATIVE_INFINITY;
|
|
@@ -6128,53 +6088,167 @@ function convertCircuitJsonToPcbSvg(circuitJson, options) {
|
|
|
6128
6088
|
continue;
|
|
6129
6089
|
}
|
|
6130
6090
|
const center = panel.center ?? { x: width / 2, y: height / 2 };
|
|
6131
|
-
updateBounds(center, width, height);
|
|
6091
|
+
updateBounds({ center, width, height });
|
|
6132
6092
|
} else if (circuitJsonElm.type === "pcb_board") {
|
|
6133
6093
|
if (circuitJsonElm.outline && Array.isArray(circuitJsonElm.outline) && circuitJsonElm.outline.length >= 3) {
|
|
6134
6094
|
updateBoundsToIncludeOutline(circuitJsonElm.outline);
|
|
6135
6095
|
updateBoardBoundsToIncludeOutline(circuitJsonElm.outline);
|
|
6136
6096
|
} else if ("center" in circuitJsonElm && "width" in circuitJsonElm && "height" in circuitJsonElm) {
|
|
6137
|
-
updateBounds(
|
|
6138
|
-
circuitJsonElm.center,
|
|
6139
|
-
circuitJsonElm.width,
|
|
6140
|
-
circuitJsonElm.height
|
|
6141
|
-
);
|
|
6142
|
-
updateBoardBounds(
|
|
6143
|
-
circuitJsonElm.center,
|
|
6144
|
-
circuitJsonElm.width,
|
|
6145
|
-
circuitJsonElm.height
|
|
6146
|
-
);
|
|
6097
|
+
updateBounds({
|
|
6098
|
+
center: circuitJsonElm.center,
|
|
6099
|
+
width: circuitJsonElm.width,
|
|
6100
|
+
height: circuitJsonElm.height
|
|
6101
|
+
});
|
|
6102
|
+
updateBoardBounds({
|
|
6103
|
+
center: circuitJsonElm.center,
|
|
6104
|
+
width: circuitJsonElm.width,
|
|
6105
|
+
height: circuitJsonElm.height
|
|
6106
|
+
});
|
|
6147
6107
|
}
|
|
6148
6108
|
} else if (circuitJsonElm.type === "pcb_smtpad") {
|
|
6149
6109
|
const pad = circuitJsonElm;
|
|
6150
6110
|
if (pad.shape === "rect" || pad.shape === "rotated_rect" || pad.shape === "pill") {
|
|
6151
|
-
updateBounds({
|
|
6111
|
+
updateBounds({
|
|
6112
|
+
center: { x: pad.x, y: pad.y },
|
|
6113
|
+
width: pad.width,
|
|
6114
|
+
height: pad.height
|
|
6115
|
+
});
|
|
6152
6116
|
} else if (pad.shape === "circle") {
|
|
6153
6117
|
const radius = distance2.parse(pad.radius);
|
|
6154
6118
|
if (radius !== void 0) {
|
|
6155
|
-
updateBounds({
|
|
6119
|
+
updateBounds({
|
|
6120
|
+
center: { x: pad.x, y: pad.y },
|
|
6121
|
+
width: radius * 2,
|
|
6122
|
+
height: radius * 2
|
|
6123
|
+
});
|
|
6156
6124
|
}
|
|
6157
6125
|
} else if (pad.shape === "polygon") {
|
|
6158
6126
|
updateTraceBounds(pad.points);
|
|
6159
6127
|
}
|
|
6160
6128
|
} else if ("x" in circuitJsonElm && "y" in circuitJsonElm) {
|
|
6161
|
-
updateBounds({
|
|
6129
|
+
updateBounds({
|
|
6130
|
+
center: { x: circuitJsonElm.x, y: circuitJsonElm.y },
|
|
6131
|
+
width: 0,
|
|
6132
|
+
height: 0
|
|
6133
|
+
});
|
|
6162
6134
|
} else if ("route" in circuitJsonElm) {
|
|
6163
6135
|
updateTraceBounds(circuitJsonElm.route);
|
|
6164
6136
|
} else if (circuitJsonElm.type === "pcb_note_rect" || circuitJsonElm.type === "pcb_fabrication_note_rect") {
|
|
6165
|
-
updateBounds(
|
|
6166
|
-
circuitJsonElm.center,
|
|
6167
|
-
circuitJsonElm.width,
|
|
6168
|
-
circuitJsonElm.height
|
|
6169
|
-
);
|
|
6137
|
+
updateBounds({
|
|
6138
|
+
center: circuitJsonElm.center,
|
|
6139
|
+
width: circuitJsonElm.width,
|
|
6140
|
+
height: circuitJsonElm.height
|
|
6141
|
+
});
|
|
6142
|
+
} else if (circuitJsonElm.type === "pcb_note_dimension" || circuitJsonElm.type === "pcb_fabrication_note_dimension") {
|
|
6143
|
+
const dimension = circuitJsonElm;
|
|
6144
|
+
const {
|
|
6145
|
+
from,
|
|
6146
|
+
to,
|
|
6147
|
+
text,
|
|
6148
|
+
font_size = 1,
|
|
6149
|
+
arrow_size,
|
|
6150
|
+
offset_distance,
|
|
6151
|
+
offset_direction
|
|
6152
|
+
} = dimension;
|
|
6153
|
+
if (!from || !to || !arrow_size) continue;
|
|
6154
|
+
updateBounds({ center: from, width: 0, height: 0 });
|
|
6155
|
+
updateBounds({ center: to, width: 0, height: 0 });
|
|
6156
|
+
const normalize3 = (v) => {
|
|
6157
|
+
const l = Math.hypot(v.x, v.y) || 1;
|
|
6158
|
+
return { x: v.x / l, y: v.y / l };
|
|
6159
|
+
};
|
|
6160
|
+
const direction = normalize3({ x: to.x - from.x, y: to.y - from.y });
|
|
6161
|
+
if (Number.isNaN(direction.x) || Number.isNaN(direction.y)) continue;
|
|
6162
|
+
const perpendicular = { x: -direction.y, y: direction.x };
|
|
6163
|
+
const hasOffsetDirection = offset_direction && typeof offset_direction.x === "number" && typeof offset_direction.y === "number";
|
|
6164
|
+
const normalizedOffsetDirection = hasOffsetDirection ? normalize3(offset_direction) : { x: 0, y: 0 };
|
|
6165
|
+
const offsetMagnitude = typeof offset_distance === "number" ? offset_distance : 0;
|
|
6166
|
+
const offsetVector = {
|
|
6167
|
+
x: normalizedOffsetDirection.x * offsetMagnitude,
|
|
6168
|
+
y: normalizedOffsetDirection.y * offsetMagnitude
|
|
6169
|
+
};
|
|
6170
|
+
const fromOffset = {
|
|
6171
|
+
x: from.x + offsetVector.x,
|
|
6172
|
+
y: from.y + offsetVector.y
|
|
6173
|
+
};
|
|
6174
|
+
const toOffset = { x: to.x + offsetVector.x, y: to.y + offsetVector.y };
|
|
6175
|
+
updateBounds({ center: fromOffset, width: 0, height: 0 });
|
|
6176
|
+
updateBounds({ center: toOffset, width: 0, height: 0 });
|
|
6177
|
+
const extensionDirection = hasOffsetDirection && (Math.abs(normalizedOffsetDirection.x) > Number.EPSILON || Math.abs(normalizedOffsetDirection.y) > Number.EPSILON) ? normalizedOffsetDirection : perpendicular;
|
|
6178
|
+
const extensionLength = offsetMagnitude + arrow_size;
|
|
6179
|
+
const fromExtEnd = {
|
|
6180
|
+
x: from.x + extensionDirection.x * extensionLength,
|
|
6181
|
+
y: from.y + extensionDirection.y * extensionLength
|
|
6182
|
+
};
|
|
6183
|
+
const toExtEnd = {
|
|
6184
|
+
x: to.x + extensionDirection.x * extensionLength,
|
|
6185
|
+
y: to.y + extensionDirection.y * extensionLength
|
|
6186
|
+
};
|
|
6187
|
+
updateBounds({ center: fromExtEnd, width: 0, height: 0 });
|
|
6188
|
+
updateBounds({ center: toExtEnd, width: 0, height: 0 });
|
|
6189
|
+
const arrowHalfWidth = arrow_size / 2;
|
|
6190
|
+
const fromBase = {
|
|
6191
|
+
x: fromOffset.x + direction.x * arrow_size,
|
|
6192
|
+
y: fromOffset.y + direction.y * arrow_size
|
|
6193
|
+
};
|
|
6194
|
+
const toBase = {
|
|
6195
|
+
x: toOffset.x - direction.x * arrow_size,
|
|
6196
|
+
y: toOffset.y - direction.y * arrow_size
|
|
6197
|
+
};
|
|
6198
|
+
const fromArrowP2 = {
|
|
6199
|
+
x: fromBase.x + perpendicular.x * arrowHalfWidth,
|
|
6200
|
+
y: fromBase.y + perpendicular.y * arrowHalfWidth
|
|
6201
|
+
};
|
|
6202
|
+
const fromArrowP3 = {
|
|
6203
|
+
x: fromBase.x - perpendicular.x * arrowHalfWidth,
|
|
6204
|
+
y: fromBase.y - perpendicular.y * arrowHalfWidth
|
|
6205
|
+
};
|
|
6206
|
+
updateBounds({ center: fromArrowP2, width: 0, height: 0 });
|
|
6207
|
+
updateBounds({ center: fromArrowP3, width: 0, height: 0 });
|
|
6208
|
+
const toArrowP2 = {
|
|
6209
|
+
x: toBase.x + perpendicular.x * arrowHalfWidth,
|
|
6210
|
+
y: toBase.y + perpendicular.y * arrowHalfWidth
|
|
6211
|
+
};
|
|
6212
|
+
const toArrowP3 = {
|
|
6213
|
+
x: toBase.x - perpendicular.x * arrowHalfWidth,
|
|
6214
|
+
y: toBase.y - perpendicular.y * arrowHalfWidth
|
|
6215
|
+
};
|
|
6216
|
+
updateBounds({ center: toArrowP2, width: 0, height: 0 });
|
|
6217
|
+
updateBounds({ center: toArrowP3, width: 0, height: 0 });
|
|
6218
|
+
if (text) {
|
|
6219
|
+
const midPoint = {
|
|
6220
|
+
x: (from.x + to.x) / 2 + offsetVector.x,
|
|
6221
|
+
y: (from.y + to.y) / 2 + offsetVector.y
|
|
6222
|
+
};
|
|
6223
|
+
const textOffset = arrow_size * 1.5;
|
|
6224
|
+
const textPoint = {
|
|
6225
|
+
x: midPoint.x + perpendicular.x * textOffset,
|
|
6226
|
+
y: midPoint.y + perpendicular.y * textOffset
|
|
6227
|
+
};
|
|
6228
|
+
const textWidth = text.length * font_size * 0.6;
|
|
6229
|
+
const textHeight = font_size;
|
|
6230
|
+
updateBounds({
|
|
6231
|
+
center: textPoint,
|
|
6232
|
+
width: textWidth,
|
|
6233
|
+
height: textHeight
|
|
6234
|
+
});
|
|
6235
|
+
}
|
|
6170
6236
|
} else if (circuitJsonElm.type === "pcb_cutout") {
|
|
6171
6237
|
const cutout = circuitJsonElm;
|
|
6172
6238
|
if (cutout.shape === "rect") {
|
|
6173
|
-
updateBounds(
|
|
6239
|
+
updateBounds({
|
|
6240
|
+
center: cutout.center,
|
|
6241
|
+
width: cutout.width,
|
|
6242
|
+
height: cutout.height
|
|
6243
|
+
});
|
|
6174
6244
|
} else if (cutout.shape === "circle") {
|
|
6175
6245
|
const radius = distance2.parse(cutout.radius);
|
|
6176
6246
|
if (radius !== void 0) {
|
|
6177
|
-
updateBounds(
|
|
6247
|
+
updateBounds({
|
|
6248
|
+
center: cutout.center,
|
|
6249
|
+
width: radius * 2,
|
|
6250
|
+
height: radius * 2
|
|
6251
|
+
});
|
|
6178
6252
|
}
|
|
6179
6253
|
} else if (cutout.shape === "polygon") {
|
|
6180
6254
|
updateTraceBounds(cutout.points);
|
|
@@ -6187,34 +6261,262 @@ function convertCircuitJsonToPcbSvg(circuitJson, options) {
|
|
|
6187
6261
|
} else if (circuitJsonElm.type === "pcb_keepout") {
|
|
6188
6262
|
const keepout = circuitJsonElm;
|
|
6189
6263
|
if (keepout.shape === "rect") {
|
|
6190
|
-
updateBounds(
|
|
6264
|
+
updateBounds({
|
|
6265
|
+
center: keepout.center,
|
|
6266
|
+
width: keepout.width,
|
|
6267
|
+
height: keepout.height
|
|
6268
|
+
});
|
|
6191
6269
|
} else if (keepout.shape === "circle") {
|
|
6192
6270
|
const radius = typeof keepout.radius === "number" ? keepout.radius : distance2.parse(keepout.radius) ?? 0;
|
|
6193
6271
|
if (radius > 0) {
|
|
6194
|
-
updateBounds(
|
|
6272
|
+
updateBounds({
|
|
6273
|
+
center: keepout.center,
|
|
6274
|
+
width: radius * 2,
|
|
6275
|
+
height: radius * 2
|
|
6276
|
+
});
|
|
6195
6277
|
}
|
|
6196
6278
|
}
|
|
6197
6279
|
} else if (circuitJsonElm.type === "pcb_silkscreen_text" || circuitJsonElm.type === "pcb_silkscreen_rect" || circuitJsonElm.type === "pcb_silkscreen_circle" || circuitJsonElm.type === "pcb_silkscreen_line" || circuitJsonElm.type === "pcb_silkscreen_oval") {
|
|
6198
6280
|
updateSilkscreenBounds(circuitJsonElm);
|
|
6199
6281
|
} else if (circuitJsonElm.type === "pcb_copper_text") {
|
|
6200
|
-
updateBounds(
|
|
6282
|
+
updateBounds({
|
|
6283
|
+
center: circuitJsonElm.anchor_position,
|
|
6284
|
+
width: 0,
|
|
6285
|
+
height: 0
|
|
6286
|
+
});
|
|
6201
6287
|
} else if (circuitJsonElm.type === "pcb_copper_pour") {
|
|
6202
6288
|
if (circuitJsonElm.shape === "rect") {
|
|
6203
|
-
updateBounds(
|
|
6204
|
-
circuitJsonElm.center,
|
|
6205
|
-
circuitJsonElm.width,
|
|
6206
|
-
circuitJsonElm.height
|
|
6207
|
-
);
|
|
6289
|
+
updateBounds({
|
|
6290
|
+
center: circuitJsonElm.center,
|
|
6291
|
+
width: circuitJsonElm.width,
|
|
6292
|
+
height: circuitJsonElm.height
|
|
6293
|
+
});
|
|
6208
6294
|
} else if (circuitJsonElm.shape === "polygon") {
|
|
6209
6295
|
updateTraceBounds(circuitJsonElm.points);
|
|
6210
6296
|
}
|
|
6211
6297
|
}
|
|
6212
6298
|
}
|
|
6299
|
+
return {
|
|
6300
|
+
minX,
|
|
6301
|
+
minY,
|
|
6302
|
+
maxX,
|
|
6303
|
+
maxY,
|
|
6304
|
+
boardMinX,
|
|
6305
|
+
boardMinY,
|
|
6306
|
+
boardMaxX,
|
|
6307
|
+
boardMaxY,
|
|
6308
|
+
hasBounds,
|
|
6309
|
+
hasBoardBounds
|
|
6310
|
+
};
|
|
6311
|
+
function updateBounds({
|
|
6312
|
+
center,
|
|
6313
|
+
width,
|
|
6314
|
+
height
|
|
6315
|
+
}) {
|
|
6316
|
+
if (!center) return;
|
|
6317
|
+
const centerX = distance2.parse(center.x);
|
|
6318
|
+
const centerY = distance2.parse(center.y);
|
|
6319
|
+
if (centerX === void 0 || centerY === void 0) return;
|
|
6320
|
+
const numericWidth = distance2.parse(width) ?? 0;
|
|
6321
|
+
const numericHeight = distance2.parse(height) ?? 0;
|
|
6322
|
+
const halfWidth = numericWidth / 2;
|
|
6323
|
+
const halfHeight = numericHeight / 2;
|
|
6324
|
+
minX = Math.min(minX, centerX - halfWidth);
|
|
6325
|
+
minY = Math.min(minY, centerY - halfHeight);
|
|
6326
|
+
maxX = Math.max(maxX, centerX + halfWidth);
|
|
6327
|
+
maxY = Math.max(maxY, centerY + halfHeight);
|
|
6328
|
+
hasBounds = true;
|
|
6329
|
+
}
|
|
6330
|
+
function updateBoardBounds({
|
|
6331
|
+
center,
|
|
6332
|
+
width,
|
|
6333
|
+
height
|
|
6334
|
+
}) {
|
|
6335
|
+
if (!center) return;
|
|
6336
|
+
const centerX = distance2.parse(center.x);
|
|
6337
|
+
const centerY = distance2.parse(center.y);
|
|
6338
|
+
if (centerX === void 0 || centerY === void 0) return;
|
|
6339
|
+
const numericWidth = distance2.parse(width) ?? 0;
|
|
6340
|
+
const numericHeight = distance2.parse(height) ?? 0;
|
|
6341
|
+
const halfWidth = numericWidth / 2;
|
|
6342
|
+
const halfHeight = numericHeight / 2;
|
|
6343
|
+
boardMinX = Math.min(boardMinX, centerX - halfWidth);
|
|
6344
|
+
boardMinY = Math.min(boardMinY, centerY - halfHeight);
|
|
6345
|
+
boardMaxX = Math.max(boardMaxX, centerX + halfWidth);
|
|
6346
|
+
boardMaxY = Math.max(boardMaxY, centerY + halfHeight);
|
|
6347
|
+
hasBounds = true;
|
|
6348
|
+
hasBoardBounds = true;
|
|
6349
|
+
}
|
|
6350
|
+
function updateBoundsToIncludeOutline(outline) {
|
|
6351
|
+
let updated = false;
|
|
6352
|
+
for (const point of outline) {
|
|
6353
|
+
const x = distance2.parse(point.x);
|
|
6354
|
+
const y = distance2.parse(point.y);
|
|
6355
|
+
if (x === void 0 || y === void 0) continue;
|
|
6356
|
+
minX = Math.min(minX, x);
|
|
6357
|
+
minY = Math.min(minY, y);
|
|
6358
|
+
maxX = Math.max(maxX, x);
|
|
6359
|
+
maxY = Math.max(maxY, y);
|
|
6360
|
+
updated = true;
|
|
6361
|
+
}
|
|
6362
|
+
if (updated) {
|
|
6363
|
+
hasBounds = true;
|
|
6364
|
+
}
|
|
6365
|
+
}
|
|
6366
|
+
function updateBoardBoundsToIncludeOutline(outline) {
|
|
6367
|
+
let updated = false;
|
|
6368
|
+
for (const point of outline) {
|
|
6369
|
+
const x = distance2.parse(point.x);
|
|
6370
|
+
const y = distance2.parse(point.y);
|
|
6371
|
+
if (x === void 0 || y === void 0) continue;
|
|
6372
|
+
boardMinX = Math.min(boardMinX, x);
|
|
6373
|
+
boardMinY = Math.min(boardMinY, y);
|
|
6374
|
+
boardMaxX = Math.max(boardMaxX, x);
|
|
6375
|
+
boardMaxY = Math.max(boardMaxY, y);
|
|
6376
|
+
updated = true;
|
|
6377
|
+
}
|
|
6378
|
+
if (updated) {
|
|
6379
|
+
hasBounds = true;
|
|
6380
|
+
hasBoardBounds = true;
|
|
6381
|
+
}
|
|
6382
|
+
}
|
|
6383
|
+
function updateTraceBounds(route) {
|
|
6384
|
+
let updated = false;
|
|
6385
|
+
for (const point of route) {
|
|
6386
|
+
const x = distance2.parse(point?.x);
|
|
6387
|
+
const y = distance2.parse(point?.y);
|
|
6388
|
+
if (x === void 0 || y === void 0) continue;
|
|
6389
|
+
minX = Math.min(minX, x);
|
|
6390
|
+
minY = Math.min(minY, y);
|
|
6391
|
+
maxX = Math.max(maxX, x);
|
|
6392
|
+
maxY = Math.max(maxY, y);
|
|
6393
|
+
updated = true;
|
|
6394
|
+
}
|
|
6395
|
+
if (updated) {
|
|
6396
|
+
hasBounds = true;
|
|
6397
|
+
}
|
|
6398
|
+
}
|
|
6399
|
+
function updateSilkscreenBounds(item) {
|
|
6400
|
+
if (item.type === "pcb_silkscreen_text") {
|
|
6401
|
+
updateBounds({ center: item.anchor_position, width: 0, height: 0 });
|
|
6402
|
+
} else if (item.type === "pcb_silkscreen_path") {
|
|
6403
|
+
updateTraceBounds(item.route);
|
|
6404
|
+
} else if (item.type === "pcb_silkscreen_rect") {
|
|
6405
|
+
updateBounds({
|
|
6406
|
+
center: item.center,
|
|
6407
|
+
width: item.width,
|
|
6408
|
+
height: item.height
|
|
6409
|
+
});
|
|
6410
|
+
} else if (item.type === "pcb_silkscreen_circle") {
|
|
6411
|
+
const radius = distance2.parse(item.radius);
|
|
6412
|
+
if (radius !== void 0) {
|
|
6413
|
+
updateBounds({
|
|
6414
|
+
center: item.center,
|
|
6415
|
+
width: radius * 2,
|
|
6416
|
+
height: radius * 2
|
|
6417
|
+
});
|
|
6418
|
+
}
|
|
6419
|
+
} else if (item.type === "pcb_silkscreen_line") {
|
|
6420
|
+
updateBounds({ center: { x: item.x1, y: item.y1 }, width: 0, height: 0 });
|
|
6421
|
+
updateBounds({ center: { x: item.x2, y: item.y2 }, width: 0, height: 0 });
|
|
6422
|
+
} else if (item.type === "pcb_silkscreen_oval") {
|
|
6423
|
+
const radiusX = distance2.parse(item.radius_x);
|
|
6424
|
+
const radiusY = distance2.parse(item.radius_y);
|
|
6425
|
+
if (radiusX !== void 0 && radiusY !== void 0) {
|
|
6426
|
+
updateBounds({
|
|
6427
|
+
center: item.center,
|
|
6428
|
+
width: radiusX * 2,
|
|
6429
|
+
height: radiusY * 2
|
|
6430
|
+
});
|
|
6431
|
+
}
|
|
6432
|
+
} else if (item.type === "pcb_cutout") {
|
|
6433
|
+
const cutout = item;
|
|
6434
|
+
if (cutout.shape === "rect") {
|
|
6435
|
+
updateBounds({
|
|
6436
|
+
center: cutout.center,
|
|
6437
|
+
width: cutout.width,
|
|
6438
|
+
height: cutout.height
|
|
6439
|
+
});
|
|
6440
|
+
} else if (cutout.shape === "circle") {
|
|
6441
|
+
const radius = distance2.parse(cutout.radius);
|
|
6442
|
+
if (radius !== void 0) {
|
|
6443
|
+
updateBounds({
|
|
6444
|
+
center: cutout.center,
|
|
6445
|
+
width: radius * 2,
|
|
6446
|
+
height: radius * 2
|
|
6447
|
+
});
|
|
6448
|
+
}
|
|
6449
|
+
} else if (cutout.shape === "polygon") {
|
|
6450
|
+
updateTraceBounds(cutout.points);
|
|
6451
|
+
} else if (cutout.shape === "path") {
|
|
6452
|
+
const cutoutPath = cutout;
|
|
6453
|
+
if (cutoutPath.route && Array.isArray(cutoutPath.route)) {
|
|
6454
|
+
updateTraceBounds(cutoutPath.route);
|
|
6455
|
+
}
|
|
6456
|
+
}
|
|
6457
|
+
}
|
|
6458
|
+
}
|
|
6459
|
+
}
|
|
6460
|
+
|
|
6461
|
+
// lib/pcb/convert-circuit-json-to-pcb-svg.ts
|
|
6462
|
+
function convertCircuitJsonToPcbSvg(circuitJson, options) {
|
|
6463
|
+
const drawPaddingOutsideBoard = options?.drawPaddingOutsideBoard ?? true;
|
|
6464
|
+
const layer = options?.layer;
|
|
6465
|
+
const colorOverrides = options?.colorOverrides;
|
|
6466
|
+
const copperColors = {
|
|
6467
|
+
...DEFAULT_PCB_COLOR_MAP.copper
|
|
6468
|
+
};
|
|
6469
|
+
if (colorOverrides?.copper) {
|
|
6470
|
+
for (const [layerName, color] of Object.entries(colorOverrides.copper)) {
|
|
6471
|
+
if (color !== void 0) {
|
|
6472
|
+
copperColors[layerName] = color;
|
|
6473
|
+
}
|
|
6474
|
+
}
|
|
6475
|
+
}
|
|
6476
|
+
const colorMap2 = {
|
|
6477
|
+
copper: copperColors,
|
|
6478
|
+
drill: colorOverrides?.drill ?? DEFAULT_PCB_COLOR_MAP.drill,
|
|
6479
|
+
silkscreen: {
|
|
6480
|
+
top: colorOverrides?.silkscreen?.top ?? DEFAULT_PCB_COLOR_MAP.silkscreen.top,
|
|
6481
|
+
bottom: colorOverrides?.silkscreen?.bottom ?? DEFAULT_PCB_COLOR_MAP.silkscreen.bottom
|
|
6482
|
+
},
|
|
6483
|
+
boardOutline: colorOverrides?.boardOutline ?? DEFAULT_PCB_COLOR_MAP.boardOutline,
|
|
6484
|
+
soldermask: {
|
|
6485
|
+
top: colorOverrides?.soldermask?.top ?? DEFAULT_PCB_COLOR_MAP.soldermask.top,
|
|
6486
|
+
bottom: colorOverrides?.soldermask?.bottom ?? DEFAULT_PCB_COLOR_MAP.soldermask.bottom
|
|
6487
|
+
},
|
|
6488
|
+
soldermaskOverCopper: {
|
|
6489
|
+
top: colorOverrides?.soldermaskOverCopper?.top ?? DEFAULT_PCB_COLOR_MAP.soldermaskOverCopper.top,
|
|
6490
|
+
bottom: colorOverrides?.soldermaskOverCopper?.bottom ?? DEFAULT_PCB_COLOR_MAP.soldermaskOverCopper.bottom
|
|
6491
|
+
},
|
|
6492
|
+
soldermaskWithCopperUnderneath: {
|
|
6493
|
+
top: colorOverrides?.soldermaskWithCopperUnderneath?.top ?? DEFAULT_PCB_COLOR_MAP.soldermaskWithCopperUnderneath.top,
|
|
6494
|
+
bottom: colorOverrides?.soldermaskWithCopperUnderneath?.bottom ?? DEFAULT_PCB_COLOR_MAP.soldermaskWithCopperUnderneath.bottom
|
|
6495
|
+
},
|
|
6496
|
+
substrate: colorOverrides?.substrate ?? DEFAULT_PCB_COLOR_MAP.substrate,
|
|
6497
|
+
courtyard: colorOverrides?.courtyard ?? DEFAULT_PCB_COLOR_MAP.courtyard,
|
|
6498
|
+
keepout: colorOverrides?.keepout ?? DEFAULT_PCB_COLOR_MAP.keepout,
|
|
6499
|
+
debugComponent: {
|
|
6500
|
+
fill: colorOverrides?.debugComponent?.fill ?? DEFAULT_PCB_COLOR_MAP.debugComponent.fill,
|
|
6501
|
+
stroke: colorOverrides?.debugComponent?.stroke ?? DEFAULT_PCB_COLOR_MAP.debugComponent.stroke
|
|
6502
|
+
}
|
|
6503
|
+
};
|
|
6504
|
+
const {
|
|
6505
|
+
minX,
|
|
6506
|
+
minY,
|
|
6507
|
+
maxX,
|
|
6508
|
+
maxY,
|
|
6509
|
+
boardMinX,
|
|
6510
|
+
boardMinY,
|
|
6511
|
+
boardMaxX,
|
|
6512
|
+
boardMaxY,
|
|
6513
|
+
hasBoardBounds
|
|
6514
|
+
} = getPcbBoundsFromCircuitJson(circuitJson);
|
|
6213
6515
|
const padding = drawPaddingOutsideBoard ? 1 : 0;
|
|
6214
|
-
const boundsMinX = drawPaddingOutsideBoard || !
|
|
6215
|
-
const boundsMinY = drawPaddingOutsideBoard || !
|
|
6216
|
-
const boundsMaxX = drawPaddingOutsideBoard || !
|
|
6217
|
-
const boundsMaxY = drawPaddingOutsideBoard || !
|
|
6516
|
+
const boundsMinX = drawPaddingOutsideBoard || !hasBoardBounds ? minX : boardMinX;
|
|
6517
|
+
const boundsMinY = drawPaddingOutsideBoard || !hasBoardBounds ? minY : boardMinY;
|
|
6518
|
+
const boundsMaxX = drawPaddingOutsideBoard || !hasBoardBounds ? maxX : boardMaxX;
|
|
6519
|
+
const boundsMaxY = drawPaddingOutsideBoard || !hasBoardBounds ? maxY : boardMaxY;
|
|
6218
6520
|
const circuitWidth = boundsMaxX - boundsMinX + 2 * padding;
|
|
6219
6521
|
const circuitHeight = boundsMaxY - boundsMinY + 2 * padding;
|
|
6220
6522
|
let svgWidth = options?.width ?? 800;
|
|
@@ -6363,126 +6665,6 @@ function convertCircuitJsonToPcbSvg(circuitJson, options) {
|
|
|
6363
6665
|
console.error("Error stringifying SVG object:", error);
|
|
6364
6666
|
throw error;
|
|
6365
6667
|
}
|
|
6366
|
-
function updateBounds(center, width, height) {
|
|
6367
|
-
if (!center) return;
|
|
6368
|
-
const centerX = distance2.parse(center.x);
|
|
6369
|
-
const centerY = distance2.parse(center.y);
|
|
6370
|
-
if (centerX === void 0 || centerY === void 0) return;
|
|
6371
|
-
const numericWidth = distance2.parse(width) ?? 0;
|
|
6372
|
-
const numericHeight = distance2.parse(height) ?? 0;
|
|
6373
|
-
const halfWidth = numericWidth / 2;
|
|
6374
|
-
const halfHeight = numericHeight / 2;
|
|
6375
|
-
minX = Math.min(minX, centerX - halfWidth);
|
|
6376
|
-
minY = Math.min(minY, centerY - halfHeight);
|
|
6377
|
-
maxX = Math.max(maxX, centerX + halfWidth);
|
|
6378
|
-
maxY = Math.max(maxY, centerY + halfHeight);
|
|
6379
|
-
hasBounds = true;
|
|
6380
|
-
}
|
|
6381
|
-
function updateBoardBounds(center, width, height) {
|
|
6382
|
-
if (!center) return;
|
|
6383
|
-
const centerX = distance2.parse(center.x);
|
|
6384
|
-
const centerY = distance2.parse(center.y);
|
|
6385
|
-
if (centerX === void 0 || centerY === void 0) return;
|
|
6386
|
-
const numericWidth = distance2.parse(width) ?? 0;
|
|
6387
|
-
const numericHeight = distance2.parse(height) ?? 0;
|
|
6388
|
-
const halfWidth = numericWidth / 2;
|
|
6389
|
-
const halfHeight = numericHeight / 2;
|
|
6390
|
-
boardMinX = Math.min(boardMinX, centerX - halfWidth);
|
|
6391
|
-
boardMinY = Math.min(boardMinY, centerY - halfHeight);
|
|
6392
|
-
boardMaxX = Math.max(boardMaxX, centerX + halfWidth);
|
|
6393
|
-
boardMaxY = Math.max(boardMaxY, centerY + halfHeight);
|
|
6394
|
-
hasBounds = true;
|
|
6395
|
-
hasBoardBounds = true;
|
|
6396
|
-
}
|
|
6397
|
-
function updateBoundsToIncludeOutline(outline) {
|
|
6398
|
-
let updated = false;
|
|
6399
|
-
for (const point of outline) {
|
|
6400
|
-
const x = distance2.parse(point.x);
|
|
6401
|
-
const y = distance2.parse(point.y);
|
|
6402
|
-
if (x === void 0 || y === void 0) continue;
|
|
6403
|
-
minX = Math.min(minX, x);
|
|
6404
|
-
minY = Math.min(minY, y);
|
|
6405
|
-
maxX = Math.max(maxX, x);
|
|
6406
|
-
maxY = Math.max(maxY, y);
|
|
6407
|
-
updated = true;
|
|
6408
|
-
}
|
|
6409
|
-
if (updated) {
|
|
6410
|
-
hasBounds = true;
|
|
6411
|
-
}
|
|
6412
|
-
}
|
|
6413
|
-
function updateBoardBoundsToIncludeOutline(outline) {
|
|
6414
|
-
let updated = false;
|
|
6415
|
-
for (const point of outline) {
|
|
6416
|
-
const x = distance2.parse(point.x);
|
|
6417
|
-
const y = distance2.parse(point.y);
|
|
6418
|
-
if (x === void 0 || y === void 0) continue;
|
|
6419
|
-
boardMinX = Math.min(boardMinX, x);
|
|
6420
|
-
boardMinY = Math.min(boardMinY, y);
|
|
6421
|
-
boardMaxX = Math.max(boardMaxX, x);
|
|
6422
|
-
boardMaxY = Math.max(boardMaxY, y);
|
|
6423
|
-
updated = true;
|
|
6424
|
-
}
|
|
6425
|
-
if (updated) {
|
|
6426
|
-
hasBounds = true;
|
|
6427
|
-
hasBoardBounds = true;
|
|
6428
|
-
}
|
|
6429
|
-
}
|
|
6430
|
-
function updateTraceBounds(route) {
|
|
6431
|
-
let updated = false;
|
|
6432
|
-
for (const point of route) {
|
|
6433
|
-
const x = distance2.parse(point?.x);
|
|
6434
|
-
const y = distance2.parse(point?.y);
|
|
6435
|
-
if (x === void 0 || y === void 0) continue;
|
|
6436
|
-
minX = Math.min(minX, x);
|
|
6437
|
-
minY = Math.min(minY, y);
|
|
6438
|
-
maxX = Math.max(maxX, x);
|
|
6439
|
-
maxY = Math.max(maxY, y);
|
|
6440
|
-
updated = true;
|
|
6441
|
-
}
|
|
6442
|
-
if (updated) {
|
|
6443
|
-
hasBounds = true;
|
|
6444
|
-
}
|
|
6445
|
-
}
|
|
6446
|
-
function updateSilkscreenBounds(item) {
|
|
6447
|
-
if (item.type === "pcb_silkscreen_text") {
|
|
6448
|
-
updateBounds(item.anchor_position, 0, 0);
|
|
6449
|
-
} else if (item.type === "pcb_silkscreen_path") {
|
|
6450
|
-
updateTraceBounds(item.route);
|
|
6451
|
-
} else if (item.type === "pcb_silkscreen_rect") {
|
|
6452
|
-
updateBounds(item.center, item.width, item.height);
|
|
6453
|
-
} else if (item.type === "pcb_silkscreen_circle") {
|
|
6454
|
-
const radius = distance2.parse(item.radius);
|
|
6455
|
-
if (radius !== void 0) {
|
|
6456
|
-
updateBounds(item.center, radius * 2, radius * 2);
|
|
6457
|
-
}
|
|
6458
|
-
} else if (item.type === "pcb_silkscreen_line") {
|
|
6459
|
-
updateBounds({ x: item.x1, y: item.y1 }, 0, 0);
|
|
6460
|
-
updateBounds({ x: item.x2, y: item.y2 }, 0, 0);
|
|
6461
|
-
} else if (item.type === "pcb_silkscreen_oval") {
|
|
6462
|
-
const radiusX = distance2.parse(item.radius_x);
|
|
6463
|
-
const radiusY = distance2.parse(item.radius_y);
|
|
6464
|
-
if (radiusX !== void 0 && radiusY !== void 0) {
|
|
6465
|
-
updateBounds(item.center, radiusX * 2, radiusY * 2);
|
|
6466
|
-
}
|
|
6467
|
-
} else if (item.type === "pcb_cutout") {
|
|
6468
|
-
const cutout = item;
|
|
6469
|
-
if (cutout.shape === "rect") {
|
|
6470
|
-
updateBounds(cutout.center, cutout.width, cutout.height);
|
|
6471
|
-
} else if (cutout.shape === "circle") {
|
|
6472
|
-
const radius = distance2.parse(cutout.radius);
|
|
6473
|
-
if (radius !== void 0) {
|
|
6474
|
-
updateBounds(cutout.center, radius * 2, radius * 2);
|
|
6475
|
-
}
|
|
6476
|
-
} else if (cutout.shape === "polygon") {
|
|
6477
|
-
updateTraceBounds(cutout.points);
|
|
6478
|
-
} else if (cutout.shape === "path") {
|
|
6479
|
-
const cutoutPath = cutout;
|
|
6480
|
-
if (cutoutPath.route && Array.isArray(cutoutPath.route)) {
|
|
6481
|
-
updateTraceBounds(cutoutPath.route);
|
|
6482
|
-
}
|
|
6483
|
-
}
|
|
6484
|
-
}
|
|
6485
|
-
}
|
|
6486
6668
|
}
|
|
6487
6669
|
function createSvgObjects({
|
|
6488
6670
|
elm,
|
|
@@ -13278,7 +13460,7 @@ function formatNumber2(value) {
|
|
|
13278
13460
|
}
|
|
13279
13461
|
|
|
13280
13462
|
// lib/pcb/convert-circuit-json-to-solder-paste-mask.ts
|
|
13281
|
-
import { distance as
|
|
13463
|
+
import { distance as distance4 } from "circuit-json";
|
|
13282
13464
|
import { stringify as stringify7 } from "svgson";
|
|
13283
13465
|
import {
|
|
13284
13466
|
applyToPoint as applyToPoint76,
|
|
@@ -13396,8 +13578,8 @@ function convertCircuitJsonToSolderPasteMask(circuitJson, options) {
|
|
|
13396
13578
|
}
|
|
13397
13579
|
} else if (item.type === "pcb_panel") {
|
|
13398
13580
|
const panel = item;
|
|
13399
|
-
const width =
|
|
13400
|
-
const height =
|
|
13581
|
+
const width = distance4.parse(panel.width);
|
|
13582
|
+
const height = distance4.parse(panel.height);
|
|
13401
13583
|
if (width !== void 0 && height !== void 0) {
|
|
13402
13584
|
const center = panel.center ?? { x: width / 2, y: height / 2 };
|
|
13403
13585
|
updateBounds(center, width, height);
|