@mlightcad/data-model 1.7.34 → 1.7.36
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/data-model.cjs +6 -6
- package/dist/data-model.js +3174 -2708
- package/lib/converter/AcDbDxfConverter.d.ts.map +1 -1
- package/lib/converter/AcDbDxfConverter.js +20 -9
- package/lib/converter/AcDbDxfConverter.js.map +1 -1
- package/lib/converter/AcDbEntitiyConverter.d.ts.map +1 -1
- package/lib/converter/AcDbEntitiyConverter.js +3 -7
- package/lib/converter/AcDbEntitiyConverter.js.map +1 -1
- package/lib/database/AcDbDatabase.d.ts +127 -11
- package/lib/database/AcDbDatabase.d.ts.map +1 -1
- package/lib/database/AcDbDatabase.js +200 -18
- package/lib/database/AcDbDatabase.js.map +1 -1
- package/lib/database/AcDbSysVarManager.d.ts +1 -0
- package/lib/database/AcDbSysVarManager.d.ts.map +1 -1
- package/lib/database/AcDbSysVarManager.js +126 -15
- package/lib/database/AcDbSysVarManager.js.map +1 -1
- package/lib/database/AcDbSystemVariables.d.ts +25 -9
- package/lib/database/AcDbSystemVariables.d.ts.map +1 -1
- package/lib/database/AcDbSystemVariables.js +24 -8
- package/lib/database/AcDbSystemVariables.js.map +1 -1
- package/lib/misc/AcDbConstants.d.ts +26 -0
- package/lib/misc/AcDbConstants.d.ts.map +1 -1
- package/lib/misc/AcDbConstants.js +9 -0
- package/lib/misc/AcDbConstants.js.map +1 -1
- package/lib/misc/AcDbFormatter.d.ts +215 -0
- package/lib/misc/AcDbFormatter.d.ts.map +1 -0
- package/lib/misc/AcDbFormatter.js +863 -0
- package/lib/misc/AcDbFormatter.js.map +1 -0
- package/lib/misc/AcDbLinearUnits.d.ts +21 -0
- package/lib/misc/AcDbLinearUnits.d.ts.map +1 -0
- package/lib/misc/AcDbLinearUnits.js +22 -0
- package/lib/misc/AcDbLinearUnits.js.map +1 -0
- package/lib/misc/index.d.ts +2 -0
- package/lib/misc/index.d.ts.map +1 -1
- package/lib/misc/index.js +2 -0
- package/lib/misc/index.js.map +1 -1
- package/lib/misc/pat/AcDbPatSvgRenderer.d.ts.map +1 -1
- package/lib/misc/pat/AcDbPatSvgRenderer.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,863 @@
|
|
|
1
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
2
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
3
|
+
if (!m) return o;
|
|
4
|
+
var i = m.call(o), r, ar = [], e;
|
|
5
|
+
try {
|
|
6
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
7
|
+
}
|
|
8
|
+
catch (error) { e = { error: error }; }
|
|
9
|
+
finally {
|
|
10
|
+
try {
|
|
11
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
12
|
+
}
|
|
13
|
+
finally { if (e) throw e.error; }
|
|
14
|
+
}
|
|
15
|
+
return ar;
|
|
16
|
+
};
|
|
17
|
+
import { AcGeMathUtil } from '@mlightcad/geometry-engine';
|
|
18
|
+
import { AcDbAngleUnits } from './AcDbAngleUnits';
|
|
19
|
+
import { AcDbLinearUnits } from './AcDbLinearUnits';
|
|
20
|
+
import { AcDbUnitsValue, isImperialUnits, isMetricUnits } from './AcDbUnitsValue';
|
|
21
|
+
/** Radians per gradian (400 grads = full circle). */
|
|
22
|
+
var RAD_PER_GRAD = Math.PI / 200;
|
|
23
|
+
/**
|
|
24
|
+
* Formats linear distances, point coordinates, and angles for display in the UI,
|
|
25
|
+
* matching AutoCAD drawing-unit behavior as closely as the supported system variables allow.
|
|
26
|
+
*
|
|
27
|
+
* An instance is bound to one {@link AcDbDatabase}. On each call it reads the current values of
|
|
28
|
+
* the relevant header/system variables from that database (not a snapshot taken at construction).
|
|
29
|
+
*
|
|
30
|
+
* ### Linear distances and coordinates
|
|
31
|
+
*
|
|
32
|
+
* | Variable | Role |
|
|
33
|
+
* |----------|------|
|
|
34
|
+
* | **LUNITS** | Display format (scientific, decimal, engineering, …); see {@link AcDbDatabase.lunits} |
|
|
35
|
+
* | **LUPREC** | Precision (decimal places or fractional denominator); see {@link AcDbDatabase.luprec} |
|
|
36
|
+
* | **INSUNITS** | Unit suffix when {@link AcDbFormatterOptions.showUnits} is `true`; see {@link AcDbDatabase.insunits} |
|
|
37
|
+
* | **UNITMODE** | Report vs input delimiters for feet-inch and fractions; see {@link AcDbDatabase.unitmode} |
|
|
38
|
+
* | **MEASUREMENT** | Imperial vs metric suffix when **INSUNITS** is unitless; see {@link AcDbDatabase.measurement} |
|
|
39
|
+
*
|
|
40
|
+
* Engineering (**LUNITS** = 3) and architectural (**LUNITS** = 4) formats treat the numeric
|
|
41
|
+
* value as **inches**, consistent with AutoCAD.
|
|
42
|
+
*
|
|
43
|
+
* ### Angles
|
|
44
|
+
*
|
|
45
|
+
* Input angles are **radians in WCS**. Before formatting, the value is adjusted by
|
|
46
|
+
* {@link AcDbDatabase.angbase | ANGBASE} and {@link AcDbDatabase.angdir | ANGDIR}, then converted
|
|
47
|
+
* per {@link AcDbDatabase.aunits | AUNITS} and {@link AcDbDatabase.auprec | AUPREC}.
|
|
48
|
+
*
|
|
49
|
+
* ### Out of scope
|
|
50
|
+
*
|
|
51
|
+
* Dimension entity text uses per-style **DIM\*** variables (for example **DIMLUNIT**, **DIMDEC**),
|
|
52
|
+
* not this class. **SNAPANG** and UCS settings affect snapping/input, not WCS coordinate strings here.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* database.lunits = AcDbLinearUnits.Decimal;
|
|
57
|
+
* database.luprec = 2;
|
|
58
|
+
*
|
|
59
|
+
* database.formatter.formatLength(12.3456); // "12.35"
|
|
60
|
+
* database.formatter.formatLength(12.3456, { showUnits: true }); // "12.35 mm" (with INSUNITS = mm)
|
|
61
|
+
* database.formatter.formatPoint2d(new AcGePoint2d(1, 2)); // "1, 2"
|
|
62
|
+
* database.formatter.formatAngle(Math.PI / 4, { showUnits: true }); // "45°"
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
var AcDbFormatter = /** @class */ (function () {
|
|
66
|
+
/**
|
|
67
|
+
* Creates a formatter that reads unit settings from the given database.
|
|
68
|
+
*
|
|
69
|
+
* @param database - Drawing database whose **LUNITS**, **AUNITS**, and related variables
|
|
70
|
+
* are consulted on every format call.
|
|
71
|
+
*/
|
|
72
|
+
function AcDbFormatter(database) {
|
|
73
|
+
this.database = database;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Formats a single linear distance in **drawing units**.
|
|
77
|
+
*
|
|
78
|
+
* The output pattern follows {@link AcDbDatabase.lunits | LUNITS} and
|
|
79
|
+
* {@link AcDbDatabase.luprec | LUPREC}. When {@link AcDbFormatterOptions.showUnits} is `true`,
|
|
80
|
+
* a suffix may be appended based on {@link AcDbDatabase.insunits | INSUNITS} and
|
|
81
|
+
* {@link AcDbDatabase.measurement | MEASUREMENT}.
|
|
82
|
+
*
|
|
83
|
+
* | **LUNITS** | Typical output (no unit suffix) |
|
|
84
|
+
* |-----------:|--------------------------------|
|
|
85
|
+
* | `1` Scientific | `1.23E+02` |
|
|
86
|
+
* | `2` Decimal | `12.35` |
|
|
87
|
+
* | `3` Engineering | `1'-3.5` (value interpreted as inches) |
|
|
88
|
+
* | `4` Architectural | `1'-3 1/2` |
|
|
89
|
+
* | `5` Fractional | `15 1/2` |
|
|
90
|
+
* | `6` Windows desktop | Same as decimal |
|
|
91
|
+
*
|
|
92
|
+
* {@link AcDbDatabase.unitmode | UNITMODE} changes delimiters for engineering, architectural,
|
|
93
|
+
* and fractional modes (for example `1'3-1/2` when **UNITMODE** = 1).
|
|
94
|
+
*
|
|
95
|
+
* @param value - Distance in drawing units (WCS length, not pre-converted to feet or degrees).
|
|
96
|
+
* @param options - Optional display flags; see {@link AcDbFormatterOptions}.
|
|
97
|
+
* @returns Formatted string suitable for status bars, measurement overlays, or tooltips.
|
|
98
|
+
*
|
|
99
|
+
* @remarks
|
|
100
|
+
* Non-finite values (`NaN`, `±Infinity`) are formatted as `"0"`.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* database.lunits = AcDbLinearUnits.Architectural;
|
|
105
|
+
* database.luprec = 2;
|
|
106
|
+
* formatter.formatLength(15.5); // "1'-3 1/2"
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
AcDbFormatter.prototype.formatLength = function (value, options) {
|
|
110
|
+
var ctx = this.createContext(options);
|
|
111
|
+
return formatLengthWithContext(value, ctx);
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Formats a 2D point as `"x, y"`, formatting each component with {@link formatLength}.
|
|
115
|
+
*
|
|
116
|
+
* Both coordinates use the same {@link AcDbDatabase.lunits | LUNITS} / **LUPREC** rules and the
|
|
117
|
+
* same {@link AcDbFormatterOptions} for the call. The separator is a comma followed by a space
|
|
118
|
+
* (`, `), which matches common Cartesian display in measurement UIs.
|
|
119
|
+
*
|
|
120
|
+
* @param point - Point in drawing units (WCS **x** / **y**).
|
|
121
|
+
* @param options - Optional display flags applied to each coordinate.
|
|
122
|
+
* @returns Formatted coordinate pair, for example `"1.2, 4.6"` or `"1'-0, 2'-6"` depending on **LUNITS**.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* database.lunits = AcDbLinearUnits.Decimal;
|
|
127
|
+
* database.luprec = 1;
|
|
128
|
+
* formatter.formatPoint2d(new AcGePoint2d(1.23, 4.56)); // "1.2, 4.6"
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
AcDbFormatter.prototype.formatPoint2d = function (point, options) {
|
|
132
|
+
var ctx = this.createContext(options);
|
|
133
|
+
return "".concat(formatLengthWithContext(point.x, ctx), ", ").concat(formatLengthWithContext(point.y, ctx));
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Formats a 3D point as `"x, y, z"`, formatting each component with {@link formatLength}.
|
|
137
|
+
*
|
|
138
|
+
* Behavior is the same as {@link formatPoint2d} for **x** and **y**, with **z** appended using
|
|
139
|
+
* the same linear formatting and options.
|
|
140
|
+
*
|
|
141
|
+
* @param point - Point in drawing units (WCS **x** / **y** / **z**).
|
|
142
|
+
* @param options - Optional display flags applied to each coordinate.
|
|
143
|
+
* @returns Formatted coordinate triple, for example `"1.2, 4.6, 7.9"`.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```typescript
|
|
147
|
+
* formatter.formatPoint3d(new AcGePoint3d(1, 2, 3)); // "1, 2, 3" (with default decimal LUNITS)
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
AcDbFormatter.prototype.formatPoint3d = function (point, options) {
|
|
151
|
+
var ctx = this.createContext(options);
|
|
152
|
+
return "".concat(formatLengthWithContext(point.x, ctx), ", ").concat(formatLengthWithContext(point.y, ctx), ", ").concat(formatLengthWithContext(point.z, ctx));
|
|
153
|
+
};
|
|
154
|
+
/**
|
|
155
|
+
* Formats an angle given in **radians** (WCS), for display according to the drawing angle units.
|
|
156
|
+
*
|
|
157
|
+
* Processing order:
|
|
158
|
+
* 1. Subtract {@link AcDbDatabase.angbase | ANGBASE} (zero direction).
|
|
159
|
+
* 2. Negate if {@link AcDbDatabase.angdir | ANGDIR} = 1 (clockwise positive).
|
|
160
|
+
* 3. Normalize to \([0, 2\pi)\) via {@link AcGeMathUtil.normalizeAngle}.
|
|
161
|
+
* 4. Format using {@link AcDbDatabase.aunits | AUNITS} and {@link AcDbDatabase.auprec | AUPREC}.
|
|
162
|
+
*
|
|
163
|
+
* | **AUNITS** | Typical output (no unit suffix) |
|
|
164
|
+
* |-----------:|--------------------------------|
|
|
165
|
+
* | `0` Decimal degrees | `45` or `45.5` |
|
|
166
|
+
* | `1` Degrees/minutes/seconds | `45d30'15"` |
|
|
167
|
+
* | `2` Gradians | `50` |
|
|
168
|
+
* | `3` Radians | `0.785` |
|
|
169
|
+
* | `4` Surveyor's | `N 45d30'15" E` |
|
|
170
|
+
*
|
|
171
|
+
* @param radians - Angle in radians. When {@link AcDbFormatterOptions.applyAngbaseAngdir} is
|
|
172
|
+
* `true` (default), this is an absolute WCS angle (counterclockwise from +X before
|
|
173
|
+
* **ANGBASE** / **ANGDIR** adjustment). When `false`, this is the scalar angle to display.
|
|
174
|
+
* @param options - Optional display flags; when {@link AcDbFormatterOptions.showUnits} is `true`,
|
|
175
|
+
* unit markers such as `°`, `g`, or `rad` may be appended.
|
|
176
|
+
* @returns Formatted angle string.
|
|
177
|
+
*
|
|
178
|
+
* @remarks
|
|
179
|
+
* For included or relative angles, pass {@link AcDbFormatterOptions.applyAngbaseAngdir} = `false`.
|
|
180
|
+
* For arc sweep or dimension overrides, supply the appropriate radians value and flags.
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```typescript
|
|
184
|
+
* database.aunits = AcDbAngleUnits.DecimalDegrees;
|
|
185
|
+
* database.auprec = 0;
|
|
186
|
+
* formatter.formatAngle(Math.PI / 4); // "45"
|
|
187
|
+
* formatter.formatAngle(Math.PI / 4, { showUnits: true }); // "45°"
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
AcDbFormatter.prototype.formatAngle = function (radians, options) {
|
|
191
|
+
var _a;
|
|
192
|
+
var ctx = this.createContext(options);
|
|
193
|
+
var applyAngbaseAngdir = (_a = options === null || options === void 0 ? void 0 : options.applyAngbaseAngdir) !== null && _a !== void 0 ? _a : true;
|
|
194
|
+
var displayRadians = applyAngbaseAngdir
|
|
195
|
+
? toDisplayAngleRadians(radians, this.database.angbase, this.database.angdir)
|
|
196
|
+
: AcGeMathUtil.normalizeAngle(radians);
|
|
197
|
+
return formatAngleWithContext(displayRadians, ctx);
|
|
198
|
+
};
|
|
199
|
+
/**
|
|
200
|
+
* Builds the formatting context from the bound database and call options.
|
|
201
|
+
*
|
|
202
|
+
* @param options - Per-call overrides; omitted fields use database defaults.
|
|
203
|
+
* @returns Snapshot of linear and angular unit settings for one format call.
|
|
204
|
+
* @internal
|
|
205
|
+
*/
|
|
206
|
+
AcDbFormatter.prototype.createContext = function (options) {
|
|
207
|
+
var _a, _b;
|
|
208
|
+
return {
|
|
209
|
+
lunits: this.database.lunits,
|
|
210
|
+
luprec: clampPrecision(this.database.luprec),
|
|
211
|
+
insunits: this.database.insunits,
|
|
212
|
+
unitmode: this.database.unitmode,
|
|
213
|
+
measurement: this.database.measurement,
|
|
214
|
+
aunits: this.database.aunits,
|
|
215
|
+
auprec: clampPrecision(this.database.auprec),
|
|
216
|
+
showUnits: (_a = options === null || options === void 0 ? void 0 : options.showUnits) !== null && _a !== void 0 ? _a : false,
|
|
217
|
+
showApproximate: (_b = options === null || options === void 0 ? void 0 : options.showApproximate) !== null && _b !== void 0 ? _b : false
|
|
218
|
+
};
|
|
219
|
+
};
|
|
220
|
+
return AcDbFormatter;
|
|
221
|
+
}());
|
|
222
|
+
export { AcDbFormatter };
|
|
223
|
+
/**
|
|
224
|
+
* Formats one linear distance using a pre-built {@link AcDbFormatContext}.
|
|
225
|
+
*
|
|
226
|
+
* @param value - Distance in drawing units.
|
|
227
|
+
* @param ctx - Unit settings snapshot for this call.
|
|
228
|
+
* @returns Formatted linear string.
|
|
229
|
+
* @internal
|
|
230
|
+
*/
|
|
231
|
+
function formatLengthWithContext(value, ctx) {
|
|
232
|
+
var formatted;
|
|
233
|
+
switch (ctx.lunits) {
|
|
234
|
+
case AcDbLinearUnits.Scientific:
|
|
235
|
+
formatted = appendLinearUnitSuffix(formatScientific(value, ctx.luprec), ctx);
|
|
236
|
+
break;
|
|
237
|
+
case AcDbLinearUnits.Engineering:
|
|
238
|
+
formatted = formatEngineering(value, ctx);
|
|
239
|
+
break;
|
|
240
|
+
case AcDbLinearUnits.Architectural:
|
|
241
|
+
formatted = formatArchitectural(value, ctx);
|
|
242
|
+
break;
|
|
243
|
+
case AcDbLinearUnits.Fractional:
|
|
244
|
+
formatted = appendLinearUnitSuffix(formatFractionalLinear(value, ctx), ctx);
|
|
245
|
+
break;
|
|
246
|
+
case AcDbLinearUnits.WindowsDesktop:
|
|
247
|
+
case AcDbLinearUnits.Decimal:
|
|
248
|
+
default:
|
|
249
|
+
formatted = appendLinearUnitSuffix(formatDecimal(value, ctx.luprec), ctx);
|
|
250
|
+
}
|
|
251
|
+
return applyApproximatePrefix(formatted, isLinearValueApproximate(value, ctx), ctx);
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Formats one angle (already adjusted for **ANGBASE** / **ANGDIR**) using {@link AcDbFormatContext}.
|
|
255
|
+
*
|
|
256
|
+
* @param radians - Display angle in radians, in range \([0, 2\pi)\).
|
|
257
|
+
* @param ctx - Unit settings snapshot for this call.
|
|
258
|
+
* @returns Formatted angle string.
|
|
259
|
+
* @internal
|
|
260
|
+
*/
|
|
261
|
+
function formatAngleWithContext(radians, ctx) {
|
|
262
|
+
var formatted;
|
|
263
|
+
switch (ctx.aunits) {
|
|
264
|
+
case AcDbAngleUnits.DegreesMinutesSeconds:
|
|
265
|
+
formatted = formatAngleDms(radians, ctx);
|
|
266
|
+
break;
|
|
267
|
+
case AcDbAngleUnits.Gradians:
|
|
268
|
+
formatted = formatAngleGradians(radians, ctx);
|
|
269
|
+
break;
|
|
270
|
+
case AcDbAngleUnits.Radians:
|
|
271
|
+
formatted = formatAngleRadians(radians, ctx);
|
|
272
|
+
break;
|
|
273
|
+
case AcDbAngleUnits.SurveyorsUnits:
|
|
274
|
+
formatted = formatAngleSurveyor(radians, ctx);
|
|
275
|
+
break;
|
|
276
|
+
case AcDbAngleUnits.DecimalDegrees:
|
|
277
|
+
default:
|
|
278
|
+
formatted = formatAngleDecimalDegrees(radians, ctx);
|
|
279
|
+
}
|
|
280
|
+
return applyApproximatePrefix(formatted, isAngleValueApproximate(radians, ctx), ctx);
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Converts a WCS angle to the drawing's display angle before **AUNITS** formatting.
|
|
284
|
+
*
|
|
285
|
+
* @param radians - Raw angle in radians (WCS, counterclockwise from +X).
|
|
286
|
+
* @param angbase - **ANGBASE** zero direction in radians.
|
|
287
|
+
* @param angdir - **ANGDIR** (`0` = CCW positive, `1` = CW positive).
|
|
288
|
+
* @returns Normalized display angle in radians.
|
|
289
|
+
* @internal
|
|
290
|
+
*/
|
|
291
|
+
function toDisplayAngleRadians(radians, angbase, angdir) {
|
|
292
|
+
var angle = radians - angbase;
|
|
293
|
+
if (angdir === 1) {
|
|
294
|
+
angle = -angle;
|
|
295
|
+
}
|
|
296
|
+
return AcGeMathUtil.normalizeAngle(angle);
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Resolves feet-inch delimiters from **UNITMODE** and {@link AcDbFormatContext.showUnits}.
|
|
300
|
+
*
|
|
301
|
+
* @param ctx - Formatting context.
|
|
302
|
+
* @returns Delimiter pattern for imperial linear modes.
|
|
303
|
+
* @internal
|
|
304
|
+
*/
|
|
305
|
+
function imperialDelimiterStyle(ctx) {
|
|
306
|
+
var inchSuffix = ctx.showUnits ? '"' : '';
|
|
307
|
+
if (ctx.unitmode === 1) {
|
|
308
|
+
return {
|
|
309
|
+
feetInchSeparator: '',
|
|
310
|
+
fractionSeparator: '-',
|
|
311
|
+
inchSuffix: inchSuffix
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
return {
|
|
315
|
+
feetInchSeparator: '-',
|
|
316
|
+
fractionSeparator: ' ',
|
|
317
|
+
inchSuffix: inchSuffix
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Rounds and clamps a precision value to a safe integer range.
|
|
322
|
+
*
|
|
323
|
+
* @param value - Raw precision (for example **LUPREC** or **AUPREC**).
|
|
324
|
+
* @param min - Minimum allowed precision (default `0`).
|
|
325
|
+
* @param max - Maximum allowed precision (default `8`).
|
|
326
|
+
* @returns Clamped integer precision, or `min` when `value` is non-finite.
|
|
327
|
+
* @internal
|
|
328
|
+
*/
|
|
329
|
+
function clampPrecision(value, min, max) {
|
|
330
|
+
if (min === void 0) { min = 0; }
|
|
331
|
+
if (max === void 0) { max = 8; }
|
|
332
|
+
if (!Number.isFinite(value))
|
|
333
|
+
return min;
|
|
334
|
+
return Math.max(min, Math.min(max, Math.round(value)));
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Maps negative zero to positive zero for consistent string output.
|
|
338
|
+
*
|
|
339
|
+
* @param value - Input number.
|
|
340
|
+
* @returns `0` when `value` is `-0`, otherwise `value`.
|
|
341
|
+
* @internal
|
|
342
|
+
*/
|
|
343
|
+
function normalizeZero(value) {
|
|
344
|
+
return Object.is(value, -0) ? 0 : value;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Prefixes `~ ` when approximate display is enabled and the value was rounded.
|
|
348
|
+
*
|
|
349
|
+
* @param formatted - Fully formatted display string (including unit suffixes).
|
|
350
|
+
* @param approximate - Whether the input differs from the quantized display value.
|
|
351
|
+
* @param ctx - Formatting context.
|
|
352
|
+
* @returns Original text, or `~ ${formatted}` when flagged approximate.
|
|
353
|
+
* @internal
|
|
354
|
+
*/
|
|
355
|
+
function applyApproximatePrefix(formatted, approximate, ctx) {
|
|
356
|
+
if (!ctx.showApproximate || !approximate)
|
|
357
|
+
return formatted;
|
|
358
|
+
return "~ ".concat(formatted);
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Returns whether a linear value differs from its **LUPREC**-quantized representation.
|
|
362
|
+
*
|
|
363
|
+
* @param value - Raw distance in drawing units.
|
|
364
|
+
* @param ctx - Formatting context.
|
|
365
|
+
* @internal
|
|
366
|
+
*/
|
|
367
|
+
function isLinearValueApproximate(value, ctx) {
|
|
368
|
+
if (!Number.isFinite(value))
|
|
369
|
+
return false;
|
|
370
|
+
var quantized = quantizeLinearValue(value, ctx);
|
|
371
|
+
return differsAfterQuantization(value, quantized);
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Returns whether an angle differs from its **AUPREC**-quantized representation.
|
|
375
|
+
*
|
|
376
|
+
* @param radians - Display angle in radians (after **ANGBASE** / **ANGDIR**).
|
|
377
|
+
* @param ctx - Formatting context.
|
|
378
|
+
* @internal
|
|
379
|
+
*/
|
|
380
|
+
function isAngleValueApproximate(radians, ctx) {
|
|
381
|
+
if (!Number.isFinite(radians))
|
|
382
|
+
return false;
|
|
383
|
+
if (ctx.aunits === AcDbAngleUnits.SurveyorsUnits) {
|
|
384
|
+
return isSurveyorAngleApproximate(radians, ctx.auprec);
|
|
385
|
+
}
|
|
386
|
+
var quantized = quantizeAngleValue(radians, ctx);
|
|
387
|
+
return differsAfterQuantization(radians, quantized);
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Returns whether the surveyor deflection angle would be rounded in DMS output.
|
|
391
|
+
*
|
|
392
|
+
* @internal
|
|
393
|
+
*/
|
|
394
|
+
function isSurveyorAngleApproximate(radians, auprec) {
|
|
395
|
+
var degrees = AcGeMathUtil.radToDeg(radians);
|
|
396
|
+
var bearing = (((90 - degrees) % 360) + 360) % 360;
|
|
397
|
+
var quadrant = bearingToQuadrant(bearing);
|
|
398
|
+
var deflection = Math.min(Math.abs(bearing - quadrant.base), Math.abs(quadrant.base + 90 - bearing));
|
|
399
|
+
var deflectionRadians = AcGeMathUtil.degToRad(deflection);
|
|
400
|
+
var quantizedDeflection = quantizeAngleDmsRadians(deflectionRadians, auprec);
|
|
401
|
+
return differsAfterQuantization(deflectionRadians, quantizedDeflection);
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Quantizes a linear value to the precision implied by **LUNITS** and **LUPREC**.
|
|
405
|
+
*
|
|
406
|
+
* @internal
|
|
407
|
+
*/
|
|
408
|
+
function quantizeLinearValue(value, ctx) {
|
|
409
|
+
var normalized = normalizeZero(value);
|
|
410
|
+
switch (ctx.lunits) {
|
|
411
|
+
case AcDbLinearUnits.Scientific:
|
|
412
|
+
return quantizeScientific(normalized, ctx.luprec);
|
|
413
|
+
case AcDbLinearUnits.Engineering:
|
|
414
|
+
case AcDbLinearUnits.Architectural:
|
|
415
|
+
case AcDbLinearUnits.Fractional:
|
|
416
|
+
return quantizeImperialInches(normalized, ctx);
|
|
417
|
+
case AcDbLinearUnits.WindowsDesktop:
|
|
418
|
+
case AcDbLinearUnits.Decimal:
|
|
419
|
+
default:
|
|
420
|
+
return quantizeDecimal(normalized, ctx.luprec);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Quantizes an angle to the precision implied by **AUNITS** and **AUPREC**.
|
|
425
|
+
*
|
|
426
|
+
* @internal
|
|
427
|
+
*/
|
|
428
|
+
function quantizeAngleValue(radians, ctx) {
|
|
429
|
+
var normalized = normalizeZero(radians);
|
|
430
|
+
switch (ctx.aunits) {
|
|
431
|
+
case AcDbAngleUnits.DegreesMinutesSeconds:
|
|
432
|
+
return quantizeAngleDmsRadians(normalized, ctx.auprec);
|
|
433
|
+
case AcDbAngleUnits.Gradians:
|
|
434
|
+
return quantizeDecimal(normalized / RAD_PER_GRAD, ctx.auprec) * RAD_PER_GRAD;
|
|
435
|
+
case AcDbAngleUnits.Radians:
|
|
436
|
+
return quantizeDecimal(normalized, ctx.auprec);
|
|
437
|
+
case AcDbAngleUnits.DecimalDegrees:
|
|
438
|
+
default:
|
|
439
|
+
return AcGeMathUtil.degToRad(quantizeDecimal(AcGeMathUtil.radToDeg(normalized), ctx.auprec));
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Rounds a number to a fixed number of decimal places.
|
|
444
|
+
*
|
|
445
|
+
* @internal
|
|
446
|
+
*/
|
|
447
|
+
function quantizeDecimal(value, precision) {
|
|
448
|
+
if (!Number.isFinite(value))
|
|
449
|
+
return 0;
|
|
450
|
+
var factor = Math.pow(10, precision);
|
|
451
|
+
return Math.round(normalizeZero(value) * factor) / factor;
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Rounds a value to the mantissa precision used by {@link formatScientific}.
|
|
455
|
+
*
|
|
456
|
+
* @internal
|
|
457
|
+
*/
|
|
458
|
+
function quantizeScientific(value, precision) {
|
|
459
|
+
if (!Number.isFinite(value))
|
|
460
|
+
return 0;
|
|
461
|
+
var normalized = normalizeZero(value);
|
|
462
|
+
if (normalized === 0)
|
|
463
|
+
return 0;
|
|
464
|
+
var formatted = normalized.toExponential(precision);
|
|
465
|
+
return Number(formatted);
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Quantizes an inch-based length for engineering, architectural, or fractional **LUNITS**.
|
|
469
|
+
*
|
|
470
|
+
* @internal
|
|
471
|
+
*/
|
|
472
|
+
function quantizeImperialInches(inches, ctx) {
|
|
473
|
+
if (!Number.isFinite(inches))
|
|
474
|
+
return 0;
|
|
475
|
+
var sign = inches < 0 ? -1 : 1;
|
|
476
|
+
var absInches = Math.abs(inches);
|
|
477
|
+
var feet = Math.floor(absInches / 12);
|
|
478
|
+
var inchPart = absInches - feet * 12;
|
|
479
|
+
if (ctx.lunits === AcDbLinearUnits.Architectural ||
|
|
480
|
+
ctx.lunits === AcDbLinearUnits.Fractional) {
|
|
481
|
+
var denominator = 1 << clampPrecision(ctx.luprec, 0, 8);
|
|
482
|
+
var quantizedInches = quantizeFractionalInches(inchPart, denominator);
|
|
483
|
+
return sign * (feet * 12 + quantizedInches);
|
|
484
|
+
}
|
|
485
|
+
return sign * (feet * 12 + quantizeDecimal(inchPart, ctx.luprec));
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Quantizes the inch component using the same rounding as {@link formatFractionalInches}.
|
|
489
|
+
*
|
|
490
|
+
* @internal
|
|
491
|
+
*/
|
|
492
|
+
function quantizeFractionalInches(inches, denominator) {
|
|
493
|
+
var whole = Math.floor(inches);
|
|
494
|
+
var remainder = inches - whole;
|
|
495
|
+
var numerator = Math.round(remainder * denominator);
|
|
496
|
+
if (numerator >= denominator) {
|
|
497
|
+
return whole + 1;
|
|
498
|
+
}
|
|
499
|
+
return whole + numerator / denominator;
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Quantizes an angle in radians using DMS seconds precision (**AUPREC**).
|
|
503
|
+
*
|
|
504
|
+
* @internal
|
|
505
|
+
*/
|
|
506
|
+
function quantizeAngleDmsRadians(radians, auprec) {
|
|
507
|
+
var degrees = AcGeMathUtil.radToDeg(radians);
|
|
508
|
+
var sign = degrees < 0 ? -1 : 1;
|
|
509
|
+
var absDegrees = Math.abs(degrees);
|
|
510
|
+
var d = Math.floor(absDegrees);
|
|
511
|
+
var minutesFloat = (absDegrees - d) * 60;
|
|
512
|
+
var m = Math.floor(minutesFloat);
|
|
513
|
+
var seconds = quantizeDecimal((minutesFloat - m) * 60, auprec);
|
|
514
|
+
var quantizedDegrees = d + m / 60 + seconds / 3600;
|
|
515
|
+
return AcGeMathUtil.degToRad(sign * quantizedDegrees);
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Returns whether quantization changed the numeric value (beyond float noise).
|
|
519
|
+
*
|
|
520
|
+
* @internal
|
|
521
|
+
*/
|
|
522
|
+
function differsAfterQuantization(original, quantized) {
|
|
523
|
+
if (original === quantized)
|
|
524
|
+
return false;
|
|
525
|
+
var scale = Math.max(Math.abs(original), Math.abs(quantized), 1);
|
|
526
|
+
return Math.abs(original - quantized) > scale * Number.EPSILON * 8;
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Formats a number in plain decimal form with trailing zeros trimmed.
|
|
530
|
+
*
|
|
531
|
+
* @param value - Numeric value to format.
|
|
532
|
+
* @param precision - Number of decimal places (**LUPREC** / **AUPREC**).
|
|
533
|
+
* @returns Decimal string, or `"0"` for non-finite input.
|
|
534
|
+
* @internal
|
|
535
|
+
*/
|
|
536
|
+
function formatDecimal(value, precision) {
|
|
537
|
+
if (!Number.isFinite(value))
|
|
538
|
+
return '0';
|
|
539
|
+
var normalized = normalizeZero(value);
|
|
540
|
+
if (Number.isInteger(normalized) && precision === 0) {
|
|
541
|
+
return String(normalized);
|
|
542
|
+
}
|
|
543
|
+
var fixed = normalized.toFixed(precision);
|
|
544
|
+
var trimmed = fixed.replace(/\.?0+$/, '');
|
|
545
|
+
if (trimmed === '' || trimmed === '-')
|
|
546
|
+
return '0';
|
|
547
|
+
return trimmed;
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* Formats a number in scientific notation (**LUNITS** = scientific).
|
|
551
|
+
*
|
|
552
|
+
* @param value - Numeric value to format.
|
|
553
|
+
* @param precision - Mantissa decimal places.
|
|
554
|
+
* @returns Uppercase exponent string (for example `1.23E+02`), or `"0"` for non-finite/zero input.
|
|
555
|
+
* @internal
|
|
556
|
+
*/
|
|
557
|
+
function formatScientific(value, precision) {
|
|
558
|
+
if (!Number.isFinite(value))
|
|
559
|
+
return '0';
|
|
560
|
+
var normalized = normalizeZero(value);
|
|
561
|
+
if (normalized === 0)
|
|
562
|
+
return '0';
|
|
563
|
+
var match = normalized.toExponential(precision).match(/^(.+)e([+-])(\d+)$/i);
|
|
564
|
+
if (!match)
|
|
565
|
+
return '0';
|
|
566
|
+
var _a = __read(match, 4), mantissa = _a[1], sign = _a[2], exponentDigits = _a[3];
|
|
567
|
+
var paddedExponent = exponentDigits.length < 2 ? exponentDigits.padStart(2, '0') : exponentDigits;
|
|
568
|
+
return "".concat(mantissa, "E").concat(sign).concat(paddedExponent).toUpperCase();
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Formats a length in engineering feet-and-decimal-inches (**LUNITS** = 3).
|
|
572
|
+
*
|
|
573
|
+
* @param inches - Length interpreted as inches.
|
|
574
|
+
* @param ctx - Formatting context (**LUPREC**, **UNITMODE**, suffix flags).
|
|
575
|
+
* @returns Engineering string (for example `1'-3.5`).
|
|
576
|
+
* @internal
|
|
577
|
+
*/
|
|
578
|
+
function formatEngineering(inches, ctx) {
|
|
579
|
+
if (!Number.isFinite(inches))
|
|
580
|
+
return '0';
|
|
581
|
+
var style = imperialDelimiterStyle(ctx);
|
|
582
|
+
var sign = inches < 0 ? '-' : '';
|
|
583
|
+
var absInches = Math.abs(inches);
|
|
584
|
+
var feet = Math.floor(absInches / 12);
|
|
585
|
+
var inchPart = absInches - feet * 12;
|
|
586
|
+
var inchText = formatDecimal(inchPart, ctx.luprec);
|
|
587
|
+
if (feet === 0) {
|
|
588
|
+
return "".concat(sign).concat(inchText).concat(style.inchSuffix);
|
|
589
|
+
}
|
|
590
|
+
return "".concat(sign).concat(feet, "'").concat(style.feetInchSeparator).concat(inchText).concat(style.inchSuffix);
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Formats a length in architectural feet-and-fractional-inches (**LUNITS** = 4).
|
|
594
|
+
*
|
|
595
|
+
* @param inches - Length interpreted as inches.
|
|
596
|
+
* @param ctx - Formatting context; **LUPREC** selects fractional denominator \(2^{LUPREC}\).
|
|
597
|
+
* @returns Architectural string (for example `1'-3 1/2`).
|
|
598
|
+
* @internal
|
|
599
|
+
*/
|
|
600
|
+
function formatArchitectural(inches, ctx) {
|
|
601
|
+
if (!Number.isFinite(inches))
|
|
602
|
+
return '0';
|
|
603
|
+
var style = imperialDelimiterStyle(ctx);
|
|
604
|
+
var sign = inches < 0 ? '-' : '';
|
|
605
|
+
var absInches = Math.abs(inches);
|
|
606
|
+
var feet = Math.floor(absInches / 12);
|
|
607
|
+
var inchPart = absInches - feet * 12;
|
|
608
|
+
var denominator = 1 << clampPrecision(ctx.luprec, 0, 8);
|
|
609
|
+
var inchText = formatFractionalInches(inchPart, denominator, style.fractionSeparator);
|
|
610
|
+
if (feet === 0) {
|
|
611
|
+
return "".concat(sign).concat(inchText).concat(style.inchSuffix);
|
|
612
|
+
}
|
|
613
|
+
return "".concat(sign).concat(feet, "'").concat(style.feetInchSeparator).concat(inchText).concat(style.inchSuffix);
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Formats a length as a whole number plus fraction (**LUNITS** = fractional).
|
|
617
|
+
*
|
|
618
|
+
* @param inches - Length interpreted as inches.
|
|
619
|
+
* @param ctx - Formatting context.
|
|
620
|
+
* @returns Fractional string (for example `15 1/2`).
|
|
621
|
+
* @internal
|
|
622
|
+
*/
|
|
623
|
+
function formatFractionalLinear(inches, ctx) {
|
|
624
|
+
if (!Number.isFinite(inches))
|
|
625
|
+
return '0';
|
|
626
|
+
var style = imperialDelimiterStyle(ctx);
|
|
627
|
+
var sign = inches < 0 ? '-' : '';
|
|
628
|
+
var absInches = Math.abs(inches);
|
|
629
|
+
var denominator = 1 << clampPrecision(ctx.luprec, 0, 8);
|
|
630
|
+
return "".concat(sign).concat(formatFractionalInches(absInches, denominator, style.fractionSeparator));
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Formats the inch component as a whole number and reduced fraction.
|
|
634
|
+
*
|
|
635
|
+
* @param inches - Inch value in \([0, 12)\) (caller supplies fractional part of feet-inch).
|
|
636
|
+
* @param denominator - Fraction denominator (power of two from **LUPREC**).
|
|
637
|
+
* @param fractionSeparator - Space or dash between whole inches and fraction.
|
|
638
|
+
* @returns Inch-only fractional text (for example `3 1/2`).
|
|
639
|
+
* @internal
|
|
640
|
+
*/
|
|
641
|
+
function formatFractionalInches(inches, denominator, fractionSeparator) {
|
|
642
|
+
var whole = Math.floor(inches);
|
|
643
|
+
var remainder = inches - whole;
|
|
644
|
+
var numerator = Math.round(remainder * denominator);
|
|
645
|
+
if (numerator >= denominator) {
|
|
646
|
+
return String(whole + 1);
|
|
647
|
+
}
|
|
648
|
+
if (numerator === 0) {
|
|
649
|
+
return String(whole);
|
|
650
|
+
}
|
|
651
|
+
var divisor = gcd(numerator, denominator);
|
|
652
|
+
numerator /= divisor;
|
|
653
|
+
var reducedDenominator = denominator / divisor;
|
|
654
|
+
var fraction = "".concat(numerator, "/").concat(reducedDenominator);
|
|
655
|
+
if (whole === 0) {
|
|
656
|
+
return fraction;
|
|
657
|
+
}
|
|
658
|
+
return "".concat(whole).concat(fractionSeparator).concat(fraction);
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* Formats an angle as decimal degrees (**AUNITS** = 0).
|
|
662
|
+
*
|
|
663
|
+
* @param radians - Display angle in radians.
|
|
664
|
+
* @param ctx - Formatting context.
|
|
665
|
+
* @returns Decimal degree string, optionally suffixed with `°`.
|
|
666
|
+
* @internal
|
|
667
|
+
*/
|
|
668
|
+
function formatAngleDecimalDegrees(radians, ctx) {
|
|
669
|
+
var degrees = AcGeMathUtil.radToDeg(radians);
|
|
670
|
+
return "".concat(formatDecimal(degrees, ctx.auprec)).concat(ctx.showUnits ? '°' : '');
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* Formats an angle as radians (**AUNITS** = 3).
|
|
674
|
+
*
|
|
675
|
+
* @param radians - Display angle in radians.
|
|
676
|
+
* @param ctx - Formatting context.
|
|
677
|
+
* @returns Radian string, optionally suffixed with ` rad`.
|
|
678
|
+
* @internal
|
|
679
|
+
*/
|
|
680
|
+
function formatAngleRadians(radians, ctx) {
|
|
681
|
+
return "".concat(formatDecimal(radians, ctx.auprec)).concat(ctx.showUnits ? ' rad' : '');
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* Formats an angle as gradians (**AUNITS** = 2).
|
|
685
|
+
*
|
|
686
|
+
* @param radians - Display angle in radians.
|
|
687
|
+
* @param ctx - Formatting context.
|
|
688
|
+
* @returns Gradian string, optionally suffixed with `g`.
|
|
689
|
+
* @internal
|
|
690
|
+
*/
|
|
691
|
+
function formatAngleGradians(radians, ctx) {
|
|
692
|
+
var grads = radians / RAD_PER_GRAD;
|
|
693
|
+
return "".concat(formatDecimal(grads, ctx.auprec)).concat(ctx.showUnits ? 'g' : '');
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Formats an angle as degrees, minutes, and seconds (**AUNITS** = 1).
|
|
697
|
+
*
|
|
698
|
+
* @param radians - Display angle in radians.
|
|
699
|
+
* @param ctx - Formatting context; **AUPREC** applies to the seconds field.
|
|
700
|
+
* @returns DMS string (for example `45d30'15"`).
|
|
701
|
+
* @internal
|
|
702
|
+
*/
|
|
703
|
+
function formatAngleDms(radians, ctx) {
|
|
704
|
+
var degrees = AcGeMathUtil.radToDeg(radians);
|
|
705
|
+
var sign = degrees < 0 ? '-' : '';
|
|
706
|
+
var absDegrees = Math.abs(degrees);
|
|
707
|
+
var d = Math.floor(absDegrees);
|
|
708
|
+
var minutesFloat = (absDegrees - d) * 60;
|
|
709
|
+
var m = Math.floor(minutesFloat);
|
|
710
|
+
var seconds = (minutesFloat - m) * 60;
|
|
711
|
+
var secondsText = formatDecimal(seconds, ctx.auprec);
|
|
712
|
+
var secondSuffix = ctx.showUnits ? '"' : '';
|
|
713
|
+
return "".concat(sign).concat(d, "d").concat(m, "'").concat(secondsText).concat(secondSuffix);
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* Formats an angle in surveyor's bearing notation (**AUNITS** = 4).
|
|
717
|
+
*
|
|
718
|
+
* @param radians - Display angle in radians.
|
|
719
|
+
* @param ctx - Formatting context; DMS portion uses {@link formatAngleDms}.
|
|
720
|
+
* @returns Bearing string (for example `N 45d30'15" E`).
|
|
721
|
+
* @internal
|
|
722
|
+
*/
|
|
723
|
+
function formatAngleSurveyor(radians, ctx) {
|
|
724
|
+
var degrees = AcGeMathUtil.radToDeg(radians);
|
|
725
|
+
var bearing = (((90 - degrees) % 360) + 360) % 360;
|
|
726
|
+
var quadrant = bearingToQuadrant(bearing);
|
|
727
|
+
var deflection = Math.min(Math.abs(bearing - quadrant.base), Math.abs(quadrant.base + 90 - bearing));
|
|
728
|
+
var dms = formatAngleDms(AcGeMathUtil.degToRad(deflection), ctx);
|
|
729
|
+
var dmsBody = dms.replace(/^-/, '');
|
|
730
|
+
return "".concat(quadrant.prefix, " ").concat(dmsBody, " ").concat(quadrant.suffix).trim();
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* Maps a north-based bearing in degrees to a surveyor quadrant label and reference azimuth.
|
|
734
|
+
*
|
|
735
|
+
* @param bearing - Bearing from north, clockwise, in \([0, 360)\) degrees.
|
|
736
|
+
* @returns Quadrant prefix/suffix (N/S + E/W) and the quadrant's base bearing in degrees.
|
|
737
|
+
* @internal
|
|
738
|
+
*/
|
|
739
|
+
function bearingToQuadrant(bearing) {
|
|
740
|
+
if (bearing < 90) {
|
|
741
|
+
return { prefix: 'N', suffix: 'E', base: 0 };
|
|
742
|
+
}
|
|
743
|
+
if (bearing < 180) {
|
|
744
|
+
return { prefix: 'S', suffix: 'E', base: 90 };
|
|
745
|
+
}
|
|
746
|
+
if (bearing < 270) {
|
|
747
|
+
return { prefix: 'S', suffix: 'W', base: 180 };
|
|
748
|
+
}
|
|
749
|
+
return { prefix: 'N', suffix: 'W', base: 270 };
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* Appends an **INSUNITS** / **MEASUREMENT** suffix to a linear string when enabled.
|
|
753
|
+
*
|
|
754
|
+
* Engineering and architectural strings are returned unchanged (units are already embedded).
|
|
755
|
+
*
|
|
756
|
+
* @param text - Formatted numeric linear text.
|
|
757
|
+
* @param ctx - Formatting context.
|
|
758
|
+
* @returns Text with optional suffix (for example `12.35 mm`).
|
|
759
|
+
* @internal
|
|
760
|
+
*/
|
|
761
|
+
function appendLinearUnitSuffix(text, ctx) {
|
|
762
|
+
if (!ctx.showUnits)
|
|
763
|
+
return text;
|
|
764
|
+
if (ctx.lunits === AcDbLinearUnits.Engineering ||
|
|
765
|
+
ctx.lunits === AcDbLinearUnits.Architectural) {
|
|
766
|
+
return text;
|
|
767
|
+
}
|
|
768
|
+
var suffix = linearUnitSuffix(ctx.insunits, ctx.measurement);
|
|
769
|
+
return suffix ? "".concat(text).concat(suffix) : text;
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Resolves the suffix for decimal/scientific/fractional linear output.
|
|
773
|
+
*
|
|
774
|
+
* @param insunits - **INSUNITS** value.
|
|
775
|
+
* @param measurement - **MEASUREMENT** flag when **INSUNITS** is unitless.
|
|
776
|
+
* @returns Suffix string, or empty when unknown or suffix not applicable.
|
|
777
|
+
* @internal
|
|
778
|
+
*/
|
|
779
|
+
function linearUnitSuffix(insunits, measurement) {
|
|
780
|
+
if (insunits === AcDbUnitsValue.Undefined) {
|
|
781
|
+
return measurement === 0 ? '"' : ' mm';
|
|
782
|
+
}
|
|
783
|
+
if (isMetricUnits(insunits)) {
|
|
784
|
+
return metricUnitSuffix(insunits);
|
|
785
|
+
}
|
|
786
|
+
if (isImperialUnits(insunits)) {
|
|
787
|
+
return imperialUnitSuffix(insunits);
|
|
788
|
+
}
|
|
789
|
+
return '';
|
|
790
|
+
}
|
|
791
|
+
/**
|
|
792
|
+
* Returns the display suffix for a metric {@link AcDbUnitsValue}.
|
|
793
|
+
*
|
|
794
|
+
* @param insunits - Metric insertion unit code.
|
|
795
|
+
* @returns Suffix such as ` mm`, or empty for unsupported codes.
|
|
796
|
+
* @internal
|
|
797
|
+
*/
|
|
798
|
+
function metricUnitSuffix(insunits) {
|
|
799
|
+
switch (insunits) {
|
|
800
|
+
case AcDbUnitsValue.Millimeters:
|
|
801
|
+
return ' mm';
|
|
802
|
+
case AcDbUnitsValue.Centimeters:
|
|
803
|
+
return ' cm';
|
|
804
|
+
case AcDbUnitsValue.Meters:
|
|
805
|
+
return ' m';
|
|
806
|
+
case AcDbUnitsValue.Kilometers:
|
|
807
|
+
return ' km';
|
|
808
|
+
case AcDbUnitsValue.Decimeters:
|
|
809
|
+
return ' dm';
|
|
810
|
+
case AcDbUnitsValue.Microns:
|
|
811
|
+
return ' µm';
|
|
812
|
+
case AcDbUnitsValue.Nanometers:
|
|
813
|
+
return ' nm';
|
|
814
|
+
default:
|
|
815
|
+
return '';
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
/**
|
|
819
|
+
* Returns the display suffix for an imperial {@link AcDbUnitsValue}.
|
|
820
|
+
*
|
|
821
|
+
* @param insunits - Imperial insertion unit code.
|
|
822
|
+
* @returns Suffix such as `"` or ` mi`, or empty for unsupported codes.
|
|
823
|
+
* @internal
|
|
824
|
+
*/
|
|
825
|
+
function imperialUnitSuffix(insunits) {
|
|
826
|
+
switch (insunits) {
|
|
827
|
+
case AcDbUnitsValue.Inches:
|
|
828
|
+
case AcDbUnitsValue.Microinches:
|
|
829
|
+
case AcDbUnitsValue.Mils:
|
|
830
|
+
case AcDbUnitsValue.USSurveyInch:
|
|
831
|
+
return '"';
|
|
832
|
+
case AcDbUnitsValue.Feet:
|
|
833
|
+
case AcDbUnitsValue.USSurveyFeet:
|
|
834
|
+
return '\'';
|
|
835
|
+
case AcDbUnitsValue.Miles:
|
|
836
|
+
case AcDbUnitsValue.USSurveyMile:
|
|
837
|
+
return ' mi';
|
|
838
|
+
case AcDbUnitsValue.Yards:
|
|
839
|
+
case AcDbUnitsValue.USSurveyYard:
|
|
840
|
+
return ' yd';
|
|
841
|
+
default:
|
|
842
|
+
return '';
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
/**
|
|
846
|
+
* Greatest common divisor of two integers (Euclidean algorithm).
|
|
847
|
+
*
|
|
848
|
+
* @param a - First integer.
|
|
849
|
+
* @param b - Second integer.
|
|
850
|
+
* @returns GCD of `|a|` and `|b|`, minimum `1`.
|
|
851
|
+
* @internal
|
|
852
|
+
*/
|
|
853
|
+
function gcd(a, b) {
|
|
854
|
+
var x = Math.abs(a);
|
|
855
|
+
var y = Math.abs(b);
|
|
856
|
+
while (y !== 0) {
|
|
857
|
+
var temp = y;
|
|
858
|
+
y = x % y;
|
|
859
|
+
x = temp;
|
|
860
|
+
}
|
|
861
|
+
return x || 1;
|
|
862
|
+
}
|
|
863
|
+
//# sourceMappingURL=AcDbFormatter.js.map
|