circuit-json-to-gltf 0.0.71 → 0.0.72
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.d.ts +33 -1
- package/dist/index.js +163 -38
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -196,6 +196,38 @@ declare const COORDINATE_TRANSFORMS: {
|
|
|
196
196
|
readonly OBJ_Z_UP_TO_Y_UP: CoordinateTransformConfig;
|
|
197
197
|
};
|
|
198
198
|
|
|
199
|
+
interface CameraFitOptions {
|
|
200
|
+
/**
|
|
201
|
+
* Target-to-camera direction vector used for solved camera position.
|
|
202
|
+
*/
|
|
203
|
+
direction?: readonly [number, number, number];
|
|
204
|
+
/**
|
|
205
|
+
* Vertical field of view in degrees.
|
|
206
|
+
*/
|
|
207
|
+
fov?: number;
|
|
208
|
+
/**
|
|
209
|
+
* Aspect ratio (width / height) used for horizontal fit calculations.
|
|
210
|
+
*/
|
|
211
|
+
aspectRatio?: number;
|
|
212
|
+
/**
|
|
213
|
+
* Focal length in millimeters. If provided with sensorHeight,
|
|
214
|
+
* it is used instead of fov.
|
|
215
|
+
*/
|
|
216
|
+
focalLength?: number;
|
|
217
|
+
/**
|
|
218
|
+
* Sensor height in millimeters for focalLength->fov conversion.
|
|
219
|
+
*/
|
|
220
|
+
sensorHeight?: number;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Calculate optimal camera position for PCB viewing based on circuit dimensions
|
|
224
|
+
*/
|
|
225
|
+
declare function getBestCameraPosition(circuitJson: CircuitJson): {
|
|
226
|
+
camPos: readonly [number, number, number];
|
|
227
|
+
lookAt: readonly [number, number, number];
|
|
228
|
+
fov: number;
|
|
229
|
+
};
|
|
230
|
+
|
|
199
231
|
declare function convertCircuitJsonToGltf(circuitJson: CircuitJson, options?: ConversionOptions): Promise<ArrayBuffer | object>;
|
|
200
232
|
|
|
201
233
|
interface Point {
|
|
@@ -208,4 +240,4 @@ interface BRepShape {
|
|
|
208
240
|
is_negative?: boolean;
|
|
209
241
|
}
|
|
210
242
|
|
|
211
|
-
export { type BRepShape, type BoardRenderOptions, type BoundingBox, type Box3D, COORDINATE_TRANSFORMS, type Camera3D, type CircuitTo3DOptions, type Color, type ConversionOptions, type CoordinateTransformConfig, type GLTFExportOptions, type LayerRef, type Light3D, type OBJMaterial, type OBJMesh, type Point, type Point3, type STLMesh, type Scene3D, type Size3, type Triangle, applyCoordinateTransform, clearGLBCache, clearOBJCache, clearSTLCache, convertCircuitJsonTo3D, convertCircuitJsonToGltf, convertSceneToGLTF, loadGLB, loadOBJ, loadSTL, renderBoardLayer, renderBoardTextures, transformTriangles };
|
|
243
|
+
export { type BRepShape, type BoardRenderOptions, type BoundingBox, type Box3D, COORDINATE_TRANSFORMS, type Camera3D, type CameraFitOptions, type CircuitTo3DOptions, type Color, type ConversionOptions, type CoordinateTransformConfig, type GLTFExportOptions, type LayerRef, type Light3D, type OBJMaterial, type OBJMesh, type Point, type Point3, type STLMesh, type Scene3D, type Size3, type Triangle, applyCoordinateTransform, clearGLBCache, clearOBJCache, clearSTLCache, convertCircuitJsonTo3D, convertCircuitJsonToGltf, convertSceneToGLTF, getBestCameraPosition, loadGLB, loadOBJ, loadSTL, renderBoardLayer, renderBoardTextures, transformTriangles };
|
package/dist/index.js
CHANGED
|
@@ -446,8 +446,8 @@ var require_add2 = __commonJS({
|
|
|
446
446
|
var require_dot = __commonJS({
|
|
447
447
|
"node_modules/@jscad/modeling/src/maths/vec3/dot.js"(exports, module) {
|
|
448
448
|
"use strict";
|
|
449
|
-
var
|
|
450
|
-
module.exports =
|
|
449
|
+
var dot2 = (a, b) => a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
|
450
|
+
module.exports = dot2;
|
|
451
451
|
}
|
|
452
452
|
});
|
|
453
453
|
|
|
@@ -455,7 +455,7 @@ var require_dot = __commonJS({
|
|
|
455
455
|
var require_angle = __commonJS({
|
|
456
456
|
"node_modules/@jscad/modeling/src/maths/vec3/angle.js"(exports, module) {
|
|
457
457
|
"use strict";
|
|
458
|
-
var
|
|
458
|
+
var dot2 = require_dot();
|
|
459
459
|
var angle = (a, b) => {
|
|
460
460
|
const ax = a[0];
|
|
461
461
|
const ay = a[1];
|
|
@@ -466,7 +466,7 @@ var require_angle = __commonJS({
|
|
|
466
466
|
const mag1 = Math.sqrt(ax * ax + ay * ay + az * az);
|
|
467
467
|
const mag2 = Math.sqrt(bx * bx + by * by + bz * bz);
|
|
468
468
|
const mag = mag1 * mag2;
|
|
469
|
-
const cosine = mag &&
|
|
469
|
+
const cosine = mag && dot2(a, b) / mag;
|
|
470
470
|
return Math.acos(Math.min(Math.max(cosine, -1), 1));
|
|
471
471
|
};
|
|
472
472
|
module.exports = angle;
|
|
@@ -516,7 +516,7 @@ var require_copy2 = __commonJS({
|
|
|
516
516
|
var require_cross = __commonJS({
|
|
517
517
|
"node_modules/@jscad/modeling/src/maths/vec3/cross.js"(exports, module) {
|
|
518
518
|
"use strict";
|
|
519
|
-
var
|
|
519
|
+
var cross2 = (out, a, b) => {
|
|
520
520
|
const ax = a[0];
|
|
521
521
|
const ay = a[1];
|
|
522
522
|
const az = a[2];
|
|
@@ -528,7 +528,7 @@ var require_cross = __commonJS({
|
|
|
528
528
|
out[2] = ax * by - ay * bx;
|
|
529
529
|
return out;
|
|
530
530
|
};
|
|
531
|
-
module.exports =
|
|
531
|
+
module.exports = cross2;
|
|
532
532
|
}
|
|
533
533
|
});
|
|
534
534
|
|
|
@@ -724,13 +724,13 @@ var require_orthogonal = __commonJS({
|
|
|
724
724
|
"use strict";
|
|
725
725
|
var abs = require_abs();
|
|
726
726
|
var create = require_create2();
|
|
727
|
-
var
|
|
727
|
+
var cross2 = require_cross();
|
|
728
728
|
var orthogonal = (out, vector) => {
|
|
729
729
|
const bV = abs(create(), vector);
|
|
730
730
|
const b0 = 0 + (bV[0] < bV[1] && bV[0] < bV[2]);
|
|
731
731
|
const b1 = 0 + (bV[1] <= bV[0] && bV[1] < bV[2]);
|
|
732
732
|
const b2 = 0 + (bV[2] <= bV[0] && bV[2] <= bV[1]);
|
|
733
|
-
return
|
|
733
|
+
return cross2(out, vector, [b0, b1, b2]);
|
|
734
734
|
};
|
|
735
735
|
module.exports = orthogonal;
|
|
736
736
|
}
|
|
@@ -1650,13 +1650,13 @@ var require_copy3 = __commonJS({
|
|
|
1650
1650
|
var require_cross2 = __commonJS({
|
|
1651
1651
|
"node_modules/@jscad/modeling/src/maths/vec2/cross.js"(exports, module) {
|
|
1652
1652
|
"use strict";
|
|
1653
|
-
var
|
|
1653
|
+
var cross2 = (out, a, b) => {
|
|
1654
1654
|
out[0] = 0;
|
|
1655
1655
|
out[1] = 0;
|
|
1656
1656
|
out[2] = a[0] * b[1] - a[1] * b[0];
|
|
1657
1657
|
return out;
|
|
1658
1658
|
};
|
|
1659
|
-
module.exports =
|
|
1659
|
+
module.exports = cross2;
|
|
1660
1660
|
}
|
|
1661
1661
|
});
|
|
1662
1662
|
|
|
@@ -1690,8 +1690,8 @@ var require_divide2 = __commonJS({
|
|
|
1690
1690
|
var require_dot2 = __commonJS({
|
|
1691
1691
|
"node_modules/@jscad/modeling/src/maths/vec2/dot.js"(exports, module) {
|
|
1692
1692
|
"use strict";
|
|
1693
|
-
var
|
|
1694
|
-
module.exports =
|
|
1693
|
+
var dot2 = (a, b) => a[0] * b[0] + a[1] * b[1];
|
|
1694
|
+
module.exports = dot2;
|
|
1695
1695
|
}
|
|
1696
1696
|
});
|
|
1697
1697
|
|
|
@@ -2401,7 +2401,7 @@ var require_create5 = __commonJS({
|
|
|
2401
2401
|
var require_point_line_distance = __commonJS({
|
|
2402
2402
|
"node_modules/@jscad/modeling/src/operations/hulls/quickhull/point-line-distance.js"(exports, module) {
|
|
2403
2403
|
"use strict";
|
|
2404
|
-
var
|
|
2404
|
+
var cross2 = require_cross();
|
|
2405
2405
|
var subtract3 = require_subtract();
|
|
2406
2406
|
var squaredLength = require_squaredLength();
|
|
2407
2407
|
var distanceSquared = (p, a, b) => {
|
|
@@ -2410,7 +2410,7 @@ var require_point_line_distance = __commonJS({
|
|
|
2410
2410
|
const cr = [];
|
|
2411
2411
|
subtract3(ab, b, a);
|
|
2412
2412
|
subtract3(ap, p, a);
|
|
2413
|
-
const area = squaredLength(
|
|
2413
|
+
const area = squaredLength(cross2(cr, ap, ab));
|
|
2414
2414
|
const s = squaredLength(ab);
|
|
2415
2415
|
if (s === 0) {
|
|
2416
2416
|
throw Error("a and b are the same point");
|
|
@@ -2426,14 +2426,14 @@ var require_point_line_distance = __commonJS({
|
|
|
2426
2426
|
var require_get_plane_normal = __commonJS({
|
|
2427
2427
|
"node_modules/@jscad/modeling/src/operations/hulls/quickhull/get-plane-normal.js"(exports, module) {
|
|
2428
2428
|
"use strict";
|
|
2429
|
-
var
|
|
2429
|
+
var cross2 = require_cross();
|
|
2430
2430
|
var normalize = require_normalize();
|
|
2431
2431
|
var subtract3 = require_subtract();
|
|
2432
2432
|
var planeNormal = (out, point1, point2, point3) => {
|
|
2433
2433
|
const tmp = [0, 0, 0];
|
|
2434
2434
|
subtract3(out, point1, point2);
|
|
2435
2435
|
subtract3(tmp, point2, point3);
|
|
2436
|
-
|
|
2436
|
+
cross2(out, out, tmp);
|
|
2437
2437
|
return normalize(out, out);
|
|
2438
2438
|
};
|
|
2439
2439
|
module.exports = planeNormal;
|
|
@@ -2641,8 +2641,8 @@ var require_Face = __commonJS({
|
|
|
2641
2641
|
"use strict";
|
|
2642
2642
|
var add = require_add2();
|
|
2643
2643
|
var copy = require_copy2();
|
|
2644
|
-
var
|
|
2645
|
-
var
|
|
2644
|
+
var cross2 = require_cross();
|
|
2645
|
+
var dot2 = require_dot();
|
|
2646
2646
|
var length = require_length();
|
|
2647
2647
|
var normalize = require_normalize();
|
|
2648
2648
|
var scale = require_scale();
|
|
@@ -2688,7 +2688,7 @@ var require_Face = __commonJS({
|
|
|
2688
2688
|
while (e2 !== e0) {
|
|
2689
2689
|
copy(v1, v2);
|
|
2690
2690
|
subtract3(v2, e2.head().point, e0.head().point);
|
|
2691
|
-
add(this.normal, this.normal,
|
|
2691
|
+
add(this.normal, this.normal, cross2(t, v1, v2));
|
|
2692
2692
|
e2 = e2.next;
|
|
2693
2693
|
this.nVertices += 1;
|
|
2694
2694
|
}
|
|
@@ -2714,7 +2714,7 @@ var require_Face = __commonJS({
|
|
|
2714
2714
|
const maxVector = subtract3([], p2, p1);
|
|
2715
2715
|
const maxLength = Math.sqrt(maxSquaredLength);
|
|
2716
2716
|
scale(maxVector, maxVector, 1 / maxLength);
|
|
2717
|
-
const maxProjection =
|
|
2717
|
+
const maxProjection = dot2(this.normal, maxVector);
|
|
2718
2718
|
scale(maxVector, maxVector, -maxProjection);
|
|
2719
2719
|
add(this.normal, this.normal, maxVector);
|
|
2720
2720
|
normalize(this.normal, this.normal);
|
|
@@ -2736,10 +2736,10 @@ var require_Face = __commonJS({
|
|
|
2736
2736
|
this.computeNormal();
|
|
2737
2737
|
}
|
|
2738
2738
|
this.computeCentroid();
|
|
2739
|
-
this.offset =
|
|
2739
|
+
this.offset = dot2(this.normal, this.centroid);
|
|
2740
2740
|
}
|
|
2741
2741
|
distanceToPlane(point) {
|
|
2742
|
-
return
|
|
2742
|
+
return dot2(this.normal, point) - this.offset;
|
|
2743
2743
|
}
|
|
2744
2744
|
/**
|
|
2745
2745
|
* @private
|
|
@@ -2848,7 +2848,7 @@ var require_Face = __commonJS({
|
|
|
2848
2848
|
var require_QuickHull = __commonJS({
|
|
2849
2849
|
"node_modules/@jscad/modeling/src/operations/hulls/quickhull/QuickHull.js"(exports, module) {
|
|
2850
2850
|
"use strict";
|
|
2851
|
-
var
|
|
2851
|
+
var dot2 = require_dot();
|
|
2852
2852
|
var pointLineDistance = require_point_line_distance();
|
|
2853
2853
|
var getPlaneNormal = require_get_plane_normal();
|
|
2854
2854
|
var VertexList = require_VertexList();
|
|
@@ -3059,12 +3059,12 @@ var require_QuickHull = __commonJS({
|
|
|
3059
3059
|
}
|
|
3060
3060
|
}
|
|
3061
3061
|
const normal = getPlaneNormal([], v0.point, v1.point, v2.point);
|
|
3062
|
-
const distPO =
|
|
3062
|
+
const distPO = dot2(v0.point, normal);
|
|
3063
3063
|
maxDistance = -1;
|
|
3064
3064
|
for (i = 0; i < this.vertices.length; i += 1) {
|
|
3065
3065
|
const vertex = this.vertices[i];
|
|
3066
3066
|
if (vertex !== v0 && vertex !== v1 && vertex !== v2) {
|
|
3067
|
-
const distance = Math.abs(
|
|
3067
|
+
const distance = Math.abs(dot2(normal, vertex.point) - distPO);
|
|
3068
3068
|
if (distance > maxDistance) {
|
|
3069
3069
|
maxDistance = distance;
|
|
3070
3070
|
v3 = vertex;
|
|
@@ -3072,7 +3072,7 @@ var require_QuickHull = __commonJS({
|
|
|
3072
3072
|
}
|
|
3073
3073
|
}
|
|
3074
3074
|
const faces = [];
|
|
3075
|
-
if (
|
|
3075
|
+
if (dot2(v3.point, normal) - distPO < 0) {
|
|
3076
3076
|
faces.push(
|
|
3077
3077
|
Face.createTriangle(v0, v1, v2),
|
|
3078
3078
|
Face.createTriangle(v3, v1, v0),
|
|
@@ -4004,8 +4004,8 @@ var require_measureBoundingBox = __commonJS({
|
|
|
4004
4004
|
var require_dot3 = __commonJS({
|
|
4005
4005
|
"node_modules/@jscad/modeling/src/maths/vec4/dot.js"(exports, module) {
|
|
4006
4006
|
"use strict";
|
|
4007
|
-
var
|
|
4008
|
-
module.exports =
|
|
4007
|
+
var dot2 = (a, b) => a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
|
|
4008
|
+
module.exports = dot2;
|
|
4009
4009
|
}
|
|
4010
4010
|
});
|
|
4011
4011
|
|
|
@@ -4112,10 +4112,10 @@ var require_measureSignedVolume = __commonJS({
|
|
|
4112
4112
|
var measureSignedVolume = (polygon3) => {
|
|
4113
4113
|
let signedVolume = 0;
|
|
4114
4114
|
const vertices = polygon3.vertices;
|
|
4115
|
-
const
|
|
4115
|
+
const cross2 = vec3.create();
|
|
4116
4116
|
for (let i = 0; i < vertices.length - 2; i++) {
|
|
4117
|
-
vec3.cross(
|
|
4118
|
-
signedVolume += vec3.dot(vertices[0],
|
|
4117
|
+
vec3.cross(cross2, vertices[i + 1], vertices[i + 2]);
|
|
4118
|
+
signedVolume += vec3.dot(vertices[0], cross2);
|
|
4119
4119
|
}
|
|
4120
4120
|
signedVolume /= 6;
|
|
4121
4121
|
return signedVolume;
|
|
@@ -11871,8 +11871,8 @@ var require_expandShell = __commonJS({
|
|
|
11871
11871
|
let bestzaxisorthogonality = 0;
|
|
11872
11872
|
for (let i = 1; i < planes.length; i++) {
|
|
11873
11873
|
const normal = planes[i];
|
|
11874
|
-
const
|
|
11875
|
-
const crosslength = vec3.length(
|
|
11874
|
+
const cross2 = vec3.cross(v1, xaxis, normal);
|
|
11875
|
+
const crosslength = vec3.length(cross2);
|
|
11876
11876
|
if (crosslength > 0.05) {
|
|
11877
11877
|
if (crosslength > bestzaxisorthogonality) {
|
|
11878
11878
|
bestzaxisorthogonality = crosslength;
|
|
@@ -15264,16 +15264,16 @@ var geom3ToTriangles = (geometry, polygons) => {
|
|
|
15264
15264
|
next2[1] - base[1],
|
|
15265
15265
|
next2[2] - base[2]
|
|
15266
15266
|
];
|
|
15267
|
-
const
|
|
15267
|
+
const cross2 = [
|
|
15268
15268
|
ab[1] * ac[2] - ab[2] * ac[1],
|
|
15269
15269
|
ab[2] * ac[0] - ab[0] * ac[2],
|
|
15270
15270
|
ab[0] * ac[1] - ab[1] * ac[0]
|
|
15271
15271
|
];
|
|
15272
|
-
const length = Math.sqrt(
|
|
15272
|
+
const length = Math.sqrt(cross2[0] ** 2 + cross2[1] ** 2 + cross2[2] ** 2) || 1;
|
|
15273
15273
|
const normal = {
|
|
15274
|
-
x:
|
|
15275
|
-
y:
|
|
15276
|
-
z:
|
|
15274
|
+
x: cross2[0] / length,
|
|
15275
|
+
y: cross2[1] / length,
|
|
15276
|
+
z: cross2[2] / length
|
|
15277
15277
|
};
|
|
15278
15278
|
for (let i = 1; i < poly.vertices.length - 1; i++) {
|
|
15279
15279
|
const v1 = poly.vertices[i];
|
|
@@ -17190,6 +17190,130 @@ async function convertSceneToGLTF(scene, options = {}) {
|
|
|
17190
17190
|
return result;
|
|
17191
17191
|
}
|
|
17192
17192
|
|
|
17193
|
+
// lib/utils/camera-position.ts
|
|
17194
|
+
var DEFAULT_CAMERA_DIRECTION = [-0.7, 1.2, -0.8];
|
|
17195
|
+
function normalizeVector([x, y, z]) {
|
|
17196
|
+
const length = Math.hypot(x, y, z);
|
|
17197
|
+
if (length === 0) {
|
|
17198
|
+
return [0, 1, 0];
|
|
17199
|
+
}
|
|
17200
|
+
return [x / length, y / length, z / length];
|
|
17201
|
+
}
|
|
17202
|
+
function dot([ax, ay, az], [bx, by, bz]) {
|
|
17203
|
+
return ax * bx + ay * by + az * bz;
|
|
17204
|
+
}
|
|
17205
|
+
function cross([ax, ay, az], [bx, by, bz]) {
|
|
17206
|
+
return [ay * bz - az * by, az * bx - ax * bz, ax * by - ay * bx];
|
|
17207
|
+
}
|
|
17208
|
+
function getVerticalFovRadians(opts) {
|
|
17209
|
+
if (opts?.focalLength !== void 0 && opts.sensorHeight !== void 0 && opts.focalLength > 0 && opts.sensorHeight > 0) {
|
|
17210
|
+
return 2 * Math.atan(opts.sensorHeight / (2 * opts.focalLength));
|
|
17211
|
+
}
|
|
17212
|
+
const fovDegrees = opts?.fov ?? 50;
|
|
17213
|
+
const fovRadians = fovDegrees * Math.PI / 180;
|
|
17214
|
+
if (!Number.isFinite(fovRadians) || fovRadians <= 0) {
|
|
17215
|
+
return 50 * Math.PI / 180;
|
|
17216
|
+
}
|
|
17217
|
+
return Math.min(Math.max(fovRadians, 0.01), Math.PI - 0.01);
|
|
17218
|
+
}
|
|
17219
|
+
function getVerticalFovDegrees(opts) {
|
|
17220
|
+
return getVerticalFovRadians(opts) * 180 / Math.PI;
|
|
17221
|
+
}
|
|
17222
|
+
function getRequiredDistanceForFrustum(corners, cameraDirection, right, up, tanHalfHorizontal, tanHalfVertical) {
|
|
17223
|
+
let requiredDistance = 0;
|
|
17224
|
+
for (const corner of corners) {
|
|
17225
|
+
const u = [corner[0], corner[1], corner[2]];
|
|
17226
|
+
const un = dot(u, cameraDirection);
|
|
17227
|
+
const ur = Math.abs(dot(u, right));
|
|
17228
|
+
const uu = Math.abs(dot(u, up));
|
|
17229
|
+
const distanceForHorizontal = un + ur / tanHalfHorizontal;
|
|
17230
|
+
const distanceForVertical = un + uu / tanHalfVertical;
|
|
17231
|
+
requiredDistance = Math.max(
|
|
17232
|
+
requiredDistance,
|
|
17233
|
+
distanceForHorizontal,
|
|
17234
|
+
distanceForVertical
|
|
17235
|
+
);
|
|
17236
|
+
}
|
|
17237
|
+
return requiredDistance;
|
|
17238
|
+
}
|
|
17239
|
+
function getBestCameraPosition(circuitJson, opts) {
|
|
17240
|
+
const verticalFovDegrees = getVerticalFovDegrees(opts);
|
|
17241
|
+
const panel = circuitJson.find((item) => item.type === "pcb_panel");
|
|
17242
|
+
const board = circuitJson.find((item) => item.type === "pcb_board");
|
|
17243
|
+
const surface = panel || board;
|
|
17244
|
+
if (!surface) {
|
|
17245
|
+
return {
|
|
17246
|
+
camPos: [30, 30, 25],
|
|
17247
|
+
lookAt: [0, 0, 0],
|
|
17248
|
+
fov: verticalFovDegrees
|
|
17249
|
+
};
|
|
17250
|
+
}
|
|
17251
|
+
const { width, height, center } = surface;
|
|
17252
|
+
if (!width || !height || !center) {
|
|
17253
|
+
return {
|
|
17254
|
+
camPos: [30, 30, 25],
|
|
17255
|
+
lookAt: [0, 0, 0],
|
|
17256
|
+
fov: verticalFovDegrees
|
|
17257
|
+
};
|
|
17258
|
+
}
|
|
17259
|
+
const lookAtX = center.x;
|
|
17260
|
+
const lookAtZ = center.y;
|
|
17261
|
+
const cameraDirection = normalizeVector(
|
|
17262
|
+
opts?.direction ?? DEFAULT_CAMERA_DIRECTION
|
|
17263
|
+
);
|
|
17264
|
+
const forward = [
|
|
17265
|
+
-cameraDirection[0],
|
|
17266
|
+
-cameraDirection[1],
|
|
17267
|
+
-cameraDirection[2]
|
|
17268
|
+
];
|
|
17269
|
+
const worldUp = [0, 1, 0];
|
|
17270
|
+
const right = normalizeVector(cross(forward, worldUp));
|
|
17271
|
+
const up = normalizeVector(cross(right, forward));
|
|
17272
|
+
const verticalFov = verticalFovDegrees * Math.PI / 180;
|
|
17273
|
+
const aspectRatio = opts?.aspectRatio !== void 0 && Number.isFinite(opts.aspectRatio) && opts.aspectRatio > 0 ? opts.aspectRatio : 4 / 3;
|
|
17274
|
+
const tanHalfVertical = Math.tan(verticalFov / 2);
|
|
17275
|
+
const tanHalfHorizontal = tanHalfVertical * aspectRatio;
|
|
17276
|
+
const halfWidth = width / 2;
|
|
17277
|
+
const halfHeight = height / 2;
|
|
17278
|
+
const boardCorners = [
|
|
17279
|
+
[halfWidth, 0, halfHeight],
|
|
17280
|
+
[halfWidth, 0, -halfHeight],
|
|
17281
|
+
[-halfWidth, 0, halfHeight],
|
|
17282
|
+
[-halfWidth, 0, -halfHeight]
|
|
17283
|
+
];
|
|
17284
|
+
const requiredDistanceAssumingVerticalFov = getRequiredDistanceForFrustum(
|
|
17285
|
+
boardCorners,
|
|
17286
|
+
cameraDirection,
|
|
17287
|
+
right,
|
|
17288
|
+
up,
|
|
17289
|
+
tanHalfHorizontal,
|
|
17290
|
+
tanHalfVertical
|
|
17291
|
+
);
|
|
17292
|
+
const tanHalfHorizontalIfFovIsHorizontal = tanHalfVertical;
|
|
17293
|
+
const tanHalfVerticalIfFovIsHorizontal = tanHalfHorizontalIfFovIsHorizontal / aspectRatio;
|
|
17294
|
+
const requiredDistanceAssumingHorizontalFov = getRequiredDistanceForFrustum(
|
|
17295
|
+
boardCorners,
|
|
17296
|
+
cameraDirection,
|
|
17297
|
+
right,
|
|
17298
|
+
up,
|
|
17299
|
+
tanHalfHorizontalIfFovIsHorizontal,
|
|
17300
|
+
tanHalfVerticalIfFovIsHorizontal
|
|
17301
|
+
);
|
|
17302
|
+
const requiredDistance = Math.max(
|
|
17303
|
+
requiredDistanceAssumingVerticalFov,
|
|
17304
|
+
requiredDistanceAssumingHorizontalFov
|
|
17305
|
+
);
|
|
17306
|
+
const distance = Math.max(requiredDistance, 1);
|
|
17307
|
+
const camX = lookAtX + cameraDirection[0] * distance;
|
|
17308
|
+
const camY = cameraDirection[1] * distance;
|
|
17309
|
+
const camZ = lookAtZ + cameraDirection[2] * distance;
|
|
17310
|
+
return {
|
|
17311
|
+
camPos: [-camX, camY, camZ],
|
|
17312
|
+
lookAt: [-lookAtX, 0, lookAtZ],
|
|
17313
|
+
fov: verticalFovDegrees
|
|
17314
|
+
};
|
|
17315
|
+
}
|
|
17316
|
+
|
|
17193
17317
|
// lib/index.ts
|
|
17194
17318
|
async function convertCircuitJsonToGltf(circuitJson, options = {}) {
|
|
17195
17319
|
const {
|
|
@@ -17227,6 +17351,7 @@ export {
|
|
|
17227
17351
|
convertCircuitJsonTo3D,
|
|
17228
17352
|
convertCircuitJsonToGltf,
|
|
17229
17353
|
convertSceneToGLTF,
|
|
17354
|
+
getBestCameraPosition,
|
|
17230
17355
|
loadGLB,
|
|
17231
17356
|
loadOBJ,
|
|
17232
17357
|
loadSTL,
|