@build-qube/takeoff-calculator 2.0.4 → 2.3.0

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 (5) hide show
  1. package/README.md +4 -0
  2. package/browser.js +1 -1
  3. package/index.d.ts +308 -70
  4. package/index.js +204 -196
  5. package/package.json +14 -33
package/README.md CHANGED
@@ -1,3 +1,7 @@
1
1
  # `@build-qube/takeoff-calculator`
2
2
 
3
3
  ![https://github.com/BuildQube/takeoff-calculator/actions](https://github.com/BuildQube/takeoff-calculator/workflows/CI/badge.svg)
4
+
5
+ ## Benchmarks
6
+
7
+ A performance benchmark suite runs in this package to guard against regressions. See [benchmark/README.md](./benchmark/README.md) for how to run benchmarks locally, interpret results, and CI policy.
package/browser.js CHANGED
@@ -1 +1 @@
1
- export * from "@build-qube/takeoff-calculator-wasm32-wasi";
1
+ export * from '@build-qube/takeoff-calculator-wasm32-wasi';
package/index.d.ts CHANGED
@@ -1,27 +1,86 @@
1
1
  /* auto-generated by NAPI-RS */
2
2
  /* eslint-disable */
3
+ export declare class ContourWrapper {
4
+ /** Create a new contour wrapper from a contour input. */
5
+ constructor(contour: ContourInput);
6
+ /**
7
+ * Set the scale of the contour.
8
+ * This will rebuild the surface mesh.
9
+ */
10
+ setScale(scale: Scale): void;
11
+ /** Get the id of the contour. */
12
+ get id(): string;
13
+ /** Get the page id of the contour. */
14
+ get pageId(): string;
15
+ /** Get the scale of the contour. */
16
+ get scale(): Scale | null;
17
+ /** Get the surface points of the contour. */
18
+ getSurfacePoints(): Array<Point3D> | null;
19
+ /** Get the z value at the given x and y coordinates. */
20
+ getZAt(x: number, y: number): number | null;
21
+ /** Get the scatter data of the contour. */
22
+ getScatterData(step: number): Array<Point3D> | null;
23
+ /** Get scaled scatter data of the contour. */
24
+ getRealWorldScatterData(step: number): Array<Point3D> | null;
25
+ /** Compute raw cut/fill volume (pixel-space values) against a reference surface. */
26
+ rawVolumeAgainst(
27
+ reference: ReferenceSurfaceInput,
28
+ cellSize?: number | undefined | null,
29
+ ): VolumetricResult | null;
30
+ /**
31
+ * Compute unit-aware cut/fill volume against a reference surface.
32
+ * Returns None if surface mesh or scale is not available.
33
+ */
34
+ volumeAgainst(
35
+ reference: ReferenceSurfaceInput,
36
+ cellSize?: number | undefined | null,
37
+ ): VolumetricUnitResult | null;
38
+ }
39
+
3
40
  export declare class GroupWrapper {
4
41
  /** Get the id of the group. */
5
- get id(): string
6
- get area(): UnitValue | null
7
- get length(): UnitValue | null
8
- get points(): number | null
9
- get count(): number | null
42
+ get id(): string;
43
+ /**
44
+ * Get the area for this group.
45
+ *
46
+ * Returns `None` if the area has not been computed or if the mutex is poisoned.
47
+ */
48
+ get area(): UnitValue | null;
49
+ /**
50
+ * Get the length for this group.
51
+ *
52
+ * Returns `None` if the length has not been computed or if the mutex is poisoned.
53
+ */
54
+ get length(): UnitValue | null;
55
+ /**
56
+ * Get the points count for this group.
57
+ *
58
+ * Returns `None` if the points count has not been computed or if the mutex is poisoned.
59
+ */
60
+ get points(): number | null;
61
+ /**
62
+ * Get the count for this group.
63
+ *
64
+ * Returns `None` if the count has not been computed or if the mutex is poisoned.
65
+ */
66
+ get count(): number | null;
67
+ get group(): Group;
10
68
  }
11
69
 
12
70
  export declare class MeasurementWrapper {
13
- get points(): number
14
- get measurement(): Measurement
15
- get area(): UnitValue | null
16
- convertArea(unit: Unit): number | null
17
- convertLength(unit: Unit): number | null
18
- get length(): UnitValue | null
19
- get scale(): Scale | null
20
- get id(): string
21
- get pageId(): string
22
- get groupId(): string
23
- get rawArea(): number
24
- get rawPerimeter(): number
71
+ get points(): number;
72
+ get count(): number;
73
+ get measurement(): Measurement;
74
+ get area(): UnitValue | null;
75
+ convertArea(unit: Unit): number | null;
76
+ convertLength(unit: Unit): number | null;
77
+ get length(): UnitValue | null;
78
+ get scale(): Scale | null;
79
+ get id(): string;
80
+ get pageId(): string;
81
+ get groupId(): string;
82
+ get rawArea(): number;
83
+ get rawPerimeter(): number;
25
84
  }
26
85
 
27
86
  export declare class TakeoffStateHandler {
@@ -36,8 +95,20 @@ export declare class TakeoffStateHandler {
36
95
  *
37
96
  * * `State` - The new state.
38
97
  */
39
- constructor(options?: StateOptions | undefined | null)
40
- getMeasurementsByGroupId(groupId: string): Array<MeasurementWrapper>
98
+ constructor(options?: StateOptions | undefined | null);
99
+ getMeasurementsByGroupId(groupId: string): Array<MeasurementWrapper>;
100
+ /**
101
+ * Get the measurements by page id.
102
+ *
103
+ * # Arguments
104
+ *
105
+ * * `page_id` - The id of the page.
106
+ *
107
+ * # Returns
108
+ *
109
+ * * `Vec<MeasurementWrapper>` - The measurements that are on the page.
110
+ */
111
+ getMeasurementsByPageId(pageId: string): Array<MeasurementWrapper>;
41
112
  /**
42
113
  * Get the scale for a measurement.
43
114
  *
@@ -50,7 +121,7 @@ export declare class TakeoffStateHandler {
50
121
  * * `None` - If the measurement was not found.
51
122
  * * `Some(scale)` - If the scale was found.
52
123
  */
53
- getMeasurementScale(measurementId: string): Scale | null
124
+ getMeasurementScale(measurementId: string): Scale | null;
54
125
  /**
55
126
  * Inserts or updates a page in the state.
56
127
  *
@@ -63,8 +134,9 @@ export declare class TakeoffStateHandler {
63
134
  * * `None` - If the page was not found.
64
135
  * * `Some(page)` - If the page was found and updated.
65
136
  */
66
- upsertPage(page: Page): Page | null
67
- getGroup(groupId: string): GroupWrapper | null
137
+ upsertPage(page: Page): Page | null;
138
+ removePage(pageId: string): Page | null;
139
+ getGroup(groupId: string): GroupWrapper | null;
68
140
  /**
69
141
  * Inserts or updates a group in the state.
70
142
  *
@@ -77,7 +149,19 @@ export declare class TakeoffStateHandler {
77
149
  * * `None` - If the group was not found.
78
150
  * * `Some(group)` - If the group was found and updated.
79
151
  */
80
- upsertGroup(group: Group): Group | null
152
+ upsertGroup(group: Group): Group | null;
153
+ /**
154
+ * Removes a group from the state.
155
+ *
156
+ * # Arguments
157
+ *
158
+ * * `group_id` - The id of the group to remove.
159
+ *
160
+ * # Returns
161
+ * * `None` - If the group was not found.
162
+ * * `Some(group)` - If the group was found and removed.
163
+ */
164
+ removeGroup(groupId: string): Group | null;
81
165
  /**
82
166
  * Inserts or updates a measurement in the state.
83
167
  *
@@ -90,8 +174,21 @@ export declare class TakeoffStateHandler {
90
174
  * * `None` - If the measurement was not found.
91
175
  * * `Some(measurement)` - If the measurement was found and updated.
92
176
  */
93
- upsertMeasurement(measurement: Measurement): Measurement | null
94
- getMeasurement(measurementId: string): MeasurementWrapper | null
177
+ upsertMeasurement(measurement: Measurement): Measurement | null;
178
+ /**
179
+ * Removes a measurement from the state.
180
+ *
181
+ * # Arguments
182
+ *
183
+ * * `measurement_id` - The id of the measurement to remove.
184
+ *
185
+ * # Returns
186
+ *
187
+ * * `None` - If the measurement was not found.
188
+ * * `Some(measurement)` - If the measurement was found and removed.
189
+ */
190
+ removeMeasurement(measurementId: string): Measurement | null;
191
+ getMeasurement(measurementId: string): MeasurementWrapper | null;
95
192
  /**
96
193
  * Inserts or updates a scale in the state.
97
194
  *
@@ -104,7 +201,19 @@ export declare class TakeoffStateHandler {
104
201
  * * `None` - If the scale was not found.
105
202
  * * `Some(scale)` - If the scale was found and updated.
106
203
  */
107
- upsertScale(scale: Scale): Scale | null
204
+ upsertScale(scale: Scale): Scale | null;
205
+ /**
206
+ * Removes a scale from the state.
207
+ *
208
+ * # Arguments
209
+ *
210
+ * * `scale_id` - The id of the scale to remove.
211
+ *
212
+ * # Returns
213
+ * * `None` - If the scale was not found.
214
+ * * `Some(scale)` - If the scale was found and removed.
215
+ */
216
+ removeScale(scaleId: string): Scale | null;
108
217
  /**
109
218
  * Get the measurements that are missing a scale.
110
219
  *
@@ -112,80 +221,209 @@ export declare class TakeoffStateHandler {
112
221
  *
113
222
  * * `Vec<MeasurementWrapper>` - The measurements that are missing a scale.
114
223
  */
115
- getMeasurementsMissingScale(): Array<MeasurementWrapper>
224
+ getMeasurementsMissingScale(): Array<MeasurementWrapper>;
225
+ upsertContour(input: ContourInput): void;
226
+ removeContour(contourId: string): boolean;
227
+ getContour(contourId: string): ContourWrapper | null;
228
+ getContoursByPageId(pageId: string): Array<ContourWrapper>;
229
+ getContoursMissingScale(): Array<ContourWrapper>;
230
+ }
116
231
 
232
+ export declare class VolumetricUnitResult {
233
+ get cut(): UnitValue;
234
+ get fill(): UnitValue;
235
+ get uncoveredArea(): UnitValue;
117
236
  }
118
237
 
119
- export declare function plus100(input: number): number
238
+ /** Add 100 to the input */
239
+ export declare function plus100(input: number): number;
240
+
241
+ /** Add 200 to the input */
242
+ export declare function plus200(input: number): number;
243
+
244
+ /** Input for creating a reference surface from JS/TS. */
245
+ export type ReferenceSurfaceInputJs =
246
+ | { type: 'Polygon'; points: Array<Point>; elevation: number; unit: Unit }
247
+ | {
248
+ type: 'Rectangle';
249
+ points: [Point, Point];
250
+ elevation: number;
251
+ unit: Unit;
252
+ };
120
253
  export declare class UnitValue {
121
- constructor(value: number, unit: Unit, magnitude: UnitValueItemType)
122
- display(unit: Unit): string
123
- getConvertedValue(to: Unit): number
254
+ constructor(value: number, unit: Unit, magnitude: UnitValueItemType);
255
+ display(unit: Unit): string;
256
+ getConvertedValue(to: Unit): number;
257
+ }
258
+
259
+ export interface ContourInput {
260
+ id: string;
261
+ name?: string;
262
+ pageId: string;
263
+ /** The lines that make up the contour map */
264
+ lines: Array<ContourLineInput>;
265
+ /** The points of interest that are used to create the contour map */
266
+ pointsOfInterest: Array<ContourPointOfInterestInput>;
267
+ }
268
+
269
+ export interface ContourLineInput {
270
+ /** The elevation of the contour line (real-world value) */
271
+ elevation: number;
272
+ points: Array<Point>;
273
+ unit: Unit;
124
274
  }
125
275
 
276
+ export interface ContourPointOfInterestInput {
277
+ /** The elevation of the point of interest (real-world value) */
278
+ elevation: number;
279
+ point: Point;
280
+ unit: Unit;
281
+ }
282
+
283
+ /** Calculate distance between two points */
284
+ export declare function distance(
285
+ points: [Point, Point] | [Point3D, Point3D],
286
+ ): number;
287
+
288
+ /** Generate a random id */
289
+ export declare function generateRandomId(): string;
290
+
291
+ /**
292
+ * Get the centroid of a measurement
293
+ *
294
+ * Returns `None` if the measurement has invalid geometry.
295
+ * For more detailed error information, use `measurement.get_centroid()` directly.
296
+ */
297
+ export declare function getCentroid(measurement: Measurement): Point | null;
298
+
126
299
  export interface Group {
127
- id: string
128
- name?: string
129
- measurementType: MeasurementType
300
+ id: string;
301
+ name?: string;
302
+ measurementType: MeasurementType;
130
303
  }
131
304
 
132
305
  export type Measurement =
133
- | { type: 'Count', id: string, pageId: string, groupId: string, points: [Point] }
134
- | { type: 'Polygon', id: string, pageId: string, groupId: string, points: Array<Point> }
135
- | { type: 'Polyline', id: string, pageId: string, groupId: string, points: Array<Point> }
136
- | { type: 'Rectangle', id: string, pageId: string, groupId: string, points: [Point, Point] }
306
+ | {
307
+ type: 'Count';
308
+ id: string;
309
+ pageId: string;
310
+ groupId: string;
311
+ points: [Point];
312
+ }
313
+ | {
314
+ type: 'Polygon';
315
+ id: string;
316
+ pageId: string;
317
+ groupId: string;
318
+ points: Array<Point>;
319
+ }
320
+ | {
321
+ type: 'Polyline';
322
+ id: string;
323
+ pageId: string;
324
+ groupId: string;
325
+ points: Array<Point>;
326
+ }
327
+ | {
328
+ type: 'Rectangle';
329
+ id: string;
330
+ pageId: string;
331
+ groupId: string;
332
+ points: [Point, Point];
333
+ };
137
334
 
138
- export type MeasurementType = 'Area'|
139
- 'Linear'|
140
- 'Count';
335
+ export type MeasurementType = 'Area' | 'Linear' | 'Count';
141
336
 
142
337
  export interface Page {
143
- id: string
144
- name?: string
145
- width?: number
146
- height?: number
147
- viewport?: PageViewport
338
+ id: string;
339
+ name?: string;
340
+ width?: number;
341
+ height?: number;
342
+ viewport?: PageViewport;
148
343
  }
149
344
 
150
345
  export interface PageViewport {
151
- width: number
152
- height: number
346
+ width: number;
347
+ height: number;
153
348
  }
154
349
 
155
350
  /** Represents a 2D point with floating point coordinates */
156
351
  export interface Point {
157
- x: number
158
- y: number
352
+ x: number;
353
+ y: number;
354
+ }
355
+
356
+ export interface Point3D {
357
+ x: number;
358
+ y: number;
359
+ z: number;
159
360
  }
160
361
 
362
+ /** Input for creating a reference surface from JS/TS. */
363
+ export type ReferenceSurfaceInput =
364
+ | { type: 'Polygon'; points: Array<Point>; elevation: number }
365
+ | { type: 'Rectangle'; points: [Point, Point]; elevation: number };
366
+
367
+ /**
368
+ * Reposition a measurement so its centroid is at the given point.
369
+ * Returns a new measurement (same kind and metadata); area, length, and count are unchanged.
370
+ *
371
+ * # Errors
372
+ *
373
+ * Returns an error if the measurement has invalid or empty geometry (e.g. `EmptyGeometry`).
374
+ */
375
+ export declare function repositionMeasurementToCentroid(
376
+ measurement: Measurement,
377
+ newCentroid: Point,
378
+ ): Measurement;
379
+
161
380
  export type Scale =
162
- | { type: 'Area', id: string, pageId: string, scale: ScaleDefinition, boundingBox: [Point, Point] }
163
- | { type: 'Default', id: string, pageId: string, scale: ScaleDefinition }
381
+ | {
382
+ type: 'Area';
383
+ id: string;
384
+ pageId: string;
385
+ scale: ScaleDefinition;
386
+ boundingBox: [Point, Point];
387
+ }
388
+ | { type: 'Default'; id: string; pageId: string; scale: ScaleDefinition };
164
389
 
165
390
  export interface ScaleDefinition {
166
- pixelDistance: number
167
- realDistance: number
168
- unit: Unit
391
+ pixelDistance: number;
392
+ realDistance: number;
393
+ unit: Unit;
169
394
  }
170
395
 
171
396
  /** Simplify a polyline using the Ramer-Douglas-Peucker algorithm */
172
- export declare function simplifyPolyline(points: Array<Point>, tolerance: number): Array<Point>
397
+ export declare function simplifyPolyline(
398
+ points: Array<Point>,
399
+ tolerance: number,
400
+ ): Array<Point>;
173
401
 
174
402
  export interface StateOptions {
175
- pages: Array<Page>
176
- groups: Array<Group>
177
- measurements: Array<Measurement>
178
- scales: Array<Scale>
403
+ pages: Array<Page>;
404
+ groups: Array<Group>;
405
+ measurements: Array<Measurement>;
406
+ scales: Array<Scale>;
179
407
  }
180
408
 
181
409
  /** Measurement units supported by the system */
182
- export type Unit = /** Imperial units */
183
- 'Yards'|
184
- 'Feet'|
185
- 'Inches'|
186
- /** Metric units */
187
- 'Meters'|
188
- 'Centimeters';
189
-
190
- export type UnitValueItemType = 'Area'|
191
- 'Length';
410
+ export type Unit =
411
+ /** Imperial units */
412
+ | 'Yards'
413
+ | 'Feet'
414
+ | 'Inches'
415
+ /** Metric units */
416
+ | 'Meters'
417
+ | 'Centimeters';
418
+
419
+ export type UnitValueItemType = 'Area' | 'Length' | 'Volume';
420
+
421
+ /** Result of a volumetric cut/fill calculation. */
422
+ export interface VolumetricResult {
423
+ /** Volume to remove (terrain above reference). */
424
+ cut: number;
425
+ /** Volume to add (terrain below reference). */
426
+ fill: number;
427
+ /** Area where terrain data was unavailable (z_at returned None). */
428
+ uncoveredArea: number;
429
+ }