-
Notifications
You must be signed in to change notification settings - Fork 210
/
ModelGeometryChanges.ts
169 lines (151 loc) · 6.95 KB
/
ModelGeometryChanges.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
* @module Geometry
*/
import { assert, CompressedId64Set, DbOpcode, GuidString, Id64String } from "@itwin/core-bentley";
import { Range3d, Range3dProps } from "@itwin/core-geometry";
/** Compact wire format representing geometric changes to a set of elements as part of a [[ModelGeometryChangesProps]].
* All of the elements belong to the same model.
* The number of [[ids]] and [[ranges]] are guaranteed to be the same.
* @see [[ElementGeometryChange]] for a more useful representation of an individual element change.
* @see [[ModelGeometryChanges.iterable]] to iterate over [[ElementGeometryChange]]s.
* @public
* @extensions
*/
export interface ElementIdsAndRangesProps {
/** The Ids of the elements, compressed and sorted in ascending order. */
readonly ids: CompressedId64Set;
/** The range of each element, indexed by the position of the corresponding element's Id in [[ids]]. */
readonly ranges: Range3dProps[];
}
/** Compact wire format representing geometric changes to [GeometricElement]($backend)s within a [GeometricModel]($backend).
* A given element Id will appear in no more than one of [[inserted]], [[updated]], or [[deleted]].
* @see [[ModelGeometryChanges]] for a more useful representation.
* @public
* @extensions
*/
export interface ModelGeometryChangesProps {
/** The Id of the model. */
readonly id: Id64String;
/** The range of the model, computed as the union of the ranges of all geometric elements within the model. */
readonly range: Range3dProps;
/** The geometry GUID of the model. */
readonly guid: GuidString;
/** If defined, the Ids and ranges of newly-inserted [GeometricElement]($backend)s. */
readonly inserted?: ElementIdsAndRangesProps;
/** If defined, the Ids and ranges of [GeometricElement]($backend)s whose geometric properties were modified. */
readonly updated?: ElementIdsAndRangesProps;
/** If defined, the Ids of deleted [GeometricElement]($backend)s. */
readonly deleted?: CompressedId64Set;
}
/** Represents the insertion of a new [GeometricElement]($backend), or a change to the geometric properties of an existing [GeometricElement]($backend).
* @see [[ElementGeometryChange]].
* @public
* @extensions
*/
export interface ExtantElementGeometryChange {
/** Indicates whether this change resulted from the insertion of a new element or modification of an existing one.
* Used as discriminant for [[ElementGeometryChange]] union.
*/
readonly type: DbOpcode.Insert | DbOpcode.Update;
/** The element's Id. */
readonly id: Id64String;
/** The element's range. */
readonly range: Range3d;
}
/** Represents the deletion of a [GeometricElement]($backend).
* @see [[ElementGeometryChange]].
* @public
* @extensions
*/
export interface DeletedElementGeometryChange {
/** Discriminant for [[ElementGeometryChange]] union. */
readonly type: DbOpcode.Delete;
/** The element's Id. */
readonly id: Id64String;
}
/**
* @public
* @extensions
*/
export type ElementGeometryChange = ExtantElementGeometryChange | DeletedElementGeometryChange;
/** Represents a change to the geometry of a [GeometricElement]($backend), as exposed by [[ModelGeometryChanges.elements]].
* @public
*/
export namespace ElementGeometryChange { // eslint-disable-line @typescript-eslint/no-redeclare
function* extantIterator(props: ElementIdsAndRangesProps, type: DbOpcode.Insert | DbOpcode.Update): Iterator<ElementGeometryChange> {
let index = 0;
const ids = CompressedId64Set.iterable(props.ids);
for (const id of ids) {
assert(undefined !== props.ranges[index]);
const range = Range3d.fromJSON(props.ranges[index]);
index++;
yield { type, id, range };
}
}
function extantIterable(props: ElementIdsAndRangesProps, type: DbOpcode.Insert | DbOpcode.Update): Iterable<ElementGeometryChange> {
return { [Symbol.iterator]: () => extantIterator(props, type) };
}
/** Obtain an iterator over the geometry changes for a single [GeometricModel]($backend). A given element will appear at most once. */
export function* iterator(modelChanges: ModelGeometryChangesProps): Iterator<ElementGeometryChange> {
if (modelChanges.inserted)
yield* extantIterable(modelChanges.inserted, DbOpcode.Insert);
if (modelChanges.updated)
yield* extantIterable(modelChanges.updated, DbOpcode.Update);
if (modelChanges.deleted)
for (const id of CompressedId64Set.iterable(modelChanges.deleted))
yield { type: DbOpcode.Delete, id };
}
/** Obtain an iterable over the geometry changes for a single [GeometricModel]($backend). A given element will appear at most once. */
export function iterable(modelChanges: ModelGeometryChangesProps): Iterable<ElementGeometryChange> {
return { [Symbol.iterator]: () => iterator(modelChanges) };
}
}
/** Represents geometric changes to a set of [GeometricElement]($backend)s belonging to a single [GeometricModel]($backend).
* @public
* @extensions
*/
export interface ModelGeometryChanges {
/** The model's Id. */
readonly id: Id64String;
/** The model's geometry GUID. */
readonly geometryGuid: GuidString;
/** The model's range. */
readonly range: Range3d;
/** The individual geometric element changes. */
readonly elements: Iterable<ElementGeometryChange>;
}
/** Represents geometric changes to a set of [GeometricElement]($backend)s belonging to a single [GeometricModel]($backend).
* @see [GraphicalEditingScope]($frontend) to monitor these changes.
* @public
*/
export namespace ModelGeometryChanges {
/** Obtain an iterator over the geometry changes for a set of models. A given model will appear at most once. */
export function* iterator(modelChanges: ModelGeometryChangesProps[]): Iterator<ModelGeometryChanges> {
for (const props of modelChanges)
yield fromJSON(props);
}
/** Obtain an iterable over the geometry changes for a set of models. A given model will appear at most once. */
export function iterable(modelChanges: ModelGeometryChangesProps[]): Iterable<ModelGeometryChanges> {
return { [Symbol.iterator]: () => iterator(modelChanges) };
}
/** Instantiate from wire format. */
export function fromJSON(props: ModelGeometryChangesProps): ModelGeometryChanges {
return {
id: props.id,
geometryGuid: props.guid,
range: Range3d.fromJSON(props.range),
elements: ElementGeometryChange.iterable(props),
};
}
/** Obtain the ModelGeometryChanges for the specified model Id. */
export function findByModelId(changes: Iterable<ModelGeometryChanges>, modelId: Id64String): ModelGeometryChanges | undefined {
for (const change of changes)
if (change.id === modelId)
return change;
return undefined;
}
}