@tscircuit/3d-viewer 0.0.458 → 0.0.460

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.
Files changed (2) hide show
  1. package/dist/index.js +153 -30
  2. 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.457",
28512
+ version: "0.0.459",
28513
28513
  main: "./dist/index.js",
28514
28514
  module: "./dist/index.js",
28515
28515
  type: "module",
@@ -34040,10 +34040,22 @@ function createSoldermaskTextureForLayer({
34040
34040
  ctx.translate(0, canvasHeight);
34041
34041
  ctx.scale(1, -1);
34042
34042
  }
34043
- ctx.fillStyle = soldermaskColor;
34044
- ctx.fillRect(0, 0, canvasWidth, canvasHeight);
34045
34043
  const canvasXFromPcb = (pcbX) => (pcbX - boardData.center.x + boardData.width / 2) * traceTextureResolution;
34046
34044
  const canvasYFromPcb = (pcbY) => (-(pcbY - boardData.center.y) + boardData.height / 2) * traceTextureResolution;
34045
+ ctx.fillStyle = soldermaskColor;
34046
+ if (boardData.outline && boardData.outline.length >= 3) {
34047
+ ctx.beginPath();
34048
+ const firstPoint = boardData.outline[0];
34049
+ ctx.moveTo(canvasXFromPcb(firstPoint.x), canvasYFromPcb(firstPoint.y));
34050
+ for (let i = 1; i < boardData.outline.length; i++) {
34051
+ const point2 = boardData.outline[i];
34052
+ ctx.lineTo(canvasXFromPcb(point2.x), canvasYFromPcb(point2.y));
34053
+ }
34054
+ ctx.closePath();
34055
+ ctx.fill();
34056
+ } else {
34057
+ ctx.fillRect(0, 0, canvasWidth, canvasHeight);
34058
+ }
34047
34059
  ctx.globalCompositeOperation = "destination-out";
34048
34060
  ctx.fillStyle = "black";
34049
34061
  const pcbSmtPads = su13(circuitJson).pcb_smtpad.list();
@@ -34065,6 +34077,12 @@ function createSoldermaskTextureForLayer({
34065
34077
  return;
34066
34078
  }
34067
34079
  if (pad2.x === void 0 || pad2.y === void 0) return;
34080
+ if (Number.isNaN(pad2.x) || Number.isNaN(pad2.y)) {
34081
+ console.warn(
34082
+ `[soldermask-texture] Skipping pad ${pad2.pcb_smtpad_id} with NaN coordinates`
34083
+ );
34084
+ return;
34085
+ }
34068
34086
  const x = pad2.x;
34069
34087
  const y = pad2.y;
34070
34088
  const canvasX = canvasXFromPcb(x);
@@ -34072,25 +34090,67 @@ function createSoldermaskTextureForLayer({
34072
34090
  if (pad2.shape === "rect") {
34073
34091
  const width10 = pad2.width * traceTextureResolution;
34074
34092
  const height10 = pad2.height * traceTextureResolution;
34075
- ctx.fillRect(canvasX - width10 / 2, canvasY - height10 / 2, width10, height10);
34093
+ const rawRadius = extractRectBorderRadius(pad2);
34094
+ const borderRadius = clampRectBorderRadius(
34095
+ pad2.width,
34096
+ pad2.height,
34097
+ rawRadius
34098
+ ) * traceTextureResolution;
34099
+ if (borderRadius > 0) {
34100
+ ctx.beginPath();
34101
+ ctx.roundRect(
34102
+ canvasX - width10 / 2,
34103
+ canvasY - height10 / 2,
34104
+ width10,
34105
+ height10,
34106
+ borderRadius
34107
+ );
34108
+ ctx.fill();
34109
+ } else {
34110
+ ctx.fillRect(canvasX - width10 / 2, canvasY - height10 / 2, width10, height10);
34111
+ }
34076
34112
  } else if (pad2.shape === "circle") {
34077
34113
  const radius = (pad2.radius ?? pad2.width / 2) * traceTextureResolution;
34078
34114
  ctx.beginPath();
34079
34115
  ctx.arc(canvasX, canvasY, radius, 0, 2 * Math.PI);
34080
34116
  ctx.fill();
34081
- } else if (pad2.shape === "pill" || pad2.shape === "rotated_rect") {
34117
+ } else if (pad2.shape === "pill") {
34082
34118
  const width10 = pad2.width * traceTextureResolution;
34083
34119
  const height10 = pad2.height * traceTextureResolution;
34084
- const radius = Math.min(width10, height10) / 2;
34120
+ const rawRadius = extractRectBorderRadius(pad2);
34121
+ const borderRadius = clampRectBorderRadius(
34122
+ pad2.width,
34123
+ pad2.height,
34124
+ rawRadius
34125
+ ) * traceTextureResolution;
34085
34126
  ctx.beginPath();
34086
34127
  ctx.roundRect(
34087
34128
  canvasX - width10 / 2,
34088
34129
  canvasY - height10 / 2,
34089
34130
  width10,
34090
34131
  height10,
34091
- radius
34132
+ borderRadius
34092
34133
  );
34093
34134
  ctx.fill();
34135
+ } else if (pad2.shape === "rotated_rect") {
34136
+ const width10 = pad2.width * traceTextureResolution;
34137
+ const height10 = pad2.height * traceTextureResolution;
34138
+ const rawRadius = extractRectBorderRadius(pad2);
34139
+ const borderRadius = clampRectBorderRadius(
34140
+ pad2.width,
34141
+ pad2.height,
34142
+ rawRadius
34143
+ ) * traceTextureResolution;
34144
+ const ccwRotation = pad2.ccw_rotation || 0;
34145
+ const rotationRadians = ccwRotation * (Math.PI / 180);
34146
+ const rotation2 = layer === "bottom" ? -rotationRadians : rotationRadians;
34147
+ ctx.save();
34148
+ ctx.translate(canvasX, canvasY);
34149
+ ctx.rotate(rotation2);
34150
+ ctx.beginPath();
34151
+ ctx.roundRect(-width10 / 2, -height10 / 2, width10, height10, borderRadius);
34152
+ ctx.fill();
34153
+ ctx.restore();
34094
34154
  }
34095
34155
  });
34096
34156
  const pcbVias = su13(circuitJson).pcb_via.list();
@@ -34234,6 +34294,71 @@ function createSoldermaskTextureForLayer({
34234
34294
  ctx.arc(adjustedCanvasX, adjustedCanvasY, canvasRadius, 0, 2 * Math.PI);
34235
34295
  ctx.fill();
34236
34296
  }
34297
+ } else if (hole.shape === "circular_hole_with_rect_pad") {
34298
+ const padWidth = (hole.rect_pad_width ?? hole.hole_diameter ?? 0) * traceTextureResolution;
34299
+ const padHeight = (hole.rect_pad_height ?? hole.hole_diameter ?? 0) * traceTextureResolution;
34300
+ const rawRadius = extractRectBorderRadius(hole);
34301
+ const borderRadius = clampRectBorderRadius(
34302
+ hole.rect_pad_width ?? hole.hole_diameter ?? 0,
34303
+ hole.rect_pad_height ?? hole.hole_diameter ?? 0,
34304
+ rawRadius
34305
+ ) * traceTextureResolution;
34306
+ if (borderRadius > 0) {
34307
+ ctx.beginPath();
34308
+ ctx.roundRect(
34309
+ canvasX - padWidth / 2,
34310
+ canvasY - padHeight / 2,
34311
+ padWidth,
34312
+ padHeight,
34313
+ borderRadius
34314
+ );
34315
+ ctx.fill();
34316
+ } else {
34317
+ ctx.fillRect(
34318
+ canvasX - padWidth / 2,
34319
+ canvasY - padHeight / 2,
34320
+ padWidth,
34321
+ padHeight
34322
+ );
34323
+ }
34324
+ } else if (hole.shape === "pill_hole_with_rect_pad") {
34325
+ const padWidth = (hole.rect_pad_width ?? hole.hole_width ?? 0) * traceTextureResolution;
34326
+ const padHeight = (hole.rect_pad_height ?? hole.hole_height ?? 0) * traceTextureResolution;
34327
+ const rawRadius = extractRectBorderRadius(hole);
34328
+ const borderRadius = clampRectBorderRadius(
34329
+ hole.rect_pad_width ?? hole.hole_width ?? 0,
34330
+ hole.rect_pad_height ?? hole.hole_height ?? 0,
34331
+ rawRadius
34332
+ ) * traceTextureResolution;
34333
+ let rotation2 = hole.ccw_rotation || 0;
34334
+ if (layer === "bottom") {
34335
+ rotation2 = -rotation2;
34336
+ }
34337
+ if (rotation2) {
34338
+ ctx.save();
34339
+ ctx.translate(canvasX, canvasY);
34340
+ ctx.rotate(rotation2 * Math.PI / 180);
34341
+ ctx.beginPath();
34342
+ ctx.roundRect(
34343
+ -padWidth / 2,
34344
+ -padHeight / 2,
34345
+ padWidth,
34346
+ padHeight,
34347
+ borderRadius
34348
+ );
34349
+ ctx.fill();
34350
+ ctx.restore();
34351
+ } else {
34352
+ ctx.beginPath();
34353
+ ctx.roundRect(
34354
+ canvasX - padWidth / 2,
34355
+ canvasY - padHeight / 2,
34356
+ padWidth,
34357
+ padHeight,
34358
+ borderRadius
34359
+ );
34360
+ ctx.fill();
34361
+ }
34237
34362
  }
34238
34363
  });
34239
34364
  const pcbHoles = su13(circuitJson).pcb_hole.list();
@@ -34248,35 +34373,33 @@ function createSoldermaskTextureForLayer({
34248
34373
  ctx.beginPath();
34249
34374
  ctx.arc(canvasX, canvasY, canvasRadius, 0, 2 * Math.PI);
34250
34375
  ctx.fill();
34251
- } else if (holeShape === "pill" && typeof hole.hole_width === "number" && typeof hole.hole_height === "number") {
34376
+ } else if ((holeShape === "pill" || holeShape === "rotated_pill") && typeof hole.hole_width === "number" && typeof hole.hole_height === "number") {
34252
34377
  const width10 = hole.hole_width * traceTextureResolution;
34253
34378
  const height10 = hole.hole_height * traceTextureResolution;
34254
34379
  const radius = Math.min(width10, height10) / 2;
34255
- ctx.beginPath();
34256
- ctx.roundRect(
34257
- canvasX - width10 / 2,
34258
- canvasY - height10 / 2,
34259
- width10,
34260
- height10,
34261
- radius
34262
- );
34263
- ctx.fill();
34264
- } else if (holeShape === "rotated_pill" && typeof hole.hole_width === "number" && typeof hole.hole_height === "number") {
34265
- const width10 = hole.hole_width * traceTextureResolution;
34266
- const height10 = hole.hole_height * traceTextureResolution;
34267
- const radius = Math.min(width10, height10) / 2;
34268
- const rotation2 = (hole.ccw_rotation || 0) * (Math.PI / 180);
34269
- ctx.save();
34270
- ctx.translate(canvasX, canvasY);
34380
+ let rotation2 = (hole.ccw_rotation || 0) * (Math.PI / 180);
34271
34381
  if (layer === "bottom") {
34272
- ctx.rotate(-rotation2);
34273
- } else {
34382
+ rotation2 = -rotation2;
34383
+ }
34384
+ if (rotation2) {
34385
+ ctx.save();
34386
+ ctx.translate(canvasX, canvasY);
34274
34387
  ctx.rotate(rotation2);
34388
+ ctx.beginPath();
34389
+ ctx.roundRect(-width10 / 2, -height10 / 2, width10, height10, radius);
34390
+ ctx.fill();
34391
+ ctx.restore();
34392
+ } else {
34393
+ ctx.beginPath();
34394
+ ctx.roundRect(
34395
+ canvasX - width10 / 2,
34396
+ canvasY - height10 / 2,
34397
+ width10,
34398
+ height10,
34399
+ radius
34400
+ );
34401
+ ctx.fill();
34275
34402
  }
34276
- ctx.beginPath();
34277
- ctx.roundRect(-width10 / 2, -height10 / 2, width10, height10, radius);
34278
- ctx.fill();
34279
- ctx.restore();
34280
34403
  }
34281
34404
  });
34282
34405
  const pcbCopperPours = su13(circuitJson).pcb_copper_pour.list();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/3d-viewer",
3
- "version": "0.0.458",
3
+ "version": "0.0.460",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.js",
6
6
  "type": "module",