itowns 2.43.2-next.25 → 2.43.2-next.26
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/debug.js +1 -1
- package/dist/debug.js.map +1 -1
- package/dist/itowns.js +1 -1
- package/dist/itowns.js.map +1 -1
- package/dist/itowns_widgets.js +1 -1
- package/examples/3dtiles_loader.html +150 -0
- package/examples/config.json +4 -0
- package/examples/jsm/.eslintrc.cjs +38 -0
- package/examples/jsm/OGC3DTilesHelper.js +105 -0
- package/examples/misc_instancing.html +2 -1
- package/lib/Core/View.js +3 -0
- package/lib/Layer/C3DTilesLayer.js +1 -1
- package/lib/Layer/OGC3DTilesLayer.js +386 -0
- package/lib/Main.js +6 -1
- package/lib/Parser/B3dmParser.js +11 -22
- package/lib/Parser/deprecated/LegacyGLTFLoader.js +25 -5
- package/lib/Parser/iGLTFLoader.js +169 -0
- package/lib/Provider/3dTilesProvider.js +4 -2
- package/lib/Renderer/PointsMaterial.js +5 -1
- package/lib/Source/OGC3DTilesGoogleSource.js +32 -0
- package/lib/Source/OGC3DTilesIonSource.js +37 -0
- package/lib/Source/OGC3DTilesSource.js +24 -0
- package/package.json +4 -3
- package/lib/Parser/GLTFParser.js +0 -88
package/dist/itowns_widgets.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("itowns_widgets",[],e):"object"==typeof exports?exports.itowns_widgets=e():t.itowns_widgets=e()}(self,(()=>(self.webpackChunkitowns=self.webpackChunkitowns||[]).push([[605],{12587:(t,e,o)=>{o.r(e),o.d(e,{C3DTilesStyle:()=>I,Minimap:()=>f,Navigation:()=>c,Scale:()=>y,Searchbar:()=>T,Widget:()=>n});var i=o(59432);const n=class{#t;constructor(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},o=arguments.length>2?arguments[2]:void 0;this.parentElement=e.parentElement||t.domElement,this.position=e.position||o.position,["top-left","top-right","bottom-left","bottom-right","top","bottom","left","right"].includes(this.position)||(console.warn(`'position' optional parameter for 'Widget' constructor is not a valid option. It will be set to '${o.position}'.`),this.position=o.position),this.domElement=document.createElement("div"),this.parentElement.appendChild(this.domElement),this.domElement.style.width=`${e.width||e.size||o.width}px`,this.domElement.style.height=`${e.height||e.size||o.height}px`;const i=this.position.split("-");if(this.domElement.classList.add(`${i[0]}-widget`),i[1])this.domElement.classList.add(`${i[1]}-widget`);else switch(i[0]){case"top":case"bottom":this.domElement.style.left=`calc(50% - ${this.domElement.offsetWidth/2}px)`;break;case"left":case"right":this.domElement.style.top=`calc(50% - ${this.domElement.offsetHeight/2}px)`}e.translate&&(this.domElement.style.transform=`translate(${e.translate.x||0}px, ${e.translate.y||0}px)`),this.domElement.addEventListener("pointerdown",(t=>{t.stopPropagation()})),this.domElement.addEventListener("mousedown",(t=>{t.stopPropagation()}))}show(){this.domElement.style.display=this.#t}hide(){this.#t=window.getComputedStyle(this.domElement).display,this.domElement.style.display="none"}},s={displayCompass:!0,display3DToggle:!0,displayZoomIn:!0,displayZoomOut:!0,animationDuration:500,position:"bottom-left",direction:"column"},a={id:"compass",content:"",info:"Rotate the camera to face North",parentId:"widgets"},l={id:"3d-button",content:"3D",info:"Tilt the camera"},r={id:"zoom-in-button",content:'<span class="widget-zoom-button-logo"></span>',info:"Zoom in",parentId:"zoom-button-bar"},d={id:"zoom-out-button",content:'<span id="zoom-out-logo" class="widget-zoom-button-logo"></span>',info:"Zoom out",parentId:"zoom-button-bar"},c=class extends n{#e;#o(t){return t.time=this.animationDuration,this.#e.controls.lookAtCoordinate(t)}#i(t,e){return this.addButton(t.id,t.content,t.info,e,t.parentId)}constructor(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!t.isGlobeView)throw new Error("'Navigation' plugin only supports 'GlobeView'. Therefore, the 'view' parameter must be a 'GlobeView'.");["top","bottom","left","right"].includes(e.position)&&(console.warn(`'position' optional parameter for 'Navigation' is not a valid option. It will be set to '${s.position}'.`),e.position=s.position),super(t,e,s),this.#e=t,this.direction=e.direction||s.direction,["column","row"].includes(this.direction)||(console.warn(`'direction' optional parameter for 'Navigation' constructor is not a valid option. It will be set to '${s.direction}'.`),this.direction=s.direction),this.animationDuration=void 0===e.animationDuration?s.animationDuration:e.animationDuration,this.domElement.id="widgets-navigation",this.domElement.classList.add(`${this.direction}-widget`),(e.displayCompass??s.displayCompass)&&(this.compass=this.#i(a,(()=>{this.#o({heading:0,tilt:89.5})})),t.addEventListener(i.G.CAMERA_MOVED,(t=>{this.compass.style.transform=`rotate(${-t.heading}deg)`}))),(e.display3DToggle??s.display3DToggle)&&(this.toggle3D=this.#i(l,(()=>{this.#o({tilt:this.#e.controls.getTilt()<89?89.5:40})})),t.addEventListener(i.G.CAMERA_MOVED,(t=>{this.toggle3D.innerHTML=t.tilt<89?"2D":"3D"}))),(e.displayZoomIn??s.displayZoomIn)&&(this.zoomIn=this.#i(r,(()=>{this.#o({zoom:Math.min(20,this.#e.controls.getZoom()+1)})}))),(e.displayZoomOut??s.displayZoomOut)&&(this.zoomOut=this.#i(d,(()=>{this.#o({zoom:Math.max(3,this.#e.controls.getZoom()-1)})})))}addButton(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"",i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:()=>{},n=arguments.length>4?arguments[4]:void 0,s=document.getElementById(n);s||(s=this.addButtonBar(n));const a=document.createElement("button");return a.className="widget-button",a.id=t,a.innerHTML=e,a.title=o,a.onclick=i,s.appendChild(a),a.tabIndex=-1,window.addEventListener("pointerup",(()=>{document.activeElement===a&&this.#e.domElement.focus()})),a}addButtonBar(t){const e=document.createElement("div");return e.className="widget-button-bar",t&&(e.id=t),this.domElement.appendChild(e),e}};var m=o(52404),h=o(87196),p=o(8917),u=o(93320);const g={minScale:2e-6,maxScale:2e-9,zoomRatio:1/30,width:150,height:150,position:"bottom-left"},f=class extends n{constructor(t,e){let o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(!t.isGlobeView)throw new Error("'Minimap' plugin only supports 'GlobeView'. Therefore, the 'view' parameter must be a 'GlobeView'.");if(!e.isColorLayer)throw new Error("'layer' parameter form 'Minimap' constructor should be a 'ColorLayer'.");if(super(t,o,g),this.minScale=o.minScale||g.minScale,this.maxScale=o.maxScale||g.maxScale,this.zoomRatio=o.zoomRatio||g.zoomRatio,this.domElement.id="widgets-minimap",o.cursor){const t=document.createElement("div");t.id="cursor-wrapper",this.domElement.appendChild(t),"string"==typeof o.cursor?t.innerHTML=o.cursor:o.cursor instanceof HTMLElement&&t.appendChild(o.cursor)}this.view=new p.A(this.domElement,e.source.extent,{camera:{type:u.d.ORTHOGRAPHIC},placement:e.source.extent,noControls:!0,maxSubdivisionLevel:t.tileLayer.maxSubdivisionLevel,disableFocusOnStart:!0}),this.view.addLayer(e),this.domElement.addEventListener("pointerdown",(t=>{t.preventDefault()}));const i=this.view.getScale(o.pitch),n=this.view.camera3D.zoom*this.maxScale/i,s=this.view.camera3D.zoom*this.minScale/i,a=new m.A(t.referenceCrs),l=new m.A(this.view.referenceCrs),r=t.controls.getCameraTargetPosition();t.addFrameRequester(h.n7.AFTER_RENDER,(()=>{const e=t.camera3D.position.distanceTo(r),i=t.getScaleFromDistance(o.pitch,e);this.view.camera3D.zoom=this.zoomRatio*s*i/this.minScale,this.view.camera3D.zoom=Math.min(Math.max(this.view.camera3D.zoom,n),s),this.view.camera3D.updateProjectionMatrix(),a.setFromVector3(t.controls.getCameraTargetPosition()),a.as(this.view.referenceCrs,l),this.view.camera3D.position.x=l.x,this.view.camera3D.position.y=l.y,this.view.camera3D.updateMatrixWorld(!0),this.view.notifyChange(this.view.camera3D)}))}};var w=o(98211),v=o(86397),E=o(72682);const b={width:200,height:30,position:"bottom-left"},y=class extends n{constructor(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};super(t,e,b),this.domElement.id="widgets-scale",this.view=t,this.domElement.innerHTML="Scale",this.width=e.width||b.width,this.view.isGlobeView?(this.view.addEventListener(v.S.GLOBE_INITIALIZED,(()=>{this.update()})),this.view.controls.addEventListener(w.W.RANGE_CHANGED,(()=>{this.update()}))):this.view.isPlanarView?(this.view.addEventListener(i.G.INITIALIZED,(()=>{this.update()})),this.view.addEventListener(E.w7.MOVED,(()=>{this.update()}))):console.warn("The 'view' linked to scale widget is neither a 'GlobeView' nor a 'PlanarView'. The scale wont automatically update. You can implement its update automation using 'Scale.update' method.")}addEventListeners(){}update(){let t=Math.round(this.view.getPixelsToMeters(this.width));const e=10**(t.toString().length-1);t=Math.round(t/e)*e;const o=this.view.getMetersToPixels(t);let i="m";t>=1e3&&(t/=1e3,i="km"),this.domElement.innerHTML=`${t} ${i}`,this.domElement.style.width=`${o}px`}};var C=o(7794);const x={width:300,height:38,position:"top",maxSuggestionNumber:10,fontSize:16,placeholder:"Search location"};function L(t,e){return t?(D(t),e>=t.length?e=0:e<0&&(e=t.length-1),t[e]?.classList.add("active"),e):e}function D(t){for(let e=0;e<t.length;e++)t[e].classList.remove("active")}function S(t){for(;t.children.length>1;)t.removeChild(t.lastChild)}const T=class extends n{#n;constructor(t,e){let o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(super(t,o,x),!e||!e.url||!e.parser||"function"!=typeof e.parser)throw new Error("'geocodingOptions' parameter for 'Searchbar' constructor is not a valid option. Please refer to the documentation.");this.#n=e.onSelected??(()=>{}),this.domElement.id="widgets-searchbar",this.domElement.style.height="auto";const i=document.createElement("form");i.setAttribute("autocomplete","off"),i.id="searchbar-autocompletion-form",this.domElement.appendChild(i);const n=document.createElement("input");let s;n.setAttribute("type","text"),n.setAttribute("name","mySearch"),n.setAttribute("placeholder",o.placeholder||x.placeholder),n.style.height=`${o.height||o.size||x.height}px`,n.style.fontSize=`${o.fontSize||x.fontSize}px`,i.appendChild(n),n.addEventListener("input",(()=>{const t=n.value;if(S(i),s=-1,!t)return!1;e.url.searchParams.set("text",t),C.A.json(e.url).then((a=>{const l=e.parser(a);let r=0;l.forEach(((e,a)=>{if(r===Math.min(l.size,o.maxSuggestionNumber||x.maxSuggestionNumber))return;const d=r;r++;const c=a.toUpperCase().indexOf(t.toUpperCase());if(c>-1){const l=document.createElement("div");l.style.minHeight=n.style.height,l.style.fontSize=`${o.fontSize||x.fontSize}px`;const r=a.slice(0,c),m=a.slice(c,c+t.length),h=a.slice(c+t.length,a.length);l.innerHTML=`<p>${r}<strong>${m}</strong>${h}</p>`,l.setAttribute("location",a),i.appendChild(l),l.addEventListener("mouseover",(()=>{D(i.children),s=d,l.classList.add("active")})),l.addEventListener("click",(()=>{this.#n(e),n.value=l.getAttribute("location"),S(i)}))}}))}))}));const a=(o.position||x.position).includes("top")?1:-1;n.addEventListener("keydown",(e=>{e.stopPropagation();const o=i.getElementsByTagName("div");switch(e.code){case"Escape":S(i),n.value="",t.domElement.focus();break;case"ArrowDown":e.preventDefault(),s=L(o,s+a);break;case"ArrowUp":e.preventDefault(),s=L(o,s-a);break;case"Enter":e.preventDefault(),o[Math.max(s,0)]&&(o[Math.max(s,0)].click(),t.domElement.focus())}})),n.addEventListener("focus",(()=>{i.classList.add("focus")})),n.addEventListener("blur",(()=>{i.classList.remove("focus"),D(i.children)})),i.addEventListener("mouseleave",(()=>{D(i.children),s=-1}))}};var _=o(48306),M=o(14333);const z={width:200,position:"top-right"};class A extends n{constructor(t,e){super(t,e,z),this.domElement.onclick=t=>t.stopImmediatePropagation();const o=document.createElement("select");this.domElement.appendChild(o);const i=new Map,n=()=>{for(const[t,e]of i)e.hidden=t!==o.selectedOptions[0]};o.onchange=n,t.getLayers().filter((t=>!0===t.isC3DTilesLayer)).forEach((e=>{const n=document.createElement("option");n.innerText=e.name,o.add(n);const s=document.createElement("div");this.domElement.appendChild(s),i.set(n,s),e.addEventListener(M.s.ON_TILE_CONTENT_LOADED,(()=>{for(;s.firstChild;)s.firstChild.remove();const o=new Map;for(const[,t]of e.tilesC3DTileFeatures)for(const[,e]of t)for(const t in e.getInfo().batchTable){o.has(t)||o.set(t,[]);const i=e.getInfo().batchTable[t];o.get(t).includes(i)||o.get(t).push(i)}const i=new Map,n=new Map,a=(o,a,l)=>{const r=document.createElement("input");r.setAttribute("type","color"),s.appendChild(r),r.onchange=()=>{const n=o();if(!l.includes(n))return;const s=r.value;i.set(n,(t=>t.getInfo().batchTable[a]==n?s:null)),e.updateStyle(),t.notifyChange()};const d=document.createElement("input");return d.setAttribute("type","range"),d.min=0,d.max=1,d.step=.1,d.value=1,s.appendChild(d),d.onchange=()=>{const i=o();if(!l.includes(i))return;const s=d.value;n.set(i,(t=>t.getInfo().batchTable[a]==i?s:null)),e.updateStyle(),t.notifyChange()},{inputColor:r,opacityElement:d}},l=(t,e)=>{const o=document.createElement("label");o.innerText=t,s.appendChild(o);const i=document.createElement("select");s.appendChild(i),e.forEach((t=>{const e=document.createElement("option");e.value=t,e.text=t,i.add(e)})),a((()=>i.selectedOptions[0].value),t,e)},r=(o,l)=>{const r=document.createElement("label");r.innerText=o,s.appendChild(r);const d=document.createElement("input");d.setAttribute("type","text"),s.appendChild(d);const{inputColor:c,opacityElement:m}=a((()=>d.value),o,l);d.onchange=()=>{if(!l.includes(d.value))return;const s=c.value,a=d.value;i.set(a,(t=>t.getInfo().batchTable[o]==a?s:null));const r=m.value;n.set(a,(t=>t.getInfo().batchTable[o]==a?r:null)),e.updateStyle(),t.notifyChange()}};for(const[t,e]of o)e.length<A.MAX_SELECT_VALUE?l(t,e):r(t,e);e.style=new _.Ay({fill:{color:t=>{let e=null;for(const[,o]of i)e=o(t)||e;return e},opacity:t=>{let e=1;for(const[,o]of n)e=o(t)||e;return e}}})}))})),n()}static get MAX_SELECT_VALUE(){return 10}}const I=A}},t=>t(t.s=12587)])));
|
|
1
|
+
"use strict";!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("itowns_widgets",[],e):"object"==typeof exports?exports.itowns_widgets=e():t.itowns_widgets=e()}(self,(()=>(self.webpackChunkitowns=self.webpackChunkitowns||[]).push([[605],{12587:(t,e,o)=>{o.r(e),o.d(e,{C3DTilesStyle:()=>I,Minimap:()=>f,Navigation:()=>c,Scale:()=>y,Searchbar:()=>T,Widget:()=>n});var i=o(84354);const n=class{#t;constructor(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},o=arguments.length>2?arguments[2]:void 0;this.parentElement=e.parentElement||t.domElement,this.position=e.position||o.position,["top-left","top-right","bottom-left","bottom-right","top","bottom","left","right"].includes(this.position)||(console.warn(`'position' optional parameter for 'Widget' constructor is not a valid option. It will be set to '${o.position}'.`),this.position=o.position),this.domElement=document.createElement("div"),this.parentElement.appendChild(this.domElement),this.domElement.style.width=`${e.width||e.size||o.width}px`,this.domElement.style.height=`${e.height||e.size||o.height}px`;const i=this.position.split("-");if(this.domElement.classList.add(`${i[0]}-widget`),i[1])this.domElement.classList.add(`${i[1]}-widget`);else switch(i[0]){case"top":case"bottom":this.domElement.style.left=`calc(50% - ${this.domElement.offsetWidth/2}px)`;break;case"left":case"right":this.domElement.style.top=`calc(50% - ${this.domElement.offsetHeight/2}px)`}e.translate&&(this.domElement.style.transform=`translate(${e.translate.x||0}px, ${e.translate.y||0}px)`),this.domElement.addEventListener("pointerdown",(t=>{t.stopPropagation()})),this.domElement.addEventListener("mousedown",(t=>{t.stopPropagation()}))}show(){this.domElement.style.display=this.#t}hide(){this.#t=window.getComputedStyle(this.domElement).display,this.domElement.style.display="none"}},s={displayCompass:!0,display3DToggle:!0,displayZoomIn:!0,displayZoomOut:!0,animationDuration:500,position:"bottom-left",direction:"column"},a={id:"compass",content:"",info:"Rotate the camera to face North",parentId:"widgets"},l={id:"3d-button",content:"3D",info:"Tilt the camera"},r={id:"zoom-in-button",content:'<span class="widget-zoom-button-logo"></span>',info:"Zoom in",parentId:"zoom-button-bar"},d={id:"zoom-out-button",content:'<span id="zoom-out-logo" class="widget-zoom-button-logo"></span>',info:"Zoom out",parentId:"zoom-button-bar"},c=class extends n{#e;#o(t){return t.time=this.animationDuration,this.#e.controls.lookAtCoordinate(t)}#i(t,e){return this.addButton(t.id,t.content,t.info,e,t.parentId)}constructor(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!t.isGlobeView)throw new Error("'Navigation' plugin only supports 'GlobeView'. Therefore, the 'view' parameter must be a 'GlobeView'.");["top","bottom","left","right"].includes(e.position)&&(console.warn(`'position' optional parameter for 'Navigation' is not a valid option. It will be set to '${s.position}'.`),e.position=s.position),super(t,e,s),this.#e=t,this.direction=e.direction||s.direction,["column","row"].includes(this.direction)||(console.warn(`'direction' optional parameter for 'Navigation' constructor is not a valid option. It will be set to '${s.direction}'.`),this.direction=s.direction),this.animationDuration=void 0===e.animationDuration?s.animationDuration:e.animationDuration,this.domElement.id="widgets-navigation",this.domElement.classList.add(`${this.direction}-widget`),(e.displayCompass??s.displayCompass)&&(this.compass=this.#i(a,(()=>{this.#o({heading:0,tilt:89.5})})),t.addEventListener(i.G.CAMERA_MOVED,(t=>{this.compass.style.transform=`rotate(${-t.heading}deg)`}))),(e.display3DToggle??s.display3DToggle)&&(this.toggle3D=this.#i(l,(()=>{this.#o({tilt:this.#e.controls.getTilt()<89?89.5:40})})),t.addEventListener(i.G.CAMERA_MOVED,(t=>{this.toggle3D.innerHTML=t.tilt<89?"2D":"3D"}))),(e.displayZoomIn??s.displayZoomIn)&&(this.zoomIn=this.#i(r,(()=>{this.#o({zoom:Math.min(20,this.#e.controls.getZoom()+1)})}))),(e.displayZoomOut??s.displayZoomOut)&&(this.zoomOut=this.#i(d,(()=>{this.#o({zoom:Math.max(3,this.#e.controls.getZoom()-1)})})))}addButton(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"",i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:()=>{},n=arguments.length>4?arguments[4]:void 0,s=document.getElementById(n);s||(s=this.addButtonBar(n));const a=document.createElement("button");return a.className="widget-button",a.id=t,a.innerHTML=e,a.title=o,a.onclick=i,s.appendChild(a),a.tabIndex=-1,window.addEventListener("pointerup",(()=>{document.activeElement===a&&this.#e.domElement.focus()})),a}addButtonBar(t){const e=document.createElement("div");return e.className="widget-button-bar",t&&(e.id=t),this.domElement.appendChild(e),e}};var m=o(52404),h=o(87196),p=o(8917),u=o(93320);const g={minScale:2e-6,maxScale:2e-9,zoomRatio:1/30,width:150,height:150,position:"bottom-left"},f=class extends n{constructor(t,e){let o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(!t.isGlobeView)throw new Error("'Minimap' plugin only supports 'GlobeView'. Therefore, the 'view' parameter must be a 'GlobeView'.");if(!e.isColorLayer)throw new Error("'layer' parameter form 'Minimap' constructor should be a 'ColorLayer'.");if(super(t,o,g),this.minScale=o.minScale||g.minScale,this.maxScale=o.maxScale||g.maxScale,this.zoomRatio=o.zoomRatio||g.zoomRatio,this.domElement.id="widgets-minimap",o.cursor){const t=document.createElement("div");t.id="cursor-wrapper",this.domElement.appendChild(t),"string"==typeof o.cursor?t.innerHTML=o.cursor:o.cursor instanceof HTMLElement&&t.appendChild(o.cursor)}this.view=new p.A(this.domElement,e.source.extent,{camera:{type:u.d.ORTHOGRAPHIC},placement:e.source.extent,noControls:!0,maxSubdivisionLevel:t.tileLayer.maxSubdivisionLevel,disableFocusOnStart:!0}),this.view.addLayer(e),this.domElement.addEventListener("pointerdown",(t=>{t.preventDefault()}));const i=this.view.getScale(o.pitch),n=this.view.camera3D.zoom*this.maxScale/i,s=this.view.camera3D.zoom*this.minScale/i,a=new m.A(t.referenceCrs),l=new m.A(this.view.referenceCrs),r=t.controls.getCameraTargetPosition();t.addFrameRequester(h.n7.AFTER_RENDER,(()=>{const e=t.camera3D.position.distanceTo(r),i=t.getScaleFromDistance(o.pitch,e);this.view.camera3D.zoom=this.zoomRatio*s*i/this.minScale,this.view.camera3D.zoom=Math.min(Math.max(this.view.camera3D.zoom,n),s),this.view.camera3D.updateProjectionMatrix(),a.setFromVector3(t.controls.getCameraTargetPosition()),a.as(this.view.referenceCrs,l),this.view.camera3D.position.x=l.x,this.view.camera3D.position.y=l.y,this.view.camera3D.updateMatrixWorld(!0),this.view.notifyChange(this.view.camera3D)}))}};var w=o(98211),v=o(86397),E=o(72682);const b={width:200,height:30,position:"bottom-left"},y=class extends n{constructor(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};super(t,e,b),this.domElement.id="widgets-scale",this.view=t,this.domElement.innerHTML="Scale",this.width=e.width||b.width,this.view.isGlobeView?(this.view.addEventListener(v.S.GLOBE_INITIALIZED,(()=>{this.update()})),this.view.controls.addEventListener(w.W.RANGE_CHANGED,(()=>{this.update()}))):this.view.isPlanarView?(this.view.addEventListener(i.G.INITIALIZED,(()=>{this.update()})),this.view.addEventListener(E.w7.MOVED,(()=>{this.update()}))):console.warn("The 'view' linked to scale widget is neither a 'GlobeView' nor a 'PlanarView'. The scale wont automatically update. You can implement its update automation using 'Scale.update' method.")}addEventListeners(){}update(){let t=Math.round(this.view.getPixelsToMeters(this.width));const e=10**(t.toString().length-1);t=Math.round(t/e)*e;const o=this.view.getMetersToPixels(t);let i="m";t>=1e3&&(t/=1e3,i="km"),this.domElement.innerHTML=`${t} ${i}`,this.domElement.style.width=`${o}px`}};var C=o(7794);const x={width:300,height:38,position:"top",maxSuggestionNumber:10,fontSize:16,placeholder:"Search location"};function L(t,e){return t?(D(t),e>=t.length?e=0:e<0&&(e=t.length-1),t[e]?.classList.add("active"),e):e}function D(t){for(let e=0;e<t.length;e++)t[e].classList.remove("active")}function S(t){for(;t.children.length>1;)t.removeChild(t.lastChild)}const T=class extends n{#n;constructor(t,e){let o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(super(t,o,x),!e||!e.url||!e.parser||"function"!=typeof e.parser)throw new Error("'geocodingOptions' parameter for 'Searchbar' constructor is not a valid option. Please refer to the documentation.");this.#n=e.onSelected??(()=>{}),this.domElement.id="widgets-searchbar",this.domElement.style.height="auto";const i=document.createElement("form");i.setAttribute("autocomplete","off"),i.id="searchbar-autocompletion-form",this.domElement.appendChild(i);const n=document.createElement("input");let s;n.setAttribute("type","text"),n.setAttribute("name","mySearch"),n.setAttribute("placeholder",o.placeholder||x.placeholder),n.style.height=`${o.height||o.size||x.height}px`,n.style.fontSize=`${o.fontSize||x.fontSize}px`,i.appendChild(n),n.addEventListener("input",(()=>{const t=n.value;if(S(i),s=-1,!t)return!1;e.url.searchParams.set("text",t),C.A.json(e.url).then((a=>{const l=e.parser(a);let r=0;l.forEach(((e,a)=>{if(r===Math.min(l.size,o.maxSuggestionNumber||x.maxSuggestionNumber))return;const d=r;r++;const c=a.toUpperCase().indexOf(t.toUpperCase());if(c>-1){const l=document.createElement("div");l.style.minHeight=n.style.height,l.style.fontSize=`${o.fontSize||x.fontSize}px`;const r=a.slice(0,c),m=a.slice(c,c+t.length),h=a.slice(c+t.length,a.length);l.innerHTML=`<p>${r}<strong>${m}</strong>${h}</p>`,l.setAttribute("location",a),i.appendChild(l),l.addEventListener("mouseover",(()=>{D(i.children),s=d,l.classList.add("active")})),l.addEventListener("click",(()=>{this.#n(e),n.value=l.getAttribute("location"),S(i)}))}}))}))}));const a=(o.position||x.position).includes("top")?1:-1;n.addEventListener("keydown",(e=>{e.stopPropagation();const o=i.getElementsByTagName("div");switch(e.code){case"Escape":S(i),n.value="",t.domElement.focus();break;case"ArrowDown":e.preventDefault(),s=L(o,s+a);break;case"ArrowUp":e.preventDefault(),s=L(o,s-a);break;case"Enter":e.preventDefault(),o[Math.max(s,0)]&&(o[Math.max(s,0)].click(),t.domElement.focus())}})),n.addEventListener("focus",(()=>{i.classList.add("focus")})),n.addEventListener("blur",(()=>{i.classList.remove("focus"),D(i.children)})),i.addEventListener("mouseleave",(()=>{D(i.children),s=-1}))}};var _=o(48306),M=o(14333);const z={width:200,position:"top-right"};class A extends n{constructor(t,e){super(t,e,z),this.domElement.onclick=t=>t.stopImmediatePropagation();const o=document.createElement("select");this.domElement.appendChild(o);const i=new Map,n=()=>{for(const[t,e]of i)e.hidden=t!==o.selectedOptions[0]};o.onchange=n,t.getLayers().filter((t=>!0===t.isC3DTilesLayer)).forEach((e=>{const n=document.createElement("option");n.innerText=e.name,o.add(n);const s=document.createElement("div");this.domElement.appendChild(s),i.set(n,s),e.addEventListener(M.s.ON_TILE_CONTENT_LOADED,(()=>{for(;s.firstChild;)s.firstChild.remove();const o=new Map;for(const[,t]of e.tilesC3DTileFeatures)for(const[,e]of t)for(const t in e.getInfo().batchTable){o.has(t)||o.set(t,[]);const i=e.getInfo().batchTable[t];o.get(t).includes(i)||o.get(t).push(i)}const i=new Map,n=new Map,a=(o,a,l)=>{const r=document.createElement("input");r.setAttribute("type","color"),s.appendChild(r),r.onchange=()=>{const n=o();if(!l.includes(n))return;const s=r.value;i.set(n,(t=>t.getInfo().batchTable[a]==n?s:null)),e.updateStyle(),t.notifyChange()};const d=document.createElement("input");return d.setAttribute("type","range"),d.min=0,d.max=1,d.step=.1,d.value=1,s.appendChild(d),d.onchange=()=>{const i=o();if(!l.includes(i))return;const s=d.value;n.set(i,(t=>t.getInfo().batchTable[a]==i?s:null)),e.updateStyle(),t.notifyChange()},{inputColor:r,opacityElement:d}},l=(t,e)=>{const o=document.createElement("label");o.innerText=t,s.appendChild(o);const i=document.createElement("select");s.appendChild(i),e.forEach((t=>{const e=document.createElement("option");e.value=t,e.text=t,i.add(e)})),a((()=>i.selectedOptions[0].value),t,e)},r=(o,l)=>{const r=document.createElement("label");r.innerText=o,s.appendChild(r);const d=document.createElement("input");d.setAttribute("type","text"),s.appendChild(d);const{inputColor:c,opacityElement:m}=a((()=>d.value),o,l);d.onchange=()=>{if(!l.includes(d.value))return;const s=c.value,a=d.value;i.set(a,(t=>t.getInfo().batchTable[o]==a?s:null));const r=m.value;n.set(a,(t=>t.getInfo().batchTable[o]==a?r:null)),e.updateStyle(),t.notifyChange()}};for(const[t,e]of o)e.length<A.MAX_SELECT_VALUE?l(t,e):r(t,e);e.style=new _.Ay({fill:{color:t=>{let e=null;for(const[,o]of i)e=o(t)||e;return e},opacity:t=>{let e=1;for(const[,o]of n)e=o(t)||e;return e}}})}))})),n()}static get MAX_SELECT_VALUE(){return 10}}const I=A}},t=>t(t.s=12587)])));
|
|
2
2
|
//# sourceMappingURL=itowns_widgets.js.map
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
<html>
|
|
2
|
+
<head>
|
|
3
|
+
<title>Itowns - 3D Tiles loader</title>
|
|
4
|
+
|
|
5
|
+
<meta charset="UTF-8">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
+
|
|
8
|
+
<link rel="stylesheet" type="text/css" href="css/example.css">
|
|
9
|
+
<link rel="stylesheet" type="text/css" href="css/LoadingScreen.css">
|
|
10
|
+
|
|
11
|
+
<style type="text/css">
|
|
12
|
+
#description {
|
|
13
|
+
z-index: 2;
|
|
14
|
+
right: 10px;
|
|
15
|
+
}
|
|
16
|
+
</style>
|
|
17
|
+
|
|
18
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.6/dat.gui.min.js"></script>
|
|
19
|
+
</head>
|
|
20
|
+
<body>
|
|
21
|
+
<div id="viewerDiv"></div>
|
|
22
|
+
<div id="description">Specify the URL of a tileset to load:
|
|
23
|
+
<input type="text" id="url" />
|
|
24
|
+
<button onclick="setURL(document.getElementById('url').value)">
|
|
25
|
+
Load
|
|
26
|
+
</button>
|
|
27
|
+
<hr />
|
|
28
|
+
<p><b>Feature Information:</b></p>
|
|
29
|
+
<div id="featureInfo"></div>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<script src="js/GUI/GuiTools.js"></script>
|
|
33
|
+
<script src="../dist/itowns.js"></script>
|
|
34
|
+
<script src="js/GUI/LoadingScreen.js"></script>
|
|
35
|
+
<script src="../dist/debug.js"></script>
|
|
36
|
+
|
|
37
|
+
<script type="importmap">
|
|
38
|
+
{
|
|
39
|
+
"imports": {
|
|
40
|
+
"three": "https://cdn.jsdelivr.net/npm/three@0.165.0/build/three.module.js",
|
|
41
|
+
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.165.0/examples/jsm/"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<script type="module">
|
|
47
|
+
import { AmbientLight } from 'three';
|
|
48
|
+
import {
|
|
49
|
+
zoomToLayer,
|
|
50
|
+
fillHTMLWithPickingInfo,
|
|
51
|
+
} from './jsm/OGC3DTilesHelper.js';
|
|
52
|
+
|
|
53
|
+
const {
|
|
54
|
+
TMSSource, WMTSSource, OGC3DTilesSource,
|
|
55
|
+
ColorLayer, ElevationLayer, OGC3DTilesLayer,
|
|
56
|
+
GlobeView, Coordinates, Fetcher,
|
|
57
|
+
} = itowns;
|
|
58
|
+
|
|
59
|
+
const uri = new URL(location);
|
|
60
|
+
const state = {
|
|
61
|
+
// URL to tileset JSON
|
|
62
|
+
tileset: uri.searchParams.get('tileset'),
|
|
63
|
+
// Cesium ION /
|
|
64
|
+
assetId: uri.searchParams.get('assetId'),
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
function setURL(url) {
|
|
68
|
+
if (!url) return;
|
|
69
|
+
|
|
70
|
+
uri.searchParams.set('tileset', url);
|
|
71
|
+
history.pushState(null, '', `?${uri.searchParams.toString()}`);
|
|
72
|
+
|
|
73
|
+
location.reload();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ---- CREATE A GlobeView FOR SUPPORTING DATA VISUALIZATION ----
|
|
77
|
+
|
|
78
|
+
// Define camera initial position
|
|
79
|
+
const placement = {
|
|
80
|
+
coord: new Coordinates('EPSG:4326', 2.351323, 48.856712),
|
|
81
|
+
range: 12500000,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// `viewerDiv` will contain iTowns' rendering area (`<canvas>`)
|
|
85
|
+
const viewerDiv = document.getElementById('viewerDiv');
|
|
86
|
+
|
|
87
|
+
// Create a GlobeView
|
|
88
|
+
const view = new GlobeView(viewerDiv, placement, {});
|
|
89
|
+
|
|
90
|
+
// Add ambient light to globally illuminates all objects
|
|
91
|
+
const light = new AmbientLight(0x404040, 15);
|
|
92
|
+
view.scene.add(light);
|
|
93
|
+
|
|
94
|
+
// Setup loading screen
|
|
95
|
+
setupLoadingScreen(viewerDiv, view);
|
|
96
|
+
|
|
97
|
+
// Setup debug menu
|
|
98
|
+
const menuGlobe = new GuiTools('menuDiv', view, 300);
|
|
99
|
+
debug.createTileDebugUI(menuGlobe.gui, view, view.tileLayer);
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
// ---- ADD A BASEMAP ----
|
|
103
|
+
|
|
104
|
+
// Add one imagery layer to the scene. This layer's properties are
|
|
105
|
+
// defined in a json file, but it cou ld be defined as a plain js
|
|
106
|
+
// object. See `Layer` documentation for more info.
|
|
107
|
+
Fetcher.json('./layers/JSONLayers/OPENSM.json').then((config) => {
|
|
108
|
+
const layer = new ColorLayer('Ortho', {
|
|
109
|
+
...config,
|
|
110
|
+
source: new TMSSource(config.source),
|
|
111
|
+
});
|
|
112
|
+
view.addLayer(layer).then(menuGlobe.addLayerGUI.bind(menuGlobe));
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// ---- ADD 3D TILES TILESET ----
|
|
116
|
+
|
|
117
|
+
// Enable various compression support for 3D Tiles tileset:
|
|
118
|
+
// - `KHR_draco_mesh_compression` mesh compression extension
|
|
119
|
+
// - `KHR_texture_basisu` texture compresion extension
|
|
120
|
+
itowns.enableDracoLoader('./libs/draco/');
|
|
121
|
+
itowns.enableKtx2Loader('./lib/basis/', view.renderer);
|
|
122
|
+
|
|
123
|
+
if (state.tileset) {
|
|
124
|
+
const source = new OGC3DTilesSource({ url: state.tileset });
|
|
125
|
+
const layer = new OGC3DTilesLayer('3DTiles', {
|
|
126
|
+
source,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// Add an event for picking the 3D Tiles layer and displaying
|
|
130
|
+
// information about the picked feature in an html div
|
|
131
|
+
const pickingArgs = {
|
|
132
|
+
htmlDiv: document.getElementById('featureInfo'),
|
|
133
|
+
view,
|
|
134
|
+
layer,
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// Add the layer to our view
|
|
138
|
+
view.addLayer(layer).then((layer) => {
|
|
139
|
+
zoomToLayer(view, layer);
|
|
140
|
+
window.addEventListener('click',
|
|
141
|
+
(event) => fillHTMLWithPickingInfo(event, pickingArgs), false);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
debug.createOGC3DTilesDebugUI(menuGlobe.gui, view, layer);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
window.setURL = setURL;
|
|
148
|
+
</script>
|
|
149
|
+
</body>
|
|
150
|
+
</html>
|
package/examples/config.json
CHANGED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
extends: [
|
|
3
|
+
'eslint-config-airbnb-base',
|
|
4
|
+
'eslint-config-airbnb-base/rules/strict',
|
|
5
|
+
'../.eslintrc.cjs',
|
|
6
|
+
],
|
|
7
|
+
parserOptions: {
|
|
8
|
+
ecmaVersion: 13,
|
|
9
|
+
sourceType: 'module',
|
|
10
|
+
ecmaFeatures: {
|
|
11
|
+
impliedStrict: true,
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
env: {
|
|
15
|
+
browser: true,
|
|
16
|
+
es6: true,
|
|
17
|
+
amd: true,
|
|
18
|
+
commonjs: true,
|
|
19
|
+
},
|
|
20
|
+
globals: {
|
|
21
|
+
itowns: true,
|
|
22
|
+
},
|
|
23
|
+
rules: {
|
|
24
|
+
'prefer-arrow-callback': 'off',
|
|
25
|
+
'object-shorthand': 'off',
|
|
26
|
+
'no-param-reassign': ['error', { props: false }],
|
|
27
|
+
'no-mixed-operators': ['error', { allowSamePrecedence: true }],
|
|
28
|
+
'prefer-template': 'off',
|
|
29
|
+
'prefer-rest-params': 'off',
|
|
30
|
+
'arrow-parens': ['error', 'as-needed', { requireForBlockBody: true }],
|
|
31
|
+
|
|
32
|
+
// deactivated rules for `examples/`
|
|
33
|
+
'no-console': 'off',
|
|
34
|
+
// TODO reactivate all the following rules
|
|
35
|
+
'no-underscore-dangle': 'off',
|
|
36
|
+
|
|
37
|
+
},
|
|
38
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { MathUtils, Vector3 } from 'three';
|
|
2
|
+
|
|
3
|
+
const { Coordinates, Extent, CameraUtils } = itowns;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Function allowing picking on a given 3D tiles layer and filling an html div
|
|
7
|
+
* with information on the picked feature.
|
|
8
|
+
* @param {MouseEvent} event
|
|
9
|
+
* @param {Object} pickingArg
|
|
10
|
+
* @param {HTMLDivElement} pickingArg.htmlDiv - div element which contains the
|
|
11
|
+
* picked information
|
|
12
|
+
* @param {GlobeView} picking.view - iTowns view where the picking must be done
|
|
13
|
+
* @param {OGC3DTilesLayer} pickingArg.layer - the layer on which the picking
|
|
14
|
+
* must be done
|
|
15
|
+
*/
|
|
16
|
+
export function fillHTMLWithPickingInfo(event, pickingArg) {
|
|
17
|
+
const { htmlDiv, view, layer } = pickingArg;
|
|
18
|
+
|
|
19
|
+
// Remove content already in html div
|
|
20
|
+
while (htmlDiv.firstChild) {
|
|
21
|
+
htmlDiv.removeChild(htmlDiv.firstChild);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Get intersected objects
|
|
25
|
+
const intersects = view.pickObjectsAt(event, 5, layer);
|
|
26
|
+
|
|
27
|
+
// Get information from intersected objects (from the batch table and
|
|
28
|
+
// eventually the 3D Tiles extensions
|
|
29
|
+
const closestC3DTileFeature =
|
|
30
|
+
layer.getC3DTileFeatureFromIntersectsArray(intersects);
|
|
31
|
+
|
|
32
|
+
if (closestC3DTileFeature) {
|
|
33
|
+
// eslint-disable-next-line
|
|
34
|
+
htmlDiv.appendChild(createHTMLListFromObject(closestC3DTileFeature));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function zoomToSphere(view, tile, sphere) {
|
|
39
|
+
const transform = tile.cached.transform;
|
|
40
|
+
|
|
41
|
+
const center = new Vector3().fromArray(sphere).applyMatrix4(transform);
|
|
42
|
+
const radius = sphere[3] * transform.getMaxScaleOnAxis();
|
|
43
|
+
|
|
44
|
+
// Get the distance to sphere where the diameter cover the whole screen
|
|
45
|
+
// This is similar to SSE computation where sse = screen height.
|
|
46
|
+
const fov = view.camera3D.fov * MathUtils.DEG2RAD;
|
|
47
|
+
const distance = radius * Math.tan(fov * 2);
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
coord: new Coordinates('EPSG:4978', center),
|
|
51
|
+
range: distance + radius,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function zoomToBox(view, tile, box) {
|
|
56
|
+
const radius = Math.max(
|
|
57
|
+
new Vector3().fromArray(box, 3).length(),
|
|
58
|
+
new Vector3().fromArray(box, 6).length(),
|
|
59
|
+
new Vector3().fromArray(box, 9).length(),
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
// Approximate zoomToBox with sphere
|
|
63
|
+
const sphere = [box[0], box[1], box[2], radius];
|
|
64
|
+
return zoomToSphere(view, tile, sphere);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function zoomToRegion(view, region) {
|
|
68
|
+
const extent = new Extent('EPSG:4326',
|
|
69
|
+
region[0] * MathUtils.RAD2DEG, // west
|
|
70
|
+
region[2] * MathUtils.RAD2DEG, // east
|
|
71
|
+
region[1] * MathUtils.RAD2DEG, // south
|
|
72
|
+
region[3] * MathUtils.RAD2DEG, // north
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
return CameraUtils.getCameraTransformOptionsFromExtent(
|
|
76
|
+
view,
|
|
77
|
+
view.camera3D,
|
|
78
|
+
extent,
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function zoomToTile(view, tile) {
|
|
83
|
+
const { region, box, sphere } = tile.boundingVolume;
|
|
84
|
+
|
|
85
|
+
let cameraTransform;
|
|
86
|
+
if (region) {
|
|
87
|
+
cameraTransform = zoomToRegion(view, region);
|
|
88
|
+
} else if (box) {
|
|
89
|
+
cameraTransform = zoomToBox(view, tile, box);
|
|
90
|
+
} else {
|
|
91
|
+
cameraTransform = zoomToSphere(view, tile, sphere);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
view.controls.lookAtCoordinate({
|
|
95
|
+
coord: cameraTransform.coord,
|
|
96
|
+
range: 1.25 * cameraTransform.range, // zoom out a little bit
|
|
97
|
+
tilt: 60,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function zoomToLayer(view, layer) {
|
|
102
|
+
const root = layer.tilesRenderer.root;
|
|
103
|
+
|
|
104
|
+
zoomToTile(view, root);
|
|
105
|
+
}
|
|
@@ -145,7 +145,8 @@
|
|
|
145
145
|
});
|
|
146
146
|
|
|
147
147
|
// Load a glTF resource
|
|
148
|
-
itowns.
|
|
148
|
+
var gltfLoader = new itowns.iGLTFLoader();
|
|
149
|
+
gltfLoader.load(
|
|
149
150
|
// resource URL
|
|
150
151
|
"https://raw.githubusercontent.com/iTowns/iTowns2-sample-data/master/models/lampadaire/scene.gltf",
|
|
151
152
|
|
package/lib/Core/View.js
CHANGED
|
@@ -54,7 +54,7 @@ function object3DHasFeature(object3d) {
|
|
|
54
54
|
class C3DTilesLayer extends GeometryLayer {
|
|
55
55
|
#fillColorMaterialsBuffer;
|
|
56
56
|
/**
|
|
57
|
-
*
|
|
57
|
+
* @deprecated Deprecated 3D Tiles layer. Use {@link OGC3DTilesLayer} instead.
|
|
58
58
|
* @constructor
|
|
59
59
|
* @extends GeometryLayer
|
|
60
60
|
*
|