@tscircuit/cli 0.1.1493 → 0.1.1494

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/cli/main.js CHANGED
@@ -100763,7 +100763,7 @@ var import_perfect_cli = __toESM2(require_dist2(), 1);
100763
100763
  // lib/getVersion.ts
100764
100764
  import { createRequire as createRequire2 } from "node:module";
100765
100765
  // package.json
100766
- var version = "0.1.1492";
100766
+ var version = "0.1.1493";
100767
100767
  var package_default = {
100768
100768
  name: "@tscircuit/cli",
100769
100769
  version,
@@ -100814,7 +100814,7 @@ var package_default = {
100814
100814
  cosmiconfig: "^9.0.0",
100815
100815
  debug: "^4.4.0",
100816
100816
  delay: "^6.0.0",
100817
- "dsn-converter": "^0.0.88",
100817
+ "dsn-converter": "^0.0.90",
100818
100818
  easyeda: "^0.0.269",
100819
100819
  "fuse.js": "^7.1.0",
100820
100820
  "get-port": "^7.1.0",
@@ -252869,6 +252869,7 @@ import {
252869
252869
 
252870
252870
  // node_modules/dsn-converter/dist/index.js
252871
252871
  import { su as su13 } from "@tscircuit/soup-util";
252872
+ import { getBoundsFromPoints as getBoundsFromPoints3 } from "@tscircuit/math-utils";
252872
252873
  import { applyToPoint as applyToPoint25, scale as scale7 } from "transformation-matrix";
252873
252874
  import { su as su24 } from "@tscircuit/soup-util";
252874
252875
  import { su as su34 } from "@tscircuit/soup-util";
@@ -252995,6 +252996,24 @@ function createRectangularPadstack(name, width, height, layer) {
252995
252996
  attach: "off"
252996
252997
  };
252997
252998
  }
252999
+ function createPolygonPadstack({
253000
+ name,
253001
+ coordinates,
253002
+ layer
253003
+ }) {
253004
+ return {
253005
+ name,
253006
+ shapes: [
253007
+ {
253008
+ shapeType: "polygon",
253009
+ layer: layer === "bottom" ? "B.Cu" : "F.Cu",
253010
+ width: 0,
253011
+ coordinates
253012
+ }
253013
+ ],
253014
+ attach: "off"
253015
+ };
253016
+ }
252998
253017
  function createCircularHoleRectangularPadstack(name, outerWidth, outerHeight, holeDiameter, numLayers = 2) {
252999
253018
  const halfWidth = outerWidth / 2;
253000
253019
  const halfHeight = outerHeight / 2;
@@ -253025,13 +253044,21 @@ function createCircularHoleRectangularPadstack(name, outerWidth, outerHeight, ho
253025
253044
  attach: "off"
253026
253045
  };
253027
253046
  }
253047
+ var padstackNamePrefixes = {
253048
+ circle: "Round[",
253049
+ oval: "Oval[",
253050
+ pill: "Oval[",
253051
+ rect: "RoundRect[",
253052
+ polygon: "Cust["
253053
+ };
253028
253054
  function getPadstackName({
253029
253055
  shape,
253030
253056
  width,
253031
253057
  height,
253032
253058
  holeDiameter,
253033
253059
  outerDiameter,
253034
- layer = "top"
253060
+ layer = "top",
253061
+ customDescriptor
253035
253062
  }) {
253036
253063
  const layerCode = {
253037
253064
  top: "T",
@@ -253040,52 +253067,182 @@ function getPadstackName({
253040
253067
  }[layer] ?? "T";
253041
253068
  switch (shape) {
253042
253069
  case "circle":
253043
- return `Round[${layerCode}]Pad_${holeDiameter}_${outerDiameter}_um`;
253070
+ return `${padstackNamePrefixes.circle}${layerCode}]Pad_${holeDiameter}_${outerDiameter}_um`;
253044
253071
  case "oval":
253045
- return `Oval[${layerCode}]Pad_${width}x${height}_um`;
253072
+ return `${padstackNamePrefixes.oval}${layerCode}]Pad_${width}x${height}_um`;
253046
253073
  case "pill":
253047
- return `Oval[${layerCode}]Pad_${width}x${height}_um`;
253074
+ return `${padstackNamePrefixes.pill}${layerCode}]Pad_${width}x${height}_um`;
253048
253075
  case "rect":
253049
- return `RoundRect[${layerCode}]Pad_${width}x${height}_um`;
253076
+ return `${padstackNamePrefixes.rect}${layerCode}]Pad_${width}x${height}_um`;
253077
+ case "polygon":
253078
+ return `${padstackNamePrefixes.polygon}${layerCode}]Pad_${customDescriptor ?? `${width}x${height}`}_um`;
253050
253079
  default:
253051
253080
  return "default_pad";
253052
253081
  }
253053
253082
  }
253054
- function createAndAddPadstackFromPcbSmtPad(pcb, pad2, processedPadstacks) {
253083
+ function roundMicrons(microns) {
253084
+ return Number(microns.toFixed(3));
253085
+ }
253086
+ function getNormalizedPoints(points) {
253087
+ if (points.length < 2)
253088
+ return points;
253089
+ const firstPoint = points[0];
253090
+ const lastPoint = points[points.length - 1];
253091
+ if (firstPoint.x === lastPoint.x && firstPoint.y === lastPoint.y) {
253092
+ return points.slice(0, -1);
253093
+ }
253094
+ return points;
253095
+ }
253096
+ function getPolygonCentroid2(points) {
253097
+ let signedArea3 = 0;
253098
+ let centroidX = 0;
253099
+ let centroidY = 0;
253100
+ for (let index = 0;index < points.length; index++) {
253101
+ const currentPoint = points[index];
253102
+ const nextPoint = points[(index + 1) % points.length];
253103
+ const crossProduct = currentPoint.x * nextPoint.y - nextPoint.x * currentPoint.y;
253104
+ signedArea3 += crossProduct;
253105
+ centroidX += (currentPoint.x + nextPoint.x) * crossProduct;
253106
+ centroidY += (currentPoint.y + nextPoint.y) * crossProduct;
253107
+ }
253108
+ if (signedArea3 === 0)
253109
+ return null;
253110
+ const areaFactor = signedArea3 * 3;
253111
+ return {
253112
+ x: centroidX / areaFactor,
253113
+ y: centroidY / areaFactor
253114
+ };
253115
+ }
253116
+ function getPolygonSmtPadGeometry(pad2) {
253117
+ const points = getNormalizedPoints(pad2.points);
253118
+ const bounds = getBoundsFromPoints3(points);
253119
+ if (!bounds) {
253120
+ return {
253121
+ center: { x: 0, y: 0 },
253122
+ widthUm: 0,
253123
+ heightUm: 0,
253124
+ relativePointsUm: []
253125
+ };
253126
+ }
253127
+ const { minX, maxX, minY, maxY } = bounds;
253128
+ const polygonCentroid = getPolygonCentroid2(points);
253129
+ const center2 = polygonCentroid ?? {
253130
+ x: (minX + maxX) / 2,
253131
+ y: (minY + maxY) / 2
253132
+ };
253133
+ const relativePointsUm = points.flatMap((point5) => [
253134
+ roundMicrons((point5.x - center2.x) * 1000),
253135
+ roundMicrons((point5.y - center2.y) * 1000)
253136
+ ]);
253137
+ if (points.length > 0) {
253138
+ relativePointsUm.push(relativePointsUm[0], relativePointsUm[1]);
253139
+ }
253140
+ return {
253141
+ center: center2,
253142
+ widthUm: roundMicrons((maxX - minX) * 1000),
253143
+ heightUm: roundMicrons((maxY - minY) * 1000),
253144
+ relativePointsUm
253145
+ };
253146
+ }
253147
+ function createAndAddPadstackFromPcbSmtPad({
253148
+ pcb,
253149
+ pad: pad2,
253150
+ processedPadstacks
253151
+ }) {
253055
253152
  const isCircle = pad2.shape === "circle";
253153
+ const isPolygon = pad2.shape === "polygon";
253154
+ const polygonPadGeometry = isPolygon ? getPolygonSmtPadGeometry(pad2) : undefined;
253155
+ let shape = "rect";
253156
+ let outerDiameter;
253157
+ let holeDiameter;
253158
+ let width;
253159
+ let height;
253160
+ let customDescriptor;
253161
+ if (isCircle) {
253162
+ shape = "circle";
253163
+ outerDiameter = pad2.radius * 1000 * 2;
253164
+ holeDiameter = pad2.radius * 1000 * 2;
253165
+ } else if (isPolygon) {
253166
+ shape = "polygon";
253167
+ width = polygonPadGeometry?.widthUm;
253168
+ height = polygonPadGeometry?.heightUm;
253169
+ customDescriptor = `${polygonPadGeometry?.widthUm}x${polygonPadGeometry?.heightUm}_${polygonPadGeometry?.relativePointsUm.join("_")}`;
253170
+ } else {
253171
+ width = pad2.width * 1000;
253172
+ height = pad2.height * 1000;
253173
+ }
253056
253174
  const padstackParams = {
253057
- shape: isCircle ? "circle" : "rect",
253058
- outerDiameter: isCircle ? pad2.radius * 1000 * 2 : undefined,
253059
- holeDiameter: isCircle ? pad2.radius * 1000 * 2 : undefined,
253060
- width: isCircle ? undefined : pad2.width * 1000,
253061
- height: isCircle ? undefined : pad2.height * 1000,
253062
- layer: pad2.layer
253175
+ shape,
253176
+ outerDiameter,
253177
+ holeDiameter,
253178
+ width,
253179
+ height,
253180
+ layer: pad2.layer,
253181
+ customDescriptor
253063
253182
  };
253064
253183
  const padstackName = getPadstackName(padstackParams);
253065
253184
  if (!processedPadstacks.has(padstackName)) {
253066
- const padstack = isCircle ? createCircularPadstack(padstackName, padstackParams.outerDiameter, padstackParams.holeDiameter) : createRectangularPadstack(padstackName, padstackParams.width, padstackParams.height, pad2.layer);
253185
+ let padstack;
253186
+ if (isCircle) {
253187
+ padstack = createCircularPadstack(padstackName, padstackParams.outerDiameter, padstackParams.holeDiameter);
253188
+ } else if (isPolygon) {
253189
+ padstack = createPolygonPadstack({
253190
+ name: padstackName,
253191
+ coordinates: polygonPadGeometry.relativePointsUm,
253192
+ layer: pad2.layer
253193
+ });
253194
+ } else {
253195
+ padstack = createRectangularPadstack(padstackName, padstackParams.width, padstackParams.height, pad2.layer);
253196
+ }
253067
253197
  pcb.library.padstacks.push(padstack);
253068
253198
  processedPadstacks.add(padstackName);
253069
253199
  }
253070
253200
  return padstackName;
253071
253201
  }
253072
- function createPinForImage(pad2, pcbComponent, sourcePort) {
253202
+ function createPinForImage({
253203
+ pad: pad2,
253204
+ pcbComponent,
253205
+ sourcePort
253206
+ }) {
253073
253207
  if (!sourcePort)
253074
253208
  return;
253075
253209
  const isCircle = pad2.shape === "circle";
253210
+ const isPolygon = pad2.shape === "polygon";
253211
+ const polygonPadGeometry = isPolygon ? getPolygonSmtPadGeometry(pad2) : undefined;
253212
+ let shape = "rect";
253213
+ let outerDiameter;
253214
+ let holeDiameter;
253215
+ let width;
253216
+ let height;
253217
+ let customDescriptor;
253218
+ if (isCircle) {
253219
+ shape = "circle";
253220
+ outerDiameter = pad2.radius * 1000 * 2;
253221
+ holeDiameter = pad2.radius * 1000 * 2;
253222
+ } else if (isPolygon) {
253223
+ shape = "polygon";
253224
+ width = polygonPadGeometry?.widthUm;
253225
+ height = polygonPadGeometry?.heightUm;
253226
+ customDescriptor = `${polygonPadGeometry?.widthUm}x${polygonPadGeometry?.heightUm}_${polygonPadGeometry?.relativePointsUm.join("_")}`;
253227
+ } else {
253228
+ width = pad2.width * 1000;
253229
+ height = pad2.height * 1000;
253230
+ }
253076
253231
  const padstackParams = {
253077
- shape: isCircle ? "circle" : "rect",
253078
- outerDiameter: isCircle ? pad2.radius * 1000 * 2 : undefined,
253079
- holeDiameter: isCircle ? pad2.radius * 1000 * 2 : undefined,
253080
- width: isCircle ? undefined : pad2.width * 1000,
253081
- height: isCircle ? undefined : pad2.height * 1000,
253082
- layer: pad2.layer
253232
+ shape,
253233
+ outerDiameter,
253234
+ holeDiameter,
253235
+ width,
253236
+ height,
253237
+ layer: pad2.layer,
253238
+ customDescriptor
253083
253239
  };
253240
+ const padCenter = isPolygon ? polygonPadGeometry.center : { x: pad2.x, y: pad2.y };
253084
253241
  return {
253085
253242
  padstack_name: getPadstackName(padstackParams),
253086
253243
  pin_number: sourcePort.port_hints?.find((hint) => !Number.isNaN(Number(hint))) || 1,
253087
- x: (pad2.x - pcbComponent.center.x) * 1000,
253088
- y: (pad2.y - pcbComponent.center.y) * 1000
253244
+ x: (padCenter.x - pcbComponent.center.x) * 1000,
253245
+ y: (padCenter.y - pcbComponent.center.y) * 1000
253089
253246
  };
253090
253247
  }
253091
253248
  function getComponentValue(sourceComponent) {
@@ -253145,7 +253302,11 @@ function processComponentsAndPads(componentGroups, circuitElements, pcb) {
253145
253302
  if (!componentGroup)
253146
253303
  continue;
253147
253304
  for (const pad2 of componentGroup.pcb_smtpads) {
253148
- createAndAddPadstackFromPcbSmtPad(pcb, pad2, processedPadstacks);
253305
+ createAndAddPadstackFromPcbSmtPad({
253306
+ pcb,
253307
+ pad: pad2,
253308
+ processedPadstacks
253309
+ });
253149
253310
  }
253150
253311
  const image = {
253151
253312
  name: footprintName,
@@ -253154,7 +253315,11 @@ function processComponentsAndPads(componentGroups, circuitElements, pcb) {
253154
253315
  const pcbComponent = circuitElements.find((e4) => e4.type === "pcb_component" && e4.source_component_id === firstComponent.sourceComponent?.source_component_id);
253155
253316
  const pcbPort = su13(circuitElements).pcb_port.list().find((e4) => e4.pcb_port_id === pad2.pcb_port_id);
253156
253317
  const sourcePort = su13(circuitElements).source_port.list().find((e4) => e4.source_port_id === pcbPort?.source_port_id);
253157
- return createPinForImage(pad2, pcbComponent, sourcePort);
253318
+ return createPinForImage({
253319
+ pad: pad2,
253320
+ pcbComponent,
253321
+ sourcePort
253322
+ });
253158
253323
  }).filter((pin) => pin !== undefined)
253159
253324
  };
253160
253325
  pcb.library.images.push(image);
@@ -265222,7 +265387,7 @@ var getBoundsCenter = (bounds) => ({
265222
265387
  x: (bounds.minX + bounds.maxX) / 2,
265223
265388
  y: (bounds.minY + bounds.maxY) / 2
265224
265389
  });
265225
- var getBoundsFromPoints3 = (points) => {
265390
+ var getBoundsFromPoints4 = (points) => {
265226
265391
  if (points.length === 0) {
265227
265392
  return null;
265228
265393
  }
@@ -265288,7 +265453,7 @@ var getEasyEdaModelOriginOnBoardMm = ({
265288
265453
  }
265289
265454
  let modelOriginMm = null;
265290
265455
  if (points.length > 0) {
265291
- const bounds = getBoundsFromPoints3(points);
265456
+ const bounds = getBoundsFromPoints4(points);
265292
265457
  modelOriginMm = bounds ? getBoundsCenter(bounds) : null;
265293
265458
  } else {
265294
265459
  const [originX, originY] = String(svgNode.svgData.attrs?.c_origin ?? "0,0").split(",").map((value) => Number(value.trim()));
@@ -272005,7 +272170,7 @@ var getBoundsCenter2 = (bounds) => ({
272005
272170
  x: (bounds.minX + bounds.maxX) / 2,
272006
272171
  y: (bounds.minY + bounds.maxY) / 2
272007
272172
  });
272008
- var getBoundsFromPoints4 = (points) => {
272173
+ var getBoundsFromPoints5 = (points) => {
272009
272174
  if (points.length === 0) {
272010
272175
  return null;
272011
272176
  }
@@ -272071,7 +272236,7 @@ var getEasyEdaModelOriginOnBoardMm2 = ({
272071
272236
  }
272072
272237
  let modelOriginMm = null;
272073
272238
  if (points.length > 0) {
272074
- const bounds = getBoundsFromPoints4(points);
272239
+ const bounds = getBoundsFromPoints5(points);
272075
272240
  modelOriginMm = bounds ? getBoundsCenter2(bounds) : null;
272076
272241
  } else {
272077
272242
  const [originX, originY] = String(svgNode.svgData.attrs?.c_origin ?? "0,0").split(",").map((value) => Number(value.trim()));
package/dist/lib/index.js CHANGED
@@ -65808,7 +65808,7 @@ var getNodeHandler = (winterSpec, { port, middleware = [] }) => {
65808
65808
  }));
65809
65809
  };
65810
65810
  // package.json
65811
- var version = "0.1.1492";
65811
+ var version = "0.1.1493";
65812
65812
  var package_default = {
65813
65813
  name: "@tscircuit/cli",
65814
65814
  version,
@@ -65859,7 +65859,7 @@ var package_default = {
65859
65859
  cosmiconfig: "^9.0.0",
65860
65860
  debug: "^4.4.0",
65861
65861
  delay: "^6.0.0",
65862
- "dsn-converter": "^0.0.88",
65862
+ "dsn-converter": "^0.0.90",
65863
65863
  easyeda: "^0.0.269",
65864
65864
  "fuse.js": "^7.1.0",
65865
65865
  "get-port": "^7.1.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/cli",
3
- "version": "0.1.1493",
3
+ "version": "0.1.1494",
4
4
  "main": "dist/cli/main.js",
5
5
  "exports": {
6
6
  ".": "./dist/cli/main.js",
@@ -48,7 +48,7 @@
48
48
  "cosmiconfig": "^9.0.0",
49
49
  "debug": "^4.4.0",
50
50
  "delay": "^6.0.0",
51
- "dsn-converter": "^0.0.88",
51
+ "dsn-converter": "^0.0.90",
52
52
  "easyeda": "^0.0.269",
53
53
  "fuse.js": "^7.1.0",
54
54
  "get-port": "^7.1.0",