@snaptrude/plugin-core 0.8.0 → 0.9.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.
- package/CHANGELOG.md +16 -1
- package/api-manifest.full.json +1350 -89
- package/api-manifest.json +826 -40
- 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 +438 -14
- package/dist/api/analysis/heatmaps.d.ts.map +1 -1
- package/dist/api/analysis/index.d.ts +15 -0
- package/dist/api/analysis/index.d.ts.map +1 -1
- package/dist/api/analysis/solar.d.ts +249 -0
- package/dist/api/analysis/solar.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 +37 -0
- package/dist/api/core/camera/index.d.ts.map +1 -1
- package/dist/api/core/geom/create/index.d.ts +318 -1
- package/dist/api/core/geom/create/index.d.ts.map +1 -1
- package/dist/api/core/index.d.ts +9 -0
- package/dist/api/core/index.d.ts.map +1 -1
- package/dist/api/core/io/export/index.d.ts +3 -1
- package/dist/api/core/io/export/index.d.ts.map +1 -1
- package/dist/api/core/io/import/index.d.ts +61 -0
- package/dist/api/core/io/import/index.d.ts.map +1 -1
- 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/storeys/index.d.ts +251 -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/zoom/index.d.ts +4 -0
- package/dist/api/core/zoom/index.d.ts.map +1 -1
- package/dist/api/design/create/index.d.ts +115 -4
- 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/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 +4 -0
- 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 +173 -0
- package/dist/api/design/query/spaces.d.ts.map +1 -1
- package/dist/api/design/transform/index.d.ts +12 -0
- package/dist/api/design/transform/index.d.ts.map +1 -1
- package/dist/api/design/update/index.d.ts +51 -1
- package/dist/api/design/update/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 +8 -0
- package/dist/api/entity/referenceLine.d.ts.map +1 -1
- package/dist/api/entity/story.d.ts +20 -0
- package/dist/api/entity/story.d.ts.map +1 -1
- package/dist/api/index.d.ts +5 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/presentation/export.d.ts +4 -0
- package/dist/api/presentation/export.d.ts.map +1 -1
- package/dist/api/presentation/import.d.ts +6 -0
- package/dist/api/presentation/import.d.ts.map +1 -1
- package/dist/api/presentation/index.d.ts +9 -0
- package/dist/api/presentation/index.d.ts.map +1 -1
- package/dist/api/presentation/placedViews.d.ts +370 -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/program/site.d.ts +94 -0
- package/dist/api/program/site.d.ts.map +1 -1
- package/dist/api/program/spreadsheet.d.ts +260 -28
- package/dist/api/program/spreadsheet.d.ts.map +1 -1
- package/dist/api/workspace/index.d.ts +460 -0
- package/dist/api/workspace/index.d.ts.map +1 -0
- package/dist/index.cjs +2625 -1758
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2515 -1758
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/scripts/generate-manifest.mjs +45 -0
- package/src/api/analysis/daylight.ts +470 -0
- package/src/api/analysis/heatmaps.ts +444 -17
- package/src/api/analysis/index.ts +15 -0
- package/src/api/analysis/solar.ts +237 -0
- package/src/api/analysis/weather.ts +179 -0
- package/src/api/core/camera/index.ts +39 -0
- package/src/api/core/geom/create/index.ts +344 -1
- package/src/api/core/index.ts +9 -0
- package/src/api/core/io/export/index.ts +3 -1
- package/src/api/core/io/import/index.ts +64 -0
- package/src/api/core/mode/index.ts +96 -0
- package/src/api/core/storeys/index.ts +279 -0
- package/src/api/core/tags.ts +27 -0
- package/src/api/core/zoom/index.ts +4 -0
- package/src/api/design/create/index.ts +138 -1
- package/src/api/design/delete/index.ts +3 -0
- package/src/api/design/query/geometry/index.ts +125 -3
- package/src/api/design/query/index.ts +4 -0
- package/src/api/design/query/referenceLines.ts +52 -0
- package/src/api/design/query/spaces.ts +143 -0
- package/src/api/design/transform/index.ts +12 -0
- package/src/api/design/update/index.ts +66 -1
- package/src/api/entity/buildableEnvelope.ts +4 -0
- package/src/api/entity/referenceLine.ts +8 -0
- package/src/api/entity/story.ts +20 -0
- package/src/api/index.ts +5 -0
- package/src/api/presentation/export.ts +4 -0
- package/src/api/presentation/import.ts +6 -0
- package/src/api/presentation/index.ts +9 -0
- package/src/api/presentation/placedViews.ts +363 -0
- package/src/api/presentation/shapes.ts +274 -0
- package/src/api/program/site.ts +95 -0
- package/src/api/program/spreadsheet.ts +251 -6
- package/src/api/workspace/index.ts +516 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as z from "zod"
|
|
2
2
|
import { PluginApiReturn } from "../../../../types"
|
|
3
|
-
import { Vec3Handle, LineHandle, ArcHandle, CircleHandle, CurveHandle, ProfileHandle, ContourHandle } from "../../../../handles"
|
|
3
|
+
import { Vec3Handle, LineHandle, ArcHandle, CircleHandle, CurveHandle, ProfileHandle, ContourHandle, BrepHandle, Vec3Components } from "../../../../handles"
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Curve creation — construct new geometric curves from point handles (all-handle
|
|
@@ -177,6 +177,260 @@ export abstract class PluginGeomCreateApi {
|
|
|
177
177
|
outer: ProfileHandle,
|
|
178
178
|
holes?: ProfileHandle[],
|
|
179
179
|
): PluginApiReturn<ContourHandle>
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Create a closed solid **B-rep** from explicit face loops. Host API call —
|
|
183
|
+
* returns a {@linkcode BrepHandle}. Faces are plain arrays of `{x, y, z}`
|
|
184
|
+
* point components, NOT point handles (bulk-data precedent:
|
|
185
|
+
* `design.query.geometry.getTriangulatedMeshes`), in raw Babylon units.
|
|
186
|
+
*
|
|
187
|
+
* Each face is one planar loop of at least 3 points; at least 4 faces are
|
|
188
|
+
* required. Loops may be authored in any consistent winding — the host
|
|
189
|
+
* validates edge coherence (every edge shared by exactly two faces, in
|
|
190
|
+
* opposite directions) and fixes the global orientation so faces point
|
|
191
|
+
* outward. Faces must be planar and the solid must be closed; holes in faces
|
|
192
|
+
* are not supported (v1).
|
|
193
|
+
*
|
|
194
|
+
* Inspect the result via `core.geom.query.brep.*`, or commit it to the scene
|
|
195
|
+
* with `design.create.massFromBrep`.
|
|
196
|
+
*
|
|
197
|
+
* @param faces Face loops — each an ordered array of `{x, y, z}` points (≥3 points per face, ≥4 faces)
|
|
198
|
+
* @returns The new solid as a {@linkcode BrepHandle}
|
|
199
|
+
* @throws if a face is degenerate or non-planar, an edge is not shared by
|
|
200
|
+
* exactly two faces (open shell, non-manifold, or inconsistent winding), or
|
|
201
|
+
* the faces do not form a valid closed solid
|
|
202
|
+
*
|
|
203
|
+
* @examplePrompt Create a brep from faces
|
|
204
|
+
* @examplePrompt Build a custom solid from a set of faces
|
|
205
|
+
* @examplePrompt Make a pyramid from triangular faces
|
|
206
|
+
*
|
|
207
|
+
* # Example
|
|
208
|
+
* ```ts
|
|
209
|
+
* // A pyramid: square base + 4 triangular sides
|
|
210
|
+
* const apex = { x: 0, y: 4, z: 0 }
|
|
211
|
+
* const a = { x: -2, y: 0, z: -2 }
|
|
212
|
+
* const b = { x: 2, y: 0, z: -2 }
|
|
213
|
+
* const c = { x: 2, y: 0, z: 2 }
|
|
214
|
+
* const d = { x: -2, y: 0, z: 2 }
|
|
215
|
+
* const brep = await snaptrude.core.geom.create.brepFromFaces([
|
|
216
|
+
* [a, d, c, b], // base
|
|
217
|
+
* [a, b, apex],
|
|
218
|
+
* [b, c, apex],
|
|
219
|
+
* [c, d, apex],
|
|
220
|
+
* [d, a, apex],
|
|
221
|
+
* ])
|
|
222
|
+
* const faceCount = await snaptrude.core.geom.query.brep.getFaceCount(brep) // 5
|
|
223
|
+
* ```
|
|
224
|
+
*/
|
|
225
|
+
public abstract brepFromFaces(faces: Vec3Components[][]): PluginApiReturn<BrepHandle>
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Create a closed solid **B-rep** by extruding a contour along a direction.
|
|
229
|
+
* Host API call — returns a {@linkcode BrepHandle}. The direction is
|
|
230
|
+
* normalised by the host, so `amount` is the extrusion distance in raw
|
|
231
|
+
* Babylon units (negative extrudes the opposite way). The contour is copied —
|
|
232
|
+
* the input handle is never mutated. Holes and arc/circle profiles extrude
|
|
233
|
+
* natively (a circle profile yields a cylinder).
|
|
234
|
+
*
|
|
235
|
+
* Inspect the result via `core.geom.query.brep.*`, or commit it to the scene
|
|
236
|
+
* with `design.create.massFromBrep`.
|
|
237
|
+
*
|
|
238
|
+
* @param contour The cross-section to extrude (outer profile + optional holes)
|
|
239
|
+
* @param direction Extrusion direction as plain `{x, y, z}` components (non-zero, normalised by the host)
|
|
240
|
+
* @param amount Extrusion distance (non-zero; negative extrudes opposite to `direction`)
|
|
241
|
+
* @returns The new solid as a {@linkcode BrepHandle}
|
|
242
|
+
* @throws if the extrusion is degenerate (zero amount, zero direction, or a
|
|
243
|
+
* direction lying in the contour plane) or the contour cannot be extruded
|
|
244
|
+
* into a valid solid
|
|
245
|
+
*
|
|
246
|
+
* @examplePrompt Extrude this profile 3 metres up
|
|
247
|
+
* @examplePrompt Make a solid by extruding this outline
|
|
248
|
+
* @examplePrompt Create a cylinder from a circle profile
|
|
249
|
+
*
|
|
250
|
+
* # Example
|
|
251
|
+
* ```ts
|
|
252
|
+
* const rect = await snaptrude.core.geom.create.profileRect(4, 3)
|
|
253
|
+
* const contour = await snaptrude.core.geom.create.contourFromProfile(rect)
|
|
254
|
+
* const brep = await snaptrude.core.geom.create.brepFromExtrusion(contour, { x: 0, y: 1, z: 0 }, 3)
|
|
255
|
+
* const faceCount = await snaptrude.core.geom.query.brep.getFaceCount(brep) // 6
|
|
256
|
+
* ```
|
|
257
|
+
*/
|
|
258
|
+
public abstract brepFromExtrusion(
|
|
259
|
+
contour: ContourHandle,
|
|
260
|
+
direction: Vec3Components,
|
|
261
|
+
amount: number,
|
|
262
|
+
): PluginApiReturn<BrepHandle>
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Create a closed solid **B-rep** by lofting between a bottom and a top
|
|
266
|
+
* contour. Host API call — returns a {@linkcode BrepHandle}. Both contours
|
|
267
|
+
* must have the same number of edges (and matching hole counts); side faces
|
|
268
|
+
* connect corresponding edges by authored index. Corresponding edges must
|
|
269
|
+
* stay coplanar — a twisted loft would produce non-planar side faces and is
|
|
270
|
+
* rejected. The contours are copied — the input handles are never mutated.
|
|
271
|
+
*
|
|
272
|
+
* Inspect the result via `core.geom.query.brep.*`, or commit it to the scene
|
|
273
|
+
* with `design.create.massFromBrep`.
|
|
274
|
+
*
|
|
275
|
+
* @param bottomContour The bottom cross-section
|
|
276
|
+
* @param topContour The top cross-section (same edge and hole counts as the bottom)
|
|
277
|
+
* @returns The new solid as a {@linkcode BrepHandle}
|
|
278
|
+
* @throws if the contours are coincident, their edge or hole counts differ,
|
|
279
|
+
* a side face between corresponding edges would be non-planar, or the
|
|
280
|
+
* contours cannot be lofted into a valid solid
|
|
281
|
+
*
|
|
282
|
+
* @examplePrompt Make a tapered tower from these two outlines
|
|
283
|
+
* @examplePrompt Loft between a large base and a smaller top
|
|
284
|
+
* @examplePrompt Create a frustum from two squares
|
|
285
|
+
*
|
|
286
|
+
* # Example
|
|
287
|
+
* ```ts
|
|
288
|
+
* // A square frustum: 4m base lofted to a 2m top, 3m up
|
|
289
|
+
* const base = await snaptrude.core.geom.create.profileRect(4, 4)
|
|
290
|
+
* const top = await snaptrude.core.geom.create.profileRect(2, 2, await snaptrude.core.math.vec3.new(0, 3, 0))
|
|
291
|
+
* const brep = await snaptrude.core.geom.create.brepFromLoft(
|
|
292
|
+
* await snaptrude.core.geom.create.contourFromProfile(base),
|
|
293
|
+
* await snaptrude.core.geom.create.contourFromProfile(top),
|
|
294
|
+
* )
|
|
295
|
+
* const faceCount = await snaptrude.core.geom.query.brep.getFaceCount(brep) // 6
|
|
296
|
+
* ```
|
|
297
|
+
*/
|
|
298
|
+
public abstract brepFromLoft(
|
|
299
|
+
bottomContour: ContourHandle,
|
|
300
|
+
topContour: ContourHandle,
|
|
301
|
+
): PluginApiReturn<BrepHandle>
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Create a closed solid **B-rep** from indexed mesh data: a vertex position
|
|
305
|
+
* array plus face loops of indices into it. Host API call — returns a
|
|
306
|
+
* {@linkcode BrepHandle}. The indexed form of
|
|
307
|
+
* {@linkcode PluginGeomCreateApi.brepFromFaces} — same validation (planar
|
|
308
|
+
* faces, closed manifold solid, every edge shared by exactly two faces) after
|
|
309
|
+
* the indices are expanded to point loops.
|
|
310
|
+
*
|
|
311
|
+
* Inspect the result via `core.geom.query.brep.*`, or commit it to the scene
|
|
312
|
+
* with `design.create.massFromBrep`.
|
|
313
|
+
*
|
|
314
|
+
* @param positions Vertex positions as plain `{x, y, z}` components (≥4)
|
|
315
|
+
* @param faces Face loops — each an ordered array of indices into `positions` (≥3 indices per face, ≥4 faces)
|
|
316
|
+
* @returns The new solid as a {@linkcode BrepHandle}
|
|
317
|
+
* @throws if an index is not an integer within `positions` bounds, a face is
|
|
318
|
+
* degenerate or non-planar, or the faces do not form a valid closed solid
|
|
319
|
+
*
|
|
320
|
+
* @examplePrompt Create a brep from mesh vertices and indices
|
|
321
|
+
* @examplePrompt Turn this indexed mesh into a solid
|
|
322
|
+
* @examplePrompt Build a solid from vertex positions and face indices
|
|
323
|
+
*
|
|
324
|
+
* # Example
|
|
325
|
+
* ```ts
|
|
326
|
+
* // A tetrahedron from 4 vertices and 4 triangular faces
|
|
327
|
+
* const positions = [
|
|
328
|
+
* { x: 0, y: 0, z: 0 },
|
|
329
|
+
* { x: 4, y: 0, z: 0 },
|
|
330
|
+
* { x: 2, y: 0, z: 4 },
|
|
331
|
+
* { x: 2, y: 3, z: 1.5 },
|
|
332
|
+
* ]
|
|
333
|
+
* const brep = await snaptrude.core.geom.create.brepFromMesh(positions, [
|
|
334
|
+
* [0, 2, 1], // base
|
|
335
|
+
* [0, 1, 3],
|
|
336
|
+
* [1, 2, 3],
|
|
337
|
+
* [2, 0, 3],
|
|
338
|
+
* ])
|
|
339
|
+
* const vertexCount = await snaptrude.core.geom.query.brep.getVertexCount(brep) // 4
|
|
340
|
+
* ```
|
|
341
|
+
*/
|
|
342
|
+
public abstract brepFromMesh(
|
|
343
|
+
positions: Vec3Components[],
|
|
344
|
+
faces: number[][],
|
|
345
|
+
): PluginApiReturn<BrepHandle>
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Create a closed solid **B-rep** as the boolean **union** of two breps
|
|
349
|
+
* (`a ∪ b`). Host API call — returns a new {@linkcode BrepHandle}. Inputs are
|
|
350
|
+
* read-only and may be authored breps (any `core.geom.create` brep
|
|
351
|
+
* constructor) or scene-derived breps from `design.query.geometry.getBrep`;
|
|
352
|
+
* coordinates are combined as-is, so both inputs must share a frame. The
|
|
353
|
+
* result must be a single solid — disjoint inputs are rejected.
|
|
354
|
+
*
|
|
355
|
+
* The first boolean call loads the OpenCascade geometry kernel (a wasm of
|
|
356
|
+
* tens of MB — expect a pause of seconds); subsequent calls are fast.
|
|
357
|
+
*
|
|
358
|
+
* @param a First solid
|
|
359
|
+
* @param b Second solid
|
|
360
|
+
* @returns The union as a new {@linkcode BrepHandle}
|
|
361
|
+
* @throws if the inputs do not overlap or touch (the union would be disjoint
|
|
362
|
+
* solids) or the result cannot be built as a valid single solid
|
|
363
|
+
*
|
|
364
|
+
* @examplePrompt Union these two solids
|
|
365
|
+
* @examplePrompt Merge these breps into one mass
|
|
366
|
+
* @examplePrompt Combine the tower and the podium into a single solid
|
|
367
|
+
*
|
|
368
|
+
* # Example
|
|
369
|
+
* ```ts
|
|
370
|
+
* const a = await snaptrude.core.geom.create.brepFromExtrusion(baseContour, { x: 0, y: 1, z: 0 }, 3)
|
|
371
|
+
* const b = await snaptrude.core.geom.create.brepFromExtrusion(overlappingContour, { x: 0, y: 1, z: 0 }, 5)
|
|
372
|
+
* const merged = await snaptrude.core.geom.create.brepFromUnion(a, b)
|
|
373
|
+
* ```
|
|
374
|
+
*/
|
|
375
|
+
public abstract brepFromUnion(a: BrepHandle, b: BrepHandle): PluginApiReturn<BrepHandle>
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Create a closed solid **B-rep** as the boolean **subtraction** of two
|
|
379
|
+
* breps: **`a` minus `b`** — `b` is cut away from `a`. Host API call —
|
|
380
|
+
* returns a new {@linkcode BrepHandle}. Argument order matters:
|
|
381
|
+
* `brepFromSubtraction(a, b)` removes `b`'s volume from `a`. Inputs are
|
|
382
|
+
* read-only and may be authored or scene-derived breps (see
|
|
383
|
+
* {@linkcode PluginGeomCreateApi.brepFromUnion}); coordinates are combined
|
|
384
|
+
* as-is.
|
|
385
|
+
*
|
|
386
|
+
* The first boolean call loads the OpenCascade geometry kernel (a wasm of
|
|
387
|
+
* tens of MB — expect a pause of seconds); subsequent calls are fast.
|
|
388
|
+
*
|
|
389
|
+
* @param a The solid to subtract from
|
|
390
|
+
* @param b The solid to remove from `a`
|
|
391
|
+
* @returns `a` minus `b` as a new {@linkcode BrepHandle}
|
|
392
|
+
* @throws if `b` consumes `a` entirely (empty result), the result splits into
|
|
393
|
+
* disjoint solids, or it cannot be built as a valid single solid
|
|
394
|
+
*
|
|
395
|
+
* @examplePrompt Subtract the courtyard from the building mass
|
|
396
|
+
* @examplePrompt Cut this solid out of that one
|
|
397
|
+
* @examplePrompt Punch a hole through the slab with this box
|
|
398
|
+
*
|
|
399
|
+
* # Example
|
|
400
|
+
* ```ts
|
|
401
|
+
* // buildingBrep minus courtyardBrep — order matters
|
|
402
|
+
* const carved = await snaptrude.core.geom.create.brepFromSubtraction(buildingBrep, courtyardBrep)
|
|
403
|
+
* ```
|
|
404
|
+
*/
|
|
405
|
+
public abstract brepFromSubtraction(a: BrepHandle, b: BrepHandle): PluginApiReturn<BrepHandle>
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Create a closed solid **B-rep** as the boolean **intersection** of two
|
|
409
|
+
* breps (`a ∩ b` — the shared volume only). Host API call — returns a new
|
|
410
|
+
* {@linkcode BrepHandle}. Inputs are read-only and may be authored or
|
|
411
|
+
* scene-derived breps (see {@linkcode PluginGeomCreateApi.brepFromUnion});
|
|
412
|
+
* coordinates are combined as-is.
|
|
413
|
+
*
|
|
414
|
+
* The first boolean call loads the OpenCascade geometry kernel (a wasm of
|
|
415
|
+
* tens of MB — expect a pause of seconds); subsequent calls are fast.
|
|
416
|
+
*
|
|
417
|
+
* @param a First solid
|
|
418
|
+
* @param b Second solid
|
|
419
|
+
* @returns The shared volume as a new {@linkcode BrepHandle}
|
|
420
|
+
* @throws if the inputs do not overlap (empty intersection), the result
|
|
421
|
+
* splits into disjoint solids, or it cannot be built as a valid single
|
|
422
|
+
* solid
|
|
423
|
+
*
|
|
424
|
+
* @examplePrompt Keep only the overlap of these two solids
|
|
425
|
+
* @examplePrompt Intersect these two masses
|
|
426
|
+
* @examplePrompt Clip the tower to the zoning envelope
|
|
427
|
+
*
|
|
428
|
+
* # Example
|
|
429
|
+
* ```ts
|
|
430
|
+
* const overlap = await snaptrude.core.geom.create.brepFromIntersection(towerBrep, envelopeBrep)
|
|
431
|
+
* ```
|
|
432
|
+
*/
|
|
433
|
+
public abstract brepFromIntersection(a: BrepHandle, b: BrepHandle): PluginApiReturn<BrepHandle>
|
|
180
434
|
}
|
|
181
435
|
|
|
182
436
|
/**
|
|
@@ -291,3 +545,92 @@ export const PluginGeomCreateContourFromProfilesArgs = z.object({
|
|
|
291
545
|
export type PluginGeomCreateContourFromProfilesArgs = z.infer<
|
|
292
546
|
typeof PluginGeomCreateContourFromProfilesArgs
|
|
293
547
|
>
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* Arguments for {@linkcode PluginGeomCreateApi.brepFromFaces}.
|
|
551
|
+
*
|
|
552
|
+
* | Property | Type | Description |
|
|
553
|
+
* |---|---|---|
|
|
554
|
+
* | `faces` | {@linkcode Vec3Components}`[][]` | Face loops — each an ordered array of `{x, y, z}` points (≥3 points per face, ≥4 faces) |
|
|
555
|
+
*/
|
|
556
|
+
export const PluginGeomCreateBrepFromFacesArgs = z.object({
|
|
557
|
+
faces: z.array(z.array(Vec3Components).min(3)).min(4),
|
|
558
|
+
})
|
|
559
|
+
|
|
560
|
+
export type PluginGeomCreateBrepFromFacesArgs = z.infer<
|
|
561
|
+
typeof PluginGeomCreateBrepFromFacesArgs
|
|
562
|
+
>
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Arguments for {@linkcode PluginGeomCreateApi.brepFromExtrusion}.
|
|
566
|
+
*
|
|
567
|
+
* | Property | Type | Description |
|
|
568
|
+
* |---|---|---|
|
|
569
|
+
* | `contour` | {@linkcode ContourHandle} | The cross-section to extrude |
|
|
570
|
+
* | `direction` | {@linkcode Vec3Components} | Extrusion direction (non-zero, finite components) |
|
|
571
|
+
* | `amount` | `number` | Extrusion distance (finite, non-zero) |
|
|
572
|
+
*/
|
|
573
|
+
export const PluginGeomCreateBrepFromExtrusionArgs = z.object({
|
|
574
|
+
contour: ContourHandle,
|
|
575
|
+
direction: z.object({
|
|
576
|
+
x: z.number().finite(),
|
|
577
|
+
y: z.number().finite(),
|
|
578
|
+
z: z.number().finite(),
|
|
579
|
+
}),
|
|
580
|
+
amount: z
|
|
581
|
+
.number()
|
|
582
|
+
.finite()
|
|
583
|
+
.refine((value) => value !== 0, { message: "amount must be non-zero" }),
|
|
584
|
+
})
|
|
585
|
+
|
|
586
|
+
export type PluginGeomCreateBrepFromExtrusionArgs = z.infer<
|
|
587
|
+
typeof PluginGeomCreateBrepFromExtrusionArgs
|
|
588
|
+
>
|
|
589
|
+
|
|
590
|
+
/**
|
|
591
|
+
* Arguments for {@linkcode PluginGeomCreateApi.brepFromLoft}.
|
|
592
|
+
*
|
|
593
|
+
* | Property | Type | Description |
|
|
594
|
+
* |---|---|---|
|
|
595
|
+
* | `bottomContour` | {@linkcode ContourHandle} | The bottom cross-section |
|
|
596
|
+
* | `topContour` | {@linkcode ContourHandle} | The top cross-section |
|
|
597
|
+
*/
|
|
598
|
+
export const PluginGeomCreateBrepFromLoftArgs = z.object({
|
|
599
|
+
bottomContour: ContourHandle,
|
|
600
|
+
topContour: ContourHandle,
|
|
601
|
+
})
|
|
602
|
+
|
|
603
|
+
export type PluginGeomCreateBrepFromLoftArgs = z.infer<typeof PluginGeomCreateBrepFromLoftArgs>
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* Arguments for {@linkcode PluginGeomCreateApi.brepFromMesh}.
|
|
607
|
+
*
|
|
608
|
+
* | Property | Type | Description |
|
|
609
|
+
* |---|---|---|
|
|
610
|
+
* | `positions` | {@linkcode Vec3Components}`[]` | Vertex positions (≥4) |
|
|
611
|
+
* | `faces` | `number[][]` | Face loops of indices into `positions` (≥3 indices per face, ≥4 faces) |
|
|
612
|
+
*/
|
|
613
|
+
export const PluginGeomCreateBrepFromMeshArgs = z.object({
|
|
614
|
+
positions: z.array(Vec3Components).min(4),
|
|
615
|
+
faces: z.array(z.array(z.number()).min(3)).min(4),
|
|
616
|
+
})
|
|
617
|
+
|
|
618
|
+
export type PluginGeomCreateBrepFromMeshArgs = z.infer<typeof PluginGeomCreateBrepFromMeshArgs>
|
|
619
|
+
|
|
620
|
+
/**
|
|
621
|
+
* Arguments for the brep boolean constructors —
|
|
622
|
+
* {@linkcode PluginGeomCreateApi.brepFromUnion},
|
|
623
|
+
* {@linkcode PluginGeomCreateApi.brepFromSubtraction} (`a` minus `b`), and
|
|
624
|
+
* {@linkcode PluginGeomCreateApi.brepFromIntersection}.
|
|
625
|
+
*
|
|
626
|
+
* | Property | Type | Description |
|
|
627
|
+
* |---|---|---|
|
|
628
|
+
* | `a` | {@linkcode BrepHandle} | First solid (the subtraction target) |
|
|
629
|
+
* | `b` | {@linkcode BrepHandle} | Second solid (the subtraction tool) |
|
|
630
|
+
*/
|
|
631
|
+
export const PluginGeomCreateBrepBooleanArgs = z.object({
|
|
632
|
+
a: BrepHandle,
|
|
633
|
+
b: BrepHandle,
|
|
634
|
+
})
|
|
635
|
+
|
|
636
|
+
export type PluginGeomCreateBrepBooleanArgs = z.infer<typeof PluginGeomCreateBrepBooleanArgs>
|
package/src/api/core/index.ts
CHANGED
|
@@ -13,6 +13,8 @@ import { PluginCoreIoApi } from "./io"
|
|
|
13
13
|
import { PluginCoreHandlesApi } from "./handles"
|
|
14
14
|
import { PluginCoreProposalsApi } from "./proposals"
|
|
15
15
|
import { PluginCameraApi } from "./camera"
|
|
16
|
+
import { PluginCoreStoreysApi } from "./storeys"
|
|
17
|
+
import { PluginCoreModeApi } from "./mode"
|
|
16
18
|
import { PluginUserApi } from "./user"
|
|
17
19
|
|
|
18
20
|
/**
|
|
@@ -29,6 +31,7 @@ import { PluginUserApi } from "./user"
|
|
|
29
31
|
* - {@linkcode PluginCoreApi.comment} — Comments: create, edit, resolve, tag, list
|
|
30
32
|
* - {@linkcode PluginCoreApi.groups} — Read & edit the group hierarchy
|
|
31
33
|
* - {@linkcode PluginCoreApi.buildings} — Read & edit buildings and their storeys
|
|
34
|
+
* - {@linkcode PluginCoreApi.storeys} — Create, read & edit storeys (floors)
|
|
32
35
|
* - {@linkcode PluginCoreApi.layers} — Read & toggle storey drawing/reference layers
|
|
33
36
|
* - {@linkcode PluginCoreApi.tags} — Tag catalog + assignment
|
|
34
37
|
* - {@linkcode PluginCoreApi.io} — Import files (image/pdf/cad/model/terrain), poll jobs, manage underlays
|
|
@@ -58,6 +61,10 @@ export abstract class PluginCoreApi {
|
|
|
58
61
|
public abstract groups: PluginCoreGroupsApi
|
|
59
62
|
/** Buildings — read & edit buildings and their storeys. See {@linkcode PluginCoreBuildingsApi}. */
|
|
60
63
|
public abstract buildings: PluginCoreBuildingsApi
|
|
64
|
+
/** Storeys — create, read & edit storeys (floors). See {@linkcode PluginCoreStoreysApi}. */
|
|
65
|
+
public abstract storeys: PluginCoreStoreysApi
|
|
66
|
+
/** Application mode — read & switch the editor's top-bar mode. See {@linkcode PluginCoreModeApi}. */
|
|
67
|
+
public abstract mode: PluginCoreModeApi
|
|
61
68
|
/** Layers — read & toggle storey drawing/reference layers. See {@linkcode PluginCoreLayersApi}. */
|
|
62
69
|
public abstract layers: PluginCoreLayersApi
|
|
63
70
|
/** Tags — tag catalog + assignment. See {@linkcode PluginCoreTagsApi}. */
|
|
@@ -83,6 +90,8 @@ export * from "./project"
|
|
|
83
90
|
export * from "./comment"
|
|
84
91
|
export * from "./groups"
|
|
85
92
|
export * from "./buildings"
|
|
93
|
+
export * from "./storeys"
|
|
94
|
+
export * from "./mode"
|
|
86
95
|
export * from "./layers"
|
|
87
96
|
export * from "./tags"
|
|
88
97
|
export * from "./io"
|
|
@@ -39,7 +39,9 @@ export type ExportedFile = z.infer<typeof ExportedFile>
|
|
|
39
39
|
*
|
|
40
40
|
* `core.io.export.model` hands you the file bytes as base64 — no download
|
|
41
41
|
* dialog opens; the plugin decides what to do with the result (save it, POST
|
|
42
|
-
* it, diff it).
|
|
42
|
+
* it, diff it). For a different export intent, see `presentation.export`
|
|
43
|
+
* (Present-mode layout sheets to PDF/PNG/JPG) and `program.spreadsheet.export`
|
|
44
|
+
* (the area-program / takeoff workbook). Four formats:
|
|
43
45
|
*
|
|
44
46
|
* - `"glb"` — binary glTF (`model/gltf-binary`); geometry + materials,
|
|
45
47
|
* serialized in the browser (nothing is uploaded).
|
|
@@ -55,6 +55,9 @@ export abstract class PluginCoreIoImportApi {
|
|
|
55
55
|
* Supported formats: PNG, JPG/JPEG, BMP. The image is placed on the target
|
|
56
56
|
* storey's "Image" layer at ~50% opacity by default.
|
|
57
57
|
*
|
|
58
|
+
* To place the image on a **Present-mode sheet** instead of the scene, use
|
|
59
|
+
* `presentation.import.image`.
|
|
60
|
+
*
|
|
58
61
|
* The plane is placed at the storey origin (the engine's import placement);
|
|
59
62
|
* there is no placement parameter — calibrate size with
|
|
60
63
|
* {@link PluginCoreIoUnderlayApi.setScale} after import.
|
|
@@ -308,6 +311,40 @@ export abstract class PluginCoreIoImportApi {
|
|
|
308
311
|
neighborhood?: boolean,
|
|
309
312
|
parcels?: boolean,
|
|
310
313
|
): PluginApiReturn<TerrainHandle>
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Import an **EPW weather file** into the project's weather catalog.
|
|
317
|
+
*
|
|
318
|
+
* Uploads an EnergyPlus Weather (`.epw`) file and registers it as the
|
|
319
|
+
* project's site weather, returning its catalog `weatherFileId` — the same id
|
|
320
|
+
* {@link PluginAnalysisWeatherApi.getSeries}, `program.site.getWeather`, and a
|
|
321
|
+
* daylight run's provenance report. Uploading a user file makes the site's
|
|
322
|
+
* `selectionMethod` `"user-upload"`, overriding nearest-station resolution.
|
|
323
|
+
*
|
|
324
|
+
* **Mutating**: this writes project state and is subject to the plugin
|
|
325
|
+
* write-gate — it throws when plugin writes are disabled. Unlike the file
|
|
326
|
+
* underlay/model importers it returns no scene handle (a weather file is not
|
|
327
|
+
* a scene object), only the catalog `{ weatherFileId, label }`.
|
|
328
|
+
*
|
|
329
|
+
* @param source - The `.epw` file to import: an `https://` URL or a `data:` URL.
|
|
330
|
+
* @returns A {@linkcode PluginImportEpwResult} — the catalog `weatherFileId`
|
|
331
|
+
* and a human-readable `label` (the station/file name).
|
|
332
|
+
* @throws if writes are disabled, the source can't be loaded, or the file is
|
|
333
|
+
* not a valid EPW.
|
|
334
|
+
*
|
|
335
|
+
* @examplePrompt Import this EPW weather file for the site
|
|
336
|
+
* @examplePrompt Upload a custom weather file for the daylight analysis
|
|
337
|
+
* @examplePrompt Use this .epw as the project's weather source
|
|
338
|
+
*
|
|
339
|
+
* # Example
|
|
340
|
+
* ```ts
|
|
341
|
+
* const { weatherFileId, label } = await snaptrude.core.io.import.epw(
|
|
342
|
+
* "https://example.com/Chicago-OHare.epw",
|
|
343
|
+
* )
|
|
344
|
+
* console.log(`Weather set to ${label} (${weatherFileId})`)
|
|
345
|
+
* ```
|
|
346
|
+
*/
|
|
347
|
+
public abstract epw(source: string): PluginApiReturn<PluginImportEpwResult>
|
|
311
348
|
}
|
|
312
349
|
|
|
313
350
|
/**
|
|
@@ -430,3 +467,30 @@ export const PluginImportTerrainArgs = z.object({
|
|
|
430
467
|
parcels: z.boolean().optional(),
|
|
431
468
|
})
|
|
432
469
|
export type PluginImportTerrainArgs = z.infer<typeof PluginImportTerrainArgs>
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Arguments for {@link PluginCoreIoImportApi.epw}.
|
|
473
|
+
*
|
|
474
|
+
* | Property | Type | Description |
|
|
475
|
+
* |---|---|---|
|
|
476
|
+
* | `source` | `string` | EPW `https://` URL or `data:` URL |
|
|
477
|
+
*/
|
|
478
|
+
export const PluginImportEpwArgs = z.object({
|
|
479
|
+
source: ImportSource,
|
|
480
|
+
})
|
|
481
|
+
export type PluginImportEpwArgs = z.infer<typeof PluginImportEpwArgs>
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Result of {@link PluginCoreIoImportApi.epw} — the imported weather file's
|
|
485
|
+
* catalog entry.
|
|
486
|
+
*
|
|
487
|
+
* | Property | Type | Description |
|
|
488
|
+
* |---|---|---|
|
|
489
|
+
* | `weatherFileId` | `string` | Catalog id (same key as `analysis.weather`'s `weatherFileId`) |
|
|
490
|
+
* | `label` | `string` | Human-readable name (station / file name) |
|
|
491
|
+
*/
|
|
492
|
+
export const PluginImportEpwResult = z.object({
|
|
493
|
+
weatherFileId: z.string(),
|
|
494
|
+
label: z.string(),
|
|
495
|
+
})
|
|
496
|
+
export type PluginImportEpwResult = z.infer<typeof PluginImportEpwResult>
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import * as z from "zod"
|
|
2
|
+
import { PluginApiReturn } from "../../../types"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The editor's top-bar application modes — the tabs a user switches between
|
|
6
|
+
* while working on a project.
|
|
7
|
+
*/
|
|
8
|
+
export const PluginAppMode = z.enum(["design", "bim", "present", "program"])
|
|
9
|
+
export type PluginAppMode = z.infer<typeof PluginAppMode>
|
|
10
|
+
|
|
11
|
+
export const PluginCoreModeSetArgs = z.object({
|
|
12
|
+
mode: PluginAppMode,
|
|
13
|
+
})
|
|
14
|
+
export type PluginCoreModeSetArgs = z.infer<typeof PluginCoreModeSetArgs>
|
|
15
|
+
|
|
16
|
+
export interface PluginCoreModeListResult {
|
|
17
|
+
modes: PluginAppMode[]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface PluginCoreModeSetResult {
|
|
21
|
+
mode: PluginAppMode
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Application-mode control — read and switch the editor's top-bar mode
|
|
26
|
+
* (Design, BIM, Present, Program), the same tabs a user clicks in the
|
|
27
|
+
* top menu bar. Accessed via `snaptrude.core.mode`.
|
|
28
|
+
*
|
|
29
|
+
* Not to be confused with the viewport's 2D/3D camera mode
|
|
30
|
+
* (`core.camera.setMode`) or saved presentation views (`presentation.views`).
|
|
31
|
+
*
|
|
32
|
+
* `set` covers `design`, `bim`, and `present` — in-page switches.
|
|
33
|
+
* `program` opens in its own browser tab in the product, which a plugin worker
|
|
34
|
+
* cannot do, so `set("program")` fails with `PRECONDITION_FAILED`; `get()`
|
|
35
|
+
* still reports `"program"` for code running in the Program tab.
|
|
36
|
+
*/
|
|
37
|
+
export abstract class PluginCoreModeApi {
|
|
38
|
+
constructor() {}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* List every application mode the editor has.
|
|
42
|
+
*
|
|
43
|
+
* @returns The full set of mode tokens accepted by {@linkcode get} / {@linkcode set}.
|
|
44
|
+
*
|
|
45
|
+
* @examplePrompt What modes does Snaptrude have?
|
|
46
|
+
* @examplePrompt List the editor modes I can switch to
|
|
47
|
+
*
|
|
48
|
+
* # Example
|
|
49
|
+
* ```ts
|
|
50
|
+
* const { modes } = await snaptrude.core.mode.list()
|
|
51
|
+
* // ["design", "bim", "present", "program"]
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
public abstract list(): PluginApiReturn<PluginCoreModeListResult>
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Get the currently active application mode.
|
|
58
|
+
*
|
|
59
|
+
* @returns The active mode token (e.g. `"design"`).
|
|
60
|
+
*
|
|
61
|
+
* @examplePrompt Which mode am I in right now?
|
|
62
|
+
* @examplePrompt Am I in present mode?
|
|
63
|
+
* @examplePrompt Check whether the editor is in BIM mode
|
|
64
|
+
*
|
|
65
|
+
* # Example
|
|
66
|
+
* ```ts
|
|
67
|
+
* const mode = await snaptrude.core.mode.get()
|
|
68
|
+
* if (mode !== "present") await snaptrude.core.mode.set("present")
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
public abstract get(): PluginApiReturn<PluginAppMode>
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Switch the editor to another application mode — the same action as
|
|
75
|
+
* clicking that tab in the top menu bar.
|
|
76
|
+
*
|
|
77
|
+
* Supported: `"design"`, `"bim"`, `"present"`. Switching to
|
|
78
|
+
* `"program"` is rejected with `PRECONDITION_FAILED` (the Program surface
|
|
79
|
+
* opens in its own browser tab in the product; a plugin cannot open one).
|
|
80
|
+
*
|
|
81
|
+
* @param mode - Target mode token from {@linkcode PluginAppMode}
|
|
82
|
+
* @returns The committed `{ mode }` after the switch.
|
|
83
|
+
*
|
|
84
|
+
* @examplePrompt Switch to present mode
|
|
85
|
+
* @examplePrompt Open BIM mode
|
|
86
|
+
* @examplePrompt Go back to design mode
|
|
87
|
+
*
|
|
88
|
+
* # Example
|
|
89
|
+
* ```ts
|
|
90
|
+
* await snaptrude.core.mode.set("present")
|
|
91
|
+
* // ... presentation work ...
|
|
92
|
+
* await snaptrude.core.mode.set("design")
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
public abstract set(mode: PluginAppMode): PluginApiReturn<PluginCoreModeSetResult>
|
|
96
|
+
}
|