@faicad/faijs 0.19.0 → 0.22.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/dist/api/brep-mirror/joinery-brep.d.ts.map +1 -1
  2. package/dist/api/brep-mirror/joinery-brep.js +3 -1
  3. package/dist/api/brep-mirror/joinery-brep.js.map +1 -1
  4. package/dist/api/generated/script-face-manifest.d.ts +4 -0
  5. package/dist/api/generated/script-face-manifest.d.ts.map +1 -1
  6. package/dist/api/generated/script-face-manifest.js.map +1 -1
  7. package/dist/api/knurl.d.ts.map +1 -1
  8. package/dist/api/knurl.js +1 -0
  9. package/dist/api/knurl.js.map +1 -1
  10. package/dist/api/primitives.d.ts +4 -3
  11. package/dist/api/primitives.d.ts.map +1 -1
  12. package/dist/api/primitives.js +9 -3
  13. package/dist/api/primitives.js.map +1 -1
  14. package/dist/api/profile.d.ts +34 -5
  15. package/dist/api/profile.d.ts.map +1 -1
  16. package/dist/api/profile.js +60 -9
  17. package/dist/api/profile.js.map +1 -1
  18. package/dist/api/punch-hole.d.ts +3 -0
  19. package/dist/api/punch-hole.d.ts.map +1 -1
  20. package/dist/api/punch-hole.js.map +1 -1
  21. package/dist/api/sketch-on-plane.d.ts +12 -6
  22. package/dist/api/sketch-on-plane.d.ts.map +1 -1
  23. package/dist/api/sketch-on-plane.js +11 -8
  24. package/dist/api/sketch-on-plane.js.map +1 -1
  25. package/dist/api/surface/arg-spec.d.ts +8 -0
  26. package/dist/api/surface/arg-spec.d.ts.map +1 -1
  27. package/dist/api/surface/arg-spec.js.map +1 -1
  28. package/dist/api/transform.d.ts +5 -5
  29. package/dist/api/transform.d.ts.map +1 -1
  30. package/dist/api/transform.js +12 -10
  31. package/dist/api/transform.js.map +1 -1
  32. package/dist/api/xml-dom.d.ts +27 -0
  33. package/dist/api/xml-dom.d.ts.map +1 -0
  34. package/dist/api/xml-dom.js +45 -0
  35. package/dist/api/xml-dom.js.map +1 -0
  36. package/dist/brep/brep-ops.d.ts +4 -4
  37. package/dist/brep/brep-ops.d.ts.map +1 -1
  38. package/dist/brep/brep-ops.js +8 -6
  39. package/dist/brep/brep-ops.js.map +1 -1
  40. package/dist/brep/brep-topology.d.ts.map +1 -1
  41. package/dist/brep/brep-topology.js +3 -1
  42. package/dist/brep/brep-topology.js.map +1 -1
  43. package/dist/brep/export/export-model.d.ts +79 -0
  44. package/dist/brep/export/export-model.d.ts.map +1 -0
  45. package/dist/brep/export/export-model.js +335 -0
  46. package/dist/brep/export/export-model.js.map +1 -0
  47. package/dist/brep/primitives-brep.d.ts.map +1 -1
  48. package/dist/brep/primitives-brep.js +3 -1
  49. package/dist/brep/primitives-brep.js.map +1 -1
  50. package/dist/brepkit-kernel/brepkitKernel.d.ts.map +1 -1
  51. package/dist/brepkit-kernel/brepkitKernel.js +4 -2
  52. package/dist/brepkit-kernel/brepkitKernel.js.map +1 -1
  53. package/dist/cad-runtime/direct-executor.d.ts +4 -0
  54. package/dist/cad-runtime/direct-executor.d.ts.map +1 -1
  55. package/dist/cad-runtime/direct-executor.js +17 -1
  56. package/dist/cad-runtime/direct-executor.js.map +1 -1
  57. package/dist/cad-runtime/runtime.d.ts +24 -1
  58. package/dist/cad-runtime/runtime.d.ts.map +1 -1
  59. package/dist/cad-runtime/runtime.js +53 -3
  60. package/dist/cad-runtime/runtime.js.map +1 -1
  61. package/dist/define-op.d.ts +22 -0
  62. package/dist/define-op.d.ts.map +1 -1
  63. package/dist/define-op.js +15 -0
  64. package/dist/define-op.js.map +1 -1
  65. package/dist/env-agnostic.d.ts +7 -7
  66. package/dist/env-agnostic.d.ts.map +1 -1
  67. package/dist/env-agnostic.js +3 -3
  68. package/dist/env-agnostic.js.map +1 -1
  69. package/dist/geometry2d/bridge/lift-on-plane.d.ts.map +1 -1
  70. package/dist/geometry2d/bridge/lift-on-plane.js +6 -0
  71. package/dist/geometry2d/bridge/lift-on-plane.js.map +1 -1
  72. package/dist/geometry2d/pen-sketcher.d.ts +25 -0
  73. package/dist/geometry2d/pen-sketcher.d.ts.map +1 -1
  74. package/dist/geometry2d/pen-sketcher.js +43 -0
  75. package/dist/geometry2d/pen-sketcher.js.map +1 -1
  76. package/dist/lang/code-to-args.d.ts +29 -3
  77. package/dist/lang/code-to-args.d.ts.map +1 -1
  78. package/dist/lang/code-to-args.js +41 -2
  79. package/dist/lang/code-to-args.js.map +1 -1
  80. package/dist/lang/codegen.d.ts +45 -1
  81. package/dist/lang/codegen.d.ts.map +1 -1
  82. package/dist/lang/codegen.js +135 -6
  83. package/dist/lang/codegen.js.map +1 -1
  84. package/dist/lang/host-arg.d.ts +6 -0
  85. package/dist/lang/host-arg.d.ts.map +1 -1
  86. package/dist/lang/host-arg.js.map +1 -1
  87. package/dist/lang/metadata-extractor.d.ts +25 -0
  88. package/dist/lang/metadata-extractor.d.ts.map +1 -1
  89. package/dist/lang/metadata-extractor.js +289 -25
  90. package/dist/lang/metadata-extractor.js.map +1 -1
  91. package/dist/lang/parse-error.d.ts +7 -1
  92. package/dist/lang/parse-error.d.ts.map +1 -1
  93. package/dist/lang/parse-error.js.map +1 -1
  94. package/dist/lang/security-scanner.d.ts +9 -1
  95. package/dist/lang/security-scanner.d.ts.map +1 -1
  96. package/dist/lang/security-scanner.js +38 -1
  97. package/dist/lang/security-scanner.js.map +1 -1
  98. package/dist/mesh/io.d.ts +62 -9
  99. package/dist/mesh/io.d.ts.map +1 -1
  100. package/dist/mesh/io.js +124 -17
  101. package/dist/mesh/io.js.map +1 -1
  102. package/dist/mesh/threemf-loader.d.ts +15 -0
  103. package/dist/mesh/threemf-loader.d.ts.map +1 -0
  104. package/dist/mesh/threemf-loader.js +163 -0
  105. package/dist/mesh/threemf-loader.js.map +1 -0
  106. package/dist/mesh/transform.d.ts +2 -2
  107. package/dist/mesh/transform.d.ts.map +1 -1
  108. package/dist/mesh/transform.js +3 -3
  109. package/dist/mesh/transform.js.map +1 -1
  110. package/dist/mesh/types.d.ts +1 -1
  111. package/dist/mesh/types.d.ts.map +1 -1
  112. package/dist/mesh/types.js.map +1 -1
  113. package/dist/node-host/cli.d.ts.map +1 -1
  114. package/dist/node-host/cli.js +53 -26
  115. package/dist/node-host/cli.js.map +1 -1
  116. package/dist/occt-kernel/occtKernel.d.ts.map +1 -1
  117. package/dist/occt-kernel/occtKernel.js +4 -2
  118. package/dist/occt-kernel/occtKernel.js.map +1 -1
  119. package/dist/occt-kernel/topologyExt.d.ts.map +1 -1
  120. package/dist/occt-kernel/topologyExt.js +4 -1
  121. package/dist/occt-kernel/topologyExt.js.map +1 -1
  122. package/dist/runtime-state.d.ts +18 -0
  123. package/dist/runtime-state.d.ts.map +1 -1
  124. package/dist/runtime-state.js +23 -0
  125. package/dist/runtime-state.js.map +1 -1
  126. package/dist/sdk.d.ts +1 -1
  127. package/dist/sdk.d.ts.map +1 -1
  128. package/dist/sdk.js +1 -1
  129. package/dist/sdk.js.map +1 -1
  130. package/dist/tolerance.d.ts +38 -0
  131. package/dist/tolerance.d.ts.map +1 -0
  132. package/dist/tolerance.js +40 -0
  133. package/dist/tolerance.js.map +1 -0
  134. package/dist/topology/naming/score.js +3 -3
  135. package/dist/topology/naming/score.js.map +1 -1
  136. package/dist/units.d.ts +248 -0
  137. package/dist/units.d.ts.map +1 -0
  138. package/dist/units.js +397 -0
  139. package/dist/units.js.map +1 -0
  140. package/package.json +11 -2
@@ -0,0 +1,248 @@
1
+ /**
2
+ * faijs unit system — the single source of truth for dimensions and units.
3
+ *
4
+ * Every dimensioned value in faijs is stored in the **base unit** of its
5
+ * dimension, and units are pure scale factors relative to that base. This
6
+ * module is a zero-dependency leaf: it must not import `lang/`, any op
7
+ * registry, `occt-kernel/*` or `brepkit-kernel/*`, because it feeds the
8
+ * serialization pipeline (codegen), platform-neutral imports, and static
9
+ * dimension checks without dragging in a WASM chain.
10
+ *
11
+ * Base units (user-裁定, 2026-09-28):
12
+ * length: mm | angle: degree | mass: gram | temperature: kelvin
13
+ * time: second | current: ampere
14
+ *
15
+ * `ValueWithUnits.value` is ALWAYS the base-unit numeric value. There is no
16
+ * "this value remembers it is inches" — conversion happens only at construction
17
+ * (`inch.mul(2)`) and extraction (`.as(mm)`), which mirrors Onshape's design
18
+ * but with faijs's own base table (NOT Onshape's meter/radian — do not copy
19
+ * those numeric values).
20
+ */
21
+ /** Base dimensions of the system. Higher powers are built by exponents. */
22
+ export type BaseDimension = 'length' | 'angle' | 'mass' | 'temperature' | 'time' | 'current';
23
+ /** A dim name is any base dimension. */
24
+ export type DimName = BaseDimension;
25
+ /**
26
+ * A unit name. `micron/mm/cm/m/inch/foot/meter` are the six legal values of
27
+ * the 3MF `<model unit>` enum and must all be present in `UNIT_SCALE`.
28
+ */
29
+ export type UnitName = 'mm' | 'cm' | 'm' | 'micron' | 'inch' | 'foot' | 'yard' | 'degree' | 'radian' | 'gram' | 'kilogram' | 'second';
30
+ /**
31
+ * A dimension = a sparse map of base dimension → exponent (absent ⇒ 0).
32
+ * Implemented as a frozen plain object.
33
+ */
34
+ export type UnitSpec = Readonly<Partial<Record<BaseDimension, number>>>;
35
+ /**
36
+ * True when two specs have identical exponents for every base dimension.
37
+ * @param a - first spec.
38
+ * @param b - second spec.
39
+ * @returns `true` if every base-dimension exponent matches.
40
+ */
41
+ export declare function unitEquals(a: UnitSpec, b: UnitSpec): boolean;
42
+ /** Dimension spec for length (length^1). */
43
+ export declare const LENGTH: UnitSpec;
44
+ /** Dimension spec for area (length^2). */
45
+ export declare const AREA: UnitSpec;
46
+ /** Dimension spec for volume (length^3). */
47
+ export declare const VOLUME: UnitSpec;
48
+ /** Dimension spec for angle (angle^1). */
49
+ export declare const ANGLE: UnitSpec;
50
+ /** Dimension spec for mass (mass^1). */
51
+ export declare const MASS: UnitSpec;
52
+ /** Dimension spec for temperature (temperature^1). */
53
+ export declare const TEMPERATURE: UnitSpec;
54
+ /** Dimension spec for time (time^1). */
55
+ export declare const TIME: UnitSpec;
56
+ /** Dimension spec for electric current (current^1). */
57
+ export declare const CURRENT: UnitSpec;
58
+ /**
59
+ * The dimension spec of a named base dimension.
60
+ * @param dim - a base dimension name.
61
+ * @returns the corresponding `UnitSpec`.
62
+ */
63
+ export declare function specOfDim(dim: DimName): UnitSpec;
64
+ /**
65
+ * A value carrying an immutable dimension. All arithmetic is method-style —
66
+ * there is no operator overloading in TS. `value` is always expressed in the
67
+ * base unit of its dimension.
68
+ */
69
+ export declare class ValueWithUnits {
70
+ /** The numeric magnitude, always expressed in the base unit of the dimension. */
71
+ readonly value: number;
72
+ /** The dimension spec (which base dimensions are present and with what exponent). */
73
+ readonly spec: UnitSpec;
74
+ constructor(value: number, spec: UnitSpec);
75
+ /**
76
+ * Add another value; both must share the same dimension.
77
+ * @param rhs - the value to add (must have the same dimension).
78
+ * @returns a new `ValueWithUnits` whose value is `this.value + rhs.value`.
79
+ */
80
+ add(rhs: ValueWithUnits): ValueWithUnits;
81
+ /**
82
+ * Subtract another value; both must share the same dimension.
83
+ * @param rhs - the value to subtract (must have the same dimension).
84
+ * @returns a new `ValueWithUnits` whose value is `this.value - rhs.value`.
85
+ */
86
+ sub(rhs: ValueWithUnits): ValueWithUnits;
87
+ /**
88
+ * Negate.
89
+ * @returns a new `ValueWithUnits` with the negated magnitude.
90
+ */
91
+ neg(): ValueWithUnits;
92
+ /**
93
+ * Scale by a dimensionless number.
94
+ * @param n - a dimensionless scalar.
95
+ * @returns a new `ValueWithUnits` with the scaled magnitude.
96
+ */
97
+ mul(n: number): ValueWithUnits;
98
+ /**
99
+ * Divide by a dimensionless number.
100
+ * @param n - a dimensionless scalar.
101
+ * @returns a new `ValueWithUnits` with the divided magnitude.
102
+ */
103
+ div(n: number): ValueWithUnits;
104
+ /**
105
+ * The ratio to another value of the same dimension (dimensionless result).
106
+ * @param rhs - the divisor (must have the same dimension).
107
+ * @returns the dimensionless ratio `this.value / rhs.value`.
108
+ */
109
+ divBy(rhs: ValueWithUnits): number;
110
+ /**
111
+ * Raise to an integer power; each exponent times n must stay an integer.
112
+ * @param n - the integer power.
113
+ * @returns a new `ValueWithUnits` with exponents multiplied by `n`.
114
+ */
115
+ pow(n: number): ValueWithUnits;
116
+ /**
117
+ * Extract the numeric magnitude expressed in another unit (dimension must match).
118
+ * @param unit - a `ValueWithUnits` representing 1 of the target unit.
119
+ * @returns the magnitude in that unit.
120
+ */
121
+ as(unit: ValueWithUnits): number;
122
+ /**
123
+ * True when the magnitude is ~0 (within an optional same-dimension epsilon).
124
+ * @param eps - optional same-dimension epsilon; defaults to 1e-9 base units.
125
+ * @returns `true` when `|value| <= eps`.
126
+ */
127
+ eqZero(eps?: ValueWithUnits): boolean;
128
+ }
129
+ /**
130
+ * Unit name → base-unit scale factor. `length`: 1 mm; `angle`: 1 degree;
131
+ * `mass`: 1 gram; `time`: 1 second.
132
+ */
133
+ export declare const UNIT_SCALE: Readonly<Record<UnitName, number>>;
134
+ /** Unit name → the dimension it measures. */
135
+ export declare const UNIT_DIM: Readonly<Record<UnitName, DimName>>;
136
+ /** Derived: unit name → UnitSpec. */
137
+ export declare const UNIT_DIMS: Readonly<Record<UnitName, UnitSpec>>;
138
+ /**
139
+ * Script-side unit constant names → their numeric values (base-unit scale).
140
+ * These are registered as global read-only constants in the script runtime.
141
+ * All names are UPPERCASE to avoid collisions with user variable names
142
+ * (e.g. `cm` as center-of-mass would clash with `cm` as centimeter).
143
+ * `10 * INCH` in a script evaluates to `10 * 25.4 === 254` (plain JS multiply).
144
+ */
145
+ export declare const SCRIPT_UNIT_CONSTANTS: Readonly<Record<string, number>>;
146
+ /**
147
+ * Mapping from script-side unit constant names (UPPERCASE) to the internal
148
+ * `UnitName` (lowercase, used by UNIT_SCALE/UNIT_DIM for format-level units).
149
+ * Used by the dimension checker to resolve a script constant to its dimension.
150
+ */
151
+ export declare const SCRIPT_UNIT_TO_NAME: Readonly<Record<string, UnitName>>;
152
+ /** The set of script-side unit constant names (for fast membership tests). */
153
+ export declare const SCRIPT_UNIT_NAMES: ReadonlySet<string>;
154
+ /** 1 mm — the base length unit. */
155
+ export declare const mm: ValueWithUnits;
156
+ /** 1 cm = 10 mm. */
157
+ export declare const centimeter: ValueWithUnits;
158
+ /** 1 m = 1000 mm. */
159
+ export declare const meter: ValueWithUnits;
160
+ /** 1 micron = 0.001 mm (one of the 3MF unit enum values). */
161
+ export declare const micron: ValueWithUnits;
162
+ /** 1 inch = 25.4 mm. */
163
+ export declare const inch: ValueWithUnits;
164
+ /** 1 foot = 304.8 mm. */
165
+ export declare const foot: ValueWithUnits;
166
+ /** 1 yard = 914.4 mm. */
167
+ export declare const yard: ValueWithUnits;
168
+ /** The base angle unit — 1 degree. */
169
+ export declare const degree: ValueWithUnits;
170
+ /** 1 radian = 180/π degrees (base is degree). */
171
+ export declare const radian: ValueWithUnits;
172
+ /** 1 gram (base mass unit). */
173
+ export declare const gram: ValueWithUnits;
174
+ /** 1 kilogram = 1000 gram. */
175
+ export declare const kilogram: ValueWithUnits;
176
+ /** 1 second (base time unit). */
177
+ export declare const second: ValueWithUnits;
178
+ /** 1 (mm). */
179
+ export declare const MM = 1;
180
+ /** 10 (mm). */
181
+ export declare const CM = 10;
182
+ /** 1000 (mm). */
183
+ export declare const M = 1000;
184
+ /** 0.001 (mm). */
185
+ export declare const MICRON = 0.001;
186
+ /** 25.4 (mm). */
187
+ export declare const INCH = 25.4;
188
+ /** 304.8 (mm). */
189
+ export declare const FOOT = 304.8;
190
+ /** 914.4 (mm). */
191
+ export declare const YARD = 914.4;
192
+ /** 1 (degree). */
193
+ export declare const DEGREE = 1;
194
+ /** 180/π (degree). */
195
+ export declare const RADIAN: number;
196
+ /**
197
+ * The system display unit context, owned by the host (never a module-level
198
+ * global). Defaults to the base units.
199
+ */
200
+ export interface UnitContext {
201
+ length: UnitName;
202
+ angle: UnitName;
203
+ }
204
+ /** Base display units (mm / degree). */
205
+ export declare const BASE_UNITS: UnitContext;
206
+ /**
207
+ * The display unit for a dimension within a context. Only `length` and
208
+ * `angle` are host-settable; all other dimensions fall back to their base unit.
209
+ * @param dim - the dimension to look up.
210
+ * @param ctx - the system unit context; defaults to base units.
211
+ * @returns the unit name.
212
+ */
213
+ export declare function unitFor(dim: DimName, ctx?: UnitContext): UnitName;
214
+ /**
215
+ * Scale factor of a unit name relative to the base unit.
216
+ * @param name - the unit name.
217
+ * @returns the scale factor (e.g. `inch` → `25.4`).
218
+ */
219
+ export declare function unitScale(name: UnitName): number;
220
+ /**
221
+ * Convert a value given in a display unit to the base-unit value.
222
+ * @param n - the value in `unitName`.
223
+ * @param unitName - the source unit.
224
+ * @param dimensionName - the dimension (for validation).
225
+ * @returns the base-unit (mm/degree/...) value.
226
+ */
227
+ export declare function toBase(n: number, unitName: UnitName, dimensionName: DimName): number;
228
+ /**
229
+ * Convert a base-unit value into a display unit.
230
+ * @param base - the base-unit (mm/degree/...) value.
231
+ * @param unitName - the target unit.
232
+ * @param dimensionName - the dimension (for validation).
233
+ * @returns the value expressed in `unitName`.
234
+ */
235
+ export declare function fromBase(base: number, unitName: UnitName, dimensionName: DimName): number;
236
+ /**
237
+ * True when the value has dimension length.
238
+ * @param v - the value to check.
239
+ * @returns `true` if `v.spec` equals `LENGTH`.
240
+ */
241
+ export declare function isLength(v: ValueWithUnits): boolean;
242
+ /**
243
+ * True when the value has dimension angle.
244
+ * @param v - the value to check.
245
+ * @returns `true` if `v.spec` equals `ANGLE`.
246
+ */
247
+ export declare function isAngle(v: ValueWithUnits): boolean;
248
+ //# sourceMappingURL=units.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"units.d.ts","sourceRoot":"","sources":["../src/units.ts"],"names":[],"mappings":"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"}
package/dist/units.js ADDED
@@ -0,0 +1,397 @@
1
+ /**
2
+ * faijs unit system — the single source of truth for dimensions and units.
3
+ *
4
+ * Every dimensioned value in faijs is stored in the **base unit** of its
5
+ * dimension, and units are pure scale factors relative to that base. This
6
+ * module is a zero-dependency leaf: it must not import `lang/`, any op
7
+ * registry, `occt-kernel/*` or `brepkit-kernel/*`, because it feeds the
8
+ * serialization pipeline (codegen), platform-neutral imports, and static
9
+ * dimension checks without dragging in a WASM chain.
10
+ *
11
+ * Base units (user-裁定, 2026-09-28):
12
+ * length: mm | angle: degree | mass: gram | temperature: kelvin
13
+ * time: second | current: ampere
14
+ *
15
+ * `ValueWithUnits.value` is ALWAYS the base-unit numeric value. There is no
16
+ * "this value remembers it is inches" — conversion happens only at construction
17
+ * (`inch.mul(2)`) and extraction (`.as(mm)`), which mirrors Onshape's design
18
+ * but with faijs's own base table (NOT Onshape's meter/radian — do not copy
19
+ * those numeric values).
20
+ */
21
+ /**
22
+ * True when two specs have identical exponents for every base dimension.
23
+ * @param a - first spec.
24
+ * @param b - second spec.
25
+ * @returns `true` if every base-dimension exponent matches.
26
+ */
27
+ export function unitEquals(a, b) {
28
+ for (const dim of ALL_DIMS) {
29
+ const ea = a[dim] ?? 0;
30
+ const eb = b[dim] ?? 0;
31
+ if (ea !== eb)
32
+ return false;
33
+ }
34
+ return true;
35
+ }
36
+ /** All base dimensions, in a stable order. */
37
+ const ALL_DIMS = [
38
+ 'length', 'angle', 'mass', 'temperature', 'time', 'current',
39
+ ];
40
+ /** Dimension spec for length (length^1). */
41
+ export const LENGTH = Object.freeze({ length: 1 });
42
+ /** Dimension spec for area (length^2). */
43
+ export const AREA = Object.freeze({ length: 2 });
44
+ /** Dimension spec for volume (length^3). */
45
+ export const VOLUME = Object.freeze({ length: 3 });
46
+ /** Dimension spec for angle (angle^1). */
47
+ export const ANGLE = Object.freeze({ angle: 1 });
48
+ /** Dimension spec for mass (mass^1). */
49
+ export const MASS = Object.freeze({ mass: 1 });
50
+ /** Dimension spec for temperature (temperature^1). */
51
+ export const TEMPERATURE = Object.freeze({ temperature: 1 });
52
+ /** Dimension spec for time (time^1). */
53
+ export const TIME = Object.freeze({ time: 1 });
54
+ /** Dimension spec for electric current (current^1). */
55
+ export const CURRENT = Object.freeze({ current: 1 });
56
+ /**
57
+ * The dimension spec of a named base dimension.
58
+ * @param dim - a base dimension name.
59
+ * @returns the corresponding `UnitSpec`.
60
+ */
61
+ export function specOfDim(dim) {
62
+ switch (dim) {
63
+ case 'length': return LENGTH;
64
+ case 'angle': return ANGLE;
65
+ case 'mass': return MASS;
66
+ case 'temperature': return TEMPERATURE;
67
+ case 'time': return TIME;
68
+ case 'current': return CURRENT;
69
+ }
70
+ }
71
+ /**
72
+ * A value carrying an immutable dimension. All arithmetic is method-style —
73
+ * there is no operator overloading in TS. `value` is always expressed in the
74
+ * base unit of its dimension.
75
+ */
76
+ export class ValueWithUnits {
77
+ /** The numeric magnitude, always expressed in the base unit of the dimension. */
78
+ value;
79
+ /** The dimension spec (which base dimensions are present and with what exponent). */
80
+ spec;
81
+ constructor(value, spec) {
82
+ this.value = value;
83
+ this.spec = issueFrozen(spec);
84
+ }
85
+ /**
86
+ * Add another value; both must share the same dimension.
87
+ * @param rhs - the value to add (must have the same dimension).
88
+ * @returns a new `ValueWithUnits` whose value is `this.value + rhs.value`.
89
+ */
90
+ add(rhs) {
91
+ requireSameDim(this, rhs, 'add');
92
+ return new ValueWithUnits(this.value + rhs.value, this.spec);
93
+ }
94
+ /**
95
+ * Subtract another value; both must share the same dimension.
96
+ * @param rhs - the value to subtract (must have the same dimension).
97
+ * @returns a new `ValueWithUnits` whose value is `this.value - rhs.value`.
98
+ */
99
+ sub(rhs) {
100
+ requireSameDim(this, rhs, 'sub');
101
+ return new ValueWithUnits(this.value - rhs.value, this.spec);
102
+ }
103
+ /**
104
+ * Negate.
105
+ * @returns a new `ValueWithUnits` with the negated magnitude.
106
+ */
107
+ neg() {
108
+ return new ValueWithUnits(-this.value, this.spec);
109
+ }
110
+ /**
111
+ * Scale by a dimensionless number.
112
+ * @param n - a dimensionless scalar.
113
+ * @returns a new `ValueWithUnits` with the scaled magnitude.
114
+ */
115
+ mul(n) {
116
+ return new ValueWithUnits(this.value * n, this.spec);
117
+ }
118
+ /**
119
+ * Divide by a dimensionless number.
120
+ * @param n - a dimensionless scalar.
121
+ * @returns a new `ValueWithUnits` with the divided magnitude.
122
+ */
123
+ div(n) {
124
+ return new ValueWithUnits(this.value / n, this.spec);
125
+ }
126
+ /**
127
+ * The ratio to another value of the same dimension (dimensionless result).
128
+ * @param rhs - the divisor (must have the same dimension).
129
+ * @returns the dimensionless ratio `this.value / rhs.value`.
130
+ */
131
+ divBy(rhs) {
132
+ requireSameDim(this, rhs, 'divBy');
133
+ return this.value / rhs.value;
134
+ }
135
+ /**
136
+ * Raise to an integer power; each exponent times n must stay an integer.
137
+ * @param n - the integer power.
138
+ * @returns a new `ValueWithUnits` with exponents multiplied by `n`.
139
+ */
140
+ pow(n) {
141
+ if (!Number.isInteger(n)) {
142
+ throw dimensionalError('pow exponent must be an integer', this);
143
+ }
144
+ const out = { length: 0, angle: 0, mass: 0, temperature: 0, time: 0, current: 0 };
145
+ for (const dim of ALL_DIMS) {
146
+ const e = this.spec[dim] ?? 0;
147
+ const ne = e * n;
148
+ if (!Number.isInteger(ne)) {
149
+ throw new Error(`[units] pow(${n}) would produce a non-integer exponent ${ne} for dimension ${dim}`);
150
+ }
151
+ out[dim] = ne;
152
+ }
153
+ return new ValueWithUnits(this.value ** n, normalizeSpec(out));
154
+ }
155
+ /**
156
+ * Extract the numeric magnitude expressed in another unit (dimension must match).
157
+ * @param unit - a `ValueWithUnits` representing 1 of the target unit.
158
+ * @returns the magnitude in that unit.
159
+ */
160
+ as(unit) {
161
+ requireSameDim(this, unit, 'as');
162
+ return this.value / unit.value;
163
+ }
164
+ /**
165
+ * True when the magnitude is ~0 (within an optional same-dimension epsilon).
166
+ * @param eps - optional same-dimension epsilon; defaults to 1e-9 base units.
167
+ * @returns `true` when `|value| <= eps`.
168
+ */
169
+ eqZero(eps) {
170
+ if (eps === undefined) {
171
+ // Default epsilon is one atomic stride of the base unit.
172
+ return Math.abs(this.value) <= 1e-9;
173
+ }
174
+ requireSameDim(this, eps, 'eqZero');
175
+ return Math.abs(this.value) <= Math.abs(eps.value);
176
+ }
177
+ }
178
+ /** Builder for an error that carries both dimensions of a mismatch. */
179
+ function dimensionalError(action, a, b) {
180
+ const extras = b === undefined ? '' : ` vs {${describeSpec(b.spec)}}`;
181
+ return new Error(`[units] dimension mismatch in \`${action}\`: {${describeSpec(a.spec)}}${extras}`);
182
+ }
183
+ function requireSameDim(a, b, action) {
184
+ if (!unitEquals(a.spec, b.spec))
185
+ throw dimensionalError(action, a, b);
186
+ }
187
+ function describeSpec(spec) {
188
+ const parts = ALL_DIMS.filter((d) => (spec[d] ?? 0) !== 0)
189
+ .map((d) => `${d}^${spec[d]}`);
190
+ return parts.length ? parts.join('·') : 'dimensionless';
191
+ }
192
+ /** Freeze a spec; never expose a mutable spec to callers. */
193
+ function issueFrozen(spec) {
194
+ return Object.freeze({ ...spec });
195
+ }
196
+ function normalizeSpec(spec) {
197
+ return Object.freeze({ ...spec });
198
+ }
199
+ // ── Single-source-of-truth tables ──────────────────────────────────────────
200
+ // `UNIT_SCALE` + `UNIT_DIM` are the only data. `UNIT_DIMS`, the typed
201
+ // constants, the pure-number constants and everything else derive from them.
202
+ /**
203
+ * Unit name → base-unit scale factor. `length`: 1 mm; `angle`: 1 degree;
204
+ * `mass`: 1 gram; `time`: 1 second.
205
+ */
206
+ export const UNIT_SCALE = Object.freeze({
207
+ // length (base = mm)
208
+ mm: 1,
209
+ cm: 10,
210
+ m: 1000,
211
+ micron: 0.001,
212
+ inch: 25.4,
213
+ foot: 304.8,
214
+ yard: 914.4,
215
+ // angle (base = degree)
216
+ degree: 1,
217
+ radian: 180 / Math.PI,
218
+ // mass (base = gram)
219
+ gram: 1,
220
+ kilogram: 1000,
221
+ // time (base = second)
222
+ second: 1,
223
+ });
224
+ /** Unit name → the dimension it measures. */
225
+ export const UNIT_DIM = Object.freeze({
226
+ mm: 'length', cm: 'length', m: 'length', micron: 'length',
227
+ inch: 'length', foot: 'length', yard: 'length',
228
+ degree: 'angle', radian: 'angle',
229
+ gram: 'mass', kilogram: 'mass',
230
+ second: 'time',
231
+ });
232
+ /** Derived: unit name → UnitSpec. */
233
+ export const UNIT_DIMS = Object.freeze(Object.keys(UNIT_SCALE).reduce((acc, name) => {
234
+ acc[name] = specOfDim(UNIT_DIM[name]);
235
+ return acc;
236
+ }, {}));
237
+ // ── Script-side unit constants (D7) ──────────────────────────────────────────
238
+ // These are the bare-number constants available in .fai.js scripts.
239
+ // `cm` and `meter` are script-friendly aliases for UNIT_SCALE keys `cm` and `m`.
240
+ // The value is the base-unit scale factor (= UNIT_SCALE[name] for most, except
241
+ // `meter` which maps to `m`).
242
+ /**
243
+ * Script-side unit constant names → their numeric values (base-unit scale).
244
+ * These are registered as global read-only constants in the script runtime.
245
+ * All names are UPPERCASE to avoid collisions with user variable names
246
+ * (e.g. `cm` as center-of-mass would clash with `cm` as centimeter).
247
+ * `10 * INCH` in a script evaluates to `10 * 25.4 === 254` (plain JS multiply).
248
+ */
249
+ export const SCRIPT_UNIT_CONSTANTS = Object.freeze({
250
+ MM: 1,
251
+ CM: 10,
252
+ METER: 1000,
253
+ MICRON: 0.001,
254
+ INCH: 25.4,
255
+ FOOT: 304.8,
256
+ YARD: 914.4,
257
+ DEGREE: 1,
258
+ RADIAN: 180 / Math.PI,
259
+ GRAM: 1,
260
+ KILOGRAM: 1000,
261
+ SECOND: 1,
262
+ });
263
+ /**
264
+ * Mapping from script-side unit constant names (UPPERCASE) to the internal
265
+ * `UnitName` (lowercase, used by UNIT_SCALE/UNIT_DIM for format-level units).
266
+ * Used by the dimension checker to resolve a script constant to its dimension.
267
+ */
268
+ export const SCRIPT_UNIT_TO_NAME = Object.freeze({
269
+ MM: 'mm', CM: 'cm', METER: 'm', MICRON: 'micron',
270
+ INCH: 'inch', FOOT: 'foot', YARD: 'yard',
271
+ DEGREE: 'degree', RADIAN: 'radian',
272
+ GRAM: 'gram', KILOGRAM: 'kilogram',
273
+ SECOND: 'second',
274
+ });
275
+ /** The set of script-side unit constant names (for fast membership tests). */
276
+ export const SCRIPT_UNIT_NAMES = new Set(Object.keys(SCRIPT_UNIT_CONSTANTS));
277
+ // ── Typed constants (ValueWithUnits) ────────────────────────────────────────
278
+ /** 1 mm — the base length unit. */
279
+ export const mm = new ValueWithUnits(1, LENGTH);
280
+ /** 1 cm = 10 mm. */
281
+ export const centimeter = new ValueWithUnits(10, LENGTH);
282
+ /** 1 m = 1000 mm. */
283
+ export const meter = new ValueWithUnits(1000, LENGTH);
284
+ /** 1 micron = 0.001 mm (one of the 3MF unit enum values). */
285
+ export const micron = new ValueWithUnits(0.001, LENGTH);
286
+ /** 1 inch = 25.4 mm. */
287
+ export const inch = new ValueWithUnits(25.4, LENGTH);
288
+ /** 1 foot = 304.8 mm. */
289
+ export const foot = new ValueWithUnits(304.8, LENGTH);
290
+ /** 1 yard = 914.4 mm. */
291
+ export const yard = new ValueWithUnits(914.4, LENGTH);
292
+ /** The base angle unit — 1 degree. */
293
+ export const degree = new ValueWithUnits(1, ANGLE);
294
+ /** 1 radian = 180/π degrees (base is degree). */
295
+ export const radian = new ValueWithUnits(180 / Math.PI, ANGLE);
296
+ /** 1 gram (base mass unit). */
297
+ export const gram = new ValueWithUnits(1, MASS);
298
+ /** 1 kilogram = 1000 gram. */
299
+ export const kilogram = new ValueWithUnits(1000, MASS);
300
+ /** 1 second (base time unit). */
301
+ export const second = new ValueWithUnits(1, TIME);
302
+ // ── Pure-number constants (number) = base-unit scale ────────────────────────
303
+ // TS library code that calls geometric ops directly uses these bare numbers
304
+ // (D4): `const L = 10 * INCH; cad.box({ size: [L, 20 * MM, 30 * MM] })`.
305
+ /** 1 (mm). */
306
+ export const MM = 1;
307
+ /** 10 (mm). */
308
+ export const CM = 10;
309
+ /** 1000 (mm). */
310
+ export const M = 1000;
311
+ /** 0.001 (mm). */
312
+ export const MICRON = 0.001;
313
+ /** 25.4 (mm). */
314
+ export const INCH = 25.4;
315
+ /** 304.8 (mm). */
316
+ export const FOOT = 304.8;
317
+ /** 914.4 (mm). */
318
+ export const YARD = 914.4;
319
+ /** 1 (degree). */
320
+ export const DEGREE = 1;
321
+ /** 180/π (degree). */
322
+ export const RADIAN = 180 / Math.PI;
323
+ /** Base display units (mm / degree). */
324
+ export const BASE_UNITS = Object.freeze({ length: 'mm', angle: 'degree' });
325
+ /**
326
+ * The display unit for a dimension within a context. Only `length` and
327
+ * `angle` are host-settable; all other dimensions fall back to their base unit.
328
+ * @param dim - the dimension to look up.
329
+ * @param ctx - the system unit context; defaults to base units.
330
+ * @returns the unit name.
331
+ */
332
+ export function unitFor(dim, ctx) {
333
+ if (dim === 'length' || dim === 'angle') {
334
+ return (ctx ?? BASE_UNITS)[dim];
335
+ }
336
+ // mass / temperature / time / current have no display override → their base.
337
+ switch (dim) {
338
+ case 'mass': return 'gram';
339
+ case 'temperature': return 'kelvin';
340
+ case 'time': return 'second';
341
+ case 'current': return 'ampere';
342
+ default: return 'mm';
343
+ }
344
+ }
345
+ /**
346
+ * Scale factor of a unit name relative to the base unit.
347
+ * @param name - the unit name.
348
+ * @returns the scale factor (e.g. `inch` → `25.4`).
349
+ */
350
+ export function unitScale(name) {
351
+ return UNIT_SCALE[name];
352
+ }
353
+ /**
354
+ * Convert a value given in a display unit to the base-unit value.
355
+ * @param n - the value in `unitName`.
356
+ * @param unitName - the source unit.
357
+ * @param dimensionName - the dimension (for validation).
358
+ * @returns the base-unit (mm/degree/...) value.
359
+ */
360
+ export function toBase(n, unitName, dimensionName) {
361
+ requireDim(unitName, dimensionName);
362
+ return n * UNIT_SCALE[unitName];
363
+ }
364
+ /**
365
+ * Convert a base-unit value into a display unit.
366
+ * @param base - the base-unit (mm/degree/...) value.
367
+ * @param unitName - the target unit.
368
+ * @param dimensionName - the dimension (for validation).
369
+ * @returns the value expressed in `unitName`.
370
+ */
371
+ export function fromBase(base, unitName, dimensionName) {
372
+ requireDim(unitName, dimensionName);
373
+ return base / UNIT_SCALE[unitName];
374
+ }
375
+ /** Throw when a unit is not a member of a dimension. */
376
+ function requireDim(unitName, dimensionName) {
377
+ if (UNIT_DIM[unitName] !== dimensionName) {
378
+ throw new Error(`[units] unit '${unitName}' is ${UNIT_DIM[unitName]}; expected ${dimensionName}`);
379
+ }
380
+ }
381
+ /**
382
+ * True when the value has dimension length.
383
+ * @param v - the value to check.
384
+ * @returns `true` if `v.spec` equals `LENGTH`.
385
+ */
386
+ export function isLength(v) {
387
+ return unitEquals(v.spec, LENGTH);
388
+ }
389
+ /**
390
+ * True when the value has dimension angle.
391
+ * @param v - the value to check.
392
+ * @returns `true` if `v.spec` equals `ANGLE`.
393
+ */
394
+ export function isAngle(v) {
395
+ return unitEquals(v.spec, ANGLE);
396
+ }
397
+ //# sourceMappingURL=units.js.map