circuit-json-to-gerber 0.0.47 → 0.0.48

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.
@@ -1422,7 +1422,7 @@ var findApertureNumber = (glayer, search_params) => {
1422
1422
  // package.json
1423
1423
  var package_default = {
1424
1424
  name: "circuit-json-to-gerber",
1425
- version: "0.0.46",
1425
+ version: "0.0.47",
1426
1426
  main: "dist/index.js",
1427
1427
  type: "module",
1428
1428
  scripts: {
@@ -1772,6 +1772,179 @@ var convertSoupToGerberCommands = (soup, opts = {}) => {
1772
1772
  );
1773
1773
  }
1774
1774
  };
1775
+ const drawRingToBuilder = (builder, ring) => {
1776
+ if (!ring || ring.vertices.length === 0) return;
1777
+ builder.add("move_operation", {
1778
+ x: ring.vertices[0].x,
1779
+ y: mfy(ring.vertices[0].y)
1780
+ });
1781
+ const vertices_loop = [...ring.vertices, ring.vertices[0]];
1782
+ for (let i = 0; i < vertices_loop.length - 1; i++) {
1783
+ const start = vertices_loop[i];
1784
+ const end = vertices_loop[i + 1];
1785
+ if (start.bulge && Math.abs(start.bulge) > 1e-9) {
1786
+ const bulge = (opts.flip_y_axis ? -1 : 1) * start.bulge;
1787
+ if (bulge > 0) {
1788
+ builder.add("set_movement_mode_to_counterclockwise_circular", {});
1789
+ } else {
1790
+ builder.add("set_movement_mode_to_clockwise_circular", {});
1791
+ }
1792
+ const p1 = { x: start.x, y: start.y };
1793
+ const p2 = { x: end.x, y: end.y };
1794
+ const dx = p2.x - p1.x;
1795
+ const dy = p2.y - p1.y;
1796
+ const d = Math.sqrt(dx * dx + dy * dy);
1797
+ if (d < 1e-9) {
1798
+ builder.add("set_movement_mode_to_linear", {});
1799
+ builder.add("plot_operation", {
1800
+ x: end.x,
1801
+ y: mfy(end.y)
1802
+ });
1803
+ continue;
1804
+ }
1805
+ const abs_b = Math.abs(bulge);
1806
+ const theta = 4 * Math.atan(abs_b);
1807
+ if (Math.abs(Math.sin(theta / 2)) < 1e-9) {
1808
+ builder.add("set_movement_mode_to_linear", {});
1809
+ builder.add("plot_operation", {
1810
+ x: end.x,
1811
+ y: mfy(end.y)
1812
+ });
1813
+ continue;
1814
+ }
1815
+ const R = d / (2 * Math.sin(theta / 2));
1816
+ const alpha = (Math.PI - theta) / 2;
1817
+ const phi = Math.atan2(dy, dx);
1818
+ const delta_angle = bulge > 0 ? alpha : -alpha;
1819
+ const angle_p1_center = phi + delta_angle;
1820
+ const Cx = p1.x + R * Math.cos(angle_p1_center);
1821
+ const Cy = p1.y + R * Math.sin(angle_p1_center);
1822
+ const i_offset = Cx - p1.x;
1823
+ const j_offset = Cy - p1.y;
1824
+ builder.add("plot_operation", {
1825
+ x: end.x,
1826
+ y: mfy(end.y),
1827
+ i: i_offset,
1828
+ j: opts.flip_y_axis ? -j_offset : j_offset
1829
+ });
1830
+ } else {
1831
+ builder.add("set_movement_mode_to_linear", {});
1832
+ builder.add("plot_operation", { x: end.x, y: mfy(end.y) });
1833
+ }
1834
+ }
1835
+ };
1836
+ const reverseRing = (ring) => {
1837
+ const { vertices } = ring;
1838
+ if (!vertices || vertices.length === 0) return { vertices: [] };
1839
+ const n = vertices.length;
1840
+ const reversed_pts = [...vertices].reverse();
1841
+ const new_vertices = reversed_pts.map((pt, i) => {
1842
+ const bulge_v_idx = (n - 2 - i + n) % n;
1843
+ const bulge = vertices[bulge_v_idx].bulge;
1844
+ return { ...pt, bulge: bulge ? -bulge : void 0 };
1845
+ });
1846
+ return { vertices: new_vertices };
1847
+ };
1848
+ for (const layer of ["top", "bottom"]) {
1849
+ for (const element of soup) {
1850
+ if (element.type === "pcb_copper_pour" && layer === element.layer) {
1851
+ const copper_glayer = glayers[getGerberLayerName(layer, "copper")];
1852
+ const all_pour_commands = [];
1853
+ if (element.shape === "brep") {
1854
+ const { brep_shape } = element;
1855
+ if (!brep_shape) continue;
1856
+ const { outer_ring, inner_rings } = brep_shape;
1857
+ const outer_builder = gerberBuilder().add("select_aperture", { aperture_number: 10 }).add("start_region_statement", {});
1858
+ drawRingToBuilder(outer_builder, reverseRing(outer_ring));
1859
+ outer_builder.add("end_region_statement", {});
1860
+ all_pour_commands.push(...outer_builder.build());
1861
+ if (inner_rings && inner_rings.length > 0) {
1862
+ all_pour_commands.push(
1863
+ ...gerberBuilder().add("set_layer_polarity", { polarity: "C" }).build()
1864
+ );
1865
+ for (const inner_ring of inner_rings) {
1866
+ const inner_builder = gerberBuilder().add("select_aperture", { aperture_number: 10 }).add("start_region_statement", {});
1867
+ drawRingToBuilder(inner_builder, inner_ring);
1868
+ inner_builder.add("end_region_statement", {});
1869
+ all_pour_commands.push(...inner_builder.build());
1870
+ }
1871
+ all_pour_commands.push(
1872
+ ...gerberBuilder().add("set_layer_polarity", { polarity: "D" }).build()
1873
+ );
1874
+ }
1875
+ } else if (element.shape === "rect") {
1876
+ const { center, width, height, rotation } = element;
1877
+ const w = width / 2;
1878
+ const h = height / 2;
1879
+ const points = [
1880
+ { x: -w, y: h },
1881
+ // Top-left
1882
+ { x: w, y: h },
1883
+ // Top-right
1884
+ { x: w, y: -h },
1885
+ // Bottom-right
1886
+ { x: -w, y: -h }
1887
+ // Bottom-left
1888
+ ];
1889
+ let transformMatrix = identity();
1890
+ if (rotation) {
1891
+ const angle_rad = rotation * Math.PI / 180;
1892
+ transformMatrix = rotate(angle_rad);
1893
+ }
1894
+ transformMatrix = compose(
1895
+ translate(center.x, center.y),
1896
+ transformMatrix
1897
+ );
1898
+ const transformedPoints = points.map(
1899
+ (p) => applyToPoint(transformMatrix, p)
1900
+ );
1901
+ const rect_builder = gerberBuilder().add("select_aperture", { aperture_number: 10 }).add("start_region_statement", {});
1902
+ rect_builder.add("move_operation", {
1903
+ x: transformedPoints[0].x,
1904
+ y: mfy(transformedPoints[0].y)
1905
+ });
1906
+ for (let i = 1; i < transformedPoints.length; i++) {
1907
+ rect_builder.add("plot_operation", {
1908
+ x: transformedPoints[i].x,
1909
+ y: mfy(transformedPoints[i].y)
1910
+ });
1911
+ }
1912
+ rect_builder.add("plot_operation", {
1913
+ x: transformedPoints[0].x,
1914
+ y: mfy(transformedPoints[0].y)
1915
+ });
1916
+ rect_builder.add("end_region_statement", {});
1917
+ all_pour_commands.push(...rect_builder.build());
1918
+ } else if (element.shape === "polygon") {
1919
+ const { points } = element;
1920
+ if (points.length > 0) {
1921
+ const poly_builder = gerberBuilder().add("select_aperture", { aperture_number: 10 }).add("start_region_statement", {});
1922
+ poly_builder.add("move_operation", {
1923
+ x: points[0].x,
1924
+ y: mfy(points[0].y)
1925
+ });
1926
+ for (let i = 1; i < points.length; i++) {
1927
+ poly_builder.add("plot_operation", {
1928
+ x: points[i].x,
1929
+ y: mfy(points[i].y)
1930
+ });
1931
+ }
1932
+ poly_builder.add("plot_operation", {
1933
+ x: points[0].x,
1934
+ y: mfy(points[0].y)
1935
+ });
1936
+ poly_builder.add("end_region_statement", {});
1937
+ all_pour_commands.push(...poly_builder.build());
1938
+ }
1939
+ }
1940
+ copper_glayer.push(...all_pour_commands);
1941
+ if (element.covered_with_solder_mask === false) {
1942
+ const mask_layer = glayers[getGerberLayerName(layer, "soldermask")];
1943
+ mask_layer.push(...all_pour_commands);
1944
+ }
1945
+ }
1946
+ }
1947
+ }
1775
1948
  for (const layer of ["top", "bottom", "edgecut"]) {
1776
1949
  for (const element of soup) {
1777
1950
  if (element.type === "pcb_trace") {
@@ -2251,164 +2424,6 @@ var convertSoupToGerberCommands = (soup, opts = {}) => {
2251
2424
  }
2252
2425
  ec_layer.push(...cutout_builder.build());
2253
2426
  }
2254
- } else if (element.type === "pcb_copper_pour" && layer === element.layer) {
2255
- const copper_glayer = glayers[getGerberLayerName(layer, "copper")];
2256
- const pour_builder = gerberBuilder().add("select_aperture", { aperture_number: 10 }).add("start_region_statement", {});
2257
- if (element.shape === "brep") {
2258
- const { brep_shape } = element;
2259
- if (!brep_shape) continue;
2260
- const { outer_ring, inner_rings } = brep_shape;
2261
- const drawRing = (ring) => {
2262
- if (!ring || ring.vertices.length === 0) return;
2263
- pour_builder.add("move_operation", {
2264
- x: ring.vertices[0].x,
2265
- y: mfy(ring.vertices[0].y)
2266
- });
2267
- const vertices_loop = [...ring.vertices, ring.vertices[0]];
2268
- for (let i = 0; i < vertices_loop.length - 1; i++) {
2269
- const start = vertices_loop[i];
2270
- const end = vertices_loop[i + 1];
2271
- if (start.bulge && Math.abs(start.bulge) > 1e-9) {
2272
- const bulge = (opts.flip_y_axis ? -1 : 1) * start.bulge;
2273
- if (bulge > 0) {
2274
- pour_builder.add(
2275
- "set_movement_mode_to_counterclockwise_circular",
2276
- {}
2277
- );
2278
- } else {
2279
- pour_builder.add(
2280
- "set_movement_mode_to_clockwise_circular",
2281
- {}
2282
- );
2283
- }
2284
- const p1 = { x: start.x, y: start.y };
2285
- const p2 = { x: end.x, y: end.y };
2286
- const dx = p2.x - p1.x;
2287
- const dy = p2.y - p1.y;
2288
- const d = Math.sqrt(dx * dx + dy * dy);
2289
- if (d < 1e-9) {
2290
- pour_builder.add("set_movement_mode_to_linear", {});
2291
- pour_builder.add("plot_operation", {
2292
- x: end.x,
2293
- y: mfy(end.y)
2294
- });
2295
- continue;
2296
- }
2297
- const abs_b = Math.abs(bulge);
2298
- const theta = 4 * Math.atan(abs_b);
2299
- if (Math.abs(Math.sin(theta / 2)) < 1e-9) {
2300
- pour_builder.add("set_movement_mode_to_linear", {});
2301
- pour_builder.add("plot_operation", {
2302
- x: end.x,
2303
- y: mfy(end.y)
2304
- });
2305
- continue;
2306
- }
2307
- const R = d / (2 * Math.sin(theta / 2));
2308
- const alpha = (Math.PI - theta) / 2;
2309
- const phi = Math.atan2(dy, dx);
2310
- const delta_angle = bulge > 0 ? alpha : -alpha;
2311
- const angle_p1_center = phi + delta_angle;
2312
- const Cx = p1.x + R * Math.cos(angle_p1_center);
2313
- const Cy = p1.y + R * Math.sin(angle_p1_center);
2314
- const i_offset = Cx - p1.x;
2315
- const j_offset = Cy - p1.y;
2316
- pour_builder.add("plot_operation", {
2317
- x: end.x,
2318
- y: mfy(end.y),
2319
- i: i_offset,
2320
- j: opts.flip_y_axis ? -j_offset : j_offset
2321
- });
2322
- } else {
2323
- pour_builder.add("set_movement_mode_to_linear", {});
2324
- pour_builder.add("plot_operation", { x: end.x, y: mfy(end.y) });
2325
- }
2326
- }
2327
- };
2328
- const reverseRing = (ring) => {
2329
- const { vertices } = ring;
2330
- if (!vertices || vertices.length === 0) return { vertices: [] };
2331
- const n = vertices.length;
2332
- const reversed_pts = [...vertices].reverse();
2333
- const new_vertices = reversed_pts.map((pt, i) => {
2334
- const bulge_v_idx = (n - 2 - i + n) % n;
2335
- const bulge = vertices[bulge_v_idx].bulge;
2336
- return { ...pt, bulge: bulge ? -bulge : void 0 };
2337
- });
2338
- return { vertices: new_vertices };
2339
- };
2340
- drawRing(reverseRing(outer_ring));
2341
- if (inner_rings) {
2342
- for (const inner_ring of inner_rings) {
2343
- drawRing(reverseRing(inner_ring));
2344
- }
2345
- }
2346
- } else if (element.shape === "rect") {
2347
- const { center, width, height, rotation } = element;
2348
- const w = width / 2;
2349
- const h = height / 2;
2350
- const points = [
2351
- { x: -w, y: h },
2352
- // Top-left
2353
- { x: w, y: h },
2354
- // Top-right
2355
- { x: w, y: -h },
2356
- // Bottom-right
2357
- { x: -w, y: -h }
2358
- // Bottom-left
2359
- ];
2360
- let transformMatrix = identity();
2361
- if (rotation) {
2362
- const angle_rad = rotation * Math.PI / 180;
2363
- transformMatrix = rotate(angle_rad);
2364
- }
2365
- transformMatrix = compose(
2366
- translate(center.x, center.y),
2367
- transformMatrix
2368
- );
2369
- const transformedPoints = points.map(
2370
- (p) => applyToPoint(transformMatrix, p)
2371
- );
2372
- pour_builder.add("move_operation", {
2373
- x: transformedPoints[0].x,
2374
- y: mfy(transformedPoints[0].y)
2375
- });
2376
- for (let i = 1; i < transformedPoints.length; i++) {
2377
- pour_builder.add("plot_operation", {
2378
- x: transformedPoints[i].x,
2379
- y: mfy(transformedPoints[i].y)
2380
- });
2381
- }
2382
- pour_builder.add("plot_operation", {
2383
- x: transformedPoints[0].x,
2384
- y: mfy(transformedPoints[0].y)
2385
- });
2386
- } else if (element.shape === "polygon") {
2387
- const { points } = element;
2388
- if (points.length > 0) {
2389
- pour_builder.add("move_operation", {
2390
- x: points[0].x,
2391
- y: mfy(points[0].y)
2392
- });
2393
- for (let i = 1; i < points.length; i++) {
2394
- pour_builder.add("plot_operation", {
2395
- x: points[i].x,
2396
- y: mfy(points[i].y)
2397
- });
2398
- }
2399
- pour_builder.add("plot_operation", {
2400
- x: points[0].x,
2401
- y: mfy(points[0].y)
2402
- });
2403
- }
2404
- }
2405
- pour_builder.add("end_region_statement", {});
2406
- const pour_commands = pour_builder.build();
2407
- copper_glayer.push(...pour_commands);
2408
- if (element.covered_with_solder_mask === false) {
2409
- const mask_layer = glayers[getGerberLayerName(layer, "soldermask")];
2410
- mask_layer.push(...pour_commands);
2411
- }
2412
2427
  }
2413
2428
  }
2414
2429
  }
@@ -2430,4 +2445,4 @@ export {
2430
2445
  stringifyGerberCommands,
2431
2446
  convertSoupToGerberCommands
2432
2447
  };
2433
- //# sourceMappingURL=chunk-LRAY3J4M.js.map
2448
+ //# sourceMappingURL=chunk-VM5XFQ53.js.map