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 CHANGED
@@ -1,5 +1,5 @@
1
1
  // lib/pcb/convert-circuit-json-to-pcb-svg.ts
2
- import { distance as distance2 } from "circuit-json";
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 distance4 = Math.sqrt(dx * dx + dy * dy);
3838
- if (distance4 === 0) return [px, py];
3839
- const normalizedDx = dx / distance4;
3840
- const normalizedDy = dy / distance4;
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 distance4 = Math.hypot(dx, dy);
4046
+ const distance5 = Math.hypot(dx, dy);
4047
4047
  const totalTrim = CONNECTOR_GROUP_GAP_PX + CONNECTOR_COMPONENT_GAP_PX;
4048
- if (!(distance4 > totalTrim)) return { x1, y1, x2, y2 };
4049
- const ux = dx / distance4;
4050
- const uy = dy / distance4;
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 distance4 = Math.sqrt(dx * dx + dy * dy);
5008
- if (distance4 > 0 && distance4 < minDistance) {
5009
- minDistance = distance4;
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.304",
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/convert-circuit-json-to-pcb-svg.ts
6070
- function convertCircuitJsonToPcbSvg(circuitJson, options) {
6071
- const drawPaddingOutsideBoard = options?.drawPaddingOutsideBoard ?? true;
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({ x: pad.x, y: pad.y }, pad.width, pad.height);
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({ x: pad.x, y: pad.y }, radius * 2, radius * 2);
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({ x: circuitJsonElm.x, y: circuitJsonElm.y }, 0, 0);
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(cutout.center, cutout.width, cutout.height);
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(cutout.center, radius * 2, radius * 2);
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(keepout.center, keepout.width, keepout.height);
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(keepout.center, radius * 2, radius * 2);
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(circuitJsonElm.anchor_position, 0, 0);
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 || !Number.isFinite(boardMinX) ? minX : boardMinX;
6215
- const boundsMinY = drawPaddingOutsideBoard || !Number.isFinite(boardMinY) ? minY : boardMinY;
6216
- const boundsMaxX = drawPaddingOutsideBoard || !Number.isFinite(boardMaxX) ? maxX : boardMaxX;
6217
- const boundsMaxY = drawPaddingOutsideBoard || !Number.isFinite(boardMaxY) ? maxY : boardMaxY;
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 distance3 } from "circuit-json";
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 = distance3.parse(panel.width);
13400
- const height = distance3.parse(panel.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);