@rr0/ufoathome 0.127.3 → 0.128.0

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.
Files changed (74) hide show
  1. package/dist-embed-interview/InterviewMessages_es-CNKjrohj.js +1 -0
  2. package/dist-embed-interview/InterviewMessages_fr-BP99Pg7g.js +1 -0
  3. package/dist-embed-interview/InterviewMessages_it-DTIrw8wW.js +1 -0
  4. package/dist-embed-interview/rr0-interview.mjs +5 -5
  5. package/dist-embed-scene/RailwaySystem-IcloRjw9.js +41 -0
  6. package/dist-embed-scene/{SceneNames_es-B9tudMDH.js → SceneNames_es-BITaYGB1.js} +1 -1
  7. package/dist-embed-scene/{SceneNames_fr-DAd-g0yB.js → SceneNames_fr-Bdk_h-Pr.js} +1 -1
  8. package/dist-embed-scene/{SceneNames_it-BLLX--oG.js → SceneNames_it-DhE0SScp.js} +1 -1
  9. package/dist-embed-scene/browser-_Ncw3Jhn.js +1 -0
  10. package/dist-embed-scene/rr0-scene.mjs +303 -300
  11. package/dist-embed-scene/{sightingSchema-v2l1p6Ld.js → sightingSchema-W7ivL-LH.js} +1 -1
  12. package/dist-embed-sighting/RailwaySystem-SElJhlLh.js +41 -0
  13. package/dist-embed-sighting/{SceneNames_es-VHJ-mGWu.js → SceneNames_es-Zb4vw-Vp.js} +1 -1
  14. package/dist-embed-sighting/{SceneNames_fr-BtjbcaRx.js → SceneNames_fr-C6_IIN2c.js} +1 -1
  15. package/dist-embed-sighting/{SceneNames_it-Ck8f90Z6.js → SceneNames_it-D7GivBq2.js} +1 -1
  16. package/dist-embed-sighting/browser-_Ncw3Jhn.js +1 -0
  17. package/dist-embed-sighting/rr0-sighting.mjs +296 -293
  18. package/dist-embed-sighting/{sightingSchema-v2l1p6Ld.js → sightingSchema-W7ivL-LH.js} +1 -1
  19. package/dist-embed-sighting-editor/{AdsbLolArchiveProvider-BtbGVTLo.js → AdsbLolArchiveProvider-DAFMMxZ9.js} +1 -1
  20. package/dist-embed-sighting-editor/{BodyEditor-BAT3yx6v.js → BodyEditor-T_1Jhs5n.js} +1 -1
  21. package/dist-embed-sighting-editor/CaseEditorMessages_es-DwO2w2Vc.js +1 -0
  22. package/dist-embed-sighting-editor/CaseEditorMessages_fr-iFzha0wM.js +1 -0
  23. package/dist-embed-sighting-editor/CaseEditorMessages_it-CjdJSAvo.js +1 -0
  24. package/dist-embed-sighting-editor/{ContrailSystem-B24rkkhS.js → ContrailSystem-DAHnNwJY.js} +1 -1
  25. package/dist-embed-sighting-editor/CoverageAssessor-24x89QSu.js +1 -0
  26. package/dist-embed-sighting-editor/GLTFLoader-BrlMonfv.js +1 -0
  27. package/dist-embed-sighting-editor/HeadlightSystem-9Ve6quO7.js +34 -0
  28. package/dist-embed-sighting-editor/{HynekAssessor-DVFjzROZ.js → HynekAssessor-CspF0udm.js} +1 -1
  29. package/dist-embed-sighting-editor/{InterviewEditorElement-CcEomZL0.js → InterviewEditorElement-Dm-ghjgg.js} +7 -9
  30. package/dist-embed-sighting-editor/InterviewMessages_en-yw5Qfw-6.js +1 -0
  31. package/dist-embed-sighting-editor/InterviewMessages_es-CNKjrohj.js +1 -0
  32. package/dist-embed-sighting-editor/InterviewMessages_fr-BP99Pg7g.js +1 -0
  33. package/dist-embed-sighting-editor/InterviewMessages_it-DTIrw8wW.js +1 -0
  34. package/dist-embed-sighting-editor/{LaunchEditor-BXDWiKWm.js → LaunchEditor-DfbahkM1.js} +1 -1
  35. package/dist-embed-sighting-editor/ModelSource-BjAOa9Br.js +1 -0
  36. package/dist-embed-sighting-editor/{ModelThumbnails-CGklRkoB.js → ModelThumbnails-B8ONo6Zq.js} +1 -1
  37. package/dist-embed-sighting-editor/{ModelViewer-Bg9kN_Zq.js → ModelViewer-BRBnm1f4.js} +1 -1
  38. package/dist-embed-sighting-editor/RailwaySystem-CO0S5Tvo.js +41 -0
  39. package/dist-embed-sighting-editor/{RoadMarkings-CVibbxgC.js → RoadMarkings-ysQVkGP6.js} +1 -1
  40. package/dist-embed-sighting-editor/{SceneNames_es-4pppn42v.js → SceneNames_es-BJhUPnW8.js} +1 -1
  41. package/dist-embed-sighting-editor/{SceneNames_fr-odZ6uYWU.js → SceneNames_fr-DXA1PSOW.js} +1 -1
  42. package/dist-embed-sighting-editor/{SceneNames_it-lXfB7y6i.js → SceneNames_it-CKVqa3DF.js} +1 -1
  43. package/dist-embed-sighting-editor/{SightingEditorMessages_es-C2q5UZrw.js → SightingEditorMessages_es-j9jNoZ69.js} +2 -2
  44. package/dist-embed-sighting-editor/SightingEditorMessages_fr-ClasHdht.js +12 -0
  45. package/dist-embed-sighting-editor/SightingEditorMessages_it-CgRkHcvD.js +12 -0
  46. package/dist-embed-sighting-editor/{SightingFileEditor-7inIgp24.js → SightingFileEditor-CEjimNPM.js} +1 -1
  47. package/dist-embed-sighting-editor/{TraceSystem-CZSZY6ZM.js → TraceSystem-BJbyw7Wf.js} +2 -2
  48. package/dist-embed-sighting-editor/{WaterSystem-Bd010I79.js → WaterSystem-DprmGdDo.js} +1 -1
  49. package/dist-embed-sighting-editor/rr0-sighting-editor.mjs +429 -357
  50. package/dist-embed-sighting-editor/{sightingSchema-v2l1p6Ld.js → sightingSchema-W7ivL-LH.js} +1 -1
  51. package/dist-embed-sighting-editor/surroundingsSources-C67enaVE.js +1 -0
  52. package/dist-embed-sighting-editor/trafficRuntime-oYuU__pd.js +2 -0
  53. package/package.json +1 -1
  54. package/dist-embed-interview/InterviewMessages_es-D5d2JVA3.js +0 -1
  55. package/dist-embed-interview/InterviewMessages_fr-CmScqfza.js +0 -1
  56. package/dist-embed-interview/InterviewMessages_it-2SNw5xMp.js +0 -1
  57. package/dist-embed-scene/RailwaySystem-BSqu6iHY.js +0 -41
  58. package/dist-embed-sighting/RailwaySystem-BXRi4IAz.js +0 -41
  59. package/dist-embed-sighting-editor/CaseEditorMessages_es-CNLEMPjy.js +0 -1
  60. package/dist-embed-sighting-editor/CaseEditorMessages_fr-DN3xxn9o.js +0 -1
  61. package/dist-embed-sighting-editor/CaseEditorMessages_it-B6aG-baK.js +0 -1
  62. package/dist-embed-sighting-editor/CoverageAssessor-BPhdv7QL.js +0 -1
  63. package/dist-embed-sighting-editor/GLTFLoader-C7miE2gT.js +0 -1
  64. package/dist-embed-sighting-editor/HeadlightSystem-DaWqNslK.js +0 -34
  65. package/dist-embed-sighting-editor/InterviewMessages_en-cs-wWpmz.js +0 -1
  66. package/dist-embed-sighting-editor/InterviewMessages_es-D5d2JVA3.js +0 -1
  67. package/dist-embed-sighting-editor/InterviewMessages_fr-CmScqfza.js +0 -1
  68. package/dist-embed-sighting-editor/InterviewMessages_it-2SNw5xMp.js +0 -1
  69. package/dist-embed-sighting-editor/ModelSource-gIw80dOv.js +0 -1
  70. package/dist-embed-sighting-editor/RailwaySystem-BCDMPAEx.js +0 -41
  71. package/dist-embed-sighting-editor/SightingEditorMessages_fr-DyELrz-P.js +0 -12
  72. package/dist-embed-sighting-editor/SightingEditorMessages_it-CUKdtgr1.js +0 -12
  73. package/dist-embed-sighting-editor/surroundingsSources-98rSCu2Y.js +0 -1
  74. package/dist-embed-sighting-editor/trafficRuntime-Dk4XdgcY.js +0 -2
@@ -1,41 +0,0 @@
1
- import{G as F,c as w,C as H,g as P,B as K,d as N,b as U,e as k}from"./rr0-scene.mjs";class S{static HOLLOW_M=1;static COVERED_M=3;static WINDOW_M=30;static SAMPLE_M=4;static MAX_GRADE={rail:.025,highSpeed:.035,subway:.04,light_rail:.06,tram:.08,funicular:1/0};static heights(t,n,s){const e=t.map(r=>r.level===0),o=t.map((r,l)=>e[l]?S.targets(r,n,s):[]),c=t.map((r,l)=>e[l]?S.samples(r,o[l]):[]),a=new Map;t.forEach((r,l)=>{if(e[l])for(const p of S.ends(r)){const h=S.key(p),f=a.get(h);f?f.push(l):a.set(h,[l])}});const M=r=>{const l=a.get(S.key(r));if(l)return S.median(l.flatMap(p=>c[p]),r)};return t.map((r,l)=>{if(e[l]){const p=[...new Set([l,...S.ends(r).flatMap(g=>a.get(S.key(g))??[])])].flatMap(g=>c[g]),h=r.centre.map((g,D)=>S.median(p,g)??o[l][D]),[f,z]=S.ends(r);return h[0]=M(f)??h[0],h[h.length-1]=M(z)??h[h.length-1],S.graded(h,r.along,r.highSpeed?S.MAX_GRADE.highSpeed:S.MAX_GRADE[r.kind])}return S.carried(r,n,s,M)})}static targets(t,n,s){return t.centre.map(e=>{const o=n(e.x,e.z);if(s===void 0||e.altitudeM===void 0)return o;const c=e.altitudeM+s;return c-o>S.HOLLOW_M||o-c>S.COVERED_M?c:o})}static samples(t,n){const s=[];let e=0;return t.centre.forEach((o,c)=>{t.along[c]+1e-6<e&&c<t.centre.length-1||(s.push({x:o.x,z:o.z,y:n[c]}),e=t.along[c]+S.SAMPLE_M)}),s}static median(t,n){const s=[];for(const o of t)Math.hypot(o.x-n.x,o.z-n.z)<=S.WINDOW_M&&s.push(o.y);if(s.length===0)return;s.sort((o,c)=>o-c);const e=s.length>>1;return s.length%2===1?s[e]:(s[e-1]+s[e])/2}static graded(t,n,s){if(!Number.isFinite(s)||t.length<3)return t;const e=[...t],o=e.length-1,c=n[o];if(Math.abs(e[o]-e[0])>s*c)return n.map(a=>e[0]+(e[o]-e[0])*a/c);for(let a=1;a<o;a++){const M=s*(n[a]-n[a-1]);e[a]=Math.min(e[a-1]+M,Math.max(e[a-1]-M,e[a]))}for(let a=o-1;a>0;a--){const M=s*(n[a+1]-n[a]);e[a]=Math.min(e[a+1]+M,Math.max(e[a+1]-M,e[a]))}return e}static carried(t,n,s,e){const[o,c]=S.ends(t),a=t.along[t.along.length-1],M=e(o),r=e(c);if(s!==void 0&&t.centre.every(h=>h.altitudeM!==void 0)){const h=t.centre.map(g=>g.altitudeM+s),f=M!==void 0?M-h[0]:0,z=r!==void 0?r-h[h.length-1]:0;return h.map((g,D)=>g+f+(z-f)*t.along[D]/a)}const l=M??n(o.x,o.z),p=r??n(c.x,c.z);return t.along.map(h=>l+(p-l)*h/a)}static ends(t){return[t.centre[0],t.centre[t.centre.length-1]]}static key(t){return`${Math.round(t.x*2)},${Math.round(t.z*2)}`}}class I{positions=[];indices=[];along=[];get vertexCount(){return this.positions.length/3}strip(t,n,s){const e=this.vertexCount;for(let o=0;o<t.length;o++)this.positions.push(t[o].x,t[o].y,t[o].z,n[o].x,n[o].y,n[o].z),s&&this.along.push(s[o],s[o]);for(let o=0;o<t.length-1;o++){const c=e+o*2;this.indices.push(c,c+2,c+1,c+1,c+2,c+3)}}beam(t,n,s,e=!0){const o=n.x-t.x,c=n.y-t.y,a=n.z-t.z,M=Math.hypot(o,c,a);if(M<1e-6)return;const r={x:o/M,y:c/M,z:a/M},l=Math.abs(r.y)>.9?{x:1,y:0,z:0}:{x:0,y:1,z:0},p=r.y*l.z-r.z*l.y,h=r.z*l.x-r.x*l.z,f=r.x*l.y-r.y*l.x,z=Math.hypot(p,h,f),g={x:p/z*s/2,y:h/z*s/2,z:f/z*s/2},D={x:r.y*g.z-r.z*g.y,y:r.z*g.x-r.x*g.z,z:r.x*g.y-r.y*g.x},E=(u,A,d)=>({x:u.x+g.x*A+D.x*d,y:u.y+g.y*A+D.y*d,z:u.z+g.z*A+D.z*d}),_=[[1,1],[-1,1],[-1,-1],[1,-1]];for(let u=0;u<4;u++){const[A,d]=_[u],[v,x]=_[(u+1)%4];this.quad(E(t,A,d),E(t,v,x),E(n,v,x),E(n,A,d))}e&&(this.quad(...[..._].reverse().map(([u,A])=>E(t,u,A))),this.quad(..._.map(([u,A])=>E(n,u,A))))}quad(t,n,s,e){const o=this.vertexCount;this.positions.push(t.x,t.y,t.z,n.x,n.y,n.z,s.x,s.y,s.z,e.x,e.y,e.z),this.indices.push(o,o+1,o+2,o,o+2,o+3)}}class i{static STEP_M=6;static BALLAST_HEIGHT_M=.5;static BALLAST_SLOPE=1.5;static BALLAST_SHOULDER_M=.45;static DECK_DEPTH_M=.8;static BANK_SLOPE=1.5;static SLEEPER_LENGTH_M=2.4;static SLEEPER_WIDTH_M=.29;static SLEEPER_SPACING_M=.6;static RAIL_HEAD_M=.072;static RAIL_HEIGHT_M=.18;static TRAM_RAIL_HEIGHT_M=.03;static LIFT_M=.06;static CATENARY={rail:{contactM:5.5,systemM:1.4,spanM:54,staggerM:.2},highSpeed:{contactM:5.08,systemM:1.4,spanM:63,staggerM:.2},service:{contactM:5.5,systemM:1.2,spanM:45,staggerM:.2},tram:{contactM:6,systemM:0,spanM:30,staggerM:.2}};static MESSENGER_SAG_M=.55;static MAST_SIDE_M=.26;static MAST_OFFSET_M=3.1;static MAST_ABOVE_M=.6;static CONTACT_DIAMETER_M=.012;static MESSENGER_DIAMETER_M=.011;static ARM_SIDE_M=.06;static TRACK_SPACING_M={rail:3.7,highSpeed:4.5,tram:3.1,subway:3.4,light_rail:3.4,funicular:3.2};static BALLAST_ALBEDO=[.17,.16,.15];static BANK_ALBEDO=[.085,.09,.05];static DECK_ALBEDO=[.26,.255,.24];static CONCRETE_ALBEDO=[.36,.35,.33];static WOOD_ALBEDO=[.07,.055,.045];static RUST_ALBEDO=[.085,.068,.058];static STEEL_ALBEDO=[.3,.31,.32];static COPPER_ALBEDO=[.09,.085,.07];group=new F;stepM=i.STEP_M;drawn=0;ballastMaterial=i.pebbled(i.lambert(i.BALLAST_ALBEDO,!0));earthMaterial=i.lambert(i.BANK_ALBEDO,!0);deckMaterial=i.lambert(i.DECK_ALBEDO,!1);concreteSleepers=i.sleeperMaterial(i.CONCRETE_ALBEDO);woodSleepers=i.sleeperMaterial(i.WOOD_ALBEDO);rustMaterial=i.lambert(i.RUST_ALBEDO,!0);headMaterial=new w({color:new H(.62,.62,.62),metalness:1,roughness:.28,polygonOffset:!0,polygonOffsetFactor:-2,polygonOffsetUnits:-2});steelMaterial=i.lambert(i.STEEL_ALBEDO,!1);wireMaterial=i.lambert(i.COPPER_ALBEDO,!1);constructor(){this.group.name="railways"}get count(){return this.drawn}setGroundSpacing(t){this.stepM=Number.isFinite(t)&&t>0?Math.min(i.STEP_M,Math.max(1.5,t/2)):i.STEP_M}set(t,n,s,e,o=1/0){this.clear();const a=t.map(f=>({line:f,path:f.points.map(z=>({...P(z.lat,z.lng,n,s),altitudeM:z.altitudeM}))})).filter(({line:f,path:z})=>f.level>=0&&i.within(z,o)),M=i.altitudeOffset(a,e),r=a.flatMap(({line:f,path:z})=>{const g=this.layoutOf(f,z);return g?[{line:f,layout:g}]:[]}),l=S.heights(r.map(({layout:f})=>f),e,M),p={ballast:new I,earth:new I,deck:new I,concrete:new I,wood:new I,rust:new I,head:new I,steel:new I,wire:new I};r.forEach(({line:f,layout:z},g)=>{this.lay(f,{...z,y:l[g]},e,p),this.drawn++});const h=[[p.ballast,this.ballastMaterial,"ballast",!1],[p.earth,this.earthMaterial,"embankments",!1],[p.deck,this.deckMaterial,"decks",!0],[p.concrete,this.concreteSleepers,"sleepers",!1],[p.wood,this.woodSleepers,"sleepers wood",!1],[p.rust,this.rustMaterial,"rails",!1],[p.head,this.headMaterial,"rail heads",!1],[p.steel,this.steelMaterial,"catenary masts",!0],[p.wire,this.wireMaterial,"catenary wires",!1]];for(const[f,z,g,D]of h){const E=i.meshOf(f,z);E&&(E.name=`railways ${g}`,E.castShadow=D,E.receiveShadow=!0,this.group.add(E))}}clear(){for(const t of[...this.group.children])this.group.remove(t),t.geometry?.dispose();this.drawn=0}dispose(){this.clear();for(const t of[this.ballastMaterial,this.earthMaterial,this.deckMaterial,this.concreteSleepers,this.woodSleepers,this.rustMaterial,this.headMaterial,this.steelMaterial,this.wireMaterial])t.dispose()}static within(t,n){if(!Number.isFinite(n))return!0;const s=n*1.1+100;return t.some((e,o)=>Math.hypot(e.x,e.z)<=s||o>0&&Math.hypot((e.x+t[o-1].x)/2,(e.z+t[o-1].z)/2)<=s)}static altitudeOffset(t,n){const s=[];for(const{line:e,path:o}of t)if(e.level===0)for(const c of o)c.altitudeM!==void 0&&s.push(n(c.x,c.z)-c.altitudeM);if(!(s.length<5))return s.sort((e,o)=>e-o),s[Math.floor(s.length/2)]}layoutOf(t,n){const s=[];for(let c=0;c<n.length-1;c++){const a=n[c],M=n[c+1],r=Math.max(1,Math.ceil(Math.hypot(M.x-a.x,M.z-a.z)/this.stepM));for(let l=0;l<r;l++){const p=l/r,h=a.altitudeM!==void 0&&M.altitudeM!==void 0?a.altitudeM+(M.altitudeM-a.altitudeM)*p:void 0;s.push({x:a.x+(M.x-a.x)*p,z:a.z+(M.z-a.z)*p,altitudeM:h})}}if(s.push(n[n.length-1]),s.length<2)return;const e=[0];for(let c=1;c<s.length;c++)e.push(e[c-1]+Math.hypot(s[c].x-s[c-1].x,s[c].z-s[c-1].z));if(e[e.length-1]<.5)return;const o=s.map((c,a)=>{const M=s[Math.max(0,a-1)],r=s[Math.min(s.length-1,a+1)],l=r.x-M.x,p=r.z-M.z,h=Math.hypot(l,p);return h<1e-6?{x:1,z:0}:{x:l/h,z:p/h}});return{kind:t.kind,...t.highSpeed?{highSpeed:!0}:{},level:t.level,centre:s,along:e,dir:o}}lay(t,n,s,e){const o=t.highSpeed?i.TRACK_SPACING_M.highSpeed:i.TRACK_SPACING_M[t.kind],c=Math.min(8,Math.max(1,t.tracks)),a=Array.from({length:c},(E,_)=>(_-(c-1)/2)*o),M=t.kind==="tram",r=M?0:i.BALLAST_HEIGHT_M,l=i.LIFT_M,p=(E,_,u)=>({x:n.centre[E].x-n.dir[E].z*_,y:n.y[E]+u,z:n.centre[E].z+n.dir[E].x*_}),h=n.centre.map((E,_)=>_);if(!M){const E=i.SLEEPER_LENGTH_M/2+i.BALLAST_SHOULDER_M+(a[a.length-1]??0),_=h.map(A=>p(A,E,r+l)),u=h.map(A=>p(A,-E,r+l));if(e.ballast.strip(_,u),t.level===0){const A=E+r*i.BALLAST_SLOPE;for(const d of[1,-1]){const v=[],x=[];let m=!1;for(const L of h){const b=p(L,d*A,l),C=s(b.x,b.z)+l,T=b.y-C;T<0&&(b.y=Math.min(C,n.y[L]+r-.05+l)),v.push(b);const B=p(L,d*(A+Math.max(0,T)*i.BANK_SLOPE),l);B.y=Math.min(s(B.x,B.z)+l,b.y),b.y-B.y>.02&&(m=!0),x.push(B)}const O=d>0?_:u;d>0?e.ballast.strip(v,O):e.ballast.strip(O,v),m&&(d>0?e.earth.strip(x,v):e.earth.strip(v,x))}}else{const A=-i.DECK_DEPTH_M,d=E+.15,v=h.map(L=>p(L,d,r+l+.1)),x=h.map(L=>p(L,-d,r+l+.1)),m=h.map(L=>p(L,d,A)),O=h.map(L=>p(L,-d,A));e.deck.strip(m,v),e.deck.strip(x,O),e.deck.strip(O,m),e.deck.strip(v,h.map(L=>p(L,E,r+l+.1))),e.deck.strip(h.map(L=>p(L,-E,r+l+.1)),x)}}const f=t.service?e.wood:e.concrete,z=t.gaugeMm/2e3+i.RAIL_HEAD_M/2,g=M?i.TRAM_RAIL_HEIGHT_M:i.RAIL_HEIGHT_M,D=r+l;for(const E of a){if(!M){const _=i.SLEEPER_LENGTH_M/2;f.strip(h.map(u=>p(u,E+_,D+.004)),h.map(u=>p(u,E-_,D+.004)),n.along)}for(const _ of[1,-1]){const u=E+_*z,A=i.RAIL_HEAD_M/2,d=h.map(x=>p(x,u+A,D+g)),v=h.map(x=>p(x,u-A,D+g));e.head.strip(d,v),e.rust.strip(h.map(x=>p(x,u+A,D)),d),e.rust.strip(v,h.map(x=>p(x,u-A,D)))}}t.electrification==="overhead"&&t.kind!=="subway"&&t.kind!=="funicular"&&this.catenary(t,n,a,D+g,p,s,e)}catenary(t,n,s,e,o,c,a){const M=t.kind==="tram"?i.CATENARY.tram:t.highSpeed?i.CATENARY.highSpeed:t.service?i.CATENARY.service:i.CATENARY.rail,r=n.along[n.along.length-1],l=Math.max(1,Math.round(r/M.spanM)),p=r/l,h=Array.from({length:l},(d,v)=>(v+.5)*p),f=e+M.contactM,z=f+M.systemM,g=(M.systemM>0?z:f)+i.MAST_ABOVE_M,D=s[s.length-1],E=s.length>2,_=s.length===1?[1]:[1,-1],u=(d,v,x)=>{let m=0,O=n.along.length-2;for(;m<O;){const T=m+O+1>>1;n.along[T]<=d?m=T:O=T-1}const L=Math.min(1,Math.max(0,(d-n.along[m])/Math.max(1e-6,n.along[m+1]-n.along[m]))),b=o(m,v,x),C=o(m+1,v,x);return{x:b.x+(C.x-b.x)*L,y:b.y+(C.y-b.y)*L,z:b.z+(C.z-b.z)*L}};for(const d of h){const v=u(d,0,f);if(!(t.level===0&&c(v.x,v.z)>v.y)){for(const x of _){const m=x*(D+i.MAST_OFFSET_M),O=u(d,m,0);t.level===0&&(O.y=Math.min(O.y,c(O.x,O.z)));const L=u(d,m,g);if(a.steel.beam(O,L,i.MAST_SIDE_M),E)continue;const C=(_.length===1?s[0]:x*D)-x*.6,T=M.systemM>0?z:f+.3;a.steel.beam(u(d,m,T),u(d,C,T),i.ARM_SIDE_M),a.steel.beam(u(d,m,f-.4),u(d,C,T),i.ARM_SIDE_M)}if(E){const x=D+i.MAST_OFFSET_M;a.steel.beam(u(d,x,g-.2),u(d,-x,g-.2),i.MAST_SIDE_M*.8)}}}const A=[0,...h,r];for(const[d,v]of s.entries()){const x=m=>m===0||m===A.length-1?0:((m+d)%2===0?1:-1)*M.staggerM;for(let m=0;m<A.length-1;m++){const O=A[m],L=A[m+1];if(L-O<.1||(a.wire.beam(u(O,v+x(m),f),u(L,v+x(m+1),f),i.CONTACT_DIAMETER_M,!1),M.systemM<=0))continue;const b=4,C=T=>{const B=m===0?.5+T/2:m===A.length-2?T/2:T;return z-i.MESSENGER_SAG_M*4*B*(1-B)};for(let T=0;T<b;T++){const B=T/b,G=(T+1)/b;a.wire.beam(u(O+(L-O)*B,v,C(B)),u(O+(L-O)*G,v,C(G)),i.MESSENGER_DIAMETER_M,!1)}}}}static meshOf(t,n){if(t.indices.length===0)return;const s=new K;return s.setAttribute("position",new N(new Float32Array(t.positions),3)),t.along.length>0&&s.setAttribute("aAlong",new N(new Float32Array(t.along),1)),s.setIndex(new N(new Uint32Array(t.indices),1)),s.computeVertexNormals(),new U(s,n)}static lambert(t,n){return new k({color:new H(...t),...n?{polygonOffset:!0,polygonOffsetFactor:-2,polygonOffsetUnits:-2}:{}})}static pebbled(t){return t.onBeforeCompile=n=>{n.vertexShader=n.vertexShader.replace("#include <common>",`#include <common>
2
- varying vec3 vBallast;`).replace("#include <begin_vertex>",`#include <begin_vertex>
3
- vBallast = position;`),n.fragmentShader=n.fragmentShader.replace("#include <common>",`#include <common>
4
- varying vec3 vBallast;
5
- float ballastHash(vec2 p) {
6
- p = fract(p * vec2(127.1, 311.7));
7
- p += dot(p, p + 34.5);
8
- return fract(p.x * p.y);
9
- }
10
- float ballastNoise(vec2 p) {
11
- vec2 i = floor(p);
12
- vec2 f = fract(p);
13
- f = f * f * (3.0 - 2.0 * f);
14
- return mix(mix(ballastHash(i), ballastHash(i + vec2(1.0, 0.0)), f.x), mix(ballastHash(i + vec2(0.0, 1.0)), ballastHash(i + vec2(1.0, 1.0)), f.x), f.y);
15
- }`).replace("#include <map_fragment>",`#include <map_fragment>
16
- {
17
- float eye = length(vViewPosition);
18
- vec2 at = vBallast.xz + vec2(0.0, vBallast.y);
19
- float stones = (ballastHash(floor(at * 22.0)) - 0.5) * 0.9 * (1.0 - smoothstep(4.0, 18.0, eye))
20
- + (ballastNoise(at * 6.0) - 0.5) * 0.5 * (1.0 - smoothstep(15.0, 60.0, eye))
21
- + (ballastNoise(at * 0.7) - 0.5) * 0.35 * (1.0 - smoothstep(80.0, 300.0, eye));
22
- diffuseColor.rgb *= 1.0 + stones;
23
- }`)},t.customProgramCacheKey=()=>"rr0-railway-ballast",t}static sleeperMaterial(t){const n=new k({color:new H(1,1,1),polygonOffset:!0,polygonOffsetFactor:-3,polygonOffsetUnits:-3}),s=new H(...t),e=new H(...i.BALLAST_ALBEDO);return n.onBeforeCompile=o=>{o.uniforms.uSleeper={value:s},o.uniforms.uCrib={value:e},o.uniforms.uSpacing={value:i.SLEEPER_SPACING_M},o.uniforms.uDuty={value:i.SLEEPER_WIDTH_M/i.SLEEPER_SPACING_M},o.vertexShader=o.vertexShader.replace("#include <common>",`#include <common>
24
- attribute float aAlong;
25
- varying float vAlong;`).replace("#include <begin_vertex>",`#include <begin_vertex>
26
- vAlong = aAlong;`),o.fragmentShader=o.fragmentShader.replace("#include <common>",`#include <common>
27
- varying float vAlong;
28
- uniform vec3 uSleeper;
29
- uniform vec3 uCrib;
30
- uniform float uSpacing;
31
- uniform float uDuty;
32
- // How much of [0, x] periods is sleeper: the integral of a pulse of width uDuty at the start of each period.
33
- float sleeperIntegral(float x) {
34
- return floor(x) * uDuty + min(fract(x), uDuty);
35
- }`).replace("#include <map_fragment>",`#include <map_fragment>
36
- {
37
- float u = vAlong / uSpacing;
38
- float w = max(fwidth(u), 1e-4);
39
- float cover = (sleeperIntegral(u + 0.5 * w) - sleeperIntegral(u - 0.5 * w)) / w;
40
- diffuseColor.rgb *= mix(uCrib, uSleeper, clamp(cover, 0.0, 1.0));
41
- }`)},n.customProgramCacheKey=()=>"rr0-railway-sleepers",n}}export{i as RailwaySystem};
@@ -1,41 +0,0 @@
1
- import{G as F,f as w,C as H,g as P,B as K,h as N,b as U,i as k}from"./rr0-sighting.mjs";class S{static HOLLOW_M=1;static COVERED_M=3;static WINDOW_M=30;static SAMPLE_M=4;static MAX_GRADE={rail:.025,highSpeed:.035,subway:.04,light_rail:.06,tram:.08,funicular:1/0};static heights(t,n,s){const e=t.map(r=>r.level===0),o=t.map((r,l)=>e[l]?S.targets(r,n,s):[]),c=t.map((r,l)=>e[l]?S.samples(r,o[l]):[]),a=new Map;t.forEach((r,l)=>{if(e[l])for(const p of S.ends(r)){const h=S.key(p),f=a.get(h);f?f.push(l):a.set(h,[l])}});const M=r=>{const l=a.get(S.key(r));if(l)return S.median(l.flatMap(p=>c[p]),r)};return t.map((r,l)=>{if(e[l]){const p=[...new Set([l,...S.ends(r).flatMap(g=>a.get(S.key(g))??[])])].flatMap(g=>c[g]),h=r.centre.map((g,D)=>S.median(p,g)??o[l][D]),[f,z]=S.ends(r);return h[0]=M(f)??h[0],h[h.length-1]=M(z)??h[h.length-1],S.graded(h,r.along,r.highSpeed?S.MAX_GRADE.highSpeed:S.MAX_GRADE[r.kind])}return S.carried(r,n,s,M)})}static targets(t,n,s){return t.centre.map(e=>{const o=n(e.x,e.z);if(s===void 0||e.altitudeM===void 0)return o;const c=e.altitudeM+s;return c-o>S.HOLLOW_M||o-c>S.COVERED_M?c:o})}static samples(t,n){const s=[];let e=0;return t.centre.forEach((o,c)=>{t.along[c]+1e-6<e&&c<t.centre.length-1||(s.push({x:o.x,z:o.z,y:n[c]}),e=t.along[c]+S.SAMPLE_M)}),s}static median(t,n){const s=[];for(const o of t)Math.hypot(o.x-n.x,o.z-n.z)<=S.WINDOW_M&&s.push(o.y);if(s.length===0)return;s.sort((o,c)=>o-c);const e=s.length>>1;return s.length%2===1?s[e]:(s[e-1]+s[e])/2}static graded(t,n,s){if(!Number.isFinite(s)||t.length<3)return t;const e=[...t],o=e.length-1,c=n[o];if(Math.abs(e[o]-e[0])>s*c)return n.map(a=>e[0]+(e[o]-e[0])*a/c);for(let a=1;a<o;a++){const M=s*(n[a]-n[a-1]);e[a]=Math.min(e[a-1]+M,Math.max(e[a-1]-M,e[a]))}for(let a=o-1;a>0;a--){const M=s*(n[a+1]-n[a]);e[a]=Math.min(e[a+1]+M,Math.max(e[a+1]-M,e[a]))}return e}static carried(t,n,s,e){const[o,c]=S.ends(t),a=t.along[t.along.length-1],M=e(o),r=e(c);if(s!==void 0&&t.centre.every(h=>h.altitudeM!==void 0)){const h=t.centre.map(g=>g.altitudeM+s),f=M!==void 0?M-h[0]:0,z=r!==void 0?r-h[h.length-1]:0;return h.map((g,D)=>g+f+(z-f)*t.along[D]/a)}const l=M??n(o.x,o.z),p=r??n(c.x,c.z);return t.along.map(h=>l+(p-l)*h/a)}static ends(t){return[t.centre[0],t.centre[t.centre.length-1]]}static key(t){return`${Math.round(t.x*2)},${Math.round(t.z*2)}`}}class I{positions=[];indices=[];along=[];get vertexCount(){return this.positions.length/3}strip(t,n,s){const e=this.vertexCount;for(let o=0;o<t.length;o++)this.positions.push(t[o].x,t[o].y,t[o].z,n[o].x,n[o].y,n[o].z),s&&this.along.push(s[o],s[o]);for(let o=0;o<t.length-1;o++){const c=e+o*2;this.indices.push(c,c+2,c+1,c+1,c+2,c+3)}}beam(t,n,s,e=!0){const o=n.x-t.x,c=n.y-t.y,a=n.z-t.z,M=Math.hypot(o,c,a);if(M<1e-6)return;const r={x:o/M,y:c/M,z:a/M},l=Math.abs(r.y)>.9?{x:1,y:0,z:0}:{x:0,y:1,z:0},p=r.y*l.z-r.z*l.y,h=r.z*l.x-r.x*l.z,f=r.x*l.y-r.y*l.x,z=Math.hypot(p,h,f),g={x:p/z*s/2,y:h/z*s/2,z:f/z*s/2},D={x:r.y*g.z-r.z*g.y,y:r.z*g.x-r.x*g.z,z:r.x*g.y-r.y*g.x},E=(u,A,d)=>({x:u.x+g.x*A+D.x*d,y:u.y+g.y*A+D.y*d,z:u.z+g.z*A+D.z*d}),_=[[1,1],[-1,1],[-1,-1],[1,-1]];for(let u=0;u<4;u++){const[A,d]=_[u],[v,x]=_[(u+1)%4];this.quad(E(t,A,d),E(t,v,x),E(n,v,x),E(n,A,d))}e&&(this.quad(...[..._].reverse().map(([u,A])=>E(t,u,A))),this.quad(..._.map(([u,A])=>E(n,u,A))))}quad(t,n,s,e){const o=this.vertexCount;this.positions.push(t.x,t.y,t.z,n.x,n.y,n.z,s.x,s.y,s.z,e.x,e.y,e.z),this.indices.push(o,o+1,o+2,o,o+2,o+3)}}class i{static STEP_M=6;static BALLAST_HEIGHT_M=.5;static BALLAST_SLOPE=1.5;static BALLAST_SHOULDER_M=.45;static DECK_DEPTH_M=.8;static BANK_SLOPE=1.5;static SLEEPER_LENGTH_M=2.4;static SLEEPER_WIDTH_M=.29;static SLEEPER_SPACING_M=.6;static RAIL_HEAD_M=.072;static RAIL_HEIGHT_M=.18;static TRAM_RAIL_HEIGHT_M=.03;static LIFT_M=.06;static CATENARY={rail:{contactM:5.5,systemM:1.4,spanM:54,staggerM:.2},highSpeed:{contactM:5.08,systemM:1.4,spanM:63,staggerM:.2},service:{contactM:5.5,systemM:1.2,spanM:45,staggerM:.2},tram:{contactM:6,systemM:0,spanM:30,staggerM:.2}};static MESSENGER_SAG_M=.55;static MAST_SIDE_M=.26;static MAST_OFFSET_M=3.1;static MAST_ABOVE_M=.6;static CONTACT_DIAMETER_M=.012;static MESSENGER_DIAMETER_M=.011;static ARM_SIDE_M=.06;static TRACK_SPACING_M={rail:3.7,highSpeed:4.5,tram:3.1,subway:3.4,light_rail:3.4,funicular:3.2};static BALLAST_ALBEDO=[.17,.16,.15];static BANK_ALBEDO=[.085,.09,.05];static DECK_ALBEDO=[.26,.255,.24];static CONCRETE_ALBEDO=[.36,.35,.33];static WOOD_ALBEDO=[.07,.055,.045];static RUST_ALBEDO=[.085,.068,.058];static STEEL_ALBEDO=[.3,.31,.32];static COPPER_ALBEDO=[.09,.085,.07];group=new F;stepM=i.STEP_M;drawn=0;ballastMaterial=i.pebbled(i.lambert(i.BALLAST_ALBEDO,!0));earthMaterial=i.lambert(i.BANK_ALBEDO,!0);deckMaterial=i.lambert(i.DECK_ALBEDO,!1);concreteSleepers=i.sleeperMaterial(i.CONCRETE_ALBEDO);woodSleepers=i.sleeperMaterial(i.WOOD_ALBEDO);rustMaterial=i.lambert(i.RUST_ALBEDO,!0);headMaterial=new w({color:new H(.62,.62,.62),metalness:1,roughness:.28,polygonOffset:!0,polygonOffsetFactor:-2,polygonOffsetUnits:-2});steelMaterial=i.lambert(i.STEEL_ALBEDO,!1);wireMaterial=i.lambert(i.COPPER_ALBEDO,!1);constructor(){this.group.name="railways"}get count(){return this.drawn}setGroundSpacing(t){this.stepM=Number.isFinite(t)&&t>0?Math.min(i.STEP_M,Math.max(1.5,t/2)):i.STEP_M}set(t,n,s,e,o=1/0){this.clear();const a=t.map(f=>({line:f,path:f.points.map(z=>({...P(z.lat,z.lng,n,s),altitudeM:z.altitudeM}))})).filter(({line:f,path:z})=>f.level>=0&&i.within(z,o)),M=i.altitudeOffset(a,e),r=a.flatMap(({line:f,path:z})=>{const g=this.layoutOf(f,z);return g?[{line:f,layout:g}]:[]}),l=S.heights(r.map(({layout:f})=>f),e,M),p={ballast:new I,earth:new I,deck:new I,concrete:new I,wood:new I,rust:new I,head:new I,steel:new I,wire:new I};r.forEach(({line:f,layout:z},g)=>{this.lay(f,{...z,y:l[g]},e,p),this.drawn++});const h=[[p.ballast,this.ballastMaterial,"ballast",!1],[p.earth,this.earthMaterial,"embankments",!1],[p.deck,this.deckMaterial,"decks",!0],[p.concrete,this.concreteSleepers,"sleepers",!1],[p.wood,this.woodSleepers,"sleepers wood",!1],[p.rust,this.rustMaterial,"rails",!1],[p.head,this.headMaterial,"rail heads",!1],[p.steel,this.steelMaterial,"catenary masts",!0],[p.wire,this.wireMaterial,"catenary wires",!1]];for(const[f,z,g,D]of h){const E=i.meshOf(f,z);E&&(E.name=`railways ${g}`,E.castShadow=D,E.receiveShadow=!0,this.group.add(E))}}clear(){for(const t of[...this.group.children])this.group.remove(t),t.geometry?.dispose();this.drawn=0}dispose(){this.clear();for(const t of[this.ballastMaterial,this.earthMaterial,this.deckMaterial,this.concreteSleepers,this.woodSleepers,this.rustMaterial,this.headMaterial,this.steelMaterial,this.wireMaterial])t.dispose()}static within(t,n){if(!Number.isFinite(n))return!0;const s=n*1.1+100;return t.some((e,o)=>Math.hypot(e.x,e.z)<=s||o>0&&Math.hypot((e.x+t[o-1].x)/2,(e.z+t[o-1].z)/2)<=s)}static altitudeOffset(t,n){const s=[];for(const{line:e,path:o}of t)if(e.level===0)for(const c of o)c.altitudeM!==void 0&&s.push(n(c.x,c.z)-c.altitudeM);if(!(s.length<5))return s.sort((e,o)=>e-o),s[Math.floor(s.length/2)]}layoutOf(t,n){const s=[];for(let c=0;c<n.length-1;c++){const a=n[c],M=n[c+1],r=Math.max(1,Math.ceil(Math.hypot(M.x-a.x,M.z-a.z)/this.stepM));for(let l=0;l<r;l++){const p=l/r,h=a.altitudeM!==void 0&&M.altitudeM!==void 0?a.altitudeM+(M.altitudeM-a.altitudeM)*p:void 0;s.push({x:a.x+(M.x-a.x)*p,z:a.z+(M.z-a.z)*p,altitudeM:h})}}if(s.push(n[n.length-1]),s.length<2)return;const e=[0];for(let c=1;c<s.length;c++)e.push(e[c-1]+Math.hypot(s[c].x-s[c-1].x,s[c].z-s[c-1].z));if(e[e.length-1]<.5)return;const o=s.map((c,a)=>{const M=s[Math.max(0,a-1)],r=s[Math.min(s.length-1,a+1)],l=r.x-M.x,p=r.z-M.z,h=Math.hypot(l,p);return h<1e-6?{x:1,z:0}:{x:l/h,z:p/h}});return{kind:t.kind,...t.highSpeed?{highSpeed:!0}:{},level:t.level,centre:s,along:e,dir:o}}lay(t,n,s,e){const o=t.highSpeed?i.TRACK_SPACING_M.highSpeed:i.TRACK_SPACING_M[t.kind],c=Math.min(8,Math.max(1,t.tracks)),a=Array.from({length:c},(E,_)=>(_-(c-1)/2)*o),M=t.kind==="tram",r=M?0:i.BALLAST_HEIGHT_M,l=i.LIFT_M,p=(E,_,u)=>({x:n.centre[E].x-n.dir[E].z*_,y:n.y[E]+u,z:n.centre[E].z+n.dir[E].x*_}),h=n.centre.map((E,_)=>_);if(!M){const E=i.SLEEPER_LENGTH_M/2+i.BALLAST_SHOULDER_M+(a[a.length-1]??0),_=h.map(A=>p(A,E,r+l)),u=h.map(A=>p(A,-E,r+l));if(e.ballast.strip(_,u),t.level===0){const A=E+r*i.BALLAST_SLOPE;for(const d of[1,-1]){const v=[],x=[];let m=!1;for(const L of h){const b=p(L,d*A,l),C=s(b.x,b.z)+l,T=b.y-C;T<0&&(b.y=Math.min(C,n.y[L]+r-.05+l)),v.push(b);const B=p(L,d*(A+Math.max(0,T)*i.BANK_SLOPE),l);B.y=Math.min(s(B.x,B.z)+l,b.y),b.y-B.y>.02&&(m=!0),x.push(B)}const O=d>0?_:u;d>0?e.ballast.strip(v,O):e.ballast.strip(O,v),m&&(d>0?e.earth.strip(x,v):e.earth.strip(v,x))}}else{const A=-i.DECK_DEPTH_M,d=E+.15,v=h.map(L=>p(L,d,r+l+.1)),x=h.map(L=>p(L,-d,r+l+.1)),m=h.map(L=>p(L,d,A)),O=h.map(L=>p(L,-d,A));e.deck.strip(m,v),e.deck.strip(x,O),e.deck.strip(O,m),e.deck.strip(v,h.map(L=>p(L,E,r+l+.1))),e.deck.strip(h.map(L=>p(L,-E,r+l+.1)),x)}}const f=t.service?e.wood:e.concrete,z=t.gaugeMm/2e3+i.RAIL_HEAD_M/2,g=M?i.TRAM_RAIL_HEIGHT_M:i.RAIL_HEIGHT_M,D=r+l;for(const E of a){if(!M){const _=i.SLEEPER_LENGTH_M/2;f.strip(h.map(u=>p(u,E+_,D+.004)),h.map(u=>p(u,E-_,D+.004)),n.along)}for(const _ of[1,-1]){const u=E+_*z,A=i.RAIL_HEAD_M/2,d=h.map(x=>p(x,u+A,D+g)),v=h.map(x=>p(x,u-A,D+g));e.head.strip(d,v),e.rust.strip(h.map(x=>p(x,u+A,D)),d),e.rust.strip(v,h.map(x=>p(x,u-A,D)))}}t.electrification==="overhead"&&t.kind!=="subway"&&t.kind!=="funicular"&&this.catenary(t,n,a,D+g,p,s,e)}catenary(t,n,s,e,o,c,a){const M=t.kind==="tram"?i.CATENARY.tram:t.highSpeed?i.CATENARY.highSpeed:t.service?i.CATENARY.service:i.CATENARY.rail,r=n.along[n.along.length-1],l=Math.max(1,Math.round(r/M.spanM)),p=r/l,h=Array.from({length:l},(d,v)=>(v+.5)*p),f=e+M.contactM,z=f+M.systemM,g=(M.systemM>0?z:f)+i.MAST_ABOVE_M,D=s[s.length-1],E=s.length>2,_=s.length===1?[1]:[1,-1],u=(d,v,x)=>{let m=0,O=n.along.length-2;for(;m<O;){const T=m+O+1>>1;n.along[T]<=d?m=T:O=T-1}const L=Math.min(1,Math.max(0,(d-n.along[m])/Math.max(1e-6,n.along[m+1]-n.along[m]))),b=o(m,v,x),C=o(m+1,v,x);return{x:b.x+(C.x-b.x)*L,y:b.y+(C.y-b.y)*L,z:b.z+(C.z-b.z)*L}};for(const d of h){const v=u(d,0,f);if(!(t.level===0&&c(v.x,v.z)>v.y)){for(const x of _){const m=x*(D+i.MAST_OFFSET_M),O=u(d,m,0);t.level===0&&(O.y=Math.min(O.y,c(O.x,O.z)));const L=u(d,m,g);if(a.steel.beam(O,L,i.MAST_SIDE_M),E)continue;const C=(_.length===1?s[0]:x*D)-x*.6,T=M.systemM>0?z:f+.3;a.steel.beam(u(d,m,T),u(d,C,T),i.ARM_SIDE_M),a.steel.beam(u(d,m,f-.4),u(d,C,T),i.ARM_SIDE_M)}if(E){const x=D+i.MAST_OFFSET_M;a.steel.beam(u(d,x,g-.2),u(d,-x,g-.2),i.MAST_SIDE_M*.8)}}}const A=[0,...h,r];for(const[d,v]of s.entries()){const x=m=>m===0||m===A.length-1?0:((m+d)%2===0?1:-1)*M.staggerM;for(let m=0;m<A.length-1;m++){const O=A[m],L=A[m+1];if(L-O<.1||(a.wire.beam(u(O,v+x(m),f),u(L,v+x(m+1),f),i.CONTACT_DIAMETER_M,!1),M.systemM<=0))continue;const b=4,C=T=>{const B=m===0?.5+T/2:m===A.length-2?T/2:T;return z-i.MESSENGER_SAG_M*4*B*(1-B)};for(let T=0;T<b;T++){const B=T/b,G=(T+1)/b;a.wire.beam(u(O+(L-O)*B,v,C(B)),u(O+(L-O)*G,v,C(G)),i.MESSENGER_DIAMETER_M,!1)}}}}static meshOf(t,n){if(t.indices.length===0)return;const s=new K;return s.setAttribute("position",new N(new Float32Array(t.positions),3)),t.along.length>0&&s.setAttribute("aAlong",new N(new Float32Array(t.along),1)),s.setIndex(new N(new Uint32Array(t.indices),1)),s.computeVertexNormals(),new U(s,n)}static lambert(t,n){return new k({color:new H(...t),...n?{polygonOffset:!0,polygonOffsetFactor:-2,polygonOffsetUnits:-2}:{}})}static pebbled(t){return t.onBeforeCompile=n=>{n.vertexShader=n.vertexShader.replace("#include <common>",`#include <common>
2
- varying vec3 vBallast;`).replace("#include <begin_vertex>",`#include <begin_vertex>
3
- vBallast = position;`),n.fragmentShader=n.fragmentShader.replace("#include <common>",`#include <common>
4
- varying vec3 vBallast;
5
- float ballastHash(vec2 p) {
6
- p = fract(p * vec2(127.1, 311.7));
7
- p += dot(p, p + 34.5);
8
- return fract(p.x * p.y);
9
- }
10
- float ballastNoise(vec2 p) {
11
- vec2 i = floor(p);
12
- vec2 f = fract(p);
13
- f = f * f * (3.0 - 2.0 * f);
14
- return mix(mix(ballastHash(i), ballastHash(i + vec2(1.0, 0.0)), f.x), mix(ballastHash(i + vec2(0.0, 1.0)), ballastHash(i + vec2(1.0, 1.0)), f.x), f.y);
15
- }`).replace("#include <map_fragment>",`#include <map_fragment>
16
- {
17
- float eye = length(vViewPosition);
18
- vec2 at = vBallast.xz + vec2(0.0, vBallast.y);
19
- float stones = (ballastHash(floor(at * 22.0)) - 0.5) * 0.9 * (1.0 - smoothstep(4.0, 18.0, eye))
20
- + (ballastNoise(at * 6.0) - 0.5) * 0.5 * (1.0 - smoothstep(15.0, 60.0, eye))
21
- + (ballastNoise(at * 0.7) - 0.5) * 0.35 * (1.0 - smoothstep(80.0, 300.0, eye));
22
- diffuseColor.rgb *= 1.0 + stones;
23
- }`)},t.customProgramCacheKey=()=>"rr0-railway-ballast",t}static sleeperMaterial(t){const n=new k({color:new H(1,1,1),polygonOffset:!0,polygonOffsetFactor:-3,polygonOffsetUnits:-3}),s=new H(...t),e=new H(...i.BALLAST_ALBEDO);return n.onBeforeCompile=o=>{o.uniforms.uSleeper={value:s},o.uniforms.uCrib={value:e},o.uniforms.uSpacing={value:i.SLEEPER_SPACING_M},o.uniforms.uDuty={value:i.SLEEPER_WIDTH_M/i.SLEEPER_SPACING_M},o.vertexShader=o.vertexShader.replace("#include <common>",`#include <common>
24
- attribute float aAlong;
25
- varying float vAlong;`).replace("#include <begin_vertex>",`#include <begin_vertex>
26
- vAlong = aAlong;`),o.fragmentShader=o.fragmentShader.replace("#include <common>",`#include <common>
27
- varying float vAlong;
28
- uniform vec3 uSleeper;
29
- uniform vec3 uCrib;
30
- uniform float uSpacing;
31
- uniform float uDuty;
32
- // How much of [0, x] periods is sleeper: the integral of a pulse of width uDuty at the start of each period.
33
- float sleeperIntegral(float x) {
34
- return floor(x) * uDuty + min(fract(x), uDuty);
35
- }`).replace("#include <map_fragment>",`#include <map_fragment>
36
- {
37
- float u = vAlong / uSpacing;
38
- float w = max(fwidth(u), 1e-4);
39
- float cover = (sleeperIntegral(u + 0.5 * w) - sleeperIntegral(u - 0.5 * w)) / w;
40
- diffuseColor.rgb *= mix(uCrib, uSleeper, clamp(cover, 0.0, 1.0));
41
- }`)},n.customProgramCacheKey=()=>"rr0-railway-sleepers",n}}export{i as RailwaySystem};
@@ -1 +0,0 @@
1
- const e={event:"Evento",accountOf:"Observación de",passagesHeading:"Relatado en",interviewOf:"Entrevista a",untitledInterview:"Entrevista {n}",deleteInterviewQuestion:"¿Eliminar esta entrevista del caso? Nada se escribe hasta guardar el caso.",untitledReading:"Lectura {n}",untitledObservation:"Observación {n}",deleteRecording:"Quitar esta grabación del caso",deleteReadingQuestion:"¿Eliminar esta lectura? Nada se escribe hasta guardar el caso.",deleteObservationQuestion:"¿Eliminar esta observación del caso? Nada se escribe hasta guardar el caso.",deleteRefused:"Esta observación es interpretada por {n} lectura(s): elimínelas primero.",titleField:"Título de la interpretación",authorField:"Autor",addTitle:"Añadir un evento",kindField:"Tipo",kindObservation:"Observación",kindInterview:"Entrevista",witnessField:"Testigo",mediumField:"Medio",interviewerField:"Entrevistador",plainTitleField:"Título",sourceField:"Origen",sourceBlank:"Una grabación en blanco",sourceFile:"Un archivo JSON",sourceUrl:"Una dirección",observerField:"Testigo",fileField:"Archivo",urlField:"Dirección",loadFailed:"No se pudo leer esa grabación.",isACase:"Eso es un caso, no una grabación.",ok:"Aceptar",cancel:"Cancelar",caseHeading:"Caso",caseId:"Identificador",recordingId:"Identificador",idTaken:"Otra grabación del caso tiene este identificador.",idInvalid:"Un identificador se compone de letras, dígitos, guiones y guiones bajos, y empieza por una letra o un dígito.",idNeeded:"Una interpretación designa esta grabación por su identificador: no puede quedar vacío.",idDuplicated:"Dos eventos del caso tienen el identificador «{id}»: una interpretación que lo designa es ambigua.",readingUnresolved:"Una interpretación designa «{id}», que ningún evento del caso tiene como identificador, ni ninguna grabación que enumera.",caseTitle:"Título",caseTime:"Fecha",eventsTab:"Eventos",fileTab:"Archivo",importFile:"Cargar un archivo JSON",importUrl:"O desde una dirección",importButton:"Cargar",fileNotACase:"Ese archivo no es un caso (no tiene eventos).",fileInvalid:"Este texto aún no es JSON válido, o no es un caso: el caso conserva lo último que entendió.",fileLoading:"Cargando el editor…",add:"Añadir",addHint:"Añadir un evento",interpretationOf:"Interpretación de",interpretationOfNone:"—",exportButton:"Guardar",exportTitle:"Guardar el caso",exportAlso:"Guardar también las observaciones",addToCase:"Añadir a un caso",unsavedChanges:"Cambios sin guardar",discardQuestion:"Hay cambios que aún no se han guardado. ¿Cargar de todos modos y perderlos?",discardTitle:"Cambios sin guardar",discardOk:"Cargar de todos modos",leaveQuestion:"Hay cambios que aún no se han guardado. ¿Salir de todos modos y perderlos?",leaveOk:"Salir de todos modos"};export{e as caseEditorMessages_es};
@@ -1 +0,0 @@
1
- const e={event:"Événement",accountOf:"Observation de",passagesHeading:"Relaté dans",interviewOf:"Interview de",untitledInterview:"Interview {n}",deleteInterviewQuestion:"Supprimer cet entretien du dossier ? Rien n'est écrit avant la sauvegarde du dossier.",untitledReading:"Lecture {n}",untitledObservation:"Observation {n}",deleteRecording:"Retirer cet enregistrement du dossier",deleteReadingQuestion:"Supprimer cette lecture ? Rien n'est écrit avant la sauvegarde du dossier.",deleteObservationQuestion:"Supprimer cette observation du dossier ? Rien n'est écrit avant la sauvegarde du dossier.",deleteRefused:"Cette observation est interprétée par {n} lecture(s) : supprimez-les d'abord.",titleField:"Titre de l'interprétation",authorField:"Auteur",addTitle:"Ajouter un événement",kindField:"Type",kindObservation:"Observation",kindInterview:"Interview",witnessField:"Témoin",mediumField:"Moyen",interviewerField:"Enquêteur",plainTitleField:"Titre",sourceField:"Source",sourceBlank:"Un enregistrement vierge",sourceFile:"Un fichier JSON",sourceUrl:"Une adresse",observerField:"Témoin",fileField:"Fichier",urlField:"Adresse",loadFailed:"Cet enregistrement n'a pas pu être lu.",isACase:"C'est un dossier, pas un enregistrement.",ok:"OK",cancel:"Annuler",caseHeading:"Dossier",caseId:"Identifiant",recordingId:"Identifiant",idTaken:"Un autre enregistrement du dossier porte cet identifiant.",idInvalid:"Un identifiant est fait de lettres, de chiffres, de tirets et de soulignés, et commence par une lettre ou un chiffre.",idNeeded:"Une interprétation désigne cet enregistrement par son identifiant : il ne peut pas rester vide.",idDuplicated:"Deux événements du dossier portent l'identifiant « {id} » : une interprétation qui le désigne est ambiguë.",readingUnresolved:"Une interprétation désigne « {id} », qu'aucun événement du dossier ne porte comme identifiant, ni aucun enregistrement qu'il liste.",caseTitle:"Titre",caseTime:"Date",eventsTab:"Événements",fileTab:"Fichier",importFile:"Charger un fichier JSON",importUrl:"Ou depuis une adresse",importButton:"Charger",fileNotACase:"Ce fichier n'est pas un dossier (il n'a pas d'événements).",fileInvalid:"Ce texte n'est pas encore du JSON valide, ou pas un dossier : le dossier garde ce qu'il a compris en dernier.",fileLoading:"Chargement de l'éditeur…",add:"Ajouter",addHint:"Ajouter un événement",interpretationOf:"Interprétation de",interpretationOfNone:"—",exportButton:"Sauver",exportTitle:"Sauver le dossier",exportAlso:"Sauver aussi les observations",addToCase:"Ajouter à un dossier",unsavedChanges:"Modifications non sauvées",discardQuestion:"Des modifications ne sont pas encore sauvées. Charger quand même et les perdre ?",discardTitle:"Modifications non sauvées",discardOk:"Charger quand même",leaveQuestion:"Des modifications ne sont pas encore sauvées. Quitter quand même et les perdre ?",leaveOk:"Quitter quand même"};export{e as caseEditorMessages_fr};
@@ -1 +0,0 @@
1
- const e={event:"Evento",accountOf:"Osservazione di",passagesHeading:"Riportato in",interviewOf:"Intervista a",untitledInterview:"Intervista {n}",deleteInterviewQuestion:"Eliminare questa intervista dal caso? Nulla viene scritto prima del salvataggio del caso.",untitledReading:"Lettura {n}",untitledObservation:"Osservazione {n}",deleteRecording:"Togliere questa registrazione dal caso",deleteReadingQuestion:"Eliminare questa lettura? Nulla viene scritto prima del salvataggio del caso.",deleteObservationQuestion:"Eliminare questa osservazione dal caso? Nulla viene scritto prima del salvataggio del caso.",deleteRefused:"Questa osservazione è interpretata da {n} lettura/e: eliminale prima.",titleField:"Titolo dell'interpretazione",authorField:"Autore",addTitle:"Aggiungi un evento",kindField:"Tipo",kindObservation:"Osservazione",kindInterview:"Intervista",witnessField:"Testimone",mediumField:"Mezzo",interviewerField:"Intervistatore",plainTitleField:"Titolo",sourceField:"Origine",sourceBlank:"Una registrazione vuota",sourceFile:"Un file JSON",sourceUrl:"Un indirizzo",observerField:"Testimone",fileField:"File",urlField:"Indirizzo",loadFailed:"Impossibile leggere quella registrazione.",isACase:"Questo è un caso, non una registrazione.",ok:"OK",cancel:"Annulla",caseHeading:"Caso",caseId:"Identificativo",recordingId:"Identificativo",idTaken:"Un'altra registrazione del caso ha questo identificativo.",idInvalid:"Un identificativo è fatto di lettere, cifre, trattini e trattini bassi, e inizia con una lettera o una cifra.",idNeeded:"Un'interpretazione designa questa registrazione con il suo identificativo: non può restare vuoto.",idDuplicated:"Due eventi del caso hanno l'identificativo «{id}»: un'interpretazione che lo designa è ambigua.",readingUnresolved:"Un'interpretazione designa «{id}», che nessun evento del caso ha come identificativo, né alcuna registrazione che elenca.",caseTitle:"Titolo",caseTime:"Data",eventsTab:"Eventi",fileTab:"File",importFile:"Carica un file JSON",importUrl:"O da un indirizzo",importButton:"Carica",fileNotACase:"Quel file non è un caso (non ha eventi).",fileInvalid:"Questo testo non è ancora JSON valido, o non è un caso: il caso conserva l'ultimo che ha capito.",fileLoading:"Caricamento dell'editor…",add:"Aggiungi",addHint:"Aggiungi un evento",interpretationOf:"Interpretazione di",interpretationOfNone:"—",exportButton:"Salva",exportTitle:"Salva il caso",exportAlso:"Salva anche le osservazioni",addToCase:"Aggiungi a un caso",unsavedChanges:"Modifiche non salvate",discardQuestion:"Alcune modifiche non sono ancora state salvate. Caricare comunque e perderle?",discardTitle:"Modifiche non salvate",discardOk:"Carica comunque",leaveQuestion:"Alcune modifiche non sono ancora state salvate. Uscire comunque e perderle?",leaveOk:"Esci comunque"};export{e as caseEditorMessages_it};
@@ -1 +0,0 @@
1
- import{$ as m}from"./rr0-sighting-editor.mjs";const o=[{id:"when",paths:["time.year","time.month","time.day","time.hour","time.minute","time.raw"]},{id:"where",paths:["place.*.lat","place.*.lng","observerTrack.keyframes.*.pose.lat","observerTrack.keyframes.*.pose.lng"]},{id:"facing",paths:["observerTrack.keyframes.*.pose.headingDeg"]},{id:"apparent-size",paths:["timeline.keyframes.*.shapes.*.shape.angular.widthDeg","timeline.keyframes.*.shapes.*.shape.angular.heightDeg"]},{id:"sky-position",paths:["timeline.keyframes.*.shapes.*.shape.aim.azimuthDeg","timeline.keyframes.*.shapes.*.shape.aim.altitudeDeg"]},{id:"how-long",paths:["durationSeconds","endTime.hour","endTime.minute","endTime.raw"]},{id:"appearance",paths:["timeline.keyframes.*.shapes.*.shape.kind","timeline.keyframes.*.shapes.*.shape.title","timeline.keyframes.*.shapes.*.shape.color","timeline.keyframes.*.shapes.*.shape.brightness"]},{id:"movement",paths:["timeline.keyframes.1.t","observerTrack.keyframes.1.t"]},{id:"sound",paths:["soundTrack.keyframes.*.sound.kind"]},{id:"conditions",paths:["weatherTrack.keyframes.*.weather.*","weather.*"]}],d=["assumed","derived","stated"];class p{about="observer";async assess(t){const r=m(t),s=o.map(e=>p.answer(e,r,t));return{score:s.filter(e=>e.basis==="stated").length/s.length,criteria:s}}static answer(t,r,s){const e=t.paths.flatMap(a=>p.resolve(a,r));if(e.length===0)return{id:t.id,paths:[]};const n=e.map(a=>s.provenance.at(a)?.basis??"stated");return{id:t.id,basis:d.find(a=>n.includes(a)),paths:e}}static resolve(t,r){let s=[{path:[],value:r}];for(const e of t.split("."))s=s.flatMap(({path:n,value:a})=>{if(typeof a!="object"||a===null)return[];if(e!=="*"){const i=a[e];return i===void 0?[]:[{path:[...n,e],value:i}]}return Object.entries(a).filter(([,i])=>i!==void 0).map(([i,h])=>({path:[...n,i],value:h}))});return s.filter(({value:e})=>e!==null&&e!==""&&!(Array.isArray(e)&&e.length===0)).map(({path:e})=>e.join("."))}}export{p as CoverageAssessor};
@@ -1 +0,0 @@
1
- import{az as Le,aA as Q,aB as he,aC as Me,aD as v,aE as de,a3 as b,a6 as pe,a4 as F,aF as w,aG as U,aw as Se,aH as ye,X as be,am as K,aI as we,Z as C,aJ as me,aK as Ne,aL as ge,aM as Ie,aN as Oe,aa as V,aO as Ce,aP as Te,aQ as Fe,aR as Pe,aS as He,aT as J,aU as Re,aV as Z,aW as ke,aX as De,ap as Ge,aY as X,aZ as ve,F as Ee,av as Ue,au as G,a_ as Ke,a8 as Be,a$ as je,z as Ve,b0 as Xe,b1 as ze,b2 as qe,aq as We,G as z,Y as Ye,an as Qe,b3 as Je,b4 as Ze,b5 as $e,b6 as en,b7 as nn,b8 as tn,b9 as xe,ae as sn,ba as ne,bb as te,bc as se,bd as ie,be as re,bf as rn,bg as on,J as an,K as cn}from"./rr0-sighting-editor.mjs";function oe(f,n){if(n===Le)return console.warn("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles."),f;if(n===Q||n===he){let e=f.getIndex();if(e===null){const r=[],a=f.getAttribute("position");if(a!==void 0){for(let o=0;o<a.count;o++)r.push(o);f.setIndex(r),e=f.getIndex()}else return console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Undefined position attribute. Processing not possible."),f}const s=e.count-2,t=[];if(n===Q)for(let r=1;r<=s;r++)t.push(e.getX(0)),t.push(e.getX(r)),t.push(e.getX(r+1));else for(let r=0;r<s;r++)r%2===0?(t.push(e.getX(r)),t.push(e.getX(r+1)),t.push(e.getX(r+2))):(t.push(e.getX(r+2)),t.push(e.getX(r+1)),t.push(e.getX(r)));t.length/3!==s&&console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unable to generate correct amount of triangles.");const i=f.clone();return i.setIndex(t),i.clearGroups(),i}else return console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unknown draw mode:",n),f}class jn extends Me{constructor(n){super(n),this.dracoLoader=null,this.ktx2Loader=null,this.meshoptDecoder=null,this.pluginCallbacks=[],this.register(function(e){return new dn(e)}),this.register(function(e){return new pn(e)}),this.register(function(e){return new Ln(e)}),this.register(function(e){return new Mn(e)}),this.register(function(e){return new Sn(e)}),this.register(function(e){return new gn(e)}),this.register(function(e){return new Tn(e)}),this.register(function(e){return new Rn(e)}),this.register(function(e){return new En(e)}),this.register(function(e){return new hn(e)}),this.register(function(e){return new xn(e)}),this.register(function(e){return new mn(e)}),this.register(function(e){return new _n(e)}),this.register(function(e){return new An(e)}),this.register(function(e){return new ln(e)}),this.register(function(e){return new ae(e,g.EXT_MESHOPT_COMPRESSION)}),this.register(function(e){return new ae(e,g.KHR_MESHOPT_COMPRESSION)}),this.register(function(e){return new yn(e)})}load(n,e,s,t){const i=this;let r;if(this.resourcePath!=="")r=this.resourcePath;else if(this.path!==""){const c=v.extractUrlBase(n);r=v.resolveURL(c,this.path)}else r=v.extractUrlBase(n);this.manager.itemStart(n);const a=function(c){t?t(c):console.error(c),i.manager.itemError(n),i.manager.itemEnd(n)},o=new de(this.manager);o.setPath(this.path),o.setResponseType("arraybuffer"),o.setRequestHeader(this.requestHeader),o.setWithCredentials(this.withCredentials),o.load(n,function(c){try{i.parse(c,r,function(u){e(u),i.manager.itemEnd(n)},a)}catch(u){a(u)}},s,a)}setDRACOLoader(n){return this.dracoLoader=n,this}setKTX2Loader(n){return this.ktx2Loader=n,this}setMeshoptDecoder(n){return this.meshoptDecoder=n,this}register(n){return this.pluginCallbacks.indexOf(n)===-1&&this.pluginCallbacks.push(n),this}unregister(n){return this.pluginCallbacks.indexOf(n)!==-1&&this.pluginCallbacks.splice(this.pluginCallbacks.indexOf(n),1),this}parse(n,e,s,t){let i;const r={},a={},o=new TextDecoder;if(typeof n=="string")i=JSON.parse(n);else if(n instanceof ArrayBuffer)if(o.decode(new Uint8Array(n,0,4))===Ae){try{r[g.KHR_BINARY_GLTF]=new bn(n)}catch(l){t&&t(l);return}i=JSON.parse(r[g.KHR_BINARY_GLTF].content)}else i=JSON.parse(o.decode(n));else i=n;if(i.asset===void 0||i.asset.version[0]<2){t&&t(new Error("THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported."));return}const c=new Un(i,{path:e||this.resourcePath||"",crossOrigin:this.crossOrigin,requestHeader:this.requestHeader,manager:this.manager,ktx2Loader:this.ktx2Loader,meshoptDecoder:this.meshoptDecoder});c.fileLoader.setRequestHeader(this.requestHeader);for(let u=0;u<this.pluginCallbacks.length;u++){const l=this.pluginCallbacks[u](c);l.name||console.error("THREE.GLTFLoader: Invalid plugin found: missing name"),a[l.name]=l,r[l.name]=!0}if(i.extensionsUsed)for(let u=0;u<i.extensionsUsed.length;++u){const l=i.extensionsUsed[u],h=i.extensionsRequired||[];switch(l){case g.KHR_MATERIALS_UNLIT:r[l]=new fn;break;case g.KHR_DRACO_MESH_COMPRESSION:r[l]=new wn(i,this.dracoLoader);break;case g.KHR_TEXTURE_TRANSFORM:r[l]=new Nn;break;case g.KHR_MESH_QUANTIZATION:r[l]=new In;break;default:h.indexOf(l)>=0&&a[l]===void 0&&console.warn('THREE.GLTFLoader: Unknown extension "'+l+'".')}}c.setExtensions(r),c.setPlugins(a),c.parse(s,t)}parseAsync(n,e){const s=this;return new Promise(function(t,i){s.parse(n,e,t,i)})}}function un(){let f={};return{get:function(n){return f[n]},add:function(n,e){f[n]=e},remove:function(n){delete f[n]},removeAll:function(){f={}}}}function _(f,n,e){const s=f.json.materials[n];return s.extensions&&s.extensions[e]?s.extensions[e]:null}const g={KHR_BINARY_GLTF:"KHR_binary_glTF",KHR_DRACO_MESH_COMPRESSION:"KHR_draco_mesh_compression",KHR_LIGHTS_PUNCTUAL:"KHR_lights_punctual",KHR_MATERIALS_CLEARCOAT:"KHR_materials_clearcoat",KHR_MATERIALS_DISPERSION:"KHR_materials_dispersion",KHR_MATERIALS_IOR:"KHR_materials_ior",KHR_MATERIALS_SHEEN:"KHR_materials_sheen",KHR_MATERIALS_SPECULAR:"KHR_materials_specular",KHR_MATERIALS_TRANSMISSION:"KHR_materials_transmission",KHR_MATERIALS_IRIDESCENCE:"KHR_materials_iridescence",KHR_MATERIALS_ANISOTROPY:"KHR_materials_anisotropy",KHR_MATERIALS_UNLIT:"KHR_materials_unlit",KHR_MATERIALS_VOLUME:"KHR_materials_volume",KHR_TEXTURE_BASISU:"KHR_texture_basisu",KHR_TEXTURE_TRANSFORM:"KHR_texture_transform",KHR_MESH_QUANTIZATION:"KHR_mesh_quantization",KHR_MATERIALS_EMISSIVE_STRENGTH:"KHR_materials_emissive_strength",EXT_MATERIALS_BUMP:"EXT_materials_bump",EXT_TEXTURE_WEBP:"EXT_texture_webp",EXT_TEXTURE_AVIF:"EXT_texture_avif",EXT_MESHOPT_COMPRESSION:"EXT_meshopt_compression",KHR_MESHOPT_COMPRESSION:"KHR_meshopt_compression",EXT_MESH_GPU_INSTANCING:"EXT_mesh_gpu_instancing"};class ln{constructor(n){this.parser=n,this.name=g.KHR_LIGHTS_PUNCTUAL,this.cache={refs:{},uses:{}}}_markDefs(){const n=this.parser,e=this.parser.json.nodes||[];for(let s=0,t=e.length;s<t;s++){const i=e[s];i.extensions&&i.extensions[this.name]&&i.extensions[this.name].light!==void 0&&n._addNodeRef(this.cache,i.extensions[this.name].light)}}_loadLight(n){const e=this.parser,s="light:"+n;let t=e.cache.get(s);if(t)return t;const i=e.json,o=((i.extensions&&i.extensions[this.name]||{}).lights||[])[n];let c;const u=new F(16777215);o.color!==void 0&&u.setRGB(o.color[0],o.color[1],o.color[2],w);const l=o.range!==void 0?o.range:0;switch(o.type){case"directional":c=new be(u),c.target.position.set(0,0,-1),c.add(c.target);break;case"point":c=new ye(u),c.distance=l;break;case"spot":c=new Se(u),c.distance=l,o.spot=o.spot||{},o.spot.innerConeAngle=o.spot.innerConeAngle!==void 0?o.spot.innerConeAngle:0,o.spot.outerConeAngle=o.spot.outerConeAngle!==void 0?o.spot.outerConeAngle:Math.PI/4,c.angle=o.spot.outerConeAngle,c.penumbra=1-o.spot.innerConeAngle/o.spot.outerConeAngle,c.target.position.set(0,0,-1),c.add(c.target);break;default:throw new Error("THREE.GLTFLoader: Unexpected light type: "+o.type)}return c.position.set(0,0,0),y(c,o),o.intensity!==void 0&&(c.intensity=o.intensity),c.name=e.createUniqueName(o.name||"light_"+n),t=Promise.resolve(c),e.cache.add(s,t),t}getDependency(n,e){if(n==="light")return this._loadLight(e)}createNodeAttachment(n){const e=this,s=this.parser,i=s.json.nodes[n],a=(i.extensions&&i.extensions[this.name]||{}).light;return a===void 0?null:this._loadLight(a).then(function(o){return s._getNodeRef(e.cache,a,o)})}}class fn{constructor(){this.name=g.KHR_MATERIALS_UNLIT}getMaterialType(){return G}extendParams(n,e,s){const t=[];n.color=new F(1,1,1),n.opacity=1;const i=e.pbrMetallicRoughness;if(i){if(Array.isArray(i.baseColorFactor)){const r=i.baseColorFactor;n.color.setRGB(r[0],r[1],r[2],w),n.opacity=r[3]}i.baseColorTexture!==void 0&&t.push(s.assignTexture(n,"map",i.baseColorTexture,U))}return Promise.all(t)}}class hn{constructor(n){this.parser=n,this.name=g.KHR_MATERIALS_EMISSIVE_STRENGTH}extendMaterialParams(n,e){const s=_(this.parser,n,this.name);return s===null||s.emissiveStrength!==void 0&&(e.emissiveIntensity=s.emissiveStrength),Promise.resolve()}}class dn{constructor(n){this.parser=n,this.name=g.KHR_MATERIALS_CLEARCOAT}getMaterialType(n){return _(this.parser,n,this.name)!==null?b:null}extendMaterialParams(n,e){const s=_(this.parser,n,this.name);if(s===null)return Promise.resolve();const t=[];if(s.clearcoatFactor!==void 0&&(e.clearcoat=s.clearcoatFactor),s.clearcoatTexture!==void 0&&t.push(this.parser.assignTexture(e,"clearcoatMap",s.clearcoatTexture)),s.clearcoatRoughnessFactor!==void 0&&(e.clearcoatRoughness=s.clearcoatRoughnessFactor),s.clearcoatRoughnessTexture!==void 0&&t.push(this.parser.assignTexture(e,"clearcoatRoughnessMap",s.clearcoatRoughnessTexture)),s.clearcoatNormalTexture!==void 0&&(t.push(this.parser.assignTexture(e,"clearcoatNormalMap",s.clearcoatNormalTexture)),s.clearcoatNormalTexture.scale!==void 0)){const i=s.clearcoatNormalTexture.scale;e.clearcoatNormalScale=new pe(i,i)}return Promise.all(t)}}class pn{constructor(n){this.parser=n,this.name=g.KHR_MATERIALS_DISPERSION}getMaterialType(n){return _(this.parser,n,this.name)!==null?b:null}extendMaterialParams(n,e){const s=_(this.parser,n,this.name);return s===null||(e.dispersion=s.dispersion!==void 0?s.dispersion:0),Promise.resolve()}}class mn{constructor(n){this.parser=n,this.name=g.KHR_MATERIALS_IRIDESCENCE}getMaterialType(n){return _(this.parser,n,this.name)!==null?b:null}extendMaterialParams(n,e){const s=_(this.parser,n,this.name);if(s===null)return Promise.resolve();const t=[];return s.iridescenceFactor!==void 0&&(e.iridescence=s.iridescenceFactor),s.iridescenceTexture!==void 0&&t.push(this.parser.assignTexture(e,"iridescenceMap",s.iridescenceTexture)),s.iridescenceIor!==void 0&&(e.iridescenceIOR=s.iridescenceIor),e.iridescenceThicknessRange===void 0&&(e.iridescenceThicknessRange=[100,400]),s.iridescenceThicknessMinimum!==void 0&&(e.iridescenceThicknessRange[0]=s.iridescenceThicknessMinimum),s.iridescenceThicknessMaximum!==void 0&&(e.iridescenceThicknessRange[1]=s.iridescenceThicknessMaximum),s.iridescenceThicknessTexture!==void 0&&t.push(this.parser.assignTexture(e,"iridescenceThicknessMap",s.iridescenceThicknessTexture)),Promise.all(t)}}class gn{constructor(n){this.parser=n,this.name=g.KHR_MATERIALS_SHEEN}getMaterialType(n){return _(this.parser,n,this.name)!==null?b:null}extendMaterialParams(n,e){const s=_(this.parser,n,this.name);if(s===null)return Promise.resolve();const t=[];if(e.sheenColor=new F(0,0,0),e.sheenRoughness=0,e.sheen=1,s.sheenColorFactor!==void 0){const i=s.sheenColorFactor;e.sheenColor.setRGB(i[0],i[1],i[2],w)}return s.sheenRoughnessFactor!==void 0&&(e.sheenRoughness=s.sheenRoughnessFactor),s.sheenColorTexture!==void 0&&t.push(this.parser.assignTexture(e,"sheenColorMap",s.sheenColorTexture,U)),s.sheenRoughnessTexture!==void 0&&t.push(this.parser.assignTexture(e,"sheenRoughnessMap",s.sheenRoughnessTexture)),Promise.all(t)}}class Tn{constructor(n){this.parser=n,this.name=g.KHR_MATERIALS_TRANSMISSION}getMaterialType(n){return _(this.parser,n,this.name)!==null?b:null}extendMaterialParams(n,e){const s=_(this.parser,n,this.name);if(s===null)return Promise.resolve();const t=[];return s.transmissionFactor!==void 0&&(e.transmission=s.transmissionFactor),s.transmissionTexture!==void 0&&t.push(this.parser.assignTexture(e,"transmissionMap",s.transmissionTexture)),Promise.all(t)}}class Rn{constructor(n){this.parser=n,this.name=g.KHR_MATERIALS_VOLUME}getMaterialType(n){return _(this.parser,n,this.name)!==null?b:null}extendMaterialParams(n,e){const s=_(this.parser,n,this.name);if(s===null)return Promise.resolve();const t=[];e.thickness=s.thicknessFactor!==void 0?s.thicknessFactor:0,s.thicknessTexture!==void 0&&t.push(this.parser.assignTexture(e,"thicknessMap",s.thicknessTexture)),e.attenuationDistance=s.attenuationDistance||1/0;const i=s.attenuationColor||[1,1,1];return e.attenuationColor=new F().setRGB(i[0],i[1],i[2],w),Promise.all(t)}}class En{constructor(n){this.parser=n,this.name=g.KHR_MATERIALS_IOR}getMaterialType(n){return _(this.parser,n,this.name)!==null?b:null}extendMaterialParams(n,e){const s=_(this.parser,n,this.name);return s===null||(e.ior=s.ior!==void 0?s.ior:1.5,e.ior===0&&(e.ior=1e3)),Promise.resolve()}}class xn{constructor(n){this.parser=n,this.name=g.KHR_MATERIALS_SPECULAR}getMaterialType(n){return _(this.parser,n,this.name)!==null?b:null}extendMaterialParams(n,e){const s=_(this.parser,n,this.name);if(s===null)return Promise.resolve();const t=[];e.specularIntensity=s.specularFactor!==void 0?s.specularFactor:1,s.specularTexture!==void 0&&t.push(this.parser.assignTexture(e,"specularIntensityMap",s.specularTexture));const i=s.specularColorFactor||[1,1,1];return e.specularColor=new F().setRGB(i[0],i[1],i[2],w),s.specularColorTexture!==void 0&&t.push(this.parser.assignTexture(e,"specularColorMap",s.specularColorTexture,U)),Promise.all(t)}}class An{constructor(n){this.parser=n,this.name=g.EXT_MATERIALS_BUMP}getMaterialType(n){return _(this.parser,n,this.name)!==null?b:null}extendMaterialParams(n,e){const s=_(this.parser,n,this.name);if(s===null)return Promise.resolve();const t=[];return e.bumpScale=s.bumpFactor!==void 0?s.bumpFactor:1,s.bumpTexture!==void 0&&t.push(this.parser.assignTexture(e,"bumpMap",s.bumpTexture)),Promise.all(t)}}class _n{constructor(n){this.parser=n,this.name=g.KHR_MATERIALS_ANISOTROPY}getMaterialType(n){return _(this.parser,n,this.name)!==null?b:null}extendMaterialParams(n,e){const s=_(this.parser,n,this.name);if(s===null)return Promise.resolve();const t=[];return s.anisotropyStrength!==void 0&&(e.anisotropy=s.anisotropyStrength),s.anisotropyRotation!==void 0&&(e.anisotropyRotation=s.anisotropyRotation),s.anisotropyTexture!==void 0&&t.push(this.parser.assignTexture(e,"anisotropyMap",s.anisotropyTexture)),Promise.all(t)}}class Ln{constructor(n){this.parser=n,this.name=g.KHR_TEXTURE_BASISU}loadTexture(n){const e=this.parser,s=e.json,t=s.textures[n];if(!t.extensions||!t.extensions[this.name])return null;const i=t.extensions[this.name],r=e.options.ktx2Loader;if(!r){if(s.extensionsRequired&&s.extensionsRequired.indexOf(this.name)>=0)throw new Error("THREE.GLTFLoader: setKTX2Loader must be called before loading KTX2 textures");return null}return e.loadTextureImage(n,i.source,r)}}class Mn{constructor(n){this.parser=n,this.name=g.EXT_TEXTURE_WEBP}loadTexture(n){const e=this.name,s=this.parser,t=s.json,i=t.textures[n];if(!i.extensions||!i.extensions[e])return null;const r=i.extensions[e],a=t.images[r.source];let o=s.textureLoader;if(a.uri){const c=s.options.manager.getHandler(a.uri);c!==null&&(o=c)}return s.loadTextureImage(n,r.source,o)}}class Sn{constructor(n){this.parser=n,this.name=g.EXT_TEXTURE_AVIF}loadTexture(n){const e=this.name,s=this.parser,t=s.json,i=t.textures[n];if(!i.extensions||!i.extensions[e])return null;const r=i.extensions[e],a=t.images[r.source];let o=s.textureLoader;if(a.uri){const c=s.options.manager.getHandler(a.uri);c!==null&&(o=c)}return s.loadTextureImage(n,r.source,o)}}class ae{constructor(n,e){this.name=e,this.parser=n}loadBufferView(n){const e=this.parser.json,s=e.bufferViews[n];if(s.extensions&&s.extensions[this.name]){const t=s.extensions[this.name],i=this.parser.getDependency("buffer",t.buffer),r=this.parser.options.meshoptDecoder;if(!r||!r.supported){if(e.extensionsRequired&&e.extensionsRequired.indexOf(this.name)>=0)throw new Error("THREE.GLTFLoader: setMeshoptDecoder must be called before loading compressed files");return null}return i.then(function(a){const o=t.byteOffset||0,c=t.byteLength||0,u=t.count,l=t.byteStride,h=new Uint8Array(a,o,c);return r.decodeGltfBufferAsync?r.decodeGltfBufferAsync(u,l,h,t.mode,t.filter).then(function(d){return d.buffer}):r.ready.then(function(){const d=new ArrayBuffer(u*l);return r.decodeGltfBuffer(new Uint8Array(d),u,l,h,t.mode,t.filter),d})})}else return null}}class yn{constructor(n){this.name=g.EXT_MESH_GPU_INSTANCING,this.parser=n}createNodeMesh(n){const e=this.parser.json,s=e.nodes[n];if(!s.extensions||!s.extensions[this.name]||s.mesh===void 0)return null;const t=e.meshes[s.mesh];for(const c of t.primitives)if(c.mode!==M.TRIANGLES&&c.mode!==M.TRIANGLE_STRIP&&c.mode!==M.TRIANGLE_FAN&&c.mode!==void 0)return null;const r=s.extensions[this.name].attributes,a=[],o={};for(const c in r)a.push(this.parser.getDependency("accessor",r[c]).then(u=>(o[c]=u,o[c])));return a.length<1?null:(a.push(this.parser.createNodeMesh(n)),Promise.all(a).then(c=>{const u=c.pop(),l=u.isGroup?u.children:[u],h=c[0].count,d=[];for(const p of l){const R=new K,m=new C,T=new me,A=new C(1,1,1),x=new we(p.geometry,p.material,h);for(let E=0;E<h;E++)o.TRANSLATION&&m.fromBufferAttribute(o.TRANSLATION,E),o.ROTATION&&T.fromBufferAttribute(o.ROTATION,E),o.SCALE&&A.fromBufferAttribute(o.SCALE,E),x.setMatrixAt(E,R.compose(m,T,A));for(const E in o)if(E==="_COLOR_0"){const L=o[E];x.instanceColor=new Ne(L.array,L.itemSize,L.normalized)}else E!=="TRANSLATION"&&E!=="ROTATION"&&E!=="SCALE"&&p.geometry.setAttribute(E,o[E]);ge.prototype.copy.call(x,p),this.parser.assignFinalMaterial(x),d.push(x)}return u.isGroup?(u.clear(),u.add(...d),u):d[0]}))}}const Ae="glTF",D=12,ce={JSON:1313821514,BIN:5130562};class bn{constructor(n){this.name=g.KHR_BINARY_GLTF,this.content=null,this.body=null;const e=new DataView(n,0,D),s=new TextDecoder;if(this.header={magic:s.decode(new Uint8Array(n.slice(0,4))),version:e.getUint32(4,!0),length:e.getUint32(8,!0)},this.header.magic!==Ae)throw new Error("THREE.GLTFLoader: Unsupported glTF-Binary header.");if(this.header.version<2)throw new Error("THREE.GLTFLoader: Legacy binary file detected.");const t=this.header.length-D,i=new DataView(n,D);let r=0;for(;r<t;){const a=i.getUint32(r,!0);r+=4;const o=i.getUint32(r,!0);if(r+=4,o===ce.JSON){const c=new Uint8Array(n,D+r,a);this.content=s.decode(c)}else if(o===ce.BIN){const c=D+r;this.body=n.slice(c,c+a)}r+=a}if(this.content===null)throw new Error("THREE.GLTFLoader: JSON content not found.")}}class wn{constructor(n,e){if(!e)throw new Error("THREE.GLTFLoader: No DRACOLoader instance provided.");this.name=g.KHR_DRACO_MESH_COMPRESSION,this.json=n,this.dracoLoader=e,this.dracoLoader.preload()}decodePrimitive(n,e){const s=this.json,t=this.dracoLoader,i=n.extensions[this.name].bufferView,r=n.extensions[this.name].attributes,a={},o={},c={};for(const u in r){const l=$[u]||u.toLowerCase();a[l]=r[u]}for(const u in n.attributes){const l=$[u]||u.toLowerCase();if(r[u]!==void 0){const h=s.accessors[n.attributes[u]],d=H[h.componentType];c[l]=d.name,o[l]=h.normalized===!0}}return e.getDependency("bufferView",i).then(function(u){return new Promise(function(l,h){t.decodeDracoFile(u,function(d){for(const p in d.attributes){const R=d.attributes[p],m=o[p];m!==void 0&&(R.normalized=m)}l(d)},a,c,w,h)})})}}class Nn{constructor(){this.name=g.KHR_TEXTURE_TRANSFORM}extendTexture(n,e){return(e.texCoord===void 0||e.texCoord===n.channel)&&e.offset===void 0&&e.rotation===void 0&&e.scale===void 0||(n=n.clone(),e.texCoord!==void 0&&(n.channel=e.texCoord),e.offset!==void 0&&n.offset.fromArray(e.offset),e.rotation!==void 0&&(n.rotation=e.rotation),e.scale!==void 0&&n.repeat.fromArray(e.scale),n.needsUpdate=!0),n}}class In{constructor(){this.name=g.KHR_MESH_QUANTIZATION}}class _e extends on{constructor(n,e,s,t){super(n,e,s,t)}copySampleValue_(n){const e=this.resultBuffer,s=this.sampleValues,t=this.valueSize,i=n*t*3+t;for(let r=0;r!==t;r++)e[r]=s[i+r];return e}interpolate_(n,e,s,t){const i=this.resultBuffer,r=this.sampleValues,a=this.valueSize,o=a*2,c=a*3,u=t-e,l=(s-e)/u,h=l*l,d=h*l,p=n*c,R=p-c,m=-2*d+3*h,T=d-h,A=1-m,x=T-h+l;for(let E=0;E!==a;E++){const L=r[R+E+a],N=r[R+E+o]*u,S=r[p+E+a],k=r[p+E]*u;i[E]=A*L+x*N+m*S+T*k}return i}}const On=new me;class Cn extends _e{interpolate_(n,e,s,t){const i=super.interpolate_(n,e,s,t);return On.fromArray(i).normalize().toArray(i),i}}const M={POINTS:0,LINES:1,LINE_LOOP:2,LINE_STRIP:3,TRIANGLES:4,TRIANGLE_STRIP:5,TRIANGLE_FAN:6},H={5120:Int8Array,5121:Uint8Array,5122:Int16Array,5123:Uint16Array,5125:Uint32Array,5126:Float32Array},ue={9728:Re,9729:J,9984:He,9985:Pe,9986:Fe,9987:Te},le={33071:De,33648:ke,10497:Z},q={SCALAR:1,VEC2:2,VEC3:3,VEC4:4,MAT2:4,MAT3:9,MAT4:16},$={POSITION:"position",NORMAL:"normal",TANGENT:"tangent",TEXCOORD_0:"uv",TEXCOORD_1:"uv1",TEXCOORD_2:"uv2",TEXCOORD_3:"uv3",COLOR_0:"color",WEIGHTS_0:"skinWeight",JOINTS_0:"skinIndex"},I={scale:"scale",translation:"position",rotation:"quaternion",weights:"morphTargetInfluences"},Fn={CUBICSPLINE:void 0,LINEAR:xe,STEP:tn},W={OPAQUE:"OPAQUE",MASK:"MASK",BLEND:"BLEND"};function Pn(f){return f.DefaultMaterial===void 0&&(f.DefaultMaterial=new Ee({color:16777215,emissive:0,metalness:1,roughness:1,transparent:!1,depthTest:!0,side:rn})),f.DefaultMaterial}function O(f,n,e){for(const s in e.extensions)f[s]===void 0&&(n.userData.gltfExtensions=n.userData.gltfExtensions||{},n.userData.gltfExtensions[s]=e.extensions[s])}function y(f,n){n.extras!==void 0&&(typeof n.extras=="object"?Object.assign(f.userData,n.extras):console.warn("THREE.GLTFLoader: Ignoring primitive type .extras, "+n.extras))}function Hn(f,n,e){let s=!1,t=!1,i=!1;for(let c=0,u=n.length;c<u;c++){const l=n[c];if(l.POSITION!==void 0&&(s=!0),l.NORMAL!==void 0&&(t=!0),l.COLOR_0!==void 0&&(i=!0),s&&t&&i)break}if(!s&&!t&&!i)return Promise.resolve(f);const r=[],a=[],o=[];for(let c=0,u=n.length;c<u;c++){const l=n[c];if(s){const h=l.POSITION!==void 0?e.getDependency("accessor",l.POSITION):f.attributes.position;r.push(h)}if(t){const h=l.NORMAL!==void 0?e.getDependency("accessor",l.NORMAL):f.attributes.normal;a.push(h)}if(i){const h=l.COLOR_0!==void 0?e.getDependency("accessor",l.COLOR_0):f.attributes.color;o.push(h)}}return Promise.all([Promise.all(r),Promise.all(a),Promise.all(o)]).then(function(c){const u=c[0],l=c[1],h=c[2];return s&&(f.morphAttributes.position=u),t&&(f.morphAttributes.normal=l),i&&(f.morphAttributes.color=h),f.morphTargetsRelative=!0,f})}function kn(f,n){if(f.updateMorphTargets(),n.weights!==void 0)for(let e=0,s=n.weights.length;e<s;e++)f.morphTargetInfluences[e]=n.weights[e];if(n.extras&&Array.isArray(n.extras.targetNames)){const e=n.extras.targetNames;if(f.morphTargetInfluences.length===e.length){f.morphTargetDictionary={};for(let s=0,t=e.length;s<t;s++)f.morphTargetDictionary[e[s]]=s}else console.warn("THREE.GLTFLoader: Invalid extras.targetNames length. Ignoring names.")}}function Dn(f){let n;const e=f.extensions&&f.extensions[g.KHR_DRACO_MESH_COMPRESSION];if(e?n="draco:"+e.bufferView+":"+e.indices+":"+Y(e.attributes):n=f.indices+":"+Y(f.attributes)+":"+f.mode,f.targets!==void 0)for(let s=0,t=f.targets.length;s<t;s++)n+=":"+Y(f.targets[s]);return n}function Y(f){let n="";const e=Object.keys(f).sort();for(let s=0,t=e.length;s<t;s++)n+=e[s]+":"+f[e[s]]+";";return n}function ee(f){switch(f){case Int8Array:return 1/127;case Uint8Array:return 1/255;case Int16Array:return 1/32767;case Uint16Array:return 1/65535;default:throw new Error("THREE.GLTFLoader: Unsupported normalized accessor component type.")}}function Gn(f){return f.search(/\.jpe?g($|\?)/i)>0||f.search(/^data\:image\/jpeg/)===0?"image/jpeg":f.search(/\.webp($|\?)/i)>0||f.search(/^data\:image\/webp/)===0?"image/webp":f.search(/\.ktx2($|\?)/i)>0||f.search(/^data\:image\/ktx2/)===0?"image/ktx2":"image/png"}const vn=new K;class Un{constructor(n={},e={}){this.json=n,this.extensions={},this.plugins={},this.options=e,this.cache=new un,this.associations=new Map,this.primitiveCache={},this.nodeCache={},this.meshCache={refs:{},uses:{}},this.cameraCache={refs:{},uses:{}},this.lightCache={refs:{},uses:{}},this.sourceCache={},this.textureCache={},this.nodeNamesUsed={};let s=!1,t=-1,i=!1,r=-1;if(typeof navigator<"u"&&typeof navigator.userAgent<"u"){const a=navigator.userAgent;s=/^((?!chrome|android).)*safari/i.test(a)===!0;const o=a.match(/Version\/(\d+)/);t=s&&o?parseInt(o[1],10):-1,i=a.indexOf("Firefox")>-1,r=i?a.match(/Firefox\/([0-9]+)\./)[1]:-1}typeof createImageBitmap>"u"||s&&t<17||i&&r<98?this.textureLoader=new Ie(this.options.manager):this.textureLoader=new Oe(this.options.manager),this.textureLoader.setCrossOrigin(this.options.crossOrigin),this.textureLoader.setRequestHeader(this.options.requestHeader),this.fileLoader=new de(this.options.manager),this.fileLoader.setResponseType("arraybuffer"),this.options.crossOrigin==="use-credentials"&&this.fileLoader.setWithCredentials(!0)}setExtensions(n){this.extensions=n}setPlugins(n){this.plugins=n}parse(n,e){const s=this,t=this.json,i=this.extensions;this.cache.removeAll(),this.nodeCache={},this._invokeAll(function(r){return r._markDefs&&r._markDefs()}),Promise.all(this._invokeAll(function(r){return r.beforeRoot&&r.beforeRoot()})).then(function(){return Promise.all([s.getDependencies("scene"),s.getDependencies("animation"),s.getDependencies("camera")])}).then(function(r){const a={scene:r[0][t.scene||0],scenes:r[0],animations:r[1],cameras:r[2],asset:t.asset,parser:s,userData:{}};return O(i,a,t),y(a,t),Promise.all(s._invokeAll(function(o){return o.afterRoot&&o.afterRoot(a)})).then(function(){for(const o of a.scenes)o.updateMatrixWorld();n(a)})}).catch(e)}_markDefs(){const n=this.json.nodes||[],e=this.json.skins||[],s=this.json.meshes||[];for(let t=0,i=e.length;t<i;t++){const r=e[t].joints;for(let a=0,o=r.length;a<o;a++)n[r[a]].isBone=!0}for(let t=0,i=n.length;t<i;t++){const r=n[t];r.mesh!==void 0&&(this._addNodeRef(this.meshCache,r.mesh),r.skin!==void 0&&(s[r.mesh].isSkinnedMesh=!0)),r.camera!==void 0&&this._addNodeRef(this.cameraCache,r.camera)}}_addNodeRef(n,e){e!==void 0&&(n.refs[e]===void 0&&(n.refs[e]=n.uses[e]=0),n.refs[e]++)}_getNodeRef(n,e,s){if(n.refs[e]<=1)return s;const t=s.clone(),i=(r,a)=>{const o=this.associations.get(r);o!=null&&this.associations.set(a,o);for(const[c,u]of r.children.entries())i(u,a.children[c])};return i(s,t),t.name+="_instance_"+n.uses[e]++,t}_invokeOne(n){const e=Object.values(this.plugins);e.push(this);for(let s=0;s<e.length;s++){const t=n(e[s]);if(t)return t}return null}_invokeAll(n){const e=Object.values(this.plugins);e.unshift(this);const s=[];for(let t=0;t<e.length;t++){const i=n(e[t]);i&&s.push(i)}return s}getDependency(n,e){const s=n+":"+e;let t=this.cache.get(s);if(!t){switch(n){case"scene":t=this.loadScene(e);break;case"node":t=this._invokeOne(function(i){return i.loadNode&&i.loadNode(e)});break;case"mesh":t=this._invokeOne(function(i){return i.loadMesh&&i.loadMesh(e)});break;case"accessor":t=this.loadAccessor(e);break;case"bufferView":t=this._invokeOne(function(i){return i.loadBufferView&&i.loadBufferView(e)});break;case"buffer":t=this.loadBuffer(e);break;case"material":t=this._invokeOne(function(i){return i.loadMaterial&&i.loadMaterial(e)});break;case"texture":t=this._invokeOne(function(i){return i.loadTexture&&i.loadTexture(e)});break;case"skin":t=this.loadSkin(e);break;case"animation":t=this._invokeOne(function(i){return i.loadAnimation&&i.loadAnimation(e)});break;case"camera":t=this.loadCamera(e);break;default:if(t=this._invokeOne(function(i){return i!=this&&i.getDependency&&i.getDependency(n,e)}),!t)throw new Error("Unknown type: "+n);break}this.cache.add(s,t)}return t}getDependencies(n){let e=this.cache.get(n);if(!e){const s=this,t=this.json[n+(n==="mesh"?"es":"s")]||[];e=Promise.all(t.map(function(i,r){return s.getDependency(n,r)})),this.cache.add(n,e)}return e}loadBuffer(n){const e=this.json.buffers[n],s=this.fileLoader;if(e.type&&e.type!=="arraybuffer")throw new Error("THREE.GLTFLoader: "+e.type+" buffer type is not supported.");if(e.uri===void 0&&n===0)return Promise.resolve(this.extensions[g.KHR_BINARY_GLTF].body);const t=this.options;return new Promise(function(i,r){s.load(v.resolveURL(e.uri,t.path),i,void 0,function(){r(new Error('THREE.GLTFLoader: Failed to load buffer "'+e.uri+'".'))})})}loadBufferView(n){const e=this.json.bufferViews[n];return this.getDependency("buffer",e.buffer).then(function(s){const t=e.byteLength||0,i=e.byteOffset||0;return s.slice(i,i+t)})}loadAccessor(n){const e=this,s=this.json,t=this.json.accessors[n];if(t.bufferView===void 0&&t.sparse===void 0){const r=q[t.type],a=H[t.componentType],o=t.normalized===!0,c=new a(t.count*r);return Promise.resolve(new V(c,r,o))}const i=[];return t.bufferView!==void 0?i.push(this.getDependency("bufferView",t.bufferView)):i.push(null),t.sparse!==void 0&&(i.push(this.getDependency("bufferView",t.sparse.indices.bufferView)),i.push(this.getDependency("bufferView",t.sparse.values.bufferView))),Promise.all(i).then(function(r){const a=r[0],o=q[t.type],c=H[t.componentType],u=c.BYTES_PER_ELEMENT,l=u*o,h=t.byteOffset||0,d=t.bufferView!==void 0?s.bufferViews[t.bufferView].byteStride:void 0,p=t.normalized===!0;let R,m;if(d&&d!==l){const T=Math.floor(h/d),A="InterleavedBuffer:"+t.bufferView+":"+t.componentType+":"+T+":"+t.count;let x=e.cache.get(A);x||(R=new c(a,T*d,t.count*d/u),x=new Ce(R,d/u),e.cache.add(A,x)),m=new sn(x,o,h%d/u,p)}else a===null?R=new c(t.count*o):R=new c(a,h,t.count*o),m=new V(R,o,p);if(t.sparse!==void 0){const T=q.SCALAR,A=H[t.sparse.indices.componentType],x=t.sparse.indices.byteOffset||0,E=t.sparse.values.byteOffset||0,L=new A(r[1],x,t.sparse.count*T),N=new c(r[2],E,t.sparse.count*o);a!==null&&(m=new V(m.array.slice(),m.itemSize,m.normalized)),m.normalized=!1;for(let S=0,k=L.length;S<k;S++){const P=L[S];if(m.setX(P,N[S*o]),o>=2&&m.setY(P,N[S*o+1]),o>=3&&m.setZ(P,N[S*o+2]),o>=4&&m.setW(P,N[S*o+3]),o>=5)throw new Error("THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute.")}m.normalized=p}return m})}loadTexture(n){const e=this.json,s=this.options,i=e.textures[n].source,r=e.images[i];let a=this.textureLoader;if(r.uri){const o=s.manager.getHandler(r.uri);o!==null&&(a=o)}return this.loadTextureImage(n,i,a)}loadTextureImage(n,e,s){const t=this,i=this.json,r=i.textures[n],a=i.images[e],o=(a.uri||a.bufferView)+":"+r.sampler;if(this.textureCache[o])return this.textureCache[o];const c=this.loadImageSource(e,s).then(function(u){u.flipY=!1,u.name=r.name||a.name||"",u.name===""&&typeof a.uri=="string"&&a.uri.startsWith("data:image/")===!1&&(u.name=a.uri);const h=(i.samplers||{})[r.sampler]||{};return u.magFilter=ue[h.magFilter]||J,u.minFilter=ue[h.minFilter]||Te,u.wrapS=le[h.wrapS]||Z,u.wrapT=le[h.wrapT]||Z,u.generateMipmaps=!u.isCompressedTexture&&u.minFilter!==Re&&u.minFilter!==J,t.associations.set(u,{textures:n}),u}).catch(function(){return null});return this.textureCache[o]=c,c}loadImageSource(n,e){const s=this,t=this.json,i=this.options;if(this.sourceCache[n]!==void 0)return this.sourceCache[n].then(l=>l.clone());const r=t.images[n],a=self.URL||self.webkitURL;let o=r.uri||"",c=!1;if(r.bufferView!==void 0)o=s.getDependency("bufferView",r.bufferView).then(function(l){c=!0;const h=new Blob([l],{type:r.mimeType});return o=a.createObjectURL(h),o});else if(r.uri===void 0)throw new Error("THREE.GLTFLoader: Image "+n+" is missing URI and bufferView");const u=Promise.resolve(o).then(function(l){return new Promise(function(h,d){let p=h;e.isImageBitmapLoader===!0&&(p=function(R){const m=new ne(R);m.needsUpdate=!0,h(m)}),e.load(v.resolveURL(l,i.path),p,void 0,d)})}).then(function(l){return c===!0&&a.revokeObjectURL(o),y(l,r),l.userData.mimeType=r.mimeType||Gn(r.uri),l}).catch(function(l){throw console.error("THREE.GLTFLoader: Couldn't load texture",o),l});return this.sourceCache[n]=u,u}assignTexture(n,e,s,t){const i=this;return this.getDependency("texture",s.index).then(function(r){if(!r)return null;if(s.texCoord!==void 0&&s.texCoord>0&&(r=r.clone(),r.channel=s.texCoord),i.extensions[g.KHR_TEXTURE_TRANSFORM]){const a=s.extensions!==void 0?s.extensions[g.KHR_TEXTURE_TRANSFORM]:void 0;if(a){const o=i.associations.get(r);r=i.extensions[g.KHR_TEXTURE_TRANSFORM].extendTexture(r,a),i.associations.set(r,o)}}return t!==void 0&&(r.colorSpace=t),n[e]=r,r})}assignFinalMaterial(n){const e=n.geometry;let s=n.material;const t=e.attributes.tangent===void 0,i=e.attributes.color!==void 0,r=e.attributes.normal===void 0;if(n.isPoints){const a="PointsMaterial:"+s.uuid;let o=this.cache.get(a);o||(o=new Ge,X.prototype.copy.call(o,s),o.color.copy(s.color),o.map=s.map,o.sizeAttenuation=!1,this.cache.add(a,o)),s=o}else if(n.isLine){const a="LineBasicMaterial:"+s.uuid;let o=this.cache.get(a);o||(o=new ve,X.prototype.copy.call(o,s),o.color.copy(s.color),o.map=s.map,this.cache.add(a,o)),s=o}if(t||i||r){let a="ClonedMaterial:"+s.uuid+":";t&&(a+="derivative-tangents:"),i&&(a+="vertex-colors:"),r&&(a+="flat-shading:");let o=this.cache.get(a);o||(o=s.clone(),i&&(o.vertexColors=!0),r&&(o.flatShading=!0),t&&(o.normalScale&&(o.normalScale.y*=-1),o.clearcoatNormalScale&&(o.clearcoatNormalScale.y*=-1)),this.cache.add(a,o),this.associations.set(o,this.associations.get(s))),s=o}n.material=s}getMaterialType(){return Ee}loadMaterial(n){const e=this,s=this.json,t=this.extensions,i=s.materials[n];let r;const a={},o=i.extensions||{},c=[];if(o[g.KHR_MATERIALS_UNLIT]){const l=t[g.KHR_MATERIALS_UNLIT];r=l.getMaterialType(),c.push(l.extendParams(a,i,e))}else{const l=i.pbrMetallicRoughness||{};if(a.color=new F(1,1,1),a.opacity=1,Array.isArray(l.baseColorFactor)){const h=l.baseColorFactor;a.color.setRGB(h[0],h[1],h[2],w),a.opacity=h[3]}l.baseColorTexture!==void 0&&c.push(e.assignTexture(a,"map",l.baseColorTexture,U)),a.metalness=l.metallicFactor!==void 0?l.metallicFactor:1,a.roughness=l.roughnessFactor!==void 0?l.roughnessFactor:1,l.metallicRoughnessTexture!==void 0&&(c.push(e.assignTexture(a,"metalnessMap",l.metallicRoughnessTexture)),c.push(e.assignTexture(a,"roughnessMap",l.metallicRoughnessTexture))),r=this._invokeOne(function(h){return h.getMaterialType&&h.getMaterialType(n)}),c.push(Promise.all(this._invokeAll(function(h){return h.extendMaterialParams&&h.extendMaterialParams(n,a)})))}i.doubleSided===!0&&(a.side=Ue);const u=i.alphaMode||W.OPAQUE;if(u===W.BLEND?(a.transparent=!0,a.depthWrite=!1):(a.transparent=!1,u===W.MASK&&(a.alphaTest=i.alphaCutoff!==void 0?i.alphaCutoff:.5)),i.normalTexture!==void 0&&r!==G&&(c.push(e.assignTexture(a,"normalMap",i.normalTexture)),a.normalScale=new pe(1,1),i.normalTexture.scale!==void 0)){const l=i.normalTexture.scale;a.normalScale.set(l,l)}if(i.occlusionTexture!==void 0&&r!==G&&(c.push(e.assignTexture(a,"aoMap",i.occlusionTexture)),i.occlusionTexture.strength!==void 0&&(a.aoMapIntensity=i.occlusionTexture.strength)),i.emissiveFactor!==void 0&&r!==G){const l=i.emissiveFactor;a.emissive=new F().setRGB(l[0],l[1],l[2],w)}return i.emissiveTexture!==void 0&&r!==G&&c.push(e.assignTexture(a,"emissiveMap",i.emissiveTexture,U)),Promise.all(c).then(function(){const l=new r(a);return i.name&&(l.name=i.name),y(l,i),e.associations.set(l,{materials:n}),i.extensions&&O(t,l,i),l})}createUniqueName(n){const e=Ke.sanitizeNodeName(n||"");return e in this.nodeNamesUsed?e+"_"+ ++this.nodeNamesUsed[e]:(this.nodeNamesUsed[e]=0,e)}loadGeometries(n){const e=this,s=this.extensions,t=this.primitiveCache;function i(a){return s[g.KHR_DRACO_MESH_COMPRESSION].decodePrimitive(a,e).then(function(o){return fe(o,a,e)})}const r=[];for(let a=0,o=n.length;a<o;a++){const c=n[a],u=Dn(c),l=t[u];if(l)r.push(l.promise);else{let h;c.extensions&&c.extensions[g.KHR_DRACO_MESH_COMPRESSION]?h=i(c):h=fe(new Be,c,e),t[u]={primitive:c,promise:h},r.push(h)}}return Promise.all(r)}loadMesh(n){const e=this,s=this.json,t=this.extensions,i=s.meshes[n],r=i.primitives,a=[];for(let o=0,c=r.length;o<c;o++){const u=r[o].material===void 0?Pn(this.cache):this.getDependency("material",r[o].material);a.push(u)}return a.push(e.loadGeometries(r)),Promise.all(a).then(function(o){const c=o.slice(0,o.length-1),u=o[o.length-1],l=[];for(let d=0,p=u.length;d<p;d++){const R=u[d],m=r[d];let T;const A=c[d];if(m.mode===M.TRIANGLES||m.mode===M.TRIANGLE_STRIP||m.mode===M.TRIANGLE_FAN||m.mode===void 0)T=i.isSkinnedMesh===!0?new je(R,A):new Ve(R,A),T.isSkinnedMesh===!0&&T.normalizeSkinWeights(),m.mode===M.TRIANGLE_STRIP?T.geometry=oe(T.geometry,he):m.mode===M.TRIANGLE_FAN&&(T.geometry=oe(T.geometry,Q));else if(m.mode===M.LINES)T=new Xe(R,A);else if(m.mode===M.LINE_STRIP)T=new ze(R,A);else if(m.mode===M.LINE_LOOP)T=new qe(R,A);else if(m.mode===M.POINTS)T=new We(R,A);else throw new Error("THREE.GLTFLoader: Primitive mode unsupported: "+m.mode);Object.keys(T.geometry.morphAttributes).length>0&&kn(T,i),T.name=e.createUniqueName(i.name||"mesh_"+n),y(T,i),m.extensions&&O(t,T,m),e.assignFinalMaterial(T),l.push(T)}for(let d=0,p=l.length;d<p;d++)e.associations.set(l[d],{meshes:n,primitives:d});if(l.length===1)return i.extensions&&O(t,l[0],i),l[0];const h=new z;i.extensions&&O(t,h,i),e.associations.set(h,{meshes:n});for(let d=0,p=l.length;d<p;d++)h.add(l[d]);return h})}loadCamera(n){let e;const s=this.json.cameras[n],t=s[s.type];if(!t){console.warn("THREE.GLTFLoader: Missing camera parameters.");return}return s.type==="perspective"?e=new Ye(Qe.radToDeg(t.yfov),t.aspectRatio||1,t.znear||1,t.zfar||2e6):s.type==="orthographic"&&(e=new Je(-t.xmag,t.xmag,t.ymag,-t.ymag,t.znear,t.zfar)),s.name&&(e.name=this.createUniqueName(s.name)),y(e,s),Promise.resolve(e)}loadSkin(n){const e=this.json.skins[n],s=[];for(let t=0,i=e.joints.length;t<i;t++)s.push(this._loadNodeShallow(e.joints[t]));return e.inverseBindMatrices!==void 0?s.push(this.getDependency("accessor",e.inverseBindMatrices)):s.push(null),Promise.all(s).then(function(t){const i=t.pop(),r=t,a=[],o=[];for(let c=0,u=r.length;c<u;c++){const l=r[c];if(l){a.push(l);const h=new K;i!==null&&h.fromArray(i.array,c*16),o.push(h)}else console.warn('THREE.GLTFLoader: Joint "%s" could not be found.',e.joints[c])}return new Ze(a,o)})}loadAnimation(n){const e=this.json,s=this,t=e.animations[n],i=t.name?t.name:"animation_"+n,r=[],a=[],o=[],c=[],u=[];for(let l=0,h=t.channels.length;l<h;l++){const d=t.channels[l],p=t.samplers[d.sampler],R=d.target,m=R.node,T=t.parameters!==void 0?t.parameters[p.input]:p.input,A=t.parameters!==void 0?t.parameters[p.output]:p.output;R.node!==void 0&&(r.push(this.getDependency("node",m)),a.push(this.getDependency("accessor",T)),o.push(this.getDependency("accessor",A)),c.push(p),u.push(R))}return Promise.all([Promise.all(r),Promise.all(a),Promise.all(o),Promise.all(c),Promise.all(u)]).then(function(l){const h=l[0],d=l[1],p=l[2],R=l[3],m=l[4],T=[];for(let x=0,E=h.length;x<E;x++){const L=h[x],N=d[x],S=p[x],k=R[x],P=m[x];if(L===void 0)continue;L.updateMatrix&&L.updateMatrix();const B=s._createAnimationTracks(L,N,S,k,P);if(B)for(let j=0;j<B.length;j++)T.push(B[j])}const A=new $e(i,void 0,T);return y(A,t),A})}createNodeMesh(n){const e=this.json,s=this,t=e.nodes[n];return t.mesh===void 0?null:s.getDependency("mesh",t.mesh).then(function(i){const r=s._getNodeRef(s.meshCache,t.mesh,i);return t.weights!==void 0&&r.traverse(function(a){if(a.isMesh)for(let o=0,c=t.weights.length;o<c;o++)a.morphTargetInfluences[o]=t.weights[o]}),r})}loadNode(n){const e=this.json,s=this,t=e.nodes[n],i=s._loadNodeShallow(n),r=[],a=t.children||[];for(let c=0,u=a.length;c<u;c++)r.push(s.getDependency("node",a[c]));const o=t.skin===void 0?Promise.resolve(null):s.getDependency("skin",t.skin);return Promise.all([i,Promise.all(r),o]).then(function(c){const u=c[0],l=c[1],h=c[2];h!==null&&u.traverse(function(d){d.isSkinnedMesh&&d.bind(h,vn)});for(let d=0,p=l.length;d<p;d++)u.add(l[d]);if(u.userData.pivot!==void 0&&l.length>0){const d=u.userData.pivot,p=l[0];u.pivot=new C().fromArray(d),u.position.x-=d[0],u.position.y-=d[1],u.position.z-=d[2],p.position.set(0,0,0),delete u.userData.pivot}return u})}_loadNodeShallow(n){const e=this.json,s=this.extensions,t=this;if(this.nodeCache[n]!==void 0)return this.nodeCache[n];const i=e.nodes[n],r=i.name?t.createUniqueName(i.name):"",a=[],o=t._invokeOne(function(c){return c.createNodeMesh&&c.createNodeMesh(n)});return o&&a.push(o),i.camera!==void 0&&a.push(t.getDependency("camera",i.camera).then(function(c){return t._getNodeRef(t.cameraCache,i.camera,c)})),t._invokeAll(function(c){return c.createNodeAttachment&&c.createNodeAttachment(n)}).forEach(function(c){a.push(c)}),this.nodeCache[n]=Promise.all(a).then(function(c){let u;if(i.isBone===!0?u=new en:c.length>1?u=new z:c.length===1?u=c[0]:u=new ge,u!==c[0])for(let l=0,h=c.length;l<h;l++)u.add(c[l]);if(i.name&&(u.userData.name=i.name,u.name=r),y(u,i),i.extensions&&O(s,u,i),i.matrix!==void 0){const l=new K;l.fromArray(i.matrix),u.applyMatrix4(l)}else i.translation!==void 0&&u.position.fromArray(i.translation),i.rotation!==void 0&&u.quaternion.fromArray(i.rotation),i.scale!==void 0&&u.scale.fromArray(i.scale);if(!t.associations.has(u))t.associations.set(u,{});else if(i.mesh!==void 0&&t.meshCache.refs[i.mesh]>1){const l=t.associations.get(u);t.associations.set(u,{...l})}return t.associations.get(u).nodes=n,u}),this.nodeCache[n]}loadScene(n){const e=this.extensions,s=this.json.scenes[n],t=this,i=new z;s.name&&(i.name=t.createUniqueName(s.name)),y(i,s),s.extensions&&O(e,i,s);const r=s.nodes||[],a=[];for(let o=0,c=r.length;o<c;o++)a.push(t.getDependency("node",r[o]));return Promise.all(a).then(function(o){for(let u=0,l=o.length;u<l;u++){const h=o[u];h.parent!==null?i.add(nn(h)):i.add(h)}const c=u=>{const l=new Map;for(const[h,d]of t.associations)(h instanceof X||h instanceof ne)&&l.set(h,d);return u.traverse(h=>{const d=t.associations.get(h);d!=null&&l.set(h,d)}),l};return t.associations=c(i),i})}_createAnimationTracks(n,e,s,t,i){const r=[],a=n.name?n.name:n.uuid,o=[];function c(d){d.morphTargetInfluences&&o.push(d.name?d.name:d.uuid)}I[i.path]===I.weights?(c(n),n.isGroup&&n.children.forEach(c)):o.push(a);let u;switch(I[i.path]){case I.weights:u=se;break;case I.rotation:u=ie;break;case I.translation:case I.scale:u=te;break;default:switch(s.itemSize){case 1:u=se;break;case 2:case 3:default:u=te;break}break}const l=t.interpolation!==void 0?Fn[t.interpolation]:xe,h=this._getArrayFromAccessor(s);for(let d=0,p=o.length;d<p;d++){const R=new u(o[d]+"."+I[i.path],e.array,h,l);t.interpolation==="CUBICSPLINE"&&this._createCubicSplineTrackInterpolant(R),r.push(R)}return r}_getArrayFromAccessor(n){let e=n.array;if(n.normalized){const s=ee(e.constructor),t=new Float32Array(e.length);for(let i=0,r=e.length;i<r;i++)t[i]=e[i]*s;e=t}return e}_createCubicSplineTrackInterpolant(n){n.createInterpolant=function(s){const t=this instanceof ie?Cn:_e;return new t(this.times,this.values,this.getValueSize()/3,s)},n.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline=!0}}function Kn(f,n,e){const s=n.attributes,t=new an;if(s.POSITION!==void 0){const a=e.json.accessors[s.POSITION],o=a.min,c=a.max;if(o!==void 0&&c!==void 0){if(t.set(new C(o[0],o[1],o[2]),new C(c[0],c[1],c[2])),a.normalized){const u=ee(H[a.componentType]);t.min.multiplyScalar(u),t.max.multiplyScalar(u)}}else{console.warn("THREE.GLTFLoader: Missing min/max properties for accessor POSITION.");return}}else return;const i=n.targets;if(i!==void 0){const a=new C,o=new C;for(let c=0,u=i.length;c<u;c++){const l=i[c];if(l.POSITION!==void 0){const h=e.json.accessors[l.POSITION],d=h.min,p=h.max;if(d!==void 0&&p!==void 0){if(o.setX(Math.max(Math.abs(d[0]),Math.abs(p[0]))),o.setY(Math.max(Math.abs(d[1]),Math.abs(p[1]))),o.setZ(Math.max(Math.abs(d[2]),Math.abs(p[2]))),h.normalized){const R=ee(H[h.componentType]);o.multiplyScalar(R)}a.max(o)}else console.warn("THREE.GLTFLoader: Missing min/max properties for accessor POSITION.")}}t.expandByVector(a)}f.boundingBox=t;const r=new cn;t.getCenter(r.center),r.radius=t.min.distanceTo(t.max)/2,f.boundingSphere=r}function fe(f,n,e){const s=n.attributes,t=[];function i(r,a){return e.getDependency("accessor",r).then(function(o){f.setAttribute(a,o)})}for(const r in s){const a=$[r]||r.toLowerCase();a in f.attributes||t.push(i(s[r],a))}if(n.indices!==void 0&&!f.index){const r=e.getDependency("accessor",n.indices).then(function(a){f.setIndex(a)});t.push(r)}return re.workingColorSpace!==w&&"COLOR_0"in s&&console.warn(`THREE.GLTFLoader: Converting vertex colors from "srgb-linear" to "${re.workingColorSpace}" not supported.`),y(f,n),Kn(f,n,e),Promise.all(t).then(function(){return n.targets!==void 0?Hn(f,n.targets,e):f})}export{jn as GLTFLoader};
@@ -1,34 +0,0 @@
1
- import{aw as b,z as g,Z as P,ax as m,a8 as C,aa as x,ag as E,a4 as L,av as R,ay as I}from"./rr0-sighting-editor.mjs";class i{constructor(e){this.scene=e}static REAL_BEAMS=4;static LAMPS=2;static DISTANCE_M=500;static AIR_LENGTH_M=90;static CLEAR_AIR_SCATTER_PER_M=2e-4;static SHADOW_MAP_PX=1024;beams=new Map;static airGeometry;has(e){return this.beams.has(e)}get size(){return this.beams.size}lamps(e){return this.beams.get(e)?.lamps??[]}airMeshes(e){return this.beams.get(e)?.air??[]}add(e){if(this.beams.has(e))return!0;if(this.beams.size>=i.REAL_BEAMS)return!1;const t=[],r=[];for(let n=0;n<i.LAMPS;n++){const a=new b(16777215,0,i.DISTANCE_M,Math.PI/8,.5,2);a.castShadow=e==="observer",a.shadow.mapSize.set(i.SHADOW_MAP_PX,i.SHADOW_MAP_PX),a.shadow.camera.near=.4,a.shadow.camera.far=110,a.shadow.bias=-4e-4,a.shadow.normalBias=.04,a.shadow.radius=2,this.scene.add(a),this.scene.add(a.target),t.push(a);const o=new g(i.airCone(),i.airMaterial());o.visible=!1,o.frustumCulled=!1,o.renderOrder=8,o.castShadow=!1,o.receiveShadow=!1,o.name="headlight air",this.scene.add(o),r.push(o)}return this.beams.set(e,{lamps:t,air:r}),!0}remove(e){const t=this.beams.get(e);if(t){for(const r of t.lamps)r.removeFromParent(),r.target.removeFromParent(),r.dispose();for(const r of t.air)r.removeFromParent(),r.material.dispose();this.beams.delete(e)}}clear(e){for(const t of[...this.beams.keys()])e&&t==="observer"||this.remove(t)}dispose(){this.clear(!1),i.airGeometry?.dispose(),i.airGeometry=void 0}aim(e,t,r,n,a,o,u){const c=this.beams.get(e),w=Math.max(u,i.CLEAR_AIR_SCATTER_PER_M);if(!c)return;const l=m.BEAMS[t],v=new P(-n.z,0,n.x),A=e==="observer"&&l!==void 0;c.lamps.forEach((s,d)=>{if(!l){s.intensity=0,c.air[d].visible=!1,s.shadow.autoUpdate=!1;return}const f=d===0?-1:1,h=l.pitchDeg*Math.PI/180,p=l.candela*m.DISPLAY_GAIN*o/c.lamps.length;s.color.set(l.color),s.intensity=p,s.angle=l.halfAngleDeg*Math.PI/180,s.penumbra=l.penumbra,A?(s.shadow.autoUpdate||(s.shadow.needsUpdate=!0),s.shadow.autoUpdate=!0):s.shadow.autoUpdate=!1,s.position.copy(r).addScaledVector(v,f*a);const M=n.clone().addScaledVector(v,-f*Math.tan(m.TOE_IN_DEG*Math.PI/180)).normalize();s.target.position.set(s.position.x+M.x*Math.cos(h)*50,s.position.y-Math.sin(h)*50,s.position.z+M.z*Math.cos(h)*50),s.target.updateMatrixWorld(),this.aimAir(c.air[d],s,l.color,p,w)})}aimAir(e,t,r,n,a){if(e.visible=a*n>1e-4,!e.visible)return;const o=i.AIR_LENGTH_M,u=o*Math.tan(t.angle);e.position.copy(t.position),e.scale.set(u,u,o),e.lookAt(t.target.position),e.updateMatrixWorld();const c=e.material.uniforms;c.uColor.value.set(r),c.uCandela.value=n,c.uScatter.value=a,c.uLength.value=o,c.uRadius.value=u}static airCone(){if(i.airGeometry)return i.airGeometry;const e=24,t=new Float32Array((e+1)*3);for(let a=0;a<e;a++){const o=a/e*Math.PI*2;t.set([Math.cos(o),Math.sin(o),1],(a+1)*3)}const r=[];for(let a=0;a<e;a++)r.push(0,1+a,1+(a+1)%e);const n=new C;return n.setAttribute("position",new x(t,3)),n.setIndex(r),i.airGeometry=n,n}static airMaterial(){return new E({transparent:!0,depthWrite:!1,depthTest:!0,blending:I,side:R,uniforms:{uColor:{value:new L(1,1,1)},uCandela:{value:0},uScatter:{value:0},uLength:{value:90},uRadius:{value:20}},vertexShader:`
2
- varying vec3 vLocal;
3
- varying vec3 vNormalView;
4
- varying vec3 vViewDir;
5
- void main() {
6
- vLocal = position;
7
- vec4 viewPosition = modelViewMatrix * vec4(position, 1.0);
8
- // The side's normal, out of the axis: the apex has none (its length is nought), and a normal of nought there would spread NaN over the whole cone.
9
- float ring = length(position.xy);
10
- vec3 outward = ring > 1e-5 ? vec3(position.xy / ring, 0.0) : vec3(0.0, 0.0, 1.0);
11
- vNormalView = normalize(normalMatrix * outward);
12
- vViewDir = -viewPosition.xyz;
13
- gl_Position = projectionMatrix * viewPosition;
14
- }`,fragmentShader:`
15
- uniform vec3 uColor;
16
- uniform float uCandela;
17
- uniform float uScatter;
18
- uniform float uLength;
19
- uniform float uRadius;
20
- varying vec3 vLocal;
21
- varying vec3 vNormalView;
22
- varying vec3 vViewDir;
23
- void main() {
24
- float t = clamp(vLocal.z, 0.0, 1.0);
25
- float distanceM = max(t * uLength, 1.5);
26
- // The chord a ray makes through a cone of this thickness: long going along the beam, short going across its edge.
27
- float facing = abs(dot(normalize(vNormalView), normalize(vViewDir + vec3(0.0, 0.0, 1e-4))));
28
- float chord = 2.0 * uRadius * t * (0.25 + 0.75 * facing);
29
- // The beam's own profile averaged over the chord: strongest on the axis, none at the edge of the cone.
30
- float profile = 0.55;
31
- float radiance = uScatter * uCandela * chord * profile / (distanceM * distanceM + 9.0);
32
- float ends = (1.0 - smoothstep(0.75, 1.0, t)) * smoothstep(0.0, 0.04, t);
33
- gl_FragColor = vec4(uColor * radiance * ends, 1.0);
34
- }`})}}export{i as HeadlightSystem};
@@ -1 +0,0 @@
1
- const e={title:"Title",time:"When",by:"Interviewer",medium:"Medium",witness:"Witness",witnessNone:"—",summary:"Description",transcript:"Transcript",transcriptHint:"Address of the anonymised transcript file (optional)",summaryTab:"Summary",fileTab:"File",importFile:"Load a file (JSON, text, WebVTT, SRT)",importUrl:"Or load from URL",importButton:"Load",saveButton:"Save",loading:"Loading the transcript…",invalid:"This text is not valid JSON yet: the interview keeps the last transcript it understood.",notATranscript:"That file is not an interview transcript (it has no segments).",loadFailed:"That transcript could not be read.",editorLabel:"Interview transcript as JSON",byHint:"RR0 people ids, separated by commas",exchangesTab:"Exchanges",exchangesEmpty:"Nothing was said yet.",redacted:"Passage removed",proofreadAll:"Proofread by everyone.",proofreadPending:"Not proofread yet by: {names}",roles:{interviewer:"Interviewer",interviewee:"Interviewee",witness:"Witness"}};export{e as interviewMessages_en};
@@ -1 +0,0 @@
1
- const e={title:"Título",time:"Fecha",by:"Entrevistador",medium:"Medio",witness:"Testigo",witnessNone:"—",summary:"Descripción",transcript:"Transcripción",transcriptHint:"Dirección del archivo de transcripción anonimizada (opcional)",summaryTab:"Resumen",fileTab:"Archivo",importFile:"Cargar un archivo (JSON, texto, WebVTT, SRT)",importUrl:"O desde una dirección",importButton:"Cargar",saveButton:"Guardar",loading:"Cargando la transcripción…",invalid:"Este texto aún no es JSON válido: la entrevista conserva la última transcripción que entendió.",notATranscript:"Ese archivo no es una transcripción de entrevista (no tiene turnos de palabra).",loadFailed:"No se pudo leer esa transcripción.",editorLabel:"Transcripción de la entrevista en JSON",byHint:"Identificadores de personas de RR0, separados por comas",exchangesTab:"Intercambios",exchangesEmpty:"Todavía no se ha dicho nada.",redacted:"Pasaje eliminado",proofreadAll:"Revisado por todos.",proofreadPending:"Aún no revisado por: {names}",roles:{interviewer:"Entrevistador",interviewee:"Entrevistado",witness:"Testigo"}};export{e as interviewMessages_es};
@@ -1 +0,0 @@
1
- const e={title:"Titre",time:"Date",by:"Enquêteur",medium:"Moyen",witness:"Témoin",witnessNone:"—",summary:"Description",transcript:"Transcription",transcriptHint:"Adresse du fichier de transcription anonymisée (facultative)",summaryTab:"Résumé",fileTab:"Fichier",importFile:"Charger un fichier (JSON, texte, WebVTT, SRT)",importUrl:"Ou depuis une adresse",importButton:"Charger",saveButton:"Sauver",loading:"Chargement de la transcription…",invalid:"Ce texte n'est pas encore du JSON valide : l'interview garde la dernière transcription qu'elle a comprise.",notATranscript:"Ce fichier n'est pas une transcription d'interview (il n'a pas de tours de parole).",loadFailed:"Cette transcription n'a pas pu être lue.",editorLabel:"Transcription de l'interview en JSON",byHint:"Identifiants de personnes RR0, séparés par des virgules",exchangesTab:"Échanges",exchangesEmpty:"Rien n'a encore été dit.",redacted:"Passage retiré",proofreadAll:"Relu par tous les participants.",proofreadPending:"Pas encore relu par : {names}",roles:{interviewer:"Intervieweur",interviewee:"Interviewé",witness:"Témoin"}};export{e as interviewMessages_fr};
@@ -1 +0,0 @@
1
- const i={title:"Titolo",time:"Data",by:"Intervistatore",medium:"Mezzo",witness:"Testimone",witnessNone:"—",summary:"Descrizione",transcript:"Trascrizione",transcriptHint:"Indirizzo del file di trascrizione anonimizzata (facoltativo)",summaryTab:"Riepilogo",fileTab:"File",importFile:"Carica un file (JSON, testo, WebVTT, SRT)",importUrl:"O da un indirizzo",importButton:"Carica",saveButton:"Salva",loading:"Caricamento della trascrizione…",invalid:"Questo testo non è ancora JSON valido: l'intervista conserva l'ultima trascrizione che ha capito.",notATranscript:"Quel file non è una trascrizione di intervista (non ha turni di parola).",loadFailed:"Impossibile leggere quella trascrizione.",editorLabel:"Trascrizione dell'intervista in JSON",byHint:"Identificatori di persone RR0, separati da virgole",exchangesTab:"Scambi",exchangesEmpty:"Non è stato ancora detto nulla.",redacted:"Passaggio rimosso",proofreadAll:"Rivisto da tutti.",proofreadPending:"Non ancora rivisto da: {names}",roles:{interviewer:"Intervistatore",interviewee:"Intervistato",witness:"Testimone"}};export{i as interviewMessages_it};
@@ -1 +0,0 @@
1
- import{G as d,x as c,y as l,z as f,C as m,F as u,J as w,K as y,N as g,Q as M,X as S,Y as v,Z as O}from"./rr0-sighting-editor.mjs";class h{static key(e){return"url"in e?`url:${e.url}|${e.headingOffsetDeg??0}`:"shape"in e?`shape:${e.shape}`:`decor:${e.decorKind}`}static async build(e){const s=new d;if("url"in e){const t=await c(e.url);t.rotation.y=-(e.headingOffsetDeg??0)*Math.PI/180,s.add(t)}else"shape"in e?s.add(h.shapeOf(e.shape)):s.add(l.build({id:"preview",kind:e.decorKind,eastM:0,northM:0},!1));return s}static shapeOf(e){if(e==="figure")return l.build({id:"preview",kind:"entity",eastM:0,northM:0},!1);const s=new f(m.unitGeometry(e),new u({color:13158608,roughness:.5,metalness:0}));return e==="ellipsoid"&&s.scale.set(1,.55,1),s}static dispose(e){e.traverse(s=>{const t=s;if(t.isMesh){t.geometry?.dispose();for(const a of[t.material].flat())a.dispose()}})}static stage(e,s){const t=new w().setFromObject(e);if(t.isEmpty())return;const a=t.getBoundingSphere(new y),r=new d;e.position.sub(a.center),r.add(e);const n=new g;n.add(r),n.add(new M(16777215,6715272,1.6));const o=new S(16777215,2.5);o.position.set(1,2,1.5),n.add(o);const i=new v(30,s,a.radius*.05,a.radius*20),p=a.radius/Math.sin(i.fov*Math.PI/360)*1.05;return i.position.copy(new O(.55,.3,-.78).normalize().multiplyScalar(p)),i.lookAt(0,0,0),{scene:n,camera:i,pivot:r}}}export{h as M};
@@ -1,41 +0,0 @@
1
- import{G as k,F as w,a4 as H,a5 as P,a8 as K,aa as N,z as U,ab as F}from"./rr0-sighting-editor.mjs";class S{static HOLLOW_M=1;static COVERED_M=3;static WINDOW_M=30;static SAMPLE_M=4;static MAX_GRADE={rail:.025,highSpeed:.035,subway:.04,light_rail:.06,tram:.08,funicular:1/0};static heights(t,n,s){const e=t.map(r=>r.level===0),o=t.map((r,l)=>e[l]?S.targets(r,n,s):[]),c=t.map((r,l)=>e[l]?S.samples(r,o[l]):[]),a=new Map;t.forEach((r,l)=>{if(e[l])for(const p of S.ends(r)){const h=S.key(p),f=a.get(h);f?f.push(l):a.set(h,[l])}});const M=r=>{const l=a.get(S.key(r));if(l)return S.median(l.flatMap(p=>c[p]),r)};return t.map((r,l)=>{if(e[l]){const p=[...new Set([l,...S.ends(r).flatMap(g=>a.get(S.key(g))??[])])].flatMap(g=>c[g]),h=r.centre.map((g,D)=>S.median(p,g)??o[l][D]),[f,z]=S.ends(r);return h[0]=M(f)??h[0],h[h.length-1]=M(z)??h[h.length-1],S.graded(h,r.along,r.highSpeed?S.MAX_GRADE.highSpeed:S.MAX_GRADE[r.kind])}return S.carried(r,n,s,M)})}static targets(t,n,s){return t.centre.map(e=>{const o=n(e.x,e.z);if(s===void 0||e.altitudeM===void 0)return o;const c=e.altitudeM+s;return c-o>S.HOLLOW_M||o-c>S.COVERED_M?c:o})}static samples(t,n){const s=[];let e=0;return t.centre.forEach((o,c)=>{t.along[c]+1e-6<e&&c<t.centre.length-1||(s.push({x:o.x,z:o.z,y:n[c]}),e=t.along[c]+S.SAMPLE_M)}),s}static median(t,n){const s=[];for(const o of t)Math.hypot(o.x-n.x,o.z-n.z)<=S.WINDOW_M&&s.push(o.y);if(s.length===0)return;s.sort((o,c)=>o-c);const e=s.length>>1;return s.length%2===1?s[e]:(s[e-1]+s[e])/2}static graded(t,n,s){if(!Number.isFinite(s)||t.length<3)return t;const e=[...t],o=e.length-1,c=n[o];if(Math.abs(e[o]-e[0])>s*c)return n.map(a=>e[0]+(e[o]-e[0])*a/c);for(let a=1;a<o;a++){const M=s*(n[a]-n[a-1]);e[a]=Math.min(e[a-1]+M,Math.max(e[a-1]-M,e[a]))}for(let a=o-1;a>0;a--){const M=s*(n[a+1]-n[a]);e[a]=Math.min(e[a+1]+M,Math.max(e[a+1]-M,e[a]))}return e}static carried(t,n,s,e){const[o,c]=S.ends(t),a=t.along[t.along.length-1],M=e(o),r=e(c);if(s!==void 0&&t.centre.every(h=>h.altitudeM!==void 0)){const h=t.centre.map(g=>g.altitudeM+s),f=M!==void 0?M-h[0]:0,z=r!==void 0?r-h[h.length-1]:0;return h.map((g,D)=>g+f+(z-f)*t.along[D]/a)}const l=M??n(o.x,o.z),p=r??n(c.x,c.z);return t.along.map(h=>l+(p-l)*h/a)}static ends(t){return[t.centre[0],t.centre[t.centre.length-1]]}static key(t){return`${Math.round(t.x*2)},${Math.round(t.z*2)}`}}class I{positions=[];indices=[];along=[];get vertexCount(){return this.positions.length/3}strip(t,n,s){const e=this.vertexCount;for(let o=0;o<t.length;o++)this.positions.push(t[o].x,t[o].y,t[o].z,n[o].x,n[o].y,n[o].z),s&&this.along.push(s[o],s[o]);for(let o=0;o<t.length-1;o++){const c=e+o*2;this.indices.push(c,c+2,c+1,c+1,c+2,c+3)}}beam(t,n,s,e=!0){const o=n.x-t.x,c=n.y-t.y,a=n.z-t.z,M=Math.hypot(o,c,a);if(M<1e-6)return;const r={x:o/M,y:c/M,z:a/M},l=Math.abs(r.y)>.9?{x:1,y:0,z:0}:{x:0,y:1,z:0},p=r.y*l.z-r.z*l.y,h=r.z*l.x-r.x*l.z,f=r.x*l.y-r.y*l.x,z=Math.hypot(p,h,f),g={x:p/z*s/2,y:h/z*s/2,z:f/z*s/2},D={x:r.y*g.z-r.z*g.y,y:r.z*g.x-r.x*g.z,z:r.x*g.y-r.y*g.x},E=(u,A,d)=>({x:u.x+g.x*A+D.x*d,y:u.y+g.y*A+D.y*d,z:u.z+g.z*A+D.z*d}),_=[[1,1],[-1,1],[-1,-1],[1,-1]];for(let u=0;u<4;u++){const[A,d]=_[u],[v,x]=_[(u+1)%4];this.quad(E(t,A,d),E(t,v,x),E(n,v,x),E(n,A,d))}e&&(this.quad(...[..._].reverse().map(([u,A])=>E(t,u,A))),this.quad(..._.map(([u,A])=>E(n,u,A))))}quad(t,n,s,e){const o=this.vertexCount;this.positions.push(t.x,t.y,t.z,n.x,n.y,n.z,s.x,s.y,s.z,e.x,e.y,e.z),this.indices.push(o,o+1,o+2,o,o+2,o+3)}}class i{static STEP_M=6;static BALLAST_HEIGHT_M=.5;static BALLAST_SLOPE=1.5;static BALLAST_SHOULDER_M=.45;static DECK_DEPTH_M=.8;static BANK_SLOPE=1.5;static SLEEPER_LENGTH_M=2.4;static SLEEPER_WIDTH_M=.29;static SLEEPER_SPACING_M=.6;static RAIL_HEAD_M=.072;static RAIL_HEIGHT_M=.18;static TRAM_RAIL_HEIGHT_M=.03;static LIFT_M=.06;static CATENARY={rail:{contactM:5.5,systemM:1.4,spanM:54,staggerM:.2},highSpeed:{contactM:5.08,systemM:1.4,spanM:63,staggerM:.2},service:{contactM:5.5,systemM:1.2,spanM:45,staggerM:.2},tram:{contactM:6,systemM:0,spanM:30,staggerM:.2}};static MESSENGER_SAG_M=.55;static MAST_SIDE_M=.26;static MAST_OFFSET_M=3.1;static MAST_ABOVE_M=.6;static CONTACT_DIAMETER_M=.012;static MESSENGER_DIAMETER_M=.011;static ARM_SIDE_M=.06;static TRACK_SPACING_M={rail:3.7,highSpeed:4.5,tram:3.1,subway:3.4,light_rail:3.4,funicular:3.2};static BALLAST_ALBEDO=[.17,.16,.15];static BANK_ALBEDO=[.085,.09,.05];static DECK_ALBEDO=[.26,.255,.24];static CONCRETE_ALBEDO=[.36,.35,.33];static WOOD_ALBEDO=[.07,.055,.045];static RUST_ALBEDO=[.085,.068,.058];static STEEL_ALBEDO=[.3,.31,.32];static COPPER_ALBEDO=[.09,.085,.07];group=new k;stepM=i.STEP_M;drawn=0;ballastMaterial=i.pebbled(i.lambert(i.BALLAST_ALBEDO,!0));earthMaterial=i.lambert(i.BANK_ALBEDO,!0);deckMaterial=i.lambert(i.DECK_ALBEDO,!1);concreteSleepers=i.sleeperMaterial(i.CONCRETE_ALBEDO);woodSleepers=i.sleeperMaterial(i.WOOD_ALBEDO);rustMaterial=i.lambert(i.RUST_ALBEDO,!0);headMaterial=new w({color:new H(.62,.62,.62),metalness:1,roughness:.28,polygonOffset:!0,polygonOffsetFactor:-2,polygonOffsetUnits:-2});steelMaterial=i.lambert(i.STEEL_ALBEDO,!1);wireMaterial=i.lambert(i.COPPER_ALBEDO,!1);constructor(){this.group.name="railways"}get count(){return this.drawn}setGroundSpacing(t){this.stepM=Number.isFinite(t)&&t>0?Math.min(i.STEP_M,Math.max(1.5,t/2)):i.STEP_M}set(t,n,s,e,o=1/0){this.clear();const a=t.map(f=>({line:f,path:f.points.map(z=>({...P(z.lat,z.lng,n,s),altitudeM:z.altitudeM}))})).filter(({line:f,path:z})=>f.level>=0&&i.within(z,o)),M=i.altitudeOffset(a,e),r=a.flatMap(({line:f,path:z})=>{const g=this.layoutOf(f,z);return g?[{line:f,layout:g}]:[]}),l=S.heights(r.map(({layout:f})=>f),e,M),p={ballast:new I,earth:new I,deck:new I,concrete:new I,wood:new I,rust:new I,head:new I,steel:new I,wire:new I};r.forEach(({line:f,layout:z},g)=>{this.lay(f,{...z,y:l[g]},e,p),this.drawn++});const h=[[p.ballast,this.ballastMaterial,"ballast",!1],[p.earth,this.earthMaterial,"embankments",!1],[p.deck,this.deckMaterial,"decks",!0],[p.concrete,this.concreteSleepers,"sleepers",!1],[p.wood,this.woodSleepers,"sleepers wood",!1],[p.rust,this.rustMaterial,"rails",!1],[p.head,this.headMaterial,"rail heads",!1],[p.steel,this.steelMaterial,"catenary masts",!0],[p.wire,this.wireMaterial,"catenary wires",!1]];for(const[f,z,g,D]of h){const E=i.meshOf(f,z);E&&(E.name=`railways ${g}`,E.castShadow=D,E.receiveShadow=!0,this.group.add(E))}}clear(){for(const t of[...this.group.children])this.group.remove(t),t.geometry?.dispose();this.drawn=0}dispose(){this.clear();for(const t of[this.ballastMaterial,this.earthMaterial,this.deckMaterial,this.concreteSleepers,this.woodSleepers,this.rustMaterial,this.headMaterial,this.steelMaterial,this.wireMaterial])t.dispose()}static within(t,n){if(!Number.isFinite(n))return!0;const s=n*1.1+100;return t.some((e,o)=>Math.hypot(e.x,e.z)<=s||o>0&&Math.hypot((e.x+t[o-1].x)/2,(e.z+t[o-1].z)/2)<=s)}static altitudeOffset(t,n){const s=[];for(const{line:e,path:o}of t)if(e.level===0)for(const c of o)c.altitudeM!==void 0&&s.push(n(c.x,c.z)-c.altitudeM);if(!(s.length<5))return s.sort((e,o)=>e-o),s[Math.floor(s.length/2)]}layoutOf(t,n){const s=[];for(let c=0;c<n.length-1;c++){const a=n[c],M=n[c+1],r=Math.max(1,Math.ceil(Math.hypot(M.x-a.x,M.z-a.z)/this.stepM));for(let l=0;l<r;l++){const p=l/r,h=a.altitudeM!==void 0&&M.altitudeM!==void 0?a.altitudeM+(M.altitudeM-a.altitudeM)*p:void 0;s.push({x:a.x+(M.x-a.x)*p,z:a.z+(M.z-a.z)*p,altitudeM:h})}}if(s.push(n[n.length-1]),s.length<2)return;const e=[0];for(let c=1;c<s.length;c++)e.push(e[c-1]+Math.hypot(s[c].x-s[c-1].x,s[c].z-s[c-1].z));if(e[e.length-1]<.5)return;const o=s.map((c,a)=>{const M=s[Math.max(0,a-1)],r=s[Math.min(s.length-1,a+1)],l=r.x-M.x,p=r.z-M.z,h=Math.hypot(l,p);return h<1e-6?{x:1,z:0}:{x:l/h,z:p/h}});return{kind:t.kind,...t.highSpeed?{highSpeed:!0}:{},level:t.level,centre:s,along:e,dir:o}}lay(t,n,s,e){const o=t.highSpeed?i.TRACK_SPACING_M.highSpeed:i.TRACK_SPACING_M[t.kind],c=Math.min(8,Math.max(1,t.tracks)),a=Array.from({length:c},(E,_)=>(_-(c-1)/2)*o),M=t.kind==="tram",r=M?0:i.BALLAST_HEIGHT_M,l=i.LIFT_M,p=(E,_,u)=>({x:n.centre[E].x-n.dir[E].z*_,y:n.y[E]+u,z:n.centre[E].z+n.dir[E].x*_}),h=n.centre.map((E,_)=>_);if(!M){const E=i.SLEEPER_LENGTH_M/2+i.BALLAST_SHOULDER_M+(a[a.length-1]??0),_=h.map(A=>p(A,E,r+l)),u=h.map(A=>p(A,-E,r+l));if(e.ballast.strip(_,u),t.level===0){const A=E+r*i.BALLAST_SLOPE;for(const d of[1,-1]){const v=[],x=[];let m=!1;for(const L of h){const b=p(L,d*A,l),C=s(b.x,b.z)+l,T=b.y-C;T<0&&(b.y=Math.min(C,n.y[L]+r-.05+l)),v.push(b);const B=p(L,d*(A+Math.max(0,T)*i.BANK_SLOPE),l);B.y=Math.min(s(B.x,B.z)+l,b.y),b.y-B.y>.02&&(m=!0),x.push(B)}const O=d>0?_:u;d>0?e.ballast.strip(v,O):e.ballast.strip(O,v),m&&(d>0?e.earth.strip(x,v):e.earth.strip(v,x))}}else{const A=-i.DECK_DEPTH_M,d=E+.15,v=h.map(L=>p(L,d,r+l+.1)),x=h.map(L=>p(L,-d,r+l+.1)),m=h.map(L=>p(L,d,A)),O=h.map(L=>p(L,-d,A));e.deck.strip(m,v),e.deck.strip(x,O),e.deck.strip(O,m),e.deck.strip(v,h.map(L=>p(L,E,r+l+.1))),e.deck.strip(h.map(L=>p(L,-E,r+l+.1)),x)}}const f=t.service?e.wood:e.concrete,z=t.gaugeMm/2e3+i.RAIL_HEAD_M/2,g=M?i.TRAM_RAIL_HEIGHT_M:i.RAIL_HEIGHT_M,D=r+l;for(const E of a){if(!M){const _=i.SLEEPER_LENGTH_M/2;f.strip(h.map(u=>p(u,E+_,D+.004)),h.map(u=>p(u,E-_,D+.004)),n.along)}for(const _ of[1,-1]){const u=E+_*z,A=i.RAIL_HEAD_M/2,d=h.map(x=>p(x,u+A,D+g)),v=h.map(x=>p(x,u-A,D+g));e.head.strip(d,v),e.rust.strip(h.map(x=>p(x,u+A,D)),d),e.rust.strip(v,h.map(x=>p(x,u-A,D)))}}t.electrification==="overhead"&&t.kind!=="subway"&&t.kind!=="funicular"&&this.catenary(t,n,a,D+g,p,s,e)}catenary(t,n,s,e,o,c,a){const M=t.kind==="tram"?i.CATENARY.tram:t.highSpeed?i.CATENARY.highSpeed:t.service?i.CATENARY.service:i.CATENARY.rail,r=n.along[n.along.length-1],l=Math.max(1,Math.round(r/M.spanM)),p=r/l,h=Array.from({length:l},(d,v)=>(v+.5)*p),f=e+M.contactM,z=f+M.systemM,g=(M.systemM>0?z:f)+i.MAST_ABOVE_M,D=s[s.length-1],E=s.length>2,_=s.length===1?[1]:[1,-1],u=(d,v,x)=>{let m=0,O=n.along.length-2;for(;m<O;){const T=m+O+1>>1;n.along[T]<=d?m=T:O=T-1}const L=Math.min(1,Math.max(0,(d-n.along[m])/Math.max(1e-6,n.along[m+1]-n.along[m]))),b=o(m,v,x),C=o(m+1,v,x);return{x:b.x+(C.x-b.x)*L,y:b.y+(C.y-b.y)*L,z:b.z+(C.z-b.z)*L}};for(const d of h){const v=u(d,0,f);if(!(t.level===0&&c(v.x,v.z)>v.y)){for(const x of _){const m=x*(D+i.MAST_OFFSET_M),O=u(d,m,0);t.level===0&&(O.y=Math.min(O.y,c(O.x,O.z)));const L=u(d,m,g);if(a.steel.beam(O,L,i.MAST_SIDE_M),E)continue;const C=(_.length===1?s[0]:x*D)-x*.6,T=M.systemM>0?z:f+.3;a.steel.beam(u(d,m,T),u(d,C,T),i.ARM_SIDE_M),a.steel.beam(u(d,m,f-.4),u(d,C,T),i.ARM_SIDE_M)}if(E){const x=D+i.MAST_OFFSET_M;a.steel.beam(u(d,x,g-.2),u(d,-x,g-.2),i.MAST_SIDE_M*.8)}}}const A=[0,...h,r];for(const[d,v]of s.entries()){const x=m=>m===0||m===A.length-1?0:((m+d)%2===0?1:-1)*M.staggerM;for(let m=0;m<A.length-1;m++){const O=A[m],L=A[m+1];if(L-O<.1||(a.wire.beam(u(O,v+x(m),f),u(L,v+x(m+1),f),i.CONTACT_DIAMETER_M,!1),M.systemM<=0))continue;const b=4,C=T=>{const B=m===0?.5+T/2:m===A.length-2?T/2:T;return z-i.MESSENGER_SAG_M*4*B*(1-B)};for(let T=0;T<b;T++){const B=T/b,G=(T+1)/b;a.wire.beam(u(O+(L-O)*B,v,C(B)),u(O+(L-O)*G,v,C(G)),i.MESSENGER_DIAMETER_M,!1)}}}}static meshOf(t,n){if(t.indices.length===0)return;const s=new K;return s.setAttribute("position",new N(new Float32Array(t.positions),3)),t.along.length>0&&s.setAttribute("aAlong",new N(new Float32Array(t.along),1)),s.setIndex(new N(new Uint32Array(t.indices),1)),s.computeVertexNormals(),new U(s,n)}static lambert(t,n){return new F({color:new H(...t),...n?{polygonOffset:!0,polygonOffsetFactor:-2,polygonOffsetUnits:-2}:{}})}static pebbled(t){return t.onBeforeCompile=n=>{n.vertexShader=n.vertexShader.replace("#include <common>",`#include <common>
2
- varying vec3 vBallast;`).replace("#include <begin_vertex>",`#include <begin_vertex>
3
- vBallast = position;`),n.fragmentShader=n.fragmentShader.replace("#include <common>",`#include <common>
4
- varying vec3 vBallast;
5
- float ballastHash(vec2 p) {
6
- p = fract(p * vec2(127.1, 311.7));
7
- p += dot(p, p + 34.5);
8
- return fract(p.x * p.y);
9
- }
10
- float ballastNoise(vec2 p) {
11
- vec2 i = floor(p);
12
- vec2 f = fract(p);
13
- f = f * f * (3.0 - 2.0 * f);
14
- return mix(mix(ballastHash(i), ballastHash(i + vec2(1.0, 0.0)), f.x), mix(ballastHash(i + vec2(0.0, 1.0)), ballastHash(i + vec2(1.0, 1.0)), f.x), f.y);
15
- }`).replace("#include <map_fragment>",`#include <map_fragment>
16
- {
17
- float eye = length(vViewPosition);
18
- vec2 at = vBallast.xz + vec2(0.0, vBallast.y);
19
- float stones = (ballastHash(floor(at * 22.0)) - 0.5) * 0.9 * (1.0 - smoothstep(4.0, 18.0, eye))
20
- + (ballastNoise(at * 6.0) - 0.5) * 0.5 * (1.0 - smoothstep(15.0, 60.0, eye))
21
- + (ballastNoise(at * 0.7) - 0.5) * 0.35 * (1.0 - smoothstep(80.0, 300.0, eye));
22
- diffuseColor.rgb *= 1.0 + stones;
23
- }`)},t.customProgramCacheKey=()=>"rr0-railway-ballast",t}static sleeperMaterial(t){const n=new F({color:new H(1,1,1),polygonOffset:!0,polygonOffsetFactor:-3,polygonOffsetUnits:-3}),s=new H(...t),e=new H(...i.BALLAST_ALBEDO);return n.onBeforeCompile=o=>{o.uniforms.uSleeper={value:s},o.uniforms.uCrib={value:e},o.uniforms.uSpacing={value:i.SLEEPER_SPACING_M},o.uniforms.uDuty={value:i.SLEEPER_WIDTH_M/i.SLEEPER_SPACING_M},o.vertexShader=o.vertexShader.replace("#include <common>",`#include <common>
24
- attribute float aAlong;
25
- varying float vAlong;`).replace("#include <begin_vertex>",`#include <begin_vertex>
26
- vAlong = aAlong;`),o.fragmentShader=o.fragmentShader.replace("#include <common>",`#include <common>
27
- varying float vAlong;
28
- uniform vec3 uSleeper;
29
- uniform vec3 uCrib;
30
- uniform float uSpacing;
31
- uniform float uDuty;
32
- // How much of [0, x] periods is sleeper: the integral of a pulse of width uDuty at the start of each period.
33
- float sleeperIntegral(float x) {
34
- return floor(x) * uDuty + min(fract(x), uDuty);
35
- }`).replace("#include <map_fragment>",`#include <map_fragment>
36
- {
37
- float u = vAlong / uSpacing;
38
- float w = max(fwidth(u), 1e-4);
39
- float cover = (sleeperIntegral(u + 0.5 * w) - sleeperIntegral(u - 0.5 * w)) / w;
40
- diffuseColor.rgb *= mix(uCrib, uSleeper, clamp(cover, 0.0, 1.0));
41
- }`)},n.customProgramCacheKey=()=>"rr0-railway-sleepers",n}}export{i as RailwaySystem};
@@ -1,12 +0,0 @@
1
- const e={color:"Couleur",transparency:"Transparence",halo:"Halo",blur:"Flou",brightness:"Éclat",shapeTitle:"Nom",utcOffset:"Fuseau horaire",cloudBase:"Base des nuages",elevation:"Altitude",heightAboveGround:"Hauteur au-dessus du sol",duration:"Durée",placeName:"Lieu",latitude:"Latitude",longitude:"Longitude",heading:"Orientation",pitch:"Inclinaison",roll:"Roulis",sway:"Bougé au repos",swayTitle:"Combien le corps qui tient l'instrument fait bouger la vue hors de la marche : 1 pour une personne debout, 0 pour un trépied. Vide : 1 (0 si le compte rendu dit l'observateur paralysé)",lightPollution:"Ciel nocturne",lightPollutionTitle:"Le zénith d'une nuit sans Lune en ce lieu, en magnitudes par seconde d'arc carrée, tel qu'un Sky Quality Meter le lit ou que l'atlas mondial de la brillance artificielle du ciel (Falchi et al. 2016, lightpollutionmap.info, « SQM ») le donne. 22 est un ciel naturel ; une banlieue est vers 19, un centre-ville vers 17. Vide : un ciel naturel",observationTime:"Début de l'observation",observationEndTime:"Fin de l'observation",assessmentGroup:"Évaluation",assessmentNames:{coverage:"Infos de l'observateur"},assessmentVerdicts:{"hynek.nl":"NL — lumière nocturne","hynek.dd":"DD — disque diurne","hynek.rv":"RV — radar-visuel","hynek.ce1":"RR1 — rencontre rapprochée","hynek.ce2":"RR2 — avec trace physique","hynek.ce3":"RR3 — avec occupants"},timeQualifierApproximate:"Approximative",timeQualifierUncertain:"Incertaine",timeQualifierBoth:"Incertaine et approximative",timeSeasonSpring:"Printemps",timeSeasonSummer:"Été",timeSeasonAutumn:"Automne",timeSeasonWinter:"Hiver",summaryGroups:{observation:"Observation",location:"Position",temporal:"Moment",weather:"Météo",sound:"Son"},summaryGroup:"Résumé",summaryDescription:"Description",closeDescription:"Fermer la description",observerGroup:"Observateur",observerId:"ID",observerTitle:"Titre",observerLastName:"Nom de famille",observerFirstNames:"Prénoms",sightingId:"ID",tags:"Mots-clés",cloudCover:"Couverture nuageuse",highCloudCover:"Nuages de glace (cirrus)",focalLength:"Focale",fieldOfView:"Champ de vision",aperture:"Diaphragme",exposure:"Temps de pose",focusDistance:"Mise au point à",iceCrystalAlignment:"Alignement des cristaux",rareIceCrystals:"Cristaux rares",cloudDarkness:"Obscurité des nuages",precipitationType:"Précipitations",precipitationNone:"Aucune",precipitationRain:"Pluie",precipitationSnow:"Neige",precipitationHail:"Grêle",precipitationIntensity:"Intensité",windDirection:"Direction du vent",windSpeed:"Force du vent",storm:"Orage",cloudsGroup:"Nuages",precipitationGroup:"Précipitations",windGroup:"Vent",soundKind:"Son",soundNone:"Aucun (silencieux)",soundHum:"Bourdonnement",soundWhistle:"Sifflement",soundRumble:"Grondement",soundCrackle:"Crépitement",soundVolume:"Intensité sonore",soundPitch:"Hauteur",soundSrc:"Enregistrement",instrument:"Observé avec",filter:"Devant lui",filterNone:"rien",filterSolarVisual:"un filtre solaire pour l'œil (lunettes d'éclipse, densité 5)",filterSolarPhoto:"un film solaire pour appareil photo (densité 3,8)",decorAircraft:"Aéronef",decorEntity:"Être",decorAltitude:"Altitude",decorLights:"Feux",decorLightsNone:"aucun",decor:"Environnement",decorBuilding:"Bâtiment",decorTree:"Arbre",decorShrub:"Buisson",decorBridge:"Pont",decorWire:"Ligne aérienne",decorCrop:"Rang de culture",decorTerrace:"Restanque (terrasse)",decorMound:"Tas de pierres",decorWall:"Muret de pierres sèches",decorStreetlight:"Lampadaire",decorTrafficLight:"Feu de circulation",decorCrossing:"Passage piéton",decorRoadSign:"Panneau de signalisation",decorVehicle:"Véhicule",decorObserver:"Autre observateur",decorEast:"Distance à l'est",decorNorth:"Distance au nord",decorHeading:"Orientation",decorColor:"Couleur",decorLit:"Allumé",decorTitle:"Nom",milestones:"Moments",milestoneLabel:"Repère",milestoneNote:"Ce qui se passe",addMilestone:"Nommer cet instant",deleteMilestone:"Supprimer le moment",goToMilestone:"Aller à ce moment",decorWidth:"Largeur",decorLength:"Longueur",decorHeight:"Hauteur",decorModel:"Modèle 3D",decorModelAdvanced:"Modèle depuis une adresse",decorModelUrl:"Adresse glTF/GLB",decorModelTitle:"Nom du modèle",decorModelAuthor:"Auteur",decorModelLicense:"Licence",decorModelSource:"Provenance",decorObserverSide:"Emplacement de l'observateur",decorObserverSideNone:"Non présent",decorSideFront:"Avant",decorSideBehind:"Arrière",decorSideLeft:"Gauche",decorSideRight:"Droite",decorSideFrontLeft:"Avant-gauche",decorSideFrontRight:"Avant-droit",decorSideBehindLeft:"Arrière-gauche",decorSideBehindRight:"Arrière-droit"},r={...e,oval:"Ovale",polygon:"Polygone",addVertex:"Ajouter un sommet",deleteVertex:"Supprimer le sommet",notAPolygon:"Sélectionnez une seule forme polygonale",tooFewVertices:"Une forme a besoin d'au moins 3 points",shape:"Forme",apparentWidth:"Largeur apparente",realWidth:"Largeur réelle",distance:"Distance",sizeLock:"Maintenir",lockNone:"rien",lockApparent:"la largeur apparente",lockReal:"la largeur réelle",lockDistance:"la distance",apparentSize:"{moons}× la Lune",utcOffsetPlaceholder:"d'après la longitude",realSizeBetween:"La scène borne cette largeur : entre {min} et {max} m, d'après ce qu'il croise",realSizeAtLeast:"La scène borne cette largeur : au moins {min} m, d'après ce qu'il passe derrière",realSizeAtMost:"La scène borne cette largeur : au plus {max} m, d'après ce qu'il passe devant",realSizeUnknown:"Rien dans la scène ne borne cette largeur : elle ne fait que découler de la distance",realSizeOutside:" — la largeur ci-dessus en sort",blurBound:"Flou à travers cet objectif : plus près que {max} m",blurBoundNoInstrument:"Le flou à l'œil nu ne borne aucune distance — un œil n'a pas de diaphragme dont sortir",blurBoundNotAtInfinity:"Le flou ne borne une distance que pour une mise au point à l'infini : celle-ci est à {focus} m, qui floute des deux côtés",realSizeContradiction:"Contradiction : les passages déclarés ne peuvent pas être vrais ensemble",realDistanceHere:" — soit ici entre {min} et {max} m",clearDistanceHypothesis:"Retirer l'hypothèse de distance",clearDistanceHypothesisTitle:"Revenir à ce que l'enregistrement établit",depthStated:"Dessiné à {m} m, comme l'enregistrement l'énonce",depthHypothesis:"Dessiné à {m} m : votre hypothèse — ce que le décor en cache est ce qu'une chose à cette distance perdrait",depthDerived:"Dessiné à {m} m, d'après la marche de l'observateur",depthBounded:"Dessiné à {m} m, d'après ce qu'il passe derrière et devant",depthConventional:"Dessiné à {m} m par convention : rien dans l'enregistrement n'établit de distance",addShape:"Ajouter une forme",deleteShape:"Supprimer la forme",play:"Lecture",pause:"Pause",noDuration:"Aucune durée d'observation",previousKeyframe:"Image clé précédente",nextKeyframe:"Image clé suivante",keyframeMark:"Image clé",shapesTrack:"formes",observerTrack:"observateur",weatherTrack:"météo",soundTrack:"son",group:"Grouper",ungroup:"Dégrouper",bringToFront:"Placer devant",sendToBack:"Placer derrière",contextMenuDelete:"Supprimer",onlyOneShape:"Il n'y a qu'une seule forme",alreadyAtFront:"Cette forme est déjà la plus en avant",alreadyAtBack:"Cette forme est déjà la plus en arrière",needTwoShapesToGroup:"Sélectionnez au moins deux formes pour les grouper",notGrouped:"Cette forme ne fait pas partie d'un groupe",multipleShapesSelected:"Plusieurs formes sélectionnées — sélectionnez-en une seule pour modifier ceci",samplingRate:"Échantillonnage",currentPosition:"Position actuelle",switchToElapsed:"cliquer pour afficher la durée écoulée",switchToClockTime:"cliquer pour afficher l'heure de l'observation",durationPlaceholder:"durée de l'observation",durationImprecise:"Ces dates ne permettent pas de déterminer précisément une durée — saisissez-la manuellement.",export:"Sauver",identityHint:"Ne nommez quelqu'un que s'il y a consenti ou a publié lui-même son témoignage ; sinon des initiales suffisent.",identityAsk:"Cet enregistrement nomme ou situe une personne. Vous répondez de ce que vous publiez : ne nommez quelqu'un que s'il y a consenti, ou s'il a publié lui-même son témoignage. Sinon, des initiales suffisent.",identityLastName:"Nom de famille : {value}",identityFirstNames:"Prénom : {value}",identityNameInId:"Nom dans un identifiant : {value}",identityNameInText:"Nom dans le texte : {value}",identityAddress:"Adresse : {value}",identityEmail:"Adresse électronique : {value}",identityPhone:"Numéro de téléphone : {value}",identityInitials:"Remplacer par des initiales",identityKeep:"Sauver quand même",identityBack:"Revenir",importFile:"Charger un fichier JSON",importUrl:"Ou charger depuis une URL",importUrlPlaceholder:"https://…/sighting.json",importButton:"Charger",importError:"Impossible de charger cet enregistrement — vérifiez le fichier ou l'URL et réessayez.",importErrorCors:"Cette adresse répond, mais le navigateur n'a pas le droit de la lire depuis cette page. Le fichier lui-même est bon : c'est son serveur qui doit envoyer l'en-tête « Access-Control-Allow-Origin: * » avec. Si ce serveur n'est pas le vôtre, c'est ce qu'il faut demander à son administrateur.",importErrorMixedContent:"Une page sécurisée ne peut pas charger une adresse commençant par http://. Utilisez https:// si ce serveur le propose.",importErrorUnreachable:"Rien n'a répondu à cette adresse. Vérifiez l'orthographe, et que vous êtes connecté.",importErrorStatus:"Ce serveur a répondu par une erreur ({status}). L'adresse est probablement fausse, ou le fichier a été déplacé.",importErrorMalformed:"Cette adresse a répondu, mais ce qui revient n'est pas un enregistrement.",record:"Enregistrer",stop:"Arrêter",according:"selon",sourceElevation:"Relief",sourceImagery:"Imagerie",sourceAircraft:"Trafic aérien",placeNamePlaceholder:"Valensole, France",searchPlace:"Localiser",placeMatch:"Correspondances",placeSearching:"Recherche du lieu…",placeMatchFound:"lieu trouvé",placeMatchesFound:"lieux trouvés",placeNotFound:"Aucun lieu de ce nom",placeSearchFailed:"Recherche de lieu momentanément indisponible",utcOffsetNoZone:"Aucun fuseau n'indique ce décalage ce jour-là",utcOffsetImplausible:"Ce fuseau ne correspond pas à la longitude saisie, dont l'heure solaire est UTC{solar} — la scène et le relevé météo obéissent pourtant à ce qui est déclaré ici. Videz le champ pour le déduire de la longitude.",timeZoneManual:"inconnu",altitudeAboveSeaLevel:"Altitude de l'observateur au-dessus du niveau de la mer — le sol du lieu saisi en fixe le minimum : un observateur dans les Alpes n'est pas à 0 m.",groundAt:"sol à {m} m",headingPlaceholder:"inconnu",edtfInvalid:"Date/heure EDTF invalide (ex. 1965-07-01T05:00, 2025-06?, 2025~).",edtfPlaceholder:"AAAA-MM-JJThh:mm[?~%] ou hh:mm",observationTimeHint:"EDTF — ex. 1965-07-01T05:00, 2025-06? (incertain), 2025~ (approximatif), ou juste 05:00 si la date est inconnue",observationEndTimeHint:"EDTF — ex. 1965-07-01T05:10, 2025-06? (incertain), 2025~ (approximatif), ou juste 05:10 si la date est inconnue",presetsGroupLabel:"Forme de l'ovni",description:"Description",tagsPlaceholder:"séparés par des virgules",weather:"Météo",shapeGroup:"Phénomène",shapesSubgroup:"Formes",bodiesSubgroup:"Corps",launchesSubgroup:"Lancements",soundGroup:"Son",temporalGroup:"Moment",fileGroup:"Fichier",fileLoading:"Chargement de l'éditeur…",weatherEditedAsk:"Cette édition touche à la météo, une donnée lue dynamiquement depuis {source}. Voulez-vous désactiver sa lecture depuis {source} ?",weatherEditedStop:"Désactiver sa lecture",weatherEditedKeep:"Garder la lecture (annuler mon édition)",fileEditorLabel:"L'enregistrement en texte JSON",fileSearchPhrases:{Find:"Rechercher",Replace:"Remplacer",next:"suivant",previous:"précédent",all:"tout","match case":"casse","by word":"mot entier",regexp:"regexp",replace:"remplacer","replace all":"tout remplacer",close:"fermer","current match":"occurrence courante","on line":"à la ligne","replaced $ matches":"$ occurrences remplacées","replaced match on line $":"occurrence remplacée à la ligne $","Go to line":"Aller à la ligne",go:"aller"},timeQualifierExact:"Exacte",durationPrecise:"précise",durationIso:"imprécise",durationModeTitle:"Dire la durée exactement, ou comme elle a été énoncée : environ, entre deux durées",durationInvalid:"Pas une durée : PT10M, PT1H30M, PT5M/PT10M…",durationHelpTitle:"Ce que le texte accepte (EDTF)",durationHelpLines:`PT45S — 45 secondes
2
- PT10M — 10 minutes
3
- PT1H30M — 1 heure 30 minutes
4
- PT5M/PT10M — entre 5 et 10 minutes
5
- Finir par ? si incertain, ~ si approximatif, % pour les deux
6
- 1965-?07 — le doute peut aussi porter sur une partie`,durationChosen:"(simulée : {value})",accountView:"Compte rendu",accountView2d:"2D · formes",accountView3d:"3D · corps",accountViewHint:"Ce que le rendu montre et ce qu'on édite : les formes que l'observateur a dessinées, ou les corps qu'il a dit qu'elles étaient",datePrecise:"précise",dateEdtf:"imprécise",dateHelpTitle:"Ce que le texte accepte (EDTF)",dateHelpLines:`1965 — une année
7
- 1965-07 — un mois
8
- 1965-21 — une saison (21 printemps, 22 été, 23 automne, 24 hiver)
9
- 1965-07-01 — un jour
10
- 1965-07-01T05:00 — un jour et une heure
11
- 05:00 — une heure, date inconnue
12
- Finir par ? si incertain, ~ si approximatif, % pour les deux`,edtfModeTitle:"Saisir plutôt une date imprécise : une année seule, un mois, une heure sans date",locationGroup:"Position",observationGroup:"Résumé",weatherWhilePlaying:"Mettez la lecture en pause pour décrire le temps — pendant qu'elle tourne, l'instant où ceci s'écrirait se déplace",weatherInferred:"D'après les relevés",weatherInferredTitle:"La météo n'est pas un compte rendu : c'est un fait mesurable, relevé pour la date, l'heure et le lieu de l'observation. Décochez pour saisir les conditions rapportées par l'observateur, qui priment alors sur le relevé.",weatherLookingUp:"Recherche du relevé…",weatherNeedsDateAndPlace:"Date complète et lieu requis pour retrouver le relevé",weatherNeedsDate:"Une date complète (année, mois et jour) est requise pour retrouver les relevés météo",weatherNeedsPlace:"Un lieu avec ses coordonnées est requis pour retrouver les relevés météo",weatherNoRecord:"Aucun relevé pour cette date et ce lieu",weatherLookupFailed:"Relevés météo momentanément inaccessibles",lightPollutionLookingUp:"Consultation de l'atlas…",lightPollutionFound:"{artificial} µcd/m² de lumière artificielle,",lightPollutionNatural:"Aucune lumière artificielle ici,",lightPollutionOutside:"Hors de l'atlas (85°N à 60°S),",lightPollutionFailed:"Atlas momentanément inaccessible",lightPollutionTooEarly:"L'atlas décrit {atlasYear} ; le ciel de {year} était plus sombre, à indiquer s'il est connu",instrumentOutOfPeriod:"{name} — hors de son époque",instrumentCategoryEye:"Œil nu",instrumentCategoryCamera:"Appareils photo",instrumentCategoryDslr:"Reflex numériques",instrumentCategoryPhone:"Téléphones",instrumentCategoryBinoculars:"Jumelles",instrumentCategoryTelescope:"Télescopes",instrumentNotYetOnSale:"N'existait pas encore en {year} (en vente à partir de {from})",instrumentNoLongerOnSale:"N'existait plus en {year} (en vente jusqu'en {to})",filterNotForInstrument:"Inutilisable avec cet instrument",unitMillimetres:"mm",unitDegrees:"°",fieldOfViewReadout:"{deg}° de champ",soundSrcPlaceholder:"URL d'un enregistrement réel",referenceGroup:"Photos",reference:"Photo",referenceTitle:"Nom",referenceSrc:"Adresse",referenceSrcPlaceholder:"https://…/photo.jpg",referenceKind:"Type",referencePhoto:"Photo",referencePanorama:"Panorama (360°)",referenceCredit:"Crédit",referenceCreditUrl:"Lien du crédit",referenceT:"Prise à",referenceDrawing:"Dessin par-dessus",referenceOpacity:"Opacité",referenceHeading:"Cap",referencePitch:"Assiette",referenceRoll:"Roulis",referenceFov:"Champ vertical",referenceUsePose:"Prendre la pose de l'observateur",addReferenceUrl:"Ajouter depuis une adresse",addReferenceFile:"Ajouter un fichier",deleteReference:"Supprimer la photo",referenceEmbedded:"{kb} ko embarqués dans l'enregistrement — une adresse le garderait léger",referenceUnreachable:"La photo n'a pas pu être chargée : vérifiez l'adresse, et que son site autorise les autres sites à la lire",referenceRegisterHint:"Glissez pour orienter la photo, molette pour son champ ; « Ajouter un repère » pour pointer un détail sur la photo, puis le même dans le rendu",referenceLandmarkPicture:"Repère {n} : cliquez le point sur la photo",referenceLandmarkScene:"Repère {n} : cliquez le même point dans le rendu",referenceLandmarkOffPicture:"Ce clic ne tombe pas sur la photo",referenceNotLoaded:"La photo n'est pas encore arrivée",referenceLandmarksFit:"{n} repères — écart moyen {deg}°",referenceLandmarks:"Repères",addReferenceLandmark:"Ajouter un repère",deleteReferenceLandmark:"Supprimer le repère",referenceLandmarkLabel:"Nom",referenceLandmarkLabelPlaceholder:"Arbre masquant, barrière…",referenceAdoptPose:"Adopter comme pose de l'observateur",referenceAdoptRationale:"Mesuré sur la photo « {title} » : {n} repères recalés, {deg}° d'écart résiduel",referenceStreetSearch:"Photos de rue à proximité",referenceStreetSearching:"Recherche de photos prises à proximité…",referenceStreetNone:"Aucune photo de rue à moins de {m} m (Panoramax)",referenceStreetFailed:"Panoramax est injoignable",referenceStreetAdd:"Ajouter",traceImport:"Tracés d'enquêteur (KML, KMZ)",trace:"Tracé",deleteTrace:"Supprimer le tracé",traceTitle:"Nom",traceSource:"Source",traceImported:"{n} importé(s) depuis {name}.",traceSkipped:"Écarté : {what}.",traceNone:"Aucune ligne, aucun lieu ni contour dans ce fichier.",traceFailed:"Ce fichier n'a pas pu être lu.",traceKindPoint:"lieu",traceKindLine:"ligne",traceKindPolygon:"contour",referenceStreetItem:"{distance} m au {bearing}°, {date}{panorama}",referenceStreetPanorama:" — 360°",referenceStreetTitle:"Photo de rue à {distance} m au {bearing}°, {date}",skyLine:"Ciel : {parts}",skyStarsEye:"étoiles jusqu'à la magnitude {limit}, ce que l'œil atteignait sous ce ciel",skyStarsDeeper:"étoiles jusqu'à la magnitude {limit} à travers un {device} — {gain} magnitudes au-delà des {eye} qu'atteignaient les yeux de l'observateur",skyStarsShallower:"étoiles jusqu'à la magnitude {limit} à travers un {device} — {gain} magnitudes en deçà des {eye} qu'atteignaient les yeux de l'observateur",skyStarsCatalogue:", dessinées jusqu'à {catalogue}, où s'arrête le catalogue de ce projet",skyStarsNone:"aucune étoile ne se détachait d'un ciel aussi clair",skyDetails:"Voir le détail des relevés",skyDetailsHide:"Masquer le détail des relevés",skyShowerActive:"{name} — radiant à {altitude}° de hauteur, {bearing} — environ {rate}/h sous ce ciel, sur un fond sporadique de {sporadic}/h",skyShowerBelowHorizon:"{name} est actif, mais son radiant est sous l'horizon — il n'a rien pu produire",skyNothingActive:"aucune pluie de météores active à cette date — un fond sporadique d'environ {sporadic}/h",showMeteor:"Montrer un météore",skyComet:"La {name}, magnitude {magnitude}, à {altitude}° de hauteur {bearing}, queue longue de {tail}°",skyCometNoTail:"La {name}, magnitude {magnitude}, à {altitude}° de hauteur {bearing}",skyCometBelowHorizon:"La {name} était là, magnitude {magnitude}, mais sous l'horizon — personne ici ne l'a vue",skyCometInDaylight:"La {name}, magnitude {magnitude}, à {altitude}° de hauteur {bearing} — mais à {elongation}° du Soleil seulement",showComet:"Montrer la comète",skyNova:"La {name}, étoile nouvelle de magnitude {magnitude}, à {altitude}° de hauteur {bearing}",skyNovaBelowHorizon:"La {name} brillait, magnitude {magnitude}, mais sous l'horizon : personne ici ne l'a vue",showNova:"Montrer l'étoile nouvelle",skyEclipsePartial:"Éclipse de Soleil : la Lune cache {percent} % du Soleil à {time}, à {altitude}° de hauteur {bearing}",skyEclipseTotal:"Éclipse totale de Soleil : le Soleil est entièrement caché à partir de {time} pendant {duration}, à {altitude}° de hauteur {bearing}",skySupermoon:"Pleine Lune à {distance} km : {diameter}° de large, {percent} % de plus qu'à sa distance moyenne — une « super-lune », et pas plus grosse à l'horizon qu'au zénith",skyMicromoon:"Pleine Lune à {distance} km : {diameter}° de large, {percent} % de moins qu'à sa distance moyenne — une « micro-lune », et pas plus petite à l'horizon qu'au zénith",skyRedMoon:"La « lune rousse » : la pleine Lune de la lunaison qui suit Pâques, à {altitude}° de hauteur {bearing} — basse, donc rougie par l'air qu'elle traverse, et ni plus grosse ni plus brillante qu'une autre",skySatellitePasses:"{count} satellites ont traversé ce ciel assez brillants pour être vus, le plus brillant {name}, magnitude {magnitude}, à {altitude}° de hauteur {bearing} à {time}",skySatellitePassesOne:"un satellite a traversé ce ciel assez brillant pour être vu : {name}, magnitude {magnitude}, à {altitude}° de hauteur {bearing} à {time}",skySatelliteTrain:"dont un train de {count} Starlink lancés le {date}",skySatellitePassesNone:"d'après les éléments orbitaux archivés pour cette date, aucun satellite éclairé n'a traversé ce ciel assez brillant pour être vu",skySatelliteElementsGap:"aucun élément orbital archivé près de cette date",skyReentries:"rentrées au registre : {list}",skyReentriesMore:"{count} autres",skyReentrySeen:"{name} est retombé à {time}, vu depuis {place} (à {distance} km)",skyReentryObserved:"{name} est retombé à {time}, vu",skyReentryOffset:", à {minutes} min de l'observation",skyReentryPredicted:"{name} est retombé vers {time} ± {hours} h, on ne sait où",skyReentryDay:"{name} est retombé le {date} (UTC), ni l'heure ni le lieu connus",skyFireballs:"{count} bolides enregistrés par le Global Meteor Network, le plus brillant de magnitude {magnitude} à {time}, à {altitude}° de hauteur {bearing}, à {distance} km ({stations} stations)",skyFireballsOne:"un bolide enregistré par le Global Meteor Network : magnitude {magnitude} à {time}, à {altitude}° de hauteur {bearing}, à {distance} km ({stations} stations)",showFireball:"Montrer le bolide",showSatellite:"Montrer un satellite",skyOpticsPossible:"nuages de glace suffisants, autour {source}, pour {forms}",skyOpticsAlignment:" — tout sauf les halos exige des cristaux tombant à plat, ici supposés alignés à {alignment} %, qu'aucun relevé ne donne",skyOpticsHalo22:"un halo à {angle}°",skyOpticsHalo46:"un halo à {angle}°",skyOpticsParhelia:"des parhélies à {angle}° de part et d'autre",skyOpticsTangentArc:"un arc tangent au sommet",skyOpticsParhelicCircle:"un cercle parhélique blanc faisant le tour du ciel à sa hauteur",skyOpticsCircumzenithal:"un arc circumzénithal à {angle}° de hauteur",skyOpticsCircumhorizontal:"un arc circumhorizontal très au-dessous",skyOpticsPillar:"un pilier dressé au-dessus",skyOpticsNoIce:"aucun nuage de glace : ni halo ni parhélie",skyOpticsHidden:"des nuages de glace en altitude, mais une couche plus basse les cache",skyOpticsSun:"du Soleil",skyOpticsMoon:"de la Lune",skyBowPossible:"pluie et soleil suffisants pour {forms}",skyBowMoon:"pluie sous une Lune éclairée à {lit} %, de quoi former {forms} — un arc-en-ciel lunaire, que l'œil voit blanc",skyGlowBand:"la Voie lactée à {contrast}× le fond du ciel, à {altitude}° de hauteur {bearing}",skyGlowCone:"la lumière zodiacale à {contrast}× le fond du ciel, à {altitude}° de hauteur {bearing}, à {elongation}° du Soleil — une lueur en cône incliné, aux contours flous, disparue en moins d'une heure",skyGlowZodiacalBand:"la bande zodiacale à {contrast}× le fond du ciel, à {altitude}° de hauteur {bearing} — toute l'écliptique faiblement allumée, ce qui n'est pas ce que les gens rapportent",skyGlowMoon:"ni Voie lactée ni lumière zodiacale : une Lune éclairée à {lit} % tenait le ciel à {sky} magnitudes par seconde d'arc, là où il leur en faut 22",skyGlowTwilight:"ni Voie lactée ni lumière zodiacale : le crépuscule tenait encore le ciel à {sky} magnitudes par seconde d'arc, là où il leur en faut 22",skyGlowTowns:"ni Voie lactée ni lumière zodiacale : la lueur des villes tenait le ciel à {sky} magnitudes par seconde d'arc, là où il leur en faut 22",skyGlowNothingUp:"ciel assez noir ({sky} magnitudes par seconde d'arc), mais ni le plan de la Galaxie ni l'écliptique ne s'y tenaient assez haut",skyBowPrimary:"un arc de {radius}° de rayon, dont le sommet montait à {top}°",skyBowSecondary:"un second, plus pâle, à {radius}°, aux couleurs inversées",skyBowSourceTooHigh:"pluie, mais l'astre à {altitude}° de hauteur : aucun arc ne pouvait dépasser l'horizon, ils se tiennent à {radius}° du point opposé",skyBowHidden:"pluie, mais une couche continue entre elle et la lumière : aucun arc",skyBowNoSource:"pluie, et rien d'allumé pour en tirer un arc",skySatellitesLit:"l'ombre de la Terre montait à {height} km au-dessus de l'observateur, l'orbite basse était donc encore éclairée — {count} objets suivis étaient en orbite ce mois-là",skySatellitesLitWith:"l'ombre de la Terre montait à {height} km au-dessus de l'observateur, l'orbite basse était donc encore éclairée — {count} objets suivis étaient en orbite ce mois-là, dont {eras}",skySatellitesShadowed:"l'ombre de la Terre montait à {height} km au-dessus de l'observateur : sur les {count} objets suivis en orbite ce mois-là, rien en orbite basse n'était éclairé",skySatellitesNotYet:"rien n'était encore en orbite",skySatellitesDaylight:"tout ce qui est en orbite était éclairé, comme toujours de jour, et {eras} pouvaient l'emporter même sur ce ciel",skySatellitesDaylightOne:"tout ce qui est en orbite était éclairé, comme toujours de jour, et {eras} pouvait l'emporter même sur ce ciel",skyUnknown:"indéterminable sans date ni lieu",lookAtDecor:"Regarder cet élément",addDecor:"Ajouter",deleteDecor:"Supprimer l'élément de décor",undo:"Annuler",redo:"Rétablir",viewAccount:"Voir le compte rendu",noObserverRecording:"Aucune URL d'enregistrement définie pour cet observateur",masks:"Masque",masksNone:"Aucun phénomène à masquer pour l'instant",masksBodyFully:"masqué par cet objet",masksBodyPartly:"masqué à {share} % par cet objet",masksBodyNot:"non masqué par cet objet",modelPickerTitle:"Choisir un modèle 3D",modelPickerClose:"Fermer",modelPickerChoose:"Choisir un modèle 3D",modelPickerUse:"Utiliser ce modèle",modelPickerIncomplete:"Non dessiné tant que le nom et la licence du modèle ne sont pas donnés",addObserver:"Ajouter un observateur",surveyLabel:"Décor tiré d'un relevé",surveySource:"Décor tiré de",surveyDated:"Relevés du : {dates}.",surveyLaserLabel:"laser",surveyPhotoLabel:"photo aérienne",surveyMapLabel:"carte",surveyLampsLabel:"OpenStreetMap",surveyWarning:"⚠ Ce décor vient de relevés du {survey}, postérieurs à l'observation ({observation}) : ce n'est pas ce qui se tenait là alors. Gardez-le comme repère, ou supprimez-le.",surveyRadius:"Rayon",surveyRadiusTitle:"Jusqu'où autour de l'observateur le relevé est interrogé, en mètres. Un rayon plus large ramène des bâtiments, ponts et lignes plus éloignés ; les arbres viennent du laser, qui n'est interrogé que dans 150 m.",surveySourceTitle:"Le relevé d'où sont tirés, tout seuls, les arbres, bâtiments, ponts et lignes aériennes autour du lieu quand vous donnez un lieu à l'enregistrement : ils sont mis dans la liste, à leur place, leur hauteur et leur largeur mesurées. Les coordonnées du lieu sont envoyées à ce service. Aucun laisse le décor à vous seul. Ce que vous avez placé vous-même n'est jamais touché.",surveySourceNone:"Aucun (tout à la main)",surveyBusy:"Recherche du décor autour de l'observateur…",surveyDone:"D'après {source} : arbres {trees}, bâtiments {buildings}, ponts {bridges}, lignes électriques {lines}. Ce sont ceux du jour du relevé, pas ceux de l'enregistrement : gardez-les, déplacez-les ou supprimez-les.",surveyNone:"Aucun arbre, bâtiment, pont ni ligne électrique trouvé dans un rayon de {radius} m.",surveyKept:"Ce que vous avez placé vous-même reste tel quel.",surveyUnreachable:"Le relevé n'a pas pu être joint. Réessayez plus tard.",surveyFurniturePending:"Éclairage public et feux en attente d'OpenStreetMap…",surveyFurnitureDone:"D'après {source} : lampadaires {lamps}, feux {signals}, passages piétons {crossings}, panneaux {signs}.",surveyFurnitureUnavailable:"Éclairage public et feux non disponibles pour l'instant : OpenStreetMap ne répond pas.",surveyFurnitureRetry:"Réessayer",narrativePlaceholder:"Ce que l'observateur a rapporté, dans ses propres mots",narrativeSource:"Rédigé par",narrativeNeedsSetting:"Renseignez « {setting} » ({source}) pour générer la reconstitution d'après le récit",narrativeNeedsAsk:"Rien à envoyer pour l'instant",narrativeRemember:"Retenir sur cet appareil",narrativeDraft:"Générer la reconstitution",narrativeStop:"Arrêter",narrativeWorking:"Lecture du récit…",narrativeApplied:"{count} champs écrits dans l'éditeur",narrativeUnchanged:"Le récit n'énonce rien que l'enregistrement sache encore porter",narrativeStated:"Ce que l'observateur a dit",narrativeDerived:"Déduit du récit",narrativeAssumed:"Supposé, pour que la reconstitution tourne : à vérifier",narrativeGaps:"Ce que rien n'a pu trancher",narrativeErrorCredential:"Pas de clé, ou une clé refusée : vérifiez-la sur console.anthropic.com",narrativeErrorRateLimited:"Trop de requêtes sur votre compte : patientez un instant et redemandez",narrativeErrorRefused:"Le récit n'a pas reçu de réponse. Le reformuler peut aider, le redemander non",narrativeErrorMalformed:"La réponse n'était pas un brouillon exploitable : cela vaut la peine de redemander",narrativeErrorUnreachable:"Rien n'a répondu : vérifiez la connexion",narrativeErrorRejected:"Refusé : {detail}",observerAge:"Âge alors",observerBirth:"Né le",observerPerception:{"color-vision":"Vision des couleurs","color-vision.hint":"Comment les couleurs apparaissent à qui a des cônes différents (Machado et al. 2009). Ne fait que recolorer : luminosité et résolution inchangées.","color-vision.type":"Type","color-vision.type.normal":"Typique","color-vision.type.protan":"Protan (rouge faible ou aveugle)","color-vision.type.deutan":"Deutan (vert faible ou aveugle)","color-vision.type.tritan":"Tritan (bleu faible ou aveugle)","color-vision.severity":"Sévérité",intoxication:"Alcool","intoxication.hint":"Abaisse la sensibilité au contraste d'environ 0,9 dB à 0,08 % d'alcool dans le sang (une étude contrôlée ; les résultats varient), montré jusqu'à 0,1 % au plus : un taux supérieur est consigné mais montré comme 0,1 %, rien n'ayant été mesuré au-delà. Vision double, champ rétréci et autres drogues ne sont pas modélisés : aucune source ne les chiffre.","intoxication.bloodAlcohol":"Alcoolémie",fatigue:"Fatigue","fatigue.hint":"Énoncée seulement : le manque de sommeil n'a pas été montré comme changeant ce que reçoit un œil sain, l'image est donc inchangée. Il touche l'attention et la mémoire, pas la vue.","fatigue.hoursAwake":"Éveillé depuis"},observerOccupation:"Profession",accountSource:"Récit recueilli",accountUrl:"Source (URL)",accountSourceUnknown:"on ne sait pas",accountSourceOnSite:"enquête sur site",accountSourceInterview:"entretien en personne",accountSourceTelephone:"par téléphone",accountSourceQuestionnaire:"questionnaire",accountSourceLetter:"écrit par l'observateur",accountSourceSocialMedia:"publié en ligne par l'observateur",accountSourcePress:"presse ou radiodiffusion",accountFollowedUp:"Recontacté",accountUnknown:"on ne sait pas",accountYes:"oui",accountNo:"non",questionUnanswered:"Rien dans cet enregistrement ne répond à l'une des questions qu'une reconstitution doit trancher",durationRequired:"L'observation a besoin d'une longueur pour être rejouée — indiquez-la, ou une heure de fin, qui peut être approximative",questionsUnanswered:"{count} des questions auxquelles une reconstitution complète répond restent sans réponse ici",emptyDecor:"Aucun élément de décor",emptyMilestones:"Aucun moment",emptyReferences:"Aucune photo",emptyReferenceLandmarks:"Aucun repère",emptyTraces:"Aucun tracé d'enquêteur",emptyShapes:"Aucune forme",addReference:"Ajouter une photo",principalObserver:"Observateur de ce compte rendu",deleteObserver:"Supprimer l'observateur"};export{r as sightingEditorMessages_fr};