@selvajs/compute 2.0.0 → 2.1.0-beta.1

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 (35) hide show
  1. package/dist/chunk-JPXUC3P5.cjs +54 -0
  2. package/dist/chunk-JPXUC3P5.cjs.map +1 -0
  3. package/dist/{chunk-YNVXBKBY.cjs → chunk-P4SF7AKZ.cjs} +2 -2
  4. package/dist/{chunk-YNVXBKBY.cjs.map → chunk-P4SF7AKZ.cjs.map} +1 -1
  5. package/dist/{chunk-UQ3QRF72.js → chunk-SKAHIC4G.js} +2 -2
  6. package/dist/chunk-Z4TVQVMV.js +54 -0
  7. package/dist/chunk-Z4TVQVMV.js.map +1 -0
  8. package/dist/grasshopper.cjs +1 -1
  9. package/dist/grasshopper.d.cts +4 -3
  10. package/dist/grasshopper.d.ts +4 -3
  11. package/dist/grasshopper.js +1 -1
  12. package/dist/index.cjs +1 -1
  13. package/dist/index.d.cts +2 -1
  14. package/dist/index.d.ts +2 -1
  15. package/dist/index.js +1 -1
  16. package/dist/{types-CJ092lxB.d.cts → types-BuRCHPlb.d.cts} +94 -3
  17. package/dist/{types-XCUrJGby.d.ts → types-jPuWWtnU.d.ts} +94 -3
  18. package/dist/visualization-R7QUUUWV.js +2 -0
  19. package/dist/visualization-ZDXKGD2L.cjs +2 -0
  20. package/dist/visualization-ZDXKGD2L.cjs.map +1 -0
  21. package/dist/visualization.cjs +1 -1
  22. package/dist/visualization.cjs.map +1 -1
  23. package/dist/visualization.d.cts +193 -7
  24. package/dist/visualization.d.ts +193 -7
  25. package/dist/visualization.js +1 -1
  26. package/package.json +1 -1
  27. package/dist/chunk-JFLD2UCY.cjs +0 -2
  28. package/dist/chunk-JFLD2UCY.cjs.map +0 -1
  29. package/dist/chunk-MKW2KTPT.js +0 -2
  30. package/dist/chunk-MKW2KTPT.js.map +0 -1
  31. package/dist/visualization-GU7JIB4V.cjs +0 -2
  32. package/dist/visualization-GU7JIB4V.cjs.map +0 -1
  33. package/dist/visualization-WIUVT2FZ.js +0 -2
  34. /package/dist/{chunk-UQ3QRF72.js.map → chunk-SKAHIC4G.js.map} +0 -0
  35. /package/dist/{visualization-WIUVT2FZ.js.map → visualization-R7QUUUWV.js.map} +0 -0
@@ -1,4 +1,5 @@
1
1
  import { C as ComputeConfig, a as RhinoModelUnit } from './types-D1SkNje_.cjs';
2
+ import { RhinoModule } from 'rhino3dm';
2
3
 
3
4
  /**
4
5
  * Grasshopper types
@@ -310,6 +311,75 @@ interface GrasshopperParsedIO {
310
311
  loadErrors?: string[];
311
312
  }
312
313
 
314
+ /**
315
+ * Non-mesh display items: curves, points, and later labels/icons.
316
+ *
317
+ * These ride as JSON inside a {@link DisplayBatch} alongside the binary mesh blob — they are a
318
+ * separate pipeline from the SLVA mesh path in `../webdisplay`. Curves arrive as Rhino-native JSON
319
+ * (decoded via rhino3dm and tessellated on the web); points arrive as raw `{X,Y,Z}` positions.
320
+ *
321
+ * The union is STRICT and discriminated on `kind`. The parser narrows on it and uses a
322
+ * `never`-exhaustiveness check, so adding a new kind is a compile error until it is handled.
323
+ */
324
+ /**
325
+ * Identity + tagging shared by every display thing — meshes (via an adapter over `MeshMetadata`)
326
+ * and items alike — so pick / filter / label code treats them uniformly. Deliberately excludes
327
+ * rendering concerns (color/material): those differ by kind and are not identity.
328
+ */
329
+ interface DisplayIdentity {
330
+ /** Stable pick key. Both meshes and items synthesize it as `${sourceComponentId}:${originalIndex}`. */
331
+ id: string;
332
+ /** Human label (e.g. "North wall"). Distinct from {@link id} — renaming must not change identity. */
333
+ name: string;
334
+ /** Layer path for grouping in the scene manager (e.g. "Structure/Walls"). */
335
+ layer: string;
336
+ /** Arbitrary key-value pairs from the GH Metadata input. */
337
+ metadata?: Record<string, string>;
338
+ }
339
+ /**
340
+ * Style fields every visible item can honour. Lines and points have no PBR (no metalness/roughness),
341
+ * so only color + opacity apply here; a future kind that needs richer material adds fields to its own
342
+ * variant rather than bloating this base.
343
+ */
344
+ interface DisplayItemBase extends DisplayIdentity {
345
+ /** Hex/rgb/named color string, parsed by `parseColor`. Falls back to a viewer default. */
346
+ color?: string;
347
+ /** Opacity 0–1. Omitted means fully opaque. */
348
+ opacity?: number;
349
+ }
350
+ /** A world position in Rhino's Z-up frame, in Rhino's `{X,Y,Z}` casing. Rotated to Three on parse. */
351
+ interface DisplayPosition {
352
+ X: number;
353
+ Y: number;
354
+ Z: number;
355
+ }
356
+ /**
357
+ * A curve shipped as Rhino-native JSON (`curve.ToNurbsCurve().ToJSON()`), decoded via rhino3dm and
358
+ * tessellated to a fat `Line2` on the web (so {@link DisplayCurve.width} is honoured).
359
+ */
360
+ interface DisplayCurve extends DisplayItemBase {
361
+ kind: 'curve';
362
+ /** Rhino CommonObject JSON for the curve. */
363
+ json: string;
364
+ /**
365
+ * Line thickness in CSS pixels (screen-space, constant regardless of zoom). Rendered via a fat
366
+ * `Line2`, so unlike `THREE.Line` this is actually honoured. Omitted → viewer default.
367
+ */
368
+ width?: number;
369
+ }
370
+ /** A single point, shipped raw (no rhino3dm decode), rendered as one vertex of a `THREE.Points`. */
371
+ interface DisplayPoint extends DisplayItemBase {
372
+ kind: 'point';
373
+ /** World position in Rhino Z-up; the shared Rhino→Three transform is applied on parse. */
374
+ position: DisplayPosition;
375
+ }
376
+ /**
377
+ * One non-mesh display item. Meshes do NOT appear here — they ride the binary blob in `DisplayBatch`.
378
+ * New kinds (`label`, `icon`) extend this union and add a parser case; the parser's `never` guard
379
+ * forces them to be handled.
380
+ */
381
+ type DisplayItem = DisplayCurve | DisplayPoint;
382
+
313
383
  /**
314
384
  * Material properties for Three.js rendering.
315
385
  */
@@ -359,14 +429,18 @@ interface MaterialGroup {
359
429
  meshes: MeshMetadata[];
360
430
  }
361
431
  /**
362
- * Batched mesh data optimized for Three.js rendering.
432
+ * One Display component's payload, ready for Three.js rendering.
363
433
  *
364
434
  * `compressedData` contains the binary "SLVA" blob (header + metadata JSON + quantized int16 or
365
435
  * float32 vertices + uint32 indices), base64-encoded for transit inside the values JSON envelope.
366
436
  * The blob is opaque to the outer JSON: a future binary WebSocket frame can drop the base64 step
367
437
  * without changing this shape.
438
+ *
439
+ * Today this carries only meshes (the binary blob). It is named `DisplayBatch` rather than
440
+ * `MeshBatch` because it is the seam through which non-mesh display items (curves, points, and
441
+ * later labels/icons) also travel — those ride as JSON alongside the mesh blob, not inside it.
368
442
  */
369
- interface MeshBatch {
443
+ interface DisplayBatch {
370
444
  /** Array of unique materials */
371
445
  materials: SerializableMaterial[];
372
446
  /** Groups of meshes organized by material */
@@ -376,7 +450,19 @@ interface MeshBatch {
376
450
  /** InstanceGuid of the WebDisplay GH component that produced this batch.
377
451
  * Combined with MeshMetadata.originalIndex to backtrack any mesh to its GH source. */
378
452
  sourceComponentId?: string;
453
+ /**
454
+ * Non-mesh display items (curves, points; later labels/icons) — see {@link DisplayItem}.
455
+ * Optional: omitted when there are none, so mesh-only batches are unchanged on the wire. These
456
+ * ride as JSON alongside the mesh blob and are parsed by the separate `display-items` path, not
457
+ * the SLVA mesh parser.
458
+ */
459
+ items?: DisplayItem[];
379
460
  }
461
+ /**
462
+ * @deprecated Renamed to {@link DisplayBatch} — the payload now carries more than meshes.
463
+ * This alias keeps existing imports compiling; remove it once consumers migrate.
464
+ */
465
+ type MeshBatch = DisplayBatch;
380
466
  /**
381
467
  * Options for parsing mesh batch data.
382
468
  */
@@ -398,8 +484,13 @@ interface MeshExtractionOptions {
398
484
  allowScaling?: boolean;
399
485
  /** Apply automatic ground offset positioning (Z=0). Defaults to true. */
400
486
  allowAutoPosition?: boolean;
487
+ /**
488
+ * rhino3dm instance for decoding curve display items. selva-compute does not own the WASM
489
+ * instance; the host threads it in. Omit to skip curves (points still render).
490
+ */
491
+ rhino?: RhinoModule;
401
492
  /** Enable verbose logging. Defaults to false. */
402
493
  debug?: boolean;
403
494
  }
404
495
 
405
- export type { BooleanInputType as B, DataItem as D, FileInputType as F, GeometryInputType as G, InnerTreeData as I, MeshExtractionOptions as M, NumericInputType as N, OutputParamSchema as O, TextInputType as T, ValueListInputType as V, DataTree as a, DataTreeDefault as b, DataTreePath as c, DefaultValue as d, GrasshopperComputeConfig as e, GrasshopperComputeResponse as f, GrasshopperParsedIO as g, GrasshopperParsedIORaw as h, GrasshopperRequestSchema as i, InputParam as j, InputParamSchema as k, OutputType as l, MeshBatchParsingOptions as m, MeshBatch as n };
496
+ export type { BooleanInputType as B, DataItem as D, FileInputType as F, GeometryInputType as G, InnerTreeData as I, MeshExtractionOptions as M, NumericInputType as N, OutputParamSchema as O, TextInputType as T, ValueListInputType as V, DataTree as a, DataTreeDefault as b, DataTreePath as c, DefaultValue as d, GrasshopperComputeConfig as e, GrasshopperComputeResponse as f, GrasshopperParsedIO as g, GrasshopperParsedIORaw as h, GrasshopperRequestSchema as i, InputParam as j, InputParamSchema as k, OutputType as l, MeshBatchParsingOptions as m, DisplayBatch as n, DisplayItem as o, DisplayCurve as p, DisplayIdentity as q, DisplayItemBase as r, DisplayPoint as s, DisplayPosition as t, MeshBatch as u };
@@ -1,4 +1,5 @@
1
1
  import { C as ComputeConfig, a as RhinoModelUnit } from './types-D1SkNje_.js';
2
+ import { RhinoModule } from 'rhino3dm';
2
3
 
3
4
  /**
4
5
  * Grasshopper types
@@ -310,6 +311,75 @@ interface GrasshopperParsedIO {
310
311
  loadErrors?: string[];
311
312
  }
312
313
 
314
+ /**
315
+ * Non-mesh display items: curves, points, and later labels/icons.
316
+ *
317
+ * These ride as JSON inside a {@link DisplayBatch} alongside the binary mesh blob — they are a
318
+ * separate pipeline from the SLVA mesh path in `../webdisplay`. Curves arrive as Rhino-native JSON
319
+ * (decoded via rhino3dm and tessellated on the web); points arrive as raw `{X,Y,Z}` positions.
320
+ *
321
+ * The union is STRICT and discriminated on `kind`. The parser narrows on it and uses a
322
+ * `never`-exhaustiveness check, so adding a new kind is a compile error until it is handled.
323
+ */
324
+ /**
325
+ * Identity + tagging shared by every display thing — meshes (via an adapter over `MeshMetadata`)
326
+ * and items alike — so pick / filter / label code treats them uniformly. Deliberately excludes
327
+ * rendering concerns (color/material): those differ by kind and are not identity.
328
+ */
329
+ interface DisplayIdentity {
330
+ /** Stable pick key. Both meshes and items synthesize it as `${sourceComponentId}:${originalIndex}`. */
331
+ id: string;
332
+ /** Human label (e.g. "North wall"). Distinct from {@link id} — renaming must not change identity. */
333
+ name: string;
334
+ /** Layer path for grouping in the scene manager (e.g. "Structure/Walls"). */
335
+ layer: string;
336
+ /** Arbitrary key-value pairs from the GH Metadata input. */
337
+ metadata?: Record<string, string>;
338
+ }
339
+ /**
340
+ * Style fields every visible item can honour. Lines and points have no PBR (no metalness/roughness),
341
+ * so only color + opacity apply here; a future kind that needs richer material adds fields to its own
342
+ * variant rather than bloating this base.
343
+ */
344
+ interface DisplayItemBase extends DisplayIdentity {
345
+ /** Hex/rgb/named color string, parsed by `parseColor`. Falls back to a viewer default. */
346
+ color?: string;
347
+ /** Opacity 0–1. Omitted means fully opaque. */
348
+ opacity?: number;
349
+ }
350
+ /** A world position in Rhino's Z-up frame, in Rhino's `{X,Y,Z}` casing. Rotated to Three on parse. */
351
+ interface DisplayPosition {
352
+ X: number;
353
+ Y: number;
354
+ Z: number;
355
+ }
356
+ /**
357
+ * A curve shipped as Rhino-native JSON (`curve.ToNurbsCurve().ToJSON()`), decoded via rhino3dm and
358
+ * tessellated to a fat `Line2` on the web (so {@link DisplayCurve.width} is honoured).
359
+ */
360
+ interface DisplayCurve extends DisplayItemBase {
361
+ kind: 'curve';
362
+ /** Rhino CommonObject JSON for the curve. */
363
+ json: string;
364
+ /**
365
+ * Line thickness in CSS pixels (screen-space, constant regardless of zoom). Rendered via a fat
366
+ * `Line2`, so unlike `THREE.Line` this is actually honoured. Omitted → viewer default.
367
+ */
368
+ width?: number;
369
+ }
370
+ /** A single point, shipped raw (no rhino3dm decode), rendered as one vertex of a `THREE.Points`. */
371
+ interface DisplayPoint extends DisplayItemBase {
372
+ kind: 'point';
373
+ /** World position in Rhino Z-up; the shared Rhino→Three transform is applied on parse. */
374
+ position: DisplayPosition;
375
+ }
376
+ /**
377
+ * One non-mesh display item. Meshes do NOT appear here — they ride the binary blob in `DisplayBatch`.
378
+ * New kinds (`label`, `icon`) extend this union and add a parser case; the parser's `never` guard
379
+ * forces them to be handled.
380
+ */
381
+ type DisplayItem = DisplayCurve | DisplayPoint;
382
+
313
383
  /**
314
384
  * Material properties for Three.js rendering.
315
385
  */
@@ -359,14 +429,18 @@ interface MaterialGroup {
359
429
  meshes: MeshMetadata[];
360
430
  }
361
431
  /**
362
- * Batched mesh data optimized for Three.js rendering.
432
+ * One Display component's payload, ready for Three.js rendering.
363
433
  *
364
434
  * `compressedData` contains the binary "SLVA" blob (header + metadata JSON + quantized int16 or
365
435
  * float32 vertices + uint32 indices), base64-encoded for transit inside the values JSON envelope.
366
436
  * The blob is opaque to the outer JSON: a future binary WebSocket frame can drop the base64 step
367
437
  * without changing this shape.
438
+ *
439
+ * Today this carries only meshes (the binary blob). It is named `DisplayBatch` rather than
440
+ * `MeshBatch` because it is the seam through which non-mesh display items (curves, points, and
441
+ * later labels/icons) also travel — those ride as JSON alongside the mesh blob, not inside it.
368
442
  */
369
- interface MeshBatch {
443
+ interface DisplayBatch {
370
444
  /** Array of unique materials */
371
445
  materials: SerializableMaterial[];
372
446
  /** Groups of meshes organized by material */
@@ -376,7 +450,19 @@ interface MeshBatch {
376
450
  /** InstanceGuid of the WebDisplay GH component that produced this batch.
377
451
  * Combined with MeshMetadata.originalIndex to backtrack any mesh to its GH source. */
378
452
  sourceComponentId?: string;
453
+ /**
454
+ * Non-mesh display items (curves, points; later labels/icons) — see {@link DisplayItem}.
455
+ * Optional: omitted when there are none, so mesh-only batches are unchanged on the wire. These
456
+ * ride as JSON alongside the mesh blob and are parsed by the separate `display-items` path, not
457
+ * the SLVA mesh parser.
458
+ */
459
+ items?: DisplayItem[];
379
460
  }
461
+ /**
462
+ * @deprecated Renamed to {@link DisplayBatch} — the payload now carries more than meshes.
463
+ * This alias keeps existing imports compiling; remove it once consumers migrate.
464
+ */
465
+ type MeshBatch = DisplayBatch;
380
466
  /**
381
467
  * Options for parsing mesh batch data.
382
468
  */
@@ -398,8 +484,13 @@ interface MeshExtractionOptions {
398
484
  allowScaling?: boolean;
399
485
  /** Apply automatic ground offset positioning (Z=0). Defaults to true. */
400
486
  allowAutoPosition?: boolean;
487
+ /**
488
+ * rhino3dm instance for decoding curve display items. selva-compute does not own the WASM
489
+ * instance; the host threads it in. Omit to skip curves (points still render).
490
+ */
491
+ rhino?: RhinoModule;
401
492
  /** Enable verbose logging. Defaults to false. */
402
493
  debug?: boolean;
403
494
  }
404
495
 
405
- export type { BooleanInputType as B, DataItem as D, FileInputType as F, GeometryInputType as G, InnerTreeData as I, MeshExtractionOptions as M, NumericInputType as N, OutputParamSchema as O, TextInputType as T, ValueListInputType as V, DataTree as a, DataTreeDefault as b, DataTreePath as c, DefaultValue as d, GrasshopperComputeConfig as e, GrasshopperComputeResponse as f, GrasshopperParsedIO as g, GrasshopperParsedIORaw as h, GrasshopperRequestSchema as i, InputParam as j, InputParamSchema as k, OutputType as l, MeshBatchParsingOptions as m, MeshBatch as n };
496
+ export type { BooleanInputType as B, DataItem as D, FileInputType as F, GeometryInputType as G, InnerTreeData as I, MeshExtractionOptions as M, NumericInputType as N, OutputParamSchema as O, TextInputType as T, ValueListInputType as V, DataTree as a, DataTreeDefault as b, DataTreePath as c, DefaultValue as d, GrasshopperComputeConfig as e, GrasshopperComputeResponse as f, GrasshopperParsedIO as g, GrasshopperParsedIORaw as h, GrasshopperRequestSchema as i, InputParam as j, InputParamSchema as k, OutputType as l, MeshBatchParsingOptions as m, DisplayBatch as n, DisplayItem as o, DisplayCurve as p, DisplayIdentity as q, DisplayItemBase as r, DisplayPoint as s, DisplayPosition as t, MeshBatch as u };
@@ -0,0 +1,2 @@
1
+ import{A as u,a as e,b as r,c as o,d as t,e as a,f as s,g as p,h as i,i as n,j as m,k as l,l as f,m as y,n as d,o as h,p as x,q as C,r as g,s as M,t as c,u as B,v as j,w as E,x as D,y as O,z as b}from"./chunk-Z4TVQVMV.js";import"./chunk-GTTKNF4G.js";export{M as BINARY_MESH_MAGIC,c as BINARY_MESH_VERSION,i as EDGE_USERDATA_KIND,B as FLAG_FLOAT32,C as Materials,b as SCALE_FACTORS,n as addEdges,o as applyOffset,t as computeCombinedBoundingBox,a as createCameraController,s as createGrid,y as createLabelLayer,h as createMeasureTool,f as createRenderPipeline,p as createViewGizmo,u as getThreeMeshesFromComputeResponse,x as initThree,m as isEdgeOverlay,j as parseBinaryMeshBatch,r as parseColor,g as parseDisplayItems,E as parseMeshBatch,O as parseMeshBatchBlob,D as parseMeshBatchObject,l as removeEdges,d as snapToVertex,e as updateScene};
2
+ //# sourceMappingURL=visualization-R7QUUUWV.js.map
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkJPXUC3P5cjs = require('./chunk-JPXUC3P5.cjs');require('./chunk-MA6YB3YZ.cjs');exports.BINARY_MESH_MAGIC = _chunkJPXUC3P5cjs.s; exports.BINARY_MESH_VERSION = _chunkJPXUC3P5cjs.t; exports.EDGE_USERDATA_KIND = _chunkJPXUC3P5cjs.h; exports.FLAG_FLOAT32 = _chunkJPXUC3P5cjs.u; exports.Materials = _chunkJPXUC3P5cjs.q; exports.SCALE_FACTORS = _chunkJPXUC3P5cjs.z; exports.addEdges = _chunkJPXUC3P5cjs.i; exports.applyOffset = _chunkJPXUC3P5cjs.c; exports.computeCombinedBoundingBox = _chunkJPXUC3P5cjs.d; exports.createCameraController = _chunkJPXUC3P5cjs.e; exports.createGrid = _chunkJPXUC3P5cjs.f; exports.createLabelLayer = _chunkJPXUC3P5cjs.m; exports.createMeasureTool = _chunkJPXUC3P5cjs.o; exports.createRenderPipeline = _chunkJPXUC3P5cjs.l; exports.createViewGizmo = _chunkJPXUC3P5cjs.g; exports.getThreeMeshesFromComputeResponse = _chunkJPXUC3P5cjs.A; exports.initThree = _chunkJPXUC3P5cjs.p; exports.isEdgeOverlay = _chunkJPXUC3P5cjs.j; exports.parseBinaryMeshBatch = _chunkJPXUC3P5cjs.v; exports.parseColor = _chunkJPXUC3P5cjs.b; exports.parseDisplayItems = _chunkJPXUC3P5cjs.r; exports.parseMeshBatch = _chunkJPXUC3P5cjs.w; exports.parseMeshBatchBlob = _chunkJPXUC3P5cjs.y; exports.parseMeshBatchObject = _chunkJPXUC3P5cjs.x; exports.removeEdges = _chunkJPXUC3P5cjs.k; exports.snapToVertex = _chunkJPXUC3P5cjs.n; exports.updateScene = _chunkJPXUC3P5cjs.a;
2
+ //# sourceMappingURL=visualization-ZDXKGD2L.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/selva-compute/selva-compute/dist/visualization-ZDXKGD2L.cjs"],"names":[],"mappings":"AAAA,iIAA8N,gCAA6B,owCAA+kB","file":"/home/runner/work/selva-compute/selva-compute/dist/visualization-ZDXKGD2L.cjs"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkJFLD2UCYcjs = require('./chunk-JFLD2UCY.cjs');require('./chunk-MA6YB3YZ.cjs');exports.Materials = _chunkJFLD2UCYcjs.f; exports.SCALE_FACTORS = _chunkJFLD2UCYcjs.n; exports.getThreeMeshesFromComputeResponse = _chunkJFLD2UCYcjs.o; exports.initThree = _chunkJFLD2UCYcjs.a; exports.parseMeshBatchBlob = _chunkJFLD2UCYcjs.m; exports.parseMeshBatchObject = _chunkJFLD2UCYcjs.l; exports.updateScene = _chunkJFLD2UCYcjs.b;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkJPXUC3P5cjs = require('./chunk-JPXUC3P5.cjs');require('./chunk-MA6YB3YZ.cjs');exports.Materials = _chunkJPXUC3P5cjs.q; exports.SCALE_FACTORS = _chunkJPXUC3P5cjs.z; exports.getThreeMeshesFromComputeResponse = _chunkJPXUC3P5cjs.A; exports.initThree = _chunkJPXUC3P5cjs.p; exports.parseDisplayItems = _chunkJPXUC3P5cjs.r; exports.parseMeshBatchBlob = _chunkJPXUC3P5cjs.y; exports.parseMeshBatchObject = _chunkJPXUC3P5cjs.x; exports.updateScene = _chunkJPXUC3P5cjs.a;
2
2
  //# sourceMappingURL=visualization.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/selva-compute/selva-compute/dist/visualization.cjs"],"names":[],"mappings":"AAAA,iIAA6E,gCAA6B,gVAAmK","file":"/home/runner/work/selva-compute/selva-compute/dist/visualization.cjs"}
1
+ {"version":3,"sources":["/home/runner/work/selva-compute/selva-compute/dist/visualization.cjs"],"names":[],"mappings":"AAAA,iIAAyF,gCAA6B,iYAA0L","file":"/home/runner/work/selva-compute/selva-compute/dist/visualization.cjs"}
@@ -1,6 +1,8 @@
1
1
  import * as THREE from 'three';
2
2
  import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
3
- import { f as GrasshopperComputeResponse, M as MeshExtractionOptions, m as MeshBatchParsingOptions, n as MeshBatch } from './types-CJ092lxB.cjs';
3
+ import { f as GrasshopperComputeResponse, M as MeshExtractionOptions, m as MeshBatchParsingOptions, n as DisplayBatch, o as DisplayItem } from './types-BuRCHPlb.cjs';
4
+ export { p as DisplayCurve, q as DisplayIdentity, r as DisplayItemBase, s as DisplayPoint, t as DisplayPosition, u as MeshBatch } from './types-BuRCHPlb.cjs';
5
+ import { RhinoModule } from 'rhino3dm';
4
6
  import './types-D1SkNje_.cjs';
5
7
 
6
8
  type CameraConfig = {
@@ -41,6 +43,24 @@ type RenderConfig = {
41
43
  toneMapping?: THREE.ToneMapping;
42
44
  toneMappingExposure?: number;
43
45
  preserveDrawingBuffer?: boolean;
46
+ /**
47
+ * Enable ground-truth ambient occlusion (GTAO) via a postprocessing pipeline. Default false —
48
+ * turning it on switches rendering from `renderer.render` to an EffectComposer, which costs more.
49
+ */
50
+ ambientOcclusion?: boolean;
51
+ /** AO strength 0–1 when {@link RenderConfig.ambientOcclusion} is on. Default 1. */
52
+ aoIntensity?: number;
53
+ };
54
+ /** Crisp boundary/crease edge overlays on meshes. See `addEdges`. */
55
+ type EdgesConfig = {
56
+ /** Auto-attach edge overlays to meshes as they load. Default false (opt-in). */
57
+ enabled?: boolean;
58
+ /** Edge color. Default near-black. */
59
+ color?: THREE.ColorRepresentation;
60
+ /** Edge thickness in CSS px. Default 1.5. */
61
+ width?: number;
62
+ /** Crease angle (degrees): keep edges where faces differ by more than this. Default 30. */
63
+ thresholdAngle?: number;
44
64
  };
45
65
  type ControlsConfig = {
46
66
  enableDamping?: boolean;
@@ -52,6 +72,44 @@ type ControlsConfig = {
52
72
  minDistance?: number;
53
73
  maxDistance?: number;
54
74
  };
75
+ /** Infinite distance-fading reference grid. See `createGrid`. */
76
+ type GridConfig = {
77
+ /** Show the grid. Default false (opt-in). */
78
+ enabled?: boolean;
79
+ /** Minor cell size in world units (meters). Default 1. */
80
+ cellSize?: number;
81
+ /** Minor cells per major line. Default 10. */
82
+ majorEvery?: number;
83
+ /** Minor line color. */
84
+ cellColor?: THREE.ColorRepresentation;
85
+ /** Major line color. */
86
+ majorColor?: THREE.ColorRepresentation;
87
+ /** World radius at which the grid fully fades. Default 100. */
88
+ fadeDistance?: number;
89
+ /** Plane the grid lies on. 'y' = horizontal ground. Default 'y'. */
90
+ plane?: 'x' | 'y' | 'z';
91
+ };
92
+ /** Corner nav-cube/axis gizmo that snaps to preset views. See `createViewGizmo`. */
93
+ type GizmoConfig = {
94
+ /** Show the gizmo. Default false (opt-in). */
95
+ enabled?: boolean;
96
+ };
97
+ /** Two-click distance measurement tool. See `createMeasureTool`. */
98
+ type MeasureConfig = {
99
+ /**
100
+ * Create the measurement tool. Default false. Note: this only *builds* the tool (and its label
101
+ * overlay); start measuring by calling `measureTool.setEnabled(true)` on the init result.
102
+ */
103
+ enabled?: boolean;
104
+ /** Snap to a vertex within this many screen px. Default 12. */
105
+ snapPixels?: number;
106
+ /** Marker + line color. Default yellow. */
107
+ color?: THREE.ColorRepresentation;
108
+ /** CSS class for the distance label. */
109
+ labelClassName?: string;
110
+ /** Format the distance number → label text. Default 3 sig-digits + " m". */
111
+ format?: (distance: number) => string;
112
+ };
55
113
  type ThreeInitializerOptions = {
56
114
  sceneScale?: 'mm' | 'cm' | 'm' | 'inches' | 'feet';
57
115
  camera?: CameraConfig;
@@ -60,6 +118,10 @@ type ThreeInitializerOptions = {
60
118
  floor?: FloorConfig;
61
119
  render?: RenderConfig;
62
120
  controls?: ControlsConfig;
121
+ grid?: GridConfig;
122
+ gizmo?: GizmoConfig;
123
+ edges?: EdgesConfig;
124
+ measure?: MeasureConfig;
63
125
  events?: EventConfig;
64
126
  };
65
127
  type EventConfig = {
@@ -86,6 +148,105 @@ type EventConfig = {
86
148
  onFrame?: (delta: number) => void;
87
149
  };
88
150
 
151
+ /**
152
+ * Runtime camera control for the viewer: preset views (top/front/…), a true 2D/3D toggle
153
+ * (orthographic ⇄ perspective), and a rotate lock.
154
+ *
155
+ * Why a controller and not just loose methods: all three features have to agree on *which* camera
156
+ * is active. Switching projection swaps the camera object OrbitControls drives, the animation loop
157
+ * renders, the resize handler reshapes, and the raycaster picks with. Centralizing that here keeps
158
+ * those four call sites reading one source of truth ({@link getActiveCamera}) instead of each
159
+ * branching on a `mode` flag.
160
+ *
161
+ * The perspective camera stays the primary (it's what {@link updateScene} and existing consumers
162
+ * size). The orthographic camera shadows it: same position/target, frustum derived from the
163
+ * perspective FOV + current distance so the 3D→2D switch doesn't visually jump.
164
+ */
165
+ /** The six axis-aligned presets plus the default 3/4 iso. Named in Three's Y-up frame. */
166
+ type ViewPreset = 'top' | 'bottom' | 'front' | 'back' | 'left' | 'right' | 'iso';
167
+ type CameraProjection = 'perspective' | 'orthographic';
168
+ interface CameraController {
169
+ /** The camera currently being rendered/picked with. Swaps identity on {@link setProjection}. */
170
+ getActiveCamera(): THREE.Camera;
171
+ /** Current projection mode. */
172
+ getProjection(): CameraProjection;
173
+ /** Switch between perspective (3D) and orthographic (2D). No-op if already in that mode. */
174
+ setProjection(projection: CameraProjection): void;
175
+ /** Convenience toggle for a 2D/3D button. */
176
+ toggleProjection(): CameraProjection;
177
+ /** Move the camera to a preset orientation, framing current scene content. Animated. */
178
+ setView(preset: ViewPreset, animate?: boolean): void;
179
+ /** Enable/disable orbit rotation at runtime (pan/zoom unaffected). */
180
+ setRotateEnabled(enabled: boolean): void;
181
+ /** Whether rotation is currently enabled. */
182
+ isRotateEnabled(): boolean;
183
+ /** Keep the orthographic frustum aspect in sync on canvas resize. Called by the resize loop. */
184
+ updateAspect(width: number, height: number): void;
185
+ }
186
+
187
+ interface Grid {
188
+ /** The grid mesh; add to the scene. Tagged `userData.id = 'grid'` so pick/fit code skips it. */
189
+ readonly object: THREE.Mesh;
190
+ /** Keep the fade centered on the camera so the grid feels infinite as you move. Call per frame. */
191
+ update(cameraPosition: THREE.Vector3): void;
192
+ setVisible(visible: boolean): void;
193
+ dispose(): void;
194
+ }
195
+
196
+ /**
197
+ * The corner nav-cube/axis gizmo. Wraps three's {@link ViewHelper} (the standard, well-tested
198
+ * widget) and uses its built-in click → animate behavior, which we keep rather than reimplement:
199
+ * ViewHelper's hit-test depends on private internals (`dim`, `interactiveObjects`, viewport math),
200
+ * so replicating it is fragile. We let it drive the perspective camera directly.
201
+ *
202
+ * Two integration points with the viewer's dual-camera setup:
203
+ * 1. Before each click we point `helper.center` at the live orbit target, so the snap rotates about
204
+ * what the user is looking at (not the world origin).
205
+ * 2. ViewHelper only drives the perspective camera. The nav cube is inherently a 3D-orientation
206
+ * tool, so if the viewer is in orthographic (2D) mode when the gizmo is clicked, we first flip
207
+ * back to perspective — then ViewHelper animates as usual. Using the cube returns you to 3D.
208
+ *
209
+ * Caller responsibilities (mirror ViewHelper's own contract):
210
+ * - call {@link ViewGizmo.render} *after* the main scene render each frame (overlay viewport),
211
+ * - call {@link ViewGizmo.update} each frame with the frame delta (drives the snap animation),
212
+ * - forward pointer clicks to {@link ViewGizmo.handleClick}.
213
+ */
214
+ interface ViewGizmo {
215
+ render(renderer: THREE.WebGLRenderer): void;
216
+ update(delta: number): void;
217
+ /** Hit-test a click. Returns true if it hit the gizmo (and a view change started). */
218
+ handleClick(event: MouseEvent): boolean;
219
+ readonly isAnimating: boolean;
220
+ /** Show/hide the gizmo at runtime. Hidden = not rendered and not click-hittable. */
221
+ setVisible(visible: boolean): void;
222
+ isVisible(): boolean;
223
+ dispose(): void;
224
+ }
225
+
226
+ /**
227
+ * A two-click distance measurement tool — the CAD verb users expect. Click a point, click a second,
228
+ * read the distance off a label on the connecting line; a third click starts a new measurement.
229
+ *
230
+ * Picking snaps to geometry so measurements are exact, not "wherever the ray happened to land":
231
+ * on a mesh hit we snap to the nearest vertex of the struck triangle if it's within
232
+ * {@link MeasureOptions.snapPixels} on screen, else use the raw hit point. This is a cheap local
233
+ * snap (three candidate vertices), no spatial index — enough for clean vertex-to-vertex measurement
234
+ * without the cost/complexity of full edge/midpoint snapping (a later refinement).
235
+ *
236
+ * The tool is dormant until {@link MeasureTool.setEnabled}(true). While enabled it intercepts clicks
237
+ * (the caller forwards them and swallows the event when {@link MeasureTool.handleClick} returns
238
+ * true) so measuring doesn't also select objects.
239
+ */
240
+ interface MeasureTool {
241
+ setEnabled(enabled: boolean): void;
242
+ isEnabled(): boolean;
243
+ /** Process a click. Returns true if the tool consumed it (caller should not also select). */
244
+ handleClick(event: MouseEvent): boolean;
245
+ /** Clear the current measurement (markers, line, label). */
246
+ clear(): void;
247
+ dispose(): void;
248
+ }
249
+
89
250
  /**
90
251
  * Initializes a Three.js environment with scene, camera, renderer, and event handling.
91
252
  */
@@ -94,6 +255,18 @@ declare const initThree: (canvas: HTMLCanvasElement, options?: ThreeInitializerO
94
255
  camera: THREE.PerspectiveCamera;
95
256
  controls: OrbitControls;
96
257
  renderer: THREE.WebGLRenderer;
258
+ cameraController: CameraController;
259
+ grid: Grid | null;
260
+ gizmo: ViewGizmo | null;
261
+ /** Two-click distance measurement tool. Null unless `measure.enabled`; `setEnabled(true)` to use. */
262
+ measureTool: MeasureTool | null;
263
+ /**
264
+ * Attach edge overlays to the meshes under `root` (no-op unless `edges.enabled`). Call after
265
+ * loading meshes via `updateScene`, since meshes arrive after init.
266
+ */
267
+ applyEdges: (root: THREE.Object3D) => void;
268
+ /** Toggle ambient occlusion at runtime — builds or tears down the postprocessing pipeline. */
269
+ setAmbientOcclusion: (enabled: boolean) => void;
97
270
  dispose: () => void;
98
271
  fitToView: () => void;
99
272
  clearSelection: () => void;
@@ -108,7 +281,7 @@ declare const initThree: (canvas: HTMLCanvasElement, options?: ThreeInitializerO
108
281
  * @param controls - The OrbitControls object to update.
109
282
  * @param initialPositionSet - A boolean indicating whether the initial position of the camera and controls have been set.
110
283
  */
111
- declare function updateScene(scene: THREE.Scene, meshes: THREE.Mesh[], camera: THREE.PerspectiveCamera, controls: OrbitControls, initialPositionSet: boolean): void;
284
+ declare function updateScene(scene: THREE.Scene, meshes: THREE.Object3D[], camera: THREE.PerspectiveCamera, controls: OrbitControls, initialPositionSet: boolean): void;
112
285
 
113
286
  declare const EMISSIVE_MATERIAL: THREE.MeshPhysicalMaterial;
114
287
  declare const METAL_MATERIAL: THREE.MeshPhysicalMaterial;
@@ -174,7 +347,7 @@ declare const SCALE_FACTORS: Record<string, number>;
174
347
  * });
175
348
  * ```
176
349
  */
177
- declare function getThreeMeshesFromComputeResponse(data: GrasshopperComputeResponse, options?: MeshExtractionOptions): Promise<THREE.Mesh[]>;
350
+ declare function getThreeMeshesFromComputeResponse(data: GrasshopperComputeResponse, options?: MeshExtractionOptions): Promise<THREE.Object3D[]>;
178
351
 
179
352
  /**
180
353
  * Internal-only telemetry threaded from an outer entry point (e.g. the JSON
@@ -186,17 +359,17 @@ interface ParseTelemetry {
186
359
  perfStart?: number;
187
360
  }
188
361
  /**
189
- * Parses a MeshBatch object and creates Three.js meshes.
362
+ * Parses a DisplayBatch object and creates Three.js meshes from its mesh blob.
190
363
  *
191
364
  * The path is synchronous internally — `parseBinaryMeshBatch` does no IO, just typed-array views
192
365
  * over the blob. The function stays `async` so callers don't have to change shape if we move
193
366
  * parsing into a worker later.
194
367
  *
195
- * @param batch - MeshBatch object
368
+ * @param batch - DisplayBatch object
196
369
  * @param options - Rendering options
197
370
  * @returns Promise resolving to array of Three.js mesh objects
198
371
  */
199
- declare function parseMeshBatchObject(batch: MeshBatch, options?: MeshBatchParsingOptions & {
372
+ declare function parseMeshBatchObject(batch: DisplayBatch, options?: MeshBatchParsingOptions & {
200
373
  /** Scale factor to apply to meshes (e.g., for unit conversion) */
201
374
  scaleFactor?: number;
202
375
  },
@@ -219,4 +392,17 @@ declare function parseMeshBatchBlob(blob: ArrayBuffer | Uint8Array, options?: Me
219
392
  scaleFactor?: number;
220
393
  }): Promise<THREE.Mesh[]>;
221
394
 
222
- export { type CameraConfig, type ControlsConfig, type EnvironmentConfig, type EventConfig, type FloorConfig, type LightingConfig, threeMaterials as Materials, MeshBatch, MeshExtractionOptions, type RenderConfig, SCALE_FACTORS, type ThreeInitializerOptions, getThreeMeshesFromComputeResponse, initThree, parseMeshBatchBlob, parseMeshBatchObject, updateScene };
395
+ interface DisplayItemParseOptions {
396
+ /** rhino3dm instance for decoding curve JSON. Omit to skip curves (points still render). */
397
+ rhino?: RhinoModule;
398
+ /** Apply the Rhino Z-up → Three Y-up transform. Defaults to true (matches the mesh path). */
399
+ applyTransforms?: boolean;
400
+ }
401
+ /**
402
+ * Parse a batch's `items` into renderable THREE objects. Returns an empty array when there are no
403
+ * items. Unknown kinds are skipped with a warning (forward-compatible with future label/icon kinds
404
+ * a viewer hasn't taught itself to render yet).
405
+ */
406
+ declare function parseDisplayItems(items: DisplayItem[] | undefined, options?: DisplayItemParseOptions): THREE.Object3D[];
407
+
408
+ export { type CameraConfig, type ControlsConfig, DisplayBatch, DisplayItem, type DisplayItemParseOptions, type EnvironmentConfig, type EventConfig, type FloorConfig, type LightingConfig, threeMaterials as Materials, MeshExtractionOptions, type RenderConfig, SCALE_FACTORS, type ThreeInitializerOptions, getThreeMeshesFromComputeResponse, initThree, parseDisplayItems, parseMeshBatchBlob, parseMeshBatchObject, updateScene };