Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
openaec-foundation avatar

Thatopen Impl Measurements

  • 5 installs
  • 17 repo stars
  • Updated July 8, 2026
  • openaec-foundation/thatopen-claude-skill-package

Helps with ai & agent building tasks.

About

thatopen-impl-measurements is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.

  • thatopen-impl-measurements
  • AI & Agent Building
  • AI-coding skill

Thatopen Impl Measurements by the numbers

  • 5 all-time installs (skills.sh)
  • Ranked #13,065 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
  • Data as of Jul 21, 2026 (Skillselion catalog sync)
npx skills add https://github.com/openaec-foundation/thatopen-claude-skill-package --skill thatopen-impl-measurements

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs5
repo stars17
Last updatedJuly 8, 2026
Repositoryopenaec-foundation/thatopen-claude-skill-package

What it does

Helps with ai & agent building tasks.

Files

SKILL.mdMarkdownGitHub ↗

ThatOpen Measurements

Overview

This skill covers the measurement system in @thatopen/components-front: LengthMeasurement, AreaMeasurement, VolumeMeasurement, and AngleMeasurement. All four extend the abstract Measurement<T, U> base class, which provides shared visual elements, snapping, units, disposal, and event handling.

Version: @thatopen/components-front 3.3.x Prerequisites: thatopen-impl-viewer (world setup), thatopen-core-architecture

Measurement Type Comparison

TypeClassModesUnit TypeVisual Elements
DistanceLengthMeasurement"free", "edge"mm, cm, m, kmDimensionLine + Mark labels
AreaAreaMeasurement"free", "square", "face"mm2, cm2, m2, km2MeasureFill + DimensionLine + Mark
VolumeVolumeMeasurement"free"mm3, cm3, m3, km3MeasureVolume + DimensionLine + Mark
AngleAngleMeasurement"free"deg, radArc geometry + DimensionLine + Mark

Measurement Base Class

All measurement classes extend:

abstract class Measurement<
  T extends Record<string, any>,
  U extends keyof MeasureToUnitMap
> extends OBC.Component implements OBC.Createable, OBC.Hideable, OBC.Disposable

Shared Data Collections

CollectionTypePurpose
listDataSet<T>All measurement elements of that type
linesDataSet<DimensionLine>Visual dimension lines
fillsDataSet<MeasureFill>Visual area fill meshes
labelsDataSet<Mark>HTML label overlays
volumesDataSet<MeasureVolume>Visual volume meshes

Shared Configuration Properties

PropertyTypeDefaultDescription
enabledbooleanfalseActivates measurement interaction
visiblebooleantrueShows/hides all visual elements
unitsMeasureToUnitMap[U]per typeUnit for display
roundingnumber2Decimal precision
colorTHREE.ColorblueColor of all visual elements
delaynumber300Pointer stop detection delay (ms)
worldOBC.WorldWorld reference (REQUIRED)

Material Properties

PropertyTypeDefault
linesMaterialTHREE.LineBasicMaterialBlue, depthTest false
fillsMaterialTHREE.MeshLambertMaterialGreen, double-sided, 30% opacity
volumesMaterialTHREE.MeshLambertMaterialGreen, double-sided, 30% opacity
linesEndpointElementHTMLElementBlue rounded div (dimension mark)

Static Members

// Custom value formatter — applies to ALL measurement instances
Measurement.valueFormatter = (value: number) => `${value.toFixed(1)} m`;

ALWAYS set Measurement.valueFormatter before enabling measurements if you need custom label formatting. It is a static property shared across all measurement types.

Events

EventPayloadTrigger
onPointerStopPointer stopped moving for delay ms
onPointerMovePointer moved
onStateChangedMeasurementStateChange[]Mode, color, units, rounding, visibility, or enabled changed
onEnabledChangebooleanEnabled toggled
onVisibilityChangebooleanVisibility toggled
onDisposedMeasurement disposed

MeasurementStateChange Values

type MeasurementStateChange =
  | "mode" | "color" | "units" | "rounding" | "visibility" | "enabled";

Unit Types

type MeasureToUnitMap = {
  length: "mm" | "cm" | "m" | "km";
  area: "mm2" | "cm2" | "m2" | "km2";
  volume: "mm3" | "cm3" | "m3" | "km3";
  angle: "deg" | "rad";
};

Default units: length = "m", area = "m2", volume = "m3", angle = "deg".

Snapping System

Snapping is provided by the GraphicVertexPicker inside the base class. Configure snapping via these properties on any measurement instance:

PropertyTypeDescription
snappingsSnapping class arrayWhich snap types to use: LINE, POINT, FACE
snapDistancenumberMaximum distance for snapping (world units)
pickerSizenumberVisual size of the snap marker (pixels, default 6)
pickerModeGraphicVertexPickerModeDEFAULT (with snapping) or SYNCHRONOUS

Snapping Classes

ClassVisual IndicatorSnap Behavior
LINEGray border, squareSnaps to nearest edge
POINTRed border, squareSnaps to nearest vertex
FACEPurple border, circleSnaps to face surface

ALWAYS configure snappings before enabling measurements. The default snapping array includes LINE, POINT, and FACE.

Measurement Lifecycle

All measurement types follow the same creation lifecycle via the Createable interface:

1. Set enabled = true        → activates vertex picker and pointer events
2. User clicks → create()    → places first point / adds point
3. User clicks → create()    → places additional points (area/volume/angle)
4. endCreation()             → finalizes measurement, adds to list
5. cancelCreation()          → discards in-progress measurement
6. delete()                  → removes measurement under cursor via raycasting
7. Set enabled = false       → deactivates interaction
  • create() is called on each click. For LengthMeasurement it takes two

clicks (start + end). For AreaMeasurement it takes 3+ clicks. For AngleMeasurement it takes exactly 3 clicks. For VolumeMeasurement, points define the volume boundary.

  • endCreation() finalizes the current measurement. For AreaMeasurement,

a minimum of 3 points is required.

  • cancelCreation() discards any in-progress measurement without saving.
  • delete() uses raycasting against measurement bounding boxes to find

and remove the measurement under the cursor.

LengthMeasurement

Measures distance between two points. Supports free placement and edge snapping.

import * as OBCF from "@thatopen/components-front";

const lengths = components.get(OBCF.LengthMeasurement);
lengths.world = world;
lengths.enabled = true;
lengths.mode = "free"; // or "edge"

UUID: "2f9bcacf-18a9-4be6-a293-e898eae64ea1"

Modes

ModeBehavior
"free"Click any two points to measure distance between them
"edge"Snap to geometry edges; measures edge length

Workflow

1. Set enabled = true and mode 2. User clicks first point → create() initializes preview line 3. Preview line follows cursor with snapping 4. User clicks second point → create()endCreation() finalizes 5. DimensionLine with label appears showing the distance

AreaMeasurement

Measures area defined by a polygon of 3+ points.

const areas = components.get(OBCF.AreaMeasurement);
areas.world = world;
areas.enabled = true;
areas.mode = "free"; // or "square" or "face"

UUID: "09b78c1f-0ff1-4630-a818-ceda3d878c75"

Modes

ModeBehavior
"free"Click 3+ points to define a polygon area
"square"Click 2 points to define a rectangular area
"face"Click a face to measure its area directly

Extra Properties

PropertyTypeDefaultDescription
pickTolerancenumber0.1Precision for point selection
tolerancenumber0.005Margin for point inclusion in area

Workflow

1. Set enabled = true and mode 2. User clicks points → create() adds each point 3. Preview fill updates showing the polygon 4. Call endCreation() when polygon is complete (min 3 points) 5. MeasureFill with perimeter DimensionLines and label appears

VolumeMeasurement

Measures volume defined by a 3D boundary.

const volumes = components.get(OBCF.VolumeMeasurement);
volumes.world = world;
volumes.enabled = true;
volumes.mode = "free";

UUID: "01f885ab-ec4e-4e6c-a853-9dfc0d6766ed"

Modes

ModeBehavior
"free"Define volume boundary by selecting geometry faces

Extra Events

EventPayloadTrigger
onPreviewInitializedMeasureVolumePreview volume object created

Workflow

1. Set enabled = true 2. initPreview() creates a MeasureVolume preview (fires onPreviewInitialized) 3. User clicks faces → create() adds selected items to preview 4. endCreation() clones preview volume into list 5. cancelCreation() disposes preview without saving

AngleMeasurement

Measures the angle between three points (vertex at second point).

const angles = components.get(OBCF.AngleMeasurement);
angles.world = world;
angles.enabled = true;
angles.mode = "free";

UUID: "2c88a142-2378-422e-b26a-bb2710841813"

Modes

ModeBehavior
"free"Click three points to measure the angle at the middle point

Constants

ConstantValuePurpose
ARC_SEGMENTS32Number of segments in the arc visualization
ARC_RADIUS_FACTOR0.3Arc radius relative to shortest arm
LABEL_OFFSET_FACTOR1.4Label distance from arc center

Workflow

1. Set enabled = true 2. User clicks first point → create() (click 1) 3. User clicks second point (vertex) → create() (click 2) 4. User clicks third point → create() (click 3) → endCreation() 5. Arc visualization with angle label appears

Setup Pattern (All Types)

ALWAYS follow this pattern when setting up any measurement type:

import * as OBC from "@thatopen/components";
import * as OBCF from "@thatopen/components-front";

// 1. Get the measurement component
const lengths = components.get(OBCF.LengthMeasurement);

// 2. Assign world (REQUIRED before enabling)
lengths.world = world;

// 3. Configure snapping (optional — defaults include LINE, POINT, FACE)
lengths.snapDistance = 0.5;
lengths.pickerSize = 8;

// 4. Configure units and rounding (optional)
lengths.units = "m";
lengths.rounding = 2;

// 5. Configure color (optional)
lengths.color = new THREE.Color(0xff0000);

// 6. Set mode
lengths.mode = "free";

// 7. Enable (ALWAYS last — this activates pointer events)
lengths.enabled = true;

NEVER enable a measurement before assigning world. The vertex picker requires a valid world reference to perform raycasting.

Toggling Between Measurement Types

ALWAYS disable the current measurement before enabling another:

// Switch from length to area
lengths.enabled = false;
areas.enabled = true;

NEVER have multiple measurement types enabled simultaneously. They share pointer events and will conflict.

Deleting Measurements

// Delete measurement under cursor (interactive)
lengths.delete();

// Delete all measurements of a type
lengths.list.clear(); // Clears all length measurements

Disposal

ALWAYS dispose measurement components when no longer needed:

// Dispose a specific measurement type
lengths.dispose();

// Or let components.dispose() handle all cleanup
components.dispose();

dispose() clears the vertex picker, all DataSets (list, lines, fills, labels, volumes), and disposes all materials. NEVER use a measurement instance after calling dispose().

Clipping Plane Integration

Measurements support clipping plane visibility:

lengths.applyPlanesVisibility(planes);

This updates all visual elements (lines, fills, volumes) to respect the provided clipping planes.

Critical Rules

1. ALWAYS assign world before setting enabled = true. 2. ALWAYS disable one measurement type before enabling another. 3. ALWAYS call dispose() or components.dispose() on cleanup. 4. ALWAYS call endCreation() to finalize a measurement. Without it, the measurement stays in preview state. 5. ALWAYS call cancelCreation() to discard an in-progress measurement cleanly. Do not just disable — this leaks preview elements. 6. NEVER enable multiple measurement types simultaneously. 7. NEVER use measurement instances after dispose(). 8. NEVER forget to set mode before enabling — the default mode may not match the desired interaction. 9. NEVER set Measurement.valueFormatter after measurements are already created — existing labels will not update retroactively. 10. NEVER skip snapping configuration when precision matters — default snap distance may be too large or too small for your model scale.

Reference Files

  • references/methods.md — Measurement base class

API, LengthMeasurement, AreaMeasurement, VolumeMeasurement, AngleMeasurement full method reference

  • references/examples.md — Setup and usage

examples for each measurement type

  • references/anti-patterns.md — Missing

dispose, snapping issues, lifecycle errors

Source Verification

All API signatures verified against:

  • GitHub: ThatOpen/engine_components main branch (packages/front/src/measurement/)
  • npm: @thatopen/components-front@3.3.3
  • Research: docs/research/vooronderzoek-thatopen.md (Section 5)

Related skills

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.