@buerli.io/core 1.0.1 → 1.1.0-beta.7
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/README.md +19 -19
- package/build/cjs/geometry/ThreeGeometryCreator.js +320 -320
- package/build/cjs/geometry/index.js +17 -17
- package/build/cjs/graphic/filters.js +25 -25
- package/build/cjs/index.js +26 -26
- package/build/cjs/re-export.js +29 -29
- package/build/cjs/store/index.js +41 -37
- package/build/cjs/store/states/buerli.js +98 -98
- package/build/cjs/store/states/cad.js +47 -47
- package/build/cjs/store/states/drawing.js +49 -49
- package/build/cjs/store/states/geometry.js +157 -157
- package/build/cjs/store/states/graphic.js +115 -115
- package/build/cjs/store/states/interaction.js +55 -55
- package/build/cjs/store/states/message.js +32 -25
- package/build/cjs/store/states/plugin.js +115 -115
- package/build/cjs/store/states/selection.js +267 -267
- package/build/cjs/store/states/structure.js +250 -250
- package/build/cjs/store/store.js +9 -9
- package/build/cjs/store/subscribtion/selection.js +49 -49
- package/build/cjs/store/subscribtion/subscribeToDrawing.js +13 -13
- package/build/cjs/types/InteractionInfo.js +11 -11
- package/build/cjs/types/index.js +34 -34
- package/build/cjs/utils/Math.js +91 -91
- package/build/cjs/utils/Measure.js +576 -576
- package/build/cjs/utils/Timing.js +34 -34
- package/build/esm/geometry/ThreeGeometryCreator.js +291 -291
- package/build/esm/geometry/index.js +1 -1
- package/build/esm/graphic/filters.js +12 -12
- package/build/esm/index.js +10 -10
- package/build/esm/re-export.js +23 -23
- package/build/esm/store/index.js +29 -26
- package/build/esm/store/states/buerli.js +92 -92
- package/build/esm/store/states/cad.js +42 -42
- package/build/esm/store/states/drawing.js +45 -45
- package/build/esm/store/states/geometry.js +129 -129
- package/build/esm/store/states/graphic.js +110 -110
- package/build/esm/store/states/interaction.js +50 -50
- package/build/esm/store/states/message.js +28 -21
- package/build/esm/store/states/plugin.js +109 -109
- package/build/esm/store/states/selection.js +261 -261
- package/build/esm/store/states/structure.js +219 -219
- package/build/esm/store/store.js +3 -3
- package/build/esm/store/subscribtion/selection.js +44 -44
- package/build/esm/store/subscribtion/subscribeToDrawing.js +9 -9
- package/build/esm/types/InteractionInfo.js +6 -6
- package/build/esm/types/index.js +16 -16
- package/build/esm/utils/Math.js +65 -65
- package/build/esm/utils/Measure.js +550 -550
- package/build/esm/utils/Timing.js +31 -31
- package/build/types/geometry/ThreeGeometryCreator.d.ts +256 -256
- package/build/types/geometry/index.d.ts +1 -1
- package/build/types/graphic/filters.d.ts +11 -11
- package/build/types/index.d.ts +38 -38
- package/build/types/re-export.d.ts +70 -70
- package/build/types/store/index.d.ts +17 -16
- package/build/types/store/states/buerli.d.ts +41 -41
- package/build/types/store/states/cad.d.ts +56 -56
- package/build/types/store/states/drawing.d.ts +45 -45
- package/build/types/store/states/geometry.d.ts +64 -64
- package/build/types/store/states/graphic.d.ts +21 -21
- package/build/types/store/states/interaction.d.ts +34 -34
- package/build/types/store/states/message.d.ts +32 -30
- package/build/types/store/states/plugin.d.ts +53 -53
- package/build/types/store/states/selection.d.ts +69 -69
- package/build/types/store/states/structure.d.ts +47 -47
- package/build/types/store/store.d.ts +2 -2
- package/build/types/store/subscribtion/selection.d.ts +7 -7
- package/build/types/store/subscribtion/subscribeToDrawing.d.ts +4 -4
- package/build/types/types/InteractionInfo.d.ts +42 -42
- package/build/types/types/index.d.ts +7 -7
- package/build/types/utils/Math.d.ts +21 -21
- package/build/types/utils/Measure.d.ts +64 -64
- package/build/types/utils/Timing.d.ts +8 -8
- package/package.json +2 -2
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Timing = void 0;
|
|
4
|
-
const uuid_1 = require("uuid");
|
|
5
|
-
const cache = {};
|
|
6
|
-
const start = (key = (0, uuid_1.v4)()) => {
|
|
7
|
-
cache[key] = { startTime: performance.now(), previousTime: performance.now() };
|
|
8
|
-
return key;
|
|
9
|
-
};
|
|
10
|
-
const measure = (key, mode = 'fromStart') => {
|
|
11
|
-
if (!cache[key])
|
|
12
|
-
return Number.NaN;
|
|
13
|
-
const curr = performance.now();
|
|
14
|
-
const prev = mode === 'fromPrevious' ? cache[key].previousTime : cache[key].startTime;
|
|
15
|
-
cache[key] = Object.assign(Object.assign({}, cache[key]), { previousTime: curr });
|
|
16
|
-
return curr - prev;
|
|
17
|
-
};
|
|
18
|
-
const stop = (key) => {
|
|
19
|
-
if (!cache[key])
|
|
20
|
-
return Number.NaN;
|
|
21
|
-
const curr = performance.now();
|
|
22
|
-
const prev = cache[key].startTime;
|
|
23
|
-
delete cache[key];
|
|
24
|
-
return curr - prev;
|
|
25
|
-
};
|
|
26
|
-
const dump = (key, message = '', mode = 'fromStart') => {
|
|
27
|
-
console.info(`${message ? message : key + ':'} ${measure(key, mode).toFixed(2)}ms`);
|
|
28
|
-
};
|
|
29
|
-
exports.Timing = {
|
|
30
|
-
start,
|
|
31
|
-
stop,
|
|
32
|
-
measure,
|
|
33
|
-
dump,
|
|
34
|
-
};
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Timing = void 0;
|
|
4
|
+
const uuid_1 = require("uuid");
|
|
5
|
+
const cache = {};
|
|
6
|
+
const start = (key = (0, uuid_1.v4)()) => {
|
|
7
|
+
cache[key] = { startTime: performance.now(), previousTime: performance.now() };
|
|
8
|
+
return key;
|
|
9
|
+
};
|
|
10
|
+
const measure = (key, mode = 'fromStart') => {
|
|
11
|
+
if (!cache[key])
|
|
12
|
+
return Number.NaN;
|
|
13
|
+
const curr = performance.now();
|
|
14
|
+
const prev = mode === 'fromPrevious' ? cache[key].previousTime : cache[key].startTime;
|
|
15
|
+
cache[key] = Object.assign(Object.assign({}, cache[key]), { previousTime: curr });
|
|
16
|
+
return curr - prev;
|
|
17
|
+
};
|
|
18
|
+
const stop = (key) => {
|
|
19
|
+
if (!cache[key])
|
|
20
|
+
return Number.NaN;
|
|
21
|
+
const curr = performance.now();
|
|
22
|
+
const prev = cache[key].startTime;
|
|
23
|
+
delete cache[key];
|
|
24
|
+
return curr - prev;
|
|
25
|
+
};
|
|
26
|
+
const dump = (key, message = '', mode = 'fromStart') => {
|
|
27
|
+
console.info(`${message ? message : key + ':'} ${measure(key, mode).toFixed(2)}ms`);
|
|
28
|
+
};
|
|
29
|
+
exports.Timing = {
|
|
30
|
+
start,
|
|
31
|
+
stop,
|
|
32
|
+
measure,
|
|
33
|
+
dump,
|
|
34
|
+
};
|
|
@@ -1,291 +1,291 @@
|
|
|
1
|
-
import * as THREE from 'three';
|
|
2
|
-
import { ContainerType, GraphicType, } from '../re-export';
|
|
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
|
-
};
|
|
18
|
-
/**
|
|
19
|
-
* Creates THREE geometry based on the data within a @see IGraphicContainer.
|
|
20
|
-
*/
|
|
21
|
-
export class ThreeGeometryCreator {
|
|
22
|
-
constructor() {
|
|
23
|
-
this.coordHeightTolerance = 0.01;
|
|
24
|
-
}
|
|
25
|
-
getMetadata(geometry, container, color, opacity = 0) {
|
|
26
|
-
var _a;
|
|
27
|
-
const geomProps = geometry ? geometry.properties : {};
|
|
28
|
-
if (geomProps && geomProps.material) {
|
|
29
|
-
color = geomProps.material.color || color;
|
|
30
|
-
opacity = geomProps.material.opacity || opacity;
|
|
31
|
-
}
|
|
32
|
-
// Provide values as a CSS color string, which will be gamma corrected by three.js
|
|
33
|
-
const rgbColor = color ? new THREE.Color(`rgb(${color[0]}, ${color[1]}, ${color[2]})`) : undefined;
|
|
34
|
-
const layer = geomProps && geomProps.layer ? geomProps.layer : container.properties.layer;
|
|
35
|
-
return {
|
|
36
|
-
color: rgbColor,
|
|
37
|
-
opacity,
|
|
38
|
-
layer,
|
|
39
|
-
container: { id: container.id, ownerId: container.owner, type: convertType(container.type) },
|
|
40
|
-
operationId: (_a = geometry === null || geometry === void 0 ? void 0 : geometry.properties) === null || _a === void 0 ? void 0 : _a.operationId,
|
|
41
|
-
rawGraphic: geometry,
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
createGeometry(container, color) {
|
|
45
|
-
var _a, _b, _c, _d;
|
|
46
|
-
const { id: graphicId, properties, type: contType } = container;
|
|
47
|
-
const type = convertType(contType);
|
|
48
|
-
const box = { min: new THREE.Vector3(...properties.min), max: new THREE.Vector3(...properties.max) };
|
|
49
|
-
const meshes = [];
|
|
50
|
-
const lines = [];
|
|
51
|
-
const edges = [];
|
|
52
|
-
const arcs = [];
|
|
53
|
-
const pointMap = {};
|
|
54
|
-
const map = {};
|
|
55
|
-
if (container.meshes) {
|
|
56
|
-
container.meshes.forEach(mesh => {
|
|
57
|
-
const elem = this.createSurface(mesh, container, color);
|
|
58
|
-
if (elem.isValid) {
|
|
59
|
-
meshes.push(elem);
|
|
60
|
-
map[mesh.id] = elem;
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
// TODO: The server should not send invalid meshes.
|
|
64
|
-
console.warn(`Invalid mesh detected`);
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
if (container.lines) {
|
|
69
|
-
container.lines.forEach(line => {
|
|
70
|
-
const elem = this.createLine(line, container, pointMap, color);
|
|
71
|
-
lines.push(elem);
|
|
72
|
-
map[line.id] = elem;
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
if (container.edges) {
|
|
76
|
-
container.edges.forEach(edge => {
|
|
77
|
-
const elem = this.createEdge(edge, container, pointMap, color);
|
|
78
|
-
edges.push(elem);
|
|
79
|
-
map[edge.id] = elem;
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
if (container.arcs) {
|
|
83
|
-
container.arcs.forEach(arc => {
|
|
84
|
-
const elem = this.createArc(arc, container, pointMap, color);
|
|
85
|
-
arcs.push(elem);
|
|
86
|
-
map[arc.id] = elem;
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
const points = Object.values(pointMap);
|
|
90
|
-
return Object.assign({ graphicId,
|
|
91
|
-
type,
|
|
92
|
-
map,
|
|
93
|
-
meshes,
|
|
94
|
-
lines,
|
|
95
|
-
edges,
|
|
96
|
-
arcs,
|
|
97
|
-
points,
|
|
98
|
-
box }, this.getMetadata(null, container, (_b = (_a = container.properties) === null || _a === void 0 ? void 0 : _a.material) === null || _b === void 0 ? void 0 : _b.color, (_d = (_c = container.properties) === null || _c === void 0 ? void 0 : _c.material) === null || _d === void 0 ? void 0 : _d.opacity));
|
|
99
|
-
}
|
|
100
|
-
createSurface(mesh, container, color) {
|
|
101
|
-
let meshGeom = this.createMesh(mesh, container, color);
|
|
102
|
-
switch (meshGeom.type) {
|
|
103
|
-
case GraphicType.PLANE:
|
|
104
|
-
meshGeom = this.createPlane(mesh, meshGeom);
|
|
105
|
-
break;
|
|
106
|
-
case GraphicType.CYLINDER:
|
|
107
|
-
meshGeom = this.createCylinder(mesh, meshGeom);
|
|
108
|
-
break;
|
|
109
|
-
case GraphicType.CONE:
|
|
110
|
-
meshGeom = this.createCone(mesh, meshGeom);
|
|
111
|
-
break;
|
|
112
|
-
case GraphicType.SPHERE:
|
|
113
|
-
meshGeom = this.createSphere(mesh, meshGeom);
|
|
114
|
-
break;
|
|
115
|
-
}
|
|
116
|
-
return meshGeom;
|
|
117
|
-
}
|
|
118
|
-
createMesh(mesh, container, color) {
|
|
119
|
-
const graphicId = mesh.id;
|
|
120
|
-
const loops = mesh.loops;
|
|
121
|
-
const type = mesh.properties.surface.type;
|
|
122
|
-
const geometry = new THREE.BufferGeometry();
|
|
123
|
-
geometry.setIndex(mesh.indices);
|
|
124
|
-
geometry.setAttribute('position', new THREE.Float32BufferAttribute(mesh.vertices, 3));
|
|
125
|
-
mesh.normals && geometry.setAttribute('normal', new THREE.Float32BufferAttribute(mesh.normals, 3));
|
|
126
|
-
return Object.assign({
|
|
127
|
-
// TODO: The server should not send invalid meshes.
|
|
128
|
-
isValid: mesh.vertices && mesh.vertices.length > 0, geometry,
|
|
129
|
-
graphicId,
|
|
130
|
-
type,
|
|
131
|
-
loops }, this.getMetadata(mesh, container, color));
|
|
132
|
-
}
|
|
133
|
-
createPlane(mesh, meshGeom) {
|
|
134
|
-
const type = GraphicType.PLANE;
|
|
135
|
-
const { normal: n, pointOnPlane: p } = mesh.properties.surface;
|
|
136
|
-
const pointOnPlane = new THREE.Vector3(p[0], p[1], p[2]);
|
|
137
|
-
const normal = new THREE.Vector3(n[0], n[1], n[2]).normalize();
|
|
138
|
-
return Object.assign(Object.assign({}, meshGeom), { type, pointOnPlane, normal });
|
|
139
|
-
}
|
|
140
|
-
createCylinder(mesh, meshGeom) {
|
|
141
|
-
const type = GraphicType.CYLINDER;
|
|
142
|
-
const { origin: o, axis: a, height, radius } = mesh.properties.surface;
|
|
143
|
-
const origin = new THREE.Vector3(o[0], o[1], o[2]);
|
|
144
|
-
const axis = new THREE.Vector3(a[0], a[1], a[2]).normalize();
|
|
145
|
-
return Object.assign(Object.assign({}, meshGeom), { type, origin, axis, height, radius });
|
|
146
|
-
}
|
|
147
|
-
createCone(mesh, meshGeom) {
|
|
148
|
-
const type = GraphicType.CONE;
|
|
149
|
-
const { origin: o, axis: a, height, radiusBottom, radiusTop } = mesh.properties.surface;
|
|
150
|
-
const origin = new THREE.Vector3(o[0], o[1], o[2]);
|
|
151
|
-
const axis = new THREE.Vector3(a[0], a[1], a[2]).normalize();
|
|
152
|
-
return Object.assign(Object.assign({}, meshGeom), { type, origin, axis, height, radiusBottom, radiusTop });
|
|
153
|
-
}
|
|
154
|
-
createSphere(mesh, meshGeom) {
|
|
155
|
-
const type = GraphicType.SPHERE;
|
|
156
|
-
const { radius } = mesh.properties.surface;
|
|
157
|
-
return Object.assign(Object.assign({}, meshGeom), { type, radius });
|
|
158
|
-
}
|
|
159
|
-
createLine(line, container, points, color) {
|
|
160
|
-
const graphicId = line.id;
|
|
161
|
-
let type = GraphicType.LINE;
|
|
162
|
-
if (container.type === ContainerType.CURVEARRAY) {
|
|
163
|
-
type = GraphicType.CURVELINE;
|
|
164
|
-
}
|
|
165
|
-
const pts = line.points;
|
|
166
|
-
const [startId, endId] = line.pointIds;
|
|
167
|
-
const start = new THREE.Vector3(pts[0], pts[1], pts[2]);
|
|
168
|
-
const end = new THREE.Vector3(pts[3], pts[4], pts[5]);
|
|
169
|
-
this.insertPoint(container, `${startId}|point`, startId, start.clone(), line.id, 'start', points);
|
|
170
|
-
this.insertPoint(container, `${endId}|point`, endId, end.clone(), line.id, 'end', points);
|
|
171
|
-
const geometry = new THREE.BufferGeometry().setFromPoints([start.clone(), end.clone()]);
|
|
172
|
-
return Object.assign(Object.assign({ geometry,
|
|
173
|
-
graphicId, type: type }, this.getMetadata(line, container, color)), { start: start.clone(), end: end.clone() });
|
|
174
|
-
}
|
|
175
|
-
createEdge(edge, container, points, color) {
|
|
176
|
-
const threePts = [];
|
|
177
|
-
const graphicId = edge.id;
|
|
178
|
-
let type = GraphicType.NURBSCURVE;
|
|
179
|
-
if (container.type === ContainerType.CURVEARRAY) {
|
|
180
|
-
type = GraphicType.CURVESPLINE;
|
|
181
|
-
}
|
|
182
|
-
const pts = edge.points;
|
|
183
|
-
for (let i = 0, length = pts.length / 3; i < length; i++) {
|
|
184
|
-
threePts.push(new THREE.Vector3(pts[i * 3], pts[i * 3 + 1], pts[i * 3 + 2]));
|
|
185
|
-
// Each segment has to be defined with start and end to use it for BufferGeometry
|
|
186
|
-
if (i > 0) {
|
|
187
|
-
threePts.push(new THREE.Vector3(pts[i * 3], pts[i * 3 + 1], pts[i * 3 + 2]));
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
// Seems like the three BufferGeometryUtils expect an edge to have an even number of points.
|
|
191
|
-
// Just add the end point twice if this is not the case.
|
|
192
|
-
if (threePts.length % 2 !== 0) {
|
|
193
|
-
threePts.push(threePts[threePts.length - 1].clone());
|
|
194
|
-
}
|
|
195
|
-
const start = threePts[0].clone();
|
|
196
|
-
const end = threePts[threePts.length - 1].clone();
|
|
197
|
-
const startId = edge.pointIds[0];
|
|
198
|
-
const endId = edge.pointIds[edge.pointIds.length - 1];
|
|
199
|
-
this.insertPoint(container, `${startId}|point`, startId, start, edge.id, 'start', points);
|
|
200
|
-
this.insertPoint(container, `${endId}|point`, endId, end, edge.id, 'end', points);
|
|
201
|
-
const geometry = new THREE.BufferGeometry().setFromPoints(threePts);
|
|
202
|
-
return Object.assign(Object.assign({ geometry,
|
|
203
|
-
graphicId, type: type }, this.getMetadata(edge, container, color)), { start: start.clone(), end: end.clone() });
|
|
204
|
-
}
|
|
205
|
-
createArc(arc, container, points, color) {
|
|
206
|
-
const graphicId = arc.id;
|
|
207
|
-
let type = arc.isCircle ? GraphicType.CIRCLE : GraphicType.ARC;
|
|
208
|
-
if (container.type === ContainerType.CURVEARRAY) {
|
|
209
|
-
type = arc.isCircle ? GraphicType.CURVECIRCLE : GraphicType.CURVEARC;
|
|
210
|
-
}
|
|
211
|
-
// take half of coordHeightTolerance used for faces, as classcad does it in the tessellation process
|
|
212
|
-
const coordHeight = this.coordHeightTolerance / 2;
|
|
213
|
-
const radius = arc.radius;
|
|
214
|
-
const center = new THREE.Vector3(arc.center[0], arc.center[1], arc.center[2]);
|
|
215
|
-
const normal = new THREE.Vector3(arc.zAxis[0], arc.zAxis[1], arc.zAxis[2]).normalize();
|
|
216
|
-
const startVector = new THREE.Vector3(arc.xAxis[0], arc.xAxis[1], arc.xAxis[2]).normalize().multiplyScalar(radius);
|
|
217
|
-
const theta = arc.isCircle ? Math.PI * 2 : arc.angle;
|
|
218
|
-
// calculate angle for one segment to fulfill coordHeight tolerance
|
|
219
|
-
let alpha = 2 * Math.acos(1 - coordHeight / radius);
|
|
220
|
-
// calculate number of segments
|
|
221
|
-
let segments = Math.ceil(Math.abs(arc.angle) / alpha);
|
|
222
|
-
// choose at minimum three segments
|
|
223
|
-
segments = Math.max(3, segments);
|
|
224
|
-
// adjust angle to match with number of segments, still fulfilling coordHeigth tolerance
|
|
225
|
-
alpha = theta / segments;
|
|
226
|
-
const threePts = [];
|
|
227
|
-
const matrix = new THREE.Matrix4().makeRotationAxis(normal, alpha);
|
|
228
|
-
const startPoint = center.clone();
|
|
229
|
-
startPoint.add(startVector);
|
|
230
|
-
threePts.push(startPoint);
|
|
231
|
-
for (let i = 0; i < segments; i++) {
|
|
232
|
-
startVector.applyMatrix4(matrix);
|
|
233
|
-
const nextPoint = center.clone();
|
|
234
|
-
nextPoint.add(startVector);
|
|
235
|
-
threePts.push(nextPoint.clone());
|
|
236
|
-
// Each segment has to be defined with start and end to use it for BufferGeometry
|
|
237
|
-
threePts.push(nextPoint.clone());
|
|
238
|
-
}
|
|
239
|
-
// Seems like the three BufferGeometryUtils expect an edge to have an even number of points.
|
|
240
|
-
// Just add the end point twice if this is not the case.
|
|
241
|
-
if (threePts.length % 2 !== 0) {
|
|
242
|
-
threePts.push(threePts[threePts.length - 1].clone());
|
|
243
|
-
}
|
|
244
|
-
const [startId, endId] = arc.pointIds;
|
|
245
|
-
const start = threePts[0].clone();
|
|
246
|
-
const end = threePts[threePts.length - 1].clone();
|
|
247
|
-
this.insertPoint(container, `${startId}|point`, startId, start, arc.id, 'start', points);
|
|
248
|
-
this.insertPoint(container, `${endId}|point`, endId, end, arc.id, 'end', points);
|
|
249
|
-
const geometry = new THREE.BufferGeometry().setFromPoints(threePts);
|
|
250
|
-
return Object.assign(Object.assign({ geometry,
|
|
251
|
-
graphicId, type: type }, this.getMetadata(arc, container, color)), { normal: normal.clone(), center: center.clone(), start: start.clone(), end: end.clone(), radius: arc.radius, angle: arc.angle });
|
|
252
|
-
}
|
|
253
|
-
createPoint(container, key, graphicId, position, ownerId, type) {
|
|
254
|
-
return Object.assign(Object.assign({ key,
|
|
255
|
-
graphicId, type: (container.type === ContainerType.CURVEARRAY ? GraphicType.CURVEPOINT : GraphicType.POINT) }, this.getMetadata(null, container)), { position: position.clone(), geometry: position.clone(), owners: [{ ownerId, type }] });
|
|
256
|
-
}
|
|
257
|
-
insertPoint(container, key, graphicId, position, ownerId, type, points) {
|
|
258
|
-
const existingPoint = points[key];
|
|
259
|
-
if (existingPoint) {
|
|
260
|
-
const filteredOwners = existingPoint.owners.filter(gr => gr.ownerId === ownerId && gr.type === type);
|
|
261
|
-
if (filteredOwners.length <= 0) {
|
|
262
|
-
existingPoint.owners.push({ ownerId, type });
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
else {
|
|
266
|
-
points[key] = this.createPoint(container, key, graphicId, position, ownerId, type);
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
export const EMPTY_CONTAINER_GEOMETRY = () => {
|
|
271
|
-
return {
|
|
272
|
-
graphicId: Number.NaN,
|
|
273
|
-
type: GraphicType.NONE,
|
|
274
|
-
map: {},
|
|
275
|
-
meshes: [],
|
|
276
|
-
lines: [],
|
|
277
|
-
edges: [],
|
|
278
|
-
arcs: [],
|
|
279
|
-
points: [],
|
|
280
|
-
box: { min: new THREE.Vector3(), max: new THREE.Vector3() },
|
|
281
|
-
container: { id: Number.NaN, ownerId: Number.NaN, type: GraphicType.NONE },
|
|
282
|
-
color: new THREE.Color(),
|
|
283
|
-
opacity: 1.0,
|
|
284
|
-
layer: null,
|
|
285
|
-
operationId: Number.NaN,
|
|
286
|
-
rawGraphic: null,
|
|
287
|
-
};
|
|
288
|
-
};
|
|
289
|
-
export const isEqualGeometry = (a, b) => {
|
|
290
|
-
return a.graphicId === b.graphicId && a.type === b.type;
|
|
291
|
-
};
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { ContainerType, GraphicType, } from '../re-export';
|
|
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
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Creates THREE geometry based on the data within a @see IGraphicContainer.
|
|
20
|
+
*/
|
|
21
|
+
export class ThreeGeometryCreator {
|
|
22
|
+
constructor() {
|
|
23
|
+
this.coordHeightTolerance = 0.01;
|
|
24
|
+
}
|
|
25
|
+
getMetadata(geometry, container, color, opacity = 0) {
|
|
26
|
+
var _a;
|
|
27
|
+
const geomProps = geometry ? geometry.properties : {};
|
|
28
|
+
if (geomProps && geomProps.material) {
|
|
29
|
+
color = geomProps.material.color || color;
|
|
30
|
+
opacity = geomProps.material.opacity || opacity;
|
|
31
|
+
}
|
|
32
|
+
// Provide values as a CSS color string, which will be gamma corrected by three.js
|
|
33
|
+
const rgbColor = color ? new THREE.Color(`rgb(${color[0]}, ${color[1]}, ${color[2]})`) : undefined;
|
|
34
|
+
const layer = geomProps && geomProps.layer ? geomProps.layer : container.properties.layer;
|
|
35
|
+
return {
|
|
36
|
+
color: rgbColor,
|
|
37
|
+
opacity,
|
|
38
|
+
layer,
|
|
39
|
+
container: { id: container.id, ownerId: container.owner, type: convertType(container.type) },
|
|
40
|
+
operationId: (_a = geometry === null || geometry === void 0 ? void 0 : geometry.properties) === null || _a === void 0 ? void 0 : _a.operationId,
|
|
41
|
+
rawGraphic: geometry,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
createGeometry(container, color) {
|
|
45
|
+
var _a, _b, _c, _d;
|
|
46
|
+
const { id: graphicId, properties, type: contType } = container;
|
|
47
|
+
const type = convertType(contType);
|
|
48
|
+
const box = { min: new THREE.Vector3(...properties.min), max: new THREE.Vector3(...properties.max) };
|
|
49
|
+
const meshes = [];
|
|
50
|
+
const lines = [];
|
|
51
|
+
const edges = [];
|
|
52
|
+
const arcs = [];
|
|
53
|
+
const pointMap = {};
|
|
54
|
+
const map = {};
|
|
55
|
+
if (container.meshes) {
|
|
56
|
+
container.meshes.forEach(mesh => {
|
|
57
|
+
const elem = this.createSurface(mesh, container, color);
|
|
58
|
+
if (elem.isValid) {
|
|
59
|
+
meshes.push(elem);
|
|
60
|
+
map[mesh.id] = elem;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
// TODO: The server should not send invalid meshes.
|
|
64
|
+
console.warn(`Invalid mesh detected`);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
if (container.lines) {
|
|
69
|
+
container.lines.forEach(line => {
|
|
70
|
+
const elem = this.createLine(line, container, pointMap, color);
|
|
71
|
+
lines.push(elem);
|
|
72
|
+
map[line.id] = elem;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
if (container.edges) {
|
|
76
|
+
container.edges.forEach(edge => {
|
|
77
|
+
const elem = this.createEdge(edge, container, pointMap, color);
|
|
78
|
+
edges.push(elem);
|
|
79
|
+
map[edge.id] = elem;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
if (container.arcs) {
|
|
83
|
+
container.arcs.forEach(arc => {
|
|
84
|
+
const elem = this.createArc(arc, container, pointMap, color);
|
|
85
|
+
arcs.push(elem);
|
|
86
|
+
map[arc.id] = elem;
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
const points = Object.values(pointMap);
|
|
90
|
+
return Object.assign({ graphicId,
|
|
91
|
+
type,
|
|
92
|
+
map,
|
|
93
|
+
meshes,
|
|
94
|
+
lines,
|
|
95
|
+
edges,
|
|
96
|
+
arcs,
|
|
97
|
+
points,
|
|
98
|
+
box }, this.getMetadata(null, container, (_b = (_a = container.properties) === null || _a === void 0 ? void 0 : _a.material) === null || _b === void 0 ? void 0 : _b.color, (_d = (_c = container.properties) === null || _c === void 0 ? void 0 : _c.material) === null || _d === void 0 ? void 0 : _d.opacity));
|
|
99
|
+
}
|
|
100
|
+
createSurface(mesh, container, color) {
|
|
101
|
+
let meshGeom = this.createMesh(mesh, container, color);
|
|
102
|
+
switch (meshGeom.type) {
|
|
103
|
+
case GraphicType.PLANE:
|
|
104
|
+
meshGeom = this.createPlane(mesh, meshGeom);
|
|
105
|
+
break;
|
|
106
|
+
case GraphicType.CYLINDER:
|
|
107
|
+
meshGeom = this.createCylinder(mesh, meshGeom);
|
|
108
|
+
break;
|
|
109
|
+
case GraphicType.CONE:
|
|
110
|
+
meshGeom = this.createCone(mesh, meshGeom);
|
|
111
|
+
break;
|
|
112
|
+
case GraphicType.SPHERE:
|
|
113
|
+
meshGeom = this.createSphere(mesh, meshGeom);
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
return meshGeom;
|
|
117
|
+
}
|
|
118
|
+
createMesh(mesh, container, color) {
|
|
119
|
+
const graphicId = mesh.id;
|
|
120
|
+
const loops = mesh.loops;
|
|
121
|
+
const type = mesh.properties.surface.type;
|
|
122
|
+
const geometry = new THREE.BufferGeometry();
|
|
123
|
+
geometry.setIndex(mesh.indices);
|
|
124
|
+
geometry.setAttribute('position', new THREE.Float32BufferAttribute(mesh.vertices, 3));
|
|
125
|
+
mesh.normals && geometry.setAttribute('normal', new THREE.Float32BufferAttribute(mesh.normals, 3));
|
|
126
|
+
return Object.assign({
|
|
127
|
+
// TODO: The server should not send invalid meshes.
|
|
128
|
+
isValid: mesh.vertices && mesh.vertices.length > 0, geometry,
|
|
129
|
+
graphicId,
|
|
130
|
+
type,
|
|
131
|
+
loops }, this.getMetadata(mesh, container, color));
|
|
132
|
+
}
|
|
133
|
+
createPlane(mesh, meshGeom) {
|
|
134
|
+
const type = GraphicType.PLANE;
|
|
135
|
+
const { normal: n, pointOnPlane: p } = mesh.properties.surface;
|
|
136
|
+
const pointOnPlane = new THREE.Vector3(p[0], p[1], p[2]);
|
|
137
|
+
const normal = new THREE.Vector3(n[0], n[1], n[2]).normalize();
|
|
138
|
+
return Object.assign(Object.assign({}, meshGeom), { type, pointOnPlane, normal });
|
|
139
|
+
}
|
|
140
|
+
createCylinder(mesh, meshGeom) {
|
|
141
|
+
const type = GraphicType.CYLINDER;
|
|
142
|
+
const { origin: o, axis: a, height, radius } = mesh.properties.surface;
|
|
143
|
+
const origin = new THREE.Vector3(o[0], o[1], o[2]);
|
|
144
|
+
const axis = new THREE.Vector3(a[0], a[1], a[2]).normalize();
|
|
145
|
+
return Object.assign(Object.assign({}, meshGeom), { type, origin, axis, height, radius });
|
|
146
|
+
}
|
|
147
|
+
createCone(mesh, meshGeom) {
|
|
148
|
+
const type = GraphicType.CONE;
|
|
149
|
+
const { origin: o, axis: a, height, radiusBottom, radiusTop } = mesh.properties.surface;
|
|
150
|
+
const origin = new THREE.Vector3(o[0], o[1], o[2]);
|
|
151
|
+
const axis = new THREE.Vector3(a[0], a[1], a[2]).normalize();
|
|
152
|
+
return Object.assign(Object.assign({}, meshGeom), { type, origin, axis, height, radiusBottom, radiusTop });
|
|
153
|
+
}
|
|
154
|
+
createSphere(mesh, meshGeom) {
|
|
155
|
+
const type = GraphicType.SPHERE;
|
|
156
|
+
const { radius } = mesh.properties.surface;
|
|
157
|
+
return Object.assign(Object.assign({}, meshGeom), { type, radius });
|
|
158
|
+
}
|
|
159
|
+
createLine(line, container, points, color) {
|
|
160
|
+
const graphicId = line.id;
|
|
161
|
+
let type = GraphicType.LINE;
|
|
162
|
+
if (container.type === ContainerType.CURVEARRAY) {
|
|
163
|
+
type = GraphicType.CURVELINE;
|
|
164
|
+
}
|
|
165
|
+
const pts = line.points;
|
|
166
|
+
const [startId, endId] = line.pointIds;
|
|
167
|
+
const start = new THREE.Vector3(pts[0], pts[1], pts[2]);
|
|
168
|
+
const end = new THREE.Vector3(pts[3], pts[4], pts[5]);
|
|
169
|
+
this.insertPoint(container, `${startId}|point`, startId, start.clone(), line.id, 'start', points);
|
|
170
|
+
this.insertPoint(container, `${endId}|point`, endId, end.clone(), line.id, 'end', points);
|
|
171
|
+
const geometry = new THREE.BufferGeometry().setFromPoints([start.clone(), end.clone()]);
|
|
172
|
+
return Object.assign(Object.assign({ geometry,
|
|
173
|
+
graphicId, type: type }, this.getMetadata(line, container, color)), { start: start.clone(), end: end.clone() });
|
|
174
|
+
}
|
|
175
|
+
createEdge(edge, container, points, color) {
|
|
176
|
+
const threePts = [];
|
|
177
|
+
const graphicId = edge.id;
|
|
178
|
+
let type = GraphicType.NURBSCURVE;
|
|
179
|
+
if (container.type === ContainerType.CURVEARRAY) {
|
|
180
|
+
type = GraphicType.CURVESPLINE;
|
|
181
|
+
}
|
|
182
|
+
const pts = edge.points;
|
|
183
|
+
for (let i = 0, length = pts.length / 3; i < length; i++) {
|
|
184
|
+
threePts.push(new THREE.Vector3(pts[i * 3], pts[i * 3 + 1], pts[i * 3 + 2]));
|
|
185
|
+
// Each segment has to be defined with start and end to use it for BufferGeometry
|
|
186
|
+
if (i > 0) {
|
|
187
|
+
threePts.push(new THREE.Vector3(pts[i * 3], pts[i * 3 + 1], pts[i * 3 + 2]));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// Seems like the three BufferGeometryUtils expect an edge to have an even number of points.
|
|
191
|
+
// Just add the end point twice if this is not the case.
|
|
192
|
+
if (threePts.length % 2 !== 0) {
|
|
193
|
+
threePts.push(threePts[threePts.length - 1].clone());
|
|
194
|
+
}
|
|
195
|
+
const start = threePts[0].clone();
|
|
196
|
+
const end = threePts[threePts.length - 1].clone();
|
|
197
|
+
const startId = edge.pointIds[0];
|
|
198
|
+
const endId = edge.pointIds[edge.pointIds.length - 1];
|
|
199
|
+
this.insertPoint(container, `${startId}|point`, startId, start, edge.id, 'start', points);
|
|
200
|
+
this.insertPoint(container, `${endId}|point`, endId, end, edge.id, 'end', points);
|
|
201
|
+
const geometry = new THREE.BufferGeometry().setFromPoints(threePts);
|
|
202
|
+
return Object.assign(Object.assign({ geometry,
|
|
203
|
+
graphicId, type: type }, this.getMetadata(edge, container, color)), { start: start.clone(), end: end.clone() });
|
|
204
|
+
}
|
|
205
|
+
createArc(arc, container, points, color) {
|
|
206
|
+
const graphicId = arc.id;
|
|
207
|
+
let type = arc.isCircle ? GraphicType.CIRCLE : GraphicType.ARC;
|
|
208
|
+
if (container.type === ContainerType.CURVEARRAY) {
|
|
209
|
+
type = arc.isCircle ? GraphicType.CURVECIRCLE : GraphicType.CURVEARC;
|
|
210
|
+
}
|
|
211
|
+
// take half of coordHeightTolerance used for faces, as classcad does it in the tessellation process
|
|
212
|
+
const coordHeight = this.coordHeightTolerance / 2;
|
|
213
|
+
const radius = arc.radius;
|
|
214
|
+
const center = new THREE.Vector3(arc.center[0], arc.center[1], arc.center[2]);
|
|
215
|
+
const normal = new THREE.Vector3(arc.zAxis[0], arc.zAxis[1], arc.zAxis[2]).normalize();
|
|
216
|
+
const startVector = new THREE.Vector3(arc.xAxis[0], arc.xAxis[1], arc.xAxis[2]).normalize().multiplyScalar(radius);
|
|
217
|
+
const theta = arc.isCircle ? Math.PI * 2 : arc.angle;
|
|
218
|
+
// calculate angle for one segment to fulfill coordHeight tolerance
|
|
219
|
+
let alpha = 2 * Math.acos(1 - coordHeight / radius);
|
|
220
|
+
// calculate number of segments
|
|
221
|
+
let segments = Math.ceil(Math.abs(arc.angle) / alpha);
|
|
222
|
+
// choose at minimum three segments
|
|
223
|
+
segments = Math.max(3, segments);
|
|
224
|
+
// adjust angle to match with number of segments, still fulfilling coordHeigth tolerance
|
|
225
|
+
alpha = theta / segments;
|
|
226
|
+
const threePts = [];
|
|
227
|
+
const matrix = new THREE.Matrix4().makeRotationAxis(normal, alpha);
|
|
228
|
+
const startPoint = center.clone();
|
|
229
|
+
startPoint.add(startVector);
|
|
230
|
+
threePts.push(startPoint);
|
|
231
|
+
for (let i = 0; i < segments; i++) {
|
|
232
|
+
startVector.applyMatrix4(matrix);
|
|
233
|
+
const nextPoint = center.clone();
|
|
234
|
+
nextPoint.add(startVector);
|
|
235
|
+
threePts.push(nextPoint.clone());
|
|
236
|
+
// Each segment has to be defined with start and end to use it for BufferGeometry
|
|
237
|
+
threePts.push(nextPoint.clone());
|
|
238
|
+
}
|
|
239
|
+
// Seems like the three BufferGeometryUtils expect an edge to have an even number of points.
|
|
240
|
+
// Just add the end point twice if this is not the case.
|
|
241
|
+
if (threePts.length % 2 !== 0) {
|
|
242
|
+
threePts.push(threePts[threePts.length - 1].clone());
|
|
243
|
+
}
|
|
244
|
+
const [startId, endId] = arc.pointIds;
|
|
245
|
+
const start = threePts[0].clone();
|
|
246
|
+
const end = threePts[threePts.length - 1].clone();
|
|
247
|
+
this.insertPoint(container, `${startId}|point`, startId, start, arc.id, 'start', points);
|
|
248
|
+
this.insertPoint(container, `${endId}|point`, endId, end, arc.id, 'end', points);
|
|
249
|
+
const geometry = new THREE.BufferGeometry().setFromPoints(threePts);
|
|
250
|
+
return Object.assign(Object.assign({ geometry,
|
|
251
|
+
graphicId, type: type }, this.getMetadata(arc, container, color)), { normal: normal.clone(), center: center.clone(), start: start.clone(), end: end.clone(), radius: arc.radius, angle: arc.angle });
|
|
252
|
+
}
|
|
253
|
+
createPoint(container, key, graphicId, position, ownerId, type) {
|
|
254
|
+
return Object.assign(Object.assign({ key,
|
|
255
|
+
graphicId, type: (container.type === ContainerType.CURVEARRAY ? GraphicType.CURVEPOINT : GraphicType.POINT) }, this.getMetadata(null, container)), { position: position.clone(), geometry: position.clone(), owners: [{ ownerId, type }] });
|
|
256
|
+
}
|
|
257
|
+
insertPoint(container, key, graphicId, position, ownerId, type, points) {
|
|
258
|
+
const existingPoint = points[key];
|
|
259
|
+
if (existingPoint) {
|
|
260
|
+
const filteredOwners = existingPoint.owners.filter(gr => gr.ownerId === ownerId && gr.type === type);
|
|
261
|
+
if (filteredOwners.length <= 0) {
|
|
262
|
+
existingPoint.owners.push({ ownerId, type });
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
points[key] = this.createPoint(container, key, graphicId, position, ownerId, type);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
export const EMPTY_CONTAINER_GEOMETRY = () => {
|
|
271
|
+
return {
|
|
272
|
+
graphicId: Number.NaN,
|
|
273
|
+
type: GraphicType.NONE,
|
|
274
|
+
map: {},
|
|
275
|
+
meshes: [],
|
|
276
|
+
lines: [],
|
|
277
|
+
edges: [],
|
|
278
|
+
arcs: [],
|
|
279
|
+
points: [],
|
|
280
|
+
box: { min: new THREE.Vector3(), max: new THREE.Vector3() },
|
|
281
|
+
container: { id: Number.NaN, ownerId: Number.NaN, type: GraphicType.NONE },
|
|
282
|
+
color: new THREE.Color(),
|
|
283
|
+
opacity: 1.0,
|
|
284
|
+
layer: null,
|
|
285
|
+
operationId: Number.NaN,
|
|
286
|
+
rawGraphic: null,
|
|
287
|
+
};
|
|
288
|
+
};
|
|
289
|
+
export const isEqualGeometry = (a, b) => {
|
|
290
|
+
return a.graphicId === b.graphicId && a.type === b.type;
|
|
291
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from './ThreeGeometryCreator';
|
|
1
|
+
export * from './ThreeGeometryCreator';
|