locar 0.2.1 → 0.2.2
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.d.ts +1 -1
- package/dist/locar.es.js +1 -1
- package/dist/locar.umd.js +2 -2
- package/package.json +1 -1
package/dist/locar.d.ts
CHANGED
|
@@ -275,7 +275,7 @@ export declare class LocAR extends EventEmitter {
|
|
|
275
275
|
* the contents of the GeoJSON properties field).
|
|
276
276
|
*/
|
|
277
277
|
add(object: THREE.Object3D, lon: number, lat: number, elev?: number | undefined, properties?: Record<string, any>): void;
|
|
278
|
-
addGeoLine(points: Array<[number, number, number?]>, material: THREE.Material, lineWidth?: number):
|
|
278
|
+
addGeoLine(points: Array<[number, number, number?]>, material: THREE.Material, lineWidth?: number): THREE.Mesh;
|
|
279
279
|
/**
|
|
280
280
|
* Set the elevation (y coordinate) of the camera.
|
|
281
281
|
* @param {number} elev - the elevation in metres.
|
package/dist/locar.es.js
CHANGED
package/dist/locar.umd.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(g,u){typeof exports=="object"&&typeof module<"u"?u(exports,require("three")):typeof define=="function"&&define.amd?define(["exports","three"],u):(g=typeof globalThis<"u"?globalThis:g||self,u(g.locar={},g.THREE))})(this,(function(g,u){"use strict";function _(f){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(f){for(const i in f)if(i!=="default"){const t=Object.getOwnPropertyDescriptor(f,i);Object.defineProperty(e,i,t.get?t:{enumerable:!0,get:()=>f[i]})}}return e.default=f,Object.freeze(e)}const m=_(u);class w{constructor(){this.on=(e,i)=>{this.eventHandlers[e]===void 0&&(this.eventHandlers[e]=[]),this.eventHandlers[e].push(i)},this.emit=(e,...i)=>{this.eventHandlers[e]?.forEach(t=>{t(...i)})},this.off=(e,i)=>{if(this.eventHandlers[e]){const t=this.eventHandlers[e].indexOf(i);t>-1&&this.eventHandlers[e].splice(t,1)}},this.eventHandlers={}}}class T extends w{constructor({cameraOptions:e,canvas:i,gpsOptions:t,videoConstraints:o,deviceOrientationOptions:l,serverLogger:p,projection:n}){super(),this.origHfov=e?.hFov||80;const s=0;this.cameraFeedDimensions=null;const d=window.innerWidth/window.innerHeight;this.camera=new m.PerspectiveCamera(this.origHfov/d,d,e?.near||.001,e?.far||1e3),i?(this.renderer=new m.WebGLRenderer({canvas:i,alpha:!0}),this.renderer.setClearColor(65280,s)):(this.renderer=new m.WebGLRenderer({alpha:!0}),this.renderer.setClearColor(65280,s),document.body.appendChild(this.renderer.domElement)),this.renderer.setSize(window.innerWidth,window.innerHeight),this.scene=new m.Scene;const c=l||{enabled:!0};window.addEventListener("resize",()=>{this.renderer.setSize(window.innerWidth,window.innerHeight);const a=window.innerWidth/window.innerHeight;if(this.camera.aspect=a,this.cameraFeedDimensions!==null){const h=a>1?this.cameraFeedDimensions.landWidth:this.cameraFeedDimensions.landHeight,v=a>1?this.cameraFeedDimensions.landHeight:this.cameraFeedDimensions.landWidth;this.#e(h,v,a)}this.camera.updateProjectionMatrix()}),this.locar=new y(this.scene,this.camera,t,p,n),this.webcam=new D(o),this.deviceOrientationControls=c.enabled===!0?new A(this.camera,c):null,this.renderer.setAnimationLoop(()=>{this.deviceOrientationControls?.update(),this.renderer.render(this.scene,this.camera)})}start(){return new Promise((i,t)=>{this.webcam.on("webcamstarted",o=>{const l=o.videoWidth>o.videoHeight;this.cameraFeedDimensions={landWidth:l?o.videoWidth:o.videoHeight,landHeight:l?o.videoHeight:o.videoWidth},this.#e(o.videoWidth,o.videoHeight,window.innerWidth/window.innerHeight),this.camera.updateProjectionMatrix()}),this.webcam.on("webcamerror",o=>{t({code:o.code,message:o.message})}),this.deviceOrientationControls===null?i(this.locar):(this.deviceOrientationControls?.on("deviceorientationgranted",o=>{o.target.connect(),i(this.locar)}),this.deviceOrientationControls.on("deviceorientationerror",o=>{t({code:o.code,message:o.message})}),this.deviceOrientationControls.init())})}#e(e,i,t){const o=e/i;if(t<o){const l=e*(window.innerHeight/i),p=this.origHfov*(window.innerWidth/l);this.camera.fov=p/t}else this.camera.fov=this.origHfov/t}}class b{constructor(){this.project=(e,i)=>[this.#e(e),this.#t(i)],this.unproject=e=>[this.#i(e[0]),this.#n(e[1])],this.#e=e=>e/180*this.HALF_EARTH,this.#t=e=>{var i=Math.log(Math.tan((90+e)*Math.PI/360))/(Math.PI/180);return i*this.HALF_EARTH/180},this.#i=e=>e/this.HALF_EARTH*180,this.#n=e=>{var i=e/this.HALF_EARTH*180;return i=180/Math.PI*(2*Math.atan(Math.exp(i*Math.PI/180))-Math.PI/2),i},this.getID=()=>"epsg:3857",this.EARTH=4007501668e-2,this.HALF_EARTH=2003750834e-2}#e;#t;#i;#n}class y extends w{#e;#t;#i;#n;#a;#s;#d;#r;#o;constructor(e,i,t={},o=null,l=new b){super(),this.scene=e,this.camera=i,this.#e=l,this.#t=null,this.#i=0,this.#n=100,this.#a=null,this.setGpsOptions(t),this.#s=null,this.#d=0,this.#r=0,this.#o=o}setProjection(e){this.#e=e}setGpsOptions(e={}){e.gpsMinDistance!==void 0&&(this.#i=e.gpsMinDistance),e.gpsMinAccuracy!==void 0&&(this.#n=e.gpsMinAccuracy)}async startGps(){if(this.#o){const i=await(await this.#o.sendData("/gps/start",{gpsMinDistance:this.#i,gpsMinAccuracy:this.#n})).json();this.#r=i.session}return this.#a===null?(this.#a=navigator.geolocation.watchPosition(e=>{this.#c(e)},e=>{this.emit("gpserror",e)},{enableHighAccuracy:!0}),!0):!1}stopGps(){return this.#a!==null?(navigator.geolocation.clearWatch(this.#a),this.#a=null,!0):!1}fakeGps(e,i,t=null,o=0){t!==null&&this.setElevation(t),this.#c({coords:{longitude:e,latitude:i,accuracy:o}})}lonLatToWorldCoords(e,i){const t=this.#e.project(e,i);if(this.#s)t[0]-=this.#s[0],t[1]-=this.#s[1];else throw"No initial position determined";return[t[0],-t[1]]}add(e,i,t,o,l={}){e.properties=l,this.#l(e,i,t,o||0),this.scene.add(e),this.#o?.sendData("/object/new",{position:e.position,x:e.position.x,z:e.position.z,session:this.#r,properties:l})}addGeoLine(e,i,t=1){const o=e.map((n=>{const[s,d]=this.lonLatToWorldCoords(n[0],n[1]);return new m.Vector3(s,n[2]||0,d)})),l=this.#h(o,t);i.setValues({side:m.DoubleSide});const p=new m.Mesh(l,i);this.scene.add(p)}#h(e,i){let t,o,l,p,n=0,s=0,d=[],c;const a=e.length-1,h=[];for(let r=0;r<a;r++)t=e[r+1].x-e[r].x,o=e[r+1].z-e[r].z,l=e[r+1].y-e[r].y,p=Math.sqrt(t*t+l*l+o*o),n=-(o*(i/2))/p,s=t*(i/2)/p,c=[e[r].x-n,e[r].y,e[r].z-s,e[r].x+n,e[r].y,e[r].z+s],r>0&&c.forEach((P,V)=>{P=(P+d[V])/2}),h.push(...c),d=[e[r+1].x-n,e[r+1].y,e[r+1].z-s,e[r+1].x+n,e[r+1].y,e[r+1].z+s];h.push(e[a].x-n),h.push(e[a].y),h.push(e[a].z-s),h.push(e[a].x+n),h.push(e[a].y),h.push(e[a].z+s);let v=[];for(let r=0;r<a;r++)v.push(r*2,r*2+1,r*2+2),v.push(r*2+1,r*2+3,r*2+2);let O=new m.BufferGeometry,z=new Float32Array(h);return O.setIndex(v),O.setAttribute("position",new m.BufferAttribute(z,3)),O.computeBoundingBox(),O}#l(e,i,t,o){const l=this.lonLatToWorldCoords(i,t);o!==void 0&&(e.position.y=o),[e.position.x,e.position.z]=l}setElevation(e){this.camera.position.y=e}#u(e,i){this.#s=this.#e.project(e,i)}#c(e){let i=Number.MAX_VALUE;this.#d++,this.#o?.sendData("/gps/new",{gpsCount:this.#d,lat:e.coords.latitude,lon:e.coords.longitude,acc:e.coords.accuracy,session:this.#r}),e.coords.accuracy<=this.#n&&(this.#t===null?this.#t={latitude:e.coords.latitude,longitude:e.coords.longitude}:i=y.haversineDist(this.#t,e.coords),i>=this.#i&&(this.#t.longitude=e.coords.longitude,this.#t.latitude=e.coords.latitude,this.#s||(this.#u(e.coords.longitude,e.coords.latitude),this.#o?.sendData("/worldorigin/new",{gpsCount:this.#d,lat:e.coords.latitude,lon:e.coords.longitude,session:this.#r,initialPosition:this.#s})),this.#l(this.camera,e.coords.longitude,e.coords.latitude),this.#o?.sendData("/gps/accepted",{gpsCount:this.#d,cameraX:this.camera.position.x,cameraZ:this.camera.position.z,session:this.#r,distMoved:i}),this.emit("gpsupdate",{position:e,distMoved:i})))}static haversineDist(e,i){const t=m.MathUtils.degToRad(i.longitude-e.longitude),o=m.MathUtils.degToRad(i.latitude-e.latitude),l=Math.sin(o/2)*Math.sin(o/2)+Math.cos(m.MathUtils.degToRad(e.latitude))*Math.cos(m.MathUtils.degToRad(i.latitude))*(Math.sin(t/2)*Math.sin(t/2));return 2*Math.atan2(Math.sqrt(l),Math.sqrt(1-l))*6371e3}getLastKnownLocation(){return this.#t}}const R="locar-device-orientation-permission-modal",x="locar-device-orientation-permission-button",L="locar-device-orientation-permission-message",S="locar-device-orientation-permission-inner",N="locar-device-orientation-permission-button-inner",C="This immersive website requires access to your device motion sensors.",E=navigator.userAgent.match(/iPhone|iPad|iPod/i)||/Macintosh/i.test(navigator.userAgent)&&navigator.maxTouchPoints!=null&&navigator.maxTouchPoints>1,H=new u.Vector3(0,0,1),M=new u.Euler,W=new u.Quaternion,F=new u.Quaternion(-Math.sqrt(.5),0,0,Math.sqrt(.5)),I=.5*Math.PI;class A extends u.EventDispatcher{constructor(e,i={}){super(),this.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})},this.eventEmitter=new w;const t=this;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.lastQuaternion=null,this.orientationChangeEventName="ondeviceorientationabsolute"in window?"deviceorientationabsolute":"deviceorientation",this.smoothingFactor=i.smoothingFactor||.2,this.enablePermissionDialog=i.enablePermissionDialog??!0,this.enableInlineStyling=i.enableStyling??!0,this.preferConfirmDialog=i.preferConfirmDialog??!1,this.orientationChangeThreshold=i.orientationChangeThreshold??0;const o=n=>{let{alpha:s,beta:d,gamma:c,webkitCompassHeading:a}=n;if(s=s??0,d=d??0,c=c??0,a=a??0,E){const h=360-a;t.alphaOffset=u.MathUtils.degToRad(h-s),t.deviceOrientation={alpha:s,beta:d,gamma:c,webkitCompassHeading:a}}else s<0&&(s+=360),t.deviceOrientation={alpha:s,beta:d,gamma:c};window.dispatchEvent(new CustomEvent("camera-rotation-change",{detail:{cameraRotation:e.rotation}}))},l=()=>{t.screenOrientation=window.screen.orientation?.angle??0,E&&(t.screenOrientation===90?t.orientationOffset=-I:t.screenOrientation===-90?t.orientationOffset=I:t.orientationOffset=0)},p=(n,s,d,c,a)=>{M.set(d,s,-c,"YXZ"),n.setFromEuler(M),n.multiply(F),n.multiply(W.setFromAxisAngle(H,-a))};this.connect=()=>{l(),window.addEventListener("orientationchange",l),window.addEventListener(t.orientationChangeEventName,o),t.enabled=!0},this.disconnect=()=>{window.removeEventListener("orientationchange",l),window.removeEventListener(t.orientationChangeEventName,o),t.enabled=!1,t.initialOffset=!1,t.deviceOrientation=null,t.lastQuaternion=null},this.requestOrientationPermissions=()=>{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(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=()=>{if(t.enabled===!1)return;const n=t.deviceOrientation;if(n){let s=n.alpha?u.MathUtils.degToRad(n.alpha)+t.alphaOffset:0,d=n.beta?u.MathUtils.degToRad(n.beta):0,c=n.gamma?u.MathUtils.degToRad(n.gamma):0;const a=t.screenOrientation?u.MathUtils.degToRad(t.screenOrientation):0,h=new u.Quaternion;if(E){p(h,s,d,c,a);const v=new u.Euler().setFromQuaternion(h,"YXZ"),O=u.MathUtils.degToRad(360-(n.webkitCompassHeading??0));v.y=O+(t.orientationOffset||0),h.setFromEuler(v)}else p(h,s,d,c,a);if(t.lastQuaternion&&t.orientationChangeThreshold>0&&h.angleTo(t.lastQuaternion)<t.orientationChangeThreshold)return;if(t.smoothingFactor<1&&t.lastQuaternion){const v=1-t.smoothingFactor;t.object.quaternion.slerp(h,v)}else t.object.quaternion.copy(h);t.lastQuaternion=t.object.quaternion.clone(),window.dispatchEvent(new CustomEvent("camera-rotation-change",{detail:{cameraRotation:t.object.rotation}}))}},this.getCorrectedHeading=()=>{const{deviceOrientation:n}=t;if(!n)return 0;let s=0;return E?(s=360-(n.webkitCompassHeading??0),t.orientationOffset&&(s+=t.orientationOffset*(180/Math.PI),s=(s+360)%360)):(n.absolute===!0||t.orientationChangeEventName,s=n.alpha?n.alpha:0,s=(360-s)%360,s<0&&(s+=360)),s},this.updateAlphaOffset=()=>{t.initialOffset=!1},this.dispose=()=>{t.disconnect()},this.getAlpha=()=>{const{deviceOrientation:n}=t;return n&&n.alpha?u.MathUtils.degToRad(n.alpha)+t.alphaOffset:0},this.getBeta=()=>{const{deviceOrientation:n}=t;return n&&n.beta?u.MathUtils.degToRad(n.beta):0},this.getGamma=()=>{const{deviceOrientation:n}=t;return n&&n.gamma?u.MathUtils.degToRad(n.gamma):0},this.createObtainPermissionGestureDialog=()=>{const n=document.createElement("div");n.classList.add(R);const s=document.createElement("div");s.classList.add(S);const d=document.createElement("div");d.classList.add(L);const c=document.createElement("div");c.classList.add(N);const a=document.createElement("button");a.classList.add(x),document.body.appendChild(n),this.enableInlineStyling===!0&&(n.style.fontFamily="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'",n.style.display="flex",n.style.position="fixed",n.style.zIndex="100000",n.style.justifyContent="center",n.style.alignItems="center",n.style.backgroundColor="rgba(0,0,0,0.2)",n.style.inset="0",n.style.padding="20px",s.style.backgroundColor="rgba(220, 220, 220, 0.85)",s.style.padding="6px 0",s.style.borderRadius="10px",s.style.width="100%",s.style.maxWidth="400px",d.style.padding="10px 12px",d.style.textAlign="center",d.style.fontWeight="400",d.style.fontSize="13px",d.style.display="flex",d.style.justifyContent="center",d.style.alignItems="center",c.style.display="block",c.style.textAlign="center",c.style.textDecoration="none",c.style.borderTop="rgb(180,180,180) solid 1px",a.style.display="block",a.style.width="100%",a.style.textAlign="center",a.style.appearance="none",a.style.background="none",a.style.border="none",a.style.outline="none",a.style.padding="10px",a.style.fontWeight="400",a.style.fontSize="16px",a.style.color="#2e7cf1",a.style.cursor="pointer"),n.appendChild(s),s.appendChild(d),s.appendChild(c),d.appendChild(document.createTextNode(C));const h=()=>{this.requestOrientationPermissions(),n.style.display="none"};a.addEventListener("click",h),a.appendChild(document.createTextNode("OK")),c.appendChild(a),document.body.appendChild(n)},this.obtainPermissionGesture=()=>{this.preferConfirmDialog===!0?window.confirm(C)&&this.requestOrientationPermissions():this.createObtainPermissionGestureDialog()}}on(e,i){this.eventEmitter.on(e,i)}}class j{constructor(e){this.raycaster=new m.Raycaster,this.normalisedMousePosition=null,e.domElement.addEventListener("click",i=>{this.normalisedMousePosition=new m.Vector2(i.clientX/e.domElement.clientWidth*2-1,-(i.clientY/e.domElement.clientHeight*2)+1)})}raycast(e,i){if(this.normalisedMousePosition!==null){this.raycaster.setFromCamera(this.normalisedMousePosition,e);const t=this.raycaster.intersectObjects(i.children,!1);return this.normalisedMousePosition=null,t}return[]}}class D extends w{#e;constructor(e={video:{facingMode:"environment"}},i){super(),this.sceneWebcam=new m.Scene,i?this.#e=document.querySelector(i):(this.#e=document.createElement("video"),this.#e.setAttribute("autoplay","true"),this.#e.setAttribute("playsinline","true"),this.#e.style.cssText+=`
|
|
1
|
+
(function(p,u){typeof exports=="object"&&typeof module<"u"?u(exports,require("three")):typeof define=="function"&&define.amd?define(["exports","three"],u):(p=typeof globalThis<"u"?globalThis:p||self,u(p.locar={},p.THREE))})(this,(function(p,u){"use strict";function _(f){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(f){for(const i in f)if(i!=="default"){const t=Object.getOwnPropertyDescriptor(f,i);Object.defineProperty(e,i,t.get?t:{enumerable:!0,get:()=>f[i]})}}return e.default=f,Object.freeze(e)}const m=_(u);class w{constructor(){this.on=(e,i)=>{this.eventHandlers[e]===void 0&&(this.eventHandlers[e]=[]),this.eventHandlers[e].push(i)},this.emit=(e,...i)=>{this.eventHandlers[e]?.forEach(t=>{t(...i)})},this.off=(e,i)=>{if(this.eventHandlers[e]){const t=this.eventHandlers[e].indexOf(i);t>-1&&this.eventHandlers[e].splice(t,1)}},this.eventHandlers={}}}class T extends w{constructor({cameraOptions:e,canvas:i,gpsOptions:t,videoConstraints:o,deviceOrientationOptions:l,serverLogger:g,projection:n}){super(),this.origHfov=e?.hFov||80;const s=0;this.cameraFeedDimensions=null;const d=window.innerWidth/window.innerHeight;this.camera=new m.PerspectiveCamera(this.origHfov/d,d,e?.near||.001,e?.far||1e3),i?(this.renderer=new m.WebGLRenderer({canvas:i,alpha:!0}),this.renderer.setClearColor(65280,s)):(this.renderer=new m.WebGLRenderer({alpha:!0}),this.renderer.setClearColor(65280,s),document.body.appendChild(this.renderer.domElement)),this.renderer.setSize(window.innerWidth,window.innerHeight),this.scene=new m.Scene;const c=l||{enabled:!0};window.addEventListener("resize",()=>{this.renderer.setSize(window.innerWidth,window.innerHeight);const a=window.innerWidth/window.innerHeight;if(this.camera.aspect=a,this.cameraFeedDimensions!==null){const h=a>1?this.cameraFeedDimensions.landWidth:this.cameraFeedDimensions.landHeight,v=a>1?this.cameraFeedDimensions.landHeight:this.cameraFeedDimensions.landWidth;this.#e(h,v,a)}this.camera.updateProjectionMatrix()}),this.locar=new y(this.scene,this.camera,t,g,n),this.webcam=new D(o),this.deviceOrientationControls=c.enabled===!0?new A(this.camera,c):null,this.renderer.setAnimationLoop(()=>{this.deviceOrientationControls?.update(),this.renderer.render(this.scene,this.camera)})}start(){return new Promise((i,t)=>{this.webcam.on("webcamstarted",o=>{const l=o.videoWidth>o.videoHeight;this.cameraFeedDimensions={landWidth:l?o.videoWidth:o.videoHeight,landHeight:l?o.videoHeight:o.videoWidth},this.#e(o.videoWidth,o.videoHeight,window.innerWidth/window.innerHeight),this.camera.updateProjectionMatrix()}),this.webcam.on("webcamerror",o=>{t({code:o.code,message:o.message})}),this.deviceOrientationControls===null?i(this.locar):(this.deviceOrientationControls?.on("deviceorientationgranted",o=>{o.target.connect(),i(this.locar)}),this.deviceOrientationControls.on("deviceorientationerror",o=>{t({code:o.code,message:o.message})}),this.deviceOrientationControls.init())})}#e(e,i,t){const o=e/i;if(t<o){const l=e*(window.innerHeight/i),g=this.origHfov*(window.innerWidth/l);this.camera.fov=g/t}else this.camera.fov=this.origHfov/t}}class b{constructor(){this.project=(e,i)=>[this.#e(e),this.#t(i)],this.unproject=e=>[this.#i(e[0]),this.#n(e[1])],this.#e=e=>e/180*this.HALF_EARTH,this.#t=e=>{var i=Math.log(Math.tan((90+e)*Math.PI/360))/(Math.PI/180);return i*this.HALF_EARTH/180},this.#i=e=>e/this.HALF_EARTH*180,this.#n=e=>{var i=e/this.HALF_EARTH*180;return i=180/Math.PI*(2*Math.atan(Math.exp(i*Math.PI/180))-Math.PI/2),i},this.getID=()=>"epsg:3857",this.EARTH=4007501668e-2,this.HALF_EARTH=2003750834e-2}#e;#t;#i;#n}class y extends w{#e;#t;#i;#n;#a;#s;#d;#r;#o;constructor(e,i,t={},o=null,l=new b){super(),this.scene=e,this.camera=i,this.#e=l,this.#t=null,this.#i=0,this.#n=100,this.#a=null,this.setGpsOptions(t),this.#s=null,this.#d=0,this.#r=0,this.#o=o}setProjection(e){this.#e=e}setGpsOptions(e={}){e.gpsMinDistance!==void 0&&(this.#i=e.gpsMinDistance),e.gpsMinAccuracy!==void 0&&(this.#n=e.gpsMinAccuracy)}async startGps(){if(this.#o){const i=await(await this.#o.sendData("/gps/start",{gpsMinDistance:this.#i,gpsMinAccuracy:this.#n})).json();this.#r=i.session}return this.#a===null?(this.#a=navigator.geolocation.watchPosition(e=>{this.#c(e)},e=>{this.emit("gpserror",e)},{enableHighAccuracy:!0}),!0):!1}stopGps(){return this.#a!==null?(navigator.geolocation.clearWatch(this.#a),this.#a=null,!0):!1}fakeGps(e,i,t=null,o=0){t!==null&&this.setElevation(t),this.#c({coords:{longitude:e,latitude:i,accuracy:o}})}lonLatToWorldCoords(e,i){const t=this.#e.project(e,i);if(this.#s)t[0]-=this.#s[0],t[1]-=this.#s[1];else throw"No initial position determined";return[t[0],-t[1]]}add(e,i,t,o,l={}){e.properties=l,this.#l(e,i,t,o||0),this.scene.add(e),this.#o?.sendData("/object/new",{position:e.position,x:e.position.x,z:e.position.z,session:this.#r,properties:l})}addGeoLine(e,i,t=1){const o=e.map((n=>{const[s,d]=this.lonLatToWorldCoords(n[0],n[1]);return new m.Vector3(s,n[2]||0,d)})),l=this.#h(o,t);i.setValues({side:m.DoubleSide});const g=new m.Mesh(l,i);return this.scene.add(g),g}#h(e,i){let t,o,l,g,n=0,s=0,d=[],c;const a=e.length-1,h=[];for(let r=0;r<a;r++)t=e[r+1].x-e[r].x,o=e[r+1].z-e[r].z,l=e[r+1].y-e[r].y,g=Math.sqrt(t*t+l*l+o*o),n=-(o*(i/2))/g,s=t*(i/2)/g,c=[e[r].x-n,e[r].y,e[r].z-s,e[r].x+n,e[r].y,e[r].z+s],r>0&&c.forEach((P,V)=>{P=(P+d[V])/2}),h.push(...c),d=[e[r+1].x-n,e[r+1].y,e[r+1].z-s,e[r+1].x+n,e[r+1].y,e[r+1].z+s];h.push(e[a].x-n),h.push(e[a].y),h.push(e[a].z-s),h.push(e[a].x+n),h.push(e[a].y),h.push(e[a].z+s);let v=[];for(let r=0;r<a;r++)v.push(r*2,r*2+1,r*2+2),v.push(r*2+1,r*2+3,r*2+2);let O=new m.BufferGeometry,z=new Float32Array(h);return O.setIndex(v),O.setAttribute("position",new m.BufferAttribute(z,3)),O.computeBoundingBox(),O}#l(e,i,t,o){const l=this.lonLatToWorldCoords(i,t);o!==void 0&&(e.position.y=o),[e.position.x,e.position.z]=l}setElevation(e){this.camera.position.y=e}#u(e,i){this.#s=this.#e.project(e,i)}#c(e){let i=Number.MAX_VALUE;this.#d++,this.#o?.sendData("/gps/new",{gpsCount:this.#d,lat:e.coords.latitude,lon:e.coords.longitude,acc:e.coords.accuracy,session:this.#r}),e.coords.accuracy<=this.#n&&(this.#t===null?this.#t={latitude:e.coords.latitude,longitude:e.coords.longitude}:i=y.haversineDist(this.#t,e.coords),i>=this.#i&&(this.#t.longitude=e.coords.longitude,this.#t.latitude=e.coords.latitude,this.#s||(this.#u(e.coords.longitude,e.coords.latitude),this.#o?.sendData("/worldorigin/new",{gpsCount:this.#d,lat:e.coords.latitude,lon:e.coords.longitude,session:this.#r,initialPosition:this.#s})),this.#l(this.camera,e.coords.longitude,e.coords.latitude),this.#o?.sendData("/gps/accepted",{gpsCount:this.#d,cameraX:this.camera.position.x,cameraZ:this.camera.position.z,session:this.#r,distMoved:i}),this.emit("gpsupdate",{position:e,distMoved:i})))}static haversineDist(e,i){const t=m.MathUtils.degToRad(i.longitude-e.longitude),o=m.MathUtils.degToRad(i.latitude-e.latitude),l=Math.sin(o/2)*Math.sin(o/2)+Math.cos(m.MathUtils.degToRad(e.latitude))*Math.cos(m.MathUtils.degToRad(i.latitude))*(Math.sin(t/2)*Math.sin(t/2));return 2*Math.atan2(Math.sqrt(l),Math.sqrt(1-l))*6371e3}getLastKnownLocation(){return this.#t}}const R="locar-device-orientation-permission-modal",x="locar-device-orientation-permission-button",L="locar-device-orientation-permission-message",S="locar-device-orientation-permission-inner",N="locar-device-orientation-permission-button-inner",C="This immersive website requires access to your device motion sensors.",E=navigator.userAgent.match(/iPhone|iPad|iPod/i)||/Macintosh/i.test(navigator.userAgent)&&navigator.maxTouchPoints!=null&&navigator.maxTouchPoints>1,H=new u.Vector3(0,0,1),M=new u.Euler,W=new u.Quaternion,F=new u.Quaternion(-Math.sqrt(.5),0,0,Math.sqrt(.5)),I=.5*Math.PI;class A extends u.EventDispatcher{constructor(e,i={}){super(),this.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})},this.eventEmitter=new w;const t=this;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.lastQuaternion=null,this.orientationChangeEventName="ondeviceorientationabsolute"in window?"deviceorientationabsolute":"deviceorientation",this.smoothingFactor=i.smoothingFactor||.2,this.enablePermissionDialog=i.enablePermissionDialog??!0,this.enableInlineStyling=i.enableStyling??!0,this.preferConfirmDialog=i.preferConfirmDialog??!1,this.orientationChangeThreshold=i.orientationChangeThreshold??0;const o=n=>{let{alpha:s,beta:d,gamma:c,webkitCompassHeading:a}=n;if(s=s??0,d=d??0,c=c??0,a=a??0,E){const h=360-a;t.alphaOffset=u.MathUtils.degToRad(h-s),t.deviceOrientation={alpha:s,beta:d,gamma:c,webkitCompassHeading:a}}else s<0&&(s+=360),t.deviceOrientation={alpha:s,beta:d,gamma:c};window.dispatchEvent(new CustomEvent("camera-rotation-change",{detail:{cameraRotation:e.rotation}}))},l=()=>{t.screenOrientation=window.screen.orientation?.angle??0,E&&(t.screenOrientation===90?t.orientationOffset=-I:t.screenOrientation===-90?t.orientationOffset=I:t.orientationOffset=0)},g=(n,s,d,c,a)=>{M.set(d,s,-c,"YXZ"),n.setFromEuler(M),n.multiply(F),n.multiply(W.setFromAxisAngle(H,-a))};this.connect=()=>{l(),window.addEventListener("orientationchange",l),window.addEventListener(t.orientationChangeEventName,o),t.enabled=!0},this.disconnect=()=>{window.removeEventListener("orientationchange",l),window.removeEventListener(t.orientationChangeEventName,o),t.enabled=!1,t.initialOffset=!1,t.deviceOrientation=null,t.lastQuaternion=null},this.requestOrientationPermissions=()=>{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(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=()=>{if(t.enabled===!1)return;const n=t.deviceOrientation;if(n){let s=n.alpha?u.MathUtils.degToRad(n.alpha)+t.alphaOffset:0,d=n.beta?u.MathUtils.degToRad(n.beta):0,c=n.gamma?u.MathUtils.degToRad(n.gamma):0;const a=t.screenOrientation?u.MathUtils.degToRad(t.screenOrientation):0,h=new u.Quaternion;if(E){g(h,s,d,c,a);const v=new u.Euler().setFromQuaternion(h,"YXZ"),O=u.MathUtils.degToRad(360-(n.webkitCompassHeading??0));v.y=O+(t.orientationOffset||0),h.setFromEuler(v)}else g(h,s,d,c,a);if(t.lastQuaternion&&t.orientationChangeThreshold>0&&h.angleTo(t.lastQuaternion)<t.orientationChangeThreshold)return;if(t.smoothingFactor<1&&t.lastQuaternion){const v=1-t.smoothingFactor;t.object.quaternion.slerp(h,v)}else t.object.quaternion.copy(h);t.lastQuaternion=t.object.quaternion.clone(),window.dispatchEvent(new CustomEvent("camera-rotation-change",{detail:{cameraRotation:t.object.rotation}}))}},this.getCorrectedHeading=()=>{const{deviceOrientation:n}=t;if(!n)return 0;let s=0;return E?(s=360-(n.webkitCompassHeading??0),t.orientationOffset&&(s+=t.orientationOffset*(180/Math.PI),s=(s+360)%360)):(n.absolute===!0||t.orientationChangeEventName,s=n.alpha?n.alpha:0,s=(360-s)%360,s<0&&(s+=360)),s},this.updateAlphaOffset=()=>{t.initialOffset=!1},this.dispose=()=>{t.disconnect()},this.getAlpha=()=>{const{deviceOrientation:n}=t;return n&&n.alpha?u.MathUtils.degToRad(n.alpha)+t.alphaOffset:0},this.getBeta=()=>{const{deviceOrientation:n}=t;return n&&n.beta?u.MathUtils.degToRad(n.beta):0},this.getGamma=()=>{const{deviceOrientation:n}=t;return n&&n.gamma?u.MathUtils.degToRad(n.gamma):0},this.createObtainPermissionGestureDialog=()=>{const n=document.createElement("div");n.classList.add(R);const s=document.createElement("div");s.classList.add(S);const d=document.createElement("div");d.classList.add(L);const c=document.createElement("div");c.classList.add(N);const a=document.createElement("button");a.classList.add(x),document.body.appendChild(n),this.enableInlineStyling===!0&&(n.style.fontFamily="-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'",n.style.display="flex",n.style.position="fixed",n.style.zIndex="100000",n.style.justifyContent="center",n.style.alignItems="center",n.style.backgroundColor="rgba(0,0,0,0.2)",n.style.inset="0",n.style.padding="20px",s.style.backgroundColor="rgba(220, 220, 220, 0.85)",s.style.padding="6px 0",s.style.borderRadius="10px",s.style.width="100%",s.style.maxWidth="400px",d.style.padding="10px 12px",d.style.textAlign="center",d.style.fontWeight="400",d.style.fontSize="13px",d.style.display="flex",d.style.justifyContent="center",d.style.alignItems="center",c.style.display="block",c.style.textAlign="center",c.style.textDecoration="none",c.style.borderTop="rgb(180,180,180) solid 1px",a.style.display="block",a.style.width="100%",a.style.textAlign="center",a.style.appearance="none",a.style.background="none",a.style.border="none",a.style.outline="none",a.style.padding="10px",a.style.fontWeight="400",a.style.fontSize="16px",a.style.color="#2e7cf1",a.style.cursor="pointer"),n.appendChild(s),s.appendChild(d),s.appendChild(c),d.appendChild(document.createTextNode(C));const h=()=>{this.requestOrientationPermissions(),n.style.display="none"};a.addEventListener("click",h),a.appendChild(document.createTextNode("OK")),c.appendChild(a),document.body.appendChild(n)},this.obtainPermissionGesture=()=>{this.preferConfirmDialog===!0?window.confirm(C)&&this.requestOrientationPermissions():this.createObtainPermissionGestureDialog()}}on(e,i){this.eventEmitter.on(e,i)}}class j{constructor(e){this.raycaster=new m.Raycaster,this.normalisedMousePosition=null,e.domElement.addEventListener("click",i=>{this.normalisedMousePosition=new m.Vector2(i.clientX/e.domElement.clientWidth*2-1,-(i.clientY/e.domElement.clientHeight*2)+1)})}raycast(e,i){if(this.normalisedMousePosition!==null){this.raycaster.setFromCamera(this.normalisedMousePosition,e);const t=this.raycaster.intersectObjects(i.children,!1);return this.normalisedMousePosition=null,t}return[]}}class D extends w{#e;constructor(e={video:{facingMode:"environment"}},i){super(),this.sceneWebcam=new m.Scene,i?this.#e=document.querySelector(i):(this.#e=document.createElement("video"),this.#e.setAttribute("autoplay","true"),this.#e.setAttribute("playsinline","true"),this.#e.style.cssText+=`
|
|
2
2
|
width: 100%;
|
|
3
3
|
height: 100%;
|
|
4
4
|
object-fit: cover;
|
|
@@ -7,4 +7,4 @@
|
|
|
7
7
|
top: 0px;
|
|
8
8
|
left: 0px;
|
|
9
9
|
z-index: -100;
|
|
10
|
-
`,document.body.appendChild(this.#e)),navigator.mediaDevices&&navigator.mediaDevices.getUserMedia?navigator.mediaDevices.getUserMedia(e).then(t=>{this.#e?.addEventListener("loadedmetadata",()=>{this.#e.play(),this.emit("webcamstarted",{videoWidth:this.#e.videoWidth,videoHeight:this.#e.videoHeight})}),this.#e&&(this.#e.srcObject=t)}).catch(t=>{this.emit("webcamerror",{code:t.name,message:t.message})}):this.emit("webcamerror",{code:"LOCAR_NO_MEDIA_DEVICES_API",message:"Media devices API not supported"})}getVideoDimensions(){return`w ${this.#e.videoWidth}, h ${this.#e.videoHeight}`}}
|
|
10
|
+
`,document.body.appendChild(this.#e)),navigator.mediaDevices&&navigator.mediaDevices.getUserMedia?navigator.mediaDevices.getUserMedia(e).then(t=>{this.#e?.addEventListener("loadedmetadata",()=>{this.#e.play(),this.emit("webcamstarted",{videoWidth:this.#e.videoWidth,videoHeight:this.#e.videoHeight})}),this.#e&&(this.#e.srcObject=t)}).catch(t=>{this.emit("webcamerror",{code:t.name,message:t.message})}):this.emit("webcamerror",{code:"LOCAR_NO_MEDIA_DEVICES_API",message:"Media devices API not supported"})}getVideoDimensions(){return`w ${this.#e.videoWidth}, h ${this.#e.videoHeight}`}}p.App=T,p.ClickHandler=j,p.DeviceOrientationControls=A,p.EventEmitter=w,p.LocAR=y,p.SphMercProjection=b,p.Webcam=D,Object.defineProperty(p,Symbol.toStringTag,{value:"Module"})}));
|