jscad-electronics 0.0.237 → 0.0.239
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 +96 -9
- package/dist/index.js +1244 -589
- package/dist/index.js.map +1 -1
- package/dist/model-contracts.json +3 -3
- package/dist/vanilla.d.ts +111 -10
- package/dist/vanilla.js +1229 -459
- package/dist/vanilla.js.map +1 -1
- package/package.json +9 -11
package/dist/vanilla.js
CHANGED
|
@@ -24,7 +24,7 @@ function h(type, props, ...restChildren) {
|
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
// .model-contracts/generations/
|
|
27
|
+
// .model-contracts/generations/ad649bc7a403a3e6e9b12ce32ac0b3d0fa61c6bf-v2/node_modules/zod/v3/external.js
|
|
28
28
|
var external_exports = {};
|
|
29
29
|
__export(external_exports, {
|
|
30
30
|
BRAND: () => BRAND,
|
|
@@ -136,7 +136,7 @@ __export(external_exports, {
|
|
|
136
136
|
void: () => voidType
|
|
137
137
|
});
|
|
138
138
|
|
|
139
|
-
// .model-contracts/generations/
|
|
139
|
+
// .model-contracts/generations/ad649bc7a403a3e6e9b12ce32ac0b3d0fa61c6bf-v2/node_modules/zod/v3/helpers/util.js
|
|
140
140
|
var util;
|
|
141
141
|
(function(util2) {
|
|
142
142
|
util2.assertEqual = (_) => {
|
|
@@ -270,7 +270,7 @@ var getParsedType = (data) => {
|
|
|
270
270
|
}
|
|
271
271
|
};
|
|
272
272
|
|
|
273
|
-
// .model-contracts/generations/
|
|
273
|
+
// .model-contracts/generations/ad649bc7a403a3e6e9b12ce32ac0b3d0fa61c6bf-v2/node_modules/zod/v3/ZodError.js
|
|
274
274
|
var ZodIssueCode = util.arrayToEnum([
|
|
275
275
|
"invalid_type",
|
|
276
276
|
"invalid_literal",
|
|
@@ -388,7 +388,7 @@ ZodError.create = (issues) => {
|
|
|
388
388
|
return error;
|
|
389
389
|
};
|
|
390
390
|
|
|
391
|
-
// .model-contracts/generations/
|
|
391
|
+
// .model-contracts/generations/ad649bc7a403a3e6e9b12ce32ac0b3d0fa61c6bf-v2/node_modules/zod/v3/locales/en.js
|
|
392
392
|
var errorMap = (issue, _ctx) => {
|
|
393
393
|
let message;
|
|
394
394
|
switch (issue.code) {
|
|
@@ -491,7 +491,7 @@ var errorMap = (issue, _ctx) => {
|
|
|
491
491
|
};
|
|
492
492
|
var en_default = errorMap;
|
|
493
493
|
|
|
494
|
-
// .model-contracts/generations/
|
|
494
|
+
// .model-contracts/generations/ad649bc7a403a3e6e9b12ce32ac0b3d0fa61c6bf-v2/node_modules/zod/v3/errors.js
|
|
495
495
|
var overrideErrorMap = en_default;
|
|
496
496
|
function setErrorMap(map) {
|
|
497
497
|
overrideErrorMap = map;
|
|
@@ -500,7 +500,7 @@ function getErrorMap() {
|
|
|
500
500
|
return overrideErrorMap;
|
|
501
501
|
}
|
|
502
502
|
|
|
503
|
-
// .model-contracts/generations/
|
|
503
|
+
// .model-contracts/generations/ad649bc7a403a3e6e9b12ce32ac0b3d0fa61c6bf-v2/node_modules/zod/v3/helpers/parseUtil.js
|
|
504
504
|
var makeIssue = (params) => {
|
|
505
505
|
const { data, path, errorMaps, issueData } = params;
|
|
506
506
|
const fullPath = [...path, ...issueData.path || []];
|
|
@@ -610,14 +610,14 @@ var isDirty = (x) => x.status === "dirty";
|
|
|
610
610
|
var isValid = (x) => x.status === "valid";
|
|
611
611
|
var isAsync = (x) => typeof Promise !== "undefined" && x instanceof Promise;
|
|
612
612
|
|
|
613
|
-
// .model-contracts/generations/
|
|
613
|
+
// .model-contracts/generations/ad649bc7a403a3e6e9b12ce32ac0b3d0fa61c6bf-v2/node_modules/zod/v3/helpers/errorUtil.js
|
|
614
614
|
var errorUtil;
|
|
615
615
|
(function(errorUtil2) {
|
|
616
616
|
errorUtil2.errToObj = (message) => typeof message === "string" ? { message } : message || {};
|
|
617
617
|
errorUtil2.toString = (message) => typeof message === "string" ? message : message?.message;
|
|
618
618
|
})(errorUtil || (errorUtil = {}));
|
|
619
619
|
|
|
620
|
-
// .model-contracts/generations/
|
|
620
|
+
// .model-contracts/generations/ad649bc7a403a3e6e9b12ce32ac0b3d0fa61c6bf-v2/node_modules/zod/v3/types.js
|
|
621
621
|
var ParseInputLazyPath = class {
|
|
622
622
|
constructor(parent, value, path, key) {
|
|
623
623
|
this._cachedPath = [];
|
|
@@ -4065,7 +4065,7 @@ var coerce = {
|
|
|
4065
4065
|
};
|
|
4066
4066
|
var NEVER = INVALID;
|
|
4067
4067
|
|
|
4068
|
-
// .model-contracts/generations/
|
|
4068
|
+
// .model-contracts/generations/ad649bc7a403a3e6e9b12ce32ac0b3d0fa61c6bf-v2/node_modules/@tscircuit/mm/dist/index.js
|
|
4069
4069
|
var unitToMm = {
|
|
4070
4070
|
in: 25.4,
|
|
4071
4071
|
inch: 25.4,
|
|
@@ -4092,7 +4092,7 @@ var mm = (n) => {
|
|
|
4092
4092
|
throw new Error(`Unsupported unit: ${unit}`);
|
|
4093
4093
|
};
|
|
4094
4094
|
|
|
4095
|
-
// .model-contracts/generations/
|
|
4095
|
+
// .model-contracts/generations/ad649bc7a403a3e6e9b12ce32ac0b3d0fa61c6bf-v2/index.js
|
|
4096
4096
|
function normalizeNemaMotorModelString(value) {
|
|
4097
4097
|
if (!/^nema(?:8|17|23|34)(?:_|$)/i.test(value)) return value;
|
|
4098
4098
|
return value.replace(/(^|_)jst([0-9]+)_(ph|sh)(?=_|$)/gi, "$1jst$3$2").replace(/(^|_)jst[_-](ph|sh)[_-]([0-9]+)(?=_|$)/gi, "$1jst$2$3").replace(/(^|_)none(?=_|$)/gi, "$1nowires").replace(/(^|_)stubs(?=_|$)/gi, "$1wirestubs");
|
|
@@ -4647,6 +4647,76 @@ var jstMotorWireConnectionSchema = external_exports.string().refine((value) => {
|
|
|
4647
4647
|
const connector = getJstMotorConnector(value);
|
|
4648
4648
|
return connector !== void 0 && connector.pinCount >= 2 && connector.pinCount <= connector.maxPinCount;
|
|
4649
4649
|
}, "Expected jst-ph-N (2\u201316 pins) or jst-sh-N (2\u201315 pins)");
|
|
4650
|
+
function isInsideNemaFace(x, y, p) {
|
|
4651
|
+
const h2 = p.width / 2;
|
|
4652
|
+
x = Math.abs(x);
|
|
4653
|
+
y = Math.abs(y);
|
|
4654
|
+
if (x > h2 || y > h2) return false;
|
|
4655
|
+
const chamfer = p.chamfer;
|
|
4656
|
+
if (!p.stepped) return x + y <= 2 * h2 - chamfer;
|
|
4657
|
+
const c = chamfer / Math.SQRT2;
|
|
4658
|
+
if (c === 0) return true;
|
|
4659
|
+
const recess = p.recessRadius;
|
|
4660
|
+
const fillet = p.filletRadius;
|
|
4661
|
+
const k = h2 - c + recess;
|
|
4662
|
+
if (x > h2 - c && y > h2 - c)
|
|
4663
|
+
return x <= k && y <= k && Math.hypot(x - k, y - k) >= recess;
|
|
4664
|
+
if (y > h2 - fillet && x > h2 - c - fillet)
|
|
4665
|
+
return Math.hypot(x - (h2 - c - fillet), y - (h2 - fillet)) <= fillet;
|
|
4666
|
+
if (x > h2 - fillet && y > h2 - c - fillet)
|
|
4667
|
+
return Math.hypot(x - (h2 - fillet), y - (h2 - c - fillet)) <= fillet;
|
|
4668
|
+
return true;
|
|
4669
|
+
}
|
|
4670
|
+
var segmentDistance = (x, y, ax, ay, bx, by) => {
|
|
4671
|
+
const dx = bx - ax;
|
|
4672
|
+
const dy = by - ay;
|
|
4673
|
+
const t = Math.max(
|
|
4674
|
+
0,
|
|
4675
|
+
Math.min(1, ((x - ax) * dx + (y - ay) * dy) / (dx * dx + dy * dy || 1))
|
|
4676
|
+
);
|
|
4677
|
+
return Math.hypot(x - ax - t * dx, y - ay - t * dy);
|
|
4678
|
+
};
|
|
4679
|
+
var arcDistance = (x, y, cx, cy, r, start, end) => {
|
|
4680
|
+
const angle = (Math.atan2(y - cy, x - cx) + 2 * Math.PI) % (2 * Math.PI);
|
|
4681
|
+
if (angle >= start && angle <= end)
|
|
4682
|
+
return Math.abs(Math.hypot(x - cx, y - cy) - r);
|
|
4683
|
+
return Math.min(
|
|
4684
|
+
Math.hypot(x - cx - r * Math.cos(start), y - cy - r * Math.sin(start)),
|
|
4685
|
+
Math.hypot(x - cx - r * Math.cos(end), y - cy - r * Math.sin(end))
|
|
4686
|
+
);
|
|
4687
|
+
};
|
|
4688
|
+
var boundaryDistance = (x, y, p) => {
|
|
4689
|
+
const h2 = p.width / 2;
|
|
4690
|
+
x = Math.abs(x);
|
|
4691
|
+
y = Math.abs(y);
|
|
4692
|
+
const chamfer = p.chamfer;
|
|
4693
|
+
if (!p.stepped || chamfer === 0)
|
|
4694
|
+
return Math.min(
|
|
4695
|
+
Math.abs(h2 - x),
|
|
4696
|
+
Math.abs(h2 - y),
|
|
4697
|
+
Math.abs(2 * h2 - chamfer - x - y) / Math.SQRT2
|
|
4698
|
+
);
|
|
4699
|
+
const c = chamfer / Math.SQRT2;
|
|
4700
|
+
const recess = p.recessRadius;
|
|
4701
|
+
const fillet = p.filletRadius;
|
|
4702
|
+
const a = h2 - c - fillet;
|
|
4703
|
+
const k = h2 - c + recess;
|
|
4704
|
+
return Math.min(
|
|
4705
|
+
segmentDistance(x, y, -a, h2, a, h2),
|
|
4706
|
+
segmentDistance(x, y, h2, -a, h2, a),
|
|
4707
|
+
segmentDistance(x, y, h2 - c, h2 - fillet, h2 - c, k),
|
|
4708
|
+
segmentDistance(x, y, k, h2 - c, h2 - fillet, h2 - c),
|
|
4709
|
+
arcDistance(x, y, a, h2 - fillet, fillet, 0, Math.PI / 2),
|
|
4710
|
+
arcDistance(x, y, k, k, recess, Math.PI, 3 * Math.PI / 2),
|
|
4711
|
+
arcDistance(x, y, h2 - fillet, a, fillet, 0, Math.PI / 2)
|
|
4712
|
+
);
|
|
4713
|
+
};
|
|
4714
|
+
function fitsNemaCircle(x, y, radius, p) {
|
|
4715
|
+
return isInsideNemaFace(x, y, p) && boundaryDistance(x, y, p) > radius;
|
|
4716
|
+
}
|
|
4717
|
+
function clearsNemaCircle(x, y, radius, p) {
|
|
4718
|
+
return !isInsideNemaFace(x, y, p) && boundaryDistance(x, y, p) > radius;
|
|
4719
|
+
}
|
|
4650
4720
|
var hexSocketBoltDimensions = {
|
|
4651
4721
|
M2: {
|
|
4652
4722
|
diameter: 2,
|
|
@@ -4797,7 +4867,15 @@ var nemaMotorDimensions = {
|
|
|
4797
4867
|
bodyCornerChamfer: 6
|
|
4798
4868
|
},
|
|
4799
4869
|
23: {
|
|
4800
|
-
|
|
4870
|
+
// Representative side-tab rear pattern from STEPPERONLINE's ST-M10 adapter.
|
|
4871
|
+
// The adapter's R5/R2.5 profile is a visual reference, not a frame guarantee:
|
|
4872
|
+
// https://www.omc-stepperonline.com/image/catalog/dimensions/ST-M10_Dimension.svg
|
|
4873
|
+
backFaceHoleSpacing: 50,
|
|
4874
|
+
backFaceHoleSpacingY: 32,
|
|
4875
|
+
rearCornerChamfer: 9 * Math.SQRT2,
|
|
4876
|
+
rearCornerRecessRadius: 5,
|
|
4877
|
+
rearCornerFilletRadius: 2.5,
|
|
4878
|
+
backFaceScrewSize: "M3",
|
|
4801
4879
|
backFaceHoleDepth: 4.5,
|
|
4802
4880
|
bodyWidth: 56.4,
|
|
4803
4881
|
bodyLength: 51,
|
|
@@ -4817,7 +4895,10 @@ var nemaMotorDimensions = {
|
|
|
4817
4895
|
frontCapLength: 5,
|
|
4818
4896
|
rearCapLength: 5,
|
|
4819
4897
|
faceCornerChamfer: 2,
|
|
4820
|
-
bodyCornerChamfer:
|
|
4898
|
+
bodyCornerChamfer: 9 * Math.SQRT2,
|
|
4899
|
+
bodyCornerRecessRadius: 5,
|
|
4900
|
+
bodyCornerFilletRadius: 2.5,
|
|
4901
|
+
chamferedBodyCornerChamfer: 15
|
|
4821
4902
|
},
|
|
4822
4903
|
34: {
|
|
4823
4904
|
// Illustrative rear details; independent of the mounting flange.
|
|
@@ -4853,6 +4934,9 @@ var shape3 = {
|
|
|
4853
4934
|
backFaceHoles: external_exports.boolean().optional(),
|
|
4854
4935
|
backFaceScrews: external_exports.boolean().optional(),
|
|
4855
4936
|
backFaceHoleSpacing: positiveModelLengthSchema.optional(),
|
|
4937
|
+
/** Axis overrides; the legacy scalar still sets a square pattern when supplied. */
|
|
4938
|
+
backFaceHoleSpacingX: positiveModelLengthSchema.optional(),
|
|
4939
|
+
backFaceHoleSpacingY: positiveModelLengthSchema.optional(),
|
|
4856
4940
|
backFaceHoleDiameter: positiveModelLengthSchema.optional(),
|
|
4857
4941
|
backFaceHoleDepth: positiveModelLengthSchema.optional(),
|
|
4858
4942
|
backFaceScrewSize: metricBoltSizeSchema.optional(),
|
|
@@ -4889,8 +4973,14 @@ var shape3 = {
|
|
|
4889
4973
|
rearCapLength: positiveModelLengthSchema.optional(),
|
|
4890
4974
|
faceCornerChamfer: nonnegativeModelLengthSchema.optional(),
|
|
4891
4975
|
bodyCornerChamfer: nonnegativeModelLengthSchema.optional(),
|
|
4976
|
+
bodyCornerRecessRadius: nonnegativeModelLengthSchema.optional(),
|
|
4977
|
+
bodyCornerFilletRadius: nonnegativeModelLengthSchema.optional(),
|
|
4892
4978
|
/** Rear outline is independent of the front mounting flange. */
|
|
4893
4979
|
rearCornerChamfer: nonnegativeModelLengthSchema.optional(),
|
|
4980
|
+
rearCornerRecessRadius: nonnegativeModelLengthSchema.optional(),
|
|
4981
|
+
rearCornerFilletRadius: nonnegativeModelLengthSchema.optional(),
|
|
4982
|
+
rearChamfered: external_exports.boolean().optional(),
|
|
4983
|
+
rearStepped: external_exports.boolean().optional(),
|
|
4894
4984
|
chamfered: external_exports.boolean().optional(),
|
|
4895
4985
|
stepped: external_exports.boolean().optional()
|
|
4896
4986
|
};
|
|
@@ -4915,7 +5005,11 @@ var resolve = (p, ctx) => {
|
|
|
4915
5005
|
);
|
|
4916
5006
|
const corner = select(
|
|
4917
5007
|
["chamfered", "stepped"],
|
|
4918
|
-
p.nemaSize === 34 ? "stepped" : "chamfered"
|
|
5008
|
+
p.nemaSize === 23 || p.nemaSize === 34 ? "stepped" : "chamfered"
|
|
5009
|
+
);
|
|
5010
|
+
const rearCorner = select(
|
|
5011
|
+
["rearChamfered", "rearStepped"],
|
|
5012
|
+
p.chamfered === true ? "rearChamfered" : p.nemaSize === 23 || corner === "stepped" ? "rearStepped" : "rearChamfered"
|
|
4919
5013
|
);
|
|
4920
5014
|
const wireSpecified = p.noWires !== void 0 || p.wireStubs !== void 0 || p.wireConnection !== void 0;
|
|
4921
5015
|
const wireSelections = Number(p.noWires === true) + Number(p.wireStubs === true) + Number(p.wireConnection !== void 0);
|
|
@@ -4925,8 +5019,13 @@ var resolve = (p, ctx) => {
|
|
|
4925
5019
|
message: "Select exactly one of noWires, wireStubs or a JST wireConnection"
|
|
4926
5020
|
});
|
|
4927
5021
|
const d = nemaMotorDimensions[p.nemaSize];
|
|
5022
|
+
const bodyCornerChamfer = p.bodyCornerChamfer ?? (corner === "chamfered" && "chamferedBodyCornerChamfer" in d ? d.chamferedBodyCornerChamfer : d.bodyCornerChamfer);
|
|
5023
|
+
const defaultBodyRadius = Math.min(4, bodyCornerChamfer / Math.SQRT2 / 4);
|
|
4928
5024
|
const backFaceScrewSize = p.backFaceScrewSize ?? d.backFaceScrewSize;
|
|
4929
5025
|
const screw = hexSocketBoltDimensions[backFaceScrewSize];
|
|
5026
|
+
const backFaceHoleSpacing = p.backFaceHoleSpacing ?? ("backFaceHoleSpacing" in d ? d.backFaceHoleSpacing : p.mountingHoleSpacing ?? d.mountingHoleSpacing);
|
|
5027
|
+
const rearCornerChamfer = p.rearCornerChamfer ?? (p.nemaSize === 23 && rearCorner === "rearChamfered" ? p.faceCornerChamfer ?? d.faceCornerChamfer : "rearCornerChamfer" in d ? d.rearCornerChamfer : back === "backFacePlain" && (p.mountingHoleThrough ?? d.mountingHoleThrough) ? p.bodyCornerChamfer ?? d.bodyCornerChamfer : p.faceCornerChamfer ?? d.faceCornerChamfer);
|
|
5028
|
+
const defaultRearRadius = Math.min(4, rearCornerChamfer / Math.SQRT2 / 4);
|
|
4930
5029
|
return {
|
|
4931
5030
|
nemaSize: p.nemaSize,
|
|
4932
5031
|
noWires: p.noWires === true,
|
|
@@ -4939,7 +5038,9 @@ var resolve = (p, ctx) => {
|
|
|
4939
5038
|
backFacePlain: back === "backFacePlain",
|
|
4940
5039
|
backFaceHoles: back === "backFaceHoles",
|
|
4941
5040
|
backFaceScrews: back === "backFaceScrews",
|
|
4942
|
-
backFaceHoleSpacing
|
|
5041
|
+
backFaceHoleSpacing,
|
|
5042
|
+
backFaceHoleSpacingX: p.backFaceHoleSpacingX ?? backFaceHoleSpacing,
|
|
5043
|
+
backFaceHoleSpacingY: p.backFaceHoleSpacingY ?? p.backFaceHoleSpacing ?? ("backFaceHoleSpacingY" in d ? d.backFaceHoleSpacingY : backFaceHoleSpacing),
|
|
4943
5044
|
backFaceHoleDiameter: p.backFaceHoleDiameter ?? screw.diameter,
|
|
4944
5045
|
backFaceHoleDepth: p.backFaceHoleDepth ?? d.backFaceHoleDepth,
|
|
4945
5046
|
backFaceScrewSize,
|
|
@@ -4961,24 +5062,43 @@ var resolve = (p, ctx) => {
|
|
|
4961
5062
|
frontCapLength: p.frontCapLength ?? d.frontCapLength,
|
|
4962
5063
|
rearCapLength: p.rearCapLength ?? d.rearCapLength,
|
|
4963
5064
|
faceCornerChamfer: p.faceCornerChamfer ?? d.faceCornerChamfer,
|
|
4964
|
-
bodyCornerChamfer
|
|
5065
|
+
bodyCornerChamfer,
|
|
5066
|
+
bodyCornerRecessRadius: p.bodyCornerRecessRadius ?? ("bodyCornerRecessRadius" in d ? d.bodyCornerRecessRadius : defaultBodyRadius),
|
|
5067
|
+
bodyCornerFilletRadius: p.bodyCornerFilletRadius ?? ("bodyCornerFilletRadius" in d ? d.bodyCornerFilletRadius : defaultBodyRadius),
|
|
4965
5068
|
chamfered: corner === "chamfered",
|
|
4966
5069
|
stepped: corner === "stepped",
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
5070
|
+
rearCornerChamfer,
|
|
5071
|
+
rearStepped: rearCorner === "rearStepped",
|
|
5072
|
+
rearChamfered: rearCorner === "rearChamfered",
|
|
5073
|
+
rearCornerRecessRadius: p.rearCornerRecessRadius ?? ("rearCornerRecessRadius" in d ? d.rearCornerRecessRadius : defaultRearRadius),
|
|
5074
|
+
rearCornerFilletRadius: p.rearCornerFilletRadius ?? ("rearCornerFilletRadius" in d ? d.rearCornerFilletRadius : defaultRearRadius)
|
|
4970
5075
|
};
|
|
4971
5076
|
};
|
|
4972
5077
|
var validate3 = (p, ctx) => {
|
|
4973
5078
|
const issue = (message) => ctx.addIssue({ code: "custom", message });
|
|
5079
|
+
if (p.stepped && p.bodyCornerRecessRadius + p.bodyCornerFilletRadius > p.bodyCornerChamfer / Math.SQRT2)
|
|
5080
|
+
issue("Body recess and fillet radii must fit within the corner shoulder");
|
|
4974
5081
|
const rearChamfer = p.rearCornerChamfer ?? (p.backFacePlain && p.mountingHoleThrough ? p.bodyCornerChamfer : p.faceCornerChamfer);
|
|
4975
|
-
const rearEdge = p.
|
|
5082
|
+
const rearEdge = p.rearStepped ? rearChamfer / Math.SQRT2 : rearChamfer;
|
|
5083
|
+
if (p.rearStepped && p.rearCornerRecessRadius + p.rearCornerFilletRadius > rearEdge)
|
|
5084
|
+
issue("Rear recess and fillet radii must fit within the corner shoulder");
|
|
4976
5085
|
if (!p.backFacePlain) {
|
|
4977
5086
|
const screw = hexSocketBoltDimensions[p.backFaceScrewSize];
|
|
4978
5087
|
const radius = (p.backFaceScrews ? Math.max(p.backFaceHoleDiameter, screw.headDiameter) : p.backFaceHoleDiameter) / 2;
|
|
4979
|
-
if (p.
|
|
5088
|
+
if (p.backFaceHoleSpacingX <= 2 * radius || p.backFaceHoleSpacingY <= 2 * radius)
|
|
4980
5089
|
issue("Rear holes and screw heads must not overlap each other");
|
|
4981
|
-
if (
|
|
5090
|
+
if (!fitsNemaCircle(
|
|
5091
|
+
p.backFaceHoleSpacingX / 2,
|
|
5092
|
+
p.backFaceHoleSpacingY / 2,
|
|
5093
|
+
radius,
|
|
5094
|
+
{
|
|
5095
|
+
width: p.bodyWidth,
|
|
5096
|
+
chamfer: p.rearCornerChamfer,
|
|
5097
|
+
stepped: p.rearStepped,
|
|
5098
|
+
recessRadius: p.rearCornerRecessRadius,
|
|
5099
|
+
filletRadius: p.rearCornerFilletRadius
|
|
5100
|
+
}
|
|
5101
|
+
))
|
|
4982
5102
|
issue("Rear holes and screw heads must fit entirely inside the rear face");
|
|
4983
5103
|
if (p.backFaceHoleDepth >= p.rearCapLength)
|
|
4984
5104
|
issue("Rear hole depth must be less than the rear cap length");
|
|
@@ -5009,7 +5129,13 @@ var validate3 = (p, ctx) => {
|
|
|
5009
5129
|
issue("Mounting holes must clear the pilot");
|
|
5010
5130
|
if (!p.mountingHoleThrough && p.mountingHoleDepth >= p.frontCapLength)
|
|
5011
5131
|
issue("Blind mounting hole depth must be less than the front cap length");
|
|
5012
|
-
if (p.mountingHoleThrough && (p.
|
|
5132
|
+
if (p.mountingHoleThrough && !clearsNemaCircle(p.mountingHoleSpacing / 2, p.mountingHoleSpacing / 2, r, {
|
|
5133
|
+
width: p.bodyWidth,
|
|
5134
|
+
chamfer: p.bodyCornerChamfer,
|
|
5135
|
+
stepped: p.stepped,
|
|
5136
|
+
recessRadius: p.bodyCornerRecessRadius,
|
|
5137
|
+
filletRadius: p.bodyCornerFilletRadius
|
|
5138
|
+
}))
|
|
5013
5139
|
issue("Body must clear through front mounting holes");
|
|
5014
5140
|
if (p.shaftLength <= p.pilotLength)
|
|
5015
5141
|
issue("Shaft tip must extend beyond the pilot");
|
|
@@ -5028,6 +5154,8 @@ var lengths2 = {
|
|
|
5028
5154
|
bodylength: "bodyLength",
|
|
5029
5155
|
bodywidth: "bodyWidth",
|
|
5030
5156
|
backholespacing: "backFaceHoleSpacing",
|
|
5157
|
+
backholespacingx: "backFaceHoleSpacingX",
|
|
5158
|
+
backholespacingy: "backFaceHoleSpacingY",
|
|
5031
5159
|
backholediameter: "backFaceHoleDiameter",
|
|
5032
5160
|
backholedepth: "backFaceHoleDepth",
|
|
5033
5161
|
shaftlength: "shaftLength",
|
|
@@ -5043,7 +5171,11 @@ var lengths2 = {
|
|
|
5043
5171
|
rearcap: "rearCapLength",
|
|
5044
5172
|
facechamfer: "faceCornerChamfer",
|
|
5045
5173
|
bodychamfer: "bodyCornerChamfer",
|
|
5046
|
-
|
|
5174
|
+
bodyrecess: "bodyCornerRecessRadius",
|
|
5175
|
+
bodyfillet: "bodyCornerFilletRadius",
|
|
5176
|
+
rearchamfer: "rearCornerChamfer",
|
|
5177
|
+
rearrecess: "rearCornerRecessRadius",
|
|
5178
|
+
rearfillet: "rearCornerFilletRadius"
|
|
5047
5179
|
};
|
|
5048
5180
|
var flags = {
|
|
5049
5181
|
backfaceplain: "backFacePlain",
|
|
@@ -5055,6 +5187,8 @@ var flags = {
|
|
|
5055
5187
|
dshaft: "dShaft",
|
|
5056
5188
|
chamfered: "chamfered",
|
|
5057
5189
|
stepped: "stepped",
|
|
5190
|
+
rearstepped: "rearStepped",
|
|
5191
|
+
rearchamfered: "rearChamfered",
|
|
5058
5192
|
nowires: "noWires",
|
|
5059
5193
|
wirestubs: "wireStubs"
|
|
5060
5194
|
};
|
|
@@ -12044,24 +12178,24 @@ function getNemaMotorReferencePoints(input) {
|
|
|
12044
12178
|
p.bodyWidth / 2 / Math.max(Math.abs(x), Math.abs(y)),
|
|
12045
12179
|
(p.bodyWidth - p.faceCornerChamfer) / (Math.abs(x) + Math.abs(y))
|
|
12046
12180
|
);
|
|
12047
|
-
if (p.nemaSize
|
|
12048
|
-
const
|
|
12049
|
-
|
|
12050
|
-
|
|
12051
|
-
|
|
12052
|
-
|
|
12053
|
-
|
|
12054
|
-
|
|
12055
|
-
|
|
12056
|
-
|
|
12057
|
-
|
|
12058
|
-
|
|
12059
|
-
|
|
12181
|
+
if (p.nemaSize !== 34 || p.stepped) {
|
|
12182
|
+
const profile5 = p.nemaSize === 34 ? {
|
|
12183
|
+
width: p.bodyWidth,
|
|
12184
|
+
chamfer: p.bodyCornerChamfer,
|
|
12185
|
+
stepped: p.stepped,
|
|
12186
|
+
recessRadius: p.bodyCornerRecessRadius,
|
|
12187
|
+
filletRadius: p.bodyCornerFilletRadius
|
|
12188
|
+
} : {
|
|
12189
|
+
width: p.bodyWidth,
|
|
12190
|
+
chamfer: p.rearCornerChamfer,
|
|
12191
|
+
stepped: p.rearStepped,
|
|
12192
|
+
recessRadius: p.rearCornerRecessRadius,
|
|
12193
|
+
filletRadius: p.rearCornerFilletRadius
|
|
12060
12194
|
};
|
|
12061
12195
|
let low = 0, high = p.bodyWidth;
|
|
12062
12196
|
for (let i = 0; i < 50; i++) {
|
|
12063
12197
|
const mid = (low + high) / 2;
|
|
12064
|
-
if (
|
|
12198
|
+
if (isInsideNemaFace(mid * x, mid * y, profile5)) low = mid;
|
|
12065
12199
|
else high = mid;
|
|
12066
12200
|
}
|
|
12067
12201
|
radius = low;
|
|
@@ -12249,6 +12383,746 @@ var componentMaterials = {
|
|
|
12249
12383
|
steel: { metalness: 1, roughness: 0.25 }
|
|
12250
12384
|
};
|
|
12251
12385
|
|
|
12386
|
+
// node_modules/@tscircuit/jscad/lib/cleanup-subtraction.ts
|
|
12387
|
+
import insertTjunctions from "@jscad/modeling/src/operations/modifiers/insertTjunctions.js";
|
|
12388
|
+
function cleanupSubtraction(kernel, geometry) {
|
|
12389
|
+
const { geom3 } = kernel.geometries;
|
|
12390
|
+
if (!geometry.polygons.length) return geometry;
|
|
12391
|
+
const source = structuredClone(geometry);
|
|
12392
|
+
const polygons = geom3.toPolygons(source);
|
|
12393
|
+
const extent = Math.max(...kernel.measurements.measureDimensions(source));
|
|
12394
|
+
if (!Number.isFinite(extent) || extent <= 0)
|
|
12395
|
+
throw new Error("Subtraction requires finite nonempty geometry");
|
|
12396
|
+
const epsilon = Math.max(extent * 1e-10, 1e-12);
|
|
12397
|
+
source.polygons = polygons.map((polygon4) => ({
|
|
12398
|
+
...polygon4,
|
|
12399
|
+
vertices: polygon4.vertices.map((point) => {
|
|
12400
|
+
if (!point.every(Number.isFinite))
|
|
12401
|
+
throw new Error("Subtraction requires finite coordinates");
|
|
12402
|
+
return point.map((value) => Math.round(value / epsilon) * epsilon);
|
|
12403
|
+
})
|
|
12404
|
+
}));
|
|
12405
|
+
const triangles = insertTjunctions(source.polygons).flatMap((polygon4) => {
|
|
12406
|
+
if (polygon4.vertices.length === 3) return [polygon4];
|
|
12407
|
+
const center = [0, 0, 0];
|
|
12408
|
+
for (const point of polygon4.vertices)
|
|
12409
|
+
for (let axis = 0; axis < 3; axis++)
|
|
12410
|
+
center[axis] += point[axis] / polygon4.vertices.length;
|
|
12411
|
+
return polygon4.vertices.map((point, index) => {
|
|
12412
|
+
const triangle = kernel.geometries.poly3.create([
|
|
12413
|
+
center,
|
|
12414
|
+
point,
|
|
12415
|
+
polygon4.vertices[(index + 1) % polygon4.vertices.length]
|
|
12416
|
+
]);
|
|
12417
|
+
if (polygon4.color) triangle.color = polygon4.color;
|
|
12418
|
+
return triangle;
|
|
12419
|
+
});
|
|
12420
|
+
});
|
|
12421
|
+
const cleaned = geom3.create(triangles);
|
|
12422
|
+
return {
|
|
12423
|
+
...geometry,
|
|
12424
|
+
polygons: cleaned.polygons,
|
|
12425
|
+
transforms: cleaned.transforms
|
|
12426
|
+
};
|
|
12427
|
+
}
|
|
12428
|
+
|
|
12429
|
+
// node_modules/@tscircuit/jscad/lib/with-references.ts
|
|
12430
|
+
import modeling from "@jscad/modeling";
|
|
12431
|
+
var metadata = /* @__PURE__ */ Symbol.for("@tscircuit/jscad/references/v1");
|
|
12432
|
+
var cache = /* @__PURE__ */ new WeakMap();
|
|
12433
|
+
var snapshot = (value) => structuredClone(value);
|
|
12434
|
+
var assertName = (name) => {
|
|
12435
|
+
if (typeof name !== "string" || !name.trim())
|
|
12436
|
+
throw new Error("Reference name must be nonempty");
|
|
12437
|
+
};
|
|
12438
|
+
function withReferences(kernel = modeling) {
|
|
12439
|
+
if (cache.has(kernel)) return cache.get(kernel);
|
|
12440
|
+
const k = kernel;
|
|
12441
|
+
const { mat4 } = k.maths;
|
|
12442
|
+
const identity = () => Array.from(mat4.create());
|
|
12443
|
+
const multiply = (a, b) => Array.from(mat4.multiply(mat4.create(), a, b));
|
|
12444
|
+
const isGeometry = (g) => g && (k.geometries.geom2.isA(g) || k.geometries.path2.isA(g) || k.geometries.geom3.isA(g));
|
|
12445
|
+
const inputs = (args) => args.flat(Infinity).filter(isGeometry);
|
|
12446
|
+
const read = (g) => g?.[metadata] ?? /* @__PURE__ */ Object.create(null);
|
|
12447
|
+
const merge = (geometries9) => {
|
|
12448
|
+
const refs = /* @__PURE__ */ Object.create(null);
|
|
12449
|
+
for (const g of geometries9)
|
|
12450
|
+
for (const [name, ref] of Object.entries(read(g))) {
|
|
12451
|
+
if (Object.hasOwn(refs, name) && refs[name] !== ref)
|
|
12452
|
+
throw new Error(`Duplicate reference: ${name}`);
|
|
12453
|
+
refs[name] = ref;
|
|
12454
|
+
}
|
|
12455
|
+
return refs;
|
|
12456
|
+
};
|
|
12457
|
+
const attach = (g, refs) => {
|
|
12458
|
+
if (!Object.keys(refs).length) return g;
|
|
12459
|
+
if (Array.isArray(g)) return g.map((item) => attach(item, refs));
|
|
12460
|
+
return isGeometry(g) ? Object.assign({}, g, { [metadata]: refs }) : g;
|
|
12461
|
+
};
|
|
12462
|
+
const moved = (refs, matrix) => Object.fromEntries(
|
|
12463
|
+
Object.entries(refs).map(([name, ref]) => [
|
|
12464
|
+
name,
|
|
12465
|
+
{ geometry: ref.geometry, matrix: multiply(matrix, ref.matrix) }
|
|
12466
|
+
])
|
|
12467
|
+
);
|
|
12468
|
+
const add = (refs, name, ref) => {
|
|
12469
|
+
assertName(name);
|
|
12470
|
+
if (Object.hasOwn(refs, name))
|
|
12471
|
+
throw new Error(`Duplicate reference: ${name}`);
|
|
12472
|
+
refs[name] = ref;
|
|
12473
|
+
};
|
|
12474
|
+
const planar = (g) => {
|
|
12475
|
+
if (!k.geometries.geom2.isA(g) && !k.geometries.path2.isA(g))
|
|
12476
|
+
throw new Error("References require native planar geometry");
|
|
12477
|
+
};
|
|
12478
|
+
const references2 = {
|
|
12479
|
+
name(name, geometry) {
|
|
12480
|
+
planar(geometry);
|
|
12481
|
+
const refs = merge([geometry]);
|
|
12482
|
+
add(refs, name, { geometry: snapshot(geometry), matrix: identity() });
|
|
12483
|
+
return attach(geometry, refs);
|
|
12484
|
+
},
|
|
12485
|
+
nameOutlines(geometry, names) {
|
|
12486
|
+
if (!k.geometries.geom2.isA(geometry))
|
|
12487
|
+
throw new Error("nameOutlines requires a native Geom2");
|
|
12488
|
+
const refs = merge([geometry]);
|
|
12489
|
+
const outlines = k.geometries.geom2.toOutlines(
|
|
12490
|
+
snapshot(geometry)
|
|
12491
|
+
);
|
|
12492
|
+
const area = (points) => points.reduce((sum, p, i) => {
|
|
12493
|
+
const q = points[(i + 1) % points.length];
|
|
12494
|
+
return sum + p[0] * q[1] - p[1] * q[0];
|
|
12495
|
+
}, 0);
|
|
12496
|
+
for (const [role, name] of Object.entries(names)) {
|
|
12497
|
+
if (name === void 0) continue;
|
|
12498
|
+
if (role !== "outer" && role !== "hole")
|
|
12499
|
+
throw new Error(`Unknown outline role: ${role}`);
|
|
12500
|
+
const matches = outlines.filter(
|
|
12501
|
+
(points) => role === "outer" ? area(points) > 0 : area(points) < 0
|
|
12502
|
+
);
|
|
12503
|
+
if (matches.length !== 1)
|
|
12504
|
+
throw new Error(
|
|
12505
|
+
`Expected exactly one ${role} outline, found ${matches.length}`
|
|
12506
|
+
);
|
|
12507
|
+
add(refs, name, {
|
|
12508
|
+
geometry: k.geometries.path2.fromPoints({ closed: true }, matches[0]),
|
|
12509
|
+
matrix: identity()
|
|
12510
|
+
});
|
|
12511
|
+
}
|
|
12512
|
+
return attach(geometry, refs);
|
|
12513
|
+
},
|
|
12514
|
+
reference(name, geometry) {
|
|
12515
|
+
return attach(
|
|
12516
|
+
k.geometries.geom3.create(),
|
|
12517
|
+
read(references2.name(name, geometry))
|
|
12518
|
+
);
|
|
12519
|
+
},
|
|
12520
|
+
get(geometry, name) {
|
|
12521
|
+
const ref = read(geometry)[name];
|
|
12522
|
+
if (!Object.hasOwn(read(geometry), name))
|
|
12523
|
+
throw new Error(`Unknown reference: ${name}`);
|
|
12524
|
+
return snapshot(ref);
|
|
12525
|
+
},
|
|
12526
|
+
list(geometry) {
|
|
12527
|
+
return Object.keys(read(geometry));
|
|
12528
|
+
},
|
|
12529
|
+
collect(geometries9) {
|
|
12530
|
+
return snapshot(merge(inputs([geometries9])));
|
|
12531
|
+
}
|
|
12532
|
+
};
|
|
12533
|
+
const wrapped = { ...k, references: references2 };
|
|
12534
|
+
for (const namespace of [
|
|
12535
|
+
"booleans",
|
|
12536
|
+
"hulls",
|
|
12537
|
+
"expansions",
|
|
12538
|
+
"modifiers",
|
|
12539
|
+
"extrusions",
|
|
12540
|
+
"colors"
|
|
12541
|
+
]) {
|
|
12542
|
+
wrapped[namespace] = { ...k[namespace] };
|
|
12543
|
+
for (const [name, fn] of Object.entries(k[namespace]))
|
|
12544
|
+
if (typeof fn === "function") {
|
|
12545
|
+
wrapped[namespace][name] = (...args) => {
|
|
12546
|
+
const refs = merge(inputs(args));
|
|
12547
|
+
let result = fn(...args);
|
|
12548
|
+
if (namespace === "booleans" && name === "subtract" && k.geometries.geom3.isA(result)) {
|
|
12549
|
+
result = cleanupSubtraction(kernel, result);
|
|
12550
|
+
}
|
|
12551
|
+
return attach(result, refs);
|
|
12552
|
+
};
|
|
12553
|
+
}
|
|
12554
|
+
}
|
|
12555
|
+
const transformResult = (fn, args, offset, boundsBased = false) => {
|
|
12556
|
+
const gs = inputs(args.slice(offset));
|
|
12557
|
+
if (!gs.some((g) => Object.keys(read(g)).length)) return fn(...args);
|
|
12558
|
+
const maps = gs.map((g) => read(g));
|
|
12559
|
+
const before = boundsBased ? gs.map((g) => k.measurements.measureBoundingBox(snapshot(g))[0]) : [];
|
|
12560
|
+
const matrix = boundsBased ? null : fn(...args.slice(0, offset), k.geometries.geom3.create()).transforms;
|
|
12561
|
+
const result = fn(...args);
|
|
12562
|
+
const results = Array.isArray(result) ? result : [result];
|
|
12563
|
+
const output = results.map((g, i) => {
|
|
12564
|
+
let m = matrix;
|
|
12565
|
+
if (boundsBased) {
|
|
12566
|
+
const after = k.measurements.measureBoundingBox(snapshot(g))[0];
|
|
12567
|
+
m = mat4.fromTranslation(
|
|
12568
|
+
mat4.create(),
|
|
12569
|
+
after.map((n, axis) => n - before[i][axis])
|
|
12570
|
+
);
|
|
12571
|
+
}
|
|
12572
|
+
return attach(g, moved(maps[i], Array.from(m)));
|
|
12573
|
+
});
|
|
12574
|
+
return Array.isArray(result) ? output : output[0];
|
|
12575
|
+
};
|
|
12576
|
+
wrapped.transforms = { ...k.transforms };
|
|
12577
|
+
for (const [name, fn] of Object.entries(k.transforms)) {
|
|
12578
|
+
const boundsBased = /^(center|align)/.test(name);
|
|
12579
|
+
const offset = /^center[XYZ]$|^mirror[XYZ]$/.test(name) ? 0 : 1;
|
|
12580
|
+
wrapped.transforms[name] = (...args) => transformResult(fn, args, offset, boundsBased);
|
|
12581
|
+
}
|
|
12582
|
+
wrapped.geometries = { ...k.geometries };
|
|
12583
|
+
for (const ns of ["geom2", "geom3", "path2"]) {
|
|
12584
|
+
wrapped.geometries[ns] = {
|
|
12585
|
+
...k.geometries[ns],
|
|
12586
|
+
transform: (matrix, g) => attach(k.geometries[ns].transform(matrix, g), moved(read(g), matrix))
|
|
12587
|
+
};
|
|
12588
|
+
}
|
|
12589
|
+
wrapped.extrusions.extrudeLinear = (options, ...objects) => {
|
|
12590
|
+
const gs = inputs(objects);
|
|
12591
|
+
const { topOutlineName, bottomOutlineName } = options ?? {};
|
|
12592
|
+
if (topOutlineName === void 0 && bottomOutlineName === void 0) {
|
|
12593
|
+
const refs2 = gs.map(read);
|
|
12594
|
+
const result = k.extrusions.extrudeLinear(options, ...objects);
|
|
12595
|
+
return Array.isArray(result) ? result.map((g, i) => attach(g, refs2[i])) : attach(result, refs2[0] ?? {});
|
|
12596
|
+
}
|
|
12597
|
+
if (gs.length !== 1)
|
|
12598
|
+
throw new Error("Named extrusion outlines require exactly one profile");
|
|
12599
|
+
const profile5 = gs[0];
|
|
12600
|
+
planar(profile5);
|
|
12601
|
+
if (k.geometries.path2.isA(profile5) && !profile5.isClosed)
|
|
12602
|
+
throw new Error("Named extrusion outlines require a closed path");
|
|
12603
|
+
const { height: height10 = 1, twistAngle = 0, twistSteps = 1 } = options;
|
|
12604
|
+
if (!Number.isFinite(height10) || !Number.isFinite(twistAngle) || !Number.isInteger(twistSteps) || twistSteps < 1)
|
|
12605
|
+
throw new Error(
|
|
12606
|
+
"Invalid named extrusion height, twistAngle or twistSteps"
|
|
12607
|
+
);
|
|
12608
|
+
const refs = merge(gs);
|
|
12609
|
+
const source = snapshot(profile5);
|
|
12610
|
+
const top = multiply(
|
|
12611
|
+
Array.from(mat4.fromTranslation(mat4.create(), [0, 0, height10])),
|
|
12612
|
+
Array.from(mat4.fromZRotation(mat4.create(), twistAngle))
|
|
12613
|
+
);
|
|
12614
|
+
for (const [prefix, matrix] of [
|
|
12615
|
+
[bottomOutlineName, identity()],
|
|
12616
|
+
[topOutlineName, top]
|
|
12617
|
+
]) {
|
|
12618
|
+
if (prefix === void 0) continue;
|
|
12619
|
+
add(refs, prefix, { geometry: source, matrix });
|
|
12620
|
+
for (const [name, ref] of Object.entries(read(profile5)))
|
|
12621
|
+
add(refs, `${prefix}.${name}`, {
|
|
12622
|
+
geometry: ref.geometry,
|
|
12623
|
+
matrix: multiply(matrix, ref.matrix)
|
|
12624
|
+
});
|
|
12625
|
+
}
|
|
12626
|
+
return attach(k.extrusions.extrudeLinear(options, ...objects), refs);
|
|
12627
|
+
};
|
|
12628
|
+
cache.set(kernel, wrapped);
|
|
12629
|
+
cache.set(wrapped, wrapped);
|
|
12630
|
+
return wrapped;
|
|
12631
|
+
}
|
|
12632
|
+
|
|
12633
|
+
// node_modules/@tscircuit/jscad/lib/geom3-to-indexed-mesh.ts
|
|
12634
|
+
import jscad from "@jscad/modeling";
|
|
12635
|
+
var edgeKey = (a, b) => a < b ? `${a},${b}` : `${b},${a}`;
|
|
12636
|
+
function geom3ToIndexedMesh(input) {
|
|
12637
|
+
const generalize8 = jscad.modifiers.generalize;
|
|
12638
|
+
input = structuredClone(input);
|
|
12639
|
+
const inputExtent = Math.max(...jscad.measurements.measureDimensions(input));
|
|
12640
|
+
if (!Number.isFinite(inputExtent) || inputExtent <= 0)
|
|
12641
|
+
throw new Error("Expected finite nonempty geometry");
|
|
12642
|
+
const weldTolerance = Math.max(inputExtent * 1e-10, 1e-12);
|
|
12643
|
+
const cells = /* @__PURE__ */ new Map();
|
|
12644
|
+
const weld = (v) => {
|
|
12645
|
+
if (v.length !== 3 || v.some((value) => !Number.isFinite(value)))
|
|
12646
|
+
throw new Error("Expected finite mesh coordinates");
|
|
12647
|
+
const cell = v.map((value) => Math.floor(value / weldTolerance));
|
|
12648
|
+
for (let x = -1; x <= 1; x++)
|
|
12649
|
+
for (let y = -1; y <= 1; y++)
|
|
12650
|
+
for (let z = -1; z <= 1; z++) {
|
|
12651
|
+
const entries2 = cells.get(
|
|
12652
|
+
`${cell[0] + x},${cell[1] + y},${cell[2] + z}`
|
|
12653
|
+
);
|
|
12654
|
+
const existing = entries2?.find(
|
|
12655
|
+
(point3) => Math.hypot(...v.map((value, axis) => value - point3[axis])) <= weldTolerance
|
|
12656
|
+
);
|
|
12657
|
+
if (existing) return existing;
|
|
12658
|
+
}
|
|
12659
|
+
const point2 = [v[0], v[1], v[2]], key = cell.join(","), entries = cells.get(key);
|
|
12660
|
+
if (entries) entries.push(point2);
|
|
12661
|
+
else cells.set(key, [point2]);
|
|
12662
|
+
return point2;
|
|
12663
|
+
};
|
|
12664
|
+
const welded = jscad.geometries.geom3.fromPoints(
|
|
12665
|
+
jscad.geometries.geom3.toPolygons(input).map((poly) => poly.vertices.map(weld))
|
|
12666
|
+
);
|
|
12667
|
+
const geom = generalize8({ snap: true, triangulate: true }, welded);
|
|
12668
|
+
const extent = Math.max(...jscad.measurements.measureDimensions(geom));
|
|
12669
|
+
if (!Number.isFinite(extent) || extent <= 0)
|
|
12670
|
+
throw new Error("Expected finite nonempty geometry");
|
|
12671
|
+
const epsilon = Math.max(extent * 1e-10, 1e-12);
|
|
12672
|
+
const snapTolerance = Math.max(
|
|
12673
|
+
2 * jscad.measurements.measureEpsilon(geom),
|
|
12674
|
+
epsilon
|
|
12675
|
+
);
|
|
12676
|
+
const positions = [], indices = [];
|
|
12677
|
+
const lookup = /* @__PURE__ */ new Map();
|
|
12678
|
+
const point = (index) => [
|
|
12679
|
+
positions[index * 3],
|
|
12680
|
+
positions[index * 3 + 1],
|
|
12681
|
+
positions[index * 3 + 2]
|
|
12682
|
+
];
|
|
12683
|
+
const vertex = (v) => {
|
|
12684
|
+
if (v.length !== 3 || v.some((value) => !Number.isFinite(value)))
|
|
12685
|
+
throw new Error("Expected finite mesh coordinates");
|
|
12686
|
+
const key = v.map((x) => Math.round(x / epsilon)).join(",");
|
|
12687
|
+
let index = lookup.get(key);
|
|
12688
|
+
if (index === void 0) {
|
|
12689
|
+
index = positions.length / 3;
|
|
12690
|
+
positions.push(...v);
|
|
12691
|
+
lookup.set(key, index);
|
|
12692
|
+
}
|
|
12693
|
+
return index;
|
|
12694
|
+
};
|
|
12695
|
+
const area = ([a, b, c]) => {
|
|
12696
|
+
const pa = point(a), pb = point(b), pc = point(c);
|
|
12697
|
+
const u = pb.map((x, i) => x - pa[i]), v = pc.map((x, i) => x - pa[i]);
|
|
12698
|
+
return Math.hypot(
|
|
12699
|
+
u[1] * v[2] - u[2] * v[1],
|
|
12700
|
+
u[2] * v[0] - u[0] * v[2],
|
|
12701
|
+
u[0] * v[1] - u[1] * v[0]
|
|
12702
|
+
);
|
|
12703
|
+
};
|
|
12704
|
+
const triangles = [];
|
|
12705
|
+
const edges = /* @__PURE__ */ new Map();
|
|
12706
|
+
for (const poly of jscad.geometries.geom3.toPolygons(geom)) {
|
|
12707
|
+
for (let i = 1; i < poly.vertices.length - 1; i++) {
|
|
12708
|
+
const triangle = [
|
|
12709
|
+
vertex(poly.vertices[0]),
|
|
12710
|
+
vertex(poly.vertices[i]),
|
|
12711
|
+
vertex(poly.vertices[i + 1])
|
|
12712
|
+
];
|
|
12713
|
+
if (area(triangle) <= epsilon * epsilon) continue;
|
|
12714
|
+
triangles.push(triangle);
|
|
12715
|
+
triangle.forEach((a, i2) => {
|
|
12716
|
+
const b = triangle[(i2 + 1) % 3], key = edgeKey(a, b), entry = edges.get(key);
|
|
12717
|
+
if (entry) entry.count++;
|
|
12718
|
+
else edges.set(key, { a, b, count: 1 });
|
|
12719
|
+
});
|
|
12720
|
+
}
|
|
12721
|
+
}
|
|
12722
|
+
const unmatched = [...edges.values()].filter(({ count }) => count === 1);
|
|
12723
|
+
const candidates = [...new Set(unmatched.flatMap(({ a, b }) => [a, b]))];
|
|
12724
|
+
const sorted = [0, 1, 2].map(
|
|
12725
|
+
(axis) => [...candidates].sort(
|
|
12726
|
+
(a, b) => positions[a * 3 + axis] - positions[b * 3 + axis]
|
|
12727
|
+
)
|
|
12728
|
+
);
|
|
12729
|
+
const subdivisions = /* @__PURE__ */ new Map();
|
|
12730
|
+
for (const { a, b } of unmatched) {
|
|
12731
|
+
const pa = point(a), pb = point(b), direction = pb.map((x, i) => x - pa[i]), length32 = Math.hypot(...direction);
|
|
12732
|
+
if (length32 <= epsilon) continue;
|
|
12733
|
+
const axis = direction.reduce(
|
|
12734
|
+
(best, x, i) => Math.abs(x) > Math.abs(direction[best]) ? i : best,
|
|
12735
|
+
0
|
|
12736
|
+
);
|
|
12737
|
+
const unit = direction.map((x) => x / length32), low = Math.min(pa[axis], pb[axis]), high = Math.max(pa[axis], pb[axis]);
|
|
12738
|
+
const byAxis = sorted[axis];
|
|
12739
|
+
let left = 0, right = byAxis.length;
|
|
12740
|
+
while (left < right) {
|
|
12741
|
+
const mid = left + right >>> 1;
|
|
12742
|
+
if (positions[byAxis[mid] * 3 + axis] < low) left = mid + 1;
|
|
12743
|
+
else right = mid;
|
|
12744
|
+
}
|
|
12745
|
+
const splits = [];
|
|
12746
|
+
for (let i = left; i < byAxis.length; i++) {
|
|
12747
|
+
const index = byAxis[i], p = point(index);
|
|
12748
|
+
if (p[axis] > high) break;
|
|
12749
|
+
if (index === a || index === b) continue;
|
|
12750
|
+
const delta = p.map((x, j) => x - pa[j]), along = delta.reduce((sum, x, j) => sum + x * unit[j], 0);
|
|
12751
|
+
if (along <= epsilon || along >= length32 - epsilon) continue;
|
|
12752
|
+
const distance2 = Math.hypot(...delta.map((x, j) => x - along * unit[j]));
|
|
12753
|
+
if (distance2 <= snapTolerance) splits.push({ index, t: along / length32 });
|
|
12754
|
+
}
|
|
12755
|
+
if (splits.length)
|
|
12756
|
+
subdivisions.set(
|
|
12757
|
+
edgeKey(a, b),
|
|
12758
|
+
splits.sort((x, y) => x.t - y.t).map(({ index }) => index)
|
|
12759
|
+
);
|
|
12760
|
+
}
|
|
12761
|
+
for (const triangle of triangles) {
|
|
12762
|
+
const boundary = triangle.flatMap((a, i) => {
|
|
12763
|
+
const b = triangle[(i + 1) % 3], splits = subdivisions.get(edgeKey(a, b));
|
|
12764
|
+
if (!splits) return [a];
|
|
12765
|
+
const edge = edges.get(edgeKey(a, b));
|
|
12766
|
+
return [a, ...edge.a === a ? splits : [...splits].reverse()];
|
|
12767
|
+
});
|
|
12768
|
+
if (boundary.length === 3) {
|
|
12769
|
+
indices.push(...triangle);
|
|
12770
|
+
continue;
|
|
12771
|
+
}
|
|
12772
|
+
const origin = point(boundary[0]);
|
|
12773
|
+
const center = origin.map(
|
|
12774
|
+
(value, axis) => value + boundary.reduce(
|
|
12775
|
+
(sum, index) => sum + (point(index)[axis] - value) / boundary.length,
|
|
12776
|
+
0
|
|
12777
|
+
)
|
|
12778
|
+
);
|
|
12779
|
+
const middle = vertex(center);
|
|
12780
|
+
for (let i = 0; i < boundary.length; i++) {
|
|
12781
|
+
const part = [
|
|
12782
|
+
middle,
|
|
12783
|
+
boundary[i],
|
|
12784
|
+
boundary[(i + 1) % boundary.length]
|
|
12785
|
+
];
|
|
12786
|
+
if (area(part) <= epsilon * epsilon)
|
|
12787
|
+
throw new Error("Unable to preserve a degenerate mesh boundary");
|
|
12788
|
+
indices.push(...part);
|
|
12789
|
+
}
|
|
12790
|
+
}
|
|
12791
|
+
const compactPositions = [], compactIndices = [], remap = /* @__PURE__ */ new Map();
|
|
12792
|
+
for (const original of indices) {
|
|
12793
|
+
let index = remap.get(original);
|
|
12794
|
+
if (index === void 0) {
|
|
12795
|
+
index = compactPositions.length / 3;
|
|
12796
|
+
compactPositions.push(...point(original));
|
|
12797
|
+
remap.set(original, index);
|
|
12798
|
+
}
|
|
12799
|
+
compactIndices.push(index);
|
|
12800
|
+
}
|
|
12801
|
+
if (!compactIndices.length)
|
|
12802
|
+
throw new Error("Expected finite nonempty geometry");
|
|
12803
|
+
return { positions: compactPositions, indices: compactIndices };
|
|
12804
|
+
}
|
|
12805
|
+
|
|
12806
|
+
// node_modules/@tscircuit/jscad/lib/index.ts
|
|
12807
|
+
var jscad2 = withReferences();
|
|
12808
|
+
var {
|
|
12809
|
+
booleans,
|
|
12810
|
+
colors,
|
|
12811
|
+
curves,
|
|
12812
|
+
expansions,
|
|
12813
|
+
extrusions,
|
|
12814
|
+
geometries,
|
|
12815
|
+
hulls,
|
|
12816
|
+
maths,
|
|
12817
|
+
measurements,
|
|
12818
|
+
modifiers,
|
|
12819
|
+
primitives,
|
|
12820
|
+
text,
|
|
12821
|
+
transforms,
|
|
12822
|
+
utils,
|
|
12823
|
+
references
|
|
12824
|
+
} = jscad2;
|
|
12825
|
+
|
|
12826
|
+
// lib/vanilla/render.ts
|
|
12827
|
+
var isVNode = (n) => n && typeof n === "object" && "type" in n;
|
|
12828
|
+
var degToRad = (v) => {
|
|
12829
|
+
if (typeof v === "number") return v;
|
|
12830
|
+
if (typeof v === "string") {
|
|
12831
|
+
const m = /^(-?\d+(?:\.\d+)?)\s*deg$/i.exec(v);
|
|
12832
|
+
if (m) return parseFloat(m[1]) * Math.PI / 180;
|
|
12833
|
+
const n = Number(v);
|
|
12834
|
+
if (!Number.isNaN(n)) return n;
|
|
12835
|
+
}
|
|
12836
|
+
return 0;
|
|
12837
|
+
};
|
|
12838
|
+
var toVec3 = (v) => {
|
|
12839
|
+
if (Array.isArray(v))
|
|
12840
|
+
return [Number(v[0]) || 0, Number(v[1]) || 0, Number(v[2]) || 0];
|
|
12841
|
+
if (typeof v === "object" && v)
|
|
12842
|
+
return [Number(v.x) || 0, Number(v.y) || 0, Number(v.z) || 0];
|
|
12843
|
+
return [0, 0, 0];
|
|
12844
|
+
};
|
|
12845
|
+
var assertFiniteFeatureTransform = (values) => {
|
|
12846
|
+
if (!values.every(Number.isFinite))
|
|
12847
|
+
throw new Error("JSCAD reference feature transforms must be finite");
|
|
12848
|
+
};
|
|
12849
|
+
var transformFeatureContext = (context, local) => {
|
|
12850
|
+
if (!context.referenceFeatures) return context;
|
|
12851
|
+
const { mat4 } = context.jscad.maths;
|
|
12852
|
+
const matrix = mat4.multiply(mat4.create(), context.matrix, local);
|
|
12853
|
+
assertFiniteFeatureTransform(matrix);
|
|
12854
|
+
return { ...context, matrix };
|
|
12855
|
+
};
|
|
12856
|
+
var validateFeatureName = (name) => {
|
|
12857
|
+
if (name !== void 0 && (typeof name !== "string" || !name.trim()))
|
|
12858
|
+
throw new Error("Named JSCAD features require a nonblank name");
|
|
12859
|
+
};
|
|
12860
|
+
var recordFeature = (context, name, geometry) => {
|
|
12861
|
+
if (!context.referenceFeatures || name === void 0) return;
|
|
12862
|
+
if (Object.hasOwn(context.referenceFeatures, name))
|
|
12863
|
+
throw new Error(`Duplicate JSCAD feature name "${name}"`);
|
|
12864
|
+
const { geometries: geometries9 } = context.jscad;
|
|
12865
|
+
if (!geometries9.geom2.isA(geometry) && !geometries9.path2.isA(geometry) && !geometries9.geom3.isA(geometry))
|
|
12866
|
+
throw new Error(`Named JSCAD feature "${name}" requires native geometry`);
|
|
12867
|
+
assertFiniteFeatureTransform(context.matrix);
|
|
12868
|
+
context.referenceFeatures[name] = {
|
|
12869
|
+
geometry,
|
|
12870
|
+
matrix: [...context.matrix]
|
|
12871
|
+
};
|
|
12872
|
+
};
|
|
12873
|
+
function renderNode(node, colorCtx, renderCtx) {
|
|
12874
|
+
const {
|
|
12875
|
+
jscad: { primitives: primitives9, booleans: booleans5, hulls: hulls2, geometries: geometries9, extrusions: extrusions9, transforms: transforms3 }
|
|
12876
|
+
} = renderCtx;
|
|
12877
|
+
if (node == null || node === false) return [];
|
|
12878
|
+
if (Array.isArray(node))
|
|
12879
|
+
return node.flatMap((n) => renderNode(n, colorCtx, renderCtx));
|
|
12880
|
+
if (!isVNode(node)) return [];
|
|
12881
|
+
const { type, props, children } = node;
|
|
12882
|
+
if (props?.material) {
|
|
12883
|
+
const { material, ...rest } = props;
|
|
12884
|
+
return renderNode({ ...node, props: rest }, colorCtx, renderCtx).map(
|
|
12885
|
+
(entry) => ({
|
|
12886
|
+
...entry,
|
|
12887
|
+
material: { ...material },
|
|
12888
|
+
geom: { ...entry.geom, material: { ...material } }
|
|
12889
|
+
})
|
|
12890
|
+
);
|
|
12891
|
+
}
|
|
12892
|
+
if (type === Fragment) {
|
|
12893
|
+
return (children ?? []).flatMap((c) => renderNode(c, colorCtx, renderCtx));
|
|
12894
|
+
}
|
|
12895
|
+
if (type === Colorize) {
|
|
12896
|
+
const newColor = props?.color;
|
|
12897
|
+
return (children ?? []).flatMap(
|
|
12898
|
+
(c) => renderNode(c, newColor ?? colorCtx, renderCtx)
|
|
12899
|
+
);
|
|
12900
|
+
}
|
|
12901
|
+
if (type === Translate) {
|
|
12902
|
+
const offset = props?.offset ?? props?.center ?? { x: props?.x, y: props?.y, z: props?.z };
|
|
12903
|
+
if (renderCtx.referenceFeatures)
|
|
12904
|
+
assertFiniteFeatureTransform(
|
|
12905
|
+
(Array.isArray(offset) ? offset.slice(0, 3) : [offset?.x, offset?.y, offset?.z]).map((value) => Number(value ?? 0))
|
|
12906
|
+
);
|
|
12907
|
+
const off = toVec3(offset);
|
|
12908
|
+
const { mat4 } = renderCtx.jscad.maths;
|
|
12909
|
+
const childContext = transformFeatureContext(
|
|
12910
|
+
renderCtx,
|
|
12911
|
+
mat4.fromTranslation(mat4.create(), off)
|
|
12912
|
+
);
|
|
12913
|
+
const geoms = (children ?? []).flatMap(
|
|
12914
|
+
(c) => renderNode(c, colorCtx, childContext)
|
|
12915
|
+
);
|
|
12916
|
+
return geoms.map(({ geom, color, material }) => ({
|
|
12917
|
+
material,
|
|
12918
|
+
geom: transforms3.translate(off, geom),
|
|
12919
|
+
color: color ?? colorCtx
|
|
12920
|
+
}));
|
|
12921
|
+
}
|
|
12922
|
+
if (type === Rotate) {
|
|
12923
|
+
const angles = props?.angles ?? props?.rotation;
|
|
12924
|
+
if (renderCtx.referenceFeatures)
|
|
12925
|
+
assertFiniteFeatureTransform(
|
|
12926
|
+
(Array.isArray(angles) ? angles.slice(0, 3) : [props?.x, props?.y, props?.z]).map(
|
|
12927
|
+
(value) => Number(
|
|
12928
|
+
typeof value === "string" ? value.replace(/\s*deg$/i, "") : value ?? 0
|
|
12929
|
+
)
|
|
12930
|
+
)
|
|
12931
|
+
);
|
|
12932
|
+
const rot = Array.isArray(angles) ? [degToRad(angles[0]), degToRad(angles[1]), degToRad(angles[2])] : [
|
|
12933
|
+
degToRad(props?.x ?? 0),
|
|
12934
|
+
degToRad(props?.y ?? 0),
|
|
12935
|
+
degToRad(props?.z ?? 0)
|
|
12936
|
+
];
|
|
12937
|
+
const { mat4 } = renderCtx.jscad.maths;
|
|
12938
|
+
const childContext = transformFeatureContext(
|
|
12939
|
+
renderCtx,
|
|
12940
|
+
mat4.fromTaitBryanRotation(mat4.create(), rot[2], rot[1], rot[0])
|
|
12941
|
+
);
|
|
12942
|
+
const geoms = (children ?? []).flatMap(
|
|
12943
|
+
(c) => renderNode(c, colorCtx, childContext)
|
|
12944
|
+
);
|
|
12945
|
+
return geoms.map(({ geom, color, material }) => ({
|
|
12946
|
+
material,
|
|
12947
|
+
geom: transforms3.rotateZ(
|
|
12948
|
+
rot[2],
|
|
12949
|
+
transforms3.rotateY(rot[1], transforms3.rotateX(rot[0], geom))
|
|
12950
|
+
),
|
|
12951
|
+
color
|
|
12952
|
+
}));
|
|
12953
|
+
}
|
|
12954
|
+
if (type === Union || type === Subtract || type === Hull) {
|
|
12955
|
+
const entries = (children ?? []).flatMap(
|
|
12956
|
+
(c) => renderNode(c, colorCtx, renderCtx)
|
|
12957
|
+
);
|
|
12958
|
+
const geoms = entries.map((g) => g.geom);
|
|
12959
|
+
if (geoms.length === 0) return [];
|
|
12960
|
+
let geom;
|
|
12961
|
+
if (type === Union) geom = booleans5.union(geoms);
|
|
12962
|
+
else if (type === Subtract)
|
|
12963
|
+
geom = booleans5.subtract(geoms[0], geoms.slice(1));
|
|
12964
|
+
else geom = hulls2.hull(geoms);
|
|
12965
|
+
return [
|
|
12966
|
+
{
|
|
12967
|
+
geom,
|
|
12968
|
+
color: colorCtx,
|
|
12969
|
+
material: type === Subtract ? entries[0]?.material : void 0
|
|
12970
|
+
}
|
|
12971
|
+
];
|
|
12972
|
+
}
|
|
12973
|
+
if (type === Custom) {
|
|
12974
|
+
const { name, reference, geometry } = props;
|
|
12975
|
+
validateFeatureName(name);
|
|
12976
|
+
if (reference && name === void 0)
|
|
12977
|
+
throw new Error("Named JSCAD features require a nonblank name");
|
|
12978
|
+
recordFeature(renderCtx, name, geometry);
|
|
12979
|
+
if (reference) return [];
|
|
12980
|
+
return [{ geom: props.geometry, color: colorCtx }];
|
|
12981
|
+
}
|
|
12982
|
+
if (type === Polygon) {
|
|
12983
|
+
const points = props?.points ?? [];
|
|
12984
|
+
const origin = points[0] ?? [0, 0];
|
|
12985
|
+
const area = points.reduce((sum, point, index) => {
|
|
12986
|
+
const next = points[(index + 1) % points.length];
|
|
12987
|
+
return sum + (point[0] - origin[0]) * (next[1] - origin[1]) - (next[0] - origin[0]) * (point[1] - origin[1]);
|
|
12988
|
+
}, 0);
|
|
12989
|
+
const oriented = area < 0 ? [...points].reverse() : points;
|
|
12990
|
+
const g2 = geometries9.geom2.fromPoints(oriented);
|
|
12991
|
+
return [{ geom: g2, color: colorCtx ?? props?.color }];
|
|
12992
|
+
}
|
|
12993
|
+
if (type === ExtrudeLinear) {
|
|
12994
|
+
const { topOutlineName, bottomOutlineName, twistAngle, twistSteps } = props;
|
|
12995
|
+
const namedOutline = topOutlineName !== void 0 || bottomOutlineName !== void 0;
|
|
12996
|
+
const height10 = props?.height ?? props?.h ?? 1;
|
|
12997
|
+
validateFeatureName(topOutlineName);
|
|
12998
|
+
validateFeatureName(bottomOutlineName);
|
|
12999
|
+
if (namedOutline) {
|
|
13000
|
+
if (!Number.isFinite(height10) || !Number.isFinite(twistAngle ?? 0))
|
|
13001
|
+
throw new Error(
|
|
13002
|
+
"Named extrusion outlines require finite height and twistAngle"
|
|
13003
|
+
);
|
|
13004
|
+
if (twistSteps !== void 0 && (!Number.isInteger(twistSteps) || twistSteps < 1))
|
|
13005
|
+
throw new Error(
|
|
13006
|
+
"Named extrusion outlines require positive integer twistSteps"
|
|
13007
|
+
);
|
|
13008
|
+
}
|
|
13009
|
+
const entries = (children ?? []).flatMap(
|
|
13010
|
+
(c) => renderNode(c, colorCtx, renderCtx)
|
|
13011
|
+
);
|
|
13012
|
+
const geoms2 = entries.map((g) => g.geom);
|
|
13013
|
+
if (geoms2.length === 0) return [];
|
|
13014
|
+
if (namedOutline && geoms2.length !== 1)
|
|
13015
|
+
throw new Error("Named extrusion outlines require exactly one profile");
|
|
13016
|
+
const base2 = geoms2.length > 1 ? booleans5.union(geoms2) : geoms2[0];
|
|
13017
|
+
if (namedOutline && !geometries9.geom2.isA(base2) && !(geometries9.path2.isA(base2) && base2.isClosed))
|
|
13018
|
+
throw new Error(
|
|
13019
|
+
"Named extrusion outlines require a geom2 or closed path2 profile"
|
|
13020
|
+
);
|
|
13021
|
+
if (namedOutline && renderCtx.referenceFeatures) {
|
|
13022
|
+
const { mat4 } = renderCtx.jscad.maths;
|
|
13023
|
+
const topContext = transformFeatureContext(
|
|
13024
|
+
renderCtx,
|
|
13025
|
+
mat4.multiply(
|
|
13026
|
+
mat4.create(),
|
|
13027
|
+
mat4.fromTranslation(mat4.create(), [0, 0, height10]),
|
|
13028
|
+
mat4.fromZRotation(mat4.create(), twistAngle ?? 0)
|
|
13029
|
+
)
|
|
13030
|
+
);
|
|
13031
|
+
recordFeature(topContext, topOutlineName, base2);
|
|
13032
|
+
recordFeature(renderCtx, bottomOutlineName, base2);
|
|
13033
|
+
}
|
|
13034
|
+
const g3 = extrusions9.extrudeLinear(
|
|
13035
|
+
{
|
|
13036
|
+
height: height10,
|
|
13037
|
+
...twistAngle !== void 0 ? { twistAngle } : {},
|
|
13038
|
+
...twistSteps !== void 0 ? { twistSteps } : {}
|
|
13039
|
+
},
|
|
13040
|
+
base2
|
|
13041
|
+
);
|
|
13042
|
+
return [
|
|
13043
|
+
{
|
|
13044
|
+
geom: g3,
|
|
13045
|
+
color: colorCtx ?? props?.color,
|
|
13046
|
+
material: entries.length === 1 ? entries[0]?.material : void 0
|
|
13047
|
+
}
|
|
13048
|
+
];
|
|
13049
|
+
}
|
|
13050
|
+
if (type === Cuboid || type === Cube || type === Cylinder || type === Sphere || type === RoundedCuboid || type === RoundedCylinder) {
|
|
13051
|
+
let g;
|
|
13052
|
+
if (type === Cuboid) {
|
|
13053
|
+
const size = props?.size ?? [1, 1, 1];
|
|
13054
|
+
const offset = props?.offset;
|
|
13055
|
+
const center = props?.center ?? (offset ? [offset[0], offset[1], offset[2]] : [0, 0, 0]);
|
|
13056
|
+
g = primitives9.cuboid({ size, center });
|
|
13057
|
+
} else if (type === Cube) {
|
|
13058
|
+
const size = props?.size ?? 1;
|
|
13059
|
+
const offset = props?.offset;
|
|
13060
|
+
const center = props?.center ?? (offset ? [offset[0], offset[1], offset[2]] : [0, 0, 0]);
|
|
13061
|
+
g = primitives9.cube({ size, center });
|
|
13062
|
+
} else if (type === Cylinder) {
|
|
13063
|
+
const height10 = props?.height ?? 1;
|
|
13064
|
+
const radius = props?.radius ?? 1;
|
|
13065
|
+
const center = props?.center ?? [0, 0, 0];
|
|
13066
|
+
g = primitives9.cylinder({ height: height10, radius, center });
|
|
13067
|
+
} else if (type === Sphere) {
|
|
13068
|
+
const radius = props?.radius ?? 1;
|
|
13069
|
+
const center = props?.center ?? [0, 0, 0];
|
|
13070
|
+
g = primitives9.sphere({ radius, center });
|
|
13071
|
+
} else if (type === RoundedCylinder) {
|
|
13072
|
+
const height10 = props?.height ?? 1;
|
|
13073
|
+
const radius = props?.radius ?? 1;
|
|
13074
|
+
const roundRadius = props?.roundRadius ?? 0.1;
|
|
13075
|
+
const center = props?.center ?? [0, 0, 0];
|
|
13076
|
+
g = primitives9.roundedCylinder({ height: height10, radius, roundRadius, center });
|
|
13077
|
+
} else {
|
|
13078
|
+
const size = props?.size ?? [1, 1, 1];
|
|
13079
|
+
const roundRadius = props?.roundRadius ?? 0.1;
|
|
13080
|
+
const center = props?.center ?? [0, 0, 0];
|
|
13081
|
+
g = primitives9.roundedCuboid({ size, roundRadius, center });
|
|
13082
|
+
}
|
|
13083
|
+
return [{ geom: g, color: colorCtx ?? props?.color }];
|
|
13084
|
+
}
|
|
13085
|
+
if (typeof type === "function") {
|
|
13086
|
+
const out = type(props ?? {});
|
|
13087
|
+
return renderNode(out, colorCtx, renderCtx);
|
|
13088
|
+
}
|
|
13089
|
+
return (children ?? []).flatMap((c) => renderNode(c, colorCtx, renderCtx));
|
|
13090
|
+
}
|
|
13091
|
+
function render(root, jscad22) {
|
|
13092
|
+
jscad22 = withReferences(
|
|
13093
|
+
jscad22
|
|
13094
|
+
);
|
|
13095
|
+
const geometries9 = renderNode(root, void 0, { jscad: jscad22 });
|
|
13096
|
+
return {
|
|
13097
|
+
geometries: geometries9.map(
|
|
13098
|
+
(entry) => entry.material ? { ...entry, geom: { ...entry.geom, material: entry.material } } : entry
|
|
13099
|
+
)
|
|
13100
|
+
};
|
|
13101
|
+
}
|
|
13102
|
+
function renderToJscadModel(root, jscad22) {
|
|
13103
|
+
jscad22 = withReferences(
|
|
13104
|
+
jscad22
|
|
13105
|
+
);
|
|
13106
|
+
const referenceFeatures = /* @__PURE__ */ Object.create(null);
|
|
13107
|
+
const geometries9 = renderNode(root, void 0, {
|
|
13108
|
+
jscad: jscad22,
|
|
13109
|
+
referenceFeatures,
|
|
13110
|
+
matrix: jscad22.maths.mat4.create()
|
|
13111
|
+
});
|
|
13112
|
+
return {
|
|
13113
|
+
geometries: geometries9.map(({ geom, color }) => {
|
|
13114
|
+
if (color === void 0) return geom;
|
|
13115
|
+
const { colors: colors2 } = jscad22;
|
|
13116
|
+
const rgb = typeof color === "string" ? color.startsWith("#") ? colors2.hexToRgb(
|
|
13117
|
+
/^#[\da-f]{3,4}$/i.test(color) ? `#${[...color.slice(1)].map((c) => c + c).join("")}` : color
|
|
13118
|
+
) : colors2.colorNameToRgb(color) : color;
|
|
13119
|
+
if (!rgb) throw new Error(`Unknown JSCAD color "${color}"`);
|
|
13120
|
+
return colors2.colorize(rgb, geom);
|
|
13121
|
+
}),
|
|
13122
|
+
referenceFeatures
|
|
13123
|
+
};
|
|
13124
|
+
}
|
|
13125
|
+
|
|
12252
13126
|
// lib/vanilla/primitives.ts
|
|
12253
13127
|
var Cuboid = /* @__PURE__ */ Symbol("Cuboid");
|
|
12254
13128
|
var Cube = /* @__PURE__ */ Symbol("Cube");
|
|
@@ -12439,11 +13313,11 @@ var ModelRendererRegistry = class {
|
|
|
12439
13313
|
};
|
|
12440
13314
|
|
|
12441
13315
|
// lib/models/anglebar/geometry.ts
|
|
12442
|
-
import
|
|
12443
|
-
var { primitives, extrusions, geometries, modifiers, measurements } =
|
|
12444
|
-
var generalize =
|
|
12445
|
-
var { rectangle, roundedRectangle, polygon } =
|
|
12446
|
-
var profile = (shape49, height10) =>
|
|
13316
|
+
import jscad3 from "@jscad/modeling";
|
|
13317
|
+
var { primitives: primitives2, extrusions: extrusions2, geometries: geometries2, modifiers: modifiers2, measurements: measurements2 } = jscad3;
|
|
13318
|
+
var generalize = modifiers2.generalize;
|
|
13319
|
+
var { rectangle, roundedRectangle, polygon } = primitives2;
|
|
13320
|
+
var profile = (shape49, height10) => extrusions2.extrudeLinear({ height: height10 }, shape49);
|
|
12447
13321
|
function filletProfile(points, radii, width10, height10) {
|
|
12448
13322
|
const outline = [];
|
|
12449
13323
|
for (let i = 0; i < points.length; i++) {
|
|
@@ -12502,7 +13376,7 @@ function createAngleBarMesh(input) {
|
|
|
12502
13376
|
{ snap: true, triangulate: true },
|
|
12503
13377
|
createAngleBarGeom(input)
|
|
12504
13378
|
);
|
|
12505
|
-
const epsilon = Math.max(...
|
|
13379
|
+
const epsilon = Math.max(...measurements2.measureDimensions(geom)) * 1e-10;
|
|
12506
13380
|
const positions = [];
|
|
12507
13381
|
const indices = [];
|
|
12508
13382
|
const lookup = /* @__PURE__ */ new Map();
|
|
@@ -12516,7 +13390,7 @@ function createAngleBarMesh(input) {
|
|
|
12516
13390
|
}
|
|
12517
13391
|
return index;
|
|
12518
13392
|
};
|
|
12519
|
-
for (const poly of
|
|
13393
|
+
for (const poly of geometries2.geom3.toPolygons(geom)) {
|
|
12520
13394
|
for (let i = 1; i < poly.vertices.length - 1; i++) {
|
|
12521
13395
|
const a = poly.vertices[0], b = poly.vertices[i], c = poly.vertices[i + 1];
|
|
12522
13396
|
const u = b.map((x, j) => x - a[j]), v = c.map((x, j) => x - a[j]);
|
|
@@ -12549,7 +13423,7 @@ function register55(registry2) {
|
|
|
12549
13423
|
}
|
|
12550
13424
|
|
|
12551
13425
|
// lib/mechanical/indexedMeshToGeom3.ts
|
|
12552
|
-
import
|
|
13426
|
+
import jscad4 from "@jscad/modeling";
|
|
12553
13427
|
function indexedMeshToGeom3(mesh) {
|
|
12554
13428
|
const polygons = [];
|
|
12555
13429
|
for (let i = 0; i < mesh.indices.length; i += 3)
|
|
@@ -12560,7 +13434,7 @@ function indexedMeshToGeom3(mesh) {
|
|
|
12560
13434
|
mesh.positions[index * 3 + 2]
|
|
12561
13435
|
])
|
|
12562
13436
|
);
|
|
12563
|
-
return
|
|
13437
|
+
return jscad4.geometries.geom3.fromPoints(polygons);
|
|
12564
13438
|
}
|
|
12565
13439
|
|
|
12566
13440
|
// lib/models/ballbearing/mesh.ts
|
|
@@ -12689,11 +13563,11 @@ function createBallBearingMesh(input = {}, options = {}) {
|
|
|
12689
13563
|
[ri + 0.15 * (ro - ri), 0.5 * t],
|
|
12690
13564
|
[ro - 0.15 * (ro - ri), 0.5 * t]
|
|
12691
13565
|
];
|
|
12692
|
-
const
|
|
13566
|
+
const profile5 = sign === -1 ? shape49 : shape49.map(([r, z]) => [r, d.width - z]).reverse();
|
|
12693
13567
|
parts.push({
|
|
12694
13568
|
name: `${face2} ${sign < 0 ? "lower" : "upper"}`,
|
|
12695
13569
|
color: face2 === "sealed" ? "#252a30" : "#b5bbc3",
|
|
12696
|
-
mesh: revolve(
|
|
13570
|
+
mesh: revolve(profile5, segments)
|
|
12697
13571
|
});
|
|
12698
13572
|
}
|
|
12699
13573
|
return { ...combine(parts), parts };
|
|
@@ -12710,21 +13584,21 @@ function checkPrecision(lengths25) {
|
|
|
12710
13584
|
"Bearing dimensions exceed the renderer's numerical resolution"
|
|
12711
13585
|
);
|
|
12712
13586
|
}
|
|
12713
|
-
function revolve(
|
|
13587
|
+
function revolve(profile5, segments) {
|
|
12714
13588
|
const positions = [];
|
|
12715
13589
|
const indices = [];
|
|
12716
|
-
for (const [radius, z] of
|
|
13590
|
+
for (const [radius, z] of profile5)
|
|
12717
13591
|
for (let i = 0; i < segments; i++) {
|
|
12718
13592
|
const angle = i * Math.PI * 2 / segments;
|
|
12719
13593
|
const r = typeof radius === "number" ? radius : radius(angle);
|
|
12720
13594
|
positions.push(r * Math.cos(angle), r * Math.sin(angle), z);
|
|
12721
13595
|
}
|
|
12722
|
-
for (let j = 0; j <
|
|
13596
|
+
for (let j = 0; j < profile5.length; j++)
|
|
12723
13597
|
for (let i = 0; i < segments; i++) {
|
|
12724
13598
|
const a = j * segments + i;
|
|
12725
13599
|
const b = j * segments + (i + 1) % segments;
|
|
12726
|
-
const c = (j + 1) %
|
|
12727
|
-
const e = (j + 1) %
|
|
13600
|
+
const c = (j + 1) % profile5.length * segments + (i + 1) % segments;
|
|
13601
|
+
const e = (j + 1) % profile5.length * segments + i;
|
|
12728
13602
|
indices.push(a, b, c, a, c, e);
|
|
12729
13603
|
}
|
|
12730
13604
|
return { positions, indices };
|
|
@@ -12735,7 +13609,7 @@ function annularSector(inner, outer, z0, z1, start, end, segments) {
|
|
|
12735
13609
|
Math.ceil((end - start) / (2 * Math.PI) * segments)
|
|
12736
13610
|
);
|
|
12737
13611
|
const count = steps + 1;
|
|
12738
|
-
const
|
|
13612
|
+
const profile5 = [
|
|
12739
13613
|
[outer, z0],
|
|
12740
13614
|
[outer, z1],
|
|
12741
13615
|
[inner, z1],
|
|
@@ -12743,7 +13617,7 @@ function annularSector(inner, outer, z0, z1, start, end, segments) {
|
|
|
12743
13617
|
];
|
|
12744
13618
|
const positions = [];
|
|
12745
13619
|
const indices = [];
|
|
12746
|
-
for (const [r, z] of
|
|
13620
|
+
for (const [r, z] of profile5)
|
|
12747
13621
|
for (let i = 0; i <= steps; i++) {
|
|
12748
13622
|
const angle = start + (end - start) * i / steps;
|
|
12749
13623
|
positions.push(r * Math.cos(angle), r * Math.sin(angle), z);
|
|
@@ -12934,7 +13808,7 @@ function createBallTransferUnitMesh(input = {}) {
|
|
|
12934
13808
|
);
|
|
12935
13809
|
const segments = 96;
|
|
12936
13810
|
const latitude = 48;
|
|
12937
|
-
const
|
|
13811
|
+
const profile5 = [
|
|
12938
13812
|
[d.bodyRadius, 0],
|
|
12939
13813
|
[d.bodyRadius, d.flangeBottomZ],
|
|
12940
13814
|
[d.flangeRadius, d.flangeBottomZ],
|
|
@@ -12947,12 +13821,12 @@ function createBallTransferUnitMesh(input = {}) {
|
|
|
12947
13821
|
for (let j = 1; j < latitude; j++) {
|
|
12948
13822
|
const angle = j * Math.PI / latitude;
|
|
12949
13823
|
if ((angle - openingAngle) * d.socketRadius > resolution7)
|
|
12950
|
-
|
|
13824
|
+
profile5.push([
|
|
12951
13825
|
d.socketRadius * Math.sin(angle),
|
|
12952
13826
|
d.ballCenterZ + d.socketRadius * Math.cos(angle)
|
|
12953
13827
|
]);
|
|
12954
13828
|
}
|
|
12955
|
-
|
|
13829
|
+
profile5.push([0, d.socketBottomZ], [0, 0]);
|
|
12956
13830
|
const holes = d.mountingHoles.map(
|
|
12957
13831
|
({ x, y, diameter }) => circularProfile(x, y, diameter / 2, segments)
|
|
12958
13832
|
);
|
|
@@ -12960,7 +13834,7 @@ function createBallTransferUnitMesh(input = {}) {
|
|
|
12960
13834
|
const housing = joinProfileMeshes([
|
|
12961
13835
|
// Cap faces are triangulated with all openings, rather than covered by
|
|
12962
13836
|
// annular triangles and repaired afterward with Boolean subtraction.
|
|
12963
|
-
revolve2(
|
|
13837
|
+
revolve2(profile5, segments, /* @__PURE__ */ new Set([1, 3])),
|
|
12964
13838
|
cap(
|
|
12965
13839
|
flangeOutline,
|
|
12966
13840
|
[circularProfile(0, 0, d.bodyRadius, segments), ...holes],
|
|
@@ -12997,10 +13871,10 @@ function createBallTransferUnitMesh(input = {}) {
|
|
|
12997
13871
|
];
|
|
12998
13872
|
return { positions, indices, parts };
|
|
12999
13873
|
}
|
|
13000
|
-
function revolve2(
|
|
13874
|
+
function revolve2(profile5, segments, omittedEdges = /* @__PURE__ */ new Set()) {
|
|
13001
13875
|
const positions = [];
|
|
13002
13876
|
const indices = [];
|
|
13003
|
-
const rings =
|
|
13877
|
+
const rings = profile5.map(([radius, z]) => {
|
|
13004
13878
|
const start = positions.length / 3;
|
|
13005
13879
|
const count = radius === 0 ? 1 : segments;
|
|
13006
13880
|
for (let i = 0; i < count; i++) {
|
|
@@ -13282,11 +14156,11 @@ function register59(registry2) {
|
|
|
13282
14156
|
}
|
|
13283
14157
|
|
|
13284
14158
|
// lib/models/channelbar/geometry.ts
|
|
13285
|
-
import
|
|
13286
|
-
var { primitives:
|
|
13287
|
-
var generalize2 =
|
|
13288
|
-
var { rectangle: rectangle2, roundedRectangle: roundedRectangle2, polygon: polygon2 } =
|
|
13289
|
-
var profile2 = (shape49, height10) =>
|
|
14159
|
+
import jscad5 from "@jscad/modeling";
|
|
14160
|
+
var { primitives: primitives3, extrusions: extrusions3, geometries: geometries3, modifiers: modifiers3, measurements: measurements3 } = jscad5;
|
|
14161
|
+
var generalize2 = modifiers3.generalize;
|
|
14162
|
+
var { rectangle: rectangle2, roundedRectangle: roundedRectangle2, polygon: polygon2 } = primitives3;
|
|
14163
|
+
var profile2 = (shape49, height10) => extrusions3.extrudeLinear({ height: height10 }, shape49);
|
|
13290
14164
|
function filletProfile2(points, radii, width10, height10) {
|
|
13291
14165
|
const outline = [];
|
|
13292
14166
|
for (let i = 0; i < points.length; i++) {
|
|
@@ -13356,7 +14230,7 @@ function createChannelBarMesh(input) {
|
|
|
13356
14230
|
{ snap: true, triangulate: true },
|
|
13357
14231
|
createChannelBarGeom(input)
|
|
13358
14232
|
);
|
|
13359
|
-
const epsilon = Math.max(...
|
|
14233
|
+
const epsilon = Math.max(...measurements3.measureDimensions(geom)) * 1e-10;
|
|
13360
14234
|
const positions = [];
|
|
13361
14235
|
const indices = [];
|
|
13362
14236
|
const lookup = /* @__PURE__ */ new Map();
|
|
@@ -13370,7 +14244,7 @@ function createChannelBarMesh(input) {
|
|
|
13370
14244
|
}
|
|
13371
14245
|
return index;
|
|
13372
14246
|
};
|
|
13373
|
-
for (const poly of
|
|
14247
|
+
for (const poly of geometries3.geom3.toPolygons(geom)) {
|
|
13374
14248
|
for (let i = 1; i < poly.vertices.length - 1; i++) {
|
|
13375
14249
|
const a = poly.vertices[0], b = poly.vertices[i], c = poly.vertices[i + 1];
|
|
13376
14250
|
const u = b.map((x, j) => x - a[j]), v = c.map((x, j) => x - a[j]);
|
|
@@ -13403,10 +14277,10 @@ function register60(registry2) {
|
|
|
13403
14277
|
}
|
|
13404
14278
|
|
|
13405
14279
|
// lib/models/clampingshaftcollar/mesh.ts
|
|
13406
|
-
import
|
|
14280
|
+
import jscad7 from "@jscad/modeling";
|
|
13407
14281
|
|
|
13408
14282
|
// lib/mechanical/shaft-mount-geometry.ts
|
|
13409
|
-
import
|
|
14283
|
+
import jscad6 from "@jscad/modeling";
|
|
13410
14284
|
var bodySegments = 64;
|
|
13411
14285
|
var threadSegments = 24;
|
|
13412
14286
|
var samplesPerTurn = 12;
|
|
@@ -13449,22 +14323,22 @@ function createAnnularSleeve({
|
|
|
13449
14323
|
[chamfer, boreARadius, true],
|
|
13450
14324
|
[0, boreARadius + chamfer, true]
|
|
13451
14325
|
];
|
|
13452
|
-
const
|
|
14326
|
+
const profile5 = raw.filter(
|
|
13453
14327
|
([z, r], i) => i === 0 || z !== raw[i - 1][0] || r !== raw[i - 1][1]
|
|
13454
14328
|
);
|
|
13455
14329
|
const positions = [];
|
|
13456
14330
|
const indices = [];
|
|
13457
|
-
for (const [z, r, isBore] of
|
|
14331
|
+
for (const [z, r, isBore] of profile5)
|
|
13458
14332
|
for (let i = 0; i < bodySegments; i++) {
|
|
13459
14333
|
const angle = (i + (isBore ? 0.5 : 0)) * Math.PI * 2 / bodySegments;
|
|
13460
14334
|
const radius = isBore ? r / cosine : r;
|
|
13461
14335
|
positions.push(radius * Math.cos(angle), radius * Math.sin(angle), z);
|
|
13462
14336
|
}
|
|
13463
|
-
for (let row = 0; row <
|
|
14337
|
+
for (let row = 0; row < profile5.length; row++)
|
|
13464
14338
|
for (let i = 0; i < bodySegments; i++) {
|
|
13465
14339
|
const next = (i + 1) % bodySegments;
|
|
13466
14340
|
const a = row * bodySegments + i, b = row * bodySegments + next;
|
|
13467
|
-
const c = (row + 1) %
|
|
14341
|
+
const c = (row + 1) % profile5.length * bodySegments + next, d = (row + 1) % profile5.length * bodySegments + i;
|
|
13468
14342
|
indices.push(a, b, c, a, c, d);
|
|
13469
14343
|
}
|
|
13470
14344
|
return indexedMeshToGeom3({ positions, indices });
|
|
@@ -13522,10 +14396,10 @@ function createMountingHoleCutter(hole) {
|
|
|
13522
14396
|
function subtractShaftMountParts(body, ...cutters) {
|
|
13523
14397
|
const factor = 100;
|
|
13524
14398
|
const scaled = [body, ...cutters].map(
|
|
13525
|
-
(geometry) =>
|
|
14399
|
+
(geometry) => jscad6.transforms.scale([factor, factor, factor], geometry)
|
|
13526
14400
|
);
|
|
13527
|
-
const result =
|
|
13528
|
-
return
|
|
14401
|
+
const result = jscad6.booleans.subtract(scaled[0], ...scaled.slice(1));
|
|
14402
|
+
return jscad6.transforms.scale([1 / factor, 1 / factor, 1 / factor], result);
|
|
13529
14403
|
}
|
|
13530
14404
|
function finishShaftMountMesh(geometry) {
|
|
13531
14405
|
const positions = [];
|
|
@@ -13551,7 +14425,7 @@ function finishShaftMountMesh(geometry) {
|
|
|
13551
14425
|
vertices.set(key, [...vertices.get(key) ?? [], index]);
|
|
13552
14426
|
return index;
|
|
13553
14427
|
};
|
|
13554
|
-
const polygons =
|
|
14428
|
+
const polygons = jscad6.geometries.geom3.toPolygons(geometry).map(
|
|
13555
14429
|
(polygon4) => polygon4.vertices.map(weld).filter((id, i, ids) => id !== ids[(i + ids.length - 1) % ids.length])
|
|
13556
14430
|
).map((ids) => [...new Set(ids)]).filter((ids) => ids.length >= 3).filter((ids) => {
|
|
13557
14431
|
let longest = 0;
|
|
@@ -13574,11 +14448,11 @@ function finishShaftMountMesh(geometry) {
|
|
|
13574
14448
|
return Math.hypot(...delta.map((v, axis) => v - t * direction[axis])) >= tolerance;
|
|
13575
14449
|
});
|
|
13576
14450
|
});
|
|
13577
|
-
const
|
|
14451
|
+
const edgeKey2 = (a, b) => `${Math.min(a, b)},${Math.max(a, b)}`;
|
|
13578
14452
|
const edges = /* @__PURE__ */ new Map();
|
|
13579
14453
|
for (const polygon4 of polygons)
|
|
13580
14454
|
for (let i = 0; i < polygon4.length; i++) {
|
|
13581
|
-
const a = polygon4[i], b = polygon4[(i + 1) % polygon4.length], key =
|
|
14455
|
+
const a = polygon4[i], b = polygon4[(i + 1) % polygon4.length], key = edgeKey2(a, b);
|
|
13582
14456
|
const edge = edges.get(key) ?? { a, b, count: 0 };
|
|
13583
14457
|
edge.count++;
|
|
13584
14458
|
edges.set(key, edge);
|
|
@@ -13663,7 +14537,7 @@ function createClampingShaftCollarMesh(input) {
|
|
|
13663
14537
|
});
|
|
13664
14538
|
const s = dimensions5.split;
|
|
13665
14539
|
const epsilon = 1e-4;
|
|
13666
|
-
const slit =
|
|
14540
|
+
const slit = jscad7.primitives.cuboid({
|
|
13667
14541
|
size: [
|
|
13668
14542
|
s.xMax - s.xMin + epsilon,
|
|
13669
14543
|
s.yMax - s.yMin,
|
|
@@ -14238,7 +15112,7 @@ function createFlangedBushingMesh(input) {
|
|
|
14238
15112
|
const ri = d.innerDiameter / 2;
|
|
14239
15113
|
const ro = d.outerDiameter / 2;
|
|
14240
15114
|
const rf = d.flangeDiameter / 2;
|
|
14241
|
-
const
|
|
15115
|
+
const profile5 = [
|
|
14242
15116
|
[rf, 0],
|
|
14243
15117
|
[rf, d.shoulderZ],
|
|
14244
15118
|
[ro, d.shoulderZ],
|
|
@@ -14249,14 +15123,14 @@ function createFlangedBushingMesh(input) {
|
|
|
14249
15123
|
const segments = 96;
|
|
14250
15124
|
const positions = [];
|
|
14251
15125
|
const indices = [];
|
|
14252
|
-
for (const [radius, z] of
|
|
15126
|
+
for (const [radius, z] of profile5)
|
|
14253
15127
|
for (let i = 0; i < segments; i++) {
|
|
14254
15128
|
const angle = i * Math.PI * 2 / segments;
|
|
14255
15129
|
positions.push(radius * Math.cos(angle), radius * Math.sin(angle), z);
|
|
14256
15130
|
}
|
|
14257
|
-
for (let ring = 0; ring <
|
|
15131
|
+
for (let ring = 0; ring < profile5.length; ring++) {
|
|
14258
15132
|
const a = ring * segments;
|
|
14259
|
-
const b = (ring + 1) %
|
|
15133
|
+
const b = (ring + 1) % profile5.length * segments;
|
|
14260
15134
|
for (let i = 0; i < segments; i++) {
|
|
14261
15135
|
const next = (i + 1) % segments;
|
|
14262
15136
|
indices.push(a + i, a + next, b + next, a + i, b + next, b + i);
|
|
@@ -14401,15 +15275,15 @@ function register67(registry2) {
|
|
|
14401
15275
|
}
|
|
14402
15276
|
|
|
14403
15277
|
// lib/models/flatcableclip/geometry.ts
|
|
14404
|
-
import
|
|
15278
|
+
import jscad8 from "@jscad/modeling";
|
|
14405
15279
|
var {
|
|
14406
|
-
primitives:
|
|
14407
|
-
extrusions:
|
|
14408
|
-
transforms,
|
|
14409
|
-
booleans,
|
|
14410
|
-
geometries:
|
|
14411
|
-
measurements:
|
|
14412
|
-
} =
|
|
15280
|
+
primitives: primitives4,
|
|
15281
|
+
extrusions: extrusions4,
|
|
15282
|
+
transforms: transforms2,
|
|
15283
|
+
booleans: booleans2,
|
|
15284
|
+
geometries: geometries4,
|
|
15285
|
+
measurements: measurements4
|
|
15286
|
+
} = jscad8;
|
|
14413
15287
|
function createFlatCableClipSolid(input) {
|
|
14414
15288
|
const p = flatCableClipModelPropsSchema.parse(input);
|
|
14415
15289
|
const legOuter = p.innerWidth / 2 + p.thickness, half = legOuter + p.footLength;
|
|
@@ -14427,25 +15301,25 @@ function createFlatCableClipSolid(input) {
|
|
|
14427
15301
|
[-legOuter, p.thickness],
|
|
14428
15302
|
[-half, p.thickness]
|
|
14429
15303
|
];
|
|
14430
|
-
const bridge =
|
|
15304
|
+
const bridge = transforms2.translate(
|
|
14431
15305
|
[0, p.depth / 2, 0],
|
|
14432
|
-
|
|
15306
|
+
transforms2.rotateX(
|
|
14433
15307
|
Math.PI / 2,
|
|
14434
|
-
|
|
15308
|
+
extrusions4.extrudeLinear(
|
|
14435
15309
|
{ height: p.depth },
|
|
14436
|
-
|
|
15310
|
+
primitives4.polygon({ points })
|
|
14437
15311
|
)
|
|
14438
15312
|
)
|
|
14439
15313
|
);
|
|
14440
15314
|
const bores = [-1, 1].map(
|
|
14441
|
-
(sign) =>
|
|
15315
|
+
(sign) => primitives4.cylinder({
|
|
14442
15316
|
radius: p.holeDiameter / 2,
|
|
14443
15317
|
height: p.thickness + 2,
|
|
14444
15318
|
center: [sign * p.holePitch / 2, 0, p.thickness / 2],
|
|
14445
15319
|
segments: 96
|
|
14446
15320
|
})
|
|
14447
15321
|
);
|
|
14448
|
-
return
|
|
15322
|
+
return booleans2.subtract(bridge, ...bores);
|
|
14449
15323
|
}
|
|
14450
15324
|
function createFlatCableClipMesh(input) {
|
|
14451
15325
|
const p = flatCableClipModelPropsSchema.parse(input);
|
|
@@ -14456,8 +15330,8 @@ function createFlatCableClipMesh(input) {
|
|
|
14456
15330
|
[0, p.thickness, p.innerHeight, p.innerHeight + p.thickness]
|
|
14457
15331
|
];
|
|
14458
15332
|
const geom = createFlatCableClipSolid(p);
|
|
14459
|
-
const tolerance = Math.max(...
|
|
14460
|
-
const polygons =
|
|
15333
|
+
const tolerance = Math.max(...measurements4.measureDimensions(geom)) * 1e-5;
|
|
15334
|
+
const polygons = geometries4.geom3.toPolygons(geom).map(
|
|
14461
15335
|
(poly) => poly.vertices.map(
|
|
14462
15336
|
(point) => point.map((value, axis) => {
|
|
14463
15337
|
const nearest = planes[axis].reduce(
|
|
@@ -14467,7 +15341,7 @@ function createFlatCableClipMesh(input) {
|
|
|
14467
15341
|
})
|
|
14468
15342
|
)
|
|
14469
15343
|
);
|
|
14470
|
-
return finishShaftMountMesh(
|
|
15344
|
+
return finishShaftMountMesh(geometries4.geom3.fromPoints(polygons));
|
|
14471
15345
|
}
|
|
14472
15346
|
function createFlatCableClipGeom(input) {
|
|
14473
15347
|
return indexedMeshToGeom3(createFlatCableClipMesh(input));
|
|
@@ -16370,7 +17244,7 @@ function register79(registry2) {
|
|
|
16370
17244
|
}
|
|
16371
17245
|
|
|
16372
17246
|
// lib/utils/nemaMotorAssemblyGeometry.ts
|
|
16373
|
-
import
|
|
17247
|
+
import jscad9 from "@jscad/modeling";
|
|
16374
17248
|
function nema34AssemblyCenters(p) {
|
|
16375
17249
|
const edge = p.bodyWidth / 2;
|
|
16376
17250
|
return [-1, 1].flatMap(
|
|
@@ -16380,16 +17254,16 @@ function nema34AssemblyCenters(p) {
|
|
|
16380
17254
|
);
|
|
16381
17255
|
}
|
|
16382
17256
|
function cutNema34FrontRecesses(geometry, p) {
|
|
16383
|
-
return
|
|
17257
|
+
return jscad9.booleans.subtract(
|
|
16384
17258
|
geometry,
|
|
16385
17259
|
...nema34AssemblyCenters(p).flatMap(([x, y]) => [
|
|
16386
|
-
|
|
17260
|
+
jscad9.primitives.cylinder({
|
|
16387
17261
|
radius: 1.6,
|
|
16388
17262
|
height: p.frontCapLength + 0.2,
|
|
16389
17263
|
center: [x, y, -p.frontCapLength / 2],
|
|
16390
17264
|
segments: 32
|
|
16391
17265
|
}),
|
|
16392
|
-
|
|
17266
|
+
jscad9.primitives.cylinder({
|
|
16393
17267
|
radius: 5,
|
|
16394
17268
|
height: Math.min(4, p.frontCapLength / 2) + 0.1,
|
|
16395
17269
|
center: [
|
|
@@ -16403,8 +17277,8 @@ function cutNema34FrontRecesses(geometry, p) {
|
|
|
16403
17277
|
);
|
|
16404
17278
|
}
|
|
16405
17279
|
function createNema34FrontScrews(p) {
|
|
16406
|
-
const head =
|
|
16407
|
-
|
|
17280
|
+
const head = jscad9.booleans.subtract(
|
|
17281
|
+
jscad9.primitives.ellipsoid({
|
|
16408
17282
|
radius: [3.2, 3.2, 1.5],
|
|
16409
17283
|
center: [0, 0, -1.8],
|
|
16410
17284
|
segments: 32
|
|
@@ -16413,22 +17287,22 @@ function createNema34FrontScrews(p) {
|
|
|
16413
17287
|
[3.7, 0.8, 1.1],
|
|
16414
17288
|
[0.8, 3.7, 1.1]
|
|
16415
17289
|
].map(
|
|
16416
|
-
(size) =>
|
|
17290
|
+
(size) => jscad9.primitives.cuboid({
|
|
16417
17291
|
size,
|
|
16418
17292
|
center: [0, 0, -0.8]
|
|
16419
17293
|
})
|
|
16420
17294
|
)
|
|
16421
17295
|
);
|
|
16422
17296
|
return nema34AssemblyCenters(p).map(
|
|
16423
|
-
([x, y]) =>
|
|
17297
|
+
([x, y]) => jscad9.transforms.translate([x, y, 0], head)
|
|
16424
17298
|
);
|
|
16425
17299
|
}
|
|
16426
17300
|
|
|
16427
17301
|
// lib/NemaMotor.tsx
|
|
16428
|
-
import
|
|
17302
|
+
import jscad11 from "@jscad/modeling";
|
|
16429
17303
|
|
|
16430
17304
|
// lib/utils/nemaMotorWireGeometry.ts
|
|
16431
|
-
import
|
|
17305
|
+
import jscad10 from "@jscad/modeling";
|
|
16432
17306
|
|
|
16433
17307
|
// lib/utils/nemaMotorParameters.ts
|
|
16434
17308
|
var resolveNemaMotorProps = nemaMotorModelPropsSchema.parse.bind(nemaMotorModelPropsSchema);
|
|
@@ -16439,12 +17313,12 @@ function createNemaMotorWireGeometry(input) {
|
|
|
16439
17313
|
if (p.noWires) return [];
|
|
16440
17314
|
const { position } = getNemaMotorReferencePoints(p).wireside;
|
|
16441
17315
|
const angle = p.wireSideAngle * Math.PI / 180;
|
|
16442
|
-
const place = (geometry) =>
|
|
17316
|
+
const place = (geometry) => jscad10.transforms.translate(
|
|
16443
17317
|
[position.x, position.y, position.z],
|
|
16444
|
-
|
|
17318
|
+
jscad10.transforms.rotateZ(angle, geometry)
|
|
16445
17319
|
);
|
|
16446
17320
|
if (p.wireStubs) {
|
|
16447
|
-
const
|
|
17321
|
+
const colors2 = [
|
|
16448
17322
|
"#d53f3f",
|
|
16449
17323
|
"#2463af",
|
|
16450
17324
|
"#3b934b",
|
|
@@ -16455,17 +17329,17 @@ function createNemaMotorWireGeometry(input) {
|
|
|
16455
17329
|
"#803e91"
|
|
16456
17330
|
];
|
|
16457
17331
|
const wires = Array.from({ length: p.wireCount }, (_, i) => ({
|
|
16458
|
-
color:
|
|
17332
|
+
color: colors2[i],
|
|
16459
17333
|
geometry: place(
|
|
16460
|
-
|
|
17334
|
+
jscad10.transforms.translate(
|
|
16461
17335
|
[
|
|
16462
17336
|
(p.wireLength - 0.15) / 2,
|
|
16463
17337
|
(i - (p.wireCount - 1) / 2) * p.wireDiameter * 1.5,
|
|
16464
17338
|
0
|
|
16465
17339
|
],
|
|
16466
|
-
|
|
17340
|
+
jscad10.transforms.rotateY(
|
|
16467
17341
|
Math.PI / 2,
|
|
16468
|
-
|
|
17342
|
+
jscad10.primitives.cylinder({
|
|
16469
17343
|
height: p.wireLength + 0.15,
|
|
16470
17344
|
radius: p.wireDiameter / 2,
|
|
16471
17345
|
segments: 24
|
|
@@ -16478,7 +17352,7 @@ function createNemaMotorWireGeometry(input) {
|
|
|
16478
17352
|
wires.unshift({
|
|
16479
17353
|
color: "#252830",
|
|
16480
17354
|
geometry: place(
|
|
16481
|
-
|
|
17355
|
+
jscad10.primitives.roundedCuboid({
|
|
16482
17356
|
size: [3, p.wireCount * p.wireDiameter * 1.5 + 3, 6],
|
|
16483
17357
|
center: [0.8, 0, 0],
|
|
16484
17358
|
roundRadius: 1,
|
|
@@ -16493,12 +17367,12 @@ function createNemaMotorWireGeometry(input) {
|
|
|
16493
17367
|
const wall = pitch === 2 ? 0.6 : 0.3;
|
|
16494
17368
|
const contactLength = pitch === 2 ? 3.4 : 2.4;
|
|
16495
17369
|
const contactSize = pitch === 2 ? 0.5 : 0.3;
|
|
16496
|
-
const shell =
|
|
16497
|
-
|
|
17370
|
+
const shell = jscad10.booleans.subtract(
|
|
17371
|
+
jscad10.primitives.cuboid({
|
|
16498
17372
|
size: [matingDepth + 0.1, bodyWidth, bodyHeight],
|
|
16499
17373
|
center: [(matingDepth - 0.1) / 2, 0, 0]
|
|
16500
17374
|
}),
|
|
16501
|
-
|
|
17375
|
+
jscad10.primitives.cuboid({
|
|
16502
17376
|
size: [matingDepth - 0.5, bodyWidth - 2 * wall, bodyHeight - 2 * wall],
|
|
16503
17377
|
center: [matingDepth / 2 + 0.55, 0, 0]
|
|
16504
17378
|
})
|
|
@@ -16508,7 +17382,7 @@ function createNemaMotorWireGeometry(input) {
|
|
|
16508
17382
|
...Array.from({ length: pinCount }, (_, i) => ({
|
|
16509
17383
|
color: "#b8bec6",
|
|
16510
17384
|
geometry: place(
|
|
16511
|
-
|
|
17385
|
+
jscad10.primitives.cuboid({
|
|
16512
17386
|
size: [contactLength, contactSize, contactSize],
|
|
16513
17387
|
center: [contactLength / 2, (i - (pinCount - 1) / 2) * pitch, 0]
|
|
16514
17388
|
})
|
|
@@ -16556,19 +17430,25 @@ var roundedFace = (width10, radius) => {
|
|
|
16556
17430
|
})
|
|
16557
17431
|
);
|
|
16558
17432
|
};
|
|
16559
|
-
var steppedFace = (width10, chamfer) => {
|
|
17433
|
+
var steppedFace = (width10, chamfer, recessRadius, filletRadius) => {
|
|
16560
17434
|
if (chamfer === 0) return face(width10, 0);
|
|
16561
17435
|
const h2 = width10 / 2, c = chamfer / Math.SQRT2, r = Math.min(4, c / 4);
|
|
16562
17436
|
const corner = [];
|
|
16563
|
-
const arc = (x, y, from, to) => {
|
|
17437
|
+
const arc = (x, y, radius, from, to) => {
|
|
17438
|
+
if (radius === 0) {
|
|
17439
|
+
corner.push([x, y]);
|
|
17440
|
+
return;
|
|
17441
|
+
}
|
|
16564
17442
|
for (let i = 0; i <= 12; i++) {
|
|
16565
17443
|
const a = (from + (to - from) * i / 12) * Math.PI / 180;
|
|
16566
|
-
corner.push([x +
|
|
17444
|
+
corner.push([x + radius * Math.cos(a), y + radius * Math.sin(a)]);
|
|
16567
17445
|
}
|
|
16568
17446
|
};
|
|
16569
|
-
|
|
16570
|
-
|
|
16571
|
-
arc(h2 -
|
|
17447
|
+
const convex = filletRadius ?? r;
|
|
17448
|
+
const concave = recessRadius ?? r;
|
|
17449
|
+
arc(h2 - c - convex, h2 - convex, convex, 90, 0);
|
|
17450
|
+
arc(h2 - c + concave, h2 - c + concave, concave, 180, 270);
|
|
17451
|
+
arc(h2 - convex, h2 - c - convex, convex, 90, 0);
|
|
16572
17452
|
return [0, 1, 2, 3].flatMap(
|
|
16573
17453
|
(i) => corner.map(([x, y]) => {
|
|
16574
17454
|
const a = -i * Math.PI / 2;
|
|
@@ -16589,12 +17469,18 @@ function createNemaMotorSections(input) {
|
|
|
16589
17469
|
p.bodyWidth,
|
|
16590
17470
|
p.faceCornerChamfer
|
|
16591
17471
|
);
|
|
16592
|
-
const
|
|
16593
|
-
const core = profile6(p.bodyWidth, p.bodyCornerChamfer);
|
|
16594
|
-
const rear = profile6(
|
|
17472
|
+
const core = p.stepped ? steppedFace(
|
|
16595
17473
|
p.bodyWidth,
|
|
16596
|
-
p.
|
|
16597
|
-
|
|
17474
|
+
p.bodyCornerChamfer,
|
|
17475
|
+
p.bodyCornerRecessRadius,
|
|
17476
|
+
p.bodyCornerFilletRadius
|
|
17477
|
+
) : face(p.bodyWidth, p.bodyCornerChamfer);
|
|
17478
|
+
const rear = p.rearStepped ? steppedFace(
|
|
17479
|
+
p.bodyWidth,
|
|
17480
|
+
p.rearCornerChamfer,
|
|
17481
|
+
p.rearCornerRecessRadius,
|
|
17482
|
+
p.rearCornerFilletRadius
|
|
17483
|
+
) : face(p.bodyWidth, p.rearCornerChamfer);
|
|
16598
17484
|
const h2 = p.mountingHoleSpacing / 2;
|
|
16599
17485
|
const centers = [
|
|
16600
17486
|
[-h2, -h2],
|
|
@@ -16612,9 +17498,10 @@ function createNemaMotorSections(input) {
|
|
|
16612
17498
|
if (p.backFacePlain) {
|
|
16613
17499
|
add("rearCap", rear, -p.bodyLength, -p.bodyLength + p.rearCapLength);
|
|
16614
17500
|
} else {
|
|
16615
|
-
const
|
|
16616
|
-
const
|
|
16617
|
-
|
|
17501
|
+
const halfPitchX = p.backFaceHoleSpacingX / 2;
|
|
17502
|
+
const halfPitchY = p.backFaceHoleSpacingY / 2;
|
|
17503
|
+
const rearHoles = [-halfPitchX, halfPitchX].flatMap(
|
|
17504
|
+
(x) => [-halfPitchY, halfPitchY].map(
|
|
16618
17505
|
(y) => circle(p.backFaceHoleDiameter / 2, x, y)
|
|
16619
17506
|
)
|
|
16620
17507
|
);
|
|
@@ -16639,12 +17526,12 @@ function createNemaMotorSections(input) {
|
|
|
16639
17526
|
else {
|
|
16640
17527
|
const cut = r - p.shaftFlatDepth;
|
|
16641
17528
|
const angle = Math.acos(cut / r);
|
|
16642
|
-
const
|
|
17529
|
+
const profile5 = Array.from({ length: 97 }, (_, i) => {
|
|
16643
17530
|
const a = angle + (2 * Math.PI - 2 * angle) * i / 96;
|
|
16644
17531
|
return [r * Math.cos(a), r * Math.sin(a)];
|
|
16645
17532
|
});
|
|
16646
17533
|
const rotation = p.shaftFlatAngle * Math.PI / 180;
|
|
16647
|
-
const d =
|
|
17534
|
+
const d = profile5.map(([x, y]) => [
|
|
16648
17535
|
x * Math.cos(rotation) - y * Math.sin(rotation),
|
|
16649
17536
|
x * Math.sin(rotation) + y * Math.cos(rotation)
|
|
16650
17537
|
]);
|
|
@@ -16655,7 +17542,7 @@ function createNemaMotorSections(input) {
|
|
|
16655
17542
|
}
|
|
16656
17543
|
|
|
16657
17544
|
// lib/NemaMotor.tsx
|
|
16658
|
-
var generalize3 =
|
|
17545
|
+
var generalize3 = jscad11.modifiers.generalize;
|
|
16659
17546
|
function NemaMotor({
|
|
16660
17547
|
bodyColor = "#242830",
|
|
16661
17548
|
capColor = "#aeb5bd",
|
|
@@ -16664,7 +17551,7 @@ function NemaMotor({
|
|
|
16664
17551
|
...props
|
|
16665
17552
|
}) {
|
|
16666
17553
|
const p = resolveNemaMotorProps(props);
|
|
16667
|
-
const screw = p.backFaceScrews ?
|
|
17554
|
+
const screw = p.backFaceScrews ? jscad11.transforms.rotateX(
|
|
16668
17555
|
Math.PI,
|
|
16669
17556
|
createHexSocketBoltGeom({
|
|
16670
17557
|
metricSize: p.backFaceScrewSize,
|
|
@@ -16672,19 +17559,20 @@ function NemaMotor({
|
|
|
16672
17559
|
showThreads: false
|
|
16673
17560
|
})
|
|
16674
17561
|
) : void 0;
|
|
16675
|
-
const
|
|
17562
|
+
const halfPitchX = p.backFaceHoleSpacingX / 2;
|
|
17563
|
+
const halfPitchY = p.backFaceHoleSpacingY / 2;
|
|
16676
17564
|
return /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
16677
17565
|
createNemaMotorSections(p).map((section, index) => {
|
|
16678
|
-
const outline =
|
|
16679
|
-
const
|
|
17566
|
+
const outline = jscad11.geometries.geom2.fromPoints(section.outline);
|
|
17567
|
+
const profile5 = section.holes.length ? jscad11.booleans.subtract(
|
|
16680
17568
|
outline,
|
|
16681
|
-
...section.holes.map((h2) =>
|
|
17569
|
+
...section.holes.map((h2) => jscad11.geometries.geom2.fromPoints(h2))
|
|
16682
17570
|
) : outline;
|
|
16683
|
-
let geometry =
|
|
17571
|
+
let geometry = jscad11.transforms.translate(
|
|
16684
17572
|
[0, 0, section.zMin],
|
|
16685
|
-
|
|
17573
|
+
jscad11.extrusions.extrudeLinear(
|
|
16686
17574
|
{ height: section.zMax - section.zMin },
|
|
16687
|
-
|
|
17575
|
+
profile5
|
|
16688
17576
|
)
|
|
16689
17577
|
);
|
|
16690
17578
|
if (p.nemaSize === 34 && section.name === "frontCap")
|
|
@@ -16717,8 +17605,8 @@ function NemaMotor({
|
|
|
16717
17605
|
},
|
|
16718
17606
|
`front-screw-${index}`
|
|
16719
17607
|
)),
|
|
16720
|
-
screw && [-
|
|
16721
|
-
(x) => [-
|
|
17608
|
+
screw && [-halfPitchX, halfPitchX].flatMap(
|
|
17609
|
+
(x) => [-halfPitchY, halfPitchY].map((y) => /* @__PURE__ */ jsx(
|
|
16722
17610
|
Colorize,
|
|
16723
17611
|
{
|
|
16724
17612
|
material: componentMaterials.steel,
|
|
@@ -16726,7 +17614,7 @@ function NemaMotor({
|
|
|
16726
17614
|
children: /* @__PURE__ */ jsx(
|
|
16727
17615
|
Custom,
|
|
16728
17616
|
{
|
|
16729
|
-
geometry:
|
|
17617
|
+
geometry: jscad11.transforms.translate(
|
|
16730
17618
|
[x, y, -p.bodyLength],
|
|
16731
17619
|
generalize3({ simplify: true }, screw)
|
|
16732
17620
|
)
|
|
@@ -17216,19 +18104,19 @@ function register83(registry2) {
|
|
|
17216
18104
|
}
|
|
17217
18105
|
|
|
17218
18106
|
// lib/models/perforatedsheet/geometry.ts
|
|
17219
|
-
import
|
|
18107
|
+
import jscad12 from "@jscad/modeling";
|
|
17220
18108
|
var {
|
|
17221
|
-
booleans:
|
|
17222
|
-
primitives:
|
|
17223
|
-
extrusions:
|
|
17224
|
-
geometries:
|
|
17225
|
-
modifiers:
|
|
17226
|
-
measurements:
|
|
17227
|
-
} =
|
|
17228
|
-
var generalize4 =
|
|
17229
|
-
var { subtract } =
|
|
17230
|
-
var { rectangle: rectangle3, roundedRectangle: roundedRectangle3, circle: circle2 } =
|
|
17231
|
-
var profile3 = (shape49, height10) =>
|
|
18109
|
+
booleans: booleans3,
|
|
18110
|
+
primitives: primitives5,
|
|
18111
|
+
extrusions: extrusions5,
|
|
18112
|
+
geometries: geometries5,
|
|
18113
|
+
modifiers: modifiers4,
|
|
18114
|
+
measurements: measurements5
|
|
18115
|
+
} = jscad12;
|
|
18116
|
+
var generalize4 = modifiers4.generalize;
|
|
18117
|
+
var { subtract } = booleans3;
|
|
18118
|
+
var { rectangle: rectangle3, roundedRectangle: roundedRectangle3, circle: circle2 } = primitives5;
|
|
18119
|
+
var profile3 = (shape49, height10) => extrusions5.extrudeLinear({ height: height10 }, shape49);
|
|
17232
18120
|
function perforated(p) {
|
|
17233
18121
|
const holes = [];
|
|
17234
18122
|
const rows = Math.floor((p.width - 2 * p.edgeY) / p.pitchY + 1 + 1e-10);
|
|
@@ -17259,7 +18147,7 @@ function createPerforatedSheetMesh(input) {
|
|
|
17259
18147
|
{ snap: true, triangulate: true },
|
|
17260
18148
|
createPerforatedSheetGeom(input)
|
|
17261
18149
|
);
|
|
17262
|
-
const epsilon = Math.max(...
|
|
18150
|
+
const epsilon = Math.max(...measurements5.measureDimensions(geom)) * 1e-10;
|
|
17263
18151
|
const positions = [];
|
|
17264
18152
|
const indices = [];
|
|
17265
18153
|
const lookup = /* @__PURE__ */ new Map();
|
|
@@ -17273,7 +18161,7 @@ function createPerforatedSheetMesh(input) {
|
|
|
17273
18161
|
}
|
|
17274
18162
|
return index;
|
|
17275
18163
|
};
|
|
17276
|
-
for (const poly of
|
|
18164
|
+
for (const poly of geometries5.geom3.toPolygons(geom)) {
|
|
17277
18165
|
for (let i = 1; i < poly.vertices.length - 1; i++) {
|
|
17278
18166
|
const a = poly.vertices[0], b = poly.vertices[i], c = poly.vertices[i + 1];
|
|
17279
18167
|
const u = b.map((x, j) => x - a[j]), v = c.map((x, j) => x - a[j]);
|
|
@@ -17315,7 +18203,7 @@ function createPlainBushingMesh(input) {
|
|
|
17315
18203
|
const ri = d.innerDiameter / 2;
|
|
17316
18204
|
const ro = d.outerDiameter / 2;
|
|
17317
18205
|
const c = props.edgeChamfer;
|
|
17318
|
-
const
|
|
18206
|
+
const profile5 = c > 0 ? [
|
|
17319
18207
|
[d.endOuterDiameter / 2, 0],
|
|
17320
18208
|
[ro, c],
|
|
17321
18209
|
[ro, d.length - c],
|
|
@@ -17333,14 +18221,14 @@ function createPlainBushingMesh(input) {
|
|
|
17333
18221
|
const segments = 96;
|
|
17334
18222
|
const positions = [];
|
|
17335
18223
|
const indices = [];
|
|
17336
|
-
for (const [radius, z] of
|
|
18224
|
+
for (const [radius, z] of profile5)
|
|
17337
18225
|
for (let i = 0; i < segments; i++) {
|
|
17338
18226
|
const angle = i * Math.PI * 2 / segments;
|
|
17339
18227
|
positions.push(radius * Math.cos(angle), radius * Math.sin(angle), z);
|
|
17340
18228
|
}
|
|
17341
|
-
for (let ring = 0; ring <
|
|
18229
|
+
for (let ring = 0; ring < profile5.length; ring++) {
|
|
17342
18230
|
const a = ring * segments;
|
|
17343
|
-
const b = (ring + 1) %
|
|
18231
|
+
const b = (ring + 1) % profile5.length * segments;
|
|
17344
18232
|
for (let i = 0; i < segments; i++) {
|
|
17345
18233
|
const next = (i + 1) % segments;
|
|
17346
18234
|
indices.push(a + i, a + next, b + next, a + i, b + next, b + i);
|
|
@@ -17372,13 +18260,13 @@ function register85(registry2) {
|
|
|
17372
18260
|
}
|
|
17373
18261
|
|
|
17374
18262
|
// lib/models/pushfitplug/geometry.ts
|
|
17375
|
-
import
|
|
17376
|
-
var { primitives:
|
|
17377
|
-
var generalize5 =
|
|
17378
|
-
var { rectangle: rectangle4, roundedRectangle: roundedRectangle4, polygon: polygon3 } =
|
|
18263
|
+
import jscad13 from "@jscad/modeling";
|
|
18264
|
+
var { primitives: primitives6, extrusions: extrusions6, geometries: geometries6, modifiers: modifiers5, measurements: measurements6 } = jscad13;
|
|
18265
|
+
var generalize5 = modifiers5.generalize;
|
|
18266
|
+
var { rectangle: rectangle4, roundedRectangle: roundedRectangle4, polygon: polygon3 } = primitives6;
|
|
17379
18267
|
function createPushFitPlugGeom(input) {
|
|
17380
18268
|
const p = pushFitPlugModelPropsSchema.parse(input);
|
|
17381
|
-
return
|
|
18269
|
+
return extrusions6.extrudeRotate(
|
|
17382
18270
|
{ segments: 64 },
|
|
17383
18271
|
polygon3({
|
|
17384
18272
|
points: [
|
|
@@ -17397,7 +18285,7 @@ function createPushFitPlugMesh(input) {
|
|
|
17397
18285
|
{ snap: true, triangulate: true },
|
|
17398
18286
|
createPushFitPlugGeom(input)
|
|
17399
18287
|
);
|
|
17400
|
-
const epsilon = Math.max(...
|
|
18288
|
+
const epsilon = Math.max(...measurements6.measureDimensions(geom)) * 1e-10;
|
|
17401
18289
|
const positions = [];
|
|
17402
18290
|
const indices = [];
|
|
17403
18291
|
const lookup = /* @__PURE__ */ new Map();
|
|
@@ -17411,7 +18299,7 @@ function createPushFitPlugMesh(input) {
|
|
|
17411
18299
|
}
|
|
17412
18300
|
return index;
|
|
17413
18301
|
};
|
|
17414
|
-
for (const poly of
|
|
18302
|
+
for (const poly of geometries6.geom3.toPolygons(geom)) {
|
|
17415
18303
|
for (let i = 1; i < poly.vertices.length - 1; i++) {
|
|
17416
18304
|
const a = poly.vertices[0], b = poly.vertices[i], c = poly.vertices[i + 1];
|
|
17417
18305
|
const u = b.map((x, j) => x - a[j]), v = c.map((x, j) => x - a[j]);
|
|
@@ -17444,11 +18332,11 @@ function register86(registry2) {
|
|
|
17444
18332
|
}
|
|
17445
18333
|
|
|
17446
18334
|
// lib/models/rectangularbar/geometry.ts
|
|
17447
|
-
import
|
|
17448
|
-
var { primitives:
|
|
17449
|
-
var generalize6 =
|
|
17450
|
-
var { rectangle: rectangle5, roundedRectangle: roundedRectangle5 } =
|
|
17451
|
-
var profile4 = (shape49, height10) =>
|
|
18335
|
+
import jscad14 from "@jscad/modeling";
|
|
18336
|
+
var { primitives: primitives7, extrusions: extrusions7, geometries: geometries7, modifiers: modifiers6, measurements: measurements7 } = jscad14;
|
|
18337
|
+
var generalize6 = modifiers6.generalize;
|
|
18338
|
+
var { rectangle: rectangle5, roundedRectangle: roundedRectangle5 } = primitives7;
|
|
18339
|
+
var profile4 = (shape49, height10) => extrusions7.extrudeLinear({ height: height10 }, shape49);
|
|
17452
18340
|
var roundedRect = (width10, height10, radius) => radius ? roundedRectangle5({
|
|
17453
18341
|
size: [width10, height10],
|
|
17454
18342
|
roundRadius: radius,
|
|
@@ -17463,7 +18351,7 @@ function createRectangularBarMesh(input) {
|
|
|
17463
18351
|
{ snap: true, triangulate: true },
|
|
17464
18352
|
createRectangularBarGeom(input)
|
|
17465
18353
|
);
|
|
17466
|
-
const epsilon = Math.max(...
|
|
18354
|
+
const epsilon = Math.max(...measurements7.measureDimensions(geom)) * 1e-10;
|
|
17467
18355
|
const positions = [];
|
|
17468
18356
|
const indices = [];
|
|
17469
18357
|
const lookup = /* @__PURE__ */ new Map();
|
|
@@ -17477,7 +18365,7 @@ function createRectangularBarMesh(input) {
|
|
|
17477
18365
|
}
|
|
17478
18366
|
return index;
|
|
17479
18367
|
};
|
|
17480
|
-
for (const poly of
|
|
18368
|
+
for (const poly of geometries7.geom3.toPolygons(geom)) {
|
|
17481
18369
|
for (let i = 1; i < poly.vertices.length - 1; i++) {
|
|
17482
18370
|
const a = poly.vertices[0], b = poly.vertices[i], c = poly.vertices[i + 1];
|
|
17483
18371
|
const u = b.map((x, j) => x - a[j]), v = c.map((x, j) => x - a[j]);
|
|
@@ -17621,72 +18509,27 @@ function register88(registry2) {
|
|
|
17621
18509
|
registry2.register(model88);
|
|
17622
18510
|
}
|
|
17623
18511
|
|
|
17624
|
-
// lib/models/rectangulartube/
|
|
17625
|
-
import
|
|
17626
|
-
var {
|
|
17627
|
-
booleans: booleans3,
|
|
17628
|
-
primitives: primitives7,
|
|
17629
|
-
extrusions: extrusions7,
|
|
17630
|
-
geometries: geometries7,
|
|
17631
|
-
modifiers: modifiers6,
|
|
17632
|
-
measurements: measurements7
|
|
17633
|
-
} = jscad13;
|
|
17634
|
-
var generalize7 = modifiers6.generalize;
|
|
17635
|
-
var { subtract: subtract2 } = booleans3;
|
|
17636
|
-
var { rectangle: rectangle6, roundedRectangle: roundedRectangle6 } = primitives7;
|
|
17637
|
-
var profile5 = (shape49, height10) => extrusions7.extrudeLinear({ height: height10 }, shape49);
|
|
17638
|
-
var roundedRect2 = (width10, height10, radius) => radius ? roundedRectangle6({
|
|
18512
|
+
// lib/models/rectangulartube/profiles.ts
|
|
18513
|
+
import jscad15 from "@jscad/modeling";
|
|
18514
|
+
var roundedRectangle6 = (width10, height10, radius) => radius ? jscad15.primitives.roundedRectangle({
|
|
17639
18515
|
size: [width10, height10],
|
|
17640
18516
|
roundRadius: radius,
|
|
17641
18517
|
segments: 64
|
|
17642
|
-
}) :
|
|
17643
|
-
function
|
|
18518
|
+
}) : jscad15.primitives.rectangle({ size: [width10, height10] });
|
|
18519
|
+
function getRectangularTubeProfiles(input) {
|
|
17644
18520
|
const p = rectangularTubeModelPropsSchema.parse(input);
|
|
17645
|
-
|
|
17646
|
-
|
|
17647
|
-
|
|
17648
|
-
|
|
18521
|
+
const points = (geometry) => jscad15.geometries.geom2.toPoints(geometry);
|
|
18522
|
+
return {
|
|
18523
|
+
length: p.length,
|
|
18524
|
+
outerPoints: points(roundedRectangle6(p.width, p.height, p.outerRadius)),
|
|
18525
|
+
innerPoints: points(
|
|
18526
|
+
roundedRectangle6(
|
|
17649
18527
|
p.width - 2 * p.wallThickness,
|
|
17650
18528
|
p.height - 2 * p.wallThickness,
|
|
17651
18529
|
p.innerRadius
|
|
17652
18530
|
)
|
|
17653
|
-
)
|
|
17654
|
-
p.length
|
|
17655
|
-
);
|
|
17656
|
-
}
|
|
17657
|
-
function createRectangularTubeMesh(input) {
|
|
17658
|
-
const geom = generalize7(
|
|
17659
|
-
{ snap: true, triangulate: true },
|
|
17660
|
-
createRectangularTubeGeom(input)
|
|
17661
|
-
);
|
|
17662
|
-
const epsilon = Math.max(...measurements7.measureDimensions(geom)) * 1e-10;
|
|
17663
|
-
const positions = [];
|
|
17664
|
-
const indices = [];
|
|
17665
|
-
const lookup = /* @__PURE__ */ new Map();
|
|
17666
|
-
const vertex = (v) => {
|
|
17667
|
-
const key = v.map((x) => Math.round(x / epsilon)).join(",");
|
|
17668
|
-
let index = lookup.get(key);
|
|
17669
|
-
if (index === void 0) {
|
|
17670
|
-
index = positions.length / 3;
|
|
17671
|
-
positions.push(...v);
|
|
17672
|
-
lookup.set(key, index);
|
|
17673
|
-
}
|
|
17674
|
-
return index;
|
|
18531
|
+
)
|
|
17675
18532
|
};
|
|
17676
|
-
for (const poly of geometries7.geom3.toPolygons(geom)) {
|
|
17677
|
-
for (let i = 1; i < poly.vertices.length - 1; i++) {
|
|
17678
|
-
const a = poly.vertices[0], b = poly.vertices[i], c = poly.vertices[i + 1];
|
|
17679
|
-
const u = b.map((x, j) => x - a[j]), v = c.map((x, j) => x - a[j]);
|
|
17680
|
-
const area = Math.hypot(
|
|
17681
|
-
u[1] * v[2] - u[2] * v[1],
|
|
17682
|
-
u[2] * v[0] - u[0] * v[2],
|
|
17683
|
-
u[0] * v[1] - u[1] * v[0]
|
|
17684
|
-
);
|
|
17685
|
-
if (area > epsilon * epsilon)
|
|
17686
|
-
indices.push(vertex(a), vertex(b), vertex(c));
|
|
17687
|
-
}
|
|
17688
|
-
}
|
|
17689
|
-
return { positions, indices };
|
|
17690
18533
|
}
|
|
17691
18534
|
|
|
17692
18535
|
// lib/models/rectangulartube/RectangularTube.tsx
|
|
@@ -17694,7 +18537,27 @@ function RectangularTube({
|
|
|
17694
18537
|
color = "#929da9",
|
|
17695
18538
|
...props
|
|
17696
18539
|
}) {
|
|
17697
|
-
|
|
18540
|
+
const { length: length32, outerPoints, innerPoints } = getRectangularTubeProfiles(props);
|
|
18541
|
+
return /* @__PURE__ */ jsx(Colorize, { color, children: /* @__PURE__ */ jsxs(Subtract, { children: [
|
|
18542
|
+
/* @__PURE__ */ jsx(
|
|
18543
|
+
ExtrudeLinear,
|
|
18544
|
+
{
|
|
18545
|
+
height: length32,
|
|
18546
|
+
topOutlineName: "outer_top",
|
|
18547
|
+
bottomOutlineName: "outer_bottom",
|
|
18548
|
+
children: /* @__PURE__ */ jsx(Polygon, { points: outerPoints })
|
|
18549
|
+
}
|
|
18550
|
+
),
|
|
18551
|
+
/* @__PURE__ */ jsx(
|
|
18552
|
+
ExtrudeLinear,
|
|
18553
|
+
{
|
|
18554
|
+
height: length32,
|
|
18555
|
+
topOutlineName: "inner_top",
|
|
18556
|
+
bottomOutlineName: "inner_bottom",
|
|
18557
|
+
children: /* @__PURE__ */ jsx(Polygon, { points: innerPoints })
|
|
18558
|
+
}
|
|
18559
|
+
)
|
|
18560
|
+
] }) });
|
|
17698
18561
|
}
|
|
17699
18562
|
|
|
17700
18563
|
// lib/models/rectangulartube/register.tsx
|
|
@@ -17939,7 +18802,7 @@ function holeOutline(hole) {
|
|
|
17939
18802
|
function createSheetMetalMesh(input) {
|
|
17940
18803
|
const props = sheetMetalModelPropsSchema.parse(input);
|
|
17941
18804
|
const { width: width10, baseLength, flangeHeight, thickness } = props;
|
|
17942
|
-
const
|
|
18805
|
+
const profile5 = props.channel ? "channel" : props.angle ? "angle" : "plate";
|
|
17943
18806
|
const radius = props.insideBendRadius + thickness / 2;
|
|
17944
18807
|
const positions = [];
|
|
17945
18808
|
const indices = [];
|
|
@@ -17952,10 +18815,10 @@ function createSheetMetalMesh(input) {
|
|
|
17952
18815
|
addTriangle([vertices[0], vertices[1], vertices[2]], reverse);
|
|
17953
18816
|
addTriangle([vertices[0], vertices[2], vertices[3]], reverse);
|
|
17954
18817
|
};
|
|
17955
|
-
const panels =
|
|
18818
|
+
const panels = profile5 === "plate" ? ["base"] : profile5 === "angle" ? ["base", "right"] : ["base", "left", "right"];
|
|
17956
18819
|
for (const hole of props.holes) {
|
|
17957
18820
|
if (!panels.includes(hole.panel))
|
|
17958
|
-
throw new Error(`No ${hole.panel} panel on ${
|
|
18821
|
+
throw new Error(`No ${hole.panel} panel on ${profile5}`);
|
|
17959
18822
|
}
|
|
17960
18823
|
for (const panel of panels) {
|
|
17961
18824
|
const length32 = panel === "base" ? baseLength : flangeHeight;
|
|
@@ -18006,7 +18869,7 @@ function createSheetMetalMesh(input) {
|
|
|
18006
18869
|
for (const [loopIndex, loop] of loops.entries())
|
|
18007
18870
|
for (let i = 0; i < loop.length; i++) {
|
|
18008
18871
|
const a = loop[i], b = loop[(i + 1) % loop.length];
|
|
18009
|
-
if (loopIndex === 0 && a.u === b.u && (panel === "base" && (a.u > 0 &&
|
|
18872
|
+
if (loopIndex === 0 && a.u === b.u && (panel === "base" && (a.u > 0 && profile5 !== "plate" || a.u < 0 && profile5 === "channel") || panel !== "base" && a.u < 0))
|
|
18010
18873
|
continue;
|
|
18011
18874
|
addQuad(
|
|
18012
18875
|
[
|
|
@@ -18019,7 +18882,7 @@ function createSheetMetalMesh(input) {
|
|
|
18019
18882
|
);
|
|
18020
18883
|
}
|
|
18021
18884
|
}
|
|
18022
|
-
const sides =
|
|
18885
|
+
const sides = profile5 === "plate" ? [] : profile5 === "angle" ? [1] : [-1, 1];
|
|
18023
18886
|
for (const side of sides) {
|
|
18024
18887
|
const project = (angle, crossSection) => {
|
|
18025
18888
|
const r = radius - crossSection.offset;
|
|
@@ -18618,7 +19481,7 @@ function register100(registry2) {
|
|
|
18618
19481
|
}
|
|
18619
19482
|
|
|
18620
19483
|
// lib/models/tslotcoverstrip/geometry.ts
|
|
18621
|
-
import
|
|
19484
|
+
import jscad18 from "@jscad/modeling";
|
|
18622
19485
|
var {
|
|
18623
19486
|
primitives: primitives8,
|
|
18624
19487
|
extrusions: extrusions8,
|
|
@@ -18626,8 +19489,8 @@ var {
|
|
|
18626
19489
|
geometries: geometries8,
|
|
18627
19490
|
modifiers: modifiers7,
|
|
18628
19491
|
measurements: measurements8
|
|
18629
|
-
} =
|
|
18630
|
-
var
|
|
19492
|
+
} = jscad18;
|
|
19493
|
+
var generalize7 = modifiers7.generalize;
|
|
18631
19494
|
function createTSlotCoverStripGeom(input) {
|
|
18632
19495
|
const p = tSlotCoverStripModelPropsSchema.parse(input);
|
|
18633
19496
|
const w = p.width / 2;
|
|
@@ -18654,7 +19517,7 @@ function createTSlotCoverStripGeom(input) {
|
|
|
18654
19517
|
return extrusions8.extrudeLinear({ height: p.length }, outline);
|
|
18655
19518
|
}
|
|
18656
19519
|
function createTSlotCoverStripMesh(input) {
|
|
18657
|
-
const geom =
|
|
19520
|
+
const geom = generalize7(
|
|
18658
19521
|
{ snap: false, triangulate: true },
|
|
18659
19522
|
createTSlotCoverStripGeom(input)
|
|
18660
19523
|
);
|
|
@@ -18908,10 +19771,10 @@ function register104(registry2) {
|
|
|
18908
19771
|
}
|
|
18909
19772
|
|
|
18910
19773
|
// lib/models/ufl/geometry.ts
|
|
18911
|
-
import
|
|
19774
|
+
import jscad19 from "@jscad/modeling";
|
|
18912
19775
|
function createUflGeometries(input = {}) {
|
|
18913
19776
|
const d = getUflDimensions(input);
|
|
18914
|
-
const { booleans: booleans5, primitives: primitives9 } =
|
|
19777
|
+
const { booleans: booleans5, primitives: primitives9 } = jscad19;
|
|
18915
19778
|
const silver = "#bcbfc3";
|
|
18916
19779
|
const dielectric = "#eee9d5";
|
|
18917
19780
|
const gold = "#d9b45b";
|
|
@@ -19068,17 +19931,17 @@ var createWormGearMesh = (input) => {
|
|
|
19068
19931
|
fractions.push(fraction);
|
|
19069
19932
|
}
|
|
19070
19933
|
}
|
|
19071
|
-
const
|
|
19934
|
+
const profile5 = [];
|
|
19072
19935
|
for (let start = 0; start < props.starts; start++) {
|
|
19073
19936
|
for (const fraction of fractions) {
|
|
19074
19937
|
const distance2 = Math.min(fraction, 1 - fraction) * axialPitch;
|
|
19075
|
-
|
|
19938
|
+
profile5.push({
|
|
19076
19939
|
angle: (start + fraction) * Math.PI * 2 / props.starts,
|
|
19077
19940
|
radius: distance2 <= tipHalfWidth ? outsideRadius : distance2 >= rootHalfWidth ? rootRadius : pitchRadius + (toothThickness / 2 - distance2) / pressureTangent
|
|
19078
19941
|
});
|
|
19079
19942
|
}
|
|
19080
19943
|
}
|
|
19081
|
-
const count =
|
|
19944
|
+
const count = profile5.length;
|
|
19082
19945
|
const positions = [];
|
|
19083
19946
|
const indices = [];
|
|
19084
19947
|
const phase = props.phase % 360 * Math.PI / 180;
|
|
@@ -19086,7 +19949,7 @@ var createWormGearMesh = (input) => {
|
|
|
19086
19949
|
const ring = (z) => {
|
|
19087
19950
|
const first = positions.length / 3;
|
|
19088
19951
|
const rotation = phase + direction * (z / lead) * Math.PI * 2;
|
|
19089
|
-
for (const sample of
|
|
19952
|
+
for (const sample of profile5) {
|
|
19090
19953
|
const angle = sample.angle + rotation;
|
|
19091
19954
|
positions.push(
|
|
19092
19955
|
sample.radius * Math.cos(angle),
|
|
@@ -27589,185 +28452,6 @@ var Footprinter3d = ({ footprint }) => {
|
|
|
27589
28452
|
return null;
|
|
27590
28453
|
};
|
|
27591
28454
|
|
|
27592
|
-
// lib/vanilla/render.ts
|
|
27593
|
-
var isVNode = (n) => n && typeof n === "object" && "type" in n;
|
|
27594
|
-
var degToRad = (v) => {
|
|
27595
|
-
if (typeof v === "number") return v;
|
|
27596
|
-
if (typeof v === "string") {
|
|
27597
|
-
const m = /^(-?\d+(?:\.\d+)?)\s*deg$/i.exec(v);
|
|
27598
|
-
if (m) return parseFloat(m[1]) * Math.PI / 180;
|
|
27599
|
-
const n = Number(v);
|
|
27600
|
-
if (!Number.isNaN(n)) return n;
|
|
27601
|
-
}
|
|
27602
|
-
return 0;
|
|
27603
|
-
};
|
|
27604
|
-
var toVec3 = (v) => {
|
|
27605
|
-
if (Array.isArray(v))
|
|
27606
|
-
return [Number(v[0]) || 0, Number(v[1]) || 0, Number(v[2]) || 0];
|
|
27607
|
-
if (typeof v === "object" && v)
|
|
27608
|
-
return [Number(v.x) || 0, Number(v.y) || 0, Number(v.z) || 0];
|
|
27609
|
-
return [0, 0, 0];
|
|
27610
|
-
};
|
|
27611
|
-
function renderNode(node, colorCtx, renderCtx) {
|
|
27612
|
-
const {
|
|
27613
|
-
jscad: { primitives: primitives9, booleans: booleans5, hulls, geometries: geometries9, extrusions: extrusions9, transforms: transforms2 }
|
|
27614
|
-
} = renderCtx;
|
|
27615
|
-
if (node == null || node === false) return [];
|
|
27616
|
-
if (Array.isArray(node))
|
|
27617
|
-
return node.flatMap((n) => renderNode(n, colorCtx, renderCtx));
|
|
27618
|
-
if (!isVNode(node)) return [];
|
|
27619
|
-
const { type, props, children } = node;
|
|
27620
|
-
if (props?.material) {
|
|
27621
|
-
const { material, ...rest } = props;
|
|
27622
|
-
return renderNode({ ...node, props: rest }, colorCtx, renderCtx).map(
|
|
27623
|
-
(entry) => ({
|
|
27624
|
-
...entry,
|
|
27625
|
-
material: { ...material },
|
|
27626
|
-
geom: { ...entry.geom, material: { ...material } }
|
|
27627
|
-
})
|
|
27628
|
-
);
|
|
27629
|
-
}
|
|
27630
|
-
if (type === Fragment) {
|
|
27631
|
-
return (children ?? []).flatMap((c) => renderNode(c, colorCtx, renderCtx));
|
|
27632
|
-
}
|
|
27633
|
-
if (type === Colorize) {
|
|
27634
|
-
const newColor = props?.color;
|
|
27635
|
-
return (children ?? []).flatMap(
|
|
27636
|
-
(c) => renderNode(c, newColor ?? colorCtx, renderCtx)
|
|
27637
|
-
);
|
|
27638
|
-
}
|
|
27639
|
-
if (type === Translate) {
|
|
27640
|
-
const off = toVec3(
|
|
27641
|
-
props?.offset ?? props?.center ?? { x: props?.x, y: props?.y, z: props?.z }
|
|
27642
|
-
);
|
|
27643
|
-
const geoms = (children ?? []).flatMap(
|
|
27644
|
-
(c) => renderNode(c, colorCtx, renderCtx)
|
|
27645
|
-
);
|
|
27646
|
-
return geoms.map(({ geom, color, material }) => ({
|
|
27647
|
-
material,
|
|
27648
|
-
geom: transforms2.translate(off, geom),
|
|
27649
|
-
color: color ?? colorCtx
|
|
27650
|
-
}));
|
|
27651
|
-
}
|
|
27652
|
-
if (type === Rotate) {
|
|
27653
|
-
const angles = props?.angles ?? props?.rotation;
|
|
27654
|
-
const rot = Array.isArray(angles) ? [degToRad(angles[0]), degToRad(angles[1]), degToRad(angles[2])] : [
|
|
27655
|
-
degToRad(props?.x ?? 0),
|
|
27656
|
-
degToRad(props?.y ?? 0),
|
|
27657
|
-
degToRad(props?.z ?? 0)
|
|
27658
|
-
];
|
|
27659
|
-
const geoms = (children ?? []).flatMap(
|
|
27660
|
-
(c) => renderNode(c, colorCtx, renderCtx)
|
|
27661
|
-
);
|
|
27662
|
-
return geoms.map(({ geom, color, material }) => ({
|
|
27663
|
-
material,
|
|
27664
|
-
geom: transforms2.rotateZ(
|
|
27665
|
-
rot[2],
|
|
27666
|
-
transforms2.rotateY(rot[1], transforms2.rotateX(rot[0], geom))
|
|
27667
|
-
),
|
|
27668
|
-
color
|
|
27669
|
-
}));
|
|
27670
|
-
}
|
|
27671
|
-
if (type === Union || type === Subtract || type === Hull) {
|
|
27672
|
-
const entries = (children ?? []).flatMap(
|
|
27673
|
-
(c) => renderNode(c, colorCtx, renderCtx)
|
|
27674
|
-
);
|
|
27675
|
-
const geoms = entries.map((g) => g.geom);
|
|
27676
|
-
if (geoms.length === 0) return [];
|
|
27677
|
-
let geom;
|
|
27678
|
-
if (type === Union) geom = booleans5.union(geoms);
|
|
27679
|
-
else if (type === Subtract)
|
|
27680
|
-
geom = booleans5.subtract(geoms[0], geoms.slice(1));
|
|
27681
|
-
else geom = hulls.hull(geoms);
|
|
27682
|
-
return [
|
|
27683
|
-
{
|
|
27684
|
-
geom,
|
|
27685
|
-
color: colorCtx,
|
|
27686
|
-
material: type === Subtract ? entries[0]?.material : void 0
|
|
27687
|
-
}
|
|
27688
|
-
];
|
|
27689
|
-
}
|
|
27690
|
-
if (type === Custom) {
|
|
27691
|
-
return [{ geom: props.geometry, color: colorCtx }];
|
|
27692
|
-
}
|
|
27693
|
-
if (type === Polygon) {
|
|
27694
|
-
const points = props?.points ?? [];
|
|
27695
|
-
const g2 = geometries9.geom2.fromPoints(points);
|
|
27696
|
-
return [{ geom: g2, color: colorCtx ?? props?.color }];
|
|
27697
|
-
}
|
|
27698
|
-
if (type === ExtrudeLinear) {
|
|
27699
|
-
const entries = (children ?? []).flatMap(
|
|
27700
|
-
(c) => renderNode(c, colorCtx, renderCtx)
|
|
27701
|
-
);
|
|
27702
|
-
const geoms2 = entries.map((g) => g.geom);
|
|
27703
|
-
if (geoms2.length === 0) return [];
|
|
27704
|
-
const base2 = geoms2.length > 1 ? booleans5.union(geoms2) : geoms2[0];
|
|
27705
|
-
const height10 = props?.height ?? props?.h ?? 1;
|
|
27706
|
-
let g3 = extrusions9.extrudeLinear({ height: height10 }, base2);
|
|
27707
|
-
if (g3.polygons) {
|
|
27708
|
-
for (const poly of g3.polygons) {
|
|
27709
|
-
if (!poly.plane || !poly.vertices || poly.vertices.length < 3) continue;
|
|
27710
|
-
poly.vertices.reverse();
|
|
27711
|
-
}
|
|
27712
|
-
}
|
|
27713
|
-
return [
|
|
27714
|
-
{
|
|
27715
|
-
geom: g3,
|
|
27716
|
-
color: colorCtx ?? props?.color,
|
|
27717
|
-
material: entries.length === 1 ? entries[0]?.material : void 0
|
|
27718
|
-
}
|
|
27719
|
-
];
|
|
27720
|
-
}
|
|
27721
|
-
if (type === Cuboid || type === Cube || type === Cylinder || type === Sphere || type === RoundedCuboid || type === RoundedCylinder) {
|
|
27722
|
-
let g;
|
|
27723
|
-
if (type === Cuboid) {
|
|
27724
|
-
const size = props?.size ?? [1, 1, 1];
|
|
27725
|
-
const offset = props?.offset;
|
|
27726
|
-
const center = props?.center ?? (offset ? [offset[0], offset[1], offset[2]] : [0, 0, 0]);
|
|
27727
|
-
g = primitives9.cuboid({ size, center });
|
|
27728
|
-
} else if (type === Cube) {
|
|
27729
|
-
const size = props?.size ?? 1;
|
|
27730
|
-
const offset = props?.offset;
|
|
27731
|
-
const center = props?.center ?? (offset ? [offset[0], offset[1], offset[2]] : [0, 0, 0]);
|
|
27732
|
-
g = primitives9.cube({ size, center });
|
|
27733
|
-
} else if (type === Cylinder) {
|
|
27734
|
-
const height10 = props?.height ?? 1;
|
|
27735
|
-
const radius = props?.radius ?? 1;
|
|
27736
|
-
const center = props?.center ?? [0, 0, 0];
|
|
27737
|
-
g = primitives9.cylinder({ height: height10, radius, center });
|
|
27738
|
-
} else if (type === Sphere) {
|
|
27739
|
-
const radius = props?.radius ?? 1;
|
|
27740
|
-
const center = props?.center ?? [0, 0, 0];
|
|
27741
|
-
g = primitives9.sphere({ radius, center });
|
|
27742
|
-
} else if (type === RoundedCylinder) {
|
|
27743
|
-
const height10 = props?.height ?? 1;
|
|
27744
|
-
const radius = props?.radius ?? 1;
|
|
27745
|
-
const roundRadius = props?.roundRadius ?? 0.1;
|
|
27746
|
-
const center = props?.center ?? [0, 0, 0];
|
|
27747
|
-
g = primitives9.roundedCylinder({ height: height10, radius, roundRadius, center });
|
|
27748
|
-
} else {
|
|
27749
|
-
const size = props?.size ?? [1, 1, 1];
|
|
27750
|
-
const roundRadius = props?.roundRadius ?? 0.1;
|
|
27751
|
-
const center = props?.center ?? [0, 0, 0];
|
|
27752
|
-
g = primitives9.roundedCuboid({ size, roundRadius, center });
|
|
27753
|
-
}
|
|
27754
|
-
return [{ geom: g, color: colorCtx ?? props?.color }];
|
|
27755
|
-
}
|
|
27756
|
-
if (typeof type === "function") {
|
|
27757
|
-
const out = type(props ?? {});
|
|
27758
|
-
return renderNode(out, colorCtx, renderCtx);
|
|
27759
|
-
}
|
|
27760
|
-
return (children ?? []).flatMap((c) => renderNode(c, colorCtx, renderCtx));
|
|
27761
|
-
}
|
|
27762
|
-
function render(root, jscad18) {
|
|
27763
|
-
const geometries9 = renderNode(root, void 0, { jscad: jscad18 });
|
|
27764
|
-
return {
|
|
27765
|
-
geometries: geometries9.map(
|
|
27766
|
-
(entry) => entry.material ? { ...entry, geom: { ...entry.geom, material: entry.material } } : entry
|
|
27767
|
-
)
|
|
27768
|
-
};
|
|
27769
|
-
}
|
|
27770
|
-
|
|
27771
28455
|
// lib/vanilla/convertCSGToThreeGeom.ts
|
|
27772
28456
|
import {
|
|
27773
28457
|
BufferAttribute,
|
|
@@ -27778,16 +28462,16 @@ function convertCSGToThreeGeom(csg) {
|
|
|
27778
28462
|
if (csg.polygons) {
|
|
27779
28463
|
const vertices = [];
|
|
27780
28464
|
const indices = [];
|
|
27781
|
-
const
|
|
28465
|
+
const colors2 = [];
|
|
27782
28466
|
let idx = 0;
|
|
27783
28467
|
for (const polygon4 of csg.polygons) {
|
|
27784
28468
|
for (const vertex of polygon4.vertices) {
|
|
27785
28469
|
vertex.index = idx;
|
|
27786
28470
|
vertices.push(vertex[0], vertex[1], vertex[2]);
|
|
27787
28471
|
if (csg.color && csg.color.length >= 3) {
|
|
27788
|
-
|
|
28472
|
+
colors2.push(csg.color[0], csg.color[1], csg.color[2]);
|
|
27789
28473
|
} else {
|
|
27790
|
-
|
|
28474
|
+
colors2.push(1, 1, 1);
|
|
27791
28475
|
}
|
|
27792
28476
|
idx++;
|
|
27793
28477
|
}
|
|
@@ -27804,29 +28488,29 @@ function convertCSGToThreeGeom(csg) {
|
|
|
27804
28488
|
new BufferAttribute(new Float32Array(vertices), 3)
|
|
27805
28489
|
);
|
|
27806
28490
|
geo.setIndex(indices);
|
|
27807
|
-
if (
|
|
28491
|
+
if (colors2.length > 0) {
|
|
27808
28492
|
geo.setAttribute(
|
|
27809
28493
|
"color",
|
|
27810
|
-
new BufferAttribute(new Float32Array(
|
|
28494
|
+
new BufferAttribute(new Float32Array(colors2), 3)
|
|
27811
28495
|
);
|
|
27812
28496
|
}
|
|
27813
28497
|
if (csg.transforms) {
|
|
27814
|
-
const
|
|
27815
|
-
|
|
27816
|
-
geo.applyMatrix4(
|
|
28498
|
+
const transforms3 = new Matrix4();
|
|
28499
|
+
transforms3.fromArray(csg.transforms);
|
|
28500
|
+
geo.applyMatrix4(transforms3);
|
|
27817
28501
|
}
|
|
27818
28502
|
geo.computeVertexNormals();
|
|
27819
28503
|
return geo;
|
|
27820
28504
|
}
|
|
27821
28505
|
if (csg.sides) {
|
|
27822
28506
|
const vertices = [];
|
|
27823
|
-
const
|
|
28507
|
+
const colors2 = [];
|
|
27824
28508
|
for (const side of csg.sides) {
|
|
27825
28509
|
vertices.push(side[0][0], side[0][1], 0);
|
|
27826
28510
|
if (csg.color && csg.color.length >= 3) {
|
|
27827
|
-
|
|
28511
|
+
colors2.push(csg.color[0], csg.color[1], csg.color[2]);
|
|
27828
28512
|
} else {
|
|
27829
|
-
|
|
28513
|
+
colors2.push(1, 1, 1);
|
|
27830
28514
|
}
|
|
27831
28515
|
}
|
|
27832
28516
|
const geo = new BufferGeometry();
|
|
@@ -27834,16 +28518,16 @@ function convertCSGToThreeGeom(csg) {
|
|
|
27834
28518
|
"position",
|
|
27835
28519
|
new BufferAttribute(new Float32Array(vertices), 3)
|
|
27836
28520
|
);
|
|
27837
|
-
if (
|
|
28521
|
+
if (colors2.length > 0) {
|
|
27838
28522
|
geo.setAttribute(
|
|
27839
28523
|
"color",
|
|
27840
|
-
new BufferAttribute(new Float32Array(
|
|
28524
|
+
new BufferAttribute(new Float32Array(colors2), 3)
|
|
27841
28525
|
);
|
|
27842
28526
|
}
|
|
27843
28527
|
if (csg.transforms) {
|
|
27844
|
-
const
|
|
27845
|
-
|
|
27846
|
-
geo.applyMatrix4(
|
|
28528
|
+
const transforms3 = new Matrix4();
|
|
28529
|
+
transforms3.fromArray(csg.transforms);
|
|
28530
|
+
geo.applyMatrix4(transforms3);
|
|
27847
28531
|
}
|
|
27848
28532
|
return geo;
|
|
27849
28533
|
}
|
|
@@ -27851,25 +28535,104 @@ function convertCSGToThreeGeom(csg) {
|
|
|
27851
28535
|
return new BufferGeometry();
|
|
27852
28536
|
}
|
|
27853
28537
|
|
|
28538
|
+
// lib/named-edges.ts
|
|
28539
|
+
import jscad20 from "@jscad/modeling";
|
|
28540
|
+
function listJscadNamedEdges(model108) {
|
|
28541
|
+
return listJscadReferenceFeatures(model108).filter((name) => {
|
|
28542
|
+
const { geometry } = model108.referenceFeatures[name];
|
|
28543
|
+
return jscad20.geometries.geom2.isA(geometry) || jscad20.geometries.path2.isA(geometry);
|
|
28544
|
+
});
|
|
28545
|
+
}
|
|
28546
|
+
function listJscadReferenceFeatures(model108) {
|
|
28547
|
+
return Object.keys(model108.referenceFeatures);
|
|
28548
|
+
}
|
|
28549
|
+
function readJscadReferenceFeature(model108, name) {
|
|
28550
|
+
if (!Object.hasOwn(model108.referenceFeatures, name))
|
|
28551
|
+
throw new Error(`JSCAD model does not define named feature "${name}"`);
|
|
28552
|
+
return model108.referenceFeatures[name];
|
|
28553
|
+
}
|
|
28554
|
+
function readJscadNamedEdge(model108, name) {
|
|
28555
|
+
const { geometry: feature, matrix } = readJscadReferenceFeature(model108, name);
|
|
28556
|
+
if (matrix.length !== 16 || !matrix.every(Number.isFinite))
|
|
28557
|
+
throw new Error(
|
|
28558
|
+
`Named JSCAD feature "${name}" requires a finite 4x4 matrix`
|
|
28559
|
+
);
|
|
28560
|
+
let points;
|
|
28561
|
+
let closed;
|
|
28562
|
+
if (jscad20.geometries.path2.isA(feature)) {
|
|
28563
|
+
const path = jscad20.geometries.path2.clone(feature);
|
|
28564
|
+
points = jscad20.geometries.path2.toPoints(path);
|
|
28565
|
+
closed = path.isClosed;
|
|
28566
|
+
} else if (jscad20.geometries.geom2.isA(feature)) {
|
|
28567
|
+
const outlines = jscad20.geometries.geom2.toOutlines(
|
|
28568
|
+
jscad20.geometries.geom2.clone(feature)
|
|
28569
|
+
);
|
|
28570
|
+
if (outlines.length !== 1)
|
|
28571
|
+
throw new Error(
|
|
28572
|
+
`Named JSCAD edge "${name}" must identify one contour; name its boundaries separately`
|
|
28573
|
+
);
|
|
28574
|
+
points = outlines[0];
|
|
28575
|
+
closed = true;
|
|
28576
|
+
} else {
|
|
28577
|
+
throw new Error(
|
|
28578
|
+
`Named JSCAD edge "${name}" is not a geom2 or path2 feature`
|
|
28579
|
+
);
|
|
28580
|
+
}
|
|
28581
|
+
if (points.length < 2)
|
|
28582
|
+
throw new Error(`Named JSCAD edge "${name}" has no measurable path`);
|
|
28583
|
+
return {
|
|
28584
|
+
points: points.map(([x, y]) => {
|
|
28585
|
+
const point = jscad20.maths.vec3.transform(
|
|
28586
|
+
jscad20.maths.vec3.create(),
|
|
28587
|
+
[x, y, 0],
|
|
28588
|
+
matrix
|
|
28589
|
+
);
|
|
28590
|
+
return { x: point[0], y: point[1], z: point[2] };
|
|
28591
|
+
}),
|
|
28592
|
+
closed
|
|
28593
|
+
};
|
|
28594
|
+
}
|
|
28595
|
+
|
|
28596
|
+
// lib/models/rectangulartube/model.tsx
|
|
28597
|
+
import jscad21 from "@jscad/modeling";
|
|
28598
|
+
function createRectangularTubeModel(input) {
|
|
28599
|
+
const model108 = renderToJscadModel(
|
|
28600
|
+
/* @__PURE__ */ jsx(RectangularTube, { ...input }),
|
|
28601
|
+
jscad21
|
|
28602
|
+
);
|
|
28603
|
+
if (model108.geometries.length !== 1 || !jscad21.geometries.geom3.isA(model108.geometries[0]))
|
|
28604
|
+
throw new Error("RectangularTube must render exactly one native solid");
|
|
28605
|
+
return model108;
|
|
28606
|
+
}
|
|
28607
|
+
|
|
28608
|
+
// lib/models/rectangulartube/geometry.ts
|
|
28609
|
+
function createRectangularTubeGeom(input) {
|
|
28610
|
+
const model108 = createRectangularTubeModel(input);
|
|
28611
|
+
return model108.geometries[0];
|
|
28612
|
+
}
|
|
28613
|
+
function createRectangularTubeMesh(input) {
|
|
28614
|
+
return geom3ToIndexedMesh(createRectangularTubeGeom(input));
|
|
28615
|
+
}
|
|
28616
|
+
|
|
27854
28617
|
// lib/vanilla/index.ts
|
|
27855
|
-
function getJscadModelForFootprint(footprint,
|
|
28618
|
+
function getJscadModelForFootprint(footprint, jscad22) {
|
|
27856
28619
|
const vnode = h(Footprinter3d, { footprint });
|
|
27857
|
-
return render(vnode,
|
|
28620
|
+
return render(vnode, jscad22);
|
|
27858
28621
|
}
|
|
27859
|
-
function getJscadModelForFootprintWithPads(footprint,
|
|
28622
|
+
function getJscadModelForFootprintWithPads(footprint, jscad22) {
|
|
27860
28623
|
const vnode = h(
|
|
27861
28624
|
Fragment,
|
|
27862
28625
|
{},
|
|
27863
28626
|
h(Footprinter3d, { footprint }),
|
|
27864
28627
|
h(ExtrudedPads, { footprint })
|
|
27865
28628
|
);
|
|
27866
|
-
return render(vnode,
|
|
28629
|
+
return render(vnode, jscad22);
|
|
27867
28630
|
}
|
|
27868
|
-
function createJSCADRenderer(
|
|
28631
|
+
function createJSCADRenderer(jscad22) {
|
|
27869
28632
|
function createJSCADRoot(container) {
|
|
27870
28633
|
return {
|
|
27871
28634
|
render(element) {
|
|
27872
|
-
const { geometries: geometries9 } = render(element,
|
|
28635
|
+
const { geometries: geometries9 } = render(element, jscad22);
|
|
27873
28636
|
container.splice(0, container.length, ...geometries9);
|
|
27874
28637
|
}
|
|
27875
28638
|
};
|
|
@@ -28004,6 +28767,7 @@ export {
|
|
|
28004
28767
|
createRectangularGasketMesh,
|
|
28005
28768
|
createRectangularTubeGeom,
|
|
28006
28769
|
createRectangularTubeMesh,
|
|
28770
|
+
createRectangularTubeModel,
|
|
28007
28771
|
createRigidCouplerGeom,
|
|
28008
28772
|
createRigidCouplerMesh,
|
|
28009
28773
|
createSetScrewGeom,
|
|
@@ -28039,8 +28803,14 @@ export {
|
|
|
28039
28803
|
createWormGearMesh,
|
|
28040
28804
|
createZeeBarGeom,
|
|
28041
28805
|
createZeeBarMesh,
|
|
28806
|
+
geom3ToIndexedMesh,
|
|
28042
28807
|
getJscadModelForFootprint,
|
|
28043
28808
|
getJscadModelForFootprintWithPads,
|
|
28044
|
-
h
|
|
28809
|
+
h,
|
|
28810
|
+
listJscadNamedEdges,
|
|
28811
|
+
listJscadReferenceFeatures,
|
|
28812
|
+
readJscadNamedEdge,
|
|
28813
|
+
readJscadReferenceFeature,
|
|
28814
|
+
renderToJscadModel
|
|
28045
28815
|
};
|
|
28046
28816
|
//# sourceMappingURL=vanilla.js.map
|