@snaptrude/plugin-core 0.0.0-dev-20260708130115 → 0.0.0-dev-20260827135706
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/CHANGELOG.md +152 -1
- package/api-manifest.json +3620 -276
- package/dist/api/analysis/daylight.d.ts +603 -0
- package/dist/api/analysis/daylight.d.ts.map +1 -0
- package/dist/api/analysis/heatmaps.d.ts +658 -0
- package/dist/api/analysis/heatmaps.d.ts.map +1 -0
- package/dist/api/analysis/illuminance.d.ts +145 -0
- package/dist/api/analysis/illuminance.d.ts.map +1 -0
- package/dist/api/analysis/index.d.ts +59 -0
- package/dist/api/analysis/index.d.ts.map +1 -0
- package/dist/api/analysis/shadows.d.ts +165 -0
- package/dist/api/analysis/shadows.d.ts.map +1 -0
- package/dist/api/analysis/solar.d.ts +249 -0
- package/dist/api/analysis/solar.d.ts.map +1 -0
- package/dist/api/analysis/sunlightHours.d.ts +208 -0
- package/dist/api/analysis/sunlightHours.d.ts.map +1 -0
- package/dist/api/analysis/sunpath.d.ts +80 -0
- package/dist/api/analysis/sunpath.d.ts.map +1 -0
- package/dist/api/analysis/weather.d.ts +193 -0
- package/dist/api/analysis/weather.d.ts.map +1 -0
- package/dist/api/core/camera/index.d.ts +261 -0
- package/dist/api/core/camera/index.d.ts.map +1 -0
- package/dist/api/core/comment/index.d.ts +105 -2
- package/dist/api/core/comment/index.d.ts.map +1 -1
- package/dist/api/core/geom/create/index.d.ts +840 -14
- package/dist/api/core/geom/create/index.d.ts.map +1 -1
- package/dist/api/core/geom/delete/index.d.ts +8 -2
- package/dist/api/core/geom/delete/index.d.ts.map +1 -1
- package/dist/api/core/geom/query/arc.d.ts +5 -5
- package/dist/api/core/geom/query/brep.d.ts +130 -18
- package/dist/api/core/geom/query/brep.d.ts.map +1 -1
- package/dist/api/core/geom/query/circle.d.ts +18 -18
- package/dist/api/core/geom/query/contour.d.ts +20 -20
- package/dist/api/core/geom/query/curve.d.ts +49 -49
- package/dist/api/core/geom/query/edge.d.ts +5 -5
- package/dist/api/core/geom/query/face.d.ts +16 -16
- package/dist/api/core/geom/query/halfedge.d.ts +8 -8
- package/dist/api/core/geom/query/profile.d.ts +19 -19
- package/dist/api/core/geom/query/vertex.d.ts +8 -8
- package/dist/api/core/geom/update/contour.d.ts +14 -14
- package/dist/api/core/geom/update/curve.d.ts +7 -7
- package/dist/api/core/geom/update/profile.d.ts +16 -16
- package/dist/api/core/handles/index.d.ts +210 -0
- package/dist/api/core/handles/index.d.ts.map +1 -0
- package/dist/api/core/index.d.ts +34 -0
- package/dist/api/core/index.d.ts.map +1 -1
- package/dist/api/core/io/export/index.d.ts +134 -0
- package/dist/api/core/io/export/index.d.ts.map +1 -0
- package/dist/api/core/io/import/index.d.ts +453 -0
- package/dist/api/core/io/import/index.d.ts.map +1 -0
- package/dist/api/core/io/index.d.ts +40 -0
- package/dist/api/core/io/index.d.ts.map +1 -0
- package/dist/api/core/io/job/index.d.ts +139 -0
- package/dist/api/core/io/job/index.d.ts.map +1 -0
- package/dist/api/core/io/query/index.d.ts +74 -0
- package/dist/api/core/io/query/index.d.ts.map +1 -0
- package/dist/api/core/io/terrain/index.d.ts +341 -0
- package/dist/api/core/io/terrain/index.d.ts.map +1 -0
- package/dist/api/core/io/underlay/index.d.ts +805 -0
- package/dist/api/core/io/underlay/index.d.ts.map +1 -0
- package/dist/api/core/layers.d.ts +7 -7
- package/dist/api/core/mode/index.d.ts +99 -0
- package/dist/api/core/mode/index.d.ts.map +1 -0
- package/dist/api/core/project/index.d.ts +68 -1
- package/dist/api/core/project/index.d.ts.map +1 -1
- package/dist/api/core/proposals/index.d.ts +531 -0
- package/dist/api/core/proposals/index.d.ts.map +1 -0
- package/dist/api/core/storeys/index.d.ts +265 -0
- package/dist/api/core/storeys/index.d.ts.map +1 -0
- package/dist/api/core/tags.d.ts +24 -0
- package/dist/api/core/tags.d.ts.map +1 -1
- package/dist/api/core/user.d.ts +44 -0
- package/dist/api/core/user.d.ts.map +1 -0
- package/dist/api/core/zoom/index.d.ts +4 -0
- package/dist/api/core/zoom/index.d.ts.map +1 -1
- package/dist/api/design/boolean/index.d.ts +4 -4
- package/dist/api/design/create/index.d.ts +568 -45
- package/dist/api/design/create/index.d.ts.map +1 -1
- package/dist/api/design/delete/index.d.ts +3 -0
- package/dist/api/design/delete/index.d.ts.map +1 -1
- package/dist/api/design/doors/index.d.ts +195 -0
- package/dist/api/design/doors/index.d.ts.map +1 -1
- package/dist/api/design/edit/index.d.ts +1 -1
- package/dist/api/design/erase/index.d.ts +2 -2
- package/dist/api/design/family.d.ts +349 -0
- package/dist/api/design/family.d.ts.map +1 -0
- package/dist/api/design/furniture/index.d.ts +181 -8
- package/dist/api/design/furniture/index.d.ts.map +1 -1
- package/dist/api/design/index.d.ts +98 -0
- package/dist/api/design/index.d.ts.map +1 -1
- package/dist/api/design/lock.d.ts +26 -0
- package/dist/api/design/lock.d.ts.map +1 -1
- package/dist/api/design/materials/index.d.ts +270 -16
- package/dist/api/design/materials/index.d.ts.map +1 -1
- package/dist/api/design/query/geometry/index.d.ts +112 -0
- package/dist/api/design/query/geometry/index.d.ts.map +1 -1
- package/dist/api/design/query/index.d.ts +282 -11
- package/dist/api/design/query/index.d.ts.map +1 -1
- package/dist/api/design/query/referenceLines.d.ts +45 -0
- package/dist/api/design/query/referenceLines.d.ts.map +1 -0
- package/dist/api/design/query/spaces.d.ts +181 -8
- package/dist/api/design/query/spaces.d.ts.map +1 -1
- package/dist/api/design/selection/index.d.ts +144 -0
- package/dist/api/design/selection/index.d.ts.map +1 -1
- package/dist/api/design/transform/index.d.ts +172 -10
- package/dist/api/design/transform/index.d.ts.map +1 -1
- package/dist/api/design/types/index.d.ts +181 -0
- package/dist/api/design/types/index.d.ts.map +1 -0
- package/dist/api/design/update/index.d.ts +553 -2
- package/dist/api/design/update/index.d.ts.map +1 -1
- package/dist/api/design/visibility.d.ts +126 -0
- package/dist/api/design/visibility.d.ts.map +1 -0
- package/dist/api/design/windows/index.d.ts +113 -2
- package/dist/api/design/windows/index.d.ts.map +1 -1
- package/dist/api/entity/buildableEnvelope.d.ts +4 -0
- package/dist/api/entity/buildableEnvelope.d.ts.map +1 -1
- package/dist/api/entity/referenceLine.d.ts +10 -2
- package/dist/api/entity/referenceLine.d.ts.map +1 -1
- package/dist/api/entity/space.d.ts +21 -21
- package/dist/api/entity/story.d.ts +242 -15
- package/dist/api/entity/story.d.ts.map +1 -1
- package/dist/api/index.d.ts +10 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/presentation/aiInspiration.d.ts +25 -25
- package/dist/api/presentation/annotate.d.ts +467 -0
- package/dist/api/presentation/annotate.d.ts.map +1 -0
- package/dist/api/presentation/diagrams.d.ts +111 -8
- package/dist/api/presentation/diagrams.d.ts.map +1 -1
- package/dist/api/presentation/export.d.ts +108 -0
- package/dist/api/presentation/export.d.ts.map +1 -0
- package/dist/api/presentation/import.d.ts +55 -4
- package/dist/api/presentation/import.d.ts.map +1 -1
- package/dist/api/presentation/index.d.ts +58 -1
- package/dist/api/presentation/index.d.ts.map +1 -1
- package/dist/api/presentation/placedViews.d.ts +1139 -0
- package/dist/api/presentation/placedViews.d.ts.map +1 -0
- package/dist/api/presentation/shapes.d.ts +481 -0
- package/dist/api/presentation/shapes.d.ts.map +1 -0
- package/dist/api/presentation/sheets.d.ts +452 -13
- package/dist/api/presentation/sheets.d.ts.map +1 -1
- package/dist/api/presentation/slideshow.d.ts +125 -0
- package/dist/api/presentation/slideshow.d.ts.map +1 -0
- package/dist/api/presentation/tables.d.ts +81 -0
- package/dist/api/presentation/tables.d.ts.map +1 -0
- package/dist/api/presentation/views.d.ts +367 -7
- package/dist/api/presentation/views.d.ts.map +1 -1
- package/dist/api/program/areas.d.ts +102 -12
- package/dist/api/program/areas.d.ts.map +1 -1
- package/dist/api/program/cores.d.ts +3 -99
- package/dist/api/program/cores.d.ts.map +1 -1
- package/dist/api/program/index.d.ts +7 -15
- package/dist/api/program/index.d.ts.map +1 -1
- package/dist/api/program/layout.d.ts +346 -11
- package/dist/api/program/layout.d.ts.map +1 -1
- package/dist/api/program/site.d.ts +469 -13
- package/dist/api/program/site.d.ts.map +1 -1
- package/dist/api/program/spreadsheet.d.ts +365 -41
- package/dist/api/program/spreadsheet.d.ts.map +1 -1
- package/dist/api/workspace/index.d.ts +505 -0
- package/dist/api/workspace/index.d.ts.map +1 -0
- package/dist/errors/codes.d.ts +34 -0
- package/dist/errors/codes.d.ts.map +1 -0
- package/dist/errors/envelope.d.ts +56 -0
- package/dist/errors/envelope.d.ts.map +1 -0
- package/dist/errors/index.d.ts +6 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/plugin-error.d.ts +69 -0
- package/dist/errors/plugin-error.d.ts.map +1 -0
- package/dist/handles.d.ts +97 -25
- package/dist/handles.d.ts.map +1 -1
- package/dist/host-utils.d.ts +4 -0
- package/dist/host-utils.d.ts.map +1 -1
- package/dist/index.cjs +4582 -1422
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4171 -1411
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
- package/scripts/generate-manifest.mjs +45 -0
- package/scripts/generate-manifest.test.mjs +103 -4
- package/src/api/analysis/daylight.ts +470 -0
- package/src/api/analysis/heatmaps.ts +683 -0
- package/src/api/analysis/illuminance.ts +155 -0
- package/src/api/analysis/index.ts +61 -0
- package/src/api/analysis/shadows.ts +183 -0
- package/src/api/analysis/solar.ts +237 -0
- package/src/api/analysis/sunlightHours.ts +211 -0
- package/src/api/analysis/sunpath.ts +83 -0
- package/src/api/analysis/weather.ts +179 -0
- package/src/api/core/camera/index.ts +268 -0
- package/src/api/core/comment/index.ts +120 -2
- package/src/api/core/geom/create/index.ts +912 -1
- package/src/api/core/geom/delete/index.ts +6 -0
- package/src/api/core/geom/query/brep.ts +119 -0
- package/src/api/core/handles/index.ts +233 -0
- package/src/api/core/index.ts +34 -0
- package/src/api/core/io/export/index.ts +126 -0
- package/src/api/core/io/import/index.ts +496 -0
- package/src/api/core/io/index.ts +42 -0
- package/src/api/core/io/job/index.ts +140 -0
- package/src/api/core/io/query/index.ts +71 -0
- package/src/api/core/io/terrain/index.ts +360 -0
- package/src/api/core/io/underlay/index.ts +705 -0
- package/src/api/core/mode/index.ts +96 -0
- package/src/api/core/project/index.ts +62 -1
- package/src/api/core/proposals/index.ts +569 -0
- package/src/api/core/storeys/index.ts +294 -0
- package/src/api/core/tags.ts +27 -0
- package/src/api/core/user.ts +46 -0
- package/src/api/core/zoom/index.ts +4 -0
- package/src/api/design/create/index.ts +670 -30
- package/src/api/design/delete/index.ts +3 -0
- package/src/api/design/doors/index.ts +208 -0
- package/src/api/design/erase/index.ts +1 -1
- package/src/api/design/family.ts +388 -0
- package/src/api/design/furniture/index.ts +197 -8
- package/src/api/design/index.ts +102 -0
- package/src/api/design/lock.ts +27 -0
- package/src/api/design/materials/index.ts +334 -27
- package/src/api/design/query/geometry/index.ts +125 -3
- package/src/api/design/query/index.ts +217 -7
- package/src/api/design/query/referenceLines.ts +52 -0
- package/src/api/design/query/spaces.ts +143 -0
- package/src/api/design/selection/index.ts +129 -0
- package/src/api/design/transform/index.ts +170 -9
- package/src/api/design/types/index.ts +156 -0
- package/src/api/design/update/index.ts +631 -3
- package/src/api/design/visibility.ts +143 -0
- package/src/api/design/windows/index.ts +128 -2
- package/src/api/entity/buildableEnvelope.ts +4 -0
- package/src/api/entity/referenceLine.ts +8 -0
- package/src/api/entity/story.ts +259 -15
- package/src/api/index.ts +10 -0
- package/src/api/presentation/annotate.ts +385 -0
- package/src/api/presentation/diagrams.ts +118 -8
- package/src/api/presentation/export.ts +108 -0
- package/src/api/presentation/import.ts +51 -4
- package/src/api/presentation/index.ts +66 -1
- package/src/api/presentation/placedViews.ts +1120 -0
- package/src/api/presentation/shapes.ts +274 -0
- package/src/api/presentation/sheets.ts +400 -13
- package/src/api/presentation/slideshow.ts +134 -0
- package/src/api/presentation/tables.ts +84 -0
- package/src/api/presentation/views.ts +376 -8
- package/src/api/program/areas.ts +88 -15
- package/src/api/program/cores.ts +3 -91
- package/src/api/program/index.ts +7 -15
- package/src/api/program/layout.ts +365 -11
- package/src/api/program/site.ts +435 -13
- package/src/api/program/spreadsheet.ts +376 -35
- package/src/api/workspace/index.ts +563 -0
- package/src/errors/codes.ts +136 -0
- package/src/errors/envelope.ts +75 -0
- package/src/errors/index.ts +21 -0
- package/src/errors/plugin-error.ts +134 -0
- package/src/handles.ts +123 -13
- package/src/host-utils.ts +4 -0
- package/src/index.ts +1 -0
- package/test/errors.test.mjs +184 -0
- package/tsconfig.json +7 -2
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import * as z from "zod"
|
|
2
|
+
import { PluginApiReturn } from "../../../../types"
|
|
3
|
+
import { CadJsonInput } from "../import"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Import queries — read metadata about a source **before** importing it.
|
|
7
|
+
*
|
|
8
|
+
* These reads let a plugin discover a source's shape before importing it:
|
|
9
|
+
* how many pages a PDF has (for `import.pdf`'s `page`), and which CAD layers a
|
|
10
|
+
* drawing defines (imports always bring in every layer — there is no filter —
|
|
11
|
+
* but the names tell you what the drawing contains).
|
|
12
|
+
*
|
|
13
|
+
* Accessed via `snaptrude.core.io.query`.
|
|
14
|
+
*/
|
|
15
|
+
export abstract class PluginCoreIoQueryApi {
|
|
16
|
+
constructor() {}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Count the pages of a PDF without importing it. `null` if the source can't be
|
|
20
|
+
* read as a PDF.
|
|
21
|
+
*
|
|
22
|
+
* @param source - The PDF: an `https://` URL or a `data:` URL.
|
|
23
|
+
* @returns the page count, or `null`.
|
|
24
|
+
*
|
|
25
|
+
* @examplePrompt How many pages does this PDF have?
|
|
26
|
+
* @examplePrompt Count the pages in the drawing set before importing
|
|
27
|
+
* @examplePrompt Get the PDF page count
|
|
28
|
+
* @examplePrompt Is this a multi-page PDF, and how many?
|
|
29
|
+
*
|
|
30
|
+
* # Example
|
|
31
|
+
* ```ts
|
|
32
|
+
* const pages = await snaptrude.core.io.query.getPdfPageCount(url)
|
|
33
|
+
* for (let p = 1; p <= (pages ?? 0); p++) {
|
|
34
|
+
* await snaptrude.core.io.import.pdf(url, p, p) // one page per storey
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
public abstract getPdfPageCount(source: string): PluginApiReturn<number | null>
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* List the distinct CAD layer names tagged on a parsed CAD JSON's entities.
|
|
42
|
+
* Read-only inspection: imports always bring in **every** layer (there is no
|
|
43
|
+
* layer filter on {@link core.io.import.dwg} / {@link core.io.import.cadJson}) —
|
|
44
|
+
* use the names to decide whether to import at all, or what to tell the user.
|
|
45
|
+
*
|
|
46
|
+
* @param cad - Parsed CAD JSON (same shape `import.cadJson` accepts).
|
|
47
|
+
* @returns the layer names (empty array if none).
|
|
48
|
+
*
|
|
49
|
+
* @examplePrompt What CAD layers are in this drawing?
|
|
50
|
+
* @examplePrompt List the layers before importing the CAD
|
|
51
|
+
* @examplePrompt Show the DWG layer names so I can pick which to import
|
|
52
|
+
* @examplePrompt Enumerate the CAD JSON layers
|
|
53
|
+
*
|
|
54
|
+
* # Example
|
|
55
|
+
* ```ts
|
|
56
|
+
* const layers = await snaptrude.core.io.query.listCadLayers(cad)
|
|
57
|
+
* if (layers.some((l) => l.toUpperCase().includes("WALL"))) {
|
|
58
|
+
* await snaptrude.core.io.import.cadJson(cad, 1) // all layers import together
|
|
59
|
+
* }
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
public abstract listCadLayers(cad: CadJsonInput): PluginApiReturn<string[]>
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Arguments for {@link PluginCoreIoQueryApi.getPdfPageCount}. */
|
|
66
|
+
export const PluginQueryPdfPageCountArgs = z.object({ source: z.string().min(1) })
|
|
67
|
+
export type PluginQueryPdfPageCountArgs = z.infer<typeof PluginQueryPdfPageCountArgs>
|
|
68
|
+
|
|
69
|
+
/** Arguments for {@link PluginCoreIoQueryApi.listCadLayers}. */
|
|
70
|
+
export const PluginQueryCadLayersArgs = z.object({ cad: CadJsonInput })
|
|
71
|
+
export type PluginQueryCadLayersArgs = z.infer<typeof PluginQueryCadLayersArgs>
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import * as z from "zod"
|
|
2
|
+
import { PluginApiReturn } from "../../../../types"
|
|
3
|
+
import { TerrainHandle } from "../../../../handles"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Terrain — inspect and manage the project's site terrain (the singleton created
|
|
7
|
+
* by `core.io.import.terrain`).
|
|
8
|
+
*
|
|
9
|
+
* There is at most one terrain per project. These methods read and edit it: the
|
|
10
|
+
* vertical **datum**, elevation/satellite layers, opacity, the cut/fill report,
|
|
11
|
+
* and removal. All edits are undoable.
|
|
12
|
+
*
|
|
13
|
+
* ## Datum
|
|
14
|
+
* The **datum** is the terrain's vertical position relative to where it was
|
|
15
|
+
* imported. {@link PluginCoreIoTerrainApi.setDatum} shifts the whole terrain
|
|
16
|
+
* vertically by a **relative** offset (each call moves it further — calls are
|
|
17
|
+
* cumulative, not absolute); {@link PluginCoreIoTerrainApi.getDatum} reads the
|
|
18
|
+
* current vertical offset from the imported position.
|
|
19
|
+
*
|
|
20
|
+
* Accessed via `snaptrude.core.io.terrain`.
|
|
21
|
+
*/
|
|
22
|
+
export abstract class PluginCoreIoTerrainApi {
|
|
23
|
+
constructor() {}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Whether the project has a site terrain.
|
|
27
|
+
*
|
|
28
|
+
* @examplePrompt Does this project have site terrain?
|
|
29
|
+
* @examplePrompt Is there a terrain imported?
|
|
30
|
+
* @examplePrompt Check if the site topography exists
|
|
31
|
+
* @examplePrompt Has a terrain been added yet?
|
|
32
|
+
*
|
|
33
|
+
* # Example
|
|
34
|
+
* ```ts
|
|
35
|
+
* if (!(await snaptrude.core.io.terrain.exists())) {
|
|
36
|
+
* await snaptrude.core.io.import.terrain(40.7128, -74.006, 300, 300)
|
|
37
|
+
* }
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
public abstract exists(): PluginApiReturn<boolean>
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Resolve the project's terrain handle, or `null` if there is none. The same
|
|
44
|
+
* handle {@link core.io.import.terrain} returns — use it to obtain the handle
|
|
45
|
+
* without re-importing.
|
|
46
|
+
*
|
|
47
|
+
* @examplePrompt Get the terrain handle
|
|
48
|
+
* @examplePrompt Give me the site terrain
|
|
49
|
+
* @examplePrompt Fetch the current terrain
|
|
50
|
+
* @examplePrompt Return the topography handle if it exists
|
|
51
|
+
*/
|
|
52
|
+
public abstract get(): PluginApiReturn<TerrainHandle | null>
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Read the terrain's current vertical position (world Y, internal units).
|
|
56
|
+
* `null` if there is no terrain. Import places the terrain so its highest
|
|
57
|
+
* point sits at `y = 0`, so a never-shifted terrain reads a negative
|
|
58
|
+
* baseline, not `0`; each {@link PluginCoreIoTerrainApi.setDatum} shift
|
|
59
|
+
* moves this value.
|
|
60
|
+
*
|
|
61
|
+
* @examplePrompt What's the terrain's datum?
|
|
62
|
+
* @examplePrompt Read the current site elevation reference
|
|
63
|
+
* @examplePrompt Get the terrain vertical offset
|
|
64
|
+
* @examplePrompt How far has the datum been shifted?
|
|
65
|
+
*/
|
|
66
|
+
public abstract getDatum(): PluginApiReturn<number | null>
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Shift the terrain's **datum** — move the whole terrain vertically DOWN by
|
|
70
|
+
* `offset` (internal units) from its current position; pass a negative value to
|
|
71
|
+
* raise it. Undoable.
|
|
72
|
+
*
|
|
73
|
+
* **Relative and cumulative**, not absolute: `setDatum(5)` called twice shifts
|
|
74
|
+
* the terrain down by 10 total, it does not settle at a fixed level. Read the
|
|
75
|
+
* terrain's resulting vertical position (world Y — not the accumulated
|
|
76
|
+
* shift) back with {@link PluginCoreIoTerrainApi.getDatum}.
|
|
77
|
+
*
|
|
78
|
+
* @param offset - How far to shift the terrain down, in internal units
|
|
79
|
+
* (negative raises it).
|
|
80
|
+
* @throws if writes are disabled, there is no terrain, or the terrain is
|
|
81
|
+
* **locked** (unlock it in the app first).
|
|
82
|
+
*
|
|
83
|
+
* @examplePrompt Shift the terrain datum down by 12
|
|
84
|
+
* @examplePrompt Lower the site terrain by 10
|
|
85
|
+
* @examplePrompt Raise the terrain a little
|
|
86
|
+
* @examplePrompt Nudge the terrain datum down
|
|
87
|
+
*
|
|
88
|
+
* # Example
|
|
89
|
+
* ```ts
|
|
90
|
+
* await snaptrude.core.io.terrain.setDatum(12) // shift terrain down by 12 (relative)
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
public abstract setDatum(offset: number): PluginApiReturn<void>
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Delete the site terrain. Undoable.
|
|
97
|
+
*
|
|
98
|
+
* @throws if writes are disabled, there is no terrain, or the terrain is
|
|
99
|
+
* **locked** (unlock it in the app first).
|
|
100
|
+
*
|
|
101
|
+
* @examplePrompt Delete the site terrain
|
|
102
|
+
* @examplePrompt Remove the topography
|
|
103
|
+
* @examplePrompt Clear the imported site
|
|
104
|
+
* @examplePrompt Get rid of the terrain
|
|
105
|
+
*/
|
|
106
|
+
public abstract delete(): PluginApiReturn<void>
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* The terrain cut/fill earthwork report — cut, fill, and net volumes — or
|
|
110
|
+
* `null` if there is no terrain.
|
|
111
|
+
*
|
|
112
|
+
* @examplePrompt What are the cut and fill volumes for the site?
|
|
113
|
+
* @examplePrompt Get the terrain earthwork report
|
|
114
|
+
* @examplePrompt How much cut and fill does the grading need?
|
|
115
|
+
* @examplePrompt Show the net volume of the terrain edits
|
|
116
|
+
*
|
|
117
|
+
* # Example
|
|
118
|
+
* ```ts
|
|
119
|
+
* const r = await snaptrude.core.io.terrain.getReport()
|
|
120
|
+
* if (r) console.log(`cut ${r.cutVolume}, fill ${r.fillVolume}, net ${r.netVolume}`)
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
public abstract getReport(): PluginApiReturn<TerrainReport | null>
|
|
124
|
+
|
|
125
|
+
/** Whether terrain elevation (DEM height) is on. `null` if no terrain. */
|
|
126
|
+
public abstract isElevationEnabled(): PluginApiReturn<boolean | null>
|
|
127
|
+
/**
|
|
128
|
+
* Turn terrain elevation (DEM height) ON — a real 3D topography surface. Undoable.
|
|
129
|
+
* @throws if writes are disabled, there is no terrain, or the terrain is
|
|
130
|
+
* **locked** (unlock it in the app first).
|
|
131
|
+
* @examplePrompt Turn on terrain elevation
|
|
132
|
+
* @examplePrompt Enable the site heightmap
|
|
133
|
+
* @examplePrompt Make the terrain 3D
|
|
134
|
+
* @examplePrompt Show the topography relief
|
|
135
|
+
*/
|
|
136
|
+
public abstract enableElevation(): PluginApiReturn<void>
|
|
137
|
+
/**
|
|
138
|
+
* Turn terrain elevation OFF — flatten to a plane. Undoable.
|
|
139
|
+
* @throws if writes are disabled, there is no terrain, or the terrain is
|
|
140
|
+
* **locked** (unlock it in the app first).
|
|
141
|
+
* @examplePrompt Flatten the terrain
|
|
142
|
+
* @examplePrompt Turn off site elevation
|
|
143
|
+
* @examplePrompt Disable the heightmap
|
|
144
|
+
* @examplePrompt Make the terrain flat
|
|
145
|
+
*/
|
|
146
|
+
public abstract disableElevation(): PluginApiReturn<void>
|
|
147
|
+
|
|
148
|
+
/** Whether satellite imagery is draped on the terrain. `null` if no terrain. */
|
|
149
|
+
public abstract isSatelliteEnabled(): PluginApiReturn<boolean | null>
|
|
150
|
+
/**
|
|
151
|
+
* Turn satellite imagery ON. Undoable.
|
|
152
|
+
* @throws if writes are disabled, there is no terrain, or the terrain is
|
|
153
|
+
* **locked** (unlock it in the app first).
|
|
154
|
+
* @examplePrompt Show satellite imagery on the site
|
|
155
|
+
* @examplePrompt Enable the satellite texture
|
|
156
|
+
* @examplePrompt Turn on aerial imagery
|
|
157
|
+
* @examplePrompt Drape satellite over the terrain
|
|
158
|
+
*/
|
|
159
|
+
public abstract enableSatellite(): PluginApiReturn<void>
|
|
160
|
+
/**
|
|
161
|
+
* Turn satellite imagery OFF. Undoable.
|
|
162
|
+
* @throws if writes are disabled, there is no terrain, or the terrain is
|
|
163
|
+
* **locked** (unlock it in the app first).
|
|
164
|
+
* @examplePrompt Hide the satellite imagery
|
|
165
|
+
* @examplePrompt Turn off the aerial texture
|
|
166
|
+
* @examplePrompt Disable satellite on the site
|
|
167
|
+
* @examplePrompt Remove the satellite drape
|
|
168
|
+
*/
|
|
169
|
+
public abstract disableSatellite(): PluginApiReturn<void>
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Replace the terrain surface with a caller-supplied triangle mesh. Undoable
|
|
173
|
+
* (one step), and the replacement persists with the project. The returned
|
|
174
|
+
* promise resolves only after the surface is fully applied and recorded —
|
|
175
|
+
* it is safe to toggle terrain resolution or read the surface back the
|
|
176
|
+
* moment it resolves.
|
|
177
|
+
*
|
|
178
|
+
* `positions` is a flat `[x, y, z, …]` array in **world space** — the same
|
|
179
|
+
* frame `design.query.geometry.getTriangulatedMeshes` reads — so a
|
|
180
|
+
* read-modify-write round trip needs no conversion. `indices` is a flat
|
|
181
|
+
* triangle list into `positions` (three indices per triangle). A
|
|
182
|
+
* predominantly down-facing surface is flipped automatically (reported in
|
|
183
|
+
* `warnings`), and zero-area sliver triangles are tolerated and counted.
|
|
184
|
+
*
|
|
185
|
+
* **What survives the replacement:** the datum, geolocation, opacity, lock
|
|
186
|
+
* state, and the elevation/satellite toggles. The map/satellite texture is
|
|
187
|
+
* re-projected onto the new surface from above (best effort — alignment is
|
|
188
|
+
* approximate, reported in `warnings`). **What resets:** cut/fill history
|
|
189
|
+
* and the earthwork report — the replaced surface starts with a clean
|
|
190
|
+
* grading slate.
|
|
191
|
+
*
|
|
192
|
+
* Limits: at most 500,000 triangles and 500,000 vertices; every coordinate
|
|
193
|
+
* must be finite and within the scene bound.
|
|
194
|
+
*
|
|
195
|
+
* @param positions - Flat `[x, y, z, …]` world-space vertex positions.
|
|
196
|
+
* @param indices - Flat triangle list into `positions`.
|
|
197
|
+
* @param units - `"world"` (default): coordinates are raw internal units;
|
|
198
|
+
* `"meters"`: coordinates are metres and are converted on the way in.
|
|
199
|
+
* @param options - Optional {@linkcode PluginTerrainReplaceMeshOptions}:
|
|
200
|
+
* optimistic-concurrency expectations (`expectedTerrain`,
|
|
201
|
+
* `expectedModelRevision`), `preserve` opt-outs, idempotent replay via
|
|
202
|
+
* `clientMutationId`, and the `coordinateSpace`/`baseline` declarations.
|
|
203
|
+
* @throws if writes are disabled, there is no terrain (import one first),
|
|
204
|
+
* the terrain is **locked**, the mesh fails validation (non-finite or
|
|
205
|
+
* out-of-bound coordinates, bad indices, degenerate-only geometry, over
|
|
206
|
+
* the size caps), `expectedTerrain` does not match the live terrain, or
|
|
207
|
+
* `expectedModelRevision` is stale.
|
|
208
|
+
*
|
|
209
|
+
* @examplePrompt Replace the terrain with this surveyed mesh
|
|
210
|
+
* @examplePrompt Flatten a building pad into the site surface
|
|
211
|
+
* @examplePrompt Load a custom DEM surface onto the terrain
|
|
212
|
+
* @examplePrompt Regrade the terrain from these points
|
|
213
|
+
*
|
|
214
|
+
* # Example
|
|
215
|
+
* ```ts
|
|
216
|
+
* // Projects with no terrain yet: import first, then replace.
|
|
217
|
+
* if (!(await snaptrude.core.io.terrain.exists())) {
|
|
218
|
+
* await snaptrude.core.io.import.terrain(40.7128, -74.006, 300, 300)
|
|
219
|
+
* }
|
|
220
|
+
* const result = await snaptrude.core.io.terrain.replaceMesh(
|
|
221
|
+
* positions, // [x0, y0, z0, x1, y1, z1, …] — world space
|
|
222
|
+
* indices, // [a0, b0, c0, a1, b1, c1, …]
|
|
223
|
+
* "meters",
|
|
224
|
+
* {
|
|
225
|
+
* coordinateSpace: "world",
|
|
226
|
+
* expectedTerrain: await snaptrude.core.io.terrain.get(),
|
|
227
|
+
* baseline: "make-replacement-original",
|
|
228
|
+
* preserve: { datum: true, geolocation: true, satellite: true, material: true },
|
|
229
|
+
* clientMutationId: "survey-2026-08-05-r1",
|
|
230
|
+
* },
|
|
231
|
+
* )
|
|
232
|
+
* // result.modelRevision — pass back as expectedModelRevision on the next call
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
public abstract replaceMesh(
|
|
236
|
+
positions: number[],
|
|
237
|
+
indices: number[],
|
|
238
|
+
units?: "world" | "meters",
|
|
239
|
+
options?: PluginTerrainReplaceMeshOptions,
|
|
240
|
+
): PluginApiReturn<PluginTerrainReplaceMeshResult>
|
|
241
|
+
|
|
242
|
+
/** Read the terrain opacity, `0`..`1`, or `null` if no terrain. */
|
|
243
|
+
public abstract getOpacity(): PluginApiReturn<number | null>
|
|
244
|
+
/**
|
|
245
|
+
* Set the terrain opacity (`0` transparent .. `1` opaque). Undoable.
|
|
246
|
+
* @param opacity - Target opacity, `0`..`1`.
|
|
247
|
+
* @throws if writes are disabled, there is no terrain, or the terrain is
|
|
248
|
+
* **locked** (unlock it in the app first).
|
|
249
|
+
* @examplePrompt Fade the terrain to 50%
|
|
250
|
+
* @examplePrompt Make the site semi-transparent
|
|
251
|
+
* @examplePrompt Set terrain opacity to 0.3
|
|
252
|
+
* @examplePrompt Dim the topography
|
|
253
|
+
*
|
|
254
|
+
* # Example
|
|
255
|
+
* ```ts
|
|
256
|
+
* await snaptrude.core.io.terrain.setOpacity(0.5)
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
public abstract setOpacity(opacity: number): PluginApiReturn<void>
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Terrain cut/fill earthwork report. Volumes are in the **project's display
|
|
264
|
+
* volume unit** (what the UI shows), not internal units.
|
|
265
|
+
*
|
|
266
|
+
* | Property | Type | Description |
|
|
267
|
+
* |---|---|---|
|
|
268
|
+
* | `cutVolume` | `number` | Total excavated (cut) volume |
|
|
269
|
+
* | `fillVolume` | `number` | Total added (fill) volume |
|
|
270
|
+
* | `netVolume` | `number` | Net volume (`fill − cut`) |
|
|
271
|
+
*/
|
|
272
|
+
export const TerrainReport = z.object({
|
|
273
|
+
cutVolume: z.number(),
|
|
274
|
+
fillVolume: z.number(),
|
|
275
|
+
netVolume: z.number(),
|
|
276
|
+
})
|
|
277
|
+
export type TerrainReport = z.infer<typeof TerrainReport>
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Result of {@link PluginCoreIoTerrainApi.replaceMesh}.
|
|
281
|
+
*
|
|
282
|
+
* | Property | Type | Description |
|
|
283
|
+
* |---|---|---|
|
|
284
|
+
* | `terrain` | `TerrainHandle` | The terrain (unchanged singleton handle) |
|
|
285
|
+
* | `modelRevision` | `number` | Session-scoped terrain-mesh revision after this replace — pass back as `expectedModelRevision` for compare-and-swap semantics |
|
|
286
|
+
* | `vertexCount` | `number` | Vertices in the applied mesh |
|
|
287
|
+
* | `triangleCount` | `number` | Triangles in the applied mesh |
|
|
288
|
+
* | `warnings` | `string[]` | Non-fatal notes: winding flipped, sliver triangles, approximate texture re-projection |
|
|
289
|
+
*/
|
|
290
|
+
export type PluginTerrainReplaceMeshResult = {
|
|
291
|
+
terrain: TerrainHandle
|
|
292
|
+
modelRevision: number
|
|
293
|
+
vertexCount: number
|
|
294
|
+
triangleCount: number
|
|
295
|
+
warnings: string[]
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Options for {@link PluginCoreIoTerrainApi.replaceMesh}.
|
|
300
|
+
*
|
|
301
|
+
* | Property | Type | Description |
|
|
302
|
+
* |---|---|---|
|
|
303
|
+
* | `coordinateSpace` | `"world"`? | Declares the input frame. `world` is the only supported space (the same frame `getTriangulatedMeshes` reads) |
|
|
304
|
+
* | `expectedTerrain` | `TerrainHandle`? | Optimistic check: throws `HANDLE_INVALID` if the live terrain is not this handle (session-scoped — handles do not survive reloads) |
|
|
305
|
+
* | `expectedModelRevision` | `number`? | Optimistic check against the session terrain-mesh revision (starts at `0`, increments per successful `replaceMesh`; the result returns the new value). Stale → `PRECONDITION_FAILED` with the current revision in `details` |
|
|
306
|
+
* | `baseline` | `"make-replacement-original"`? | Declares replacement semantics. This is the only (and default) behavior: the replacement becomes the persisted surface; the app's terrain Reset restores the original map heightmap as the escape hatch |
|
|
307
|
+
* | `preserve` | object? | Opt-outs, all defaulting `true`. `datum: false` resets the terrain transform (authored coordinates become the local frame). `satellite: false` switches the drape off after the replace. `material: false` skips texture re-projection — the whole surface takes the ground material. `geolocation: false` is rejected (`VALIDATION`): geolocation is always preserved in this version |
|
|
308
|
+
* | `clientMutationId` | `string`? | Session-scoped idempotency: a repeated call with the same id returns the original result without re-executing |
|
|
309
|
+
*/
|
|
310
|
+
export const PluginTerrainReplaceMeshOptions = z
|
|
311
|
+
.object({
|
|
312
|
+
coordinateSpace: z.literal("world").optional(),
|
|
313
|
+
expectedTerrain: z.string().min(1).optional(),
|
|
314
|
+
expectedModelRevision: z.number().int().nonnegative().optional(),
|
|
315
|
+
baseline: z.literal("make-replacement-original").optional(),
|
|
316
|
+
preserve: z
|
|
317
|
+
.object({
|
|
318
|
+
datum: z.boolean().optional(),
|
|
319
|
+
geolocation: z.boolean().optional(),
|
|
320
|
+
satellite: z.boolean().optional(),
|
|
321
|
+
material: z.boolean().optional(),
|
|
322
|
+
})
|
|
323
|
+
.strict()
|
|
324
|
+
.optional(),
|
|
325
|
+
clientMutationId: z.string().min(1).max(128).optional(),
|
|
326
|
+
})
|
|
327
|
+
.strict()
|
|
328
|
+
export type PluginTerrainReplaceMeshOptions = z.infer<typeof PluginTerrainReplaceMeshOptions>
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Arguments for {@link PluginCoreIoTerrainApi.replaceMesh}. The caps are the
|
|
332
|
+
* plugin surface's explicit payload ceiling: 500k vertices / 500k triangles.
|
|
333
|
+
*/
|
|
334
|
+
export const PluginTerrainReplaceMeshArgs = z.object({
|
|
335
|
+
positions: z
|
|
336
|
+
.array(z.number().finite())
|
|
337
|
+
.min(9)
|
|
338
|
+
.max(1_500_000)
|
|
339
|
+
.refine((a) => a.length % 3 === 0, {
|
|
340
|
+
message: "positions must be a flat [x, y, z, …] array (length a multiple of 3)",
|
|
341
|
+
}),
|
|
342
|
+
indices: z
|
|
343
|
+
.array(z.number().int().nonnegative())
|
|
344
|
+
.min(3)
|
|
345
|
+
.max(1_500_000)
|
|
346
|
+
.refine((a) => a.length % 3 === 0, {
|
|
347
|
+
message: "indices must be a flat triangle list (length a multiple of 3)",
|
|
348
|
+
}),
|
|
349
|
+
units: z.enum(["world", "meters"]).optional(),
|
|
350
|
+
options: PluginTerrainReplaceMeshOptions.optional(),
|
|
351
|
+
})
|
|
352
|
+
export type PluginTerrainReplaceMeshArgs = z.infer<typeof PluginTerrainReplaceMeshArgs>
|
|
353
|
+
|
|
354
|
+
/** Arguments for {@link PluginCoreIoTerrainApi.setDatum}. */
|
|
355
|
+
export const PluginTerrainSetDatumArgs = z.object({ offset: z.number().finite() })
|
|
356
|
+
export type PluginTerrainSetDatumArgs = z.infer<typeof PluginTerrainSetDatumArgs>
|
|
357
|
+
|
|
358
|
+
/** Arguments for {@link PluginCoreIoTerrainApi.setOpacity}. */
|
|
359
|
+
export const PluginTerrainSetOpacityArgs = z.object({ opacity: z.number().min(0).max(1) })
|
|
360
|
+
export type PluginTerrainSetOpacityArgs = z.infer<typeof PluginTerrainSetOpacityArgs>
|