ocearo-ui
Version:
Ocean Robot UI: Sailing made smarter
1 lines • 26.6 kB
JavaScript
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[890],{29927:function(e,n,t){var r={"./default/Scene.jsx":[42967,967],"./optimist/Scene.jsx":[96154,154],"./sailboat/Scene.jsx":[82274,274],"./ship/Scene.jsx":[75221,221],"./windsurf/Scene.jsx":[92975,975]};function o(e){if(!t.o(r,e))return Promise.resolve().then(function(){var n=Error("Cannot find module '"+e+"'");throw n.code="MODULE_NOT_FOUND",n});var n=r[e],o=n[0];return t.e(n[1]).then(function(){return t(o)})}o.keys=function(){return Object.keys(r)},o.id=29927,e.exports=o},10890:function(e,n,t){"use strict";t.r(n),t.d(n,{default:function(){return X}});var r=t(57437),o=t(2265),a=t(68328),i=t(44725),l=t(85903),s=t(5550),c=t(11909),u=t(21276),d=t(88345),g=t(72079),h=t(53082);let m=(0,d.g)({time:0,speed:1,scale:3,opacity:.5,color:new g.Ilk(7895160),foamColor:new g.Ilk(16777215),waterColor:new g.Ilk(26367),rainbowActive:0},"\n varying vec2 vUv;\n varying float vElevation;\n \n void main() {\n vUv = uv;\n \n // Add subtle vertex displacement for a wavy effect.\n float elevation = sin(position.x * 0.2 + position.y * 0.3) * 0.1;\n vElevation = elevation;\n vec3 newPosition = position + normal * elevation;\n \n gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);\n }\n ","\n uniform float time;\n uniform float speed;\n uniform float scale;\n uniform float opacity;\n uniform vec3 color;\n uniform vec3 foamColor;\n uniform vec3 waterColor;\n uniform float rainbowActive; // Controls whether the rainbow effect is applied.\n\n varying vec2 vUv;\n varying float vElevation;\n\n // Standard noise functions.\n vec4 permute(vec4 x) {\n return mod(((x * 34.0) + 1.0) * x, 289.0);\n }\n\n vec2 fade(vec2 t) {\n return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);\n }\n\n float cnoise(vec2 P) {\n vec4 Pi = floor(P.xyxy) + vec4(0.0, 0.0, 1.0, 1.0);\n vec4 Pf = fract(P.xyxy) - vec4(0.0, 0.0, 1.0, 1.0);\n Pi = mod(Pi, 289.0);\n vec4 ix = Pi.xzxz;\n vec4 iy = Pi.yyww;\n vec4 fx = Pf.xzxz;\n vec4 fy = Pf.yyww;\n vec4 i = permute(permute(ix) + iy);\n vec4 gx = 2.0 * fract(i * 0.0243902439) - 1.0;\n vec4 gy = abs(gx) - 0.5;\n vec4 tx = floor(gx + 0.5);\n gx = gx - tx;\n vec2 g00 = vec2(gx.x, gy.x);\n vec2 g10 = vec2(gx.y, gy.y);\n vec2 g01 = vec2(gx.z, gy.z);\n vec2 g11 = vec2(gx.w, gy.w);\n vec4 norm = 1.79284291400159 - 0.85373472095314 *\n vec4(dot(g00, g00), dot(g10, g10), dot(g01, g01), dot(g11, g11));\n g00 *= norm.x;\n g10 *= norm.y;\n g01 *= norm.z;\n g11 *= norm.w;\n float n00 = dot(g00, vec2(fx.x, fy.x));\n float n10 = dot(g10, vec2(fx.y, fy.y));\n float n01 = dot(g01, vec2(fx.z, fy.z));\n float n11 = dot(g11, vec2(fx.w, fy.w));\n vec2 fade_xy = fade(Pf.xy);\n vec2 n_x = mix(vec2(n00, n01), vec2(n10, n11), fade_xy.x);\n float n_xy = mix(n_x.x, n_x.y, fade_xy.y);\n return 2.3 * n_xy;\n }\n\n // HSL to RGB conversion function.\n vec3 hsl2rgb(vec3 hsl) {\n vec3 rgb = clamp(abs(mod(hsl.x * 6.0 + vec3(0.0, 4.0, 2.0), 6.0) - 3.0) - 1.0,\n 0.0, 1.0);\n rgb = rgb * rgb * (3.0 - 2.0 * rgb);\n return hsl.z + hsl.y * (rgb - 0.5) * (1.0 - abs(2.0 * hsl.z - 1.0));\n }\n\n void main() {\n // Combine multiple layers of noise to build a complex water pattern.\n float baseNoise = cnoise(vUv * scale + vec2(time * speed, 0.0));\n float detailNoise = cnoise(vUv * scale * 2.0 + vec2(time * speed * 1.5, 0.0)) * 0.5;\n float turbulence = cnoise(vUv * scale * 4.0 + vec2(time * speed * 2.0, 0.0)) * 0.25;\n float noise = baseNoise + detailNoise + turbulence;\n \n // Create a wake pattern.\n float wake = smoothstep(0.3, 0.7, 1.0 - abs(vUv.x - 0.5) * 2.0);\n \n // Create a foam effect.\n float foam = smoothstep(0.4, 0.6, noise + wake);\n \n // Mix water and foam colors, then blend in the base color.\n vec3 finalColor = mix(waterColor, foamColor, foam);\n finalColor = mix(finalColor, color, wake * 0.5);\n \n // Adjust dynamic opacity.\n float alpha = opacity * (wake + foam * 0.5) * (1.0 - vUv.y);\n \n // Add wave highlights.\n float highlight = smoothstep(0.2, 0.4, noise + wake) *\n (1.0 - smoothstep(0.4, 0.6, noise + wake));\n finalColor += highlight * foamColor * 0.5;\n \n // --- Rainbow Effect ---\n // When rainbowActive is enabled, overlay a dynamic rainbow gradient.\n if (rainbowActive > 0.5) {\n // Cycle the hue based on the horizontal UV and time.\n float rainbowHue = mod(vUv.x + time * 0.5, 1.0);\n vec3 rainbowColor = hsl2rgb(vec3(rainbowHue, 1.0, 0.5));\n // Blend the rainbow with the original finalColor.\n finalColor = mix(finalColor, rainbowColor, 0.7);\n }\n \n gl_FragColor = vec4(finalColor, alpha);\n }\n ");(0,u.e)({TrailShaderMaterial:m});let f=e=>{let{color:n="#787878",waterColor:t="#0066ff",foamColor:a="#ffffff",speed:i=1,scale:l=3,opacity:s=.5}=e,c=(0,o.useRef)(),{getSignalKValue:d}=(0,h.yC)();return(0,u.F)((e,n)=>{if(c.current){c.current.uniforms.time.value+=n;let e="auto"==d("steering.autopilot.state");c.current.uniforms.rainbowActive.value=e?1:0}}),(0,r.jsxs)("mesh",{rotation:[-Math.PI/2,0,Math.PI/2],position:[0,0,22.5],children:[(0,r.jsx)("planeGeometry",{args:[40,2.2,128,32]}),(0,r.jsx)("trailShaderMaterial",{ref:c,color:new g.Ilk(n),waterColor:new g.Ilk(t),foamColor:new g.Ilk(a),speed:i,scale:l,opacity:s,transparent:!0,depthWrite:!1,blending:g.WMw})]})};var v=t(54752),p=t(33866),x=t(79257);(0,u.e)({Water:v.B,Sky:p.q});var w=function(){let{nightMode:e}=(0,h.yC)(),n=(0,o.useRef)(),t=(0,o.useRef)(),a=(0,o.useRef)(),i=(0,u.D)(e=>e.gl),l=(0,u.D)(e=>e.scene),s=(0,o.useMemo)(()=>new g.Pa4,[]),c=(0,x.mE)("assets/moon.jpg"),d=(0,u.H)(g.dpR,"assets/waternormals.jpg");(0,o.useMemo)(()=>{d.wrapS=d.wrapT=g.rpg},[d]);let m=(0,o.useMemo)(()=>new g._12(1e4,1e4,32,32),[]),f=(0,o.useMemo)(()=>({textureWidth:256,textureHeight:256,waterNormals:d,sunDirection:new g.Pa4,sunColor:e?12642559:16777215,waterColor:e?6702:30668,distortionScale:2,format:i.outputColorSpace,reflectivity:0}),[d,i.outputColorSpace,e]);(0,u.F)(()=>{let r=e?45:2,o=e?30:180;if(t.current){let a=t.current.material.uniforms;e?(a.turbidity.value=.2,a.rayleigh.value=.5,a.mieCoefficient.value=.01,a.mieDirectionalG.value=.8):(a.turbidity.value=1,a.rayleigh.value=1,a.mieCoefficient.value=.003,a.mieDirectionalG.value=.5);let i=g.M8C.degToRad(90-r),l=g.M8C.degToRad(o);s.setFromSphericalCoords(1,i,l),a.sunPosition.value.copy(s),n.current&&n.current.material.uniforms.sunDirection.value.copy(s).normalize()}}),(0,o.useEffect)(()=>{e?l.background=new g.Ilk(2068):l.background=new g.Ilk(8900331);let n=new g.Ilk(e?4640:8900331);return l.fog=new g.yo9(n,15e-5),i.outputColorSpace=g.KI_,()=>{l.background=null,l.environment=null,l.fog=null}},[l,e,i]);let v=0;return(0,u.F)((e,t)=>{(v+=t)>.1&&(n.current&&(n.current.material.uniforms.time.value+=.5*v),v=0)}),(0,r.jsxs)(r.Fragment,{children:[!e&&(0,r.jsx)("sky",{ref:t,scale:45e4}),e&&(0,r.jsxs)("mesh",{ref:a,position:[600,200,-1500],children:[(0,r.jsx)("sphereGeometry",{args:[80,32,32]}),(0,r.jsx)("meshStandardMaterial",{map:c,emissive:16777215,emissiveIntensity:.8})]}),(0,r.jsx)("water",{ref:n,args:[m,f],"rotation-x":-Math.PI/2,position:[0,-1,0]})]})},y=t(14578),M=t(63321);let b=(0,o.createContext)(),j=()=>(0,o.useContext)(b),C=(e,n,t,r)=>{let o=t.split(".").reduce((e,n)=>null==e?void 0:e[n],r);void 0!==o&&(e[n]=o)},S=e=>{let{children:n}=e,[t,a]=(0,o.useState)({}),[i,l]=(0,o.useState)([]),s=(0,o.useRef)(null),c=(0,o.useRef)({});return(0,o.useEffect)(()=>{let e=async e=>{console.log("Fetching static vessel information...");try{let n=await e.API().then(e=>e.vessels()),t=Object.entries(n).map(e=>{let[n,t]=e,r={mmsi:n};return C(r,"name","name",t),C(r,"latitude","navigation.position.value.latitude",t),C(r,"longitude","navigation.position.value.longitude",t),C(r,"sog","navigation.speedOverGround.value",t),C(r,"cog","navigation.courseOverGroundTrue.value",t),C(r,"cogMagnetic","navigation.courseOverGroundMagnetic.value",t),C(r,"heading","navigation.headingTrue.value",t),C(r,"headingMagnetic","navigation.headingMagnetic.value",t),C(r,"length","design.length.value.overall",t),C(r,"beam","design.beam.value",t),C(r,"callsign","communication.callsignVhf",t),C(r,"shipType","design.aisShipType.value.id",t),r.lastUpdate=Date.now(),r});console.log("Fetched ".concat(t.length," vessels.")),l(t);let r={};t.forEach(e=>{e.mmsi&&(null!==e.latitude||null!==e.longitude)&&(r[e.mmsi]=e)}),Object.keys(r).length>0&&(console.log("Initializing AIS data with ".concat(Object.keys(r).length," vessels")),a(r))}catch(e){console.error("Error fetching static vessel info:",e)}},n=e=>{if(!(null==e?void 0:e.updates)){console.warn("Delta is missing or does not contain updates:",e);return}let n=e=>({mmsi:e,name:"unknown",latitude:null,longitude:null,sog:null,cog:null,cogMagnetic:null,heading:null,headingMagnetic:null}),t=e.context.replace("vessels.","");if(!t){console.warn("Update missing MMSI context:",e);return}c.current[t]=Date.now(),a(r=>{let o=r[t]||n(t);return o.lastUpdate=c.current[t],e.updates.forEach(e=>{e.values.forEach(e=>{switch(e.path){case"name":o.name=e.value;break;case"navigation.position":o.latitude=e.value.latitude,o.longitude=e.value.longitude;break;case"navigation.speedOverGround":o.sog=e.value;break;case"navigation.courseOverGroundTrue":o.cog=e.value;break;case"navigation.courseOverGroundMagnetic":o.cogMagnetic=e.value;break;case"navigation.headingTrue":o.heading=e.value;break;case"navigation.headingMagnetic":o.headingMagnetic=e.value}})}),{...r,[t]:o}})};return(async()=>{try{let{signalkUrl:t}=M.Z.getAll();if(console.log("SignalK URL:",t),!t)throw Error("SignalK URL is undefined or invalid.");let[r,o]=t.replace(/https?:\/\//,"").split(":");console.log("Connecting to SignalK at hostname: ".concat(r,", port: ").concat(o));let a=new y.default({hostname:r||"localhost",port:parseInt(o)||3e3,useTLS:t.startsWith("https"),reconnect:!0,autoConnect:!1,notifications:!1,subscriptions:[{context:"vessels.*",subscribe:[{path:"navigation.position"},{path:"navigation.speedOverGround"},{path:"navigation.courseOverGroundTrue"},{path:"navigation.courseOverGroundMagnetic"},{path:"navigation.headingTrue"},{path:"navigation.headingMagnetic"}]}]});s.current=a,await a.connect(),console.log("SignalK client connected."),await e(a),a.on("delta",n)}catch(e){console.error("Error connecting to SignalK:",e)}})(),()=>{var e;console.log("Disconnecting SignalK client..."),null===(e=s.current)||void 0===e||e.disconnect()}},[]),(0,r.jsx)(b.Provider,{value:{aisData:t,vesselIds:i},children:n})};var R=t(45476);let I=async e=>{try{let n=await t(29927)("./".concat(e,"/Scene.jsx"));return n.default?n.default:n.Model}catch(n){throw console.error("Error loading ".concat(e," component:"),n),n}},P=e=>0===e?"windsurf":30===e?"optimist":36===e?"sailboat":"ship",E=(0,o.forwardRef)((e,n)=>{let{position:t,visible:a,boatData:i,onHover:l}=e,[s,c]=(0,o.useState)(null),u=P(i.shipType);if((0,o.useEffect)(()=>{let e=!0;return I(u).then(n=>{e&&c(()=>n)}).catch(e=>console.error("Failed to load ".concat(u,":"),e)),()=>{e=!1}},[u]),!s)return null;let d=[i.name?function(e,n){let t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"",r=null!=n?"".concat(n).concat(t):"N/A";return"".concat(e,": ").concat(r,"\n")}("Name",i.name,""):"MMSI ".concat(i.mmsi.replace("urn:mrn:imo:mmsi:",""),"\n")].join(""),g=Math.max(i.length||10,4)/10;return(0,r.jsxs)("group",{ref:n,position:t,visible:a,children:[(0,r.jsx)("group",{onClick:e=>{e.stopPropagation(),s&&l&&l(i),console.log("Clicked on boat:",i.name||i.mmsi)},children:(0,r.jsx)(s,{scale:[g,g,g]})}),(0,r.jsx)("group",{position:[1.5,4,0],children:(0,r.jsx)(R.x,{position:[0,0,0],fontSize:.4,maxWidth:3,lineHeight:1.2,textAlign:"left",color:"white",anchorX:"center",anchorY:"middle",font:"fonts/Roboto-Bold.ttf",renderOrder:1e3,depthTest:!1,children:d})})]})});E.displayName="AISBoat";let O=e=>{if(e.material)return e;for(let n of e.children){let e=O(n);if(e)return e}return null},T=function(e,n,t){let r=!(arguments.length>3)||void 0===arguments[3]||arguments[3],o=M.Z.get("aisLengthScalingFactor")||.7,a=n*o,i=t*o;r?(e.position.x+=(a-e.position.x)*.1,e.position.z+=(i-e.position.z)*.1):e.position.set(a,0,i)},_=function(e,n){let t=!(arguments.length>2)||void 0===arguments[2]||arguments[2],r=-n;t?e.children[0].rotation.y=e.children[0].rotation.y+(r-e.children[0].rotation.y)*.1:e.children[0].rotation.y=r};var k=e=>{let{onUpdateInfoPanel:n}=e,{aisData:t,vesselIds:a}=j(),i=(0,o.useRef)({}),l=(0,o.useRef)(null),{getSignalKValue:s,getBoatRotationAngle:c,getAISBoatRotationAngle:d,convertLatLonToXY:g}=(0,h.yC)(),[m,f]=(0,o.useState)(null),v=(0,o.useRef)(0),p=()=>M.Z.get("aisLengthScalingFactor")||.7,x=500*p(),w=550*p(),y=3e3*p();(0,o.useRef)(!1),(0,u.F)(()=>{let e=s("navigation.position"),n=c();v.current=n,l.current=e,(null==e?void 0:e.latitude)&&(null==e?void 0:e.longitude)&&Object.keys(i.current).length&&(performance.now(),Object.values(t).forEach(n=>{if(null==n.latitude||null==n.longitude||!i.current[n.mmsi])return;let t=i.current[n.mmsi];if(!t)return;n.lastUpdate;let{x:r,y:o}=g({lat:n.latitude,lon:n.longitude},{lat:e.latitude,lon:e.longitude});T(t,r,o,!0),_(t,d(n),!0);let a=Math.sqrt((r*p())**2+(o*p())**2);if(0===r&&0===o){t.visible=!1;return}if(a>0&&a<=y){t.visible=!0,t.currentColor||(t.currentColor=a<x?"red":"white");let e=t.currentColor;"red"===t.currentColor&&a>w?e="white":"white"===t.currentColor&&a<x&&(e="red");let r=O(t.children[0]);r?(t.redMaterial||(t.redMaterial=r.material.clone(),t.redMaterial.color.set("red")),t.whiteMaterial||(t.whiteMaterial=r.material.clone(),t.whiteMaterial.color.set("white")),"red"===e&&"red"!==t.currentMaterial?(r.material=t.redMaterial,t.currentMaterial="red"):"white"===e&&"white"!==t.currentMaterial&&(r.material=t.whiteMaterial,t.currentMaterial="white"),t.currentColor=e):console.warn("Material not found for boat ".concat(n.mmsi))}else t.visible=!1}))});let b=(0,o.useMemo)(()=>{let e=l.current;return(null==e?void 0:e.latitude)&&(null==e?void 0:e.longitude)?a.filter(e=>{if(!e.mmsi||e.mmsi.startsWith("urn:mrn:signalk:uuid:")||e.mmsi.startsWith("227925790")||e.mmsi.startsWith("urn:mrn:imo:mmsi:230035780"))return!1;let n=t[e.mmsi];return!!n&&null!==n.latitude&&null!==n.longitude}).map(n=>{let o=t[n.mmsi],a=g({lat:o.latitude,lon:o.longitude},{lat:e.latitude,lon:e.longitude});if(0===a.x&&0===a.y)return!1;let l=M.Z.get("aisLengthScalingFactor")||.7,s=a.x*l,c=a.y*l,u=Math.sqrt(s*s+c*c)<=y;return(0,r.jsx)(E,{ref:e=>{e&&(e.mmsi=n.mmsi,i.current[n.mmsi]=e)},position:[s,0,c],visible:u,boatData:{...n,...o},onHover:e=>{m&&e&&m.mmsi===e.mmsi?f(null):f(e)}},n.mmsi)}):[]},[a,t,y,m,g]),C=function(e,n){let t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"",r=arguments.length>3&&void 0!==arguments[3]&&arguments[3],o=arguments.length>4&&void 0!==arguments[4]&&arguments[4];return null==n||""===n||"string"==typeof n&&0===n.trim().length?null:(r&&null!==n&&(n=(0,h.Ux)(n)),o&&null!==n&&(n=(0,h.Qj)(n)),"".concat(e,": ").concat(n).concat(t))},S=m?[C("Name",m.name),C("MMSI",(e=>{if(!e)return null;let n=e;for(let e of["urn:mrn:imo:mmsi:","urn:mrn:signalk:uuid:"])if(n.startsWith(e)){n=n.substring(e.length);break}return n})(m.mmsi)),C("Distance",(e=>{if(!e||!l.current)return null;let n=l.current;if(!(null==n?void 0:n.latitude)||!(null==n?void 0:n.longitude)||!e.latitude||!e.longitude)return null;let{x:t,y:r}=g({lat:e.latitude,lon:e.longitude},{lat:n.latitude,lon:n.longitude});return Math.round(Math.sqrt(t*t+r*r)/1852*10)/10})(m)," NM"),C("Length",m.length,"m"),C("Type",m.shipType),C("SOG",m.sog," kts",!1,!0),C("COG",m.cog,"\xb0",!0),C("Heading",m.heading,"\xb0",!0),C("Beam",m.beam,"m"),C("Draft",m.draft,"m"),C("Callsign",m.callsign),C("Destination",m.destination)].filter(e=>null!==e).join("\n"):"";return o.useEffect(()=>{n&&n(S)},[m,S,n]),(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("group",{rotation:[0,-v.current,0],children:b}),m&&(0,r.jsx)("group",{position:[0,1,0],children:(0,r.jsxs)("mesh",{scale:[.1,.1,.1],visible:!1,children:[(0,r.jsx)("boxGeometry",{}),(0,r.jsx)("meshBasicMaterial",{color:"yellow"})]})})]})},N=t(1);let A=o.memo(e=>{let{radius:n,isOuter:t,markerColorPrimary:a,markerColorGreen:i,markerColorRed:l}=e,s=(0,o.useMemo)(()=>{let e=[];for(let o=0;o<360;o+=10){let s=g.M8C.degToRad(o-90),c=o%30==0,u=t?c?.4:.2:c?.3:.15,d=(n+.5*u+.2)*Math.cos(s),h=(n+.5*u+.2)*Math.sin(s),m=t&&o>0&&o<61,f=t&&o>=300&&o<360,v=m?i:f?l:a;if(!t&&c){let n;n=0===o?"N":90===o?"E":180===o?"S":270===o?"W":o.toString(),e.push((0,r.jsx)(R.x,{characters:"NESW0123456789",position:[d,.01,h],color:a,fontSize:.5,rotation:[-Math.PI/2,0,Math.PI/2-s],font:"fonts/Roboto-Bold.ttf",anchorY:"middle",children:n},"text-".concat(o)))}else e.push((0,r.jsx)(N.aL,{args:[u/2,16,16],position:[d,0,h],children:(0,r.jsx)("meshBasicMaterial",{color:v})},"marker-".concat(t?"outer":"inner","-").concat(o)))}return e},[n,t,a,i,l]);return(0,r.jsx)(r.Fragment,{children:s})});A.displayName="StaticMarkers";let F=o.memo(e=>{let{innerRadius:n,outerRadius:t,dialColor:o,opacity:a=1,transparent:i=!1}=e;return(0,r.jsx)(N.FM,{args:[n,t,64],rotation:[Math.PI/2,0,0],children:(0,r.jsx)("meshBasicMaterial",{color:o,side:g.ehD,transparent:i,opacity:a})})});F.displayName="StaticRing";let G=e=>{let{outerRadius:n,innerRadius:t}=e,a=h.FV,i=h.HH,{nightMode:l,getSignalKValue:s,getBoatRotationAngle:c}=(0,h.yC)(),u=l?h.eF:16777215,d=c(),g=M.Z.get("compassNorthUp"),m=(0,o.useMemo)(()=>({innerRadius:t,outerRadius:n,dialColor:u,markerColorPrimary:0,markerColorGreen:a,markerColorRed:i}),[t,n,u,0,a,i]);return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)("group",{rotation:[0,d+(g?0:Math.PI),0],children:[(0,r.jsx)(F,{innerRadius:m.innerRadius,outerRadius:m.outerRadius,dialColor:m.dialColor}),(0,r.jsx)(A,{radius:m.innerRadius,isOuter:!1,markerColorPrimary:m.markerColorPrimary,markerColorGreen:m.markerColorGreen,markerColorRed:m.markerColorRed})]}),(0,r.jsxs)("group",{children:[(0,r.jsx)(F,{innerRadius:m.innerRadius+1,outerRadius:m.outerRadius+1,dialColor:m.dialColor,transparent:!0,opacity:.5}),(0,r.jsx)(A,{radius:m.innerRadius+1,isOuter:!0,markerColorPrimary:m.markerColorPrimary,markerColorGreen:m.markerColorGreen,markerColorRed:m.markerColorRed})]})]})};G.displayName="CompassDial";var D=t(95723),U=()=>(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(G,{outerRadius:5.6,innerRadius:5}),(0,r.jsx)(D.Z,{outerRadius:5.6+1.1})]}),L=t(58181),z=JSON.parse('{"N":{"52":[4.98,5.86,6.31,6.45,6.51,6.52,6.41],"60":[5.25,6.11,6.56,6.73,6.79,6.82,6.79],"75":[5.45,6.33,6.77,7.01,7.13,7.2,7.24],"90":[5.66,6.55,7,7.25,7.38,7.53,7.7],"110":[5.49,6.49,7.04,7.4,7.69,7.97,8.38],"120":[5.32,6.36,6.97,7.39,7.77,8.1,8.6],"135":[4.81,5.92,6.68,7.15,7.55,7.95,8.85],"150":[4.09,5.17,6.04,6.61,6.99,7.31,7.93],"angles":[52,60,75,90,110,120,135,150],"speeds":[6,8,10,12,14,16,20],"beat_angle":[43.6,42,41.2,41.2,41.7,42.1,44.2],"beat_vmg":[3.26,3.91,4.24,4.34,4.36,4.34,4.16],"run_angle":[144.8,147.8,148.5,149.6,171.8,175.4,177.2],"run_vmg":[3.54,4.48,5.23,5.73,6.17,6.67,7.36]}}');let H={DEG2RAD:Math.PI/180,ROTATION_INTERPOLATION_FACTOR:.05,SOG_SMOOTHING_FACTOR:.1,DEFAULT_SOG:3,ANGLE_INCREMENT:10,SPHERE_SIZE:.4,SPHERE_SEGMENTS:32,DEFAULT_LINE_WIDTH:1,PLOTS_COUNT:5,FRAME_TO_MINUTE_RATIO:3600},W=(e,n)=>26.8224*e*n*.1,Z=(e,n,t)=>{if(!e||!n)return new g.Pa4(0,0,0);let r=e*H.DEG2RAD,o=W(n,t);return new g.Pa4(o*Math.sin(r),0,-o*Math.cos(r))},B=(e,n)=>{if(!(null==e?void 0:e.length))return 0;let t=0,r=e.length-1;for(;t<r;){let o=Math.floor((t+r)/2);e[o]<n?t=o+1:r=o}return t},q=e=>{let{position:n,color:t}=e;return n?(0,r.jsxs)("mesh",{position:n,children:[(0,r.jsx)("sphereGeometry",{args:[H.SPHERE_SIZE,H.SPHERE_SEGMENTS,H.SPHERE_SEGMENTS]}),(0,r.jsx)("meshStandardMaterial",{color:t})]}):null},K=e=>{let{points:n,color:t}=e;return(null==n?void 0:n.length)?(0,r.jsx)(L.x,{points:n,color:t,lineWidth:H.DEFAULT_LINE_WIDTH}):null},V=o.memo(e=>{let{timeInMinute:n,windSpeed:t}=e,a=(0,o.useRef)(z.N),i=(0,o.useCallback)((e,n,t,r)=>{if(!(null==e?void 0:e.length)||!(null==n?void 0:n.length)||e.length<=t||n.length<=t)return console.warn("Invalid angle or VMG data"),null;let o=e[t],a=n[t],i=o*H.DEG2RAD,l=W(a,r);return new g.Pa4(l*Math.sin(i),0,-l*Math.cos(i))},[]),l=(0,o.useCallback)((e,n)=>{let{speeds:t,angles:r,beat_angle:o,beat_vmg:i,run_angle:l,run_vmg:s}=a.current;if(!(null==t?void 0:t.length)||!(null==r?void 0:r.length))return console.warn("Invalid polar data"),null;let c=(e,n,t)=>e+t*(n-e),u=[],d=(e,t,r)=>{for(let o=e;o<=t;o+=H.ANGLE_INCREMENT)u.push(Z(o,r(o),n))};d(0,o[e]-H.ANGLE_INCREMENT,n=>c(0,i[e],n/o[e]));let h=Z(o[e],i[e],n);u.push(h),r.forEach(t=>{if(t>o[e]&&t<l[e]){var r;let o=(null===(r=a.current[Math.floor(t)])||void 0===r?void 0:r[e])||0;u.push(Z(t,o,n))}});let m=Z(l[e],s[e],n);return u.push(m),d(l[e]+H.ANGLE_INCREMENT,180,()=>s[e]),new g.YT8(u,!0)},[]),s=(0,o.useMemo)(()=>{var e;let r=a.current;if(!(null==r?void 0:null===(e=r.speeds)||void 0===e?void 0:e.length))return console.warn("Invalid polar data structure"),{curve:null,beat:null,run:null};let o=B(r.speeds,t);return{curve:l(o,n),beat:i(r.beat_angle,r.beat_vmg,o,n),run:i(r.run_angle,r.run_vmg,o,n)}},[n,t,i,l]);return(0,r.jsx)(r.Fragment,{children:[0,-Math.PI].map((e,n)=>(0,r.jsxs)("group",{position:[0,-.7,0],rotation:[0,0,e],children:[s.curve&&(0,r.jsx)(K,{points:s.curve.getPoints(100),color:h.gK}),(0,r.jsx)(q,{position:s.beat,color:h.FV}),(0,r.jsx)(q,{position:s.run,color:h.HH})]},n))})});V.displayName="PolarPlot";var Q=function(){let e=(0,o.useRef)([]),[n,t]=(0,o.useState)([]),a=(0,o.useRef)(0),i=(0,o.useRef)([]),l=(0,o.useRef)(H.DEFAULT_SOG),{getSignalKValue:s}=(0,h.yC)(),c=-s("environment.wind.angleApparent"),d=(0,h.HQ)(s("environment.wind.speedOverGround"))||0,m=s("navigation.speedOverGround")||H.DEFAULT_SOG,f=(0,o.useRef)(d),[v,p]=(0,o.useState)(Date.now()),x=(0,o.useRef)(null);return(0,o.useEffect)(()=>{let n=Array.from({length:H.PLOTS_COUNT},(e,n)=>({id:n,timeInMinute:5*(n+1)}));return t(n),e.current=n.map(()=>new g.ZAu),i.current=Array(H.PLOTS_COUNT).fill(0),x.current=setInterval(()=>{p(Date.now()),a.current=0,console.log("Forcing redraw of polar plots")},12e4),()=>{x.current&&clearInterval(x.current)}},[]),(0,o.useEffect)(()=>{Math.abs(f.current-d)>5&&(console.log("Wind speed changed from ".concat(f.current," to ").concat(d,", recreating polar curves")),p(Date.now()),a.current=0,f.current=d)},[d]),(0,u.F)((t,r)=>{a.current+=1,l.current=g.M8C.lerp(l.current,m,H.SOG_SMOOTHING_FACTOR),n.forEach((n,t)=>{let r=e.current[t];if(r&&n.timeInMinute-a.current/H.FRAME_TO_MINUTE_RATIO>0){let e=i.current[t],n=g.M8C.lerp(e,c,H.ROTATION_INTERPOLATION_FACTOR);r.rotation.set(0,n,0),i.current[t]=n}})}),(0,r.jsx)(r.Fragment,{children:n.map((n,t)=>(0,r.jsx)("group",{ref:n=>{n&&(e.current[t]=n)},children:(0,r.jsx)(V,{timeInMinute:n.timeInMinute,windSpeed:d},"plot-".concat(v,"-").concat(t))},"".concat(n.id,"-").concat(v)))})},Y=()=>{let{states:e,nightMode:n}=(0,h.yC)(),t=n?.2:.4;return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("ambientLight",{intensity:n?.3:.5}),(0,r.jsx)("directionalLight",{position:[0,70,-100],intensity:n?.8:1.4,castShadow:!0,"shadow-mapSize-width":1024,"shadow-mapSize-height":1024,"shadow-camera-near":.5,"shadow-camera-far":200,"shadow-camera-left":-50,"shadow-camera-right":50,"shadow-camera-top":50,"shadow-camera-bottom":-50,"shadow-bias":-.0001,color:n?"#c8e6ff":"#ffffff"}),(0,r.jsx)("pointLight",{position:[0,40,-80],intensity:2.5*t,distance:150,decay:2}),(0,r.jsx)("pointLight",{position:[0,30,100],intensity:.8*t,distance:120,decay:2})]})},X=e=>{let{onUpdateInfoPanel:n}=e,{states:t,getSignalKValue:u}=(0,h.yC)();M.Z.getAll();let d=(0,o.useRef)();return(0,r.jsxs)(o.Suspense,{fallback:(0,r.jsx)(a.V,{children:"Loading..."}),children:[(0,r.jsx)(i.c,{makeDefault:!0,fov:60,near:5,far:500,position:[0,5,20]}),(0,r.jsx)(l.z,{enableZoom:!0,enableRotate:!0,maxPolarAngle:Math.PI/2,minPolarAngle:Math.PI/4,enableDamping:!1,zoomSpeed:.5,rotateSpeed:.5}),(0,r.jsx)(s.qA,{files:"./assets/ocearo_env.hdr",background:!1,intensity:.8,resolution:256}),(0,r.jsx)(Y,{}),(0,r.jsxs)("group",{position:[0,-3,0],children:[(0,r.jsx)(c.Z,{position:[0,0,.7],scale:[.7,.7,.7],ref:d,showSail:!0,onUpdateInfoPanel:n}),t.showOcean&&(0,r.jsx)(w,{}),(0,r.jsx)(f,{}),t.showPolar&&!t.showOcean&&(0,r.jsx)(Q,{}),t.ais&&(0,r.jsx)(S,{children:(0,r.jsx)(k,{onUpdateInfoPanel:n})}),(0,r.jsx)(U,{visible:!1})]})]})}},95723:function(e,n,t){"use strict";var r=t(57437),o=t(2265),a=t(40718),i=t.n(a),l=t(53082),s=t(72079),c=t(45476);let u={TRUE_WIND:1,APP_WIND:1},d=e=>{let{position:n=[0,0,0],rotation:t=[0,0,0],speed:o,color:a="#ffffff",fontSize:i=.5,textPosition:l=[0,.8,0],arrowSize:u=1}=e;return(0,r.jsxs)("group",{position:n,rotation:t,children:[(0,r.jsx)(c.x,{characters:".0123456789",color:a,fontSize:i*u,position:l,font:"fonts/Roboto-Bold.ttf",anchorX:"center",anchorY:"middle",children:o.toFixed(1)}),(0,r.jsxs)("mesh",{children:[(0,r.jsx)("shapeGeometry",{args:[new s.bnF([new s.FM8(0,0),new s.FM8(.5*u*Math.cos(5*Math.PI/6),.5*u*Math.sin(5*Math.PI/6)),new s.FM8(0,-.577*u),new s.FM8(-.5*u*Math.cos(5*Math.PI/6),.5*u*Math.sin(5*Math.PI/6)),new s.FM8(0,0)])]}),(0,r.jsx)("meshStandardMaterial",{color:a,side:s.ehD})]})]})};d.propTypes={position:i().oneOfType([i().instanceOf(s.Pa4),i().arrayOf(i().number)]).isRequired,rotation:i().arrayOf(i().number).isRequired,speed:i().number.isRequired,color:i().oneOfType([i().string,i().number]).isRequired,fontSize:i().number,textPosition:i().arrayOf(i().number),arrowSize:i().number};let g=e=>{let{outerRadius:n}=e,{getSignalKValue:t}=(0,l.yC)(),a=Math.PI/2-t("environment.wind.angleTrueGround")||0,i=(0,l.HQ)(t("environment.wind.speedOverGround"))||0,c=Math.PI/2-t("environment.wind.angleApparent")||0,g=(0,l.HQ)(t("environment.wind.speedApparent"))||0,h=(0,o.useMemo)(()=>new s.Pa4((n+.7)*Math.cos(a),0,-(n+.7)*Math.sin(a)),[n,a]),m=(0,o.useMemo)(()=>new s.Pa4((n+.7)*Math.cos(c),0,-(n+.7)*Math.sin(c)),[n,c]);return(0,r.jsxs)("group",{children:[i>0&&(0,r.jsx)(d,{position:h,rotation:[-Math.PI/2,0,-(Math.PI/2-a)],speed:i,color:"#0000FF",fontSize:u.TRUE_WIND}),g>0&&(0,r.jsx)(d,{position:m,rotation:[-Math.PI/2,0,-(Math.PI/2-c)],speed:g,color:l.gK,fontSize:u.APP_WIND})]})};g.propTypes={outerRadius:i().number.isRequired},n.Z=g}}]);