| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 |
- <!doctype html>
- <html lang="zh-CN"><head><meta charset="utf-8"><title>管道模型隔离验收(非业务数据)</title>
- <style>html,body,#map{margin:0;width:100%;height:100%;overflow:hidden;background:#04121f;color:white;font:16px sans-serif}aside{position:absolute;top:8px;left:8px;z-index:5;background:#04121fe8;padding:12px;max-width:90vw}button{margin:4px;padding:8px}pre{white-space:pre-wrap;margin:4px;font:12px monospace;max-height:24vh;overflow:auto}</style></head>
- <body><div id="map"></div><aside><strong>隔离验收:真实数据与构件样例分开,不修改业务接口/统计</strong><br>
- <button id="examples">四类示意件</button><button id="real">真实几何</button><button id="stress">隔离压力样例(虚拟管径)</button><button id="ground">地面视图</button><button id="underground">地下视图</button><button id="fps">采样 10 秒真实渲染 FPS</button><button id="clear">清理</button>
- <pre id="state">加载引擎</pre><pre id="performance"></pre></aside>
- <script type="module">
- window.CESIUM_BASE_URL='/cesium/'
- const missingKind=new URLSearchParams(location.search).get('missing')
- const originalFetch=window.fetch.bind(window)
- if(['spline','elbow','valve','branch','cross'].includes(missingKind)) {
- window.fetch=(input,options)=>String(input).endsWith(`/models/pipes/${missingKind}.gltf`)?Promise.resolve(new Response('isolated missing asset',{status:404})):originalFetch(input,options)
- }
- const { Cartesian3, HeadingPitchRange, Color }=await import('/.cache/deps/cesium.js')
- const { createViewer, applyTerrain }=await import('/src/modules/cockpit/services/cesiumEngine.js')
- const { syncPipeLayer, clearPipeLayer }=await import('/src/modules/cockpit/services/cesiumPipeLayer.js')
- const { toPipeNetwork }=await import('/src/modules/cockpit/domain/pipeNetwork.js')
- const config=await fetch('/cockpit/config.json').then(r=>r.json())
- const viewer=createViewer(document.querySelector('#map'),{ready:true,kind:'tms',url:'Assets/Textures/NaturalEarthII'})
- await applyTerrain(viewer,{ready:true,url:config.map.terrain.url,requestVertexNormals:true})
- let network={pipes:[],components:[]}
- viewer.canvas.setAttribute('aria-label','管道模型验收画面')
- viewer.canvas.setAttribute('role','img')
- let focus={lon:config.map.home.lon,lat:config.map.home.lat,height:100,range:config.map.home.range}
- const paint=(state)=>{const {covered=[],...counts}=state;document.querySelector('#state').textContent=JSON.stringify({mode:document.body.dataset.mode,missingAsset:missingKind,width:viewer.canvas.width,height:viewer.canvas.height,pipes:network.pipes.length,components:network.components.length,coveredObjects:covered.length,...counts},null,2);document.body.dataset.instances=state.instances;document.body.dataset.failed=state.failed;document.body.dataset.fallback=state.fallback;document.body.dataset.pending=state.pending}
- const draw=()=>syncPipeLayer(viewer,network,{onModelChange:paint})
- const look=(lon,lat,height,range)=>{focus={lon,lat,height,range};viewer.camera.lookAt(Cartesian3.fromDegrees(lon,lat,height),new HeadingPitchRange(0,-Math.PI/5,range))}
- const underground=()=>{viewer.scene.globe.translucency.enabled=true;viewer.scene.globe.translucency.frontFaceAlpha=.2;viewer.scene.globe.translucency.backFaceAlpha=.2;viewer.scene.requestRender()}
- document.querySelector('#examples').onclick=async()=>{
- document.body.dataset.mode='isolated-four-classes'
- const lon=110.39028,lat=28.44368
- network={pipes:[{code:'DEMO-SPLINE',industry:'GAS',diameter:600,positions:[[lon-.00012,lat],[lon-.00005,lat],[lon,lat+.00005]]}],components:[
- {code:'DEMO-ELBOW',kind:'elbow',label:'elbow',industry:'GAS',position:[lon+.00004,lat]},
- {code:'DEMO-VALVE',kind:'valve',label:'valve',industry:'GAS',position:[lon+.00007,lat]},
- {code:'DEMO-TEE',kind:'branch',label:'tee',industry:'GAS',position:[lon+.0001,lat]},
- {code:'DEMO-CROSS',kind:'branch',label:'cross',industry:'GAS',position:[lon+.00013,lat]},
- {code:'DEMO-UNKNOWN',kind:'other',label:'regulator',industry:'GAS',position:[lon+.00017,lat]}]}
- const {Cartographic,sampleTerrainMostDetailed}=await import('/.cache/deps/cesium.js')
- const [point]=await sampleTerrainMostDetailed(viewer.terrainProvider,[Cartographic.fromDegrees(lon,lat)])
- look(lon,lat,point.height,50);underground();await draw()
- }
- document.querySelector('#real').onclick=async()=>{
- document.body.dataset.mode='real-geometry'
- const response=await fetch(config.api.baseUrl+'/infrastructure/geometry').then(r=>r.json())
- network=toPipeNetwork(response.data)
- look(config.map.home.lon,config.map.home.lat,100,config.map.home.range);underground();await draw()
- }
- document.querySelector('#stress').onclick=async()=>{
- document.body.dataset.mode='isolated-stress-virtual-400mm'
- const response=await fetch(config.api.baseUrl+'/infrastructure/geometry').then(r=>r.json())
- const real=toPipeNetwork(response.data)
- network={pipes:real.pipes.map((pipe)=>({...pipe,diameter:400})),components:[]}
- look(config.map.home.lon,config.map.home.lat,100,config.map.home.range);underground();await draw()
- }
- document.querySelector('#ground').onclick=()=>{viewer.scene.globe.translucency.enabled=false;viewer.scene.requestRender()}
- document.querySelector('#underground').onclick=underground
- document.querySelector('#clear').onclick=async()=>{await clearPipeLayer(viewer);paint({instances:0,failed:0,fallback:0,pending:0})}
- document.querySelector('#fps').onclick=()=>{
- const scene=viewer.scene,old=scene.requestRenderMode
- scene.requestRenderMode=false
- const start=performance.now(),stamps=[]
- const detach=scene.postRender.addEventListener(()=>{
- const elapsed=performance.now()-start
- stamps.push(performance.now())
- if(elapsed<10000){
- viewer.camera.lookAt(Cartesian3.fromDegrees(focus.lon,focus.lat,focus.height),new HeadingPitchRange(elapsed/10000*Math.PI/4,-Math.PI/5,focus.range))
- return
- }
- detach();scene.requestRenderMode=old
- const seconds=(stamps.at(-1)-stamps[0])/1000,fps=(stamps.length-1)/seconds
- const gaps=stamps.slice(1).map((t,i)=>t-stamps[i]).sort((a,b)=>a-b)
- const result={mode:document.body.dataset.mode,frames:stamps.length,seconds,fps,p95FrameMs:gaps[Math.floor(gaps.length*.95)],maxFrameMs:gaps.at(-1),motion:'45deg heading / 10s',canvas:[viewer.canvas.width,viewer.canvas.height],viewport:[innerWidth,innerHeight],visibility:document.visibilityState,pass:fps>=30}
- document.querySelector('#performance').textContent=JSON.stringify(result,null,2)
- document.body.dataset.fps=String(fps)
- })
- }
- look(config.map.home.lon,config.map.home.lat,100,config.map.home.range)
- document.querySelector('#state').textContent='引擎已就绪;请选择样例或真实几何'
- </script></body></html>
|