Appearance
MeasurementService
Manages 3D measurements (distance, angle, area, multi-point, bounding box, volume, circle, arc) using a descriptor-based type system. Owns measurement state, raycasting, and point interaction; rendering and label layout are owned by the per-type descriptors.
Access
Registered under the name "measurement" on ViewerCore.
ts
import { MeasurementService } from "@optellix/xviewr-sdk";
await viewer.ready();
const measurement = viewer.getService<MeasurementService>("measurement");Public API
Lifecycle
activate(): void— turn on pointer-driven measurement placement.deactivate(): void— turn off placement and detach listeners.reset(): void— clear all measurements and pending points.
Configuration
getConfig(): MeasurementConfigupdateConfig(config: Partial<MeasurementConfig>): voidsetMeasurementMode(mode: string): void—"distance","angle","area","multipoint","aabb","obb","volume","circle","arc", or any registered descriptor name.getMeasurementMode(): string
Points
addPoint(point: THREE.Vector3, hitMesh?: THREE.Mesh | null, hitFace?: number | null): voidsetTemporaryPoint(point: THREE.Vector3 | null): voidgetAllPoints(): THREE.Vector3[]getCurrentPoints(): THREE.Vector3[]getTemporaryPoint(): THREE.Vector3 | nullupdatePointer(x: number, y: number): void— canvas-relative coords.raycast(): THREE.Intersection | null
Measurements
createMeasurement(points: THREE.Vector3[], type?: string): Measurement—typedefaults to"distance".createMeasurementWithResult(points: THREE.Vector3[], type: string, result: MeasurementResultValue): MeasurementmeasureVolume(objects: THREE.Object3D[], options?: VolumeMeasurementOptions): Measurement | nullcompleteMeasurement(): Promise<void>— manual finalize for variable-point modes (area, multipoint).getMeasurements(): Measurement[]removeMeasurement(id: string): booleansetMeasurementVisibility(id: string, visible: boolean): booleanupdateMeasurementPoint(measurementId: string, pointIndex: number, point: THREE.Vector3): boolean
Descriptors
registerDescriptor(descriptor: MeasurementTypeDescriptor): voidgetDescriptor(name: string): MeasurementTypeDescriptor | undefined
Built-in descriptors exported from the SDK: distanceDescriptor, angleDescriptor, areaDescriptor, multiPointDescriptor, aabbDescriptor, obbDescriptor, volumeDescriptor, circleDescriptor, arcDescriptor. Bounding-box computers: AABBComputer, OBBComputer. Volume helpers: computeVolumeMeasurement(objects, options), normalizeVolumeOptions(options).
Events
| Event | Payload |
|---|---|
measurement:activated | null |
measurement:deactivated | null |
measurement:config-updated | { config: MeasurementConfig } |
measurement:point-added | { point, totalPoints } |
measurement:temporary-point-changed | { point } |
measurement:created | { measurement } |
measurement:volume-created | { measurement, options } |
measurement:removed | { measurement } |
measurement:visibility-changed | { id, visible } |
measurement:reset | { clearedMeasurements } |
measurement:in-progress | { mode, pointCount, canComplete } |
measurement:mode-changed | { mode, requiredPoints } |
measurement:point-updated | { measurement } |
measurement:hover-point | { measurementId, pointIndex } | null |
Example
ts
const measurement = viewer.getService<MeasurementService>("measurement");
measurement.setMeasurementMode("distance");
measurement.activate();
viewer.eventBus.on("measurement:created", ({ measurement: m }) => {
if (m.result.type === "distance") {
console.log(`distance: ${m.result.distance.toFixed(2)}`);
}
});
// Programmatic volume measurement on a selection.
const volume = measurement.measureVolume(selectedObjects, {
method: "auto",
voxelResolution: 64,
});Configuration
ts
interface MeasurementConfig {
textScalingFactor: number; // label scale base
raycastThreshold: number;
sectionEnabled: boolean; // limit raycast to contour objects
contourObjects: THREE.Object3D | THREE.Object3D[] | null;
selectableOnly: boolean; // only raycast userData.isSelectable
measurementMode: string;
autoCreateMeasurements: boolean; // finalize when requiredPoints reached
showComponents: boolean; // render dx/dy/dz legs on 2-point distance
surfaceSnap: boolean; // drape distance/multipoint along mesh
volumeMeasurement: VolumeMeasurementOptions;
}
interface VolumeMeasurementOptions {
method?: "auto" | "tetrahedron" | "voxel";
voxelResolution?: number; // default 48
voxelMaxCells?: number; // default 250000
voxelSampleMode?: "center" | "corners";
voxelAxisVotes?: boolean; // 3-axis parity voting
watertightTolerance?: number; // default 1e-5
}Result types
MeasurementResultValue is the union of DistanceResult, AngleResult, AreaResult, MultiPointResult, BoundingBoxResult, VolumeResult, CircleResult, ArcResult. Each carries a type discriminator matching the descriptor name.