@soonspacejs/plugin-measuring 2.13.5 → 2.13.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 CHANGED
@@ -1,5 +1,5 @@
1
- # @soonspacejs/plugin-model-blast
2
-
3
- > Model blast plugin for SoonSpace.js
4
-
5
- Document: [http://www.xwbuilders.com:8800/plugin/model-blast.html](http://www.xwbuilders.com:8800/plugin/model-blast.html)
1
+ # @soonspacejs/plugin-model-blast
2
+
3
+ > Model blast plugin for SoonSpace.js
4
+
5
+ Document: [http://www.xwbuilders.com:8800/plugin/model-blast.html](http://www.xwbuilders.com:8800/plugin/model-blast.html)
package/dist/index.esm.js CHANGED
@@ -1 +1,534 @@
1
- import t from"soonspacejs";import{LineBasicMaterial as e,DoubleSide as s,MeshBasicMaterial as i,Vector3 as n,SpriteMaterial as r,Sprite as o,BufferGeometry as h,Line as a,Mesh as l,QuadraticBezierCurve3 as c}from"three";const p={m:1,mm:.001,cm:.01,ft:.3048,in:.0254,pt:function(){const t=document.createElement("div");return t.setAttribute("style","height: 1in; visibility: hidden; position: absolute; margin: 0; padding: 0;"),document.body.appendChild(t),.0254/t.clientHeight}()},d=t=>2===t?"²":3===t?"³":"",m=(t,e=1)=>t+d(e),A=(t,e,s,i=1)=>{if(null==s&&(s=e),s===e)return{value:t,unit:m(s)};return{value:t*Math.pow(p[e]/p[s],i),unit:m(s)+d(i)}},u=(t,e)=>t.toFixed(e);var y;!function(t){t.Distance="Distance",t.Area="Area",t.Angle="Angle"}(y||(y={}));const{utils:{randomString:f}}=t;class b{constructor(t){this.ssp=t,this.mode=null,this.options={unit:"m",precision:2},this.objectsStore=new Set,this.onCancel=()=>{},this.onDone=()=>{},this.pointMarkers=[],this.labels=[],this.pointArray=[],this.mousemove=t=>{if(null===this.mode)return;const e=this.getClosestIntersection(t);if(e){if(this.tempPointMarker?this.tempPointMarker.position.set(e.x,e.y,e.z):(this.tempPointMarker=this.createPointMarker(e),this.scene.add(this.tempPointMarker)),this.pointArray.length>0){const t=this.pointArray[this.pointArray.length-1],s=this.tempLine||this.createLine(),i=s.geometry,r=this.pointArray[0],o=this.pointArray[this.pointArray.length-1];if(this.mode===y.Area?i.setFromPoints([o,e,r]):i.setFromPoints([o,e]),this.mode===y.Distance){const s=t.distanceTo(e),i=`${u(A(s,"m",this.options.unit).value,this.options.precision)} ${this.getUnitString()}`,r=new n((e.x+t.x)/2,(e.y+t.y)/2,(e.z+t.z)/2);this.addOrUpdateTempLabel(i,r)}this.tempLine||(this.scene.add(s),this.tempLine=s)}this.ssp.render()}},this.dblclick=t=>{this.click(t),this.done()},this.click=t=>{if(null===this.mode)return;const e=this.getClosestIntersection(t);if(!e)return;const s=Date.now();if(this.lastClickTime&&s-this.lastClickTime<300)return;this.lastClickTime=s,this.pointArray.push(e);const i=this.pointArray.length,n=this.createPointMarker(e);if(this.pointMarkers.push(n),this.scene.add(n),this.polyline&&(this.polyline.geometry.setFromPoints(this.pointArray),this.tempLabel&&i>1)){const t=this.pointArray[i-2];this.tempLabel.position.set((t.x+e.x)/2,(t.y+e.y)/2,(t.z+e.z)/2),this.scene.add(this.tempLabel),this.labels.push(this.tempLabel),this.tempLabel=void 0}if(this.mode===y.Area&&this.faces){const t=this.faces.geometry,s=this.faces.userData.vertices;s.push(e),t.setFromPoints(s);const i=s.length;if(i>2){const e=[];for(let t=1;t<i-1;++t)e.push(0,t,t+1);t.setIndex(e)}}this.mode===y.Angle&&this.pointArray.length>=3&&this.done(),this.ssp.render()},this.keydown=t=>{"Enter"===t.key?this.done():"Escape"===t.key&&this.cancel()},this.getClosestIntersection=t=>{if(null===this.mode)return;let e=this.ssp.viewport.getIntersects(t);return e&&e.length>0&&(e=e.filter((t=>t.object.name!==b.OBJ_NAME&&t.object.visible)),e.length>0&&e[0].distance<b.MAX_DISTANCE)?e[0].point:null};const{viewport:{scene:e,camera:s}}=t;this.scene=e,this.camera=s}get domElement(){return this.ssp.domElement}start(t=y.Distance,e={}){const{unit:s="m",precision:i=2}=e;this.mode=t,this.options.unit=s,this.options.precision=i,this.ssp.signals.mouseMove.add(this.mousemove),this.ssp.signals.click.add(this.click),this.ssp.signals.dblClick.add(this.dblclick),this.ssp.signals.keyDown.add(this.keydown),this.pointArray=[],this.polyline=this.createLine(),this.scene.add(this.polyline),this.mode===y.Area&&(this.faces=this.createFaces(),this.scene.add(this.faces)),this.domElement.style.cursor="crosshair"}close(){null!==this.mode&&(this.ssp.signals.mouseMove.remove(this.mousemove),this.ssp.signals.click.remove(this.click),this.ssp.signals.dblClick.remove(this.dblclick),this.ssp.signals.keyDown.remove(this.keydown),this.mode=null,this.domElement.style.cursor="",this.pointArray=[],this.tempPointMarker&&this.scene.remove(this.tempPointMarker),this.tempLine&&this.scene.remove(this.tempLine),this.tempLabel&&this.ssp.removeObject(this.tempLabel),this.pointMarkers.forEach((t=>this.scene.remove(t))),this.polyline&&this.scene.remove(this.polyline),this.faces&&this.scene.remove(this.faces),this.curve&&this.scene.remove(this.curve),this.labels.forEach((t=>this.ssp.removeObject(t))),this.tempPointMarker=void 0,this.tempLine=void 0,this.tempLabel=void 0,this.pointMarkers=[],this.polyline=void 0,this.faces=void 0,this.curve=void 0,this.labels=[],this.ssp.render())}cancel(){this.close(),this.onCancel()}clear(){this.objectsStore.forEach((t=>this.ssp.removeObject(t))),this.objectsStore.clear()}initPointMarkerMaterial(){const e=t.utils.textureLoader.load("data:image/webp;base64,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");this.spriteMaterial=new r({map:e,depthTest:!1,depthWrite:!1,sizeAttenuation:!1,opacity:.8})}createPointMarker(t){this.spriteMaterial||this.initPointMarkerMaterial();const e=.012,s=new o(this.spriteMaterial);return s.scale.set(e,e,e),t&&s.position.copy(t),s.name=b.OBJ_NAME,s}createLine(t=b.LINE_MATERIAL){const e=new h,s=new a(e,t);return s.frustumCulled=!1,s.name=b.OBJ_NAME,s}createFaces(){const t=new h,e=new l(t,b.MESH_MATERIAL);return e.userData.vertices=[],e.frustumCulled=!1,e.name=b.OBJ_NAME,e}done(){if(null===this.mode)return;let t=!1;const e=this.pointArray.length;if(this.mode===y.Area&&this.polyline)if(e>2){const t=this.pointArray[0];this.polyline.geometry.setFromPoints([...this.pointArray,t]);const e=this.calculateArea(this.pointArray),s=`${u(A(e,"m",this.options.unit,2).value,this.options.precision)} ${this.getUnitString()}`,i=this.getBarycenter(this.pointArray),n=this.createLabel(s);n.position.copy(i),n.element&&(n.element.innerHTML=s),this.labels.push(n)}else t=!0;if(this.mode===y.Distance&&e<2&&(t=!0),this.mode===y.Angle&&this.polyline)if(e>=3){const t=this.pointArray[0],e=this.pointArray[1],s=this.pointArray[2],i=new n(t.x-e.x,t.y-e.y,t.z-e.z).normalize(),r=this.getAngleBisector(t,e,s),o=new n(s.x-e.x,s.y-e.y,s.z-e.z).normalize(),h=this.calculateAngle(t,e,s),a=`${u(h,this.options.precision)} ${this.getUnitString()}`,l=Math.min(t.distanceTo(e),s.distanceTo(e));let c=.3*l,p=e.clone().add(new n(r.x*c,r.y*c,r.z*c));const d=this.createLabel(a);d.position.set(p.x,p.y,p.z),d.element.innerHTML=a,this.labels.push(d),c=.2*l,p=e.clone().add(new n(r.x*c,r.y*c,r.z*c));const m=e.clone().add(new n(i.x*c,i.y*c,i.z*c)),A=e.clone().add(new n(o.x*c,o.y*c,o.z*c));this.curve=this.createCurve(m,p,A),this.scene.add(this.curve)}else t=!0;t||(this.pointMarkers.length>0&&this.pointMarkers.forEach((t=>this.objectsStore.add(t))),this.polyline&&this.objectsStore.add(this.polyline),this.faces&&this.objectsStore.add(this.faces),this.curve&&this.objectsStore.add(this.curve),this.labels.length>0&&this.labels.forEach((t=>this.objectsStore.add(t))),this.pointMarkers=[],this.polyline=void 0,this.faces=void 0,this.curve=void 0,this.labels=[]),this.close(),this.ssp.render(),this.onDone()}addOrUpdateTempLabel(t,e){this.tempLabel||(this.tempLabel=this.createLabel(t)),this.tempLabel.position.set(e.x,e.y,e.z),this.tempLabel.element.innerHTML=t}createLabel(t){const e=document.createElement("div");e.innerHTML=t,e.style.padding="3px 6px",e.style.color="#fff",e.style.fontSize="12px",e.style.position="absolute",e.style.backgroundColor="rgba(25, 25, 25, 0.3)",e.style.borderRadius="12px",e.style.top="0px",e.style.left="0px";const s=this.ssp.createPoiNode({id:f(),element:e,type:"2D"});return s.name=b.LABEL_NAME,s}createCurve(t,e,s){const i=new c(t,e,s).getPoints(4),n=(new h).setFromPoints(i),r=new a(n,b.LINE_MATERIAL);return r.name=b.OBJ_NAME,r}calculateArea(t){let e=0;for(let s=0,i=1,n=2;n<t.length;i++,n++){const r=t[s].distanceTo(t[i]),o=t[i].distanceTo(t[n]),h=t[n].distanceTo(t[s]),a=(r+o+h)/2;e+=Math.sqrt(a*(a-r)*(a-o)*(a-h))}return e}calculateAngle(t,e,s){const i=t,r=e,o=s,h=new n(i.x-r.x,i.y-r.y,i.z-r.z),a=new n(o.x-r.x,o.y-r.y,o.z-r.z);return 180*h.angleTo(a)/Math.PI}getAngleBisector(t,e,s){const i=t,r=e,o=s,h=new n(i.x-r.x,i.y-r.y,i.z-r.z).normalize(),a=new n(o.x-r.x,o.y-r.y,o.z-r.z).normalize();return new n(h.x+a.x,h.y+a.y,h.z+a.z).normalize()}getBarycenter(t){const e=t.length;let s=0,i=0,r=0;return t.forEach((t=>{s+=t.x,i+=t.y,r+=t.z})),new n(s/e,i/e,r/e)}getUnitString(){return this.mode===y.Distance?m(this.options.unit):this.mode===y.Area?`${m(this.options.unit,2)}`:this.mode===y.Angle?"°":""}numberToString(t){if(t<1e-4)return t.toString();let e=2;return t<.01?e=4:t<.1&&(e=3),t.toFixed(e)}}b.LINE_MATERIAL=new e({color:16773120,linewidth:2,opacity:.8,transparent:!0,side:s,depthWrite:!1,depthTest:!1}),b.MESH_MATERIAL=new i({color:8900346,transparent:!0,opacity:.8,side:s,depthWrite:!1,depthTest:!1}),b.MAX_DISTANCE=500,b.OBJ_NAME="object_for_measure"+f(),b.LABEL_NAME="label_for_measure"+f();export{y as MeasuringMode,b as default};
1
+ import SoonSpace from 'soonspacejs';
2
+ import { LineBasicMaterial, DoubleSide, MeshBasicMaterial, Vector3, SpriteMaterial, Sprite, BufferGeometry, Line, Mesh, QuadraticBezierCurve3 } from 'three';
3
+
4
+ function __getPointBaseLength() {
5
+ const testDiv = document.createElement('div'); // get ppi
6
+ testDiv.setAttribute('style', 'height: 1in; visibility: hidden; position: absolute; margin: 0; padding: 0;');
7
+ document.body.appendChild(testDiv);
8
+ const baseLen = testDiv.clientHeight;
9
+ const inchToMeter = 0.0254;
10
+ return inchToMeter / baseLen;
11
+ }
12
+ const unitConversionByMeter = {
13
+ m: 1,
14
+ mm: 0.001,
15
+ cm: 0.01,
16
+ ft: 0.3048,
17
+ in: 0.0254,
18
+ pt: __getPointBaseLength(),
19
+ };
20
+ const _getSuffix = (power) => {
21
+ if (power === 2) {
22
+ return '²';
23
+ }
24
+ if (power === 3) {
25
+ return '³';
26
+ }
27
+ return '';
28
+ };
29
+ const getUnitStr = (unit, power = 1) => {
30
+ return unit + _getSuffix(power);
31
+ };
32
+ const getLengthValueByUnit = (value, sourceUnit, targetUnit, power = 1) => {
33
+ if (targetUnit === null || targetUnit === undefined) {
34
+ targetUnit = sourceUnit;
35
+ }
36
+ if (targetUnit === sourceUnit) {
37
+ return {
38
+ value,
39
+ unit: getUnitStr(targetUnit),
40
+ };
41
+ }
42
+ else {
43
+ const targetValue = value * Math.pow(unitConversionByMeter[sourceUnit] / unitConversionByMeter[targetUnit], power);
44
+ return {
45
+ value: targetValue,
46
+ unit: getUnitStr(targetUnit) + _getSuffix(power),
47
+ };
48
+ }
49
+ };
50
+
51
+ const showPrecisionValue = (value, precistionType) => {
52
+ const str = value.toFixed(precistionType);
53
+ return str;
54
+ };
55
+
56
+ var img = "data:image/webp;base64,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";
57
+
58
+ var MeasuringMode;
59
+ (function (MeasuringMode) {
60
+ MeasuringMode["Distance"] = "Distance";
61
+ MeasuringMode["Area"] = "Area";
62
+ MeasuringMode["Angle"] = "Angle";
63
+ })(MeasuringMode || (MeasuringMode = {}));
64
+ const { utils: { randomString, }, } = SoonSpace;
65
+ /**
66
+ * MeasuringPlugin
67
+ */
68
+ class MeasuringPlugin {
69
+ constructor(ssp) {
70
+ this.ssp = ssp;
71
+ this.mode = null;
72
+ this.options = { unit: 'm', precision: 2, };
73
+ // 缓存之前的绘制对象
74
+ this.objectsStore = new Set();
75
+ this.onCancel = () => { };
76
+ this.onDone = () => { };
77
+ this.pointMarkers = []; // 边缘点标记
78
+ this.labels = []; // poinode 标签
79
+ this.pointArray = [];
80
+ this.mousemove = (e) => {
81
+ if (this.mode === null)
82
+ return;
83
+ const point = this.getClosestIntersection(e);
84
+ if (!point)
85
+ return;
86
+ // draw the temp point as mouse moves
87
+ if (this.tempPointMarker) {
88
+ this.tempPointMarker.position.set(point.x, point.y, point.z);
89
+ }
90
+ else {
91
+ this.tempPointMarker = this.createPointMarker(point);
92
+ this.scene.add(this.tempPointMarker);
93
+ }
94
+ // draw the temp line as mouse moves
95
+ if (this.pointArray.length > 0) {
96
+ const p0 = this.pointArray[this.pointArray.length - 1]; // get last point
97
+ const line = this.tempLine || this.createLine();
98
+ const geom = line.geometry;
99
+ const startPoint = this.pointArray[0];
100
+ const lastPoint = this.pointArray[this.pointArray.length - 1];
101
+ if (this.mode === MeasuringMode.Area) {
102
+ // draw two line segments for area
103
+ geom.setFromPoints([lastPoint, point, startPoint]); // close the line as a loop
104
+ }
105
+ else {
106
+ geom.setFromPoints([lastPoint, point]);
107
+ }
108
+ if (this.mode === MeasuringMode.Distance) {
109
+ const dist = p0.distanceTo(point);
110
+ const label = `${showPrecisionValue(getLengthValueByUnit(dist, 'm', this.options.unit).value, this.options.precision)} ${this.getUnitString()}`; // hard code unit to 'm' here
111
+ const position = new Vector3((point.x + p0.x) / 2, (point.y + p0.y) / 2, (point.z + p0.z) / 2);
112
+ this.addOrUpdateTempLabel(label, position);
113
+ }
114
+ if (!this.tempLine) {
115
+ this.scene.add(line); // just add to scene once
116
+ this.tempLine = line;
117
+ }
118
+ }
119
+ this.ssp.render();
120
+ };
121
+ this.dblclick = (e) => {
122
+ this.click(e);
123
+ // double click means to done the draw operation
124
+ this.done();
125
+ };
126
+ this.click = (e) => {
127
+ if (this.mode === null)
128
+ return;
129
+ const point = this.getClosestIntersection(e);
130
+ if (!point)
131
+ return;
132
+ // double click triggers two click events, we need to avoid the second click here
133
+ const now = Date.now();
134
+ if (this.lastClickTime && (now - this.lastClickTime < 300)) {
135
+ return;
136
+ }
137
+ this.lastClickTime = now;
138
+ this.pointArray.push(point);
139
+ const count = this.pointArray.length;
140
+ const marker = this.createPointMarker(point);
141
+ this.pointMarkers.push(marker);
142
+ this.scene.add(marker);
143
+ if (this.polyline) {
144
+ this.polyline.geometry.setFromPoints(this.pointArray);
145
+ if (this.tempLabel && count > 1) {
146
+ const p0 = this.pointArray[count - 2];
147
+ this.tempLabel.position.set((p0.x + point.x) / 2, (p0.y + point.y) / 2, (p0.z + point.z) / 2);
148
+ this.scene.add(this.tempLabel);
149
+ this.labels.push(this.tempLabel);
150
+ this.tempLabel = undefined;
151
+ }
152
+ }
153
+ if (this.mode === MeasuringMode.Area && this.faces) {
154
+ const geom = this.faces.geometry;
155
+ const vertices = this.faces.userData.vertices;
156
+ vertices.push(point);
157
+ geom.setFromPoints(vertices);
158
+ const len = vertices.length;
159
+ if (len > 2) {
160
+ const indexArray = [];
161
+ for (let i = 1; i < len - 1; ++i) {
162
+ indexArray.push(0, i, i + 1); // add one triangle
163
+ }
164
+ geom.setIndex(indexArray);
165
+ }
166
+ }
167
+ if (this.mode === MeasuringMode.Angle && this.pointArray.length >= 3) {
168
+ this.done();
169
+ }
170
+ this.ssp.render();
171
+ };
172
+ this.keydown = (e) => {
173
+ if (e.key === 'Enter') {
174
+ this.done();
175
+ }
176
+ else if (e.key === 'Escape') {
177
+ this.cancel();
178
+ }
179
+ };
180
+ /**
181
+ * The the closest intersection
182
+ * @param e
183
+ */
184
+ this.getClosestIntersection = (e) => {
185
+ if (this.mode === null)
186
+ return;
187
+ let intersects = this.ssp.viewport.getIntersects(e);
188
+ if (intersects && intersects.length > 0) {
189
+ // filter out the objects for measurement
190
+ intersects = intersects.filter(item => {
191
+ return item.object.name !== MeasuringPlugin.OBJ_NAME && item.object.visible;
192
+ });
193
+ if (intersects.length > 0 && intersects[0].distance < MeasuringPlugin.MAX_DISTANCE) {
194
+ return intersects[0].point;
195
+ }
196
+ }
197
+ return null;
198
+ };
199
+ const { viewport: { scene, camera, }, } = ssp;
200
+ this.scene = scene;
201
+ this.camera = camera;
202
+ }
203
+ get domElement() {
204
+ return this.ssp.domElement;
205
+ }
206
+ /**
207
+ * Starts the measurement
208
+ */
209
+ start(mode = MeasuringMode.Distance, options = {}) {
210
+ const { unit = 'm', precision = 2, } = options;
211
+ this.mode = mode;
212
+ this.options.unit = unit;
213
+ this.options.precision = precision;
214
+ // add mouse 'click' event, but do not trigger highlight for mouse drag event
215
+ // mouseup/mousedown/mousemove event is prevented by OrbitControls, let's use pointerup/pointerdown/pointermove
216
+ this.ssp.signals.mouseMove.add(this.mousemove);
217
+ this.ssp.signals.click.add(this.click);
218
+ this.ssp.signals.dblClick.add(this.dblclick);
219
+ this.ssp.signals.keyDown.add(this.keydown);
220
+ this.pointArray = [];
221
+ // polyline is required for measuring distance, area and angle
222
+ this.polyline = this.createLine();
223
+ this.scene.add(this.polyline);
224
+ if (this.mode === MeasuringMode.Area) {
225
+ this.faces = this.createFaces();
226
+ this.scene.add(this.faces);
227
+ }
228
+ this.domElement.style.cursor = 'crosshair';
229
+ }
230
+ /**
231
+ * Ends the measurement
232
+ */
233
+ close() {
234
+ if (this.mode === null)
235
+ return;
236
+ this.ssp.signals.mouseMove.remove(this.mousemove);
237
+ this.ssp.signals.click.remove(this.click);
238
+ this.ssp.signals.dblClick.remove(this.dblclick);
239
+ this.ssp.signals.keyDown.remove(this.keydown);
240
+ this.mode = null;
241
+ this.domElement.style.cursor = '';
242
+ this.pointArray = [];
243
+ this.tempPointMarker && this.scene.remove(this.tempPointMarker);
244
+ this.tempLine && this.scene.remove(this.tempLine);
245
+ this.tempLabel && this.ssp.removeObject(this.tempLabel);
246
+ this.pointMarkers.forEach(item => this.scene.remove(item));
247
+ this.polyline && this.scene.remove(this.polyline);
248
+ this.faces && this.scene.remove(this.faces);
249
+ this.curve && this.scene.remove(this.curve);
250
+ this.labels.forEach(item => this.ssp.removeObject(item));
251
+ this.tempPointMarker = undefined;
252
+ this.tempLine = undefined;
253
+ this.tempLabel = undefined;
254
+ this.pointMarkers = [];
255
+ this.polyline = undefined;
256
+ this.faces = undefined;
257
+ this.curve = undefined;
258
+ this.labels = [];
259
+ this.ssp.render();
260
+ }
261
+ cancel() {
262
+ this.close();
263
+ // events
264
+ this.onCancel();
265
+ }
266
+ clear() {
267
+ this.objectsStore.forEach(item => this.ssp.removeObject(item));
268
+ this.objectsStore.clear();
269
+ }
270
+ /**
271
+ * Initializes point marker material
272
+ */
273
+ initPointMarkerMaterial() {
274
+ const markerTexture = SoonSpace.utils.textureLoader.load(img);
275
+ this.spriteMaterial = new SpriteMaterial({
276
+ map: markerTexture,
277
+ depthTest: false,
278
+ depthWrite: false,
279
+ sizeAttenuation: false,
280
+ opacity: 0.8,
281
+ });
282
+ }
283
+ /**
284
+ * Creates point marker
285
+ */
286
+ createPointMarker(position) {
287
+ if (!this.spriteMaterial) {
288
+ this.initPointMarkerMaterial();
289
+ }
290
+ const scale = 0.012; // change marker's size here
291
+ const obj = new Sprite(this.spriteMaterial);
292
+ obj.scale.set(scale, scale, scale);
293
+ if (position)
294
+ obj.position.copy(position);
295
+ obj.name = MeasuringPlugin.OBJ_NAME;
296
+ return obj;
297
+ }
298
+ /**
299
+ * Creates Line
300
+ */
301
+ createLine(material = MeasuringPlugin.LINE_MATERIAL) {
302
+ const geom = new BufferGeometry();
303
+ const obj = new Line(geom, material);
304
+ obj.frustumCulled = false; // Force to draw it. This fixes a bug that it disappear in some case
305
+ obj.name = MeasuringPlugin.OBJ_NAME;
306
+ return obj;
307
+ }
308
+ /**
309
+ * Creates Mesh
310
+ */
311
+ createFaces() {
312
+ const geom = new BufferGeometry();
313
+ const obj = new Mesh(geom, MeasuringPlugin.MESH_MATERIAL);
314
+ // since we have to use BufferGeometry rather than Geometry, and we need to store points,
315
+ // let's store points into userData!
316
+ obj.userData.vertices = [];
317
+ obj.frustumCulled = false; // Force to draw it. This fixes a bug that it disappear in some case
318
+ obj.name = MeasuringPlugin.OBJ_NAME;
319
+ return obj;
320
+ }
321
+ /**
322
+ * Draw completed
323
+ */
324
+ done() {
325
+ if (this.mode === null)
326
+ return;
327
+ let needsClear = false;
328
+ // for measure area, we need to make a close surface, then add area label
329
+ const count = this.pointArray.length;
330
+ if (this.mode === MeasuringMode.Area && this.polyline) {
331
+ if (count > 2) {
332
+ const p0 = this.pointArray[0];
333
+ this.polyline.geometry.setFromPoints([...this.pointArray, p0]); // close the line as a loop
334
+ const area = this.calculateArea(this.pointArray);
335
+ const label = `${showPrecisionValue(getLengthValueByUnit(area, 'm', this.options.unit, 2).value, this.options.precision)} ${this.getUnitString()}`;
336
+ const p = this.getBarycenter(this.pointArray);
337
+ const labelObj = this.createLabel(label);
338
+ labelObj.position.copy(p);
339
+ if (labelObj.element)
340
+ labelObj.element.innerHTML = label;
341
+ this.labels.push(labelObj);
342
+ }
343
+ else {
344
+ needsClear = true;
345
+ }
346
+ }
347
+ if (this.mode === MeasuringMode.Distance) {
348
+ if (count < 2) {
349
+ needsClear = true;
350
+ }
351
+ }
352
+ if (this.mode === MeasuringMode.Angle && this.polyline) {
353
+ if (count >= 3) {
354
+ const p0 = this.pointArray[0];
355
+ const p1 = this.pointArray[1];
356
+ const p2 = this.pointArray[2];
357
+ const dir0 = new Vector3(p0.x - p1.x, p0.y - p1.y, p0.z - p1.z).normalize();
358
+ const dir1 = this.getAngleBisector(p0, p1, p2);
359
+ const dir2 = new Vector3(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z).normalize();
360
+ const angle = this.calculateAngle(p0, p1, p2);
361
+ const label = `${showPrecisionValue(angle, this.options.precision)} ${this.getUnitString()}`;
362
+ const distance = Math.min(p0.distanceTo(p1), p2.distanceTo(p1));
363
+ let d = distance * 0.3; // distance from label to p1
364
+ let p = p1.clone().add(new Vector3(dir1.x * d, dir1.y * d, dir1.z * d)); // label's position
365
+ const labelObj = this.createLabel(label);
366
+ labelObj.position.set(p.x, p.y, p.z);
367
+ labelObj.element.innerHTML = label;
368
+ this.labels.push(labelObj);
369
+ d = distance * 0.2; // distance from arc to p1
370
+ p = p1.clone().add(new Vector3(dir1.x * d, dir1.y * d, dir1.z * d)); // arc's middle position
371
+ const arcP0 = p1.clone().add(new Vector3(dir0.x * d, dir0.y * d, dir0.z * d));
372
+ const arcP2 = p1.clone().add(new Vector3(dir2.x * d, dir2.y * d, dir2.z * d));
373
+ this.curve = this.createCurve(arcP0, p, arcP2);
374
+ this.scene.add(this.curve);
375
+ }
376
+ else {
377
+ needsClear = true;
378
+ }
379
+ }
380
+ if (!needsClear) {
381
+ // 存储测量3d对象
382
+ if (this.pointMarkers.length > 0)
383
+ this.pointMarkers.forEach(p => this.objectsStore.add(p));
384
+ if (this.polyline)
385
+ this.objectsStore.add(this.polyline);
386
+ if (this.faces)
387
+ this.objectsStore.add(this.faces);
388
+ if (this.curve)
389
+ this.objectsStore.add(this.curve);
390
+ if (this.labels.length > 0)
391
+ this.labels.forEach(l => this.objectsStore.add(l));
392
+ this.pointMarkers = [];
393
+ this.polyline = undefined;
394
+ this.faces = undefined;
395
+ this.curve = undefined;
396
+ this.labels = [];
397
+ }
398
+ this.close();
399
+ this.ssp.render();
400
+ // events
401
+ this.onDone();
402
+ }
403
+ /**
404
+ * Adds or update temp label and position
405
+ */
406
+ addOrUpdateTempLabel(label, position) {
407
+ if (!this.tempLabel) {
408
+ this.tempLabel = this.createLabel(label);
409
+ }
410
+ this.tempLabel.position.set(position.x, position.y, position.z);
411
+ this.tempLabel.element.innerHTML = label;
412
+ }
413
+ /**
414
+ * Creates label
415
+ */
416
+ createLabel(text) {
417
+ const div = document.createElement('div');
418
+ div.innerHTML = text;
419
+ div.style.padding = '3px 6px';
420
+ div.style.color = '#fff';
421
+ div.style.fontSize = '12px';
422
+ div.style.position = 'absolute';
423
+ div.style.backgroundColor = 'rgba(25, 25, 25, 0.3)';
424
+ div.style.borderRadius = '12px';
425
+ div.style.top = '0px';
426
+ div.style.left = '0px';
427
+ const obj = this.ssp.createPoiNode({ id: randomString(), element: div, type: '2D', });
428
+ obj.name = MeasuringPlugin.LABEL_NAME;
429
+ return obj;
430
+ }
431
+ /**
432
+ * Creates the arc curve to indicate the angle in degree
433
+ */
434
+ createCurve(p0, p1, p2) {
435
+ const curve = new QuadraticBezierCurve3(p0, p1, p2);
436
+ const points = curve.getPoints(4); // get points
437
+ const geometry = new BufferGeometry().setFromPoints(points);
438
+ const obj = new Line(geometry, MeasuringPlugin.LINE_MATERIAL);
439
+ obj.name = MeasuringPlugin.OBJ_NAME;
440
+ return obj;
441
+ }
442
+ /**
443
+ * Calculates area
444
+ * TODO: for concave polygon, the value doesn't right, need to fix it
445
+ * @param points
446
+ */
447
+ calculateArea(points) {
448
+ let area = 0;
449
+ for (let i = 0, j = 1, k = 2; k < points.length; j++, k++) {
450
+ const a = points[i].distanceTo(points[j]);
451
+ const b = points[j].distanceTo(points[k]);
452
+ const c = points[k].distanceTo(points[i]);
453
+ const p = (a + b + c) / 2;
454
+ area += Math.sqrt(p * (p - a) * (p - b) * (p - c));
455
+ }
456
+ return area;
457
+ }
458
+ /**
459
+ * Gets included angle of two lines in degree
460
+ */
461
+ calculateAngle(startPoint, middlePoint, endPoint) {
462
+ const p0 = startPoint;
463
+ const p1 = middlePoint;
464
+ const p2 = endPoint;
465
+ const dir0 = new Vector3(p0.x - p1.x, p0.y - p1.y, p0.z - p1.z);
466
+ const dir1 = new Vector3(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
467
+ const angle = dir0.angleTo(dir1);
468
+ return angle * 180 / Math.PI; // convert to degree
469
+ }
470
+ /**
471
+ * Gets angle bisector of two lines
472
+ */
473
+ getAngleBisector(startPoint, middlePoint, endPoint) {
474
+ const p0 = startPoint;
475
+ const p1 = middlePoint;
476
+ const p2 = endPoint;
477
+ const dir0 = new Vector3(p0.x - p1.x, p0.y - p1.y, p0.z - p1.z).normalize();
478
+ const dir2 = new Vector3(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z).normalize();
479
+ return new Vector3(dir0.x + dir2.x, dir0.y + dir2.y, dir0.z + dir2.z).normalize(); // the middle direction between dir0 and dir2
480
+ }
481
+ /**
482
+ * Get the barycenter of points
483
+ */
484
+ getBarycenter(points) {
485
+ const l = points.length;
486
+ let x = 0;
487
+ let y = 0;
488
+ let z = 0;
489
+ points.forEach(p => {
490
+ x += p.x;
491
+ y += p.y;
492
+ z += p.z;
493
+ });
494
+ return new Vector3(x / l, y / l, z / l);
495
+ }
496
+ /**
497
+ * Gets unit string for distance, area or angle
498
+ */
499
+ getUnitString() {
500
+ if (this.mode === MeasuringMode.Distance)
501
+ return getUnitStr(this.options.unit);
502
+ if (this.mode === MeasuringMode.Area)
503
+ return `${getUnitStr(this.options.unit, 2)}`;
504
+ if (this.mode === MeasuringMode.Angle)
505
+ return '°';
506
+ return '';
507
+ }
508
+ /**
509
+ * Converts a number to a string with proper fraction digits
510
+ */
511
+ numberToString(num) {
512
+ if (num < 0.0001) {
513
+ return num.toString();
514
+ }
515
+ let fractionDigits = 2;
516
+ if (num < 0.01) {
517
+ fractionDigits = 4;
518
+ }
519
+ else if (num < 0.1) {
520
+ fractionDigits = 3;
521
+ }
522
+ return num.toFixed(fractionDigits);
523
+ }
524
+ }
525
+ // lineWidth is ignored for Chrome on Windows, which is a known issue:
526
+ // https://github.com/mrdoob/three.js/issues/269
527
+ MeasuringPlugin.LINE_MATERIAL = new LineBasicMaterial({ color: 0xfff000, linewidth: 2, opacity: 0.8, transparent: true, side: DoubleSide, depthWrite: false, depthTest: false, });
528
+ MeasuringPlugin.MESH_MATERIAL = new MeshBasicMaterial({ color: 0x87cefa, transparent: true, opacity: 0.8, side: DoubleSide, depthWrite: false, depthTest: false, });
529
+ MeasuringPlugin.MAX_DISTANCE = 500; // when intersected object's distance is too far away, then ignore it
530
+ MeasuringPlugin.OBJ_NAME = 'object_for_measure' + randomString();
531
+ MeasuringPlugin.LABEL_NAME = 'label_for_measure' + randomString();
532
+
533
+ export { MeasuringMode, MeasuringPlugin as default };
534
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":["../src/utils/UnitConversionUtils.ts","../src/utils/DecimalPrecisionUtils.ts","../src/imgs/circle.webp","../src/index.ts"],"sourcesContent":["import { UnitType, } from './ProjectSettingsDef'\r\n\r\nfunction __getPointBaseLength () {\r\n\r\n const testDiv: HTMLElement = document.createElement( 'div' ) // get ppi\r\n\r\n testDiv.setAttribute( 'style', 'height: 1in; visibility: hidden; position: absolute; margin: 0; padding: 0;' )\r\n document.body.appendChild( testDiv )\r\n const baseLen = testDiv.clientHeight\r\n const inchToMeter = 0.0254\r\n\r\n return inchToMeter / baseLen\r\n\r\n}\r\n\r\nexport const unitConversionByMeter: Record<UnitType, number> = {\r\n m: 1,\r\n mm: 0.001,\r\n cm: 0.01,\r\n ft: 0.3048,\r\n in: 0.0254,\r\n pt: __getPointBaseLength(),\r\n}\r\n\r\nconst _getSuffix = ( power: number ) => {\r\n\r\n if ( power === 2 ) {\r\n\r\n return '²'\r\n \r\n }\r\n if ( power === 3 ) {\r\n\r\n return '³'\r\n \r\n }\r\n return ''\r\n\r\n}\r\n\r\nexport const getUnitStr = ( unit: UnitType, power = 1 ): string => {\r\n\r\n return unit + _getSuffix( power )\r\n\r\n}\r\n\r\n/**\r\n * Gets unit\r\n * value\r\n * sourceUnit\r\n * targetUnit\r\n */\r\ninterface valueWithUnit {\r\n value: number;\r\n unit: string;\r\n}\r\nexport const getLengthValueByUnit = ( value: number, sourceUnit: UnitType, targetUnit: UnitType, power = 1 ): valueWithUnit => {\r\n\r\n if ( targetUnit === null || targetUnit === undefined ) {\r\n\r\n targetUnit = sourceUnit\r\n \r\n }\r\n if ( targetUnit === sourceUnit ) {\r\n\r\n return {\r\n value,\r\n unit: getUnitStr( targetUnit ),\r\n }\r\n \r\n } else {\r\n\r\n const targetValue = value * Math.pow( unitConversionByMeter[ sourceUnit ] / unitConversionByMeter[ targetUnit ], power )\r\n\r\n return {\r\n value: targetValue,\r\n unit: getUnitStr( targetUnit ) + _getSuffix( power ),\r\n }\r\n \r\n }\r\n\r\n}\r\n","export const showPrecisionValue = ( value: number, precistionType: number ) => {\r\n\r\n const str = value.toFixed( precistionType )\r\n\r\n return str\r\n\r\n}\r\n","var img = \"data:image/webp;base64,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\";\n export default img;","import SoonSpace, { PoiNode, } from 'soonspacejs'\r\nimport { BufferGeometry, Camera, DoubleSide, Line, LineBasicMaterial, Mesh, MeshBasicMaterial, Object3D, QuadraticBezierCurve3, Scene, Sprite, SpriteMaterial, Vector3, } from 'three'\r\nimport { getUnitStr, getLengthValueByUnit, } from './utils/UnitConversionUtils'\r\nimport { Options, } from './utils/ProjectSettingsDef'\r\nimport { showPrecisionValue, } from './utils/DecimalPrecisionUtils'\r\n\r\nimport circleImg from './imgs/circle.webp'\r\n\r\nexport enum MeasuringMode {\r\n Distance = 'Distance',\r\n Area = 'Area',\r\n Angle = 'Angle'\r\n}\r\n\r\nconst { utils: { randomString, }, } = SoonSpace\r\n\r\n/**\r\n * MeasuringPlugin\r\n */\r\nclass MeasuringPlugin {\r\n\r\n // lineWidth is ignored for Chrome on Windows, which is a known issue:\r\n // https://github.com/mrdoob/three.js/issues/269\r\n static LINE_MATERIAL = new LineBasicMaterial( { color: 0xfff000, linewidth: 2, opacity: 0.8, transparent: true, side: DoubleSide, depthWrite: false, depthTest: false, } )\r\n static MESH_MATERIAL = new MeshBasicMaterial( { color: 0x87cefa, transparent: true, opacity: 0.8, side: DoubleSide, depthWrite: false, depthTest: false, } )\r\n static MAX_DISTANCE = 500 // when intersected object's distance is too far away, then ignore it\r\n static OBJ_NAME = 'object_for_measure' + randomString()\r\n static LABEL_NAME = 'label_for_measure' + randomString()\r\n\r\n mode: MeasuringMode | null = null\r\n protected options: Required<Options> = { unit: 'm', precision: 2, }\r\n\r\n protected scene: Scene\r\n protected camera: Camera\r\n protected spriteMaterial?: SpriteMaterial\r\n\r\n // 缓存之前的绘制对象\r\n objectsStore = new Set<Object3D>()\r\n\r\n onCancel = () => {}\r\n onDone = () => {}\r\n\r\n protected pointMarkers: Sprite[] = [] // 边缘点标记\r\n protected polyline?: Line // distance/area/angle 使用的绘制线段\r\n protected faces?: Mesh // area \r\n protected curve?: Line // angle 角度曲线\r\n protected labels: PoiNode[] = [] // poinode 标签\r\n\r\n protected pointArray: Vector3[] = []\r\n\r\n protected tempPointMarker?: Sprite // used to store temporary Points\r\n protected tempLine?: Line // used to store temporary line, which is useful for drawing line/area/angle as mouse moves\r\n protected tempLabel?: PoiNode // used to store temporary label as mouse moves\r\n\r\n protected lastClickTime?: number // save the last click time, in order to detect double click event\r\n\r\n constructor ( readonly ssp: SoonSpace ) {\r\n\r\n const { viewport: { scene, camera, }, } = ssp\r\n\r\n this.scene = scene\r\n this.camera = camera\r\n \r\n }\r\n\r\n get domElement (): HTMLDivElement {\r\n\r\n return this.ssp.domElement as HTMLDivElement\r\n \r\n }\r\n\r\n /**\r\n * Starts the measurement\r\n */\r\n start ( mode = MeasuringMode.Distance, options: Options = {} ) {\r\n\r\n\r\n const { unit = 'm', precision = 2, } = options\r\n\r\n this.mode = mode\r\n this.options.unit = unit\r\n this.options.precision = precision\r\n\r\n // add mouse 'click' event, but do not trigger highlight for mouse drag event\r\n // mouseup/mousedown/mousemove event is prevented by OrbitControls, let's use pointerup/pointerdown/pointermove\r\n this.ssp.signals.mouseMove.add( this.mousemove )\r\n this.ssp.signals.click.add( this.click )\r\n this.ssp.signals.dblClick.add( this.dblclick )\r\n this.ssp.signals.keyDown.add( this.keydown )\r\n\r\n this.pointArray = []\r\n\r\n // polyline is required for measuring distance, area and angle\r\n this.polyline = this.createLine()\r\n this.scene.add( this.polyline )\r\n\r\n if ( this.mode === MeasuringMode.Area ) {\r\n\r\n this.faces = this.createFaces()\r\n this.scene.add( this.faces )\r\n \r\n }\r\n\r\n this.domElement.style.cursor = 'crosshair'\r\n \r\n }\r\n\r\n /**\r\n * Ends the measurement\r\n */\r\n close () {\r\n\r\n if ( this.mode === null ) return\r\n\r\n this.ssp.signals.mouseMove.remove( this.mousemove )\r\n this.ssp.signals.click.remove( this.click )\r\n this.ssp.signals.dblClick.remove( this.dblclick )\r\n this.ssp.signals.keyDown.remove( this.keydown )\r\n\r\n this.mode = null\r\n this.domElement.style.cursor = ''\r\n this.pointArray = []\r\n\r\n this.tempPointMarker && this.scene.remove( this.tempPointMarker )\r\n this.tempLine && this.scene.remove( this.tempLine )\r\n this.tempLabel && this.ssp.removeObject( this.tempLabel )\r\n this.pointMarkers.forEach( item => this.scene.remove( item ) )\r\n this.polyline && this.scene.remove( this.polyline )\r\n this.faces && this.scene.remove( this.faces )\r\n this.curve && this.scene.remove( this.curve )\r\n this.labels.forEach( item => this.ssp.removeObject( item ) )\r\n\r\n this.tempPointMarker = undefined\r\n this.tempLine = undefined\r\n this.tempLabel = undefined\r\n this.pointMarkers = []\r\n this.polyline = undefined\r\n this.faces = undefined\r\n this.curve = undefined\r\n this.labels = []\r\n\r\n this.ssp.render()\r\n \r\n }\r\n\r\n cancel () {\r\n\r\n this.close()\r\n\r\n // events\r\n this.onCancel()\r\n \r\n }\r\n\r\n clear () {\r\n\r\n this.objectsStore.forEach( item => this.ssp.removeObject( item ) )\r\n this.objectsStore.clear()\r\n \r\n }\r\n\r\n /**\r\n * Initializes point marker material\r\n */\r\n initPointMarkerMaterial () {\r\n\r\n const markerTexture = SoonSpace.utils.textureLoader.load( circleImg )\r\n\r\n this.spriteMaterial = new SpriteMaterial( {\r\n map: markerTexture,\r\n depthTest: false,\r\n depthWrite: false,\r\n sizeAttenuation: false,\r\n opacity: 0.8,\r\n } )\r\n \r\n }\r\n\r\n /**\r\n * Creates point marker\r\n */\r\n private createPointMarker ( position?: Vector3 ): Sprite {\r\n\r\n if ( !this.spriteMaterial ) {\r\n\r\n this.initPointMarkerMaterial()\r\n \r\n }\r\n const scale = 0.012 // change marker's size here\r\n const obj = new Sprite( this.spriteMaterial )\r\n\r\n obj.scale.set( scale, scale, scale )\r\n if ( position ) obj.position.copy( position )\r\n obj.name = MeasuringPlugin.OBJ_NAME\r\n return obj\r\n \r\n }\r\n\r\n /**\r\n * Creates Line\r\n */\r\n private createLine ( material = MeasuringPlugin.LINE_MATERIAL ): Line {\r\n\r\n const geom = new BufferGeometry()\r\n const obj = new Line( geom, material )\r\n\r\n obj.frustumCulled = false // Force to draw it. This fixes a bug that it disappear in some case\r\n obj.name = MeasuringPlugin.OBJ_NAME\r\n return obj\r\n \r\n }\r\n\r\n /**\r\n * Creates Mesh\r\n */\r\n private createFaces () {\r\n\r\n const geom = new BufferGeometry()\r\n const obj = new Mesh( geom, MeasuringPlugin.MESH_MATERIAL )\r\n\r\n // since we have to use BufferGeometry rather than Geometry, and we need to store points,\r\n // let's store points into userData!\r\n obj.userData.vertices = []\r\n obj.frustumCulled = false // Force to draw it. This fixes a bug that it disappear in some case\r\n obj.name = MeasuringPlugin.OBJ_NAME\r\n return obj\r\n \r\n }\r\n\r\n /**\r\n * Draw completed\r\n */\r\n done () {\r\n\r\n if ( this.mode === null ) return\r\n\r\n let needsClear = false\r\n\r\n // for measure area, we need to make a close surface, then add area label\r\n const count = this.pointArray.length\r\n\r\n if ( this.mode === MeasuringMode.Area && this.polyline ) {\r\n\r\n if ( count > 2 ) {\r\n\r\n const p0 = this.pointArray[ 0 ]\r\n\r\n this.polyline.geometry.setFromPoints( [ ...this.pointArray, p0 ] ) // close the line as a loop\r\n const area = this.calculateArea( this.pointArray )\r\n const label = `${showPrecisionValue( getLengthValueByUnit( area, 'm', this.options.unit, 2 ).value, this.options.precision )} ${this.getUnitString()}`\r\n const p = this.getBarycenter( this.pointArray )\r\n const labelObj = this.createLabel( label )\r\n\r\n labelObj.position.copy( p )\r\n if ( labelObj.element ) labelObj.element.innerHTML = label\r\n this.labels.push( labelObj )\r\n \r\n } else {\r\n\r\n needsClear = true\r\n \r\n }\r\n \r\n }\r\n\r\n if ( this.mode === MeasuringMode.Distance ) {\r\n\r\n if ( count < 2 ) {\r\n\r\n needsClear = true\r\n \r\n }\r\n \r\n }\r\n\r\n if ( this.mode === MeasuringMode.Angle && this.polyline ) {\r\n\r\n if ( count >= 3 ) {\r\n\r\n const p0 = this.pointArray[ 0 ]\r\n const p1 = this.pointArray[ 1 ]\r\n const p2 = this.pointArray[ 2 ]\r\n const dir0 = new Vector3( p0.x - p1.x, p0.y - p1.y, p0.z - p1.z ).normalize()\r\n const dir1 = this.getAngleBisector( p0, p1, p2 )\r\n const dir2 = new Vector3( p2.x - p1.x, p2.y - p1.y, p2.z - p1.z ).normalize()\r\n const angle = this.calculateAngle( p0, p1, p2 )\r\n const label = `${showPrecisionValue( angle, this.options.precision )} ${this.getUnitString()}`\r\n const distance = Math.min( p0.distanceTo( p1 ), p2.distanceTo( p1 ) )\r\n let d = distance * 0.3 // distance from label to p1\r\n let p = p1.clone().add( new Vector3( dir1.x * d, dir1.y * d, dir1.z * d ) ) // label's position\r\n const labelObj = this.createLabel( label )\r\n\r\n labelObj.position.set( p.x, p.y, p.z )\r\n labelObj.element.innerHTML = label\r\n this.labels.push( labelObj )\r\n\r\n d = distance * 0.2 // distance from arc to p1\r\n p = p1.clone().add( new Vector3( dir1.x * d, dir1.y * d, dir1.z * d ) ) // arc's middle position\r\n const arcP0 = p1.clone().add( new Vector3( dir0.x * d, dir0.y * d, dir0.z * d ) )\r\n const arcP2 = p1.clone().add( new Vector3( dir2.x * d, dir2.y * d, dir2.z * d ) )\r\n\r\n this.curve = this.createCurve( arcP0, p, arcP2 )\r\n this.scene.add( this.curve )\r\n \r\n } else {\r\n\r\n needsClear = true\r\n \r\n }\r\n \r\n }\r\n\r\n if ( !needsClear ) {\r\n\r\n // 存储测量3d对象\r\n if ( this.pointMarkers.length > 0 ) this.pointMarkers.forEach( p => this.objectsStore.add( p ) )\r\n if ( this.polyline ) this.objectsStore.add( this.polyline )\r\n if ( this.faces ) this.objectsStore.add( this.faces )\r\n if ( this.curve ) this.objectsStore.add( this.curve )\r\n if ( this.labels.length > 0 ) this.labels.forEach( l => this.objectsStore.add( l ) )\r\n \r\n this.pointMarkers = []\r\n this.polyline = undefined\r\n this.faces = undefined\r\n this.curve = undefined\r\n this.labels = []\r\n \r\n }\r\n\r\n this.close()\r\n\r\n this.ssp.render()\r\n\r\n // events\r\n this.onDone()\r\n \r\n }\r\n\r\n mousemove = ( e: MouseEvent ) => {\r\n\r\n if ( this.mode === null ) return\r\n\r\n const point = this.getClosestIntersection( e )\r\n\r\n if ( !point ) return\r\n\r\n // draw the temp point as mouse moves\r\n if ( this.tempPointMarker ) {\r\n\r\n this.tempPointMarker.position.set( point.x, point.y, point.z )\r\n \r\n } else {\r\n\r\n this.tempPointMarker = this.createPointMarker( point )\r\n this.scene.add( this.tempPointMarker )\r\n \r\n }\r\n\r\n // draw the temp line as mouse moves\r\n if ( this.pointArray.length > 0 ) {\r\n\r\n const p0 = this.pointArray[ this.pointArray.length - 1 ] // get last point\r\n const line = this.tempLine || this.createLine()\r\n const geom = line.geometry\r\n const startPoint = this.pointArray[ 0 ]\r\n const lastPoint = this.pointArray[ this.pointArray.length - 1 ]\r\n\r\n if ( this.mode === MeasuringMode.Area ) {\r\n\r\n // draw two line segments for area\r\n geom.setFromPoints( [ lastPoint, point, startPoint ] ) // close the line as a loop\r\n \r\n } else {\r\n\r\n geom.setFromPoints( [ lastPoint, point ] )\r\n \r\n }\r\n if ( this.mode === MeasuringMode.Distance ) {\r\n\r\n const dist = p0.distanceTo( point )\r\n const label = `${showPrecisionValue( getLengthValueByUnit( dist, 'm', this.options.unit ).value, this.options.precision )} ${this.getUnitString()}` // hard code unit to 'm' here\r\n const position = new Vector3( ( point.x + p0.x ) / 2, ( point.y + p0.y ) / 2, ( point.z + p0.z ) / 2 )\r\n\r\n this.addOrUpdateTempLabel( label, position )\r\n \r\n }\r\n if ( !this.tempLine ) {\r\n\r\n this.scene.add( line ) // just add to scene once\r\n this.tempLine = line\r\n \r\n }\r\n \r\n }\r\n\r\n this.ssp.render()\r\n \r\n }\r\n\r\n dblclick = ( e: MouseEvent ) => {\r\n\r\n this.click( e )\r\n\r\n // double click means to done the draw operation\r\n this.done()\r\n \r\n }\r\n\r\n click = ( e: MouseEvent ) => {\r\n\r\n if ( this.mode === null ) return\r\n\r\n const point = this.getClosestIntersection( e )\r\n\r\n if ( !point ) return\r\n\r\n // double click triggers two click events, we need to avoid the second click here\r\n const now = Date.now()\r\n\r\n if ( this.lastClickTime && ( now - this.lastClickTime < 300 ) ) {\r\n\r\n return\r\n \r\n }\r\n this.lastClickTime = now\r\n\r\n this.pointArray.push( point )\r\n const count = this.pointArray.length\r\n const marker = this.createPointMarker( point )\r\n\r\n this.pointMarkers.push( marker )\r\n this.scene.add( marker )\r\n\r\n if ( this.polyline ) {\r\n\r\n this.polyline.geometry.setFromPoints( this.pointArray )\r\n if ( this.tempLabel && count > 1 ) {\r\n\r\n const p0 = this.pointArray[ count - 2 ]\r\n\r\n this.tempLabel.position.set( ( p0.x + point.x ) / 2, ( p0.y + point.y ) / 2, ( p0.z + point.z ) / 2 )\r\n this.scene.add( this.tempLabel )\r\n this.labels.push( this.tempLabel )\r\n this.tempLabel = undefined\r\n \r\n }\r\n \r\n }\r\n\r\n if ( this.mode === MeasuringMode.Area && this.faces ) {\r\n\r\n const geom = this.faces.geometry as BufferGeometry\r\n const vertices = this.faces.userData.vertices\r\n\r\n vertices.push( point )\r\n geom.setFromPoints( vertices )\r\n const len = vertices.length\r\n\r\n if ( len > 2 ) {\r\n\r\n const indexArray = []\r\n\r\n for ( let i = 1; i < len - 1; ++i ) {\r\n\r\n indexArray.push( 0, i, i + 1 ) // add one triangle\r\n \r\n }\r\n geom.setIndex( indexArray )\r\n \r\n }\r\n \r\n }\r\n\r\n if ( this.mode === MeasuringMode.Angle && this.pointArray.length >= 3 ) {\r\n\r\n this.done()\r\n \r\n }\r\n \r\n this.ssp.render()\r\n \r\n }\r\n\r\n keydown = ( e: KeyboardEvent ) => {\r\n\r\n if ( e.key === 'Enter' ) {\r\n\r\n this.done()\r\n \r\n } else if ( e.key === 'Escape' ) {\r\n\r\n this.cancel()\r\n \r\n }\r\n \r\n }\r\n\r\n /**\r\n * The the closest intersection\r\n * @param e\r\n */\r\n getClosestIntersection = ( e: MouseEvent ) => {\r\n\r\n if ( this.mode === null ) return\r\n \r\n let intersects = this.ssp.viewport.getIntersects( e )\r\n\r\n if ( intersects && intersects.length > 0 ) {\r\n\r\n // filter out the objects for measurement\r\n intersects = intersects.filter( item => {\r\n\r\n return item.object.name !== MeasuringPlugin.OBJ_NAME && item.object.visible\r\n \r\n } )\r\n if ( intersects.length > 0 && intersects[ 0 ].distance < MeasuringPlugin.MAX_DISTANCE ) {\r\n\r\n return intersects[ 0 ].point\r\n \r\n }\r\n \r\n }\r\n return null\r\n \r\n }\r\n\r\n /**\r\n * Adds or update temp label and position\r\n */\r\n addOrUpdateTempLabel ( label: string, position: Vector3 ) {\r\n\r\n if ( !this.tempLabel ) {\r\n\r\n this.tempLabel = this.createLabel( label )\r\n \r\n }\r\n this.tempLabel.position.set( position.x, position.y, position.z )\r\n this.tempLabel.element.innerHTML = label\r\n \r\n }\r\n\r\n /**\r\n * Creates label\r\n */\r\n createLabel ( text: string ): PoiNode {\r\n\r\n const div = document.createElement( 'div' )\r\n\r\n div.innerHTML = text\r\n div.style.padding = '3px 6px'\r\n div.style.color = '#fff'\r\n div.style.fontSize = '12px'\r\n div.style.position = 'absolute'\r\n div.style.backgroundColor = 'rgba(25, 25, 25, 0.3)'\r\n div.style.borderRadius = '12px'\r\n div.style.top = '0px'\r\n div.style.left = '0px'\r\n\r\n const obj = this.ssp.createPoiNode( { id: randomString(), element: div, type: '2D', } )\r\n\r\n obj.name = MeasuringPlugin.LABEL_NAME\r\n\r\n return obj\r\n \r\n }\r\n\r\n /**\r\n * Creates the arc curve to indicate the angle in degree\r\n */\r\n createCurve ( p0: Vector3, p1: Vector3, p2: Vector3 ) {\r\n\r\n const curve = new QuadraticBezierCurve3( p0, p1, p2 )\r\n const points = curve.getPoints( 4 ) // get points\r\n const geometry = new BufferGeometry().setFromPoints( points )\r\n const obj = new Line( geometry, MeasuringPlugin.LINE_MATERIAL )\r\n\r\n obj.name = MeasuringPlugin.OBJ_NAME\r\n return obj\r\n \r\n }\r\n\r\n /**\r\n * Calculates area\r\n * TODO: for concave polygon, the value doesn't right, need to fix it\r\n * @param points\r\n */\r\n calculateArea ( points: Vector3[] ) {\r\n\r\n let area = 0\r\n\r\n for ( let i = 0, j = 1, k = 2; k < points.length; j++, k++ ) {\r\n\r\n const a = points[ i ].distanceTo( points[ j ] )\r\n const b = points[ j ].distanceTo( points[ k ] )\r\n const c = points[ k ].distanceTo( points[ i ] )\r\n const p = ( a + b + c ) / 2\r\n\r\n area += Math.sqrt( p * ( p - a ) * ( p - b ) * ( p - c ) )\r\n \r\n }\r\n return area\r\n \r\n }\r\n\r\n /**\r\n * Gets included angle of two lines in degree\r\n */\r\n calculateAngle ( startPoint: Vector3, middlePoint: Vector3, endPoint: Vector3 ) {\r\n\r\n const p0 = startPoint\r\n const p1 = middlePoint\r\n const p2 = endPoint\r\n const dir0 = new Vector3( p0.x - p1.x, p0.y - p1.y, p0.z - p1.z )\r\n const dir1 = new Vector3( p2.x - p1.x, p2.y - p1.y, p2.z - p1.z )\r\n const angle = dir0.angleTo( dir1 )\r\n\r\n return angle * 180 / Math.PI // convert to degree\r\n \r\n }\r\n\r\n /**\r\n * Gets angle bisector of two lines\r\n */\r\n getAngleBisector ( startPoint: Vector3, middlePoint: Vector3, endPoint: Vector3 ): Vector3 {\r\n\r\n const p0 = startPoint\r\n const p1 = middlePoint\r\n const p2 = endPoint\r\n const dir0 = new Vector3( p0.x - p1.x, p0.y - p1.y, p0.z - p1.z ).normalize()\r\n const dir2 = new Vector3( p2.x - p1.x, p2.y - p1.y, p2.z - p1.z ).normalize()\r\n\r\n return new Vector3( dir0.x + dir2.x, dir0.y + dir2.y, dir0.z + dir2.z ).normalize() // the middle direction between dir0 and dir2\r\n \r\n }\r\n\r\n /**\r\n * Get the barycenter of points\r\n */\r\n getBarycenter ( points: Vector3[] ): Vector3 {\r\n\r\n const l = points.length\r\n let x = 0\r\n let y = 0\r\n let z = 0\r\n\r\n points.forEach( p => {\r\n\r\n x += p.x; y += p.y; z += p.z \r\n\r\n } )\r\n return new Vector3( x / l, y / l, z / l )\r\n \r\n }\r\n\r\n /**\r\n * Gets unit string for distance, area or angle\r\n */\r\n getUnitString () {\r\n\r\n if ( this.mode === MeasuringMode.Distance ) return getUnitStr( this.options.unit )\r\n if ( this.mode === MeasuringMode.Area ) return `${getUnitStr( this.options.unit, 2 )}`\r\n if ( this.mode === MeasuringMode.Angle ) return '°'\r\n return ''\r\n \r\n }\r\n\r\n /**\r\n * Converts a number to a string with proper fraction digits\r\n */\r\n numberToString ( num: number ) {\r\n\r\n if ( num < 0.0001 ) {\r\n\r\n return num.toString()\r\n \r\n }\r\n let fractionDigits = 2\r\n\r\n if ( num < 0.01 ) {\r\n\r\n fractionDigits = 4\r\n \r\n } else if ( num < 0.1 ) {\r\n\r\n fractionDigits = 3\r\n \r\n }\r\n return num.toFixed( fractionDigits )\r\n \r\n }\r\n\r\n}\r\n\r\nexport default MeasuringPlugin"],"names":["circleImg"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@soonspacejs/plugin-measuring",
3
3
  "pluginName": "MeasuringPlugin",
4
- "version": "2.13.5",
4
+ "version": "2.13.7",
5
5
  "description": "Measuring plugin for SoonSpace.js",
6
6
  "main": "dist/index.esm.js",
7
7
  "module": "dist/index.esm.js",
@@ -13,8 +13,8 @@
13
13
  ],
14
14
  "author": "xunwei",
15
15
  "license": "UNLICENSED",
16
- "gitHead": "e19da4dc04255f2374645aa083e0116668894874",
16
+ "gitHead": "550040550bf20ec0015982ff1159d0cfe9b35ed3",
17
17
  "peerDependencies": {
18
- "soonspacejs": "2.13.5"
18
+ "soonspacejs": "2.13.7"
19
19
  }
20
20
  }
package/dist/index.d.ts DELETED
@@ -1,117 +0,0 @@
1
- import SoonSpace, { PoiNode } from 'soonspacejs';
2
- import { BufferGeometry, Camera, Line, LineBasicMaterial, Mesh, MeshBasicMaterial, Object3D, Scene, Sprite, SpriteMaterial, Vector3 } from 'three';
3
- import { Options } from './utils/ProjectSettingsDef';
4
- export declare enum MeasuringMode {
5
- Distance = "Distance",
6
- Area = "Area",
7
- Angle = "Angle"
8
- }
9
- /**
10
- * MeasuringPlugin
11
- */
12
- declare class MeasuringPlugin {
13
- readonly ssp: SoonSpace;
14
- static LINE_MATERIAL: LineBasicMaterial;
15
- static MESH_MATERIAL: MeshBasicMaterial;
16
- static MAX_DISTANCE: number;
17
- static OBJ_NAME: string;
18
- static LABEL_NAME: string;
19
- mode: MeasuringMode | null;
20
- protected options: Required<Options>;
21
- protected scene: Scene;
22
- protected camera: Camera;
23
- protected spriteMaterial?: SpriteMaterial;
24
- objectsStore: Set<Object3D<import("three").Object3DEventMap>>;
25
- onCancel: () => void;
26
- onDone: () => void;
27
- protected pointMarkers: Sprite[];
28
- protected polyline?: Line;
29
- protected faces?: Mesh;
30
- protected curve?: Line;
31
- protected labels: PoiNode[];
32
- protected pointArray: Vector3[];
33
- protected tempPointMarker?: Sprite;
34
- protected tempLine?: Line;
35
- protected tempLabel?: PoiNode;
36
- protected lastClickTime?: number;
37
- constructor(ssp: SoonSpace);
38
- get domElement(): HTMLDivElement;
39
- /**
40
- * Starts the measurement
41
- */
42
- start(mode?: MeasuringMode, options?: Options): void;
43
- /**
44
- * Ends the measurement
45
- */
46
- close(): void;
47
- cancel(): void;
48
- clear(): void;
49
- /**
50
- * Initializes point marker material
51
- */
52
- initPointMarkerMaterial(): void;
53
- /**
54
- * Creates point marker
55
- */
56
- private createPointMarker;
57
- /**
58
- * Creates Line
59
- */
60
- private createLine;
61
- /**
62
- * Creates Mesh
63
- */
64
- private createFaces;
65
- /**
66
- * Draw completed
67
- */
68
- done(): void;
69
- mousemove: (e: MouseEvent) => void;
70
- dblclick: (e: MouseEvent) => void;
71
- click: (e: MouseEvent) => void;
72
- keydown: (e: KeyboardEvent) => void;
73
- /**
74
- * The the closest intersection
75
- * @param e
76
- */
77
- getClosestIntersection: (e: MouseEvent) => Vector3 | null | undefined;
78
- /**
79
- * Adds or update temp label and position
80
- */
81
- addOrUpdateTempLabel(label: string, position: Vector3): void;
82
- /**
83
- * Creates label
84
- */
85
- createLabel(text: string): PoiNode;
86
- /**
87
- * Creates the arc curve to indicate the angle in degree
88
- */
89
- createCurve(p0: Vector3, p1: Vector3, p2: Vector3): Line<BufferGeometry<import("three").NormalBufferAttributes>, LineBasicMaterial, import("three").Object3DEventMap>;
90
- /**
91
- * Calculates area
92
- * TODO: for concave polygon, the value doesn't right, need to fix it
93
- * @param points
94
- */
95
- calculateArea(points: Vector3[]): number;
96
- /**
97
- * Gets included angle of two lines in degree
98
- */
99
- calculateAngle(startPoint: Vector3, middlePoint: Vector3, endPoint: Vector3): number;
100
- /**
101
- * Gets angle bisector of two lines
102
- */
103
- getAngleBisector(startPoint: Vector3, middlePoint: Vector3, endPoint: Vector3): Vector3;
104
- /**
105
- * Get the barycenter of points
106
- */
107
- getBarycenter(points: Vector3[]): Vector3;
108
- /**
109
- * Gets unit string for distance, area or angle
110
- */
111
- getUnitString(): string;
112
- /**
113
- * Converts a number to a string with proper fraction digits
114
- */
115
- numberToString(num: number): string;
116
- }
117
- export default MeasuringPlugin;
@@ -1 +0,0 @@
1
- export declare const showPrecisionValue: (value: number, precistionType: number) => string;
@@ -1,5 +0,0 @@
1
- export type UnitType = 'm' | 'mm' | 'cm' | 'ft' | 'in' | 'pt';
2
- export interface Options {
3
- unit?: UnitType;
4
- precision?: number;
5
- }
@@ -1,15 +0,0 @@
1
- import { UnitType } from './ProjectSettingsDef';
2
- export declare const unitConversionByMeter: Record<UnitType, number>;
3
- export declare const getUnitStr: (unit: UnitType, power?: number) => string;
4
- /**
5
- * Gets unit
6
- * value
7
- * sourceUnit
8
- * targetUnit
9
- */
10
- interface valueWithUnit {
11
- value: number;
12
- unit: string;
13
- }
14
- export declare const getLengthValueByUnit: (value: number, sourceUnit: UnitType, targetUnit: UnitType, power?: number) => valueWithUnit;
15
- export {};