@buerli.io/core 0.1.0 → 0.2.1-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,7 +12,10 @@ export declare class ThreeGeometryCreator {
12
12
  container: {
13
13
  id: number;
14
14
  ownerId: number;
15
+ type: GraphicType.NONE | GraphicType.BREP | GraphicType.POLYBREP | GraphicType.CURVEARRAY;
15
16
  };
17
+ operationId: any;
18
+ rawGraphic: IGraphicElement | null;
16
19
  };
17
20
  createGeometry(container: IGraphicContainer, color?: number[]): ContainerGeometryT;
18
21
  createSurface(mesh: IGraphicMesh, container: IGraphicContainer, color?: number[]): {
@@ -22,7 +25,10 @@ export declare class ThreeGeometryCreator {
22
25
  container: {
23
26
  id: number;
24
27
  ownerId: number;
28
+ type: GraphicType.NONE | GraphicType.BREP | GraphicType.POLYBREP | GraphicType.CURVEARRAY;
25
29
  };
30
+ operationId: any;
31
+ rawGraphic: IGraphicElement | null;
26
32
  isValid: boolean;
27
33
  geometry: THREE.BufferGeometry;
28
34
  graphicId: number;
@@ -36,7 +42,10 @@ export declare class ThreeGeometryCreator {
36
42
  container: {
37
43
  id: number;
38
44
  ownerId: number;
45
+ type: GraphicType.NONE | GraphicType.BREP | GraphicType.POLYBREP | GraphicType.CURVEARRAY;
39
46
  };
47
+ operationId: any;
48
+ rawGraphic: IGraphicElement | null;
40
49
  isValid: boolean;
41
50
  geometry: THREE.BufferGeometry;
42
51
  graphicId: number;
@@ -53,7 +62,10 @@ export declare class ThreeGeometryCreator {
53
62
  container: {
54
63
  id: number;
55
64
  ownerId: number;
65
+ type: GraphicType.NONE | GraphicType.BREP | GraphicType.POLYBREP | GraphicType.CURVEARRAY;
56
66
  };
67
+ operationId: any;
68
+ rawGraphic: IGraphicElement | null;
57
69
  isValid: boolean;
58
70
  geometry: THREE.BufferGeometry;
59
71
  graphicId: number;
@@ -71,7 +83,10 @@ export declare class ThreeGeometryCreator {
71
83
  container: {
72
84
  id: number;
73
85
  ownerId: number;
86
+ type: GraphicType.NONE | GraphicType.BREP | GraphicType.POLYBREP | GraphicType.CURVEARRAY;
74
87
  };
88
+ operationId: any;
89
+ rawGraphic: IGraphicElement | null;
75
90
  isValid: boolean;
76
91
  geometry: THREE.BufferGeometry;
77
92
  graphicId: number;
@@ -90,7 +105,10 @@ export declare class ThreeGeometryCreator {
90
105
  container: {
91
106
  id: number;
92
107
  ownerId: number;
108
+ type: GraphicType.NONE | GraphicType.BREP | GraphicType.POLYBREP | GraphicType.CURVEARRAY;
93
109
  };
110
+ operationId: any;
111
+ rawGraphic: IGraphicElement | null;
94
112
  isValid: boolean;
95
113
  geometry: THREE.BufferGeometry;
96
114
  graphicId: number;
@@ -105,7 +123,10 @@ export declare class ThreeGeometryCreator {
105
123
  container: {
106
124
  id: number;
107
125
  ownerId: number;
126
+ type: GraphicType.NONE | GraphicType.BREP | GraphicType.POLYBREP | GraphicType.CURVEARRAY;
108
127
  };
128
+ operationId: any;
129
+ rawGraphic: IGraphicElement | null;
109
130
  isValid: boolean;
110
131
  geometry: THREE.BufferGeometry;
111
132
  graphicId: number;
@@ -120,7 +141,10 @@ export declare class ThreeGeometryCreator {
120
141
  container: {
121
142
  id: number;
122
143
  ownerId: number;
144
+ type: GraphicType.NONE | GraphicType.BREP | GraphicType.POLYBREP | GraphicType.CURVEARRAY;
123
145
  };
146
+ operationId: any;
147
+ rawGraphic: IGraphicElement | null;
124
148
  geometry: THREE.BufferGeometry;
125
149
  graphicId: number;
126
150
  type: GraphicType;
@@ -134,7 +158,10 @@ export declare class ThreeGeometryCreator {
134
158
  container: {
135
159
  id: number;
136
160
  ownerId: number;
161
+ type: GraphicType.NONE | GraphicType.BREP | GraphicType.POLYBREP | GraphicType.CURVEARRAY;
137
162
  };
163
+ operationId: any;
164
+ rawGraphic: IGraphicElement | null;
138
165
  geometry: THREE.BufferGeometry;
139
166
  graphicId: number;
140
167
  type: GraphicType;
@@ -150,7 +177,10 @@ export declare class ThreeGeometryCreator {
150
177
  container: {
151
178
  id: number;
152
179
  ownerId: number;
180
+ type: GraphicType.NONE | GraphicType.BREP | GraphicType.POLYBREP | GraphicType.CURVEARRAY;
153
181
  };
182
+ operationId: any;
183
+ rawGraphic: IGraphicElement | null;
154
184
  geometry: THREE.BufferGeometry;
155
185
  graphicId: number;
156
186
  type: GraphicType;
@@ -168,7 +198,10 @@ export declare class ThreeGeometryCreator {
168
198
  container: {
169
199
  id: number;
170
200
  ownerId: number;
201
+ type: GraphicType.NONE | GraphicType.BREP | GraphicType.POLYBREP | GraphicType.CURVEARRAY;
171
202
  };
203
+ operationId: any;
204
+ rawGraphic: IGraphicElement | null;
172
205
  key: string;
173
206
  graphicId: number;
174
207
  type: GraphicType;
@@ -196,6 +229,7 @@ declare type PointKey = string;
196
229
  declare type PointType = 'start' | 'end' | 'center';
197
230
  export declare type ContainerGeometryT = {
198
231
  graphicId: GraphicID;
232
+ type: GraphicType;
199
233
  map: Record<GraphicID, GeometryElement>;
200
234
  meshes: MeshGeometry[];
201
235
  lines: LineGeometry[];
@@ -1,5 +1,20 @@
1
1
  import * as THREE from 'three';
2
- import { GraphicType, } from './../types';
2
+ import { ContainerType, GraphicType, } from './../types';
3
+ const convertType = (contType) => {
4
+ let type = GraphicType.NONE;
5
+ switch (contType) {
6
+ case ContainerType.BREP:
7
+ type = GraphicType.BREP;
8
+ break;
9
+ case ContainerType.CURVEARRAY:
10
+ type = GraphicType.CURVEARRAY;
11
+ break;
12
+ case ContainerType.POLYBREP:
13
+ type = GraphicType.POLYBREP;
14
+ break;
15
+ }
16
+ return type;
17
+ };
3
18
  /**
4
19
  * Creates THREE geometry based on the data within a @see IGraphicContainer.
5
20
  */
@@ -8,6 +23,7 @@ export class ThreeGeometryCreator {
8
23
  this.coordHeightTolerance = 0.01;
9
24
  }
10
25
  getMetadata(geometry, container, color = [0, 0, 0], opacity = 0) {
26
+ var _a;
11
27
  const contProps = container.properties; // container has always properties
12
28
  const geomProps = geometry ? geometry.properties : {};
13
29
  let col = container.properties.material.color || color;
@@ -18,11 +34,18 @@ export class ThreeGeometryCreator {
18
34
  }
19
35
  const rgbColor = new THREE.Color(col[0] / 255, col[1] / 255, col[2] / 255);
20
36
  const layer = geomProps && geomProps.layer ? geomProps.layer : contProps.layer;
21
- return { color: rgbColor, opacity: opa, layer, container: { id: container.id, ownerId: container.owner } };
37
+ return {
38
+ color: rgbColor,
39
+ opacity: opa,
40
+ layer,
41
+ container: { id: container.id, ownerId: container.owner, type: convertType(container.type) },
42
+ operationId: (_a = geometry === null || geometry === void 0 ? void 0 : geometry.properties) === null || _a === void 0 ? void 0 : _a.operationId,
43
+ rawGraphic: geometry,
44
+ };
22
45
  }
23
46
  createGeometry(container, color = [0, 0, 0]) {
24
- const graphicId = container.id;
25
- const { properties } = container;
47
+ const { id: graphicId, properties, type: contType } = container;
48
+ const type = convertType(contType);
26
49
  const box = { min: new THREE.Vector3(...properties.min), max: new THREE.Vector3(...properties.max) };
27
50
  const meshes = [];
28
51
  const lines = [];
@@ -66,6 +89,7 @@ export class ThreeGeometryCreator {
66
89
  }
67
90
  const points = Object.values(pointMap);
68
91
  return Object.assign({ graphicId,
92
+ type,
69
93
  map,
70
94
  meshes,
71
95
  lines,
@@ -135,7 +159,10 @@ export class ThreeGeometryCreator {
135
159
  }
136
160
  createLine(line, container, points, color = [0, 0, 0]) {
137
161
  const graphicId = line.id;
138
- const type = GraphicType.LINE;
162
+ let type = GraphicType.LINE;
163
+ if (container.type === ContainerType.CURVEARRAY) {
164
+ type = GraphicType.CURVELINE;
165
+ }
139
166
  const pts = line.points;
140
167
  const [startId, endId] = line.pointIds;
141
168
  const start = new THREE.Vector3(pts[0], pts[1], pts[2]);
@@ -144,13 +171,15 @@ export class ThreeGeometryCreator {
144
171
  this.insertPoint(container, `${endId}|point`, endId, end.clone(), line.id, 'end', points);
145
172
  const geometry = new THREE.BufferGeometry().setFromPoints([start.clone(), end.clone()]);
146
173
  return Object.assign(Object.assign({ geometry,
147
- graphicId,
148
- type }, this.getMetadata(line, container, color)), { start: start.clone(), end: end.clone() });
174
+ graphicId, type: type }, this.getMetadata(line, container, color)), { start: start.clone(), end: end.clone() });
149
175
  }
150
176
  createEdge(edge, container, points, color = [0, 0, 0]) {
151
177
  const threePts = [];
152
178
  const graphicId = edge.id;
153
- const type = GraphicType.EDGE;
179
+ let type = GraphicType.EDGE;
180
+ if (container.type === ContainerType.CURVEARRAY) {
181
+ type = GraphicType.CURVESPLINE;
182
+ }
154
183
  const pts = edge.points;
155
184
  for (let i = 0, length = pts.length / 3; i < length; i++) {
156
185
  threePts.push(new THREE.Vector3(pts[i * 3], pts[i * 3 + 1], pts[i * 3 + 2]));
@@ -172,12 +201,14 @@ export class ThreeGeometryCreator {
172
201
  this.insertPoint(container, `${endId}|point`, endId, end, edge.id, 'end', points);
173
202
  const geometry = new THREE.BufferGeometry().setFromPoints(threePts);
174
203
  return Object.assign(Object.assign({ geometry,
175
- graphicId,
176
- type }, this.getMetadata(edge, container, color)), { start: start.clone(), end: end.clone() });
204
+ graphicId, type: type }, this.getMetadata(edge, container, color)), { start: start.clone(), end: end.clone() });
177
205
  }
178
206
  createArc(arc, container, points, color = [0, 0, 0]) {
179
207
  const graphicId = arc.id;
180
- const type = arc.isCircle ? GraphicType.CIRCLE : GraphicType.ARC;
208
+ let type = arc.isCircle ? GraphicType.CIRCLE : GraphicType.ARC;
209
+ if (container.type === ContainerType.CURVEARRAY) {
210
+ type = arc.isCircle ? GraphicType.CURVECIRCLE : GraphicType.CURVEARC;
211
+ }
181
212
  // take half of coordHeightTolerance used for faces, as classcad does it in the tessellation process
182
213
  const coordHeight = this.coordHeightTolerance / 2;
183
214
  const radius = arc.radius;
@@ -218,12 +249,11 @@ export class ThreeGeometryCreator {
218
249
  this.insertPoint(container, `${endId}|point`, endId, end, arc.id, 'end', points);
219
250
  const geometry = new THREE.BufferGeometry().setFromPoints(threePts);
220
251
  return Object.assign(Object.assign({ geometry,
221
- graphicId,
222
- type }, this.getMetadata(arc, container, color)), { normal: normal.clone(), center: center.clone(), radius: arc.radius, angle: arc.angle });
252
+ graphicId, type: type }, this.getMetadata(arc, container, color)), { normal: normal.clone(), center: center.clone(), radius: arc.radius, angle: arc.angle });
223
253
  }
224
254
  createPoint(container, key, graphicId, position, ownerId, type) {
225
255
  return Object.assign(Object.assign({ key,
226
- graphicId, type: GraphicType.POINT }, this.getMetadata(null, container)), { position: position.clone(), geometry: position.clone(), owners: [{ ownerId, type }] });
256
+ graphicId, type: (container.type === ContainerType.CURVEARRAY ? GraphicType.CURVEPOINT : GraphicType.POINT) }, this.getMetadata(null, container)), { position: position.clone(), geometry: position.clone(), owners: [{ ownerId, type }] });
227
257
  }
228
258
  insertPoint(container, key, graphicId, position, ownerId, type, points) {
229
259
  const existingPoint = points[key];
@@ -241,6 +271,7 @@ export class ThreeGeometryCreator {
241
271
  export const EMPTY_CONTAINER_GEOMETRY = () => {
242
272
  return {
243
273
  graphicId: Number.NaN,
274
+ type: GraphicType.NONE,
244
275
  map: {},
245
276
  meshes: [],
246
277
  lines: [],
@@ -248,10 +279,12 @@ export const EMPTY_CONTAINER_GEOMETRY = () => {
248
279
  arcs: [],
249
280
  points: [],
250
281
  box: { min: new THREE.Vector3(), max: new THREE.Vector3() },
251
- container: { id: NaN, ownerId: NaN },
282
+ container: { id: Number.NaN, ownerId: Number.NaN, type: GraphicType.NONE },
252
283
  color: new THREE.Color(),
253
284
  opacity: 1.0,
254
285
  layer: null,
286
+ operationId: Number.NaN,
287
+ rawGraphic: null,
255
288
  };
256
289
  };
257
290
  export const isEqualGeometry = (a, b) => {
@@ -1,7 +1,7 @@
1
1
  import { GetState, SetState } from 'zustand';
2
2
  import { BuerliStoreApi } from '../../store/store';
3
3
  import { DrawingState } from './drawing';
4
- export declare type States = {
4
+ declare type States = {
5
5
  current: number;
6
6
  stack: string[];
7
7
  captionMap: Record<string, {
@@ -9,8 +9,16 @@ export declare type States = {
9
9
  caption: string;
10
10
  }>;
11
11
  };
12
+ declare type Pending = {
13
+ id: string;
14
+ name: string;
15
+ stamp: number;
16
+ args?: any;
17
+ };
12
18
  export declare type CadData = {
19
+ connected: boolean;
13
20
  states: States;
21
+ pending: Pending[];
14
22
  };
15
23
  export declare type CadApi = ReturnType<typeof cadApi>;
16
24
  export declare const cadData: () => CadData;
@@ -23,4 +31,10 @@ export declare const cadApi: (set: SetState<DrawingState>, get: GetState<Drawing
23
31
  stateName: string;
24
32
  caption: string;
25
33
  }>) => void;
34
+ addPending: (name: string, options?: {
35
+ args?: any;
36
+ } | undefined) => string;
37
+ removePending: (id: string) => void;
38
+ setConnected: (connected: boolean) => void;
26
39
  };
40
+ export {};
@@ -1,8 +1,11 @@
1
+ import { v4 } from 'uuid';
1
2
  ////////////////////////////////////////////////////
2
3
  // DATA
3
4
  ////////////////////////////////////////////////////
4
5
  export const cadData = () => ({
6
+ connected: false,
5
7
  states: { current: 0, stack: [], captionMap: {} },
8
+ pending: [],
6
9
  });
7
10
  ////////////////////////////////////////////////////
8
11
  // API
@@ -10,4 +13,18 @@ export const cadData = () => ({
10
13
  export const cadApi = (set, get, buerliApi) => ({
11
14
  setStates: (current, stack, captionMap) => set(state => ({ cad: Object.assign(Object.assign({}, state.cad), { states: Object.assign(Object.assign({}, state.cad.states), { current, stack, captionMap }) }) })),
12
15
  setCaptionMap: (captionMap) => set(state => ({ cad: Object.assign(Object.assign({}, state.cad), { states: Object.assign(Object.assign({}, state.cad.states), { captionMap }) }) })),
16
+ addPending: (name, options) => {
17
+ const id = v4();
18
+ set(state => ({
19
+ cad: Object.assign(Object.assign({}, state.cad), { pending: [...state.cad.pending, Object.assign(Object.assign({}, options), { id, name, stamp: Date.now() })] }),
20
+ }));
21
+ return id;
22
+ },
23
+ removePending: (id) => {
24
+ const newPending = get().cad.pending.filter(p => p.id !== id);
25
+ set(state => ({ cad: Object.assign(Object.assign({}, state.cad), { pending: newPending }) }));
26
+ },
27
+ setConnected: (connected) => {
28
+ return set(state => ({ cad: Object.assign(Object.assign({}, state.cad), { connected }) }));
29
+ },
13
30
  });
@@ -25,7 +25,6 @@ export declare type DrawingAPI = {
25
25
  graphic: GraphicApi;
26
26
  canvas: CanvasApi;
27
27
  cad: CadApi;
28
- setCustom: (key: string, value: Record<string, any>) => void;
29
28
  };
30
29
  declare type StateData = {
31
30
  id: DrawingID;
@@ -37,7 +36,6 @@ declare type StateData = {
37
36
  selection: SelectionData;
38
37
  plugin: PluginData;
39
38
  cad: CadData;
40
- custom: any;
41
39
  };
42
40
  export declare type DrawingState = Readonly<StateData> & Readonly<{
43
41
  api: DrawingAPI;
@@ -28,7 +28,6 @@ export const createDrawingState = (set, get, buerliApi, drawingNumber, name) =>
28
28
  graphic: graphicData(),
29
29
  canvas: canvasData(),
30
30
  cad: cadData(),
31
- custom: {},
32
31
  api: {
33
32
  structure: structureApi(set, get, buerliApi),
34
33
  selection: selectionApi(set, get, buerliApi),
@@ -37,9 +36,6 @@ export const createDrawingState = (set, get, buerliApi, drawingNumber, name) =>
37
36
  graphic: graphicApi(set, get, buerliApi),
38
37
  canvas: canvasApi(set, get, buerliApi),
39
38
  cad: cadApi(set, get, buerliApi),
40
- setCustom: (key, value) => {
41
- set(state => (Object.assign(Object.assign({}, state), { custom: Object.assign(Object.assign({}, state.custom), { [key]: Object.assign(Object.assign({}, state.custom[key]), value) }) })));
42
- },
43
39
  },
44
40
  id: drawingId,
45
41
  name: name || `Drawing #${drawingNumber}`,
@@ -1,6 +1,6 @@
1
1
  import * as THREE from 'three';
2
2
  import { GetState, SetState } from 'zustand';
3
- import { ContainerGeometryT } from '../../geometry/ThreeGeometryCreator';
3
+ import { ContainerGeometryT, GeometryElement } from '../../geometry/ThreeGeometryCreator';
4
4
  import { BuerliStoreApi } from '../../store/store';
5
5
  import { GraphicID } from '../../types/IGraphicPackage';
6
6
  import { ObjectID } from '../../types/IStructureTree';
@@ -45,5 +45,10 @@ export declare const geometryApi: (set: SetState<DrawingState>, get: GetState<Dr
45
45
  setColor: (containerId: GraphicID, r: number, g: number, b: number) => void;
46
46
  setOpacity: (containerId: GraphicID, opacity: number) => void;
47
47
  setConfig: (objId: ObjectID | GraphicID, config: Partial<GeometryConfig> | null) => void;
48
+ findDecorated: () => GeometryElement[];
49
+ filter: (cb: (elem: GeometryElement) => boolean, options?: {
50
+ onlyOne?: boolean | undefined;
51
+ containerId?: number | undefined;
52
+ } | undefined) => GeometryElement[];
48
53
  };
49
54
  export {};
@@ -83,4 +83,29 @@ export const geometryApi = (set, get, buerliApi) => ({
83
83
  return { geometry: Object.assign(Object.assign({}, state.geometry), { config: Object.assign(Object.assign({}, state.geometry.config), { product: productConfigs }) }) };
84
84
  });
85
85
  },
86
+ findDecorated: () => {
87
+ const { geometry: api } = get().api;
88
+ return api.filter(elem => { var _a, _b, _c, _d, _e; return Boolean((_b = (_a = elem.rawGraphic) === null || _a === void 0 ? void 0 : _a.properties) === null || _b === void 0 ? void 0 : _b.label) || Boolean((_e = (_d = (_c = elem.rawGraphic) === null || _c === void 0 ? void 0 : _c.properties) === null || _d === void 0 ? void 0 : _d.material) === null || _e === void 0 ? void 0 : _e.color); });
89
+ },
90
+ filter: (cb, options) => {
91
+ const result = [];
92
+ const { cache } = get().geometry;
93
+ const contIds = Object.getOwnPropertyNames(cache).map(n => Number(n));
94
+ for (const contId of contIds) {
95
+ if ((options === null || options === void 0 ? void 0 : options.containerId) && contId !== options.containerId) {
96
+ continue;
97
+ }
98
+ const ids = Object.getOwnPropertyNames(cache[contId].map).map(id => Number(id));
99
+ for (const id of ids) {
100
+ const elem = cache[contId].map[id];
101
+ if (cb(elem)) {
102
+ result.push(elem);
103
+ if (options === null || options === void 0 ? void 0 : options.onlyOne) {
104
+ return result;
105
+ }
106
+ }
107
+ }
108
+ }
109
+ return result;
110
+ },
86
111
  });
@@ -11,11 +11,6 @@ export declare const graphicData: () => GraphicData;
11
11
  export declare const graphicApi: (set: SetState<DrawingState>, get: GetState<DrawingState>, buerliApi: BuerliStoreApi) => {
12
12
  addPackages: (packages: IGraphicPackage[]) => void;
13
13
  cleanupGraphicRecords: () => void;
14
- findDecorated: () => {
15
- elem: IGraphicElement;
16
- containerId: ObjectID;
17
- solidId: ObjectID;
18
- }[];
19
14
  filter: (cb: (elem: IGraphicElement) => boolean, options?: {
20
15
  onlyOne?: boolean | undefined;
21
16
  containerId?: number | undefined;
@@ -79,10 +79,6 @@ export const graphicApi = (set, get, buerliApi) => ({
79
79
  set({ geometry: Object.assign(Object.assign({}, geometry), { cache: usedGeometry, stamp: Date.now() }) });
80
80
  }
81
81
  },
82
- findDecorated: () => {
83
- const { graphic: api } = get().api;
84
- return api.filter(elem => { var _a, _b, _c; return Boolean((_a = elem.properties) === null || _a === void 0 ? void 0 : _a.label) || Boolean((_c = (_b = elem.properties) === null || _b === void 0 ? void 0 : _b.material) === null || _c === void 0 ? void 0 : _c.color); });
85
- },
86
82
  filter: (cb, options) => {
87
83
  const result = [];
88
84
  const { containers } = get().graphic;
@@ -41,15 +41,22 @@ export declare type SelectionData = {
41
41
  export declare type SelectionApi = ReturnType<typeof selectionApi>;
42
42
  export declare const selectionData: () => SelectionData;
43
43
  export declare const selectionApi: (set: SetState<DrawingState>, get: GetState<DrawingState>, buerliApi: BuerliStoreApi) => {
44
- unselectAll(): void;
45
- unselect(...unselItems: SelectedItem[]): void;
46
- select(...newItems: SelectedItem[]): void;
44
+ unselectAll(selectorId?: SelectorID | undefined): void;
45
+ unselect(items: SelectedItem | SelectedItem[], selectorId?: SelectorID | undefined): void;
46
+ select(items: SelectedItem | SelectedItem[], selectorId?: SelectorID | undefined): void;
47
47
  setHovered(item: SelectedItem | null, selectorId?: SelectorID | undefined): void;
48
48
  activateSelector(selectorId: SelectorID | null): void;
49
49
  createSelector(selectorId: SelectorID, filter: SelectionFilter, activate?: boolean, initialItems?: SelectedItem[], maxLen?: number, customSelect?: CustomSelect | undefined, customUnSelect?: CustomSelect | undefined): () => void;
50
50
  areItemsSelected: (items: SelectedItem[], selectorId?: SelectorID | undefined) => boolean;
51
51
  isItemSelected: (item: SelectedItem, selectorId?: SelectorID | undefined) => boolean;
52
52
  setItems(id: SelectorID, items: SelectedItem[]): void;
53
- getGraphicItem: (productId: ObjectID, containerId: GraphicID, graphicId?: number | undefined) => SelectedItem | null;
53
+ selectGraphic: (selectorId: SelectorID, items: {
54
+ productId: ObjectID;
55
+ containerId: GraphicID;
56
+ graphicId?: GraphicID;
57
+ }[], options?: {
58
+ unselectExisting?: boolean | undefined;
59
+ } | undefined) => void;
60
+ getGraphicItem: (productId: ObjectID, containerId: GraphicID, graphicId?: number | undefined) => SelectedItem<ProductElement> | null;
54
61
  };
55
62
  export declare const createGraphicItem: (productId: ObjectID, el: GeometryElement) => SelectedItem<ProductElement>;
@@ -8,56 +8,58 @@ export const selectionData = () => ({
8
8
  active: null,
9
9
  });
10
10
  export const selectionApi = (set, get, buerliApi) => ({
11
- unselectAll() {
12
- const drawingId = get().id;
13
- const activeSelector = get().selection.active;
14
- if (activeSelector) {
15
- const unselItems = get().selection.refs[activeSelector].items;
16
- unsubscribeItems(buerliApi, drawingId, activeSelector, unselItems);
11
+ unselectAll(selectorId) {
12
+ const { selection, id: drawingId } = get();
13
+ const selId = (selectorId || selection.active);
14
+ if (selId) {
15
+ const unselItems = selection.refs[selId].items;
16
+ unsubscribeItems(buerliApi, drawingId, selId, unselItems);
17
17
  set(state => {
18
- const selector = state.selection.refs[activeSelector];
18
+ const selector = state.selection.refs[selId];
19
19
  return {
20
- selection: Object.assign(Object.assign({}, state.selection), { refs: Object.assign(Object.assign({}, state.selection.refs), { [activeSelector]: Object.assign(Object.assign({}, selector), { items: [] }) }) }),
20
+ selection: Object.assign(Object.assign({}, state.selection), { refs: Object.assign(Object.assign({}, state.selection.refs), { [selId]: Object.assign(Object.assign({}, selector), { items: [] }) }) }),
21
21
  };
22
22
  });
23
23
  }
24
24
  },
25
- unselect(...unselItems) {
25
+ unselect(items, selectorId) {
26
26
  const { selection, id: drawingId } = get();
27
- const activeSelectorId = selection.active;
28
- if (activeSelectorId) {
27
+ const selId = (selectorId || selection.active);
28
+ if (selId) {
29
+ const unselItems = Array.isArray(items) ? items : [items];
29
30
  // Remove unselItems from selector's items
30
- const selector = selection.refs[activeSelectorId];
31
+ const selector = selection.refs[selId];
31
32
  const newItems = selector.items.filter(item => unselItems.find(uItem => uItem.id === item.id) === undefined);
32
- unsubscribeItems(buerliApi, drawingId, activeSelectorId, unselItems);
33
+ unsubscribeItems(buerliApi, drawingId, selId, unselItems);
33
34
  if (selector.customUnSelect) {
34
35
  // Find recently unselected items
35
36
  const diff = selector.items.filter(item1 => {
36
37
  return newItems.find(item2 => item2.id === item1.id) === undefined;
37
38
  });
38
- selector.customUnSelect(activeSelectorId, newItems, diff);
39
+ selector.customUnSelect(selId, newItems, diff);
39
40
  }
40
41
  else {
41
42
  set(state => {
42
43
  return {
43
- selection: Object.assign(Object.assign({}, state.selection), { refs: Object.assign(Object.assign({}, state.selection.refs), { [activeSelectorId]: Object.assign(Object.assign({}, state.selection.refs[activeSelectorId]), { items: newItems }) }) }),
44
+ selection: Object.assign(Object.assign({}, state.selection), { refs: Object.assign(Object.assign({}, state.selection.refs), { [selId]: Object.assign(Object.assign({}, state.selection.refs[selId]), { items: newItems }) }) }),
44
45
  };
45
46
  });
46
47
  }
47
- this.setHovered(null, activeSelectorId);
48
+ this.setHovered(null, selId);
48
49
  }
49
50
  },
50
- select(...newItems) {
51
+ select(items, selectorId) {
51
52
  const { selection, api, id: drawingId } = get();
52
- const activeSelectorId = selection.active;
53
- const { isItemSelected } = api.selection;
54
- if (activeSelectorId) {
55
- const selector = selection.refs[activeSelectorId];
53
+ const selId = (selectorId || selection.active);
54
+ if (selId) {
55
+ const { isItemSelected } = api.selection;
56
+ const newItems = Array.isArray(items) ? items : [items];
57
+ const selector = selection.refs[selId];
56
58
  const curItems = selector.items;
57
59
  // Remove duplicates
58
60
  let filteredItems = newItems.filter((item1, idx) => newItems.findIndex(item2 => item2.id === item1.id) === idx);
59
61
  // Remove already selected items and duplicates
60
- filteredItems = filteredItems.filter(item => !isItemSelected(item, activeSelectorId));
62
+ filteredItems = filteredItems.filter(item => !isItemSelected(item, selId));
61
63
  let unsubItems = [];
62
64
  let result = [...curItems, ...filteredItems];
63
65
  if (selector.maxLen > 0) {
@@ -84,27 +86,26 @@ export const selectionApi = (set, get, buerliApi) => ({
84
86
  const diff = result.filter(item1 => {
85
87
  return selector.items.find(item2 => item2.id === item1.id) === undefined;
86
88
  });
87
- selector.customSelect(activeSelectorId, result, diff);
89
+ selector.customSelect(selId, result, diff);
88
90
  }
89
91
  else {
90
92
  // subscribe items which will be selected
91
- subscribeItems(buerliApi, drawingId, activeSelectorId, result);
93
+ subscribeItems(buerliApi, drawingId, selId, result);
92
94
  // unsubscribe items which will be unselected
93
- unsubscribeItems(buerliApi, drawingId, activeSelectorId, unsubItems);
95
+ unsubscribeItems(buerliApi, drawingId, selId, unsubItems);
94
96
  set(state => {
95
97
  return {
96
- selection: Object.assign(Object.assign({}, state.selection), { refs: Object.assign(Object.assign({}, state.selection.refs), { [activeSelectorId]: Object.assign(Object.assign({}, selector), { items: result }) }) }),
98
+ selection: Object.assign(Object.assign({}, state.selection), { refs: Object.assign(Object.assign({}, state.selection.refs), { [selId]: Object.assign(Object.assign({}, selector), { items: result, hoveredItem: null }) }) }),
97
99
  };
98
100
  });
99
101
  }
100
- this.setHovered(null, activeSelectorId);
101
102
  }
102
103
  },
103
104
  setHovered(item, selectorId) {
104
105
  const { selection } = get();
105
106
  if (selection.active === null && selectorId === undefined)
106
107
  return;
107
- const selId = selection.active || selectorId;
108
+ const selId = (selectorId || selection.active);
108
109
  set(state => ({
109
110
  selection: Object.assign(Object.assign({}, state.selection), { refs: Object.assign(Object.assign({}, state.selection.refs), { [selId]: Object.assign(Object.assign({}, state.selection.refs[selId]), { hoveredItem: item }) }) }),
110
111
  }));
@@ -153,7 +154,7 @@ export const selectionApi = (set, get, buerliApi) => ({
153
154
  const { selection } = get();
154
155
  if (selection.active === null && selectorId === undefined)
155
156
  return false;
156
- const selId = selection.active || selectorId;
157
+ const selId = (selectorId || selection.active);
157
158
  const selector = selection.refs[selId];
158
159
  let res = true;
159
160
  items.forEach(item => {
@@ -168,7 +169,7 @@ export const selectionApi = (set, get, buerliApi) => ({
168
169
  const { selection } = get();
169
170
  if (selection.active === null && selectorId === undefined)
170
171
  return false;
171
- const selId = selection.active || selectorId;
172
+ const selId = (selectorId || selection.active);
172
173
  const selector = selection.refs[selId];
173
174
  return Boolean(selector.items.find(i => areItemsEqual(i, item)));
174
175
  },
@@ -185,17 +186,36 @@ export const selectionApi = (set, get, buerliApi) => ({
185
186
  };
186
187
  });
187
188
  },
189
+ selectGraphic: (selectorId, items, options) => {
190
+ const { api } = get();
191
+ const selItems = items
192
+ .map(i => api.selection.getGraphicItem(i.productId, i.containerId, i.graphicId))
193
+ .filter(i => Boolean(i));
194
+ if (options === null || options === void 0 ? void 0 : options.unselectExisting) {
195
+ api.selection.setItems(selectorId, selItems);
196
+ }
197
+ else {
198
+ api.selection.select(selItems, selectorId);
199
+ }
200
+ },
188
201
  getGraphicItem: (productId, containerId, graphicId) => {
189
202
  const { cache } = get().geometry;
190
203
  const container = cache[containerId];
204
+ let useContainer = false;
191
205
  if (container) {
192
206
  if (graphicId === undefined) {
193
207
  const ids = Object.getOwnPropertyNames(container.map);
194
208
  graphicId = ids.length > 0 ? Number(ids[0]) : undefined;
209
+ useContainer = true;
195
210
  }
196
211
  if (graphicId !== undefined) {
197
- const geomElem = container.map[graphicId];
212
+ let geomElem = container.map[graphicId];
213
+ if (!geomElem) {
214
+ geomElem = container.points.find(p => p.graphicId === graphicId);
215
+ }
198
216
  if (geomElem) {
217
+ geomElem.graphicId = useContainer ? containerId : geomElem.graphicId;
218
+ geomElem.type = useContainer ? container.type : geomElem.type;
199
219
  return createGraphicItem(productId, geomElem);
200
220
  }
201
221
  }
@@ -206,11 +226,23 @@ export const selectionApi = (set, get, buerliApi) => ({
206
226
  ////////////////////////////////////////////////////
207
227
  //#region GLOBAL FUNCTIONS
208
228
  const areItemsEqual = (a, b) => a.id === b.id && a.scope === b.scope;
229
+ const getLabel = (type) => {
230
+ const uppLetters = type.replace(/[a-z]/g, '');
231
+ if (uppLetters.length >= 2) {
232
+ return uppLetters[0] + uppLetters[1];
233
+ }
234
+ else if (uppLetters.length === 1) {
235
+ return (type[0] + uppLetters[0]).toUpperCase();
236
+ }
237
+ else {
238
+ return (type[0] + type[1]).toUpperCase();
239
+ }
240
+ };
209
241
  const createGraphicIdent = (productId, graphicId, type) => {
210
242
  return {
211
243
  id: `${productId}|${graphicId}|${type}`,
212
244
  scope: BuerliScope,
213
- label: (type[0] + type[1]).toUpperCase(),
245
+ label: getLabel(type),
214
246
  };
215
247
  };
216
248
  export const createGraphicItem = (productId, el) => {
@@ -1,3 +1,4 @@
1
+ import fastpatch from 'fast-json-patch';
1
2
  import jsonpatch from 'jsonpatch';
2
3
  import * as THREE from 'three';
3
4
  import { DEFAULT_STRUCTURE_TREE, } from '../../types';
@@ -29,19 +30,50 @@ export const structureApi = (set, get, buerliApi) => ({
29
30
  },
30
31
  applyPatches: (patches) => {
31
32
  const before = get().structure.products.concat(get().structure.visibleContainers);
32
- // Timing.dump('load', 'received tree patches')
33
- set(state => {
34
- let structure = state.structure;
35
- try {
36
- structure = jsonpatch.apply_patch(state.structure, patches);
33
+ const applyBlock = (block) => {
34
+ if (block.length === 0)
35
+ return;
36
+ set(state => {
37
+ let structure = state.structure;
38
+ try {
39
+ // TODO: keep an eye on the patch behaviour in general.
40
+ // For large changes 'fast-json-patch' is much more performant than 'jsonpatch'.
41
+ // However, for smaller changes 'jsonpatch' is more performant than 'fast-json-patch'.
42
+ if (block.length > 100) {
43
+ structure = fastpatch.applyPatch(state.structure, block, false, false).newDocument;
44
+ }
45
+ else {
46
+ structure = jsonpatch.apply_patch(state.structure, block);
47
+ }
48
+ }
49
+ catch (e) {
50
+ console.error(e);
51
+ }
52
+ // console.info('currentProduct in new patched structure: ', structure.currentProduct)
53
+ return { structure: Object.assign(Object.assign({}, state.structure), structure) };
54
+ });
55
+ };
56
+ const treePatches = [];
57
+ const otherPatches = [];
58
+ for (const patch of patches) {
59
+ if (patch.path.startsWith('/tree/')) {
60
+ treePatches.push(patch);
37
61
  }
38
- catch (e) {
39
- console.error(e);
62
+ else {
63
+ otherPatches.push(patch);
40
64
  }
41
- return {
42
- structure: Object.assign(Object.assign({}, get().structure), structure),
43
- };
44
- });
65
+ }
66
+ // console.info(JSON.stringify(otherPatches))
67
+ //////////////////////////////////////////////////////////////////////////////
68
+ // The following split of the state update helps very much in some cases to
69
+ // prevent not existing object access in many React hooks.
70
+ // 1. Perform meta information update as the first step (root, currentProduct, ...)
71
+ applyBlock(otherPatches);
72
+ // 2. Perform tree update as a second, separate step
73
+ applyBlock(treePatches);
74
+ // TODO: The update behaviour for structure updates in buerli/zustand/react-hooks
75
+ // has to be analyzed in more detail based on a very simple example.
76
+ //////////////////////////////////////////////////////////////////////////////
45
77
  const { api } = get();
46
78
  api.structure.postProcessStructureUpdate();
47
79
  // Update the bounds, but only if products or visible containers changed.
@@ -10,6 +10,7 @@ export interface IGraphicPackageProperties {
10
10
  export interface IGraphicContainer {
11
11
  id: GraphicID;
12
12
  owner: ObjectID;
13
+ type: ContainerType;
13
14
  properties: IGraphicContainerProps;
14
15
  meshes: IGraphicMesh[];
15
16
  lines: IGraphicLine[];
@@ -120,14 +121,31 @@ export declare enum GraphicType {
120
121
  SPHERE = "sphere",
121
122
  NURBS = "nurbs",
122
123
  NURBSSURFACE = "nurbsSurface",
123
- LOOP = "loop",
124
- SOLID = "solid"
124
+ NONE = "none",
125
+ BREP = "brep",
126
+ POLYBREP = "polyBrep",
127
+ CURVEARRAY = "curveArray",
128
+ CURVELINE = "curveLine",
129
+ CURVESPLINE = "curveSpline",
130
+ CURVEARC = "curveArc",
131
+ CURVECIRCLE = "curveCircle",
132
+ CURVEPOINT = "curvePoint",
133
+ LOOP = "loop"
134
+ }
135
+ export declare enum ContainerType {
136
+ NONE = 0,
137
+ BREP = 1,
138
+ CURVEARRAY = 2,
139
+ POLYBREP = 3
125
140
  }
126
141
  declare type RoA = ReadonlyArray<GraphicType>;
127
142
  export declare const AllTypes: RoA;
128
143
  export declare const Surfaces: RoA;
129
144
  export declare const LineSegments: RoA;
130
145
  export declare const Primitives: RoA;
146
+ export declare const CurveSegments: RoA;
147
+ export declare const EntityTypes: RoA;
148
+ export declare const PointTypes: RoA;
131
149
  export interface IGraphicMaterial {
132
150
  color: number[];
133
151
  opacity: number;
@@ -1,5 +1,6 @@
1
1
  export var GraphicType;
2
2
  (function (GraphicType) {
3
+ // Primitives
3
4
  GraphicType["POINT"] = "point";
4
5
  GraphicType["LINE"] = "line";
5
6
  GraphicType["EDGE"] = "edge";
@@ -11,11 +12,35 @@ export var GraphicType;
11
12
  GraphicType["SPHERE"] = "sphere";
12
13
  GraphicType["NURBS"] = "nurbs";
13
14
  GraphicType["NURBSSURFACE"] = "nurbsSurface";
15
+ // Entities
16
+ GraphicType["NONE"] = "none";
17
+ GraphicType["BREP"] = "brep";
18
+ GraphicType["POLYBREP"] = "polyBrep";
19
+ GraphicType["CURVEARRAY"] = "curveArray";
20
+ // Curve array elements
21
+ GraphicType["CURVELINE"] = "curveLine";
22
+ GraphicType["CURVESPLINE"] = "curveSpline";
23
+ GraphicType["CURVEARC"] = "curveArc";
24
+ GraphicType["CURVECIRCLE"] = "curveCircle";
25
+ GraphicType["CURVEPOINT"] = "curvePoint";
26
+ // Custom type(s) (not defined by server protocol)
14
27
  GraphicType["LOOP"] = "loop";
15
- GraphicType["SOLID"] = "solid";
16
28
  })(GraphicType || (GraphicType = {}));
29
+ export var ContainerType;
30
+ (function (ContainerType) {
31
+ ContainerType[ContainerType["NONE"] = 0] = "NONE";
32
+ ContainerType[ContainerType["BREP"] = 1] = "BREP";
33
+ ContainerType[ContainerType["CURVEARRAY"] = 2] = "CURVEARRAY";
34
+ ContainerType[ContainerType["POLYBREP"] = 3] = "POLYBREP";
35
+ // POINTARRAY = 4, // Not used at the moment
36
+ // GRAPHIC = 5, // Not used at the moment
37
+ // LIGHTWEIGHTBREP = 6, // Not used at the moment
38
+ })(ContainerType || (ContainerType = {}));
17
39
  const G = GraphicType;
18
40
  export const AllTypes = Object.keys(G).map(key => G[key]);
19
41
  export const Surfaces = [G.PLANE, G.CYLINDER, G.CONE, G.SPHERE, G.NURBS, G.NURBSSURFACE];
20
42
  export const LineSegments = [G.LINE, G.EDGE, G.ARC, G.CIRCLE];
21
43
  export const Primitives = Surfaces.concat(LineSegments).concat([G.POINT]);
44
+ export const CurveSegments = [G.CURVELINE, G.CURVESPLINE, G.CURVEARC, G.CURVECIRCLE];
45
+ export const EntityTypes = [G.BREP, G.POLYBREP, G.CURVEARRAY];
46
+ export const PointTypes = [G.POINT, G.CURVEPOINT];
@@ -21,10 +21,12 @@ export const Measure = {
21
21
  const newItem = Object.assign({}, item);
22
22
  switch (newItem.type) {
23
23
  case GraphicType.POINT:
24
+ case GraphicType.CURVEPOINT:
24
25
  const point = newItem;
25
26
  point.position = point.position.clone().applyMatrix4(matrix);
26
27
  break;
27
28
  case GraphicType.LINE:
29
+ case GraphicType.CURVELINE:
28
30
  const line = newItem;
29
31
  line.start = line.start.clone().applyMatrix4(matrix);
30
32
  line.end = line.end.clone().applyMatrix4(matrix);
@@ -48,12 +50,14 @@ export const Measure = {
48
50
  cone.origin = cone.origin.clone().applyMatrix4(matrix);
49
51
  break;
50
52
  case GraphicType.ARC:
53
+ case GraphicType.CURVEARC:
51
54
  const arc = newItem;
52
55
  arc.normal = arc.normal.clone().applyMatrix3(matrix3);
53
56
  arc.normal.normalize();
54
57
  arc.center = arc.center.clone().applyMatrix4(matrix);
55
58
  break;
56
59
  case GraphicType.CIRCLE:
60
+ case GraphicType.CURVECIRCLE:
57
61
  const circle = newItem;
58
62
  circle.normal = circle.normal.clone().applyMatrix3(matrix3);
59
63
  circle.normal.normalize();
@@ -83,6 +87,7 @@ export const Measure = {
83
87
  for (const element of transformed) {
84
88
  switch (element.type) {
85
89
  case GraphicType.POINT:
90
+ case GraphicType.CURVEPOINT:
86
91
  const point = element;
87
92
  results.push({
88
93
  value: vecToStr(point.position),
@@ -91,6 +96,7 @@ export const Measure = {
91
96
  });
92
97
  break;
93
98
  case GraphicType.LINE:
99
+ case GraphicType.CURVELINE:
94
100
  const line = element;
95
101
  let absoluteDistance = line.start.distanceTo(line.end);
96
102
  absoluteDistance = Measure.round(absoluteDistance, 3);
@@ -102,6 +108,7 @@ export const Measure = {
102
108
  });
103
109
  break;
104
110
  case GraphicType.EDGE:
111
+ case GraphicType.CURVESPLINE:
105
112
  const edge = element;
106
113
  results.push({
107
114
  value: vecToStr(edge.start),
@@ -111,6 +118,7 @@ export const Measure = {
111
118
  results.push({ value: vecToStr(edge.end), description: 'Edge end', type: MeasureResultType.POSITION });
112
119
  break;
113
120
  case GraphicType.ARC:
121
+ case GraphicType.CURVEARC:
114
122
  const arc = element;
115
123
  const arcNEnd = arc.center.clone().addScaledVector(arc.normal.clone().normalize(), 40);
116
124
  const pointOnArc = getPointOnCircumference(arc.center, arc.normal, arc.radius);
@@ -134,6 +142,7 @@ export const Measure = {
134
142
  });
135
143
  break;
136
144
  case GraphicType.CIRCLE:
145
+ case GraphicType.CURVECIRCLE:
137
146
  const circle = element;
138
147
  const circleNEnd = circle.center.clone().addScaledVector(circle.normal.clone().normalize(), 40);
139
148
  const pointOnCircle = getPointOnCircumference(circle.center, circle.normal, circle.radius);
@@ -273,11 +282,14 @@ export const Measure = {
273
282
  let results = [];
274
283
  switch (first.type) {
275
284
  case GraphicType.POINT:
285
+ case GraphicType.CURVEPOINT:
276
286
  switch (second.type) {
277
287
  case GraphicType.POINT:
288
+ case GraphicType.CURVEPOINT:
278
289
  results = Measure.calculatePointPoint(first, second);
279
290
  break;
280
291
  case GraphicType.LINE:
292
+ case GraphicType.CURVELINE:
281
293
  results = Measure.calculatePointLine(first, second);
282
294
  break;
283
295
  case GraphicType.PLANE:
@@ -289,11 +301,14 @@ export const Measure = {
289
301
  }
290
302
  break;
291
303
  case GraphicType.LINE:
304
+ case GraphicType.CURVELINE:
292
305
  switch (second.type) {
293
306
  case GraphicType.POINT:
307
+ case GraphicType.CURVEPOINT:
294
308
  results = Measure.calculatePointLine(second, first);
295
309
  break;
296
310
  case GraphicType.LINE:
311
+ case GraphicType.CURVELINE:
297
312
  results = Measure.calculateLineLine(first, second);
298
313
  break;
299
314
  case GraphicType.PLANE:
@@ -307,12 +322,15 @@ export const Measure = {
307
322
  case GraphicType.PLANE:
308
323
  switch (second.type) {
309
324
  case GraphicType.POINT:
325
+ case GraphicType.CURVEPOINT:
310
326
  results = Measure.calculatePointPlane(second, first);
311
327
  break;
312
328
  case GraphicType.LINE:
329
+ case GraphicType.CURVELINE:
313
330
  results = Measure.calculateLinePlane(second, first);
314
331
  break;
315
332
  case GraphicType.ARC:
333
+ case GraphicType.CURVEARC:
316
334
  results = Measure.calculateArcPlane(second, first);
317
335
  break;
318
336
  case GraphicType.PLANE:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buerli.io/core",
3
- "version": "0.1.0",
3
+ "version": "0.2.1-beta.1",
4
4
  "description": "buerli state management",
5
5
  "author": "AWV Informatik AG <info@awv-informatik.ch>",
6
6
  "license": "ISC",
@@ -32,7 +32,8 @@
32
32
  "three": "^0.138"
33
33
  },
34
34
  "dependencies": {
35
- "jsonpatch": "^3.0.1",
35
+ "fast-json-patch": "^3.1.1",
36
+ "jsonpatch": "^3.1.0",
36
37
  "uuid": "^3.3.2",
37
38
  "zustand": "^3.5.7"
38
39
  },