locar 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/locar.es.js +146 -133
- package/dist/locar.umd.js +1 -1
- package/package.json +1 -1
package/dist/locar.es.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import { Vector3 as C, Euler as w, Quaternion as I, EventDispatcher as R, MathUtils as
|
|
1
|
+
import * as m from "three";
|
|
2
|
+
import { Vector3 as C, Euler as w, Quaternion as I, EventDispatcher as R, MathUtils as g } from "three";
|
|
3
3
|
class T {
|
|
4
4
|
/**
|
|
5
5
|
* Create a SphMercProjection.
|
|
@@ -13,29 +13,29 @@ class T {
|
|
|
13
13
|
* @param {number} lat - the latitude.
|
|
14
14
|
* @return {Array} Two-member array containing easting and northing.
|
|
15
15
|
*/
|
|
16
|
-
project(
|
|
17
|
-
return [this.#t(
|
|
16
|
+
project(t, i) {
|
|
17
|
+
return [this.#t(t), this.#l(i)];
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
20
|
* Unproject a Spherical Mercator easting and northing.
|
|
21
21
|
* @param {Array} projected - Two-member array containing easting and northing
|
|
22
22
|
* @return {Array} Two-member array containing longitude and latitude
|
|
23
23
|
*/
|
|
24
|
-
unproject(
|
|
25
|
-
return [this.#e(
|
|
24
|
+
unproject(t) {
|
|
25
|
+
return [this.#e(t[0]), this.#s(t[1])];
|
|
26
26
|
}
|
|
27
|
-
#t(
|
|
28
|
-
return
|
|
27
|
+
#t(t) {
|
|
28
|
+
return t / 180 * this.HALF_EARTH;
|
|
29
29
|
}
|
|
30
|
-
#l(
|
|
31
|
-
var i = Math.log(Math.tan((90 +
|
|
30
|
+
#l(t) {
|
|
31
|
+
var i = Math.log(Math.tan((90 + t) * Math.PI / 360)) / (Math.PI / 180);
|
|
32
32
|
return i * this.HALF_EARTH / 180;
|
|
33
33
|
}
|
|
34
|
-
#e(
|
|
35
|
-
return
|
|
34
|
+
#e(t) {
|
|
35
|
+
return t / this.HALF_EARTH * 180;
|
|
36
36
|
}
|
|
37
|
-
#s(
|
|
38
|
-
var i =
|
|
37
|
+
#s(t) {
|
|
38
|
+
var i = t / this.HALF_EARTH * 180;
|
|
39
39
|
return i = 180 / Math.PI * (2 * Math.atan(Math.exp(i * Math.PI / 180)) - Math.PI / 2), i;
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
@@ -55,16 +55,29 @@ class A {
|
|
|
55
55
|
* @param {string} eventName - the event to handle.
|
|
56
56
|
* @param {Function} eventHandler - the event handler function.
|
|
57
57
|
*/
|
|
58
|
-
on(
|
|
59
|
-
this.eventHandlers[
|
|
58
|
+
on(t, i) {
|
|
59
|
+
this.eventHandlers[t] === void 0 && (this.eventHandlers[t] = []), this.eventHandlers[t].push(i);
|
|
60
60
|
}
|
|
61
61
|
/**
|
|
62
62
|
* Emit an event.
|
|
63
63
|
* @param {string} eventName - the event to emit.
|
|
64
|
-
* @param ...params - parameters to pass to the event
|
|
64
|
+
* @param ...params - parameters to pass to the event handlers.
|
|
65
65
|
*/
|
|
66
|
-
emit(
|
|
67
|
-
this.eventHandlers[
|
|
66
|
+
emit(t, ...i) {
|
|
67
|
+
this.eventHandlers[t]?.forEach((e) => {
|
|
68
|
+
e(...i);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Remove an event handler.
|
|
73
|
+
* @param {string} eventName - the event to remove a handler from.
|
|
74
|
+
* @param {Function} eventHandler - the event handler function to remove.
|
|
75
|
+
*/
|
|
76
|
+
off(t, i) {
|
|
77
|
+
if (this.eventHandlers[t]) {
|
|
78
|
+
const e = this.eventHandlers[t].indexOf(i);
|
|
79
|
+
e > -1 && this.eventHandlers[t].splice(e, 1);
|
|
80
|
+
}
|
|
68
81
|
}
|
|
69
82
|
}
|
|
70
83
|
class k extends A {
|
|
@@ -87,8 +100,8 @@ class k extends A {
|
|
|
87
100
|
* setGpsOptions() below.
|
|
88
101
|
* @param {Object} serverLogger - an object which can optionally log GPS position to a server for debugging. null by default, so no logging will be done. This object should implement a sendData() method to send data (2nd arg) to a given endpoint (1st arg). Please see source code for details. Ensure you comply with privacy laws (GDPR or equivalent) if implementing this.
|
|
89
102
|
*/
|
|
90
|
-
constructor(
|
|
91
|
-
super(), this.scene =
|
|
103
|
+
constructor(t, i, e = {}, c = null) {
|
|
104
|
+
super(), this.scene = t, this.camera = i, this.#t = new T(), this.#e = null, this.#s = 0, this.#c = 100, this.#o = null, this.setGpsOptions(e), this.#i = null, this.#r = 0, this.#a = 0, this.#n = c;
|
|
92
105
|
}
|
|
93
106
|
/**
|
|
94
107
|
* Set the projection to use.
|
|
@@ -96,8 +109,8 @@ class k extends A {
|
|
|
96
109
|
* taking longitude and latitude as arguments and returning an array
|
|
97
110
|
* containing easting and northing.
|
|
98
111
|
*/
|
|
99
|
-
setProjection(
|
|
100
|
-
this.#t =
|
|
112
|
+
setProjection(t) {
|
|
113
|
+
this.#t = t;
|
|
101
114
|
}
|
|
102
115
|
/**
|
|
103
116
|
* Set the GPS options.
|
|
@@ -106,8 +119,8 @@ class k extends A {
|
|
|
106
119
|
* must move to process a new GPS reading, and the latter specifies the
|
|
107
120
|
* minimum accuracy, in metres, for a GPS reading to be counted.
|
|
108
121
|
*/
|
|
109
|
-
setGpsOptions(
|
|
110
|
-
|
|
122
|
+
setGpsOptions(t = {}) {
|
|
123
|
+
t.gpsMinDistance !== void 0 && (this.#s = t.gpsMinDistance), t.gpsMinAccuracy !== void 0 && (this.#c = t.gpsMinAccuracy);
|
|
111
124
|
}
|
|
112
125
|
/**
|
|
113
126
|
* Start the GPS on a real device
|
|
@@ -123,11 +136,11 @@ class k extends A {
|
|
|
123
136
|
this.#a = i.session;
|
|
124
137
|
}
|
|
125
138
|
return this.#o === null ? (this.#o = navigator.geolocation.watchPosition(
|
|
126
|
-
(
|
|
127
|
-
this.#h(
|
|
139
|
+
(t) => {
|
|
140
|
+
this.#h(t);
|
|
128
141
|
},
|
|
129
|
-
(
|
|
130
|
-
this.emit("gpserror",
|
|
142
|
+
(t) => {
|
|
143
|
+
this.emit("gpserror", t);
|
|
131
144
|
},
|
|
132
145
|
{
|
|
133
146
|
enableHighAccuracy: !0
|
|
@@ -151,10 +164,10 @@ class k extends A {
|
|
|
151
164
|
* @param {number} acc - The accuracy of the GPS reading in metres. May be
|
|
152
165
|
* ignored if lower than the specified minimum accuracy.
|
|
153
166
|
*/
|
|
154
|
-
fakeGps(
|
|
155
|
-
|
|
167
|
+
fakeGps(t, i, e = null, c = 0) {
|
|
168
|
+
e !== null && this.setElevation(e), this.#h({
|
|
156
169
|
coords: {
|
|
157
|
-
longitude:
|
|
170
|
+
longitude: t,
|
|
158
171
|
latitude: i,
|
|
159
172
|
accuracy: c
|
|
160
173
|
}
|
|
@@ -171,13 +184,13 @@ class k extends A {
|
|
|
171
184
|
* @param {number} lat - The latitude.
|
|
172
185
|
* @return {Array} a two member array containing the WebGL x and z coordinates
|
|
173
186
|
*/
|
|
174
|
-
lonLatToWorldCoords(
|
|
175
|
-
const
|
|
187
|
+
lonLatToWorldCoords(t, i) {
|
|
188
|
+
const e = this.#t.project(t, i);
|
|
176
189
|
if (this.#i)
|
|
177
|
-
|
|
190
|
+
e[0] -= this.#i[0], e[1] -= this.#i[1];
|
|
178
191
|
else
|
|
179
192
|
throw "No initial position determined";
|
|
180
|
-
return [
|
|
193
|
+
return [e[0], -e[1]];
|
|
181
194
|
}
|
|
182
195
|
/**
|
|
183
196
|
* Add a new AR object at a given latitude, longitude and elevation.
|
|
@@ -189,68 +202,68 @@ class k extends A {
|
|
|
189
202
|
* @param {Object} properties - properties describing the object (for example,
|
|
190
203
|
* the contents of the GeoJSON properties field).
|
|
191
204
|
*/
|
|
192
|
-
add(
|
|
193
|
-
|
|
194
|
-
position:
|
|
195
|
-
x:
|
|
196
|
-
z:
|
|
205
|
+
add(t, i, e, c, h = {}) {
|
|
206
|
+
t.properties = h, this.#d(t, i, e, c), this.scene.add(t), this.#n?.sendData("/object/new", {
|
|
207
|
+
position: t.position,
|
|
208
|
+
x: t.position.x,
|
|
209
|
+
z: t.position.z,
|
|
197
210
|
session: this.#a,
|
|
198
211
|
properties: h
|
|
199
212
|
});
|
|
200
213
|
}
|
|
201
|
-
#d(
|
|
202
|
-
const h = this.lonLatToWorldCoords(i,
|
|
203
|
-
c !== void 0 && (
|
|
214
|
+
#d(t, i, e, c) {
|
|
215
|
+
const h = this.lonLatToWorldCoords(i, e);
|
|
216
|
+
c !== void 0 && (t.position.y = c), [t.position.x, t.position.z] = h;
|
|
204
217
|
}
|
|
205
218
|
/**
|
|
206
219
|
* Set the elevation (y coordinate) of the camera.
|
|
207
220
|
* @param {number} elev - the elevation in metres.
|
|
208
221
|
*/
|
|
209
|
-
setElevation(
|
|
210
|
-
this.camera.position.y =
|
|
222
|
+
setElevation(t) {
|
|
223
|
+
this.camera.position.y = t;
|
|
211
224
|
}
|
|
212
|
-
#u(
|
|
213
|
-
this.#i = this.#t.project(
|
|
225
|
+
#u(t, i) {
|
|
226
|
+
this.#i = this.#t.project(t, i);
|
|
214
227
|
}
|
|
215
|
-
#h(
|
|
228
|
+
#h(t) {
|
|
216
229
|
let i = Number.MAX_VALUE;
|
|
217
230
|
this.#r++, this.#n?.sendData("/gps/new", {
|
|
218
231
|
gpsCount: this.#r,
|
|
219
|
-
lat:
|
|
220
|
-
lon:
|
|
221
|
-
acc:
|
|
232
|
+
lat: t.coords.latitude,
|
|
233
|
+
lon: t.coords.longitude,
|
|
234
|
+
acc: t.coords.accuracy,
|
|
222
235
|
session: this.#a
|
|
223
|
-
}),
|
|
224
|
-
latitude:
|
|
225
|
-
longitude:
|
|
226
|
-
} : i = this.#
|
|
227
|
-
|
|
228
|
-
|
|
236
|
+
}), t.coords.accuracy <= this.#c && (this.#e === null ? this.#e = {
|
|
237
|
+
latitude: t.coords.latitude,
|
|
238
|
+
longitude: t.coords.longitude
|
|
239
|
+
} : i = this.#g(this.#e, t.coords), i >= this.#s && (this.#e.longitude = t.coords.longitude, this.#e.latitude = t.coords.latitude, this.#i || (this.#u(
|
|
240
|
+
t.coords.longitude,
|
|
241
|
+
t.coords.latitude
|
|
229
242
|
), this.#n?.sendData("/worldorigin/new", {
|
|
230
243
|
gpsCount: this.#r,
|
|
231
|
-
lat:
|
|
232
|
-
lon:
|
|
244
|
+
lat: t.coords.latitude,
|
|
245
|
+
lon: t.coords.longitude,
|
|
233
246
|
session: this.#a,
|
|
234
247
|
initialPosition: this.#i
|
|
235
248
|
})), this.#d(
|
|
236
249
|
this.camera,
|
|
237
|
-
|
|
238
|
-
|
|
250
|
+
t.coords.longitude,
|
|
251
|
+
t.coords.latitude
|
|
239
252
|
), this.#n?.sendData("/gps/accepted", {
|
|
240
253
|
gpsCount: this.#r,
|
|
241
254
|
cameraX: this.camera.position.x,
|
|
242
255
|
cameraZ: this.camera.position.z,
|
|
243
256
|
session: this.#a,
|
|
244
257
|
distMoved: i
|
|
245
|
-
}), this.emit("gpsupdate", { position:
|
|
258
|
+
}), this.emit("gpsupdate", { position: t, distMoved: i })));
|
|
246
259
|
}
|
|
247
260
|
/**
|
|
248
261
|
* Calculate haversine distance between two lat/lon pairs.
|
|
249
262
|
*
|
|
250
263
|
* Taken from original A-Frame AR.js location-based components
|
|
251
264
|
*/
|
|
252
|
-
#
|
|
253
|
-
const
|
|
265
|
+
#g(t, i) {
|
|
266
|
+
const e = m.MathUtils.degToRad(i.longitude - t.longitude), c = m.MathUtils.degToRad(i.latitude - t.latitude), h = Math.sin(c / 2) * Math.sin(c / 2) + Math.cos(m.MathUtils.degToRad(t.latitude)) * Math.cos(m.MathUtils.degToRad(i.latitude)) * (Math.sin(e / 2) * Math.sin(e / 2));
|
|
254
267
|
return 2 * Math.atan2(Math.sqrt(h), Math.sqrt(1 - h)) * 6371e3;
|
|
255
268
|
}
|
|
256
269
|
/**
|
|
@@ -272,15 +285,15 @@ class W extends A {
|
|
|
272
285
|
* element to render the webcam feed. If a falsy value (e.g. null or
|
|
273
286
|
* undefined), a video element will be created.
|
|
274
287
|
*/
|
|
275
|
-
constructor(
|
|
276
|
-
super(), this.sceneWebcam = new
|
|
288
|
+
constructor(t = { video: { facingMode: "environment" } }, i) {
|
|
289
|
+
super(), this.sceneWebcam = new m.Scene(), i ? this.#t = document.querySelector(i) : (this.#t = document.createElement("video"), this.#t.setAttribute("autoplay", !0), this.#t.setAttribute("playsinline", !0), this.#t.style.display = "none", document.body.appendChild(this.#t)), this.texture = new m.VideoTexture(this.#t), navigator.mediaDevices && navigator.mediaDevices.getUserMedia ? navigator.mediaDevices.getUserMedia(t).then((e) => {
|
|
277
290
|
this.#t.addEventListener("loadedmetadata", () => {
|
|
278
291
|
this.#t.setAttribute("width", this.#t.videoWidth), this.#t.setAttribute("height", this.#t.videoHeight), this.#t.play(), this.emit("webcamstarted", { texture: this.texture });
|
|
279
|
-
}), this.#t.srcObject =
|
|
280
|
-
}).catch((
|
|
292
|
+
}), this.#t.srcObject = e;
|
|
293
|
+
}).catch((e) => {
|
|
281
294
|
this.emit("webcamerror", {
|
|
282
|
-
code:
|
|
283
|
-
message:
|
|
295
|
+
code: e.name,
|
|
296
|
+
message: e.message
|
|
284
297
|
});
|
|
285
298
|
}) : this.emit("webcamerror", {
|
|
286
299
|
code: "LOCAR_NO_MEDIA_DEVICES_API",
|
|
@@ -303,10 +316,10 @@ class V extends R {
|
|
|
303
316
|
* (usually your Three.js camera)
|
|
304
317
|
* @param {Object} options - options for DeviceOrientationControls: currently accepts smoothingFactor, enablePermissionDialog
|
|
305
318
|
*/
|
|
306
|
-
constructor(
|
|
319
|
+
constructor(t, i = {}) {
|
|
307
320
|
super(), this.eventEmitter = new A();
|
|
308
|
-
const
|
|
309
|
-
this.object =
|
|
321
|
+
const e = this;
|
|
322
|
+
this.object = t, this.object.rotation.reorder("YXZ"), this.enabled = !0, this.deviceOrientation = null, this.screenOrientation = 0, this.alphaOffset = 0, this.orientationOffset = 0, this.initialOffset = null, this.lastCompassY = void 0, this.lastOrientation = null, this.TWO_PI = 2 * Math.PI, this.HALF_PI = 0.5 * Math.PI, this.orientationChangeEventName = "ondeviceorientationabsolute" in window ? "deviceorientationabsolute" : "deviceorientation", this.smoothingFactor = i.smoothingFactor || 1, this.enablePermissionDialog = i.enablePermissionDialog ?? !0, this.enableInlineStyling = i.enableStyling ?? !0, this.preferConfirmDialog = i.preferConfirmDialog ?? !1;
|
|
310
323
|
const c = function({
|
|
311
324
|
alpha: n,
|
|
312
325
|
beta: s,
|
|
@@ -315,16 +328,16 @@ class V extends R {
|
|
|
315
328
|
}) {
|
|
316
329
|
if (O) {
|
|
317
330
|
const o = 360 - r;
|
|
318
|
-
|
|
331
|
+
e.alphaOffset = g.degToRad(o - n), e.deviceOrientation = { alpha: n, beta: s, gamma: a, webkitCompassHeading: r };
|
|
319
332
|
} else
|
|
320
|
-
n < 0 && (n += 360),
|
|
333
|
+
n < 0 && (n += 360), e.deviceOrientation = { alpha: n, beta: s, gamma: a };
|
|
321
334
|
window.dispatchEvent(
|
|
322
335
|
new CustomEvent("camera-rotation-change", {
|
|
323
|
-
detail: { cameraRotation:
|
|
336
|
+
detail: { cameraRotation: t.rotation }
|
|
324
337
|
})
|
|
325
338
|
);
|
|
326
339
|
}, h = function() {
|
|
327
|
-
|
|
340
|
+
e.screenOrientation = window.orientation || 0, O && (e.screenOrientation === 90 ? e.orientationOffset = -e.HALF_PI : e.screenOrientation === -90 ? e.orientationOffset = e.HALF_PI : e.orientationOffset = 0);
|
|
328
341
|
}, E = function(n, s, a, r, o) {
|
|
329
342
|
y.set(a, s, -r, "YXZ"), n.setFromEuler(y), n.multiply(F), n.multiply(H.setFromAxisAngle(x, -o));
|
|
330
343
|
};
|
|
@@ -333,17 +346,17 @@ class V extends R {
|
|
|
333
346
|
"orientationchange",
|
|
334
347
|
h
|
|
335
348
|
), window.addEventListener(
|
|
336
|
-
|
|
349
|
+
e.orientationChangeEventName,
|
|
337
350
|
c
|
|
338
|
-
),
|
|
351
|
+
), e.enabled = !0;
|
|
339
352
|
}, this.disconnect = function() {
|
|
340
353
|
window.removeEventListener(
|
|
341
354
|
"orientationchange",
|
|
342
355
|
h
|
|
343
356
|
), window.removeEventListener(
|
|
344
|
-
|
|
357
|
+
e.orientationChangeEventName,
|
|
345
358
|
c
|
|
346
|
-
),
|
|
359
|
+
), e.enabled = !1, e.initialOffset = !1, e.deviceOrientation = null;
|
|
347
360
|
}, this.requestOrientationPermissions = function() {
|
|
348
361
|
window.DeviceOrientationEvent !== void 0 && typeof window.DeviceOrientationEvent.requestPermission == "function" ? window.DeviceOrientationEvent.requestPermission().then((n) => {
|
|
349
362
|
n === "granted" ? this.eventEmitter.emit("deviceorientationgranted", {
|
|
@@ -363,31 +376,31 @@ class V extends R {
|
|
|
363
376
|
message: "Internal error: no requestPermission() found although requestOrientationPermissions() was called - please raise an issue on GitHub"
|
|
364
377
|
});
|
|
365
378
|
}, this.update = function({ theta: n = 0 } = { theta: 0 }) {
|
|
366
|
-
if (
|
|
367
|
-
const s =
|
|
379
|
+
if (e.enabled === !1) return;
|
|
380
|
+
const s = e.deviceOrientation;
|
|
368
381
|
if (s) {
|
|
369
|
-
let a = s.alpha ?
|
|
370
|
-
const f =
|
|
371
|
-
if (
|
|
372
|
-
if (
|
|
373
|
-
const d =
|
|
374
|
-
a =
|
|
382
|
+
let a = s.alpha ? g.degToRad(s.alpha) + e.alphaOffset : 0, r = s.beta ? g.degToRad(s.beta) : 0, o = s.gamma ? g.degToRad(s.gamma) : 0;
|
|
383
|
+
const f = e.screenOrientation ? g.degToRad(e.screenOrientation) : 0;
|
|
384
|
+
if (e.smoothingFactor < 1) {
|
|
385
|
+
if (e.lastOrientation) {
|
|
386
|
+
const d = e.smoothingFactor;
|
|
387
|
+
a = e._getSmoothedAngle(
|
|
375
388
|
a,
|
|
376
|
-
|
|
389
|
+
e.lastOrientation.alpha,
|
|
377
390
|
d
|
|
378
|
-
), r =
|
|
391
|
+
), r = e._getSmoothedAngle(
|
|
379
392
|
r + Math.PI,
|
|
380
|
-
|
|
393
|
+
e.lastOrientation.beta,
|
|
381
394
|
d
|
|
382
|
-
), o =
|
|
383
|
-
o +
|
|
384
|
-
|
|
395
|
+
), o = e._getSmoothedAngle(
|
|
396
|
+
o + e.HALF_PI,
|
|
397
|
+
e.lastOrientation.gamma,
|
|
385
398
|
d,
|
|
386
399
|
Math.PI
|
|
387
400
|
);
|
|
388
401
|
} else
|
|
389
|
-
r += Math.PI, o +=
|
|
390
|
-
|
|
402
|
+
r += Math.PI, o += e.HALF_PI;
|
|
403
|
+
e.lastOrientation = {
|
|
391
404
|
alpha: a,
|
|
392
405
|
beta: r,
|
|
393
406
|
gamma: o
|
|
@@ -398,54 +411,54 @@ class V extends R {
|
|
|
398
411
|
E(
|
|
399
412
|
d,
|
|
400
413
|
a,
|
|
401
|
-
|
|
402
|
-
|
|
414
|
+
e.smoothingFactor < 1 ? r - Math.PI : r,
|
|
415
|
+
e.smoothingFactor < 1 ? o - Math.PI / 2 : o,
|
|
403
416
|
f
|
|
404
417
|
);
|
|
405
418
|
const u = new w().setFromQuaternion(
|
|
406
419
|
d,
|
|
407
420
|
"YXZ"
|
|
408
421
|
);
|
|
409
|
-
let p =
|
|
410
|
-
|
|
422
|
+
let p = g.degToRad(360 - s.webkitCompassHeading);
|
|
423
|
+
e.smoothingFactor < 1 && e.lastCompassY !== void 0 && (p = e._getSmoothedAngle(
|
|
411
424
|
p,
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
)),
|
|
425
|
+
e.lastCompassY,
|
|
426
|
+
e.smoothingFactor
|
|
427
|
+
)), e.lastCompassY = p, u.y = p + (e.orientationOffset || 0), d.setFromEuler(u), e.object.quaternion.copy(d);
|
|
415
428
|
} else
|
|
416
429
|
E(
|
|
417
|
-
|
|
418
|
-
O ? a +
|
|
419
|
-
|
|
420
|
-
|
|
430
|
+
e.object.quaternion,
|
|
431
|
+
O ? a + e.alphaOffset : a,
|
|
432
|
+
e.smoothingFactor < 1 ? r - Math.PI : r,
|
|
433
|
+
e.smoothingFactor < 1 ? o - Math.PI / 2 : o,
|
|
421
434
|
f
|
|
422
435
|
);
|
|
423
436
|
}
|
|
424
437
|
}, this.getCorrectedHeading = function() {
|
|
425
|
-
const { deviceOrientation: n } =
|
|
438
|
+
const { deviceOrientation: n } = e;
|
|
426
439
|
if (!n) return 0;
|
|
427
440
|
let s = 0;
|
|
428
|
-
return O ? (s = 360 - n.webkitCompassHeading,
|
|
429
|
-
}, this._orderAngle = function(n, s, a =
|
|
441
|
+
return O ? (s = 360 - n.webkitCompassHeading, e.orientationOffset && (s += e.orientationOffset * (180 / Math.PI), s = (s + 360) % 360)) : (n.absolute === !0 || e.orientationChangeEventName, s = n.alpha ? n.alpha : 0, s = (360 - s) % 360, s < 0 && (s += 360)), s;
|
|
442
|
+
}, this._orderAngle = function(n, s, a = e.TWO_PI) {
|
|
430
443
|
return s > n && Math.abs(s - n) < a / 2 || n > s && Math.abs(s - n) > a / 2 ? { left: n, right: s } : { left: s, right: n };
|
|
431
|
-
}, this._getSmoothedAngle = function(n, s, a, r =
|
|
432
|
-
const o =
|
|
444
|
+
}, this._getSmoothedAngle = function(n, s, a, r = e.TWO_PI) {
|
|
445
|
+
const o = e._orderAngle(n, s, r), f = o.left, d = o.right;
|
|
433
446
|
o.left = 0, o.right -= f, o.right < 0 && (o.right += r);
|
|
434
447
|
let u = d == s ? (1 - a) * o.right + a * o.left : a * o.right + (1 - a) * o.left;
|
|
435
448
|
return u += f, u >= r && (u -= r), u;
|
|
436
449
|
}, this.updateAlphaOffset = function() {
|
|
437
|
-
|
|
450
|
+
e.initialOffset = !1;
|
|
438
451
|
}, this.dispose = function() {
|
|
439
|
-
|
|
452
|
+
e.disconnect();
|
|
440
453
|
}, this.getAlpha = function() {
|
|
441
|
-
const { deviceOrientation: n } =
|
|
442
|
-
return n && n.alpha ?
|
|
454
|
+
const { deviceOrientation: n } = e;
|
|
455
|
+
return n && n.alpha ? g.degToRad(n.alpha) + e.alphaOffset : 0;
|
|
443
456
|
}, this.getBeta = function() {
|
|
444
|
-
const { deviceOrientation: n } =
|
|
445
|
-
return n && n.beta ?
|
|
457
|
+
const { deviceOrientation: n } = e;
|
|
458
|
+
return n && n.beta ? g.degToRad(n.beta) : 0;
|
|
446
459
|
}, this.getGamma = function() {
|
|
447
|
-
const { deviceOrientation: n } =
|
|
448
|
-
return n && n.gamma ?
|
|
460
|
+
const { deviceOrientation: n } = e;
|
|
461
|
+
return n && n.gamma ? g.degToRad(n.gamma) : 0;
|
|
449
462
|
}, this.createObtainPermissionGestureDialog = function() {
|
|
450
463
|
const n = document.createElement("div");
|
|
451
464
|
n.classList.add(b);
|
|
@@ -522,8 +535,8 @@ class V extends R {
|
|
|
522
535
|
this.preferConfirmDialog === !0 ? window.confirm(P) && this.requestOrientationPermissions() : this.createObtainPermissionGestureDialog();
|
|
523
536
|
};
|
|
524
537
|
}
|
|
525
|
-
on(
|
|
526
|
-
this.eventEmitter.on(
|
|
538
|
+
on(t, i) {
|
|
539
|
+
this.eventEmitter.on(t, i);
|
|
527
540
|
}
|
|
528
541
|
/**
|
|
529
542
|
* Initialise device orientation controls.
|
|
@@ -547,11 +560,11 @@ class j {
|
|
|
547
560
|
* @param {THREE.WebGLRenderer} - The Three.js renderer on which the click
|
|
548
561
|
* events will be handled.
|
|
549
562
|
*/
|
|
550
|
-
constructor(
|
|
551
|
-
this.raycaster = new
|
|
563
|
+
constructor(t) {
|
|
564
|
+
this.raycaster = new m.Raycaster(), this.normalisedMousePosition = new m.Vector2(null, null), t.domElement.addEventListener("click", (i) => {
|
|
552
565
|
this.normalisedMousePosition.set(
|
|
553
|
-
i.clientX /
|
|
554
|
-
-(i.clientY /
|
|
566
|
+
i.clientX / t.domElement.clientWidth * 2 - 1,
|
|
567
|
+
-(i.clientY / t.domElement.clientHeight * 2) + 1
|
|
555
568
|
);
|
|
556
569
|
});
|
|
557
570
|
}
|
|
@@ -563,16 +576,16 @@ class j {
|
|
|
563
576
|
* cast into.
|
|
564
577
|
* @return {Array} - array of all intersected objects.
|
|
565
578
|
*/
|
|
566
|
-
raycast(
|
|
579
|
+
raycast(t, i) {
|
|
567
580
|
if (this.normalisedMousePosition.x !== null && this.normalisedMousePosition.y !== null) {
|
|
568
|
-
this.raycaster.setFromCamera(this.normalisedMousePosition,
|
|
569
|
-
const
|
|
570
|
-
return this.normalisedMousePosition.set(null, null),
|
|
581
|
+
this.raycaster.setFromCamera(this.normalisedMousePosition, t);
|
|
582
|
+
const e = this.raycaster.intersectObjects(i.children, !1);
|
|
583
|
+
return this.normalisedMousePosition.set(null, null), e;
|
|
571
584
|
}
|
|
572
585
|
return [];
|
|
573
586
|
}
|
|
574
587
|
}
|
|
575
|
-
const U = "0.1.
|
|
588
|
+
const U = "0.1.5";
|
|
576
589
|
export {
|
|
577
590
|
j as ClickHandler,
|
|
578
591
|
V as DeviceOrientationControls,
|
package/dist/locar.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(h,c){typeof exports=="object"&&typeof module<"u"?c(exports,require("three")):typeof define=="function"&&define.amd?define(["exports","three"],c):(h=typeof globalThis<"u"?globalThis:h||self,c(h.locar={},h.THREE))})(this,(function(h,c){"use strict";function w(m){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(m){for(const i in m)if(i!=="default"){const e=Object.getOwnPropertyDescriptor(m,i);Object.defineProperty(t,i,e.get?e:{enumerable:!0,get:()=>m[i]})}}return t.default=m,Object.freeze(t)}const p=w(c);class A{constructor(){this.EARTH=4007501668e-2,this.HALF_EARTH=2003750834e-2}project(t,i){return[this.#t(t),this.#l(i)]}unproject(t){return[this.#e(t[0]),this.#s(t[1])]}#t(t){return t/180*this.HALF_EARTH}#l(t){var i=Math.log(Math.tan((90+t)*Math.PI/360))/(Math.PI/180);return i*this.HALF_EARTH/180}#e(t){return t/this.HALF_EARTH*180}#s(t){var i=t/this.HALF_EARTH*180;return i=180/Math.PI*(2*Math.atan(Math.exp(i*Math.PI/180))-Math.PI/2),i}getID(){return"epsg:3857"}}class M{constructor(){this.eventHandlers={}}on(t,i){this.eventHandlers[t]=i}emit(t,...i){this.eventHandlers[t]?.call(this,...i)}}class b extends M{#t;#l;#e;#s;#c;#o;#i;#r;#a;#n;constructor(t,i,e={},l=null){super(),this.scene=t,this.camera=i,this.#t=new A,this.#e=null,this.#s=0,this.#c=100,this.#o=null,this.setGpsOptions(e),this.#i=null,this.#r=0,this.#a=0,this.#n=l}setProjection(t){this.#t=t}setGpsOptions(t={}){t.gpsMinDistance!==void 0&&(this.#s=t.gpsMinDistance),t.gpsMinAccuracy!==void 0&&(this.#c=t.gpsMinAccuracy)}async startGps(){if(this.#n){const i=await(await this.#n.sendData("/gps/start",{gpsMinDistance:this.#s,gpsMinAccuracy:this.#c})).json();this.#a=i.session}return this.#o===null?(this.#o=navigator.geolocation.watchPosition(t=>{this.#h(t)},t=>{this.emit("gpserror",t)},{enableHighAccuracy:!0}),!0):!1}stopGps(){return this.#o!==null?(navigator.geolocation.clearWatch(this.#o),this.#o=null,!0):!1}fakeGps(t,i,e=null,l=0){e!==null&&this.setElevation(e),this.#h({coords:{longitude:t,latitude:i,accuracy:l}})}lonLatToWorldCoords(t,i){const e=this.#t.project(t,i);if(this.#i)e[0]-=this.#i[0],e[1]-=this.#i[1];else throw"No initial position determined";return[e[0],-e[1]]}add(t,i,e,l,g={}){t.properties=g,this.#d(t,i,e,l),this.scene.add(t),this.#n?.sendData("/object/new",{position:t.position,x:t.position.x,z:t.position.z,session:this.#a,properties:g})}#d(t,i,e,l){const g=this.lonLatToWorldCoords(i,e);l!==void 0&&(t.position.y=l),[t.position.x,t.position.z]=g}setElevation(t){this.camera.position.y=t}#u(t,i){this.#i=this.#t.project(t,i)}#h(t){let i=Number.MAX_VALUE;this.#r++,this.#n?.sendData("/gps/new",{gpsCount:this.#r,lat:t.coords.latitude,lon:t.coords.longitude,acc:t.coords.accuracy,session:this.#a}),t.coords.accuracy<=this.#c&&(this.#e===null?this.#e={latitude:t.coords.latitude,longitude:t.coords.longitude}:i=this.#m(this.#e,t.coords),i>=this.#s&&(this.#e.longitude=t.coords.longitude,this.#e.latitude=t.coords.latitude,this.#i||(this.#u(t.coords.longitude,t.coords.latitude),this.#n?.sendData("/worldorigin/new",{gpsCount:this.#r,lat:t.coords.latitude,lon:t.coords.longitude,session:this.#a,initialPosition:this.#i})),this.#d(this.camera,t.coords.longitude,t.coords.latitude),this.#n?.sendData("/gps/accepted",{gpsCount:this.#r,cameraX:this.camera.position.x,cameraZ:this.camera.position.z,session:this.#a,distMoved:i}),this.emit("gpsupdate",{position:t,distMoved:i})))}#m(t,i){const e=p.MathUtils.degToRad(i.longitude-t.longitude),l=p.MathUtils.degToRad(i.latitude-t.latitude),g=Math.sin(l/2)*Math.sin(l/2)+Math.cos(p.MathUtils.degToRad(t.latitude))*Math.cos(p.MathUtils.degToRad(i.latitude))*(Math.sin(e/2)*Math.sin(e/2));return 2*Math.atan2(Math.sqrt(g),Math.sqrt(1-g))*6371e3}getLastKnownLocation(){return this.#e}}class D extends M{#t;constructor(t={video:{facingMode:"environment"}},i){super(),this.sceneWebcam=new p.Scene,i?this.#t=document.querySelector(i):(this.#t=document.createElement("video"),this.#t.setAttribute("autoplay",!0),this.#t.setAttribute("playsinline",!0),this.#t.style.display="none",document.body.appendChild(this.#t)),this.texture=new p.VideoTexture(this.#t),navigator.mediaDevices&&navigator.mediaDevices.getUserMedia?navigator.mediaDevices.getUserMedia(t).then(e=>{this.#t.addEventListener("loadedmetadata",()=>{this.#t.setAttribute("width",this.#t.videoWidth),this.#t.setAttribute("height",this.#t.videoHeight),this.#t.play(),this.emit("webcamstarted",{texture:this.texture})}),this.#t.srcObject=e}).catch(e=>{this.emit("webcamerror",{code:e.name,message:e.message})}):this.emit("webcamerror",{code:"LOCAR_NO_MEDIA_DEVICES_API",message:"Media devices API not supported"})}dispose(){this.texture.dispose()}}const S="locar-device-orientation-permission-modal",T="locar-device-orientation-permission-button",N="locar-device-orientation-permission-message",R="locar-device-orientation-permission-inner",L="locar-device-orientation-permission-button-inner",P="This immersive website requires access to your device motion sensors.",I=navigator.userAgent.match(/iPhone|iPad|iPod/i)||/Macintosh/i.test(navigator.userAgent)&&navigator.maxTouchPoints!=null&&navigator.maxTouchPoints>1,x=new c.Vector3(0,0,1),_=new c.Euler,F=new c.Quaternion,U=new c.Quaternion(-Math.sqrt(.5),0,0,Math.sqrt(.5));class j extends c.EventDispatcher{constructor(t,i={}){super(),this.eventEmitter=new M;const e=this;this.object=t,this.object.rotation.reorder("YXZ"),this.enabled=!0,this.deviceOrientation=null,this.screenOrientation=0,this.alphaOffset=0,this.orientationOffset=0,this.initialOffset=null,this.lastCompassY=void 0,this.lastOrientation=null,this.TWO_PI=2*Math.PI,this.HALF_PI=.5*Math.PI,this.orientationChangeEventName="ondeviceorientationabsolute"in window?"deviceorientationabsolute":"deviceorientation",this.smoothingFactor=i.smoothingFactor||1,this.enablePermissionDialog=i.enablePermissionDialog??!0,this.enableInlineStyling=i.enableStyling??!0,this.preferConfirmDialog=i.preferConfirmDialog??!1;const l=function({alpha:n,beta:s,gamma:a,webkitCompassHeading:r}){if(I){const o=360-r;e.alphaOffset=c.MathUtils.degToRad(o-n),e.deviceOrientation={alpha:n,beta:s,gamma:a,webkitCompassHeading:r}}else n<0&&(n+=360),e.deviceOrientation={alpha:n,beta:s,gamma:a};window.dispatchEvent(new CustomEvent("camera-rotation-change",{detail:{cameraRotation:t.rotation}}))},g=function(){e.screenOrientation=window.orientation||0,I&&(e.screenOrientation===90?e.orientationOffset=-e.HALF_PI:e.screenOrientation===-90?e.orientationOffset=e.HALF_PI:e.orientationOffset=0)},E=function(n,s,a,r,o){_.set(a,s,-r,"YXZ"),n.setFromEuler(_),n.multiply(U),n.multiply(F.setFromAxisAngle(x,-o))};this.connect=function(){g(),window.addEventListener("orientationchange",g),window.addEventListener(e.orientationChangeEventName,l),e.enabled=!0},this.disconnect=function(){window.removeEventListener("orientationchange",g),window.removeEventListener(e.orientationChangeEventName,l),e.enabled=!1,e.initialOffset=!1,e.deviceOrientation=null},this.requestOrientationPermissions=function(){window.DeviceOrientationEvent!==void 0&&typeof window.DeviceOrientationEvent.requestPermission=="function"?window.DeviceOrientationEvent.requestPermission().then(n=>{n==="granted"?this.eventEmitter.emit("deviceorientationgranted",{target:this}):this.eventEmitter.emit("deviceorientationerror",{code:"LOCAR_DEVICE_ORIENTATION_PERMISSION_DENIED",message:"Permission for device orientation denied - AR will not work correctly"})}).catch(function(n){this.eventEmitter.emit("deviceorientationerror",{code:"LOCAR_DEVICE_ORIENTATION_PERMISSION_FAILED",message:"Permission request for device orientation failed - AR will not work correctly",error:JSON.stringify(n,null,2)})}):this.eventEmitter.emit("deviceorientationerror",{code:"LOCAR_DEVICE_ORIENTATION_INTERNAL_ERROR",message:"Internal error: no requestPermission() found although requestOrientationPermissions() was called - please raise an issue on GitHub"})},this.update=function({theta:n=0}={theta:0}){if(e.enabled===!1)return;const s=e.deviceOrientation;if(s){let a=s.alpha?c.MathUtils.degToRad(s.alpha)+e.alphaOffset:0,r=s.beta?c.MathUtils.degToRad(s.beta):0,o=s.gamma?c.MathUtils.degToRad(s.gamma):0;const v=e.screenOrientation?c.MathUtils.degToRad(e.screenOrientation):0;if(e.smoothingFactor<1){if(e.lastOrientation){const u=e.smoothingFactor;a=e._getSmoothedAngle(a,e.lastOrientation.alpha,u),r=e._getSmoothedAngle(r+Math.PI,e.lastOrientation.beta,u),o=e._getSmoothedAngle(o+e.HALF_PI,e.lastOrientation.gamma,u,Math.PI)}else r+=Math.PI,o+=e.HALF_PI;e.lastOrientation={alpha:a,beta:r,gamma:o}}if(I){const u=new c.Quaternion;E(u,a,e.smoothingFactor<1?r-Math.PI:r,e.smoothingFactor<1?o-Math.PI/2:o,v);const f=new c.Euler().setFromQuaternion(u,"YXZ");let O=c.MathUtils.degToRad(360-s.webkitCompassHeading);e.smoothingFactor<1&&e.lastCompassY!==void 0&&(O=e._getSmoothedAngle(O,e.lastCompassY,e.smoothingFactor)),e.lastCompassY=O,f.y=O+(e.orientationOffset||0),u.setFromEuler(f),e.object.quaternion.copy(u)}else E(e.object.quaternion,I?a+e.alphaOffset:a,e.smoothingFactor<1?r-Math.PI:r,e.smoothingFactor<1?o-Math.PI/2:o,v)}},this.getCorrectedHeading=function(){const{deviceOrientation:n}=e;if(!n)return 0;let s=0;return I?(s=360-n.webkitCompassHeading,e.orientationOffset&&(s+=e.orientationOffset*(180/Math.PI),s=(s+360)%360)):(n.absolute===!0||e.orientationChangeEventName,s=n.alpha?n.alpha:0,s=(360-s)%360,s<0&&(s+=360)),s},this._orderAngle=function(n,s,a=e.TWO_PI){return s>n&&Math.abs(s-n)<a/2||n>s&&Math.abs(s-n)>a/2?{left:n,right:s}:{left:s,right:n}},this._getSmoothedAngle=function(n,s,a,r=e.TWO_PI){const o=e._orderAngle(n,s,r),v=o.left,u=o.right;o.left=0,o.right-=v,o.right<0&&(o.right+=r);let f=u==s?(1-a)*o.right+a*o.left:a*o.right+(1-a)*o.left;return f+=v,f>=r&&(f-=r),f},this.updateAlphaOffset=function(){e.initialOffset=!1},this.dispose=function(){e.disconnect()},this.getAlpha=function(){const{deviceOrientation:n}=e;return n&&n.alpha?c.MathUtils.degToRad(n.alpha)+e.alphaOffset:0},this.getBeta=function(){const{deviceOrientation:n}=e;return n&&n.beta?c.MathUtils.degToRad(n.beta):0},this.getGamma=function(){const{deviceOrientation:n}=e;return n&&n.gamma?c.MathUtils.degToRad(n.gamma):0},this.createObtainPermissionGestureDialog=function(){const n=document.createElement("div");n.classList.add(S);const s=document.createElement("div");s.classList.add(R);const a=document.createElement("div");a.classList.add(N);const r=document.createElement("div");r.classList.add(L);const o=document.createElement("button");if(o.classList.add(T),document.body.appendChild(n),this.enableInlineStyling===!0){const u={fontFamily:"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'",display:"flex",position:"fixed",zIndex:1e5,justifyContent:"center",alignItems:"center",backgroundColor:"rgba(0,0,0,0.2)",inset:0,padding:"20px"},f={backgroundColor:"rgba(220, 220, 220, 0.85)",padding:"6px 0",borderRadius:"10px",width:"100%",maxWidth:"400px"},O={padding:"10px 12px",textAlign:"center",fontWeight:400,fontSize:"13px",display:"flex",justifyContent:"center",alignItems:"center"},y={display:"block",textAlign:"center",textDecoration:"none",borderTop:"rgb(180,180,180) solid 1px"},C={display:"block",width:"100%",textAlign:"center",appearance:"none",background:"none",border:"none",outline:"none",padding:"10px",fontWeight:400,fontSize:"16px",color:"#2e7cf1",cursor:"pointer"};for(let d in u)n.style[d]=u[d];for(let d in f)s.style[d]=f[d];for(let d in O)a.style[d]=O[d];for(let d in y)r.style[d]=y[d];for(let d in C)o.style[d]=C[d]}n.appendChild(s),s.appendChild(a),s.appendChild(r),a.appendChild(document.createTextNode(P));const v=()=>{this.requestOrientationPermissions(),n.style.display="none"};o.addEventListener("click",v),o.appendChild(document.createTextNode("OK")),r.appendChild(o),document.body.appendChild(n)},this.obtainPermissionGesture=function(){this.preferConfirmDialog===!0?window.confirm(P)&&this.requestOrientationPermissions():this.createObtainPermissionGestureDialog()}}on(t,i){this.eventEmitter.on(t,i)}init(){window.DeviceOrientationEvent===void 0?this.eventEmitter.emit("deviceorientationerror",{code:"LOCAR_DEVICE_ORIENTATION_NOT_SUPPORTED",message:"Device orientation API not supported"}):window.isSecureContext===!1?this.eventEmitter.emit("deviceorientationerror",{code:"LOCAR_DEVICE_ORIENTATION_NO_HTTPS",message:"DeviceOrientationEvent is only available in secure contexts (https)"}):typeof window.DeviceOrientationEvent.requestPermission=="function"&&this.enablePermissionDialog?this.obtainPermissionGesture():this.eventEmitter.emit("deviceorientationgranted",{target:this})}}class q{constructor(t){this.raycaster=new p.Raycaster,this.normalisedMousePosition=new p.Vector2(null,null),t.domElement.addEventListener("click",i=>{this.normalisedMousePosition.set(i.clientX/t.domElement.clientWidth*2-1,-(i.clientY/t.domElement.clientHeight*2)+1)})}raycast(t,i){if(this.normalisedMousePosition.x!==null&&this.normalisedMousePosition.y!==null){this.raycaster.setFromCamera(this.normalisedMousePosition,t);const e=this.raycaster.intersectObjects(i.children,!1);return this.normalisedMousePosition.set(null,null),e}return[]}}const k="0.1.4";h.ClickHandler=q,h.DeviceOrientationControls=j,h.EventEmitter=M,h.LocationBased=b,h.SphMercProjection=A,h.Webcam=D,h.version=k,Object.defineProperty(h,Symbol.toStringTag,{value:"Module"})}));
|
|
1
|
+
(function(h,c){typeof exports=="object"&&typeof module<"u"?c(exports,require("three")):typeof define=="function"&&define.amd?define(["exports","three"],c):(h=typeof globalThis<"u"?globalThis:h||self,c(h.locar={},h.THREE))})(this,(function(h,c){"use strict";function w(g){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(g){for(const i in g)if(i!=="default"){const e=Object.getOwnPropertyDescriptor(g,i);Object.defineProperty(t,i,e.get?e:{enumerable:!0,get:()=>g[i]})}}return t.default=g,Object.freeze(t)}const p=w(c);class A{constructor(){this.EARTH=4007501668e-2,this.HALF_EARTH=2003750834e-2}project(t,i){return[this.#t(t),this.#l(i)]}unproject(t){return[this.#e(t[0]),this.#s(t[1])]}#t(t){return t/180*this.HALF_EARTH}#l(t){var i=Math.log(Math.tan((90+t)*Math.PI/360))/(Math.PI/180);return i*this.HALF_EARTH/180}#e(t){return t/this.HALF_EARTH*180}#s(t){var i=t/this.HALF_EARTH*180;return i=180/Math.PI*(2*Math.atan(Math.exp(i*Math.PI/180))-Math.PI/2),i}getID(){return"epsg:3857"}}class M{constructor(){this.eventHandlers={}}on(t,i){this.eventHandlers[t]===void 0&&(this.eventHandlers[t]=[]),this.eventHandlers[t].push(i)}emit(t,...i){this.eventHandlers[t]?.forEach(e=>{e(...i)})}off(t,i){if(this.eventHandlers[t]){const e=this.eventHandlers[t].indexOf(i);e>-1&&this.eventHandlers[t].splice(e,1)}}}class b extends M{#t;#l;#e;#s;#c;#o;#i;#r;#a;#n;constructor(t,i,e={},l=null){super(),this.scene=t,this.camera=i,this.#t=new A,this.#e=null,this.#s=0,this.#c=100,this.#o=null,this.setGpsOptions(e),this.#i=null,this.#r=0,this.#a=0,this.#n=l}setProjection(t){this.#t=t}setGpsOptions(t={}){t.gpsMinDistance!==void 0&&(this.#s=t.gpsMinDistance),t.gpsMinAccuracy!==void 0&&(this.#c=t.gpsMinAccuracy)}async startGps(){if(this.#n){const i=await(await this.#n.sendData("/gps/start",{gpsMinDistance:this.#s,gpsMinAccuracy:this.#c})).json();this.#a=i.session}return this.#o===null?(this.#o=navigator.geolocation.watchPosition(t=>{this.#h(t)},t=>{this.emit("gpserror",t)},{enableHighAccuracy:!0}),!0):!1}stopGps(){return this.#o!==null?(navigator.geolocation.clearWatch(this.#o),this.#o=null,!0):!1}fakeGps(t,i,e=null,l=0){e!==null&&this.setElevation(e),this.#h({coords:{longitude:t,latitude:i,accuracy:l}})}lonLatToWorldCoords(t,i){const e=this.#t.project(t,i);if(this.#i)e[0]-=this.#i[0],e[1]-=this.#i[1];else throw"No initial position determined";return[e[0],-e[1]]}add(t,i,e,l,m={}){t.properties=m,this.#d(t,i,e,l),this.scene.add(t),this.#n?.sendData("/object/new",{position:t.position,x:t.position.x,z:t.position.z,session:this.#a,properties:m})}#d(t,i,e,l){const m=this.lonLatToWorldCoords(i,e);l!==void 0&&(t.position.y=l),[t.position.x,t.position.z]=m}setElevation(t){this.camera.position.y=t}#u(t,i){this.#i=this.#t.project(t,i)}#h(t){let i=Number.MAX_VALUE;this.#r++,this.#n?.sendData("/gps/new",{gpsCount:this.#r,lat:t.coords.latitude,lon:t.coords.longitude,acc:t.coords.accuracy,session:this.#a}),t.coords.accuracy<=this.#c&&(this.#e===null?this.#e={latitude:t.coords.latitude,longitude:t.coords.longitude}:i=this.#g(this.#e,t.coords),i>=this.#s&&(this.#e.longitude=t.coords.longitude,this.#e.latitude=t.coords.latitude,this.#i||(this.#u(t.coords.longitude,t.coords.latitude),this.#n?.sendData("/worldorigin/new",{gpsCount:this.#r,lat:t.coords.latitude,lon:t.coords.longitude,session:this.#a,initialPosition:this.#i})),this.#d(this.camera,t.coords.longitude,t.coords.latitude),this.#n?.sendData("/gps/accepted",{gpsCount:this.#r,cameraX:this.camera.position.x,cameraZ:this.camera.position.z,session:this.#a,distMoved:i}),this.emit("gpsupdate",{position:t,distMoved:i})))}#g(t,i){const e=p.MathUtils.degToRad(i.longitude-t.longitude),l=p.MathUtils.degToRad(i.latitude-t.latitude),m=Math.sin(l/2)*Math.sin(l/2)+Math.cos(p.MathUtils.degToRad(t.latitude))*Math.cos(p.MathUtils.degToRad(i.latitude))*(Math.sin(e/2)*Math.sin(e/2));return 2*Math.atan2(Math.sqrt(m),Math.sqrt(1-m))*6371e3}getLastKnownLocation(){return this.#e}}class D extends M{#t;constructor(t={video:{facingMode:"environment"}},i){super(),this.sceneWebcam=new p.Scene,i?this.#t=document.querySelector(i):(this.#t=document.createElement("video"),this.#t.setAttribute("autoplay",!0),this.#t.setAttribute("playsinline",!0),this.#t.style.display="none",document.body.appendChild(this.#t)),this.texture=new p.VideoTexture(this.#t),navigator.mediaDevices&&navigator.mediaDevices.getUserMedia?navigator.mediaDevices.getUserMedia(t).then(e=>{this.#t.addEventListener("loadedmetadata",()=>{this.#t.setAttribute("width",this.#t.videoWidth),this.#t.setAttribute("height",this.#t.videoHeight),this.#t.play(),this.emit("webcamstarted",{texture:this.texture})}),this.#t.srcObject=e}).catch(e=>{this.emit("webcamerror",{code:e.name,message:e.message})}):this.emit("webcamerror",{code:"LOCAR_NO_MEDIA_DEVICES_API",message:"Media devices API not supported"})}dispose(){this.texture.dispose()}}const S="locar-device-orientation-permission-modal",T="locar-device-orientation-permission-button",R="locar-device-orientation-permission-message",N="locar-device-orientation-permission-inner",L="locar-device-orientation-permission-button-inner",P="This immersive website requires access to your device motion sensors.",I=navigator.userAgent.match(/iPhone|iPad|iPod/i)||/Macintosh/i.test(navigator.userAgent)&&navigator.maxTouchPoints!=null&&navigator.maxTouchPoints>1,x=new c.Vector3(0,0,1),_=new c.Euler,F=new c.Quaternion,H=new c.Quaternion(-Math.sqrt(.5),0,0,Math.sqrt(.5));class U extends c.EventDispatcher{constructor(t,i={}){super(),this.eventEmitter=new M;const e=this;this.object=t,this.object.rotation.reorder("YXZ"),this.enabled=!0,this.deviceOrientation=null,this.screenOrientation=0,this.alphaOffset=0,this.orientationOffset=0,this.initialOffset=null,this.lastCompassY=void 0,this.lastOrientation=null,this.TWO_PI=2*Math.PI,this.HALF_PI=.5*Math.PI,this.orientationChangeEventName="ondeviceorientationabsolute"in window?"deviceorientationabsolute":"deviceorientation",this.smoothingFactor=i.smoothingFactor||1,this.enablePermissionDialog=i.enablePermissionDialog??!0,this.enableInlineStyling=i.enableStyling??!0,this.preferConfirmDialog=i.preferConfirmDialog??!1;const l=function({alpha:n,beta:s,gamma:a,webkitCompassHeading:r}){if(I){const o=360-r;e.alphaOffset=c.MathUtils.degToRad(o-n),e.deviceOrientation={alpha:n,beta:s,gamma:a,webkitCompassHeading:r}}else n<0&&(n+=360),e.deviceOrientation={alpha:n,beta:s,gamma:a};window.dispatchEvent(new CustomEvent("camera-rotation-change",{detail:{cameraRotation:t.rotation}}))},m=function(){e.screenOrientation=window.orientation||0,I&&(e.screenOrientation===90?e.orientationOffset=-e.HALF_PI:e.screenOrientation===-90?e.orientationOffset=e.HALF_PI:e.orientationOffset=0)},E=function(n,s,a,r,o){_.set(a,s,-r,"YXZ"),n.setFromEuler(_),n.multiply(H),n.multiply(F.setFromAxisAngle(x,-o))};this.connect=function(){m(),window.addEventListener("orientationchange",m),window.addEventListener(e.orientationChangeEventName,l),e.enabled=!0},this.disconnect=function(){window.removeEventListener("orientationchange",m),window.removeEventListener(e.orientationChangeEventName,l),e.enabled=!1,e.initialOffset=!1,e.deviceOrientation=null},this.requestOrientationPermissions=function(){window.DeviceOrientationEvent!==void 0&&typeof window.DeviceOrientationEvent.requestPermission=="function"?window.DeviceOrientationEvent.requestPermission().then(n=>{n==="granted"?this.eventEmitter.emit("deviceorientationgranted",{target:this}):this.eventEmitter.emit("deviceorientationerror",{code:"LOCAR_DEVICE_ORIENTATION_PERMISSION_DENIED",message:"Permission for device orientation denied - AR will not work correctly"})}).catch(function(n){this.eventEmitter.emit("deviceorientationerror",{code:"LOCAR_DEVICE_ORIENTATION_PERMISSION_FAILED",message:"Permission request for device orientation failed - AR will not work correctly",error:JSON.stringify(n,null,2)})}):this.eventEmitter.emit("deviceorientationerror",{code:"LOCAR_DEVICE_ORIENTATION_INTERNAL_ERROR",message:"Internal error: no requestPermission() found although requestOrientationPermissions() was called - please raise an issue on GitHub"})},this.update=function({theta:n=0}={theta:0}){if(e.enabled===!1)return;const s=e.deviceOrientation;if(s){let a=s.alpha?c.MathUtils.degToRad(s.alpha)+e.alphaOffset:0,r=s.beta?c.MathUtils.degToRad(s.beta):0,o=s.gamma?c.MathUtils.degToRad(s.gamma):0;const v=e.screenOrientation?c.MathUtils.degToRad(e.screenOrientation):0;if(e.smoothingFactor<1){if(e.lastOrientation){const u=e.smoothingFactor;a=e._getSmoothedAngle(a,e.lastOrientation.alpha,u),r=e._getSmoothedAngle(r+Math.PI,e.lastOrientation.beta,u),o=e._getSmoothedAngle(o+e.HALF_PI,e.lastOrientation.gamma,u,Math.PI)}else r+=Math.PI,o+=e.HALF_PI;e.lastOrientation={alpha:a,beta:r,gamma:o}}if(I){const u=new c.Quaternion;E(u,a,e.smoothingFactor<1?r-Math.PI:r,e.smoothingFactor<1?o-Math.PI/2:o,v);const f=new c.Euler().setFromQuaternion(u,"YXZ");let O=c.MathUtils.degToRad(360-s.webkitCompassHeading);e.smoothingFactor<1&&e.lastCompassY!==void 0&&(O=e._getSmoothedAngle(O,e.lastCompassY,e.smoothingFactor)),e.lastCompassY=O,f.y=O+(e.orientationOffset||0),u.setFromEuler(f),e.object.quaternion.copy(u)}else E(e.object.quaternion,I?a+e.alphaOffset:a,e.smoothingFactor<1?r-Math.PI:r,e.smoothingFactor<1?o-Math.PI/2:o,v)}},this.getCorrectedHeading=function(){const{deviceOrientation:n}=e;if(!n)return 0;let s=0;return I?(s=360-n.webkitCompassHeading,e.orientationOffset&&(s+=e.orientationOffset*(180/Math.PI),s=(s+360)%360)):(n.absolute===!0||e.orientationChangeEventName,s=n.alpha?n.alpha:0,s=(360-s)%360,s<0&&(s+=360)),s},this._orderAngle=function(n,s,a=e.TWO_PI){return s>n&&Math.abs(s-n)<a/2||n>s&&Math.abs(s-n)>a/2?{left:n,right:s}:{left:s,right:n}},this._getSmoothedAngle=function(n,s,a,r=e.TWO_PI){const o=e._orderAngle(n,s,r),v=o.left,u=o.right;o.left=0,o.right-=v,o.right<0&&(o.right+=r);let f=u==s?(1-a)*o.right+a*o.left:a*o.right+(1-a)*o.left;return f+=v,f>=r&&(f-=r),f},this.updateAlphaOffset=function(){e.initialOffset=!1},this.dispose=function(){e.disconnect()},this.getAlpha=function(){const{deviceOrientation:n}=e;return n&&n.alpha?c.MathUtils.degToRad(n.alpha)+e.alphaOffset:0},this.getBeta=function(){const{deviceOrientation:n}=e;return n&&n.beta?c.MathUtils.degToRad(n.beta):0},this.getGamma=function(){const{deviceOrientation:n}=e;return n&&n.gamma?c.MathUtils.degToRad(n.gamma):0},this.createObtainPermissionGestureDialog=function(){const n=document.createElement("div");n.classList.add(S);const s=document.createElement("div");s.classList.add(N);const a=document.createElement("div");a.classList.add(R);const r=document.createElement("div");r.classList.add(L);const o=document.createElement("button");if(o.classList.add(T),document.body.appendChild(n),this.enableInlineStyling===!0){const u={fontFamily:"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'",display:"flex",position:"fixed",zIndex:1e5,justifyContent:"center",alignItems:"center",backgroundColor:"rgba(0,0,0,0.2)",inset:0,padding:"20px"},f={backgroundColor:"rgba(220, 220, 220, 0.85)",padding:"6px 0",borderRadius:"10px",width:"100%",maxWidth:"400px"},O={padding:"10px 12px",textAlign:"center",fontWeight:400,fontSize:"13px",display:"flex",justifyContent:"center",alignItems:"center"},y={display:"block",textAlign:"center",textDecoration:"none",borderTop:"rgb(180,180,180) solid 1px"},C={display:"block",width:"100%",textAlign:"center",appearance:"none",background:"none",border:"none",outline:"none",padding:"10px",fontWeight:400,fontSize:"16px",color:"#2e7cf1",cursor:"pointer"};for(let d in u)n.style[d]=u[d];for(let d in f)s.style[d]=f[d];for(let d in O)a.style[d]=O[d];for(let d in y)r.style[d]=y[d];for(let d in C)o.style[d]=C[d]}n.appendChild(s),s.appendChild(a),s.appendChild(r),a.appendChild(document.createTextNode(P));const v=()=>{this.requestOrientationPermissions(),n.style.display="none"};o.addEventListener("click",v),o.appendChild(document.createTextNode("OK")),r.appendChild(o),document.body.appendChild(n)},this.obtainPermissionGesture=function(){this.preferConfirmDialog===!0?window.confirm(P)&&this.requestOrientationPermissions():this.createObtainPermissionGestureDialog()}}on(t,i){this.eventEmitter.on(t,i)}init(){window.DeviceOrientationEvent===void 0?this.eventEmitter.emit("deviceorientationerror",{code:"LOCAR_DEVICE_ORIENTATION_NOT_SUPPORTED",message:"Device orientation API not supported"}):window.isSecureContext===!1?this.eventEmitter.emit("deviceorientationerror",{code:"LOCAR_DEVICE_ORIENTATION_NO_HTTPS",message:"DeviceOrientationEvent is only available in secure contexts (https)"}):typeof window.DeviceOrientationEvent.requestPermission=="function"&&this.enablePermissionDialog?this.obtainPermissionGesture():this.eventEmitter.emit("deviceorientationgranted",{target:this})}}class j{constructor(t){this.raycaster=new p.Raycaster,this.normalisedMousePosition=new p.Vector2(null,null),t.domElement.addEventListener("click",i=>{this.normalisedMousePosition.set(i.clientX/t.domElement.clientWidth*2-1,-(i.clientY/t.domElement.clientHeight*2)+1)})}raycast(t,i){if(this.normalisedMousePosition.x!==null&&this.normalisedMousePosition.y!==null){this.raycaster.setFromCamera(this.normalisedMousePosition,t);const e=this.raycaster.intersectObjects(i.children,!1);return this.normalisedMousePosition.set(null,null),e}return[]}}const q="0.1.5";h.ClickHandler=j,h.DeviceOrientationControls=U,h.EventEmitter=M,h.LocationBased=b,h.SphMercProjection=A,h.Webcam=D,h.version=q,Object.defineProperty(h,Symbol.toStringTag,{value:"Module"})}));
|