locar 0.1.5 → 0.1.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/dist/locar.es.js CHANGED
@@ -1,97 +1,49 @@
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
- class T {
1
+ import * as g from "three";
2
+ import { Vector3 as T, Euler as C, Quaternion as E, EventDispatcher as _, MathUtils as u } from "three";
3
+ class w {
4
4
  /**
5
5
  * Create a SphMercProjection.
6
6
  */
7
7
  constructor() {
8
- this.EARTH = 4007501668e-2, this.HALF_EARTH = 2003750834e-2;
9
- }
10
- /**
11
- * Project a longitude and latitude into Spherical Mercator.
12
- * @param {number} lon - the longitude.
13
- * @param {number} lat - the latitude.
14
- * @return {Array} Two-member array containing easting and northing.
15
- */
16
- project(t, i) {
17
- return [this.#t(t), this.#l(i)];
18
- }
19
- /**
20
- * Unproject a Spherical Mercator easting and northing.
21
- * @param {Array} projected - Two-member array containing easting and northing
22
- * @return {Array} Two-member array containing longitude and latitude
23
- */
24
- unproject(t) {
25
- return [this.#e(t[0]), this.#s(t[1])];
26
- }
27
- #t(t) {
28
- return t / 180 * this.HALF_EARTH;
29
- }
30
- #l(t) {
31
- var i = Math.log(Math.tan((90 + t) * Math.PI / 360)) / (Math.PI / 180);
32
- return i * this.HALF_EARTH / 180;
33
- }
34
- #e(t) {
35
- return t / this.HALF_EARTH * 180;
36
- }
37
- #s(t) {
38
- var i = t / this.HALF_EARTH * 180;
39
- return i = 180 / Math.PI * (2 * Math.atan(Math.exp(i * Math.PI / 180)) - Math.PI / 2), i;
40
- }
41
- /**
42
- * Return the projection's ID.
43
- * @return {string} The value "epsg:3857".
44
- */
45
- getID() {
46
- return "epsg:3857";
8
+ this.project = (e, s) => [this.#t(e), this.#e(s)], this.unproject = (e) => [this.#i(e[0]), this.#s(e[1])], this.#t = (e) => e / 180 * this.HALF_EARTH, this.#e = (e) => {
9
+ var s = Math.log(Math.tan((90 + e) * Math.PI / 360)) / (Math.PI / 180);
10
+ return s * this.HALF_EARTH / 180;
11
+ }, this.#i = (e) => e / this.HALF_EARTH * 180, this.#s = (e) => {
12
+ var s = e / this.HALF_EARTH * 180;
13
+ return s = 180 / Math.PI * (2 * Math.atan(Math.exp(s * Math.PI / 180)) - Math.PI / 2), s;
14
+ }, this.getID = () => "epsg:3857", this.EARTH = 4007501668e-2, this.HALF_EARTH = 2003750834e-2;
47
15
  }
16
+ #t;
17
+ #e;
18
+ #i;
19
+ #s;
48
20
  }
49
- class A {
21
+ class y {
50
22
  constructor() {
51
- this.eventHandlers = {};
52
- }
53
- /**
54
- * Add an event handler.
55
- * @param {string} eventName - the event to handle.
56
- * @param {Function} eventHandler - the event handler function.
57
- */
58
- on(t, i) {
59
- this.eventHandlers[t] === void 0 && (this.eventHandlers[t] = []), this.eventHandlers[t].push(i);
60
- }
61
- /**
62
- * Emit an event.
63
- * @param {string} eventName - the event to emit.
64
- * @param ...params - parameters to pass to the event handlers.
65
- */
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
- }
23
+ this.on = (e, s) => {
24
+ this.eventHandlers[e] === void 0 && (this.eventHandlers[e] = []), this.eventHandlers[e].push(s);
25
+ }, this.emit = (e, ...s) => {
26
+ this.eventHandlers[e]?.forEach((t) => {
27
+ t(...s);
28
+ });
29
+ }, this.off = (e, s) => {
30
+ if (this.eventHandlers[e]) {
31
+ const t = this.eventHandlers[e].indexOf(s);
32
+ t > -1 && this.eventHandlers[e].splice(t, 1);
33
+ }
34
+ }, this.eventHandlers = {};
81
35
  }
82
36
  }
83
- class k extends A {
37
+ class F extends y {
84
38
  #t;
85
- // eslint-disable-next-line no-unused-private-class-members
86
- #l;
87
39
  #e;
88
- #s;
89
- #c;
90
- #o;
91
40
  #i;
92
- #r;
41
+ #s;
93
42
  #a;
94
43
  #n;
44
+ #l;
45
+ #r;
46
+ #o;
95
47
  /**
96
48
  * @param {THREE.Scene} scene - The Three.js scene to use.
97
49
  * @param {THREE.Camera} camera - The Three.js camera to use. Should usually
@@ -100,8 +52,8 @@ class k extends A {
100
52
  * setGpsOptions() below.
101
53
  * @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.
102
54
  */
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;
55
+ constructor(e, s, t = {}, c = null) {
56
+ super(), this.scene = e, this.camera = s, this.#t = new w(), this.#e = null, this.#i = 0, this.#s = 100, this.#a = null, this.setGpsOptions(t), this.#n = null, this.#l = 0, this.#r = 0, this.#o = c;
105
57
  }
106
58
  /**
107
59
  * Set the projection to use.
@@ -109,8 +61,8 @@ class k extends A {
109
61
  * taking longitude and latitude as arguments and returning an array
110
62
  * containing easting and northing.
111
63
  */
112
- setProjection(t) {
113
- this.#t = t;
64
+ setProjection(e) {
65
+ this.#t = e;
114
66
  }
115
67
  /**
116
68
  * Set the GPS options.
@@ -119,8 +71,8 @@ class k extends A {
119
71
  * must move to process a new GPS reading, and the latter specifies the
120
72
  * minimum accuracy, in metres, for a GPS reading to be counted.
121
73
  */
122
- setGpsOptions(t = {}) {
123
- t.gpsMinDistance !== void 0 && (this.#s = t.gpsMinDistance), t.gpsMinAccuracy !== void 0 && (this.#c = t.gpsMinAccuracy);
74
+ setGpsOptions(e = {}) {
75
+ e.gpsMinDistance !== void 0 && (this.#i = e.gpsMinDistance), e.gpsMinAccuracy !== void 0 && (this.#s = e.gpsMinAccuracy);
124
76
  }
125
77
  /**
126
78
  * Start the GPS on a real device
@@ -128,19 +80,19 @@ class k extends A {
128
80
  * GPS errors can be handled by handling the gpserror event.
129
81
  */
130
82
  async startGps() {
131
- if (this.#n) {
132
- const i = await (await this.#n.sendData("/gps/start", {
133
- gpsMinDistance: this.#s,
134
- gpsMinAccuracy: this.#c
83
+ if (this.#o) {
84
+ const s = await (await this.#o.sendData("/gps/start", {
85
+ gpsMinDistance: this.#i,
86
+ gpsMinAccuracy: this.#s
135
87
  })).json();
136
- this.#a = i.session;
88
+ this.#r = s.session;
137
89
  }
138
- return this.#o === null ? (this.#o = navigator.geolocation.watchPosition(
139
- (t) => {
140
- this.#h(t);
90
+ return this.#a === null ? (this.#a = navigator.geolocation.watchPosition(
91
+ (e) => {
92
+ this.#h(e);
141
93
  },
142
- (t) => {
143
- this.emit("gpserror", t);
94
+ (e) => {
95
+ this.emit("gpserror", e);
144
96
  },
145
97
  {
146
98
  enableHighAccuracy: !0
@@ -153,7 +105,7 @@ class k extends A {
153
105
  * stopped (i.e. it was never started).
154
106
  */
155
107
  stopGps() {
156
- return this.#o !== null ? (navigator.geolocation.clearWatch(this.#o), this.#o = null, !0) : !1;
108
+ return this.#a !== null ? (navigator.geolocation.clearWatch(this.#a), this.#a = null, !0) : !1;
157
109
  }
158
110
  /**
159
111
  * Send a fake GPS signal. Useful for testing on a desktop or laptop.
@@ -164,11 +116,11 @@ class k extends A {
164
116
  * @param {number} acc - The accuracy of the GPS reading in metres. May be
165
117
  * ignored if lower than the specified minimum accuracy.
166
118
  */
167
- fakeGps(t, i, e = null, c = 0) {
168
- e !== null && this.setElevation(e), this.#h({
119
+ fakeGps(e, s, t = null, c = 0) {
120
+ t !== null && this.setElevation(t), this.#h({
169
121
  coords: {
170
- longitude: t,
171
- latitude: i,
122
+ longitude: e,
123
+ latitude: s,
172
124
  accuracy: c
173
125
  }
174
126
  });
@@ -184,13 +136,13 @@ class k extends A {
184
136
  * @param {number} lat - The latitude.
185
137
  * @return {Array} a two member array containing the WebGL x and z coordinates
186
138
  */
187
- lonLatToWorldCoords(t, i) {
188
- const e = this.#t.project(t, i);
189
- if (this.#i)
190
- e[0] -= this.#i[0], e[1] -= this.#i[1];
139
+ lonLatToWorldCoords(e, s) {
140
+ const t = this.#t.project(e, s);
141
+ if (this.#n)
142
+ t[0] -= this.#n[0], t[1] -= this.#n[1];
191
143
  else
192
144
  throw "No initial position determined";
193
- return [e[0], -e[1]];
145
+ return [t[0], -t[1]];
194
146
  }
195
147
  /**
196
148
  * Add a new AR object at a given latitude, longitude and elevation.
@@ -202,68 +154,68 @@ class k extends A {
202
154
  * @param {Object} properties - properties describing the object (for example,
203
155
  * the contents of the GeoJSON properties field).
204
156
  */
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,
210
- session: this.#a,
157
+ add(e, s, t, c, h = {}) {
158
+ e.properties = h, this.#c(e, s, t, c), this.scene.add(e), this.#o?.sendData("/object/new", {
159
+ position: e.position,
160
+ x: e.position.x,
161
+ z: e.position.z,
162
+ session: this.#r,
211
163
  properties: h
212
164
  });
213
165
  }
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;
166
+ #c(e, s, t, c) {
167
+ const h = this.lonLatToWorldCoords(s, t);
168
+ c !== void 0 && (e.position.y = c), [e.position.x, e.position.z] = h;
217
169
  }
218
170
  /**
219
171
  * Set the elevation (y coordinate) of the camera.
220
172
  * @param {number} elev - the elevation in metres.
221
173
  */
222
- setElevation(t) {
223
- this.camera.position.y = t;
224
- }
225
- #u(t, i) {
226
- this.#i = this.#t.project(t, i);
227
- }
228
- #h(t) {
229
- let i = Number.MAX_VALUE;
230
- this.#r++, this.#n?.sendData("/gps/new", {
231
- gpsCount: this.#r,
232
- lat: t.coords.latitude,
233
- lon: t.coords.longitude,
234
- acc: t.coords.accuracy,
235
- session: this.#a
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
242
- ), this.#n?.sendData("/worldorigin/new", {
243
- gpsCount: this.#r,
244
- lat: t.coords.latitude,
245
- lon: t.coords.longitude,
246
- session: this.#a,
247
- initialPosition: this.#i
248
- })), this.#d(
174
+ setElevation(e) {
175
+ this.camera.position.y = e;
176
+ }
177
+ #d(e, s) {
178
+ this.#n = this.#t.project(e, s);
179
+ }
180
+ #h(e) {
181
+ let s = Number.MAX_VALUE;
182
+ this.#l++, this.#o?.sendData("/gps/new", {
183
+ gpsCount: this.#l,
184
+ lat: e.coords.latitude,
185
+ lon: e.coords.longitude,
186
+ acc: e.coords.accuracy,
187
+ session: this.#r
188
+ }), e.coords.accuracy <= this.#s && (this.#e === null ? this.#e = {
189
+ latitude: e.coords.latitude,
190
+ longitude: e.coords.longitude
191
+ } : s = this.#u(this.#e, e.coords), s >= this.#i && (this.#e.longitude = e.coords.longitude, this.#e.latitude = e.coords.latitude, this.#n || (this.#d(
192
+ e.coords.longitude,
193
+ e.coords.latitude
194
+ ), this.#o?.sendData("/worldorigin/new", {
195
+ gpsCount: this.#l,
196
+ lat: e.coords.latitude,
197
+ lon: e.coords.longitude,
198
+ session: this.#r,
199
+ initialPosition: this.#n
200
+ })), this.#c(
249
201
  this.camera,
250
- t.coords.longitude,
251
- t.coords.latitude
252
- ), this.#n?.sendData("/gps/accepted", {
253
- gpsCount: this.#r,
202
+ e.coords.longitude,
203
+ e.coords.latitude
204
+ ), this.#o?.sendData("/gps/accepted", {
205
+ gpsCount: this.#l,
254
206
  cameraX: this.camera.position.x,
255
207
  cameraZ: this.camera.position.z,
256
- session: this.#a,
257
- distMoved: i
258
- }), this.emit("gpsupdate", { position: t, distMoved: i })));
208
+ session: this.#r,
209
+ distMoved: s
210
+ }), this.emit("gpsupdate", { position: e, distMoved: s })));
259
211
  }
260
212
  /**
261
213
  * Calculate haversine distance between two lat/lon pairs.
262
214
  *
263
215
  * Taken from original A-Frame AR.js location-based components
264
216
  */
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));
217
+ #u(e, s) {
218
+ const t = g.MathUtils.degToRad(s.longitude - e.longitude), c = g.MathUtils.degToRad(s.latitude - e.latitude), h = Math.sin(c / 2) * Math.sin(c / 2) + Math.cos(g.MathUtils.degToRad(e.latitude)) * Math.cos(g.MathUtils.degToRad(s.latitude)) * (Math.sin(t / 2) * Math.sin(t / 2));
267
219
  return 2 * Math.atan2(Math.sqrt(h), Math.sqrt(1 - h)) * 6371e3;
268
220
  }
269
221
  /**
@@ -275,296 +227,206 @@ class k extends A {
275
227
  return this.#e;
276
228
  }
277
229
  }
278
- class W extends A {
279
- #t;
280
- /**
281
- * Create a Webcam.
282
- * @param constraints {Object} - options to use for initialising the camera.
283
- * This is the same constraints object as used by standard MediaDevices API.
284
- * @param {string} videoElementSelector - selector to obtain the HTML video
285
- * element to render the webcam feed. If a falsy value (e.g. null or
286
- * undefined), a video element will be created.
287
- */
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) => {
290
- this.#t.addEventListener("loadedmetadata", () => {
291
- this.#t.setAttribute("width", this.#t.videoWidth), this.#t.setAttribute("height", this.#t.videoHeight), this.#t.play(), this.emit("webcamstarted", { texture: this.texture });
292
- }), this.#t.srcObject = e;
293
- }).catch((e) => {
294
- this.emit("webcamerror", {
295
- code: e.name,
296
- message: e.message
297
- });
298
- }) : this.emit("webcamerror", {
299
- code: "LOCAR_NO_MEDIA_DEVICES_API",
300
- message: "Media devices API not supported"
301
- });
302
- }
303
- /**
304
- * Free up the memory associated with the webcam.
305
- * Should be called when your application closes.
306
- */
307
- dispose() {
308
- this.texture.dispose();
309
- }
310
- }
311
- const b = "locar-device-orientation-permission-modal", D = "locar-device-orientation-permission-button", S = "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.", O = navigator.userAgent.match(/iPhone|iPad|iPod/i) || /Macintosh/i.test(navigator.userAgent) && navigator.maxTouchPoints != null && navigator.maxTouchPoints > 1, x = new C(0, 0, 1), y = new w(), H = new I(), F = new I(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5));
312
- class V extends R {
230
+ const R = "locar-device-orientation-permission-modal", P = "locar-device-orientation-permission-button", b = "locar-device-orientation-permission-message", D = "locar-device-orientation-permission-inner", S = "locar-device-orientation-permission-button-inner", I = "This immersive website requires access to your device motion sensors.", p = navigator.userAgent.match(/iPhone|iPad|iPod/i) || /Macintosh/i.test(navigator.userAgent) && navigator.maxTouchPoints != null && navigator.maxTouchPoints > 1, N = new T(0, 0, 1), A = new C(), x = new E(), L = new E(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5)), M = 2 * Math.PI, f = 0.5 * Math.PI;
231
+ class q extends _ {
313
232
  /**
314
233
  * Create an instance of DeviceOrientationControls.
315
234
  * @param {Object} object - the object to attach the controls to
316
235
  * (usually your Three.js camera)
317
- * @param {Object} options - options for DeviceOrientationControls: currently accepts smoothingFactor, enablePermissionDialog
236
+ * @param {Object} options - options for DeviceOrientationControls:
237
+ * currently accepts smoothingFactor (< 1), enablePermissionDialog, orientationChangeThreshold (radians)
318
238
  */
319
- constructor(t, i = {}) {
320
- super(), this.eventEmitter = new A();
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;
323
- const c = function({
324
- alpha: n,
325
- beta: s,
326
- gamma: a,
327
- webkitCompassHeading: r
328
- }) {
329
- if (O) {
330
- const o = 360 - r;
331
- e.alphaOffset = g.degToRad(o - n), e.deviceOrientation = { alpha: n, beta: s, gamma: a, webkitCompassHeading: r };
239
+ constructor(e, s = {}) {
240
+ super(), this.init = () => {
241
+ window.DeviceOrientationEvent === void 0 ? this.eventEmitter.emit("deviceorientationerror", {
242
+ code: "LOCAR_DEVICE_ORIENTATION_NOT_SUPPORTED",
243
+ message: "Device orientation API not supported"
244
+ }) : window.isSecureContext === !1 ? this.eventEmitter.emit("deviceorientationerror", {
245
+ code: "LOCAR_DEVICE_ORIENTATION_NO_HTTPS",
246
+ message: "DeviceOrientationEvent is only available in secure contexts (https)"
247
+ }) : typeof window.DeviceOrientationEvent.requestPermission == "function" && this.enablePermissionDialog ? this.obtainPermissionGesture() : this.eventEmitter.emit("deviceorientationgranted", { target: this });
248
+ }, this.eventEmitter = new y();
249
+ const t = this;
250
+ this.object = e, 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.orientationChangeEventName = "ondeviceorientationabsolute" in window ? "deviceorientationabsolute" : "deviceorientation", this.smoothingFactor = s.smoothingFactor || 1, this.enablePermissionDialog = s.enablePermissionDialog ?? !0, this.enableInlineStyling = s.enableStyling ?? !0, this.preferConfirmDialog = s.preferConfirmDialog ?? !1, this.orientationChangeThreshold = s.orientationChangeThreshold ?? 0;
251
+ const c = (i) => {
252
+ let { alpha: n, beta: a, gamma: r, webkitCompassHeading: o } = i;
253
+ if (n = n ?? 0, a = a ?? 0, r = r ?? 0, o = o ?? 0, p) {
254
+ const l = 360 - o;
255
+ t.alphaOffset = u.degToRad(l - n), t.deviceOrientation = { alpha: n, beta: a, gamma: r, webkitCompassHeading: o };
332
256
  } else
333
- n < 0 && (n += 360), e.deviceOrientation = { alpha: n, beta: s, gamma: a };
257
+ n < 0 && (n += 360), t.deviceOrientation = { alpha: n, beta: a, gamma: r };
334
258
  window.dispatchEvent(
335
259
  new CustomEvent("camera-rotation-change", {
336
- detail: { cameraRotation: t.rotation }
260
+ detail: { cameraRotation: e.rotation }
337
261
  })
338
262
  );
339
- }, h = function() {
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);
341
- }, E = function(n, s, a, r, o) {
342
- y.set(a, s, -r, "YXZ"), n.setFromEuler(y), n.multiply(F), n.multiply(H.setFromAxisAngle(x, -o));
263
+ }, h = () => {
264
+ t.screenOrientation = window.screen.orientation?.angle ?? 0, p && (t.screenOrientation === 90 ? t.orientationOffset = -f : t.screenOrientation === -90 ? t.orientationOffset = f : t.orientationOffset = 0);
265
+ }, O = (i, n, a, r, o) => {
266
+ A.set(a, n, -r, "YXZ"), i.setFromEuler(A), i.multiply(L), i.multiply(x.setFromAxisAngle(N, -o));
343
267
  };
344
- this.connect = function() {
268
+ this.connect = () => {
345
269
  h(), window.addEventListener(
346
270
  "orientationchange",
347
271
  h
348
272
  ), window.addEventListener(
349
- e.orientationChangeEventName,
273
+ t.orientationChangeEventName,
350
274
  c
351
- ), e.enabled = !0;
352
- }, this.disconnect = function() {
275
+ ), t.enabled = !0;
276
+ }, this.disconnect = () => {
353
277
  window.removeEventListener(
354
278
  "orientationchange",
355
279
  h
356
280
  ), window.removeEventListener(
357
- e.orientationChangeEventName,
281
+ t.orientationChangeEventName,
358
282
  c
359
- ), e.enabled = !1, e.initialOffset = !1, e.deviceOrientation = null;
360
- }, this.requestOrientationPermissions = function() {
361
- window.DeviceOrientationEvent !== void 0 && typeof window.DeviceOrientationEvent.requestPermission == "function" ? window.DeviceOrientationEvent.requestPermission().then((n) => {
362
- n === "granted" ? this.eventEmitter.emit("deviceorientationgranted", {
283
+ ), t.enabled = !1, t.initialOffset = !1, t.deviceOrientation = null;
284
+ }, this.requestOrientationPermissions = () => {
285
+ window.DeviceOrientationEvent !== void 0 && typeof window.DeviceOrientationEvent.requestPermission == "function" ? window.DeviceOrientationEvent.requestPermission().then((i) => {
286
+ i === "granted" ? this.eventEmitter.emit("deviceorientationgranted", {
363
287
  target: this
364
288
  }) : this.eventEmitter.emit("deviceorientationerror", {
365
289
  code: "LOCAR_DEVICE_ORIENTATION_PERMISSION_DENIED",
366
290
  message: "Permission for device orientation denied - AR will not work correctly"
367
291
  });
368
- }).catch(function(n) {
292
+ }).catch((i) => {
369
293
  this.eventEmitter.emit("deviceorientationerror", {
370
294
  code: "LOCAR_DEVICE_ORIENTATION_PERMISSION_FAILED",
371
295
  message: "Permission request for device orientation failed - AR will not work correctly",
372
- error: JSON.stringify(n, null, 2)
296
+ error: JSON.stringify(i, null, 2)
373
297
  });
374
298
  }) : this.eventEmitter.emit("deviceorientationerror", {
375
299
  code: "LOCAR_DEVICE_ORIENTATION_INTERNAL_ERROR",
376
300
  message: "Internal error: no requestPermission() found although requestOrientationPermissions() was called - please raise an issue on GitHub"
377
301
  });
378
- }, this.update = function({ theta: n = 0 } = { theta: 0 }) {
379
- if (e.enabled === !1) return;
380
- const s = e.deviceOrientation;
381
- if (s) {
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(
388
- a,
389
- e.lastOrientation.alpha,
390
- d
391
- ), r = e._getSmoothedAngle(
392
- r + Math.PI,
393
- e.lastOrientation.beta,
394
- d
395
- ), o = e._getSmoothedAngle(
396
- o + e.HALF_PI,
397
- e.lastOrientation.gamma,
398
- d,
302
+ }, this.update = () => {
303
+ if (t.enabled === !1) return;
304
+ const i = t.deviceOrientation;
305
+ if (i) {
306
+ let n = i.alpha ? u.degToRad(i.alpha) + t.alphaOffset : 0, a = i.beta ? u.degToRad(i.beta) : 0, r = i.gamma ? u.degToRad(i.gamma) : 0;
307
+ const o = t.screenOrientation ? u.degToRad(t.screenOrientation) : 0;
308
+ if (t.smoothingFactor < 1)
309
+ if (t.lastOrientation) {
310
+ const l = t.smoothingFactor;
311
+ n = t._getSmoothedAngle(
312
+ n,
313
+ t.lastOrientation.alpha,
314
+ l
315
+ ), a = t._getSmoothedAngle(
316
+ a + Math.PI,
317
+ t.lastOrientation.beta,
318
+ l
319
+ ), r = t._getSmoothedAngle(
320
+ r + f,
321
+ t.lastOrientation.gamma,
322
+ l,
399
323
  Math.PI
400
324
  );
401
325
  } else
402
- r += Math.PI, o += e.HALF_PI;
403
- e.lastOrientation = {
404
- alpha: a,
405
- beta: r,
406
- gamma: o
407
- };
408
- }
409
- if (O) {
410
- const d = new I();
411
- E(
412
- d,
413
- a,
414
- e.smoothingFactor < 1 ? r - Math.PI : r,
415
- e.smoothingFactor < 1 ? o - Math.PI / 2 : o,
416
- f
326
+ a += Math.PI, r += f;
327
+ if (t.lastOrientation && (n = t._calcAngleWithThreshold(
328
+ n,
329
+ t.lastOrientation.alpha
330
+ ), a = t._calcAngleWithThreshold(
331
+ a,
332
+ t.lastOrientation.beta
333
+ ), r = t._calcAngleWithThreshold(
334
+ r,
335
+ t.lastOrientation.gamma
336
+ )), p) {
337
+ const l = new E();
338
+ O(
339
+ l,
340
+ n,
341
+ t.smoothingFactor < 1 ? a - Math.PI : a,
342
+ t.smoothingFactor < 1 ? r - Math.PI / 2 : r,
343
+ o
417
344
  );
418
- const u = new w().setFromQuaternion(
419
- d,
345
+ const v = new C().setFromQuaternion(
346
+ l,
420
347
  "YXZ"
421
348
  );
422
- let p = g.degToRad(360 - s.webkitCompassHeading);
423
- e.smoothingFactor < 1 && e.lastCompassY !== void 0 && (p = e._getSmoothedAngle(
424
- p,
425
- e.lastCompassY,
426
- e.smoothingFactor
427
- )), e.lastCompassY = p, u.y = p + (e.orientationOffset || 0), d.setFromEuler(u), e.object.quaternion.copy(d);
349
+ let d = u.degToRad(
350
+ 360 - (i.webkitCompassHeading ?? 0)
351
+ );
352
+ t.smoothingFactor < 1 && t.lastCompassY !== void 0 && (d = t._getSmoothedAngle(
353
+ d,
354
+ t.lastCompassY,
355
+ t.smoothingFactor
356
+ )), t.lastCompassY = d, v.y = d + (t.orientationOffset || 0), l.setFromEuler(v), t.object.quaternion.copy(l);
428
357
  } else
429
- E(
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,
434
- f
358
+ O(
359
+ t.object.quaternion,
360
+ p ? n + t.alphaOffset : n,
361
+ t.smoothingFactor < 1 ? a - Math.PI : a,
362
+ t.smoothingFactor < 1 ? r - f : r,
363
+ o
435
364
  );
365
+ t.lastOrientation = {
366
+ alpha: n,
367
+ beta: a,
368
+ gamma: r
369
+ };
436
370
  }
437
- }, this.getCorrectedHeading = function() {
438
- const { deviceOrientation: n } = e;
439
- if (!n) return 0;
440
- let s = 0;
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) {
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 };
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;
446
- o.left = 0, o.right -= f, o.right < 0 && (o.right += r);
447
- let u = d == s ? (1 - a) * o.right + a * o.left : a * o.right + (1 - a) * o.left;
448
- return u += f, u >= r && (u -= r), u;
449
- }, this.updateAlphaOffset = function() {
450
- e.initialOffset = !1;
451
- }, this.dispose = function() {
452
- e.disconnect();
453
- }, this.getAlpha = function() {
454
- const { deviceOrientation: n } = e;
455
- return n && n.alpha ? g.degToRad(n.alpha) + e.alphaOffset : 0;
456
- }, this.getBeta = function() {
457
- const { deviceOrientation: n } = e;
458
- return n && n.beta ? g.degToRad(n.beta) : 0;
459
- }, this.getGamma = function() {
460
- const { deviceOrientation: n } = e;
461
- return n && n.gamma ? g.degToRad(n.gamma) : 0;
462
- }, this.createObtainPermissionGestureDialog = function() {
371
+ }, this.getCorrectedHeading = () => {
372
+ const { deviceOrientation: i } = t;
373
+ if (!i) return 0;
374
+ let n = 0;
375
+ return p ? (n = 360 - (i.webkitCompassHeading ?? 0), t.orientationOffset && (n += t.orientationOffset * (180 / Math.PI), n = (n + 360) % 360)) : (i.absolute === !0 || t.orientationChangeEventName, n = i.alpha ? i.alpha : 0, n = (360 - n) % 360, n < 0 && (n += 360)), n;
376
+ }, this._calcAngleWithThreshold = (i, n) => Math.abs(i - n) < t.orientationChangeThreshold ? n : i, this._orderAngle = (i, n, a = M) => n > i && Math.abs(n - i) < a / 2 || i > n && Math.abs(n - i) > a / 2 ? { left: i, right: n } : { left: n, right: i }, this._getSmoothedAngle = (i, n, a, r = M) => {
377
+ const o = t._orderAngle(i, n, r), l = o.left, v = o.right;
378
+ o.left = 0, o.right -= l, o.right < 0 && (o.right += r);
379
+ let d = v == n ? (1 - a) * o.right + a * o.left : a * o.right + (1 - a) * o.left;
380
+ return d += l, d >= r && (d -= r), d;
381
+ }, this.updateAlphaOffset = () => {
382
+ t.initialOffset = !1;
383
+ }, this.dispose = () => {
384
+ t.disconnect();
385
+ }, this.getAlpha = () => {
386
+ const { deviceOrientation: i } = t;
387
+ return i && i.alpha ? u.degToRad(i.alpha) + t.alphaOffset : 0;
388
+ }, this.getBeta = () => {
389
+ const { deviceOrientation: i } = t;
390
+ return i && i.beta ? u.degToRad(i.beta) : 0;
391
+ }, this.getGamma = () => {
392
+ const { deviceOrientation: i } = t;
393
+ return i && i.gamma ? u.degToRad(i.gamma) : 0;
394
+ }, this.createObtainPermissionGestureDialog = () => {
395
+ const i = document.createElement("div");
396
+ i.classList.add(R);
463
397
  const n = document.createElement("div");
464
- n.classList.add(b);
465
- const s = document.createElement("div");
466
- s.classList.add(N);
398
+ n.classList.add(D);
467
399
  const a = document.createElement("div");
468
- a.classList.add(S);
400
+ a.classList.add(b);
469
401
  const r = document.createElement("div");
470
- r.classList.add(L);
402
+ r.classList.add(S);
471
403
  const o = document.createElement("button");
472
- if (o.classList.add(D), document.body.appendChild(n), this.enableInlineStyling === !0) {
473
- const d = {
474
- fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'",
475
- display: "flex",
476
- position: "fixed",
477
- zIndex: 1e5,
478
- justifyContent: "center",
479
- alignItems: "center",
480
- backgroundColor: "rgba(0,0,0,0.2)",
481
- inset: 0,
482
- padding: "20px"
483
- }, u = {
484
- backgroundColor: "rgba(220, 220, 220, 0.85)",
485
- padding: "6px 0",
486
- borderRadius: "10px",
487
- width: "100%",
488
- maxWidth: "400px"
489
- }, p = {
490
- padding: "10px 12px",
491
- textAlign: "center",
492
- fontWeight: 400,
493
- fontSize: "13px",
494
- display: "flex",
495
- justifyContent: "center",
496
- alignItems: "center"
497
- }, M = {
498
- display: "block",
499
- textAlign: "center",
500
- textDecoration: "none",
501
- borderTop: "rgb(180,180,180) solid 1px"
502
- }, _ = {
503
- display: "block",
504
- width: "100%",
505
- textAlign: "center",
506
- appearance: "none",
507
- background: "none",
508
- border: "none",
509
- outline: "none",
510
- padding: "10px",
511
- fontWeight: 400,
512
- fontSize: "16px",
513
- color: "#2e7cf1",
514
- cursor: "pointer"
515
- };
516
- for (let l in d)
517
- n.style[l] = d[l];
518
- for (let l in u)
519
- s.style[l] = u[l];
520
- for (let l in p)
521
- a.style[l] = p[l];
522
- for (let l in M)
523
- r.style[l] = M[l];
524
- for (let l in _)
525
- o.style[l] = _[l];
526
- }
527
- n.appendChild(s), s.appendChild(a), s.appendChild(r), a.appendChild(
528
- document.createTextNode(P)
404
+ o.classList.add(P), document.body.appendChild(i), this.enableInlineStyling === !0 && (i.style.fontFamily = "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'", i.style.display = "flex", i.style.position = "fixed", i.style.zIndex = "100000", i.style.justifyContent = "center", i.style.alignItems = "center", i.style.backgroundColor = "rgba(0,0,0,0.2)", i.style.inset = "0", i.style.padding = "20px", n.style.backgroundColor = "rgba(220, 220, 220, 0.85)", n.style.padding = "6px 0", n.style.borderRadius = "10px", n.style.width = "100%", n.style.maxWidth = "400px", a.style.padding = "10px 12px", a.style.textAlign = "center", a.style.fontWeight = "400", a.style.fontSize = "13px", a.style.display = "flex", a.style.justifyContent = "center", a.style.alignItems = "center", r.style.display = "block", r.style.textAlign = "center", r.style.textDecoration = "none", r.style.borderTop = "rgb(180,180,180) solid 1px", o.style.display = "block", o.style.width = "100%", o.style.textAlign = "center", o.style.appearance = "none", o.style.background = "none", o.style.border = "none", o.style.outline = "none", o.style.padding = "10px", o.style.fontWeight = "400", o.style.fontSize = "16px", o.style.color = "#2e7cf1", o.style.cursor = "pointer"), i.appendChild(n), n.appendChild(a), n.appendChild(r), a.appendChild(
405
+ document.createTextNode(I)
529
406
  );
530
- const f = () => {
531
- this.requestOrientationPermissions(), n.style.display = "none";
407
+ const l = () => {
408
+ this.requestOrientationPermissions(), i.style.display = "none";
532
409
  };
533
- o.addEventListener("click", f), o.appendChild(document.createTextNode("OK")), r.appendChild(o), document.body.appendChild(n);
534
- }, this.obtainPermissionGesture = function() {
535
- this.preferConfirmDialog === !0 ? window.confirm(P) && this.requestOrientationPermissions() : this.createObtainPermissionGestureDialog();
410
+ o.addEventListener("click", l), o.appendChild(document.createTextNode("OK")), r.appendChild(o), document.body.appendChild(i);
411
+ }, this.obtainPermissionGesture = () => {
412
+ this.preferConfirmDialog === !0 ? window.confirm(I) && this.requestOrientationPermissions() : this.createObtainPermissionGestureDialog();
536
413
  };
537
414
  }
538
- on(t, i) {
539
- this.eventEmitter.on(t, i);
540
- }
541
- /**
542
- * Initialise device orientation controls.
543
- * Should be called after you have created the DeviceOrientationControls
544
- * object and set up the deviceorientationgranted and deviceorientationerror
545
- * event handlers.
546
- */
547
- init() {
548
- window.DeviceOrientationEvent === void 0 ? this.eventEmitter.emit("deviceorientationerror", {
549
- code: "LOCAR_DEVICE_ORIENTATION_NOT_SUPPORTED",
550
- message: "Device orientation API not supported"
551
- }) : window.isSecureContext === !1 ? this.eventEmitter.emit("deviceorientationerror", {
552
- code: "LOCAR_DEVICE_ORIENTATION_NO_HTTPS",
553
- message: "DeviceOrientationEvent is only available in secure contexts (https)"
554
- }) : typeof window.DeviceOrientationEvent.requestPermission == "function" && this.enablePermissionDialog ? this.obtainPermissionGesture() : this.eventEmitter.emit("deviceorientationgranted", { target: this });
415
+ on(e, s) {
416
+ this.eventEmitter.on(e, s);
555
417
  }
556
418
  }
557
- class j {
419
+ class W {
558
420
  /**
559
421
  * Create a ClickHandler.
560
422
  * @param {THREE.WebGLRenderer} - The Three.js renderer on which the click
561
423
  * events will be handled.
562
424
  */
563
- constructor(t) {
564
- this.raycaster = new m.Raycaster(), this.normalisedMousePosition = new m.Vector2(null, null), t.domElement.addEventListener("click", (i) => {
565
- this.normalisedMousePosition.set(
566
- i.clientX / t.domElement.clientWidth * 2 - 1,
567
- -(i.clientY / t.domElement.clientHeight * 2) + 1
425
+ constructor(e) {
426
+ this.raycaster = new g.Raycaster(), this.normalisedMousePosition = null, e.domElement.addEventListener("click", (s) => {
427
+ this.normalisedMousePosition = new g.Vector2(
428
+ s.clientX / e.domElement.clientWidth * 2 - 1,
429
+ -(s.clientY / e.domElement.clientHeight * 2) + 1
568
430
  );
569
431
  });
570
432
  }
@@ -576,22 +438,61 @@ class j {
576
438
  * cast into.
577
439
  * @return {Array} - array of all intersected objects.
578
440
  */
579
- raycast(t, i) {
580
- if (this.normalisedMousePosition.x !== null && this.normalisedMousePosition.y !== 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;
441
+ raycast(e, s) {
442
+ if (this.normalisedMousePosition !== null) {
443
+ this.raycaster.setFromCamera(this.normalisedMousePosition, e);
444
+ const t = this.raycaster.intersectObjects(s.children, !1);
445
+ return this.normalisedMousePosition = null, t;
584
446
  }
585
447
  return [];
586
448
  }
587
449
  }
588
- const U = "0.1.5";
450
+ class V extends y {
451
+ #t;
452
+ /**
453
+ * Create a Webcam.
454
+ * @param constraints {Object} - options to use for initialising the camera.
455
+ * This is the same constraints object as used by standard MediaDevices API.
456
+ * @param {string} videoElementSelector - selector to obtain the HTML video
457
+ * element to render the webcam feed. If a falsy value (e.g. null or
458
+ * undefined), a video element will be created.
459
+ */
460
+ constructor(e = { video: { facingMode: "environment" } }, s) {
461
+ super(), this.sceneWebcam = new g.Scene(), s ? this.#t = document.querySelector(s) : (this.#t = document.createElement("video"), this.#t.setAttribute("autoplay", "true"), this.#t.setAttribute("playsinline", "true"), this.#t.style.display = "none", document.body.appendChild(this.#t)), this.texture = this.#t ? new g.VideoTexture(this.#t) : null, navigator.mediaDevices && navigator.mediaDevices.getUserMedia ? navigator.mediaDevices.getUserMedia(e).then((t) => {
462
+ this.#t?.addEventListener("loadedmetadata", () => {
463
+ this.#t?.setAttribute(
464
+ "width",
465
+ this.#t?.videoWidth.toString() ?? "0"
466
+ ), this.#t?.setAttribute(
467
+ "height",
468
+ this.#t?.videoHeight.toString() ?? "0"
469
+ ), this.#t?.play(), this.emit("webcamstarted", { texture: this.texture });
470
+ }), this.#t && (this.#t.srcObject = t);
471
+ }).catch((t) => {
472
+ this.emit("webcamerror", {
473
+ code: t.name,
474
+ message: t.message
475
+ });
476
+ }) : this.emit("webcamerror", {
477
+ code: "LOCAR_NO_MEDIA_DEVICES_API",
478
+ message: "Media devices API not supported"
479
+ });
480
+ }
481
+ /**
482
+ * Free up the memory associated with the webcam.
483
+ * Should be called when your application closes.
484
+ */
485
+ dispose() {
486
+ this.texture?.dispose();
487
+ }
488
+ }
489
+ const j = "0.1.7";
589
490
  export {
590
- j as ClickHandler,
591
- V as DeviceOrientationControls,
592
- A as EventEmitter,
593
- k as LocationBased,
594
- T as SphMercProjection,
595
- W as Webcam,
596
- U as version
491
+ W as ClickHandler,
492
+ q as DeviceOrientationControls,
493
+ y as EventEmitter,
494
+ F as LocationBased,
495
+ w as SphMercProjection,
496
+ V as Webcam,
497
+ j as version
597
498
  };