@tscircuit/3d-viewer 0.0.453 → 0.0.455
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 +128 -11
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -28509,7 +28509,7 @@ import * as THREE15 from "three";
|
|
|
28509
28509
|
// package.json
|
|
28510
28510
|
var package_default = {
|
|
28511
28511
|
name: "@tscircuit/3d-viewer",
|
|
28512
|
-
version: "0.0.
|
|
28512
|
+
version: "0.0.454",
|
|
28513
28513
|
main: "./dist/index.js",
|
|
28514
28514
|
module: "./dist/index.js",
|
|
28515
28515
|
type: "module",
|
|
@@ -33651,6 +33651,22 @@ function processViasForManifold(Manifold, circuitJson, pcbThickness, manifoldIns
|
|
|
33651
33651
|
var import_text2 = __toESM(require_text(), 1);
|
|
33652
33652
|
import * as THREE23 from "three";
|
|
33653
33653
|
import { su as su12 } from "@tscircuit/circuit-json-util";
|
|
33654
|
+
function parseFabricationNoteColor(colorString) {
|
|
33655
|
+
let hex = colorString;
|
|
33656
|
+
if (hex.startsWith("#")) {
|
|
33657
|
+
hex = hex.slice(1);
|
|
33658
|
+
}
|
|
33659
|
+
if (hex.length === 6) {
|
|
33660
|
+
const r = parseInt(hex.slice(0, 2), 16);
|
|
33661
|
+
const g = parseInt(hex.slice(2, 4), 16);
|
|
33662
|
+
const b = parseInt(hex.slice(4, 6), 16);
|
|
33663
|
+
return `rgb(${r}, ${g}, ${b})`;
|
|
33664
|
+
}
|
|
33665
|
+
if (colorString.startsWith("rgb")) {
|
|
33666
|
+
return colorString;
|
|
33667
|
+
}
|
|
33668
|
+
return "rgb(255, 243, 204)";
|
|
33669
|
+
}
|
|
33654
33670
|
function createSilkscreenTextureForLayer({
|
|
33655
33671
|
layer,
|
|
33656
33672
|
circuitJson,
|
|
@@ -33663,12 +33679,16 @@ function createSilkscreenTextureForLayer({
|
|
|
33663
33679
|
const pcbSilkscreenLines = su12(circuitJson).pcb_silkscreen_line.list();
|
|
33664
33680
|
const pcbSilkscreenRects = su12(circuitJson).pcb_silkscreen_rect.list();
|
|
33665
33681
|
const pcbSilkscreenCircles = su12(circuitJson).pcb_silkscreen_circle.list();
|
|
33682
|
+
const pcbFabricationNoteRects = su12(circuitJson).pcb_fabrication_note_rect.list();
|
|
33666
33683
|
const textsOnLayer = pcbSilkscreenTexts.filter((t) => t.layer === layer);
|
|
33667
33684
|
const pathsOnLayer = pcbSilkscreenPaths.filter((p) => p.layer === layer);
|
|
33668
33685
|
const linesOnLayer = pcbSilkscreenLines.filter((l) => l.layer === layer);
|
|
33669
33686
|
const rectsOnLayer = pcbSilkscreenRects.filter((r) => r.layer === layer);
|
|
33670
33687
|
const circlesOnLayer = pcbSilkscreenCircles.filter((c) => c.layer === layer);
|
|
33671
|
-
|
|
33688
|
+
const fabricationNoteRectsOnLayer = pcbFabricationNoteRects.filter(
|
|
33689
|
+
(r) => r.layer === layer
|
|
33690
|
+
);
|
|
33691
|
+
if (textsOnLayer.length === 0 && pathsOnLayer.length === 0 && linesOnLayer.length === 0 && rectsOnLayer.length === 0 && circlesOnLayer.length === 0 && fabricationNoteRectsOnLayer.length === 0) {
|
|
33672
33692
|
return null;
|
|
33673
33693
|
}
|
|
33674
33694
|
const canvas = document.createElement("canvas");
|
|
@@ -33819,6 +33839,89 @@ function createSilkscreenTextureForLayer({
|
|
|
33819
33839
|
}
|
|
33820
33840
|
ctx.restore();
|
|
33821
33841
|
});
|
|
33842
|
+
fabricationNoteRectsOnLayer.forEach((rect) => {
|
|
33843
|
+
const width10 = coerceDimensionToMm(rect.width, 0);
|
|
33844
|
+
const height10 = coerceDimensionToMm(rect.height, 0);
|
|
33845
|
+
if (width10 <= 0 || height10 <= 0) return;
|
|
33846
|
+
const centerXmm = parseDimensionToMm(rect.center?.x) ?? 0;
|
|
33847
|
+
const centerYmm = parseDimensionToMm(rect.center?.y) ?? 0;
|
|
33848
|
+
const canvasCenterX = canvasXFromPcb(centerXmm);
|
|
33849
|
+
const canvasCenterY = canvasYFromPcb(centerYmm);
|
|
33850
|
+
const rawRadius = extractRectBorderRadius(rect);
|
|
33851
|
+
const borderRadiusInput = typeof rawRadius === "string" ? parseDimensionToMm(rawRadius) : rawRadius;
|
|
33852
|
+
const borderRadiusMm = clampRectBorderRadius(
|
|
33853
|
+
width10,
|
|
33854
|
+
height10,
|
|
33855
|
+
borderRadiusInput
|
|
33856
|
+
);
|
|
33857
|
+
ctx.save();
|
|
33858
|
+
ctx.translate(canvasCenterX, canvasCenterY);
|
|
33859
|
+
const halfWidthPx = width10 / 2 * traceTextureResolution;
|
|
33860
|
+
const halfHeightPx = height10 / 2 * traceTextureResolution;
|
|
33861
|
+
const borderRadiusPx = Math.min(
|
|
33862
|
+
borderRadiusMm * traceTextureResolution,
|
|
33863
|
+
halfWidthPx,
|
|
33864
|
+
halfHeightPx
|
|
33865
|
+
);
|
|
33866
|
+
const hasStroke = rect.has_stroke ?? false;
|
|
33867
|
+
const isFilled = rect.is_filled ?? true;
|
|
33868
|
+
const isDashed = rect.is_stroke_dashed ?? false;
|
|
33869
|
+
const strokeWidthPx = hasStroke ? coerceDimensionToMm(rect.stroke_width, 0.1) * traceTextureResolution : 0;
|
|
33870
|
+
let fillColor = silkscreenColor;
|
|
33871
|
+
let strokeColor = silkscreenColor;
|
|
33872
|
+
if (rect.color) {
|
|
33873
|
+
const parsedColor = parseFabricationNoteColor(rect.color);
|
|
33874
|
+
fillColor = parsedColor;
|
|
33875
|
+
strokeColor = parsedColor;
|
|
33876
|
+
} else {
|
|
33877
|
+
fillColor = "rgb(255, 243, 204)";
|
|
33878
|
+
strokeColor = "rgb(255, 243, 204)";
|
|
33879
|
+
}
|
|
33880
|
+
const drawRoundedRectPath = (x, y, rectWidth, rectHeight, radius) => {
|
|
33881
|
+
ctx.beginPath();
|
|
33882
|
+
if (radius <= 0) {
|
|
33883
|
+
ctx.rect(x, y, rectWidth, rectHeight);
|
|
33884
|
+
} else {
|
|
33885
|
+
const r = radius;
|
|
33886
|
+
const right = x + rectWidth;
|
|
33887
|
+
const bottom = y + rectHeight;
|
|
33888
|
+
ctx.moveTo(x + r, y);
|
|
33889
|
+
ctx.lineTo(right - r, y);
|
|
33890
|
+
ctx.quadraticCurveTo(right, y, right, y + r);
|
|
33891
|
+
ctx.lineTo(right, bottom - r);
|
|
33892
|
+
ctx.quadraticCurveTo(right, bottom, right - r, bottom);
|
|
33893
|
+
ctx.lineTo(x + r, bottom);
|
|
33894
|
+
ctx.quadraticCurveTo(x, bottom, x, bottom - r);
|
|
33895
|
+
ctx.lineTo(x, y + r);
|
|
33896
|
+
ctx.quadraticCurveTo(x, y, x + r, y);
|
|
33897
|
+
ctx.closePath();
|
|
33898
|
+
}
|
|
33899
|
+
};
|
|
33900
|
+
drawRoundedRectPath(
|
|
33901
|
+
-halfWidthPx,
|
|
33902
|
+
-halfHeightPx,
|
|
33903
|
+
halfWidthPx * 2,
|
|
33904
|
+
halfHeightPx * 2,
|
|
33905
|
+
borderRadiusPx
|
|
33906
|
+
);
|
|
33907
|
+
if (isFilled) {
|
|
33908
|
+
ctx.fillStyle = fillColor;
|
|
33909
|
+
ctx.fill();
|
|
33910
|
+
}
|
|
33911
|
+
if (hasStroke && strokeWidthPx > 0) {
|
|
33912
|
+
ctx.strokeStyle = strokeColor;
|
|
33913
|
+
ctx.lineWidth = strokeWidthPx;
|
|
33914
|
+
if (isDashed) {
|
|
33915
|
+
const dashLength = Math.max(strokeWidthPx * 2, 1);
|
|
33916
|
+
ctx.setLineDash([dashLength, dashLength]);
|
|
33917
|
+
}
|
|
33918
|
+
ctx.stroke();
|
|
33919
|
+
if (isDashed) {
|
|
33920
|
+
ctx.setLineDash([]);
|
|
33921
|
+
}
|
|
33922
|
+
}
|
|
33923
|
+
ctx.restore();
|
|
33924
|
+
});
|
|
33822
33925
|
textsOnLayer.forEach((textS) => {
|
|
33823
33926
|
const fontSize = textS.font_size || 0.25;
|
|
33824
33927
|
const textStrokeWidth = Math.min(Math.max(0.01, fontSize * 0.1), fontSize * 0.05) * traceTextureResolution;
|
|
@@ -34016,15 +34119,29 @@ function createSoldermaskTextureForLayer({
|
|
|
34016
34119
|
const width10 = (hole.outer_width ?? hole.outer_diameter ?? hole.hole_width) * traceTextureResolution;
|
|
34017
34120
|
const height10 = (hole.outer_height ?? hole.outer_diameter ?? hole.hole_height) * traceTextureResolution;
|
|
34018
34121
|
const radius = Math.min(width10, height10) / 2;
|
|
34019
|
-
|
|
34020
|
-
|
|
34021
|
-
|
|
34022
|
-
|
|
34023
|
-
|
|
34024
|
-
|
|
34025
|
-
|
|
34026
|
-
|
|
34027
|
-
|
|
34122
|
+
let rotation2 = hole.ccw_rotation || 0;
|
|
34123
|
+
if (rotation2) {
|
|
34124
|
+
rotation2 = -rotation2;
|
|
34125
|
+
}
|
|
34126
|
+
if (rotation2) {
|
|
34127
|
+
ctx.save();
|
|
34128
|
+
ctx.translate(canvasX, canvasY);
|
|
34129
|
+
ctx.rotate(rotation2 * Math.PI / 180);
|
|
34130
|
+
ctx.beginPath();
|
|
34131
|
+
ctx.roundRect(-width10 / 2, -height10 / 2, width10, height10, radius);
|
|
34132
|
+
ctx.fill();
|
|
34133
|
+
ctx.restore();
|
|
34134
|
+
} else {
|
|
34135
|
+
ctx.beginPath();
|
|
34136
|
+
ctx.roundRect(
|
|
34137
|
+
canvasX - width10 / 2,
|
|
34138
|
+
canvasY - height10 / 2,
|
|
34139
|
+
width10,
|
|
34140
|
+
height10,
|
|
34141
|
+
radius
|
|
34142
|
+
);
|
|
34143
|
+
ctx.fill();
|
|
34144
|
+
}
|
|
34028
34145
|
}
|
|
34029
34146
|
});
|
|
34030
34147
|
const pcbHoles = su13(circuitJson).pcb_hole.list();
|