@thatopen/components 3.3.3 → 3.4.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.
package/dist/index.d.ts CHANGED
@@ -33,6 +33,223 @@ declare class AmbientLightConfig {
33
33
  set intensity(value: number);
34
34
  }
35
35
 
36
+ export declare interface AngleAnnotation {
37
+ /** Unique identifier. */
38
+ uuid: string;
39
+ /** Snapped point on the first line — defines the first ray direction from the vertex. */
40
+ pointA: THREE.Vector3;
41
+ /** Computed intersection of the two measured lines. */
42
+ vertex: THREE.Vector3;
43
+ /** Snapped point on the second line — defines the second ray direction from the vertex. */
44
+ pointB: THREE.Vector3;
45
+ /** Radius of the arc at commit time, in drawing local units. */
46
+ arcRadius: number;
47
+ /**
48
+ * When `true`, the arc measures the reflex angle (360° − interior).
49
+ * The arc is drawn going the long way around and the bisector flips 180°.
50
+ */
51
+ flipped?: boolean;
52
+ /** Name of the {@link AngleAnnotationStyle} to use when rendering. */
53
+ style: string;
54
+ }
55
+
56
+ /** Editable fields of {@link AngleAnnotation} — everything except the `uuid`. */
57
+ export declare type AngleAnnotationData = Omit<AngleAnnotation, "uuid">;
58
+
59
+ export declare type AngleAnnotationEvent =
60
+ /**
61
+ * A point was clicked. Carries `drawing` so the machine caches it on the first
62
+ * click — subsequent events reuse that context.
63
+ * `line` is required in `awaitingFirstLine` and `awaitingSecondLine`;
64
+ * free-space clicks are accepted in `positioningArc`.
65
+ */
66
+ {
67
+ type: "CLICK";
68
+ point: THREE.Vector3;
69
+ line?: THREE.Line3;
70
+ drawing?: TechnicalDrawing;
71
+ }
72
+ /** Cursor moved — drawing context already cached from the initial CLICK. */
73
+ | {
74
+ type: "MOUSE_MOVE";
75
+ point: THREE.Vector3;
76
+ line?: THREE.Line3;
77
+ }
78
+ /** Cancel and return to the initial state. */
79
+ | {
80
+ type: "ESCAPE";
81
+ };
82
+
83
+ /** Global drawing system that manages angle dimension annotations across all {@link TechnicalDrawing} instances. */
84
+ export declare class AngleAnnotations extends AnnotationSystem<AngleAnnotationSystem> implements Transitionable<AngleAnnotationState, AngleAnnotationEvent>, Disposable_2 {
85
+ enabled: boolean;
86
+ readonly _item: AngleAnnotation;
87
+ machineState: AngleAnnotationState;
88
+ readonly onMachineStateChanged: Event_2<AngleAnnotationState>;
89
+ private _secondLinePreviewObject;
90
+ constructor(components: Components);
91
+ pickHandle(_drawing: TechnicalDrawing, _ray: THREE.Ray, _threshold?: number): {
92
+ uuid: string;
93
+ handle: "pointA" | "vertex" | "pointB";
94
+ } | null;
95
+ sendMachineEvent(event: AngleAnnotationEvent): void;
96
+ protected _buildGroup(dim: AngleAnnotation, style: AngleAnnotationStyle): THREE.Group;
97
+ protected _updatePreview(): void;
98
+ protected _onDispose(): void;
99
+ private _resetMachine;
100
+ private _clearSecondLinePreview;
101
+ private _updateSecondLinePreview;
102
+ }
103
+
104
+ export declare type AngleAnnotationState =
105
+ /** Waiting for the user to click the first measured line. */
106
+ {
107
+ kind: "awaitingFirstLine";
108
+ }
109
+ /** First line picked. Waiting for the second line. */
110
+ | {
111
+ kind: "awaitingSecondLine";
112
+ line1: THREE.Line3;
113
+ pointA: THREE.Vector3;
114
+ }
115
+ /**
116
+ * Both lines picked, vertex computed. User moves the cursor to set the
117
+ * arc radius, then clicks to commit.
118
+ */
119
+ | {
120
+ kind: "positioningArc";
121
+ pointA: THREE.Vector3;
122
+ vertex: THREE.Vector3;
123
+ pointB: THREE.Vector3;
124
+ cursor: THREE.Vector3 | null;
125
+ flipped: boolean;
126
+ }
127
+ /** Annotation just committed. */
128
+ | {
129
+ kind: "committed";
130
+ dimension: AngleAnnotation;
131
+ };
132
+
133
+ export declare interface AngleAnnotationStyle extends BaseAnnotationStyle {
134
+ /** Tick mark builder at each end of the arc. */
135
+ lineTick: LineTickBuilder;
136
+ /**
137
+ * Optional filled tick mark builder. When provided, a `THREE.Mesh` triangle
138
+ * is rendered at each arc endpoint. Set `tick` to {@link NoTick} when you
139
+ * only want the filled shape.
140
+ */
141
+ meshTick?: MeshTickBuilder;
142
+ /** Tick size in drawing local units. */
143
+ tickSize: number;
144
+ /** Gap between the vertex and the start of each extension line. */
145
+ extensionGap: number;
146
+ /** Distance from the arc to the text label, along the bisector ray. */
147
+ textOffset: number;
148
+ }
149
+
150
+ declare interface AngleAnnotationSystem {
151
+ item: AngleAnnotation;
152
+ data: AngleAnnotationData;
153
+ style: AngleAnnotationStyle;
154
+ handle: "pointA" | "vertex" | "pointB";
155
+ }
156
+
157
+ /** Pure state transition function for the angle dimension tool. */
158
+ export declare function angleDimensionMachine(state: AngleAnnotationState, event: AngleAnnotationEvent): AngleAnnotationState;
159
+
160
+ /** A single annotation entry stored in {@link DrawingAnnotations}, bundling the owning system, the annotation data, and its Three.js group. */
161
+ export declare interface AnnotationEntry {
162
+ /** The system that created and owns this annotation. */
163
+ system: AnnotationSystem<any>;
164
+ /** The persisted annotation data (e.g. {@link LinearAnnotation}). */
165
+ data: unknown;
166
+ /** The Three.js group added to {@link TechnicalDrawing.three}. */
167
+ three: THREE.Group;
168
+ }
169
+
170
+ /**
171
+ * Abstract base for all annotation sub-systems operating on a {@link TechnicalDrawing}.
172
+ * @typeParam TSystem - A {@link DrawingSystemDescriptor} that declares the item, data, style, and handle types for this specific system.
173
+ */
174
+ declare abstract class AnnotationSystem<TSystem extends DrawingSystemDescriptor> {
175
+ protected readonly _components: Components;
176
+ /* Excluded from this release type: _item */
177
+ constructor(_components: Components);
178
+ abstract enabled: boolean;
179
+ readonly styles: FRAGS.DataMap<string, TSystem["style"]>;
180
+ activeStyle: string;
181
+ readonly onCommit: Event_2<{
182
+ drawing: TechnicalDrawing;
183
+ item: TSystem["item"];
184
+ group: THREE.Group;
185
+ }[]>;
186
+ readonly onUpdate: Event_2<{
187
+ item: TSystem["item"];
188
+ group: THREE.Group;
189
+ }>;
190
+ readonly onDelete: Event_2<string[]>;
191
+ readonly onDisposed: Event_2<void>;
192
+ protected readonly _knownDrawings: Set<TechnicalDrawing>;
193
+ protected readonly _previewMaterial: THREE.LineBasicMaterial;
194
+ protected _previewObject: THREE.LineSegments | null;
195
+ protected _previewDrawing: TechnicalDrawing | null;
196
+ protected readonly _materialCache: FRAGS.DataMap<string, THREE.LineBasicMaterial>;
197
+ protected readonly _meshMaterialCache: FRAGS.DataMap<string, THREE.MeshBasicMaterial>;
198
+ /**
199
+ * When `true` (default), {@link _disposeGroup} and {@link _redraw} will call
200
+ * `.dispose()` on each child's `BufferGeometry`. Set to `false` in systems
201
+ * where geometry is shared across multiple groups (e.g. {@link BlockAnnotations}).
202
+ */
203
+ protected _ownsChildGeometry: boolean;
204
+ /**
205
+ * Build and return a `THREE.Group` containing all geometry for `item`.
206
+ * The group's own `userData` is set by the base class after this call.
207
+ * Set `userData` on *children* (e.g. `ls.userData.isDimension = true`) here.
208
+ */
209
+ protected abstract _buildGroup(item: TSystem["item"], style: TSystem["style"]): THREE.Group;
210
+ /**
211
+ * Return the closest pickable handle on `drawing` for the given world-space
212
+ * `ray`, or `null` if nothing is within `threshold` units.
213
+ */
214
+ abstract pickHandle(drawing: TechnicalDrawing, ray: THREE.Ray, threshold?: number): {
215
+ uuid: string;
216
+ handle: TSystem["handle"];
217
+ } | null;
218
+ /** Called synchronously after a group is first persisted or redrawn. */
219
+ protected _onAfterPersist(_item: TSystem["item"], _group: THREE.Group): void;
220
+ /** Called at the start of {@link dispose} before materials and events are torn down. */
221
+ protected _onDispose(): void;
222
+ /** Override to rebuild preview geometry after a state transition. */
223
+ protected _updatePreview(): void;
224
+ get(drawings: TechnicalDrawing[]): FRAGS.DataMap<string, {
225
+ drawingUuid: string;
226
+ item: TSystem["item"];
227
+ }>;
228
+ add(drawing: TechnicalDrawing, data: TSystem["data"]): TSystem["item"];
229
+ update(drawing: TechnicalDrawing, uuids: string[], changes: Partial<TSystem["data"]>): void;
230
+ pick(ray: THREE.Ray, threshold?: number): string | null;
231
+ delete(drawing: TechnicalDrawing, uuids: string[]): void;
232
+ clear(drawings?: TechnicalDrawing[]): void;
233
+ dispose(): void;
234
+ protected _trackDrawing(drawing: TechnicalDrawing): void;
235
+ protected _resolveStyle(styleName: string): TSystem["style"];
236
+ protected _getMaterial(styleName: string): THREE.LineBasicMaterial;
237
+ protected _getMeshMaterial(styleName: string): THREE.MeshBasicMaterial;
238
+ protected _disposeGroup(group: THREE.Group): void;
239
+ protected _clearPreview(): void;
240
+ protected _persist(drawing: TechnicalDrawing, item: TSystem["item"]): {
241
+ drawing: TechnicalDrawing;
242
+ item: TSystem["item"];
243
+ group: THREE.Group;
244
+ };
245
+ protected _redraw(item: TSystem["item"], group: THREE.Group): void;
246
+ }
247
+ export { AnnotationSystem }
248
+ export { AnnotationSystem as DrawingSystem }
249
+
250
+ /** Closed arrowhead tick — two wing lines plus a base line connecting them. */
251
+ export declare const ArrowTick: LineTickBuilder;
252
+
36
253
  /**
37
254
  * Simple event handler by [Jason Kleban](https://gist.github.com/JasonKleban/50cee44960c225ac1993c922563aa540). Keep in mind that if you want to remove it later, you might want to declare the callback as an object. If you want to maintain the reference to `this`, you will need to declare the callback as an arrow function.
38
255
  */
@@ -66,6 +283,17 @@ export declare class AsyncEvent<T> {
66
283
  private handlers;
67
284
  }
68
285
 
286
+ /** Minimal interface for a translate-only gizmo that can be configured and attached to one of the helper's control handles. */
287
+ export declare interface AxisGizmoLike {
288
+ attach(object: THREE.Object3D): void;
289
+ setSpace(space: "world" | "local"): void;
290
+ getHelper(): THREE.Object3D;
291
+ showX: boolean;
292
+ showY: boolean;
293
+ showZ: boolean;
294
+ addEventListener(type: string, listener: () => void): void;
295
+ }
296
+
69
297
  /**
70
298
  * Base class of the library. Useful for finding out the interfaces something implements.
71
299
  */
@@ -86,6 +314,21 @@ export declare abstract class Base {
86
314
  isSerializable: () => this is Serializable<any, Record<string, any>>;
87
315
  }
88
316
 
317
+ /** Minimum style contract shared by every annotation system. */
318
+ export declare interface BaseAnnotationStyle {
319
+ /** Line and text color as a hex number (e.g. `0xff0000`). */
320
+ color: number;
321
+ /** Distance from the annotation geometry to the text label in drawing local units. */
322
+ textOffset: number;
323
+ /** Font size of the text label in drawing local units. */
324
+ fontSize: number;
325
+ /**
326
+ * Unit used to format measured values in text labels.
327
+ * Defaults to {@link Units.m} (metres) when not set.
328
+ */
329
+ unit?: DimensionUnit;
330
+ }
331
+
89
332
  /**
90
333
  * Abstract class representing a camera in a 3D world. All cameras should use this class as a base.
91
334
  */
@@ -567,6 +810,100 @@ export declare interface BCFViewpoint {
567
810
  bitmaps?: ViewpointBitmap[];
568
811
  }
569
812
 
813
+ /** Global drawing system that manages block insertions across all {@link TechnicalDrawing} instances. */
814
+ export declare class BlockAnnotations extends AnnotationSystem<BlockAnnotationsSystem> implements Disposable_2 {
815
+ enabled: boolean;
816
+ readonly _item: BlockInsertion;
817
+ protected _ownsChildGeometry: boolean;
818
+ /**
819
+ * Named block definitions in block-local XZ space.
820
+ * Register via {@link define}. Geometry is shared across all drawings and insertions.
821
+ */
822
+ readonly definitions: FRAGS.DataMap<string, BlockDefinition>;
823
+ /**
824
+ * A **block** is a named, reusable geometry definition (e.g. a furniture symbol
825
+ * or a detail imported from a DXF). Multiple insertions of the same block share
826
+ * the same `THREE.BufferGeometry`, so only the transform (position, rotation,
827
+ * scale) differs per instance.
828
+ *
829
+ * Register via {@link TechnicalDrawings.use}:
830
+ * ```ts
831
+ * const blocks = techDrawings.use(BlockAnnotations);
832
+ * ```
833
+ *
834
+ * Typical workflow:
835
+ * ```ts
836
+ * // 1. Project external geometry to drawing space
837
+ * const projected = TechnicalDrawing.toDrawingSpace(ifcLines, drawing);
838
+ *
839
+ * // 2. Register the block definition (global — do this once)
840
+ * blocks.define("CHAIR", { lines: projected.geometry });
841
+ *
842
+ * // 3. Insert on any drawing
843
+ * blocks.add(drawing, { blockName: "CHAIR", position, rotation: 0, scale: 1, style: "default" });
844
+ * ```
845
+ */
846
+ constructor(components: Components);
847
+ pickHandle(_drawing: TechnicalDrawing, _ray: THREE.Ray, _threshold?: number): {
848
+ uuid: string;
849
+ handle: "position" | "rotation" | "scale";
850
+ } | null;
851
+ /**
852
+ * Overrides the base `pick` to use the correct `LineSegments.raycast` (pair-based)
853
+ * rather than `THREE.Line.prototype.raycast` (continuous-line).
854
+ */
855
+ pick(ray: THREE.Ray, threshold?: number): string | null;
856
+ /**
857
+ * Registers a block definition by name (global — not tied to any drawing).
858
+ * All geometry must be in block-local XZ space (Y = 0).
859
+ * Use {@link TechnicalDrawing.toDrawingSpace} to project external geometry first.
860
+ *
861
+ * Replaces any existing definition with the same name without disposing the old geometry.
862
+ */
863
+ define(name: string, definition: BlockDefinition): void;
864
+ protected _buildGroup(ins: BlockInsertion, _style: BlockStyle): THREE.Group;
865
+ protected _onAfterPersist(ins: BlockInsertion, group: THREE.Group): void;
866
+ protected _onDispose(): void;
867
+ }
868
+
869
+ declare interface BlockAnnotationsSystem {
870
+ item: BlockInsertion;
871
+ data: BlockInsertionData;
872
+ style: BlockStyle;
873
+ handle: "position" | "rotation" | "scale";
874
+ }
875
+
876
+ /** The geometry content of a named block. At least one of `lines` or `mesh` must be provided. */
877
+ export declare interface BlockDefinition {
878
+ /** Line geometry for `LineSegments`. */
879
+ lines?: THREE.BufferGeometry;
880
+ /** Triangle geometry for a filled `THREE.Mesh`. */
881
+ mesh?: THREE.BufferGeometry;
882
+ }
883
+
884
+ /** A single placed instance of a named block definition. */
885
+ export declare interface BlockInsertion {
886
+ /** Unique identifier for this insertion. */
887
+ uuid: string;
888
+ /** Name of the block definition to draw. Must be registered via {@link BlockAnnotations.define}. */
889
+ blockName: string;
890
+ /** Insertion point in drawing local space (Y is ignored — always 0). */
891
+ position: THREE.Vector3;
892
+ /** Rotation around the Y axis in radians. */
893
+ rotation: number;
894
+ /** Uniform scale applied to the block geometry. */
895
+ scale: number;
896
+ /** Style name — references a {@link BlockStyle} registered on the system. */
897
+ style: string;
898
+ }
899
+
900
+ /** Editable fields of {@link BlockInsertion} — everything except the `uuid`. */
901
+ export declare type BlockInsertionData = Omit<BlockInsertion, "uuid">;
902
+
903
+ /** Style for a {@link BlockAnnotations} system. */
904
+ export declare interface BlockStyle extends BaseAnnotationStyle {
905
+ }
906
+
570
907
  export declare interface BooleanSettingsControl {
571
908
  type: "Boolean";
572
909
  value: boolean;
@@ -634,6 +971,188 @@ export declare class BoundingBoxer extends Component implements Disposable_2 {
634
971
  }>;
635
972
  }
636
973
 
974
+ /**
975
+ * Builds the flat vertex positions for a single committed angle dimension.
976
+ */
977
+ export declare function buildAnglePositions(dim: AngleAnnotation, style: AngleAnnotationStyle): number[];
978
+
979
+ /** Builds vertex positions for the live preview during `positioningArc`. */
980
+ export declare function buildAnglePreviewPositions(pointA: THREE.Vector3, vertex: THREE.Vector3, pointB: THREE.Vector3, cursor: THREE.Vector3 | null, style: AngleAnnotationStyle, flipped?: boolean): number[];
981
+
982
+ /** Builds the flat vertex positions for a committed callout annotation. */
983
+ export declare function buildCalloutPositions(ann: CalloutAnnotation, style: CalloutAnnotationStyle): number[];
984
+
985
+ /** Builds vertex positions for the live preview during interactive placement. */
986
+ export declare function buildCalloutPreviewPositions(kind: "awaitingRadius" | "awaitingElbow" | "awaitingExtension", center: THREE.Vector3, halfW: number, halfH: number, elbow: THREE.Vector3 | null, cursor: THREE.Vector3 | null, style: CalloutAnnotationStyle): number[];
987
+
988
+ /** Builds the flat vertex positions (x,y,z triplets) for a single committed linear dimension. */
989
+ export declare function buildDimensionPositions(dim: LinearAnnotation, style: LinearAnnotationStyle): number[];
990
+
991
+ /** Builds an array of {@link LinearAnnotation}s from consecutive point pairs, all sharing the same perpendicular offset. */
992
+ export declare function buildDimensions(points: THREE.Vector3[], offset: number): LinearAnnotation[];
993
+
994
+ /**
995
+ * Builds the flat vertex positions for a committed leader annotation.
996
+ */
997
+ export declare function buildLeaderPositions(ann: LeaderAnnotation, style: LeaderAnnotationStyle): number[];
998
+
999
+ /**
1000
+ * Builds vertex positions for the live preview.
1001
+ */
1002
+ export declare function buildLeaderPreviewPositions(kind: "placingElbow" | "placingExtension", arrowTip: THREE.Vector3, elbow: THREE.Vector3 | null, cursor: THREE.Vector3 | null, style: LeaderAnnotationStyle): number[];
1003
+
1004
+ /** Builds the flat vertex positions for a live dimension preview. */
1005
+ export declare function buildPreviewPositions(kind: "placingPoints" | "positioningOffset", points: THREE.Vector3[], cursor: THREE.Vector3 | null, style: LinearAnnotationStyle): number[];
1006
+
1007
+ /**
1008
+ * Builds the `LineSegments` position array for a committed slope annotation.
1009
+ * @returns A flat `Float32Array` of XYZ triplets (vertex pairs for `LineSegments`).
1010
+ */
1011
+ export declare function buildSlopePositions(ann: SlopeAnnotation, style: SlopeAnnotationStyle): Float32Array;
1012
+
1013
+ /** The committed data for a single callout annotation. */
1014
+ export declare interface CalloutAnnotation {
1015
+ /** Unique identifier. */
1016
+ uuid: string;
1017
+ /** Centre of the enclosure shape. */
1018
+ center: THREE.Vector3;
1019
+ /** Half-width of the enclosure along the X axis. */
1020
+ halfW: number;
1021
+ /** Half-height of the enclosure along the Z axis. */
1022
+ halfH: number;
1023
+ /** Elbow — the bend between the extension line and its horizontal run. */
1024
+ elbow: THREE.Vector3;
1025
+ /** End of the horizontal extension line — anchor for the text label. */
1026
+ extensionEnd: THREE.Vector3;
1027
+ /** The annotation text. */
1028
+ text: string;
1029
+ /** Name of the {@link CalloutAnnotationStyle} to use when rendering. */
1030
+ style: string;
1031
+ }
1032
+
1033
+ /** Editable fields of {@link CalloutAnnotation} — everything except `uuid`. */
1034
+ export declare type CalloutAnnotationData = Omit<CalloutAnnotation, "uuid">;
1035
+
1036
+ export declare type CalloutAnnotationEvent =
1037
+ /** A point in drawing local space was clicked. */
1038
+ {
1039
+ type: "CLICK";
1040
+ point: THREE.Vector3;
1041
+ drawing?: TechnicalDrawing;
1042
+ }
1043
+ /** The cursor moved to a new position in drawing local space. */
1044
+ | {
1045
+ type: "MOUSE_MOVE";
1046
+ point: THREE.Vector3;
1047
+ drawing?: TechnicalDrawing;
1048
+ }
1049
+ /**
1050
+ * Consumer supplies the annotation text after the machine enters
1051
+ * `enteringText`. Ignored in all other states.
1052
+ */
1053
+ | {
1054
+ type: "SUBMIT_TEXT";
1055
+ text: string;
1056
+ }
1057
+ /** Cancel the current operation and return to the initial state. */
1058
+ | {
1059
+ type: "ESCAPE";
1060
+ };
1061
+
1062
+ /** Pure state transition function for the callout annotation tool. */
1063
+ export declare function calloutAnnotationMachine(state: CalloutAnnotationState, event: CalloutAnnotationEvent): CalloutAnnotationState;
1064
+
1065
+ /** Global drawing system that manages callout annotations across all {@link TechnicalDrawing} instances. */
1066
+ export declare class CalloutAnnotations extends AnnotationSystem<CalloutAnnotationSystem> implements Transitionable<CalloutAnnotationState, CalloutAnnotationEvent>, Disposable_2 {
1067
+ enabled: boolean;
1068
+ readonly _item: CalloutAnnotation;
1069
+ machineState: CalloutAnnotationState;
1070
+ readonly onMachineStateChanged: Event_2<CalloutAnnotationState>;
1071
+ constructor(components: Components);
1072
+ pickHandle(_drawing: TechnicalDrawing, _ray: THREE.Ray, _threshold?: number): {
1073
+ uuid: string;
1074
+ handle: string;
1075
+ } | null;
1076
+ sendMachineEvent(event: CalloutAnnotationEvent): void;
1077
+ protected _buildGroup(ann: CalloutAnnotation, style: CalloutAnnotationStyle): THREE.Group;
1078
+ protected _updatePreview(): void;
1079
+ private _resetMachine;
1080
+ }
1081
+
1082
+ export declare type CalloutAnnotationState =
1083
+ /** Waiting for the user to click the enclosure centre. */
1084
+ {
1085
+ kind: "awaitingCenter";
1086
+ }
1087
+ /**
1088
+ * Centre placed. User moves the cursor to the SE corner of the enclosure
1089
+ * to define its half-width (X) and half-height (Z) simultaneously.
1090
+ */
1091
+ | {
1092
+ kind: "awaitingRadius";
1093
+ center: THREE.Vector3;
1094
+ cursor: THREE.Vector3 | null;
1095
+ }
1096
+ /** Size set. User clicks to place the line elbow. */
1097
+ | {
1098
+ kind: "awaitingElbow";
1099
+ center: THREE.Vector3;
1100
+ halfW: number;
1101
+ halfH: number;
1102
+ cursor: THREE.Vector3 | null;
1103
+ }
1104
+ /** Elbow set. User clicks the extension endpoint. */
1105
+ | {
1106
+ kind: "awaitingExtension";
1107
+ center: THREE.Vector3;
1108
+ halfW: number;
1109
+ halfH: number;
1110
+ elbow: THREE.Vector3;
1111
+ cursor: THREE.Vector3 | null;
1112
+ }
1113
+ /**
1114
+ * All geometry is set. Paused waiting for the consumer to supply the text
1115
+ * via a `SUBMIT_TEXT` event.
1116
+ */
1117
+ | {
1118
+ kind: "enteringText";
1119
+ center: THREE.Vector3;
1120
+ halfW: number;
1121
+ halfH: number;
1122
+ elbow: THREE.Vector3;
1123
+ extensionEnd: THREE.Vector3;
1124
+ }
1125
+ /** Annotation just committed. */
1126
+ | {
1127
+ kind: "committed";
1128
+ annotation: CalloutAnnotation;
1129
+ };
1130
+
1131
+ /** Visual appearance of a callout annotation. */
1132
+ export declare interface CalloutAnnotationStyle extends BaseAnnotationStyle {
1133
+ /** The enclosure shape builder (cloud, rectangle, circle). */
1134
+ enclosure: EnclosureBuilder;
1135
+ /** Size of the optional tick at the extension end in drawing local units. */
1136
+ tickSize: number;
1137
+ /**
1138
+ * Line-segment tick at the extension end — included in the same `LineSegments`
1139
+ * as the extension line. Omit to suppress.
1140
+ */
1141
+ lineTick?: LineTickBuilder;
1142
+ /**
1143
+ * Filled (mesh) tick at the extension end — rendered as a separate `THREE.Mesh`.
1144
+ * Can be combined with `tick`.
1145
+ */
1146
+ meshTick?: MeshTickBuilder;
1147
+ }
1148
+
1149
+ declare interface CalloutAnnotationSystem {
1150
+ item: CalloutAnnotation;
1151
+ data: CalloutAnnotationData;
1152
+ style: CalloutAnnotationStyle;
1153
+ handle: string;
1154
+ }
1155
+
637
1156
  /**
638
1157
  * Whether a camera uses the Camera Controls library.
639
1158
  */
@@ -650,6 +1169,9 @@ export declare interface CameraControllable {
650
1169
  */
651
1170
  export declare type CameraProjection = "Perspective" | "Orthographic";
652
1171
 
1172
+ /** Elliptical enclosure — an ellipse approximated with line segments centred on `center`. */
1173
+ export declare const CircleEnclosure: EnclosureBuilder;
1174
+
653
1175
  /**
654
1176
  * Represents the data structure for a classification group.
655
1177
  */
@@ -1001,6 +1523,9 @@ declare type ClipperConfigType = {
1001
1523
  size: NumberSettingControl;
1002
1524
  };
1003
1525
 
1526
+ /** Revision-cloud enclosure — a bumpy rectangle centred on `center`. */
1527
+ export declare const CloudEnclosure: EnclosureBuilder;
1528
+
1004
1529
  export declare interface ColorSettingsControl {
1005
1530
  type: "Color";
1006
1531
  value: THREE.Color;
@@ -1142,6 +1667,24 @@ export declare class Components implements Disposable_2 {
1142
1667
  private static setupBVH;
1143
1668
  }
1144
1669
 
1670
+ /**
1671
+ * Computes a local-to-world transformation matrix that maps a technical drawing's local coordinate system onto a target plane in 3D world space.
1672
+ * @throws If either set of points is collinear (cannot define a plane).
1673
+ * @throws If either set contains a degenerate first pair (zero distance).
1674
+ * @param drawingPoints - Three non-collinear points in drawing local space.
1675
+ * @param worldPoints - Three corresponding non-collinear points in world space.
1676
+ */
1677
+ export declare function computeAlignmentMatrix(drawingPoints: THREE.Vector3[], worldPoints: THREE.Vector3[]): THREE.Matrix4;
1678
+
1679
+ /** Returns the angle in radians between the two rays defined by the dimension. */
1680
+ export declare function computeAngle(dim: AngleAnnotation): number;
1681
+
1682
+ /** Returns the angle (in radians, in the XZ plane) of the bisector ray between the two measured rays. */
1683
+ export declare function computeBisectorAngle(dim: AngleAnnotation): number;
1684
+
1685
+ /** Computes the signed offset from a cursor position to the measurement axis defined by the first and last points. */
1686
+ export declare function computeOffset(points: THREE.Vector3[], cursor: THREE.Vector3): number;
1687
+
1145
1688
  /**
1146
1689
  * A tool to manage all the configuration from the app centrally. 📘 [API](https://docs.thatopen.com/api/@thatopen/components/classes/ConfigManager).
1147
1690
  */
@@ -1421,6 +1964,17 @@ export declare class DataSet<T> extends Set<T> {
1421
1964
  dispose(): void;
1422
1965
  }
1423
1966
 
1967
+ /** Diagonal slash tick (architectural style). */
1968
+ export declare const DiagonalTick: LineTickBuilder;
1969
+
1970
+ /** Defines how a measured value (in drawing-space metres) is converted to a display string. */
1971
+ export declare interface DimensionUnit {
1972
+ /** Multiplier applied to the raw metre value before display. */
1973
+ factor: number;
1974
+ /** Label appended to the formatted number (e.g. `"cm"`, `"mm"`, `"ft"`). */
1975
+ suffix: string;
1976
+ }
1977
+
1424
1978
  declare class DirectionalLightConfig {
1425
1979
  private _list;
1426
1980
  private _scene;
@@ -1558,6 +2112,681 @@ export declare interface DocumentReference {
1558
2112
  description?: string;
1559
2113
  }
1560
2114
 
2115
+ /** Dot tick — a small circle drawn with line segments at the endpoint. */
2116
+ export declare const DotTick: LineTickBuilder;
2117
+
2118
+ /** Flat annotation store for a {@link TechnicalDrawing}, keyed by UUID. */
2119
+ export declare class DrawingAnnotations extends FRAGS.DataMap<string, AnnotationEntry> {
2120
+ /**
2121
+ * Each entry bundles the owning system, the data, and the Three.js group —
2122
+ * so a single `drawing.annotations.get(uuid)` gives full access to all three.
2123
+ *
2124
+ * Systems write here when they create or update annotations; consumers read
2125
+ * from here or subscribe to system-level events (`onCommit`, `onDelete`).
2126
+ *
2127
+ * ```ts
2128
+ * // Get everything for a known UUID
2129
+ * const { system, data, three } = drawing.annotations.get(uuid)!;
2130
+ *
2131
+ * // Iterate all annotations owned by a specific system
2132
+ * for (const [uuid, dim] of drawing.annotations.getBySystem(dims)) { ... }
2133
+ * ```
2134
+ */
2135
+ constructor();
2136
+ /**
2137
+ * Returns a snapshot map of `uuid → item` for all annotations owned by
2138
+ * `system` on this drawing. Filters the flat store by system identity.
2139
+ *
2140
+ * The returned `Map` is a snapshot — it does not update reactively.
2141
+ * Subscribe to system events (`onCommit`, `onDelete`, `onUpdate`) for
2142
+ * reactive updates.
2143
+ */
2144
+ /**
2145
+ * Returns a snapshot map of `uuid → item` for all annotations owned by
2146
+ * `system` on this drawing. TypeScript infers the item type from the
2147
+ * system's `_item` declaration marker, avoiding DataMap event variance issues.
2148
+ */
2149
+ getBySystem<T>(system: {
2150
+ readonly _item: T;
2151
+ }): Map<string, T>;
2152
+ }
2153
+
2154
+ /** Result of a successful raycast against a {@link TechnicalDrawing}. */
2155
+ export declare interface DrawingIntersection {
2156
+ /** Hit position in drawing local space (X right, Z down-screen, Y = 0). */
2157
+ point: THREE.Vector3;
2158
+ /** The Three.js object that was intersected (e.g. a LineSegments). */
2159
+ object: THREE.Object3D;
2160
+ /**
2161
+ * The viewport whose camera was used for the raycast, or `null` when the
2162
+ * pick originated from a world-space camera (e.g. the 3D viewer).
2163
+ */
2164
+ viewport: DrawingViewport | null;
2165
+ /**
2166
+ * The specific line segment that was hit, expressed as a `THREE.Line3`
2167
+ * in drawing local space. `null` when the hit object is not a LineSegments.
2168
+ */
2169
+ line: THREE.Line3 | null;
2170
+ }
2171
+
2172
+ /** A named organizational layer on a {@link TechnicalDrawing}. */
2173
+ export declare interface DrawingLayer {
2174
+ /** Unique name identifying this layer. */
2175
+ name: string;
2176
+ /** Whether objects on this layer are visible. Defaults to `true`. */
2177
+ visible: boolean;
2178
+ /**
2179
+ * Material applied to all projection `LineSegments` on this layer.
2180
+ * All objects on the same layer share this instance, so mutating it
2181
+ * (e.g. via {@link DrawingLayers.setColor}) is reflected immediately
2182
+ * without any traversal. Use {@link DrawingLayers.setMaterial} to
2183
+ * swap the instance entirely.
2184
+ *
2185
+ * Annotation systems always use their own style material — this field
2186
+ * does not affect them.
2187
+ */
2188
+ material: THREE.LineBasicMaterial;
2189
+ }
2190
+
2191
+ /** Manages the named layers of a {@link TechnicalDrawing}. */
2192
+ export declare class DrawingLayers extends FRAGS.DataMap<string, DrawingLayer> {
2193
+ private readonly _container;
2194
+ /**
2195
+ * Accessible via `drawing.layers`. Each layer owns a `THREE.LineBasicMaterial`
2196
+ * that is shared across all projection `LineSegments` assigned to it —
2197
+ * mutating the material (e.g. via {@link setColor}) is reflected on every line
2198
+ * immediately without any scene traversal. Annotation systems always use their
2199
+ * own style material and are not affected by layer materials.
2200
+ *
2201
+ * Extends `DataMap<string, DrawingLayer>` so consumers get reactive events
2202
+ * (`onItemSet`, `onItemDeleted`, …) directly on `drawing.layers`.
2203
+ *
2204
+ * Layer `"0"` always exists and cannot be removed.
2205
+ *
2206
+ * ```ts
2207
+ * drawing.layers.create("walls", { material: new THREE.LineBasicMaterial({ color: 0x333333 }) });
2208
+ * drawing.layers.setColor("walls", 0x888888);
2209
+ * drawing.layers.setVisibility("walls", false);
2210
+ * ```
2211
+ */
2212
+ constructor(container: THREE.Group);
2213
+ /**
2214
+ * Creates a new layer. If a layer with the same name already exists, returns
2215
+ * the existing one without modifying it.
2216
+ *
2217
+ * @param name - Unique layer name.
2218
+ * @param options - Optional material and visibility. If no material is given,
2219
+ * a default black `LineBasicMaterial` is created. Visibility defaults to `true`.
2220
+ * @returns The (possibly pre-existing) layer object.
2221
+ */
2222
+ create(name: string, options?: {
2223
+ material?: THREE.LineBasicMaterial;
2224
+ visible?: boolean;
2225
+ }): DrawingLayer;
2226
+ /**
2227
+ * Updates the color of a layer's material and fires reactive events.
2228
+ *
2229
+ * Because all `LineSegments` on the same layer share the same material
2230
+ * instance, the change is reflected immediately on all of them — no scene
2231
+ * traversal is required.
2232
+ *
2233
+ * Does nothing if the layer does not exist.
2234
+ *
2235
+ * @param name - Layer name.
2236
+ * @param color - Hex color (e.g. `0xff0000`).
2237
+ */
2238
+ setColor(name: string, color: number): void;
2239
+ /**
2240
+ * Replaces the material of a layer and updates all `LineSegments` currently
2241
+ * assigned to it. The previous material is disposed.
2242
+ *
2243
+ * Does nothing if the layer does not exist.
2244
+ *
2245
+ * @param name - Layer name.
2246
+ * @param material - New material to assign.
2247
+ */
2248
+ setMaterial(name: string, material: THREE.LineBasicMaterial): void;
2249
+ /**
2250
+ * Shows or hides all objects assigned to the given layer.
2251
+ *
2252
+ * Does nothing if the layer does not exist.
2253
+ *
2254
+ * @param name - Layer name.
2255
+ * @param visible - `true` to show, `false` to hide.
2256
+ */
2257
+ setVisibility(name: string, visible: boolean): void;
2258
+ /**
2259
+ * Assigns an object to a named layer, applies the layer's material (if the
2260
+ * object is a `LineSegments`), and immediately reflects the layer's current
2261
+ * visibility state.
2262
+ *
2263
+ * Use this instead of setting `object.userData.layer` directly so that
2264
+ * the material and visibility are always in sync at insertion time.
2265
+ *
2266
+ * Does nothing if the layer does not exist.
2267
+ *
2268
+ * @param object - The Three.js object to assign.
2269
+ * @param name - Layer name.
2270
+ */
2271
+ assign(object: THREE.Object3D, name: string): void;
2272
+ /* Excluded from this release type: resolveColor */
2273
+ }
2274
+
2275
+ /**
2276
+ * Minimal interface consumed by {@link TechnicalDrawingHelper}.
2277
+ * Satisfied by {@link TechnicalDrawing} without a direct import.
2278
+ */
2279
+ declare interface DrawingProjectionSource {
2280
+ far: number;
2281
+ }
2282
+
2283
+ /** "Type bag" descriptor that fully parameterises an annotation system. */
2284
+ export declare interface DrawingSystemDescriptor {
2285
+ item: {
2286
+ uuid: string;
2287
+ style: string;
2288
+ };
2289
+ data: object;
2290
+ style: BaseAnnotationStyle;
2291
+ handle: string;
2292
+ }
2293
+
2294
+ /** Represents a framed orthographic window into a {@link TechnicalDrawing}. */
2295
+ export declare class DrawingViewport {
2296
+ /** Unique identifier for this viewport instance. */
2297
+ readonly uuid: string;
2298
+ /** Human-readable label for this viewport. */
2299
+ name: string;
2300
+ /**
2301
+ * The Three.js orthographic camera for this viewport.
2302
+ * Add it to the drawing container via {@link DrawingViewports.add}.
2303
+ */
2304
+ readonly camera: THREE.OrthographicCamera;
2305
+ /** {@link Disposable.onDisposed} */
2306
+ readonly onDisposed: Event_2<void>;
2307
+ private _left;
2308
+ private _right;
2309
+ private _top;
2310
+ private _bottom;
2311
+ private _drawingScale;
2312
+ private _container;
2313
+ private _helper;
2314
+ private _helperVisible;
2315
+ get left(): number;
2316
+ set left(value: number);
2317
+ get right(): number;
2318
+ set right(value: number);
2319
+ get top(): number;
2320
+ set top(value: number);
2321
+ get bottom(): number;
2322
+ set bottom(value: number);
2323
+ /** Drawing scale denominator (e.g. 100 = 1:100). */
2324
+ get drawingScale(): number;
2325
+ set drawingScale(value: number);
2326
+ /**
2327
+ * The {@link DrawingViewportHelper} for this viewport.
2328
+ *
2329
+ * The helper is created lazily on first access and cached. It is a
2330
+ * `THREE.Group` on layer 0, so it is visible to the perspective camera but
2331
+ * invisible to the viewport's own orthographic camera (layer 1 only).
2332
+ *
2333
+ * Use {@link helperVisible} to attach/detach it to the drawing container
2334
+ * automatically, or manage it manually with `drawing.three.add/remove`.
2335
+ */
2336
+ get helper(): DrawingViewportHelper;
2337
+ /**
2338
+ * Shows or hides the {@link DrawingViewportHelper} by attaching it to or
2339
+ * removing it from the drawing's container group.
2340
+ *
2341
+ * Setting this to `true` before the viewport has been registered via
2342
+ * `DrawingViewports.add()` has no effect until registration occurs.
2343
+ */
2344
+ get helperVisible(): boolean;
2345
+ set helperVisible(value: boolean);
2346
+ /**
2347
+ * Axis-aligned bounding box of this viewport in world drawing space (Y = 0).
2348
+ * Used by {@link clipLine} and PDF/DXF exporters.
2349
+ *
2350
+ * Because screen-up = world −Z, the world Z range visible to the camera is
2351
+ * [−top, −bottom], not [bottom, top].
2352
+ */
2353
+ get bbox(): THREE.Box3;
2354
+ /** Viewport size in millimetres (based on local units × 1000). */
2355
+ get size(): THREE.Vector2;
2356
+ /** Local X axis direction (world +X). */
2357
+ get localXAxis(): THREE.Vector3;
2358
+ /** Local Y axis direction (world -Z). */
2359
+ get localYAxis(): THREE.Vector3;
2360
+ /** Drawing plane normal (world +Y). */
2361
+ get normal(): THREE.Vector3;
2362
+ /**
2363
+ * The viewport lives in the drawing's local coordinate system (XZ plane, Y = 0).
2364
+ * Its {@link camera} must be added as a child of the drawing's container so that
2365
+ * any world-space transform applied to the container automatically moves the camera.
2366
+ *
2367
+ * The camera uses **layer 1** exclusively, so only geometry explicitly assigned
2368
+ * to layer 1 (projection lines, dimensions) is visible in paper-space renders.
2369
+ *
2370
+ * Local coordinate convention:
2371
+ * - X right → world +X
2372
+ * - Y up (screen) → world -Z
2373
+ * - Normal (out of plane) → world +Y
2374
+ */
2375
+ constructor(config: DrawingViewportConfig);
2376
+ /* Excluded from this release type: setContainer */
2377
+ /**
2378
+ * Clips a line segment to this viewport's bounding box.
2379
+ * Returns `null` when the line is entirely outside the viewport.
2380
+ */
2381
+ clipLine(line: THREE.Line3): THREE.Line3 | null;
2382
+ /** Destroys this viewport. The camera must be removed from its parent separately. */
2383
+ dispose(): void;
2384
+ private get bboxPlanes();
2385
+ private getPlaneIntersections;
2386
+ }
2387
+
2388
+ /**
2389
+ * Configuration to create a {@link DrawingViewport}.
2390
+ */
2391
+ export declare interface DrawingViewportConfig {
2392
+ /** Left bound of the viewport in local drawing units. */
2393
+ left: number;
2394
+ /** Right bound of the viewport in local drawing units. */
2395
+ right: number;
2396
+ /**
2397
+ * Top bound of the viewport in local drawing units.
2398
+ * Maps to world -Z (screen Y up = local -Z).
2399
+ */
2400
+ top: number;
2401
+ /**
2402
+ * Bottom bound of the viewport in local drawing units.
2403
+ * Maps to world +Z (screen Y down = local +Z).
2404
+ */
2405
+ bottom: number;
2406
+ /**
2407
+ * Drawing scale denominator (e.g. 100 means 1:100).
2408
+ * Defaults to 100.
2409
+ */
2410
+ scale?: number;
2411
+ /** Human-readable label for this viewport. Defaults to an empty string. */
2412
+ name?: string;
2413
+ }
2414
+
2415
+ /** Visualises the bounds of a `DrawingViewport` as a rectangle in the 3D scene. */
2416
+ export declare class DrawingViewportHelper extends THREE.Group {
2417
+ private readonly _viewport;
2418
+ private readonly _border;
2419
+ private readonly _handles;
2420
+ private readonly _raycaster;
2421
+ private _resizable;
2422
+ private _movable;
2423
+ private _dragHandle;
2424
+ private _dragConstraints;
2425
+ private _hoveredHandle;
2426
+ private _moveDrag;
2427
+ private _hoveringBorder;
2428
+ private readonly _normalMat;
2429
+ private readonly _hoverMat;
2430
+ private readonly _borderMat;
2431
+ private static readonly _BORDER_COLOR;
2432
+ private static readonly _BORDER_HOVER_COLOR;
2433
+ private static readonly _LINE_THRESHOLD;
2434
+ private static readonly _HANDLE_DEFS;
2435
+ /**
2436
+ * When `true`, the eight handle spheres are shown and resize drag is enabled.
2437
+ */
2438
+ get resizable(): boolean;
2439
+ set resizable(value: boolean);
2440
+ /**
2441
+ * When `true`, hovering and dragging the border rectangle translates the
2442
+ * entire viewport while keeping its width and height constant.
2443
+ */
2444
+ get movable(): boolean;
2445
+ set movable(value: boolean);
2446
+ /** `true` while either a resize or a move drag is in progress. */
2447
+ get isDragging(): boolean;
2448
+ /**
2449
+ * Works exactly like the built-in Three.js helpers (e.g. `THREE.CameraHelper`):
2450
+ * the result is a plain `THREE.Group` you can add wherever you like in the scene
2451
+ * graph. It renders on **layer 0**, so it is visible to the perspective camera
2452
+ * but invisible to the viewport's own orthographic camera (which only renders
2453
+ * layer 1).
2454
+ *
2455
+ * Typically you do not construct this directly — use
2456
+ * `DrawingViewport.helperVisible = true` instead, which attaches the helper to
2457
+ * the drawing container automatically.
2458
+ *
2459
+ * When {@link editable} is `true`, two kinds of interaction are enabled:
2460
+ *
2461
+ * - **Resize** — hover one of the eight handle spheres (corners + edge midpoints)
2462
+ * and drag to resize the viewport in that direction.
2463
+ * - **Move** — hover the border rectangle itself and drag to translate the
2464
+ * entire viewport while keeping its width and height constant.
2465
+ *
2466
+ * In both cases the border and the hovered element turn orange as visual
2467
+ * feedback, and {@link isDragging} becomes `true` for the duration of the drag.
2468
+ *
2469
+ * The class contains no browser API references and is safe in Node.js
2470
+ * environments; the consumer forwards events:
2471
+ *
2472
+ * ```ts
2473
+ * container.addEventListener("mousemove", (e) => {
2474
+ * raycaster.setFromCamera(getNDC(e), camera);
2475
+ * viewport.helper.onPointerMove(raycaster.ray);
2476
+ * });
2477
+ * container.addEventListener("mousedown", (e) => {
2478
+ * raycaster.setFromCamera(getNDC(e), camera);
2479
+ * viewport.helper.onPointerDown(raycaster.ray);
2480
+ * });
2481
+ * container.addEventListener("mouseup", () => viewport.helper.onPointerUp());
2482
+ * ```
2483
+ */
2484
+ constructor(viewport: ViewportBoundsController);
2485
+ /**
2486
+ * Rebuilds the border geometry and repositions all handles to match the
2487
+ * current viewport bounds. Called automatically by the viewport whenever
2488
+ * any bound changes; you rarely need to call this yourself.
2489
+ */
2490
+ update(): void;
2491
+ /**
2492
+ * Forward `mousemove` events here.
2493
+ *
2494
+ * - **Resize drag active**: updates the bound(s) controlled by the active handle.
2495
+ * - **Move drag active**: translates all four bounds by the cursor delta,
2496
+ * preserving the viewport's width and height.
2497
+ * - **No drag**: highlights handles on hover; highlights the border when the
2498
+ * cursor is over it and no handle is hovered.
2499
+ *
2500
+ * @param ray - World-space ray, e.g. from `THREE.Raycaster.setFromCamera`.
2501
+ */
2502
+ onPointerMove(ray: THREE.Ray): void;
2503
+ /**
2504
+ * Forward `mousedown` events here.
2505
+ *
2506
+ * - If a handle is hovered, begins a **resize drag**.
2507
+ * - If the border is hovered (and no handle), begins a **move drag**.
2508
+ *
2509
+ * @param ray - World-space ray at the moment of the press.
2510
+ */
2511
+ onPointerDown(ray: THREE.Ray): void;
2512
+ /** Forward `mouseup` events here to end any active drag. */
2513
+ onPointerUp(): void;
2514
+ /** Releases all Three.js geometry and material resources. */
2515
+ dispose(): void;
2516
+ /**
2517
+ * Projects a world-space ray onto this group's local Y = 0 plane and
2518
+ * returns the intersection in local coordinates.
2519
+ */
2520
+ private _projectToLocal;
2521
+ /** Toggles the border hover colour and keeps `_hoveringBorder` in sync. */
2522
+ private _setBorderHover;
2523
+ }
2524
+
2525
+ /** Manages the viewports of a {@link TechnicalDrawing}. */
2526
+ export declare class DrawingViewports extends FRAGS.DataMap<string, DrawingViewport> {
2527
+ private readonly _container;
2528
+ /**
2529
+ * Accessible via `drawing.viewports`. Extends `DataMap` so consumers get
2530
+ * reactive events (`onItemSet`, `onBeforeDelete`, …) for free.
2531
+ *
2532
+ * ```ts
2533
+ * const vp = drawing.viewports.create({ left: -1, right: 5, top: 1, bottom: -4 });
2534
+ * drawing.viewports.delete(vp.uuid); // disposes and removes
2535
+ * ```
2536
+ */
2537
+ constructor(container: THREE.Group);
2538
+ /**
2539
+ * Creates a new {@link DrawingViewport}, adds its camera to the drawing
2540
+ * container, and registers it.
2541
+ *
2542
+ * @param config - Bounds and scale for the new viewport.
2543
+ * @returns The newly created viewport.
2544
+ */
2545
+ create(config: DrawingViewportConfig): DrawingViewport;
2546
+ }
2547
+
2548
+ /** One drawing with one or more viewport placements to export. */
2549
+ export declare interface DxfDrawingEntry {
2550
+ drawing: TechnicalDrawing;
2551
+ viewports: DxfViewportEntry[];
2552
+ }
2553
+
2554
+ /** Serializes {@link TechnicalDrawing} content to DXF format (AC1015 / AutoCAD R2000). */
2555
+ export declare class DxfExporter {
2556
+ private readonly _components;
2557
+ /** Decimal places used when formatting measurement text in DXF. */
2558
+ precision: number;
2559
+ /**
2560
+ * Export configuration options.
2561
+ * - `trueColor` — when `true`, upgrades the output to AC1018 (AutoCAD 2004+) and
2562
+ * emits group code 420 (RGB true color) alongside group code 62 (ACI) on every
2563
+ * entity. Modern viewers prioritize 420; older apps fall back to 62.
2564
+ * Note: the adaptive black/white behavior of ACI 7 is lost when true color is on,
2565
+ * since viewers treat the explicit RGB as fixed. Defaults to `false`.
2566
+ */
2567
+ config: {
2568
+ trueColor: boolean;
2569
+ };
2570
+ private _viewport;
2571
+ private _paperSlot;
2572
+ private readonly _annotationLayers;
2573
+ private readonly _systemExporters;
2574
+ /**
2575
+ * Used through {@link DxfManager}:
2576
+ * ```ts
2577
+ * const dxf = components.get(OBC.DxfManager).exporter.export([
2578
+ * { drawing, viewports: [{ viewport, x: 10, y: 10 }] },
2579
+ * ], { widthMm: 420, heightMm: 297, margin: 10 });
2580
+ * ```
2581
+ */
2582
+ constructor(_components: Components);
2583
+ /**
2584
+ * Registers a custom DXF exporter for a {@link DrawingSystem} subclass.
2585
+ */
2586
+ registerSystemExporter<T extends AnnotationSystem<any>>(SystemClass: new (...args: any[]) => T, handler: (sys: T, ctx: DxfWriteContext) => void): void;
2587
+ /**
2588
+ * Serializes one or more drawings to a DXF string.
2589
+ *
2590
+ * When `paper` is supplied the output uses millimetres (INSUNITS=4) and
2591
+ * each viewport is placed at its (`x`, `y`) position on the sheet.
2592
+ * Without `paper` the output uses world units (INSUNITS=6).
2593
+ *
2594
+ * @param entries - Drawings with their viewport placements.
2595
+ * @param paper - Optional paper sheet dimensions for paper-space export.
2596
+ */
2597
+ export(entries: DxfDrawingEntry[], paper?: DxfPaperOptions): string;
2598
+ private _writeHeader;
2599
+ private _writeTables;
2600
+ private _writeBlocks;
2601
+ private _writeBlock;
2602
+ /** Writes a rectangular border for the active viewport (no-op when no viewport is set). */
2603
+ private _writeViewportBorder;
2604
+ /**
2605
+ * Writes drawing-area and full-sheet border rectangles in paper-space coordinates.
2606
+ * Origin (0, 0) is the top-left corner of the drawing area (inside margins).
2607
+ */
2608
+ private _writePaperBorders;
2609
+ private _writeObjects;
2610
+ private _writeRawLines;
2611
+ private _writeLinearAnnotations;
2612
+ private _writeAngleAnnotations;
2613
+ private _writeLeaderAnnotations;
2614
+ private _writeSlopeAnnotations;
2615
+ private _writeCalloutAnnotations;
2616
+ private _writeBlockInsertions;
2617
+ private _writeGeoAsLines;
2618
+ private _writePairsAsLines;
2619
+ private _emitTrueColor;
2620
+ private _writeLine;
2621
+ /** Writes a LINE entity with coordinates already in DXF space (no transform applied). */
2622
+ private _writeRawLine;
2623
+ /**
2624
+ * Writes a single triangle as a DXF SOLID entity.
2625
+ * Coordinates are in drawing local space (XZ plane) — transform is applied internally.
2626
+ * The 4th vertex equals the 3rd (degenerate quad = triangle).
2627
+ */
2628
+ private _writeSolid;
2629
+ /**
2630
+ * Writes a flat XYZ triangle array (9 values per triangle, XZ plane) as SOLID entities.
2631
+ * Matches the output format of {@link MeshTickBuilder}.
2632
+ */
2633
+ private _writeMeshTriangles;
2634
+ private _writeText;
2635
+ /** Maps world X to DXF X. In paper-space, output is in mm from the drawing area origin. */
2636
+ private _tx;
2637
+ /**
2638
+ * Maps world Z to DXF Y.
2639
+ * In paper-space, output is in mm from the drawing area bottom (DXF Y-up).
2640
+ * In world-space mode, uses Y-down convention (Y=0 at viewport top).
2641
+ */
2642
+ private _ty;
2643
+ /** Returns the coordinate scale factor: mm-per-world-unit in paper mode, 1 otherwise. */
2644
+ private _scale;
2645
+ private _clipSegment;
2646
+ private _inViewport;
2647
+ private _bboxFromPositions;
2648
+ private _fullyInViewport;
2649
+ private _textAngle;
2650
+ private _writeCustomSystems;
2651
+ private _makeContext;
2652
+ }
2653
+
2654
+ /** Manages DXF import and export for technical drawings. */
2655
+ export declare class DxfManager extends Component {
2656
+ static readonly uuid: "e9a2c3d4-5f67-4b89-a012-1c3d5e7f9b2a";
2657
+ enabled: boolean;
2658
+ /** Handles DXF serialisation of {@link TechnicalDrawing} content. */
2659
+ readonly exporter: DxfExporter;
2660
+ /**
2661
+ * ```ts
2662
+ * const manager = components.get(OBC.DxfManager);
2663
+ * const dxf = manager.exporter.export([{ drawing, viewports: [{ viewport }] }]);
2664
+ * ```
2665
+ */
2666
+ constructor(components: Components);
2667
+ }
2668
+
2669
+ /** Paper sheet dimensions for paper-space export. */
2670
+ export declare interface DxfPaperOptions {
2671
+ /** Total paper width in mm. */
2672
+ widthMm: number;
2673
+ /** Total paper height in mm. */
2674
+ heightMm: number;
2675
+ /** Uniform margin in mm. */
2676
+ margin: number;
2677
+ }
2678
+
2679
+ /** Optional text formatting overrides for {@link DxfWriteContext.writeText}. */
2680
+ export declare interface DxfTextOptions {
2681
+ layer?: string;
2682
+ aciColor?: number;
2683
+ rotDeg?: number;
2684
+ hAlign?: 0 | 1 | 2;
2685
+ }
2686
+
2687
+ /** One viewport placement within a drawing entry. */
2688
+ export declare interface DxfViewportEntry {
2689
+ /** Viewport to clip and transform against. If omitted, exports the full drawing. */
2690
+ viewport?: DrawingViewport;
2691
+ /** Horizontal position in mm from the top-left of the drawing area (paper-space only). */
2692
+ x?: number;
2693
+ /** Vertical position in mm from the top-left of the drawing area (paper-space only). */
2694
+ y?: number;
2695
+ }
2696
+
2697
+ /**
2698
+ * Write-context passed to custom system exporters registered via
2699
+ * {@link DxfExporter.registerSystemExporter}.
2700
+ */
2701
+ export declare interface DxfWriteContext {
2702
+ writeLine(x1: number, y1: number, x2: number, y2: number, layer?: string, aciColor?: number): void;
2703
+ writePairs(positions: ArrayLike<number>, layer?: string, aciColor?: number): void;
2704
+ writeText(text: string, x: number, y: number, height: number, options?: DxfTextOptions): void;
2705
+ /** Writes a flat XYZ triangle array (9 values per triangle) as DXF SOLID entities. */
2706
+ writeMeshTriangles(triangles: number[], layer?: string, aciColor?: number): void;
2707
+ hexToAci(hex: number): number;
2708
+ textAngle(dx: number, dz: number): number;
2709
+ }
2710
+
2711
+ /** Result of an edge projection, containing visible/hidden geometries and a mapping from group indices to model item identifiers. */
2712
+ export declare interface EdgeProjectionResult {
2713
+ /** Line segment geometry for visible edges. Has a `group` vertex attribute with group indices. */
2714
+ visible: THREE.BufferGeometry;
2715
+ /** Line segment geometry for hidden edges. Has a `group` vertex attribute with group indices. */
2716
+ hidden: THREE.BufferGeometry;
2717
+ /** Maps group index to `{ modelId, localId }` identifying the source item. */
2718
+ groups: Record<number, {
2719
+ modelId: string;
2720
+ localId: number;
2721
+ }>;
2722
+ }
2723
+
2724
+ /** Component that generates 2D edge projections from fragment model items. */
2725
+ export declare class EdgeProjector extends Component implements Disposable_2 {
2726
+ static readonly uuid: "f2e76c3a-8b1d-4d5e-9a3f-7c6b2d4e8f1a";
2727
+ enabled: boolean;
2728
+ readonly onDisposed: Event_2<unknown>;
2729
+ /**
2730
+ * The underlying ProjectionGenerator from three-edge-projection.
2731
+ * You can configure angleThreshold, iterationTime, includeIntersectionEdges, and useWebGPU.
2732
+ */
2733
+ readonly generator: any;
2734
+ /**
2735
+ * Resolution of the visibility culler in pixels per meter.
2736
+ * Higher values = more accurate occlusion but slower culling.
2737
+ */
2738
+ cullerPixelsPerMeter: number;
2739
+ /**
2740
+ * The direction the projector looks along. Meshes are projected onto the plane
2741
+ * perpendicular to this direction. Default is top-down (plan view).
2742
+ *
2743
+ * Common values:
2744
+ * - Top/Plan: `(0, -1, 0)`
2745
+ * - Front: `(0, 0, -1)`
2746
+ * - Back: `(0, 0, 1)`
2747
+ * - Left: `(-1, 0, 0)`
2748
+ * - Right: `(1, 0, 0)`
2749
+ */
2750
+ readonly projectionDirection: THREE.Vector3;
2751
+ /**
2752
+ * Near clipping plane along the projection direction.
2753
+ * Meshes whose AABB is fully "behind" this plane (closer to the viewer) are excluded.
2754
+ * Set to -Infinity to disable.
2755
+ */
2756
+ nearPlane: number;
2757
+ /**
2758
+ * Far clipping plane along the projection direction.
2759
+ * Meshes whose AABB is fully "beyond" this plane (farther from the viewer) are excluded.
2760
+ * Set to Infinity to disable.
2761
+ */
2762
+ farPlane: number;
2763
+ constructor(components: Components);
2764
+ /**
2765
+ * Generates 2D edge projections for the given model items.
2766
+ *
2767
+ * @param modelIdMap - A map of model IDs to sets of local IDs specifying items to project.
2768
+ * @param world - The world whose renderer will be used for visibility culling.
2769
+ * @param config - Optional configuration.
2770
+ * @param config.onProgress - Optional progress callback receiving (message, progress?, collector?).
2771
+ * @returns Visible/hidden geometries with a `group` vertex attribute, and a groups mapping.
2772
+ */
2773
+ get(modelIdMap: ModelIdMap, world: World, config?: {
2774
+ onProgress?: (message: string, progress?: number) => void;
2775
+ }): Promise<EdgeProjectionResult>;
2776
+ dispose(): void;
2777
+ }
2778
+
2779
+ /** Defines a closed shape (cloud, rectangle, circle, etc.) that forms the body of a callout annotation. */
2780
+ export declare type EnclosureBuilder = {
2781
+ /** Returns flat XYZ line-segment pairs forming the enclosure outline. */
2782
+ buildGeometry: (center: THREE.Vector3, halfW: number, halfH: number) => number[];
2783
+ /**
2784
+ * Returns the point on the enclosure boundary in the direction `dir` from
2785
+ * `center`. `dir` is a unit vector in the XZ plane.
2786
+ */
2787
+ getAttachmentPoint: (center: THREE.Vector3, halfW: number, halfH: number, dir: THREE.Vector3) => THREE.Vector3;
2788
+ };
2789
+
1561
2790
  /**
1562
2791
  * Simple event handler by [Jason Kleban](https://gist.github.com/JasonKleban/50cee44960c225ac1993c922563aa540). Keep in mind that if you want to remove it later, you might want to declare the callback as an object. If you want to maintain the reference to `this`, you will need to declare the callback as an arrow function.
1563
2792
  */
@@ -1800,6 +3029,15 @@ export declare class FastModelPickers extends Component implements Disposable_2
1800
3029
  dispose(): void;
1801
3030
  }
1802
3031
 
3032
+ /** Filled arrowhead tick (solid triangle, requires a `THREE.Mesh`). */
3033
+ export declare const FilledArrowTick: MeshTickBuilder;
3034
+
3035
+ /** Filled circle tick (solid disc, requires a `THREE.Mesh`). */
3036
+ export declare const FilledCircleTick: MeshTickBuilder;
3037
+
3038
+ /** Filled square tick (solid square, requires a `THREE.Mesh`). */
3039
+ export declare const FilledSquareTick: MeshTickBuilder;
3040
+
1803
3041
  /**
1804
3042
  * Represents a finder query for retrieving items based on specified parameters. This class encapsulates the query logic, caching mechanism, and result management.
1805
3043
  */
@@ -1877,6 +3115,15 @@ export declare class FirstPersonMode implements NavigationMode {
1877
3115
  private setupFirstPersonCamera;
1878
3116
  }
1879
3117
 
3118
+ /**
3119
+ * Converts a slope ratio to a human-readable string.
3120
+ *
3121
+ * @param slope - Rise / run ratio (e.g. `0.15` for 15 %).
3122
+ * @param format - Desired output format.
3123
+ * @returns Formatted string, e.g. `"15.00 %"`, `"1:6.67"`, or `"8.53°"`.
3124
+ */
3125
+ export declare function formatSlope(slope: number, format: SlopeFormat): string;
3126
+
1880
3127
  /**
1881
3128
  * Component to load, delete and manage [fragments](https://github.com/ThatOpen/engine_fragment) efficiently. 📕 [Tutorial](https://docs.thatopen.com/Tutorials/Components/Core/FragmentsManager). 📘 [API](https://docs.thatopen.com/api/@thatopen/components/classes/FragmentsManager).
1882
3129
  */
@@ -1964,6 +3211,23 @@ export declare class FragmentsManager extends Component implements Disposable_2
1964
3211
  applyBaseCoordinateSystem(object: THREE.Object3D | THREE.Vector3, originalCoordinateSystem?: THREE.Matrix4): THREE.Matrix4;
1965
3212
  }
1966
3213
 
3214
+ /** Returns the tip position and inward tangent direction for each tick endpoint of an angle dimension arc. */
3215
+ export declare function getAngleTickEndpoints(dim: AngleAnnotation): Array<{
3216
+ tip: THREE.Vector3;
3217
+ dir: THREE.Vector3;
3218
+ }>;
3219
+
3220
+ /** Returns the tip position and inward direction for each tick endpoint of a linear dimension. */
3221
+ export declare function getDimensionTickEndpoints(dim: LinearAnnotation): Array<{
3222
+ tip: THREE.Vector3;
3223
+ dir: THREE.Vector3;
3224
+ }>;
3225
+
3226
+ /**
3227
+ * Returns the tip position of a slope annotation in drawing local space.
3228
+ */
3229
+ export declare function getSlopeTip(ann: SlopeAnnotation, length: number): THREE.Vector3;
3230
+
1967
3231
  /**
1968
3232
  * A component that manages grid instances. Each grid is associated with a unique world. 📕 [Tutorial](https://docs.thatopen.com/Tutorials/Components/Core/Grids). 📘 [API](https://docs.thatopen.com/api/@thatopen/components/classes/Grids).
1969
3233
  */
@@ -2587,29 +3851,327 @@ export declare class ItemsFinder extends Component implements Serializable<Seria
2587
3851
  */
2588
3852
  create(name: string, queries: FRAGS.ItemsQueryParams[]): FinderQuery;
2589
3853
  /**
2590
- * Adds queries based on categories from items that have geometry.
2591
- *
2592
- * @param modelIds - An optional array of model IDs to filter fragments. If not provided, all fragments are processed.
2593
- * @returns An array with the categories used to create the queries
3854
+ * Adds queries based on categories from items that have geometry.
3855
+ *
3856
+ * @param modelIds - An optional array of model IDs to filter fragments. If not provided, all fragments are processed.
3857
+ * @returns An array with the categories used to create the queries
3858
+ */
3859
+ addFromCategories(modelIds?: RegExp[]): Promise<string[]>;
3860
+ /**
3861
+ * Imports a list of `FinderQuery` instances from a `SerializationResult` containing serialized finder query data.
3862
+ *
3863
+ * @param result - The `SerializationResult` containing the serialized `SerializedFinderQuery` data.
3864
+ * @returns An array of `FinderQuery` instances created from the serialized data. Returns an empty array if the input data is null or undefined.
3865
+ */
3866
+ import(result: SerializationResult<SerializedFinderQuery>): FinderQuery[];
3867
+ /**
3868
+ * Serializes the ItemsFinder's data into a format suitable for export.
3869
+ *
3870
+ * @returns An object containing an array of serialized finder queries.
3871
+ */
3872
+ export(): {
3873
+ data: SerializedFinderQuery[];
3874
+ };
3875
+ }
3876
+
3877
+ /** The committed data for a single leader annotation. */
3878
+ export declare interface LeaderAnnotation {
3879
+ /** Unique identifier. */
3880
+ uuid: string;
3881
+ /** Tip of the arrow — the annotated point. */
3882
+ arrowTip: THREE.Vector3;
3883
+ /** Elbow — the bend between the leader line and the extension. */
3884
+ elbow: THREE.Vector3;
3885
+ /** End of the horizontal extension line — anchor for the text. */
3886
+ extensionEnd: THREE.Vector3;
3887
+ /** The annotation text. */
3888
+ text: string;
3889
+ /** Name of the {@link LeaderAnnotationStyle} to use when rendering. */
3890
+ style: string;
3891
+ }
3892
+
3893
+ /** Editable fields of {@link LeaderAnnotation} — everything except `uuid`. */
3894
+ export declare type LeaderAnnotationData = Omit<LeaderAnnotation, "uuid">;
3895
+
3896
+ export declare type LeaderAnnotationEvent =
3897
+ /** First event that starts the machine — carries the target drawing. */
3898
+ {
3899
+ type: "CLICK";
3900
+ point: THREE.Vector3;
3901
+ drawing?: TechnicalDrawing;
3902
+ }
3903
+ /** The cursor moved — drawing context is already set from the initial CLICK. */
3904
+ | {
3905
+ type: "MOUSE_MOVE";
3906
+ point: THREE.Vector3;
3907
+ }
3908
+ /**
3909
+ * Consumer supplies the annotation text after the machine enters
3910
+ * `enteringText`. Ignored in all other states.
3911
+ */
3912
+ | {
3913
+ type: "SUBMIT_TEXT";
3914
+ text: string;
3915
+ }
3916
+ /** Cancel the current operation and return to the initial state. */
3917
+ | {
3918
+ type: "ESCAPE";
3919
+ };
3920
+
3921
+ /** Pure state transition function for the leader annotation tool. */
3922
+ export declare function leaderAnnotationMachine(state: LeaderAnnotationState, event: LeaderAnnotationEvent): LeaderAnnotationState;
3923
+
3924
+ /** Global drawing system that manages leader (arrow + text) annotations across all {@link TechnicalDrawing} instances. */
3925
+ export declare class LeaderAnnotations extends AnnotationSystem<LeaderAnnotationSystem> implements Transitionable<LeaderAnnotationState, LeaderAnnotationEvent>, Disposable_2 {
3926
+ enabled: boolean;
3927
+ readonly _item: LeaderAnnotation;
3928
+ machineState: LeaderAnnotationState;
3929
+ readonly onMachineStateChanged: Event_2<LeaderAnnotationState>;
3930
+ private readonly _previewMeshMaterial;
3931
+ private _previewMeshObject;
3932
+ constructor(components: Components);
3933
+ pickHandle(drawing: TechnicalDrawing, ray: THREE.Ray, threshold?: number): {
3934
+ uuid: string;
3935
+ handle: "elbow" | "extensionEnd";
3936
+ } | null;
3937
+ sendMachineEvent(event: LeaderAnnotationEvent): void;
3938
+ protected _buildGroup(ann: LeaderAnnotation, style: LeaderAnnotationStyle): THREE.Group;
3939
+ protected _updatePreview(): void;
3940
+ protected _clearPreview(): void;
3941
+ protected _onDispose(): void;
3942
+ private _resetMachine;
3943
+ private _clearPreviewMesh;
3944
+ }
3945
+
3946
+ export declare type LeaderAnnotationState =
3947
+ /** Tool active, waiting for the first click (arrow tip). */
3948
+ {
3949
+ kind: "awaitingArrowTip";
3950
+ }
3951
+ /** Arrow tip placed. User moves toward the elbow point. */
3952
+ | {
3953
+ kind: "placingElbow";
3954
+ arrowTip: THREE.Vector3;
3955
+ cursor: THREE.Vector3 | null;
3956
+ }
3957
+ /** Elbow placed. User moves toward the extension end. */
3958
+ | {
3959
+ kind: "placingExtension";
3960
+ arrowTip: THREE.Vector3;
3961
+ elbow: THREE.Vector3;
3962
+ cursor: THREE.Vector3 | null;
3963
+ }
3964
+ /**
3965
+ * All geometry is set. The machine is paused waiting for the consumer to
3966
+ * supply the annotation text via a `SUBMIT_TEXT` event.
3967
+ */
3968
+ | {
3969
+ kind: "enteringText";
3970
+ arrowTip: THREE.Vector3;
3971
+ elbow: THREE.Vector3;
3972
+ extensionEnd: THREE.Vector3;
3973
+ }
3974
+ /** Annotation just committed. */
3975
+ | {
3976
+ kind: "committed";
3977
+ annotation: LeaderAnnotation;
3978
+ };
3979
+
3980
+ /** Visual appearance of a leader annotation. */
3981
+ export declare interface LeaderAnnotationStyle extends BaseAnnotationStyle {
3982
+ /** Size of the tick at the arrow tip in drawing local units. */
3983
+ tickSize: number;
3984
+ /**
3985
+ * Distance from `extensionEnd` to the text label anchor,
3986
+ * measured along the extension direction.
3987
+ */
3988
+ textOffset: number;
3989
+ /**
3990
+ * Leader line shape.
3991
+ * - `"angular"` (default) — two straight segments: arrowTip → elbow → extensionEnd.
3992
+ * - `"curved"` — quadratic Bézier with `elbow` as the control point.
3993
+ */
3994
+ leaderShape?: "angular" | "curved";
3995
+ /**
3996
+ * Line-segment tick at the arrow tip — geometry is included in the same
3997
+ * `LineSegments` as the leader line.
3998
+ * When both `tick` and `meshTick` are absent, nothing is drawn at the tip.
3999
+ */
4000
+ lineTick?: LineTickBuilder;
4001
+ /**
4002
+ * Filled (mesh) tick at the arrow tip — rendered as a separate `THREE.Mesh`.
4003
+ * Can be combined with `tick` (e.g. open circle + filled disc = target).
4004
+ */
4005
+ meshTick?: MeshTickBuilder;
4006
+ }
4007
+
4008
+ declare interface LeaderAnnotationSystem {
4009
+ item: LeaderAnnotation;
4010
+ data: LeaderAnnotationData;
4011
+ style: LeaderAnnotationStyle;
4012
+ handle: "elbow" | "extensionEnd";
4013
+ }
4014
+
4015
+ /** The committed data for a single linear annotation. */
4016
+ export declare interface LinearAnnotation {
4017
+ /** Unique identifier. */
4018
+ uuid: string;
4019
+ /** First measured point in drawing local space. */
4020
+ pointA: THREE.Vector3;
4021
+ /** Second measured point in drawing local space. */
4022
+ pointB: THREE.Vector3;
4023
+ /**
4024
+ * Signed distance from the AB segment to the dimension line,
4025
+ * measured along the direction perpendicular to the measurement axis.
2594
4026
  */
2595
- addFromCategories(modelIds?: RegExp[]): Promise<string[]>;
4027
+ offset: number;
4028
+ /** Name of the {@link LinearAnnotationStyle} to use when rendering this annotation. */
4029
+ style: string;
4030
+ }
4031
+
4032
+ /** Editable fields of {@link LinearAnnotation} — everything except the `uuid`. */
4033
+ export declare type LinearAnnotationData = Omit<LinearAnnotation, "uuid">;
4034
+
4035
+ export declare type LinearAnnotationEvent =
4036
+ /**
4037
+ * A point in drawing local space was clicked.
4038
+ * Carries `drawing` so the machine can lock it in as `_previewDrawing` on the
4039
+ * first click — subsequent events reuse that cached context.
4040
+ *
4041
+ * `line` MUST be provided when in `awaitingFirstPoint` or `placingPoints` —
4042
+ * the machine silently ignores the click without it (only line snaps accepted).
4043
+ * It is optional in `positioningOffset` (free-space placement).
4044
+ */
4045
+ {
4046
+ type: "CLICK";
4047
+ point: THREE.Vector3;
4048
+ line?: THREE.Line3;
4049
+ drawing?: TechnicalDrawing;
4050
+ }
4051
+ /** The cursor moved — drawing context is already cached from the initial CLICK or SELECT_LINE. */
4052
+ | {
4053
+ type: "MOUSE_MOVE";
4054
+ point: THREE.Vector3;
4055
+ }
4056
+ /**
4057
+ * Consumer signals "done placing points — move to offset positioning".
4058
+ * Relevant only in `sequential` mode; in `individual` the machine auto-advances.
4059
+ * The consumer decides the DOM mapping (Enter, double-click, etc.).
4060
+ */
4061
+ | {
4062
+ type: "CONFIRM";
4063
+ }
4064
+ /**
4065
+ * Alternative first event: selects an entire line as the dimension's measured
4066
+ * segment, jumping directly to `positioningOffset`.
4067
+ * Carries `drawing` to set the drawing context (same role as the first CLICK).
4068
+ */
4069
+ | {
4070
+ type: "SELECT_LINE";
4071
+ line: THREE.Line3;
4072
+ drawing?: TechnicalDrawing;
4073
+ }
4074
+ /** Cancel the current operation and return to the initial state. */
4075
+ | {
4076
+ type: "ESCAPE";
4077
+ };
4078
+
4079
+ /** Global drawing system that manages linear dimension annotations across all {@link TechnicalDrawing} instances. */
4080
+ export declare class LinearAnnotations extends AnnotationSystem<LinearAnnotationSystem> implements Transitionable<LinearAnnotationState, LinearAnnotationEvent>, Disposable_2 {
4081
+ enabled: boolean;
4082
+ readonly _item: LinearAnnotation;
4083
+ machineState: LinearAnnotationState;
4084
+ readonly onMachineStateChanged: Event_2<LinearAnnotationState>;
4085
+ constructor(components: Components);
4086
+ pickHandle(drawing: TechnicalDrawing, ray: THREE.Ray, threshold?: number): {
4087
+ uuid: string;
4088
+ handle: "pointA" | "pointB" | "offset";
4089
+ } | null;
4090
+ sendMachineEvent(event: LinearAnnotationEvent): void;
4091
+ protected _buildGroup(dim: LinearAnnotation, style: LinearAnnotationStyle): THREE.Group;
4092
+ protected _updatePreview(): void;
4093
+ private _resetMachine;
4094
+ }
4095
+
4096
+ export declare type LinearAnnotationState =
4097
+ /** Tool is active but no interaction has started. */
4098
+ {
4099
+ kind: "awaitingFirstPoint";
4100
+ }
4101
+ /**
4102
+ * First point placed. Stores the direction of the measured lines so that
4103
+ * subsequent clicks can be validated (must be on parallel lines) and the
4104
+ * cursor preview constrained to the orthogonal measurement direction.
4105
+ *
4106
+ * In `individual` mode the tool auto-advances after the second CLICK.
4107
+ * In `sequential` mode the user accumulates points and sends CONFIRM when done.
4108
+ */
4109
+ | {
4110
+ kind: "placingPoints";
4111
+ points: THREE.Vector3[];
4112
+ cursor: THREE.Vector3 | null;
4113
+ /** Normalised direction of the first (and all subsequent) measured lines. */
4114
+ lineDir: THREE.Vector3;
4115
+ /** The first line segment hit — used to reject clicks on the same segment. */
4116
+ firstLine: THREE.Line3;
4117
+ }
4118
+ /**
4119
+ * All measurement points are set. The user drags to define the perpendicular
4120
+ * offset of the dimension line, then clicks to commit.
4121
+ */
4122
+ | {
4123
+ kind: "positioningOffset";
4124
+ points: THREE.Vector3[];
4125
+ cursor: THREE.Vector3 | null;
4126
+ }
4127
+ /** One or more annotations have just been committed. */
4128
+ | {
4129
+ kind: "committed";
4130
+ dimensions: LinearAnnotation[];
4131
+ };
4132
+
4133
+ /** Visual appearance of a linear annotation. Registered by name on the component. */
4134
+ export declare interface LinearAnnotationStyle extends BaseAnnotationStyle {
4135
+ /** Tick mark geometry builder. Use one of the built-in exports or provide a custom one. */
4136
+ lineTick: LineTickBuilder;
2596
4137
  /**
2597
- * Imports a list of `FinderQuery` instances from a `SerializationResult` containing serialized finder query data.
2598
- *
2599
- * @param result - The `SerializationResult` containing the serialized `SerializedFinderQuery` data.
2600
- * @returns An array of `FinderQuery` instances created from the serialized data. Returns an empty array if the input data is null or undefined.
4138
+ * Optional filled tick mark builder. When provided, a `THREE.Mesh` triangle
4139
+ * is rendered at each dimension endpoint in addition to (or instead of) the
4140
+ * line tick. Set `tick` to {@link NoTick} when you only want the filled shape.
2601
4141
  */
2602
- import(result: SerializationResult<SerializedFinderQuery>): FinderQuery[];
4142
+ meshTick?: MeshTickBuilder;
4143
+ /** Size of the tick mark in drawing local units. */
4144
+ tickSize: number;
4145
+ /** Gap between the measured geometry and the start of each extension line. */
4146
+ extensionGap: number;
4147
+ /** How far extension lines overshoot beyond the dimension line. */
4148
+ extensionOvershoot: number;
2603
4149
  /**
2604
- * Serializes the ItemsFinder's data into a format suitable for export.
2605
- *
2606
- * @returns An object containing an array of serialized finder queries.
4150
+ * Signed perpendicular distance from the dimension line to the text label,
4151
+ * measured outward from the measured geometry.
4152
+ * Positive moves the text away from the geometry; negative moves it inward.
2607
4153
  */
2608
- export(): {
2609
- data: SerializedFinderQuery[];
2610
- };
4154
+ textOffset: number;
4155
+ }
4156
+
4157
+ declare interface LinearAnnotationSystem {
4158
+ item: LinearAnnotation;
4159
+ data: LinearAnnotationData;
4160
+ style: LinearAnnotationStyle;
4161
+ handle: "pointA" | "pointB" | "offset";
2611
4162
  }
2612
4163
 
4164
+ /** Pure state transition function for the linear dimension tool. */
4165
+ export declare function linearDimensionMachine(state: LinearAnnotationState, event: LinearAnnotationEvent): LinearAnnotationState;
4166
+
4167
+ /**
4168
+ * A function that produces tick mark geometry at one endpoint of a dimension or leader line.
4169
+ * @param tip - The endpoint of the line (drawing local space).
4170
+ * @param lineDir - Normalised direction FROM `tip` TOWARD the other endpoint.
4171
+ * @param size - Tick size in drawing local units.
4172
+ */
4173
+ export declare type LineTickBuilder = (tip: THREE.Vector3, lineDir: THREE.Vector3, size: number) => number[];
4174
+
2613
4175
  /**
2614
4176
  * Represents an edge measurement result.
2615
4177
  */
@@ -2679,6 +4241,14 @@ export declare class MeasurementUtils extends Component {
2679
4241
  static convertUnits(value: number, fromUnit: string, toUnit: string, precision?: number): number;
2680
4242
  }
2681
4243
 
4244
+ /**
4245
+ * A function that produces filled tick mark geometry (triangles) at one endpoint.
4246
+ * @param tip - The endpoint of the dimension or leader line.
4247
+ * @param lineDir - Normalised direction FROM `tip` TOWARD the other endpoint.
4248
+ * @param size - Tick/arrow size in drawing local units.
4249
+ */
4250
+ export declare type MeshTickBuilder = (tip: THREE.Vector3, lineDir: THREE.Vector3, size: number) => number[];
4251
+
2682
4252
  export declare type ModelIdDataMap<T> = FRAGS.DataMap<string, FRAGS.DataMap<number, T>>;
2683
4253
 
2684
4254
  /**
@@ -2809,6 +4379,9 @@ export declare interface NoControl {
2809
4379
  value: any;
2810
4380
  }
2811
4381
 
4382
+ /** No tick — dimension line ends cleanly at the extension lines. */
4383
+ export declare const NoTick: LineTickBuilder;
4384
+
2812
4385
  export declare interface NumberSettingControl {
2813
4386
  type: "Number";
2814
4387
  interpolable: boolean;
@@ -2817,6 +4390,11 @@ export declare interface NumberSettingControl {
2817
4390
  value: number;
2818
4391
  }
2819
4392
 
4393
+ /**
4394
+ * Open-V arrowhead tick — two lines from the tip to the wing points, no base.
4395
+ */
4396
+ export declare const OpenArrowTick: LineTickBuilder;
4397
+
2820
4398
  /**
2821
4399
  * A {@link NavigationMode} that allows 3D navigation and panning like in many 3D and CAD softwares.
2822
4400
  */
@@ -3027,6 +4605,9 @@ export declare class Raycasters extends Component implements Disposable_2 {
3027
4605
  dispose(): void;
3028
4606
  }
3029
4607
 
4608
+ /** Rectangular enclosure — a plain axis-aligned rectangle centred on `center`. */
4609
+ export declare const RectEnclosure: EnclosureBuilder;
4610
+
3030
4611
  /**
3031
4612
  * Configuration options for removing items from a classifier.
3032
4613
  */
@@ -3591,7 +5172,7 @@ export declare class SimpleRaycaster implements Disposable_2 {
3591
5172
  * @param items - The meshes to query. If not provided, it will query all the meshes stored in {@link World.meshes}.
3592
5173
  * @returns The first intersection found or `null` if no intersection was found.
3593
5174
  */
3594
- castRayFromVector(origin: THREE.Vector3, direction: THREE.Vector3, items?: THREE.Mesh<THREE.BufferGeometry<THREE.NormalBufferAttributes>, THREE.Material | THREE.Material[], THREE.Object3DEventMap>[]): THREE.Intersection<THREE.Object3D<THREE.Object3DEventMap>> | null;
5175
+ castRayFromVector(origin: THREE.Vector3, direction: THREE.Vector3, items?: THREE.Mesh<THREE.BufferGeometry<THREE.NormalBufferAttributes, THREE.BufferGeometryEventMap>, THREE.Material | THREE.Material[], THREE.Object3DEventMap>[]): THREE.Intersection<THREE.Object3D<THREE.Object3DEventMap>> | null;
3595
5176
  private intersect;
3596
5177
  private filterClippingPlanes;
3597
5178
  }
@@ -3727,7 +5308,7 @@ export declare class SimpleWorld<T extends BaseScene = BaseScene, U extends Base
3727
5308
  /**
3728
5309
  * All the loaded [meshes](https://threejs.org/docs/#api/en/objects/Mesh). These meshes will be taken into account in operations like raycasting.
3729
5310
  */
3730
- readonly meshes: Set<THREE.Mesh<THREE.BufferGeometry<THREE.NormalBufferAttributes>, THREE.Material | THREE.Material[], THREE.Object3DEventMap>>;
5311
+ readonly meshes: Set<THREE.Mesh<THREE.BufferGeometry<THREE.NormalBufferAttributes, THREE.BufferGeometryEventMap>, THREE.Material | THREE.Material[], THREE.Object3DEventMap>>;
3731
5312
  /** {@link Updateable.onAfterUpdate} */
3732
5313
  readonly onAfterUpdate: Event_2<unknown>;
3733
5314
  /** {@link Updateable.onBeforeUpdate} */
@@ -3802,6 +5383,531 @@ export declare class SimpleWorld<T extends BaseScene = BaseScene, U extends Base
3802
5383
  dispose(disposeResources?: boolean): void;
3803
5384
  }
3804
5385
 
5386
+ /** A single committed slope annotation. */
5387
+ export declare interface SlopeAnnotation {
5388
+ /** Unique identifier. */
5389
+ uuid: string;
5390
+ /** Anchor point of the arrow tail in drawing local space. */
5391
+ position: THREE.Vector3;
5392
+ /** Normalised downhill direction in the XZ plane. */
5393
+ direction: THREE.Vector3;
5394
+ /**
5395
+ * Slope ratio: rise / run (e.g. `0.15` for a 15 % slope).
5396
+ * Use {@link formatSlope} to convert to the desired display string.
5397
+ */
5398
+ slope: number;
5399
+ /** Name of the {@link SlopeAnnotationStyle} to use. */
5400
+ style: string;
5401
+ }
5402
+
5403
+ /** Editable fields of {@link SlopeAnnotation} — everything except the `uuid`. */
5404
+ export declare type SlopeAnnotationData = Omit<SlopeAnnotation, "uuid">;
5405
+
5406
+ /** Global drawing system that manages slope annotations across all {@link TechnicalDrawing} instances. */
5407
+ export declare class SlopeAnnotations extends AnnotationSystem<SlopeAnnotationSystem> implements Disposable_2 {
5408
+ enabled: boolean;
5409
+ readonly _item: SlopeAnnotation;
5410
+ /**
5411
+ * Because slope data comes from the 3D model, there is no state machine.
5412
+ * Call {@link add} directly with the computed slope values:
5413
+ * ```ts
5414
+ * slopes.add(drawing, { position, direction, slope, style: "default" });
5415
+ * ```
5416
+ */
5417
+ constructor(components: Components);
5418
+ pickHandle(_drawing: TechnicalDrawing, _ray: THREE.Ray, _threshold?: number): {
5419
+ uuid: string;
5420
+ handle: string;
5421
+ } | null;
5422
+ protected _buildGroup(ann: SlopeAnnotation, style: SlopeAnnotationStyle): THREE.Group;
5423
+ }
5424
+
5425
+ /** Visual appearance of a slope annotation. */
5426
+ export declare interface SlopeAnnotationStyle extends BaseAnnotationStyle {
5427
+ /** Tick mark builder at the downhill tip of the arrow. */
5428
+ lineTick: LineTickBuilder;
5429
+ /** Optional filled tick mark builder at the downhill tip. */
5430
+ meshTick?: MeshTickBuilder;
5431
+ /** Tick size in drawing local units. */
5432
+ tickSize: number;
5433
+ /** Length of the arrow shaft in drawing local units. */
5434
+ length: number;
5435
+ /**
5436
+ * Distance from the arrow midpoint to the near edge of the text label,
5437
+ * measured perpendicularly to the slope direction.
5438
+ */
5439
+ textOffset: number;
5440
+ /** How the slope ratio is formatted in the text label. */
5441
+ format: SlopeFormat;
5442
+ }
5443
+
5444
+ declare interface SlopeAnnotationSystem {
5445
+ item: SlopeAnnotation;
5446
+ data: SlopeAnnotationData;
5447
+ style: SlopeAnnotationStyle;
5448
+ handle: string;
5449
+ }
5450
+
5451
+ /** How the slope value is displayed in the text label. */
5452
+ export declare type SlopeFormat = "percentage" | "ratio" | "degrees";
5453
+
5454
+ /** A single technical drawing — the core spatial aggregate. */
5455
+ export declare class TechnicalDrawing {
5456
+ /** Unique identifier for this drawing instance. */
5457
+ readonly uuid: string;
5458
+ private readonly _raycaster;
5459
+ private readonly _components;
5460
+ /**
5461
+ * Brings together:
5462
+ * - A {@link three} (`THREE.Group`) that anchors the drawing in world space.
5463
+ * All 2D geometry (projection lines, dimensions) must be added as children of
5464
+ * this group so they inherit its world transform.
5465
+ * - A collection of {@link viewports}, each defining an orthographic framing
5466
+ * window and owning a camera that is itself a child of the container.
5467
+ *
5468
+ * Moving or rotating the container repositions the entire drawing — including
5469
+ * all its viewport cameras — in the 3D world without affecting any local
5470
+ * coordinates.
5471
+ *
5472
+ * ---
5473
+ *
5474
+ * ### Rotation convention
5475
+ *
5476
+ * The drawing projects geometry along its **local −Y axis**. The drawing
5477
+ * plane is the local **XZ plane** (Y = 0).
5478
+ *
5479
+ * When rotating `drawing.three`, two constraints must hold at the same time:
5480
+ *
5481
+ * 1. **Projection direction** — local −Y must point toward the surface you
5482
+ * want to capture.
5483
+ * 2. **Text orientation** — local +X must point toward the right side of the
5484
+ * screen when the drawing is viewed from the projection direction.
5485
+ * Violating this causes annotations and dimension text to appear mirrored.
5486
+ *
5487
+ * For the six standard orthographic views, use {@link orientTo} — it enforces
5488
+ * both constraints with a single call:
5489
+ *
5490
+ * ```ts
5491
+ * drawing.orientTo(new THREE.Vector3(0, -1, 0)); // top / plan
5492
+ * drawing.orientTo(new THREE.Vector3(0, 0, -1)); // front elevation
5493
+ * ```
5494
+ *
5495
+ * ---
5496
+ *
5497
+ * Typically created via {@link TechnicalDrawings.create}.
5498
+ */
5499
+ constructor(components: Components);
5500
+ /**
5501
+ * The world that hosts this drawing. Set automatically by
5502
+ * {@link TechnicalDrawings.create} — do not assign manually unless you are
5503
+ * managing the drawing's scene integration yourself.
5504
+ */
5505
+ world: World | null;
5506
+ /**
5507
+ * Root Three.js group for all 2D content belonging to this drawing.
5508
+ * All geometry (projection lines, dimensions) must be added as children so
5509
+ * they inherit its world transform.
5510
+ */
5511
+ readonly three: THREE.Group<THREE.Object3DEventMap>;
5512
+ /**
5513
+ * Typed access to all annotation data stored on this drawing.
5514
+ *
5515
+ * ```ts
5516
+ * const dims = techDrawings.use(OBC.LinearAnnotations);
5517
+ * const data = drawing.annotations.getBySystem(dims);
5518
+ * // DataMap<annotationUuid, LinearAnnotation>
5519
+ * ```
5520
+ */
5521
+ readonly annotations: DrawingAnnotations;
5522
+ /**
5523
+ * Layer manager for this drawing.
5524
+ * Use it to create layers, set colors, control visibility, and subscribe to
5525
+ * lifecycle events for reactive UI.
5526
+ *
5527
+ * ```ts
5528
+ * drawing.layers.create("walls", { color: 0x333333 });
5529
+ * drawing.layers.setColor("walls", 0x888888);
5530
+ * drawing.layers.setVisibility("walls", false);
5531
+ * ```
5532
+ */
5533
+ readonly layers: DrawingLayers;
5534
+ /**
5535
+ * Name of the layer new annotations will be assigned to when added via any
5536
+ * drawing system. Must be a layer registered via {@link DrawingLayers.create}.
5537
+ * Defaults to `"0"`.
5538
+ */
5539
+ activeLayer: string;
5540
+ /**
5541
+ * Depth of the projection capture volume, in world units, measured from the
5542
+ * drawing plane along the local -Y axis (the projection direction).
5543
+ *
5544
+ * Used by {@link TechnicalDrawingHelper} to visualise the volume, and by
5545
+ * `addProjectionFromItems` to set the far clipping plane of the
5546
+ * {@link EdgeProjector} automatically.
5547
+ *
5548
+ * Defaults to `10`.
5549
+ */
5550
+ far: number;
5551
+ /** All viewports registered on this drawing, keyed by their UUID. */
5552
+ readonly viewports: DrawingViewports;
5553
+ /** {@link Disposable.onDisposed} */
5554
+ readonly onDisposed: Event_2<void>;
5555
+ /**
5556
+ * Intersects a pre-built ray against all layer-1 `LineSegments` in this drawing.
5557
+ *
5558
+ * The caller is responsible for building the ray (via `THREE.Raycaster.setFromCamera`
5559
+ * or any other method) so this method stays agnostic to which camera or canvas
5560
+ * the pick originated from.
5561
+ *
5562
+ * The returned {@link DrawingIntersection.point} is in drawing **local space**
5563
+ * (XZ plane, Y = 0), ready to use for dimension creation or snapping.
5564
+ *
5565
+ * @param ray - World-space ray to cast.
5566
+ * @param viewport - The viewport the ray was built from, if any. Pass `null`
5567
+ * when picking from the 3D world camera.
5568
+ * @returns The closest intersection, or `null` if nothing was hit.
5569
+ */
5570
+ raycast(ray: THREE.Ray, viewport?: DrawingViewport | null): DrawingIntersection | null;
5571
+ /**
5572
+ * Aligns this drawing to a target plane in 3D world space using three
5573
+ * point correspondences.
5574
+ *
5575
+ * Pass three points picked on the drawing (in drawing local space) and
5576
+ * three corresponding points picked on the 3D model (in world space).
5577
+ * The drawing's container will be repositioned, rotated, and uniformly
5578
+ * scaled so that the drawing points map to their world counterparts.
5579
+ *
5580
+ * @throws If either set of points is collinear or degenerate — see
5581
+ * {@link computeAlignmentMatrix} for details.
5582
+ *
5583
+ * @param drawingPoints - Three non-collinear points in drawing local space.
5584
+ * @param worldPoints - Three corresponding points in world space.
5585
+ */
5586
+ alignTo(drawingPoints: THREE.Vector3[], worldPoints: THREE.Vector3[]): void;
5587
+ /**
5588
+ * Projects a `THREE.LineSegments` from any world-space position onto the
5589
+ * given drawing's local XZ plane (Y = 0), returning a new `THREE.LineSegments`
5590
+ * ready to be added to {@link container}.
5591
+ *
5592
+ * Vertex coordinates are transformed from the input object's local space →
5593
+ * world space → drawing local space, then Y is zeroed. The input object is
5594
+ * not modified.
5595
+ *
5596
+ * ```ts
5597
+ * const projected = TechnicalDrawing.toDrawingSpace(myIFCLines, drawing);
5598
+ * drawing.three.add(projected);
5599
+ * ```
5600
+ *
5601
+ * @param ls - Source `LineSegments` to project. Its world matrix must be
5602
+ * up-to-date (call `updateWorldMatrix(true, false)` if unsure).
5603
+ * @param drawing - Target drawing whose local XZ plane is used as destination.
5604
+ * @returns A new `LineSegments` with the projected geometry in drawing local
5605
+ * space. No material is assigned — set one before rendering.
5606
+ */
5607
+ static toDrawingSpace(ls: THREE.LineSegments, drawing: TechnicalDrawing): THREE.LineSegments;
5608
+ /**
5609
+ * Adds a `THREE.LineSegments` to this drawing's {@link container} and
5610
+ * automatically computes a BVH on its geometry so that {@link raycast} can
5611
+ * pick individual line segments efficiently.
5612
+ *
5613
+ * Use this instead of `drawing.three.add()` whenever the geometry will
5614
+ * participate in picking. Plain `container.add()` still works for rendering,
5615
+ * but without BVH the raycast falls back to a brute-force O(n) test on every
5616
+ * segment — noticeably slow for dense projections.
5617
+ *
5618
+ * The layer assignment and Three.js rendering-layer setup (layer 1) are handled
5619
+ * internally — the caller does not need to touch `userData` or `ls.layers`.
5620
+ * If the named layer has a color defined, it is applied to the material immediately.
5621
+ *
5622
+ * ```ts
5623
+ * drawing.layers.create("walls", { color: 0x333333 });
5624
+ * drawing.addProjectionLines(wallLines, "walls");
5625
+ * ```
5626
+ *
5627
+ * @param ls - The `LineSegments` to add.
5628
+ * @param layer - Layer name to assign. Defaults to `"0"`. If the layer does not
5629
+ * exist, a warning is logged and the lines fall back to `"0"`.
5630
+ * @returns The same `LineSegments` instance, for chaining.
5631
+ */
5632
+ addProjectionLines(ls: THREE.LineSegments, layer?: string): THREE.LineSegments;
5633
+ /**
5634
+ * Projects the visible and hidden edges of the given BIM model items onto
5635
+ * this drawing using {@link EdgeProjector}.
5636
+ *
5637
+ * The projection direction is inferred from the drawing's current world
5638
+ * orientation (local `-Y` axis). The capture volume extends from the drawing
5639
+ * plane by {@link far} world units along that direction. Items outside the
5640
+ * volume are excluded automatically.
5641
+ *
5642
+ * Both layer names must already exist on this drawing before calling this
5643
+ * method — create them with {@link DrawingLayers.create} beforehand.
5644
+ *
5645
+ * ```ts
5646
+ * drawing.layers.create("visible", { material: new THREE.LineBasicMaterial({ color: 0x000000 }) });
5647
+ * drawing.layers.create("hidden", { material: new THREE.LineDashedMaterial({ color: 0x888888, dashSize: 0.2, gapSize: 0.1 }) });
5648
+ *
5649
+ * await drawing.addProjectionFromItems(modelIdMap, {
5650
+ * layers: { visible: "visible", hidden: "hidden" },
5651
+ * onProgress: (msg, pct) => console.log(msg, pct),
5652
+ * });
5653
+ * ```
5654
+ *
5655
+ * @param modelIdMap - Items to project, keyed by model ID.
5656
+ * @param config - Required layer names and optional progress callback.
5657
+ */
5658
+ addProjectionFromItems(modelIdMap: ModelIdMap, config: {
5659
+ layers: {
5660
+ visible: string;
5661
+ hidden: string;
5662
+ };
5663
+ onProgress?: (message: string, progress?: number) => void;
5664
+ }): Promise<void>;
5665
+ /**
5666
+ * Orients the drawing to one of the six standard orthographic projection
5667
+ * directions.
5668
+ *
5669
+ * Pass any of the six axis-aligned unit vectors. The method sets
5670
+ * `drawing.three.quaternion` to the correct rotation so that:
5671
+ * - The drawing's local **−Y** axis aligns with `direction`.
5672
+ * - The drawing's local **+X** axis points toward the right side of the
5673
+ * screen when the drawing is viewed from that direction, ensuring
5674
+ * annotations and text render without mirroring.
5675
+ *
5676
+ * ```ts
5677
+ * drawing.orientTo(new THREE.Vector3(0, -1, 0)); // top / plan
5678
+ * drawing.orientTo(new THREE.Vector3(0, 1, 0)); // bottom / RCP
5679
+ * drawing.orientTo(new THREE.Vector3(0, 0, -1)); // front elevation
5680
+ * drawing.orientTo(new THREE.Vector3(0, 0, 1)); // back elevation
5681
+ * drawing.orientTo(new THREE.Vector3(-1, 0, 0)); // right elevation
5682
+ * drawing.orientTo(new THREE.Vector3(1, 0, 0)); // left elevation
5683
+ * ```
5684
+ *
5685
+ * A console warning is emitted if `direction` does not match any of the six
5686
+ * standard axes.
5687
+ *
5688
+ * @param direction - Desired projection direction (need not be pre-normalized).
5689
+ */
5690
+ orientTo(direction: THREE.Vector3): void;
5691
+ /** Disposes all viewports, layers, annotations and removes the container (and all its Three.js geometry) from memory. */
5692
+ dispose(): void;
5693
+ }
5694
+
5695
+ /** Visualises a {@link TechnicalDrawing}'s projection volume in the 3D scene and exposes three gizmo anchors for interactive control. */
5696
+ export declare class TechnicalDrawingHelper extends THREE.Group {
5697
+ private readonly _drawing;
5698
+ private readonly _topFrame;
5699
+ private readonly _pillars;
5700
+ private readonly _bottomFrame;
5701
+ private readonly _topPlane;
5702
+ private readonly _bottomPlane;
5703
+ private readonly _frameMat;
5704
+ private readonly _depthMat;
5705
+ private readonly _planeMat;
5706
+ private static readonly _FRAME_COLOR;
5707
+ private static readonly _DEPTH_COLOR;
5708
+ /**
5709
+ * Width of the drawing frame indicator along the local X axis, in world
5710
+ * units. Call {@link update} after changing this value programmatically.
5711
+ */
5712
+ width: number;
5713
+ /**
5714
+ * Height of the drawing frame indicator along the local Z axis, in world
5715
+ * units. Call {@link update} after changing this value programmatically.
5716
+ */
5717
+ height: number;
5718
+ /**
5719
+ * Gizmo anchor positioned at the centre of the bottom frame.
5720
+ * Pass a `TransformControls` instance to {@link attachFarGizmo} — do not
5721
+ * manipulate this object's position directly.
5722
+ */
5723
+ readonly farHandle: THREE.Object3D<THREE.Object3DEventMap>;
5724
+ /**
5725
+ * Gizmo anchor positioned at the right-edge midpoint of the top frame.
5726
+ * Pass a `TransformControls` instance to {@link attachWidthGizmo} — do not
5727
+ * manipulate this object's position directly.
5728
+ */
5729
+ readonly widthHandle: THREE.Object3D<THREE.Object3DEventMap>;
5730
+ /**
5731
+ * Gizmo anchor positioned at the bottom-edge midpoint of the top frame.
5732
+ * Pass a `TransformControls` instance to {@link attachHeightGizmo} — do not
5733
+ * manipulate this object's position directly.
5734
+ */
5735
+ readonly heightHandle: THREE.Object3D<THREE.Object3DEventMap>;
5736
+ /**
5737
+ * Works exactly like the built-in Three.js helpers (e.g. `THREE.CameraHelper`):
5738
+ * add it as a child of `drawing.three` so it inherits the drawing's world
5739
+ * transform automatically.
5740
+ *
5741
+ * It renders on **layer 0** — visible to the perspective camera, invisible to
5742
+ * the drawing's orthographic cameras (which only render layer 1).
5743
+ *
5744
+ * The helper draws three things:
5745
+ * - A rectangular frame on the drawing plane (Y = 0 in drawing local space).
5746
+ * - Four pillar lines dropping from each corner along the projection direction
5747
+ * (local −Y) to the far boundary.
5748
+ * - A matching rectangle at the far boundary.
5749
+ *
5750
+ * ### Interactive control via gizmos
5751
+ *
5752
+ * Three `THREE.Object3D` anchors are exposed for `TransformControls`:
5753
+ *
5754
+ * | Anchor | Controls | Constrained axis |
5755
+ * |---|---|---|
5756
+ * | {@link farHandle} | `drawing.far` | local Y |
5757
+ * | {@link widthHandle} | {@link width} (symmetric) | local X |
5758
+ * | {@link heightHandle} | {@link height} (symmetric) | local Z |
5759
+ *
5760
+ * Use the corresponding `attach*Gizmo` methods instead of configuring the
5761
+ * gizmos manually — they enforce the correct axis constraints, local space,
5762
+ * and change listeners automatically:
5763
+ *
5764
+ * ```ts
5765
+ * const helper = new TechnicalDrawingHelper(drawing);
5766
+ * helper.width = 20;
5767
+ * helper.height = 15;
5768
+ * drawing.three.add(helper);
5769
+ *
5770
+ * // Main gizmo — full translate + rotate on drawing.three
5771
+ * const mainGizmo = new TransformControls(camera, domElement);
5772
+ * mainGizmo.attach(drawing.three);
5773
+ * scene.add(mainGizmo);
5774
+ *
5775
+ * // Depth gizmo — controls drawing.far
5776
+ * const farGizmo = new TransformControls(camera, domElement);
5777
+ * scene.add(farGizmo);
5778
+ * helper.attachFarGizmo(farGizmo);
5779
+ *
5780
+ * // Width gizmo
5781
+ * const widthGizmo = new TransformControls(camera, domElement);
5782
+ * scene.add(widthGizmo);
5783
+ * helper.attachWidthGizmo(widthGizmo);
5784
+ *
5785
+ * // Height gizmo
5786
+ * const heightGizmo = new TransformControls(camera, domElement);
5787
+ * scene.add(heightGizmo);
5788
+ * helper.attachHeightGizmo(heightGizmo);
5789
+ * ```
5790
+ *
5791
+ * Call {@link update} after changing {@link width}, {@link height}, or
5792
+ * `drawing.far` programmatically to rebuild the geometry.
5793
+ */
5794
+ constructor(drawing: DrawingProjectionSource);
5795
+ /**
5796
+ * Rebuilds the helper geometry and repositions all gizmo anchors to match
5797
+ * the current {@link width}, {@link height}, and `drawing.far`. Call this
5798
+ * whenever any of those values change programmatically.
5799
+ */
5800
+ update(): void;
5801
+ /**
5802
+ * Configures a `TransformControls` instance to control `drawing.far` and
5803
+ * attaches it to the {@link farHandle}.
5804
+ *
5805
+ * The gizmo is constrained to the drawing's local Y axis (the projection
5806
+ * direction) and wired to update `drawing.far` on every change. Call this
5807
+ * once — calling it again on the same gizmo accumulates listeners.
5808
+ *
5809
+ * @param gizmo - A `TransformControls` instance (or any {@link AxisGizmoLike}).
5810
+ */
5811
+ attachFarGizmo(gizmo: AxisGizmoLike): void;
5812
+ /**
5813
+ * Configures a `TransformControls` instance to control {@link width} and
5814
+ * attaches it to the {@link widthHandle}.
5815
+ *
5816
+ * The gizmo is constrained to the drawing's local X axis. Width grows
5817
+ * symmetrically — dragging the right-edge handle outward expands both sides.
5818
+ *
5819
+ * @param gizmo - A `TransformControls` instance (or any {@link AxisGizmoLike}).
5820
+ */
5821
+ attachWidthGizmo(gizmo: AxisGizmoLike): void;
5822
+ /**
5823
+ * Configures a `TransformControls` instance to control {@link height} and
5824
+ * attaches it to the {@link heightHandle}.
5825
+ *
5826
+ * The gizmo is constrained to the drawing's local Z axis. Height grows
5827
+ * symmetrically — dragging the bottom-edge handle outward expands both sides.
5828
+ *
5829
+ * @param gizmo - A `TransformControls` instance (or any {@link AxisGizmoLike}).
5830
+ */
5831
+ attachHeightGizmo(gizmo: AxisGizmoLike): void;
5832
+ /** Releases all Three.js geometry and material resources. */
5833
+ dispose(): void;
5834
+ }
5835
+
5836
+ /** OBC Component that creates and manages {@link TechnicalDrawing} instances. */
5837
+ export declare class TechnicalDrawings extends Component implements Disposable_2 {
5838
+ /**
5839
+ * A unique identifier for the component.
5840
+ * This UUID is used to register the component within the Components system.
5841
+ */
5842
+ static readonly uuid: "5c7d3b9a-4e8f-4a2b-9c1d-0e3f2a5b7c8d";
5843
+ /** {@link Component.enabled} */
5844
+ enabled: boolean;
5845
+ /** All active drawings, keyed by their UUID. */
5846
+ readonly list: FRAGS.DataMap<string, TechnicalDrawing>;
5847
+ /**
5848
+ * Global system instances keyed by their constructor.
5849
+ * Register a system with {@link use}; inspect or iterate here for UI purposes.
5850
+ */
5851
+ readonly systems: FRAGS.DataMap<Function, AnnotationSystem<any>>;
5852
+ /** {@link Disposable.onDisposed} */
5853
+ readonly onDisposed: Event_2<unknown>;
5854
+ /**
5855
+ * A TechnicalDrawing is a 2D drawing plane that lives in 3D world space.
5856
+ * It contains projection lines and dimension annotations (layer 1 geometry)
5857
+ * framed by one or more orthographic {@link DrawingViewport}s.
5858
+ *
5859
+ * The drawing's `container` (a `THREE.Group`) can be freely transformed in the
5860
+ * 3D world — all viewports and geometry move together as a single unit.
5861
+ *
5862
+ * @example
5863
+ * ```ts
5864
+ * const techDrawings = components.get(TechnicalDrawings);
5865
+ * const drawing = techDrawings.create(world);
5866
+ *
5867
+ * // Add layer-1 geometry to the drawing
5868
+ * const lines = new THREE.LineSegments(geometry, material);
5869
+ * lines.layers.set(1);
5870
+ * drawing.three.add(lines);
5871
+ *
5872
+ * // Add viewports
5873
+ * const vp = drawing.viewports.create({ left: -1, right: 5, top: 1, bottom: -4 });
5874
+ * ```
5875
+ */
5876
+ constructor(components: Components);
5877
+ /**
5878
+ * Returns the global singleton instance of the given system, creating it if it
5879
+ * does not yet exist. The system constructor must accept `Components` as its
5880
+ * only argument (new-style global systems). Safe to call multiple times — always
5881
+ * returns the same instance.
5882
+ *
5883
+ * ```ts
5884
+ * const dims = techDrawings.use(OBC.LinearAnnotations);
5885
+ * dims.styles.set("default", { ... });
5886
+ * ```
5887
+ */
5888
+ use<T extends AnnotationSystem<any>>(SystemClass: new (components: Components) => T): T;
5889
+ /**
5890
+ * Creates a new {@link TechnicalDrawing} hosted in the given world.
5891
+ *
5892
+ * The drawing's Three.js group is added to the world's scene and its
5893
+ * lifecycle is tied to the world — it is automatically removed when the
5894
+ * world is disposed. Three.js rendering layer 1 is enabled on the world
5895
+ * camera so that annotation geometry is visible in the 3D view. Both
5896
+ * perspective and orthographic cameras are configured when using
5897
+ * {@link OrthoPerspectiveCamera}.
5898
+ *
5899
+ * To hide the drawing from the 3D view without removing it from the world,
5900
+ * either set `drawing.three.visible = false` or disable layer 1 on the
5901
+ * world camera: `world.camera.three.layers.disable(1)`.
5902
+ *
5903
+ * @param world - The world that will host this drawing.
5904
+ * @returns The newly created drawing.
5905
+ */
5906
+ create(world: World): TechnicalDrawing;
5907
+ /** {@link Disposable.dispose} */
5908
+ dispose(): void;
5909
+ }
5910
+
3805
5911
  export declare interface TextSetSettingControl {
3806
5912
  type: "TextSet";
3807
5913
  value: Set<string>;
@@ -3938,6 +6044,51 @@ export declare class Topic implements BCFTopic {
3938
6044
  serialize(): string;
3939
6045
  }
3940
6046
 
6047
+ /**
6048
+ * Whether this component manages its interaction through an explicit state machine.
6049
+ * @template TState - Discriminated union of all valid states (each with a `kind` string).
6050
+ * @template TEvent - Discriminated union of all accepted events (each with a `type` string).
6051
+ */
6052
+ export declare interface Transitionable<TState extends {
6053
+ kind: string;
6054
+ }, TEvent extends {
6055
+ type: string;
6056
+ }> {
6057
+ /** The current state. TypeScript guarantees it is always a valid, well-typed state. */
6058
+ readonly machineState: TState;
6059
+ /**
6060
+ * Dispatches an event to the machine, producing a deterministic state transition.
6061
+ * Events that do not apply to the current state are silently ignored.
6062
+ */
6063
+ sendMachineEvent(event: TEvent): void;
6064
+ /** Fired synchronously after every state transition with the new state as payload. */
6065
+ readonly onMachineStateChanged: Event_2<TState>;
6066
+ }
6067
+
6068
+ /** Built-in {@link DimensionUnit} presets. */
6069
+ export declare const Units: {
6070
+ readonly m: {
6071
+ readonly factor: 1;
6072
+ readonly suffix: "m";
6073
+ };
6074
+ readonly cm: {
6075
+ readonly factor: 100;
6076
+ readonly suffix: "cm";
6077
+ };
6078
+ readonly mm: {
6079
+ readonly factor: 1000;
6080
+ readonly suffix: "mm";
6081
+ };
6082
+ readonly ft: {
6083
+ readonly factor: 3.28084;
6084
+ readonly suffix: "ft";
6085
+ };
6086
+ readonly in: {
6087
+ readonly factor: 39.3701;
6088
+ readonly suffix: "in";
6089
+ };
6090
+ };
6091
+
3941
6092
  /** Whether this component should be updated each frame. */
3942
6093
  export declare interface Updateable {
3943
6094
  /** Actions that should be executed after updating the component. */
@@ -4609,6 +6760,18 @@ export declare interface ViewpointVisibility {
4609
6760
  };
4610
6761
  }
4611
6762
 
6763
+ /**
6764
+ * Minimal interface consumed by {@link DrawingViewportHelper}.
6765
+ * Satisfied by {@link DrawingViewport} without a direct import, which keeps
6766
+ * the two classes free of circular dependencies.
6767
+ */
6768
+ declare interface ViewportBoundsController {
6769
+ left: number;
6770
+ right: number;
6771
+ top: number;
6772
+ bottom: number;
6773
+ }
6774
+
4612
6775
  /**
4613
6776
  * The `Views` class is responsible for managing and interacting with a collection of 2D sections. It provides methods for creating, opening, closing, and managing views, as well as generating views from specific configurations such as IFC storeys or bounding boxes. 📕 [Tutorial](https://docs.thatopen.com/Tutorials/Components/Core/Views). 📘 [API](https://docs.thatopen.com/api/@thatopen/components/classes/Views).
4614
6777
  */