@idm-plugin/geo 1.9.4 → 1.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2096,6 +2096,16 @@ class B {
2096
2096
  hour: A
2097
2097
  };
2098
2098
  }
2099
+ /**
2100
+ * 查询特定时间的船位及航行区间
2101
+ * @param utc 目标时间, UTC格式
2102
+ * @param from 起点, 包含speed, etd, lat, lng
2103
+ * @param route
2104
+ * @return {
2105
+ * routes: [],
2106
+ * hour: Coordinate
2107
+ * }
2108
+ */
2099
2109
  static pickUTCSampleFromRoute(M, z, b) {
2100
2110
  var T;
2101
2111
  const p = this.calculateSubRoute(z, b), c = this.calculateRouteDistance(p), O = c / z.speed, A = u.utc(M), W = u(z.etd), q = (T = this.calculateNextCoordinateAlongRoute(z, z.speed * A.diff(u(z.etd), "hours", !0), p)) == null ? void 0 : T.coordinate;
@@ -2136,6 +2146,7 @@ class t0 {
2136
2146
  const s = R.clone().add(Number(i), "hour"), Z = N.point([S.lng, S.lat], {
2137
2147
  model: W.model,
2138
2148
  name: O.name,
2149
+ nameCn: O.nameCn,
2139
2150
  date: s.format(),
2140
2151
  hour: Number(i),
2141
2152
  format: s.format("MMM-DD/HHmm[Z]"),
@@ -10,4 +10,4 @@
10
10
  `;for(let p=0;p<z.length;p++)b+=`<waypoint id="${p+1}" revision="0"><position lat="${z[p].lat}" lon="${z[p].lng}" /></waypoint>
11
11
  `;return b+=`</waypoints>
12
12
  `,b+=`</route>
13
- `,b}static coordinatesSummary(M){if(M.length>1){const z=M[0],b=M[M.length-1],p=(z==null?void 0:z.positionTime)<(b==null?void 0:b.positionTime)?u.unix(z==null?void 0:z.positionTime):u.unix(b==null?void 0:b.positionTime),c=(z==null?void 0:z.positionTime)>(b==null?void 0:b.positionTime)?u.unix(z==null?void 0:z.positionTime):u.unix(b==null?void 0:b.positionTime),O=Math.round(c.diff(p,"hours",!0)*100)/100,A=this.generateRouteAccordingToWaypoints(M,!0,!0),W=this.calculateRouteDistance(A),q=O?Math.round(W/O*100)/100:0;return{begin:p.utc().format(),end:c.utc().format(),distance:W,hours:O,avgSpeed:q}}return{begin:void 0,end:void 0,distance:0,hours:0,avgSpeed:0}}static pickUTCSampleFromSpeed(M,z){var Y,d,R;if(!((d=(Y=z==null?void 0:z.sample)==null?void 0:Y.hours)!=null&&d.length))return{routes:[],hour:void 0};const b=z.sample.hours.at(0),p=u.utc(M),c=u.utc(z.eta),O=p.isAfter(c)?c:p;let A=z.sample.hours.find(T=>T.eta===O.format());if(!A){const T=z.sample.hours.filter(K=>u.utc(K.eta).isBefore(O)).at(-1),N=this.calculateSubRoute(T,z.route);A=(R=this.calculateNextCoordinateAlongRoute(T,T.speed*O.diff(u(T.etd),"hours",!0),N))==null?void 0:R.coordinate;const{bearing:i,cFactor:r,cog:s,wxFactor:Z,meteo:P}=T,B=Math.round(A.distanceFromPrevious*1e4)/1e4,C=Math.round((B+T.distanceFromStart)*1e4)/1e4;A={...A,cFactor:r,cog:s,speed:T.speed,wxFactor:Z,distanceFromStart:C,distanceFromPrevious:B,meteo:P,eta:O.format(),etd:O.format()}}A.distanceToGo=Math.round((z.distance-A.distanceFromStart)*100)/100,A.timeToGo=Math.round(c.diff(A.etd,"hours",!0)*100)/100;const W=this.calculateRangeWaypoints(b,A,z.route);return{routes:this.generateRouteAccordingToWaypoints(W),hour:A}}static pickUTCSampleFromRoute(M,z,b){var T;const p=this.calculateSubRoute(z,b),c=this.calculateRouteDistance(p),O=c/z.speed,A=u.utc(M),W=u(z.etd),q=(T=this.calculateNextCoordinateAlongRoute(z,z.speed*A.diff(u(z.etd),"hours",!0),p))==null?void 0:T.coordinate;q.speed=z.speed;const Y=W.clone().add(q.hourFromPrevious,"hour");q.eta=Math.abs(Y.diff(A,"second"))<2?A.format():Y.format(),q.etd=q.eta,q.distanceFromStart=Math.round(q.distanceFromPrevious*100)/100,q.distanceToGo=Math.round((c-q.distanceFromStart)*100)/100,q.timeToGo=Math.round(W.clone().add(O,"hour").diff(u(q.etd),"hour")*100)/100;const d=this.calculateRangeWaypoints(z,q,b);return{routes:this.generateRouteAccordingToWaypoints(d),hour:q}}}let G;try{G=y.getLogger("vessel")}catch{}finally{}class d0{static convert2Geojson(M){var b,p,c;const z=f.featureCollection([]);for(const O of M){const A=(b=O.history)==null?void 0:b[0];if(O.forecasts){A&&A.wind&&(A.wind.kts=A.kts);for(const W of O.forecasts){let q;const Y=[],d=[],R=u(W.date).utc(),T=`${O.name}-${W.model}`;for(const i in W==null?void 0:W.hours){const r=W.hours[i];q=q||r;const s=R.clone().add(Number(i),"hour"),Z=f.point([r.lng,r.lat],{model:W.model,name:O.name,date:s.format(),hour:Number(i),format:s.format("MMM-DD/HHmm[Z]"),pressure:r.pressure>1e4?a.roundPrecision(r.pressure/100,0):a.roundPrecision(r.pressure,0),gusts:r.gusts,wind:r.wind||{},movement:r.movement,category:T,type:"forecast"});d.push(Z),Y.push(Z.geometry.coordinates)}const N={kts:void 0,deg:void 0};if(A){const i=u(A.updated).utc();if(q){const s=S.calculateDistance(A,q),Z=u(q.utc||q.updated).diff(i,"h",!0);N.kts=Math.round(s/Z*100)/100,N.deg=S.calculateBearing(A,q,!0,0)}const r=f.point([A.lng,A.lat],{model:W.model,name:O.name,date:i.format(),hour:0,format:i.format("MMM-DD/HHmm[Z]"),pressure:A.pressure>1e4?a.roundPrecision((A==null?void 0:A.pressure)/100,0):a.roundPrecision(A.pressure,0),wind:A.wind,movement:N,category:T,type:"forecast",important:!0});d.unshift(r),Y.unshift(r.geometry.coordinates)}if(z.features.push(...d),(Y==null?void 0:Y.length)>1){const i=f.lineString(a.convertToMonotonicLng2(Y),{date:(A==null?void 0:A.updated)||(R==null?void 0:R.format()),id:O.id||O.name,model:W.model,name:O.name,category:T,type:"forecast",movement:N});z.features.push(i)}}}if(z.features.sort((W,q)=>W.properties.type==="forecast"&&q.properties.type==="forecast"&&W.geometry.type==="Point"&&q.geometry.type==="Point"?u(W.properties.date).valueOf()-u(q.properties.date).valueOf():0),(p=O.history)!=null&&p.length){const W=[],q=u(A==null?void 0:A.updated).utc(),Y=u((c=O.history)==null?void 0:c.at(-1).updated).utc(),d=q.diff(Y,"h")%24>2?24:12;for(const R of O.history){const T=u(R.updated).utc(),N=T.isSameOrBefore(q)||T.isSame(Y);N&&q.add(-d,"h");const i=f.point([R.lng,R.lat],{name:O.name,date:T.format(),format:T.format("MMM-DD/HHmm[Z]"),pressure:R.pressure>1e4?a.roundPrecision(R.pressure/100,0):a.roundPrecision(R.pressure,0),kts:R.kts,level:R.type,type:"history",category:`${O.name}-history`,wind:R.wind,movement:R.movement,important:N});z.features.push(i),W.push(i.geometry.coordinates)}if(W.length===1&&W.push(W[0]),W.length>1){const R=f.lineString(a.convertToMonotonicLng2(W),{name:O.name,type:"history",updated:A==null?void 0:A.updated,pressure:(A==null?void 0:A.pressure)>1e4?a.roundPrecision((A==null?void 0:A.pressure)/100,0):a.roundPrecision(A==null?void 0:A.pressure,0),kts:A==null?void 0:A.kts,level:A==null?void 0:A.type});z.features.push(R)}}}return z}static interpolate(M,z=3){var c,O,A,W;const b=(c=M==null?void 0:M.data)==null?void 0:c.features.filter(q=>q.geometry.type==="LineString"&&q.properties.type==="forecast"),p=[];for(const q of b){const Y=q.properties.name,d=q.properties.model,R=q.properties.showCircle,T=q.properties.disabled,N=u(q.properties.date).utc();let i=z*60;const r=(O=M==null?void 0:M.data)==null?void 0:O.features.filter(P=>P.geometry.type==="Point"&&P.properties.type==="forecast"&&P.properties.category===`${Y}-${d}`);let s,Z=N.clone().add(i,"minute").set({minute:0,second:0,millisecond:0});for(;s=this.pickIndex(r,Z),s<=r.length-1;){if(s>0){const P=r[s],B=s===0?void 0:r[s-1],C=(i/60-((A=B==null?void 0:B.properties)==null?void 0:A.hour))/(P.properties.hour-((W=B==null?void 0:B.properties)==null?void 0:W.hour)),K=this.computeNumber(B==null?void 0:B.geometry.coordinates[0],P.geometry.coordinates[0],C),J=this.computeNumber(B==null?void 0:B.geometry.coordinates[1],P.geometry.coordinates[1],C),$=f.point([K,J],{name:Y,model:d,category:P==null?void 0:P.properties.category,date:Z.format(),format:Z.format("MMM-DD/HHmm[Z]"),gusts:this.computeNumber(B==null?void 0:B.properties.gusts,P.properties.gusts,C),hour:this.computeNumber(B==null?void 0:B.properties.hour,P.properties.hour,C),movement:this.computeNumber(B==null?void 0:B.properties.movement,P.properties.movement,C),pressure:this.computeNumber(B==null?void 0:B.properties.pressure,P.properties.pressure,C),wind:this.computeNumber(B==null?void 0:B.properties.wind,P.properties.wind,C),type:"forecast",disabled:T,showCircle:R});p.push($)}i+=z*60,Z=N.clone().add(i,"minute").set({minute:0,second:0,millisecond:0})}}return p}static accelPassageAt(M,z){const{t1:b,t2:p,hr:c,hours:O}=this.tropicalCenterTwin(M,24,z);return{t1:b,t2:p,hr:c,hours:O}}static diversionPassageAt(M,z,b,p={}){const{t1:c,t2:O,hr:A,hours:W}=this.tropicalCenterTwin(z,24,p);if(c&&O){if(!p.debug){const N=S.calculateDistance(M,c),i=S.calculateDistance(M,O);if(N>2*b&&i>2*b)return G==null||G.info("[%s] the distance between from and t1(%d) and t2(%d) is enough, no need diversion: %j",p.requestId,N,i,{from:M,t1:c,t2:O,hr:A}),{}}const q=S.calculateBearing(M,c),Y=S.calculateBearing(c,O),d=Math.abs(q-Y);let R=0;d<180?R=d+90:d>=180&&(R=d-90);const T=S.calculateCoordinate(c,R,b);return G==null||G.info("[%s] the right tangent position: %j",p.requestId,{from:M,t1:c,t2:O,radius:b,bearing1:q,bearing2:Y,right:T}),{at:T,t1:c,t2:O,hr:Number(A),hours:W}}return{}}static driftPassageAt(M,z,b,p={}){const{t1:c,t2:O,hr:A,hours:W}=this.tropicalCenterTwin(z,24,p);if(c&&O){if(!p.debug){const T=S.calculateDistance(M,c),N=S.calculateDistance(M,O);if(T>2*b&&N>2*b)return G==null||G.info("[%s] the distance between from and t1(%d) and t2(%d) is enough, no need drifting: %j",p.requestId,T,N,{from:M,t1:c,t2:O,hr:A}),{}}const q=S.calculateBearing(M,c),Y=S.calculateBearing(c,O),d=S.calculateDistance(M,c);return{at:S.calculateCoordinate(c,q-Y+180,b<d?b:d),t1:c,t2:O,hr:Number(A),hours:W}}else return G==null||G.info("[%s] no need drift: %j",p.requestId,{from:M,t1:c,t2:O,hr:A}),{}}static tropicalCenterTwin(M,z=24,b={}){var Y,d,R,T,N;let p={};(Y=M.forecasts)==null||Y.forEach(i=>{p={...i.hours,...p}});const c=((d=M==null?void 0:M.history)==null?void 0:d[0])||(p==null?void 0:p[(R=Object.keys(p))==null?void 0:R[0]]);G==null||G.info("[%s] the first tropical center: %j",b.requestId,c);let O=(T=Object.keys(p||{}).filter(i=>Number(i)<=(z<0?24:z)))==null?void 0:T.at(-1);O||(O=(N=Object.keys(p||{}).filter(i=>Number(i)<=(z<0?24:2*z)))==null?void 0:N.at(-1));const A=p==null?void 0:p[O||-1];G==null||G.info("[%s] the second tropical center: %j in %d hrs",b.requestId,A,O);const W=Object.keys(p||{}).filter(i=>Number(i)<=Number(O)),q={0:c};for(const i of W)q[i]=p[i];return{t1:c,t2:A,hr:Number(O),hours:q}}static pickIndex(M,z){let b=0;for(const p of M){if(u(p.properties.date).isAfter(z))return b===0?-1:b;b++}return b}static computeNumber(M,z,b){if(M)if(z){if(isNaN(M)&&isNaN(z)&&typeof M!="string"&&typeof z!="string"){const p={};for(const c in M)p[c]=this.computeNumber(M[c],z[c],b);return p}return Math.round((M+(z-M)*b)*100)/100}else return M;else return z}}class a0{static json2Str(M){const z=M.type?M.type[0].toUpperCase():"A";return`${M.lat}|${M.lng}|${M.positionTime}|${M.sog}|${M.cog}|${M.hdg}|${M.draught}|${z}|${JSON.stringify(M.meteo||{})}|${M.vendor}|${M.deleted}`}static str2Json(M){const[z,b,p,c,O,A,W,q,Y,d,R]=M.split("|");return{lat:Number(z),lng:Number(b),positionTime:Number(p),sog:Number(c),cog:Number(O),hdg:Number(A),draught:isNaN(W)?null:Number(W),type:q,important:q!=="A",meteo:Y?JSON.parse(Y):void 0,vendor:d,deleted:R==="true"}}static inspectStoppages(M,z=1,b=!0){const p=M.at(0).positionTime<M.at(-1).positionTime;p||M.sort((W,q)=>W.positionTime-q.positionTime);const c=[];let O,A;for(let W=0;W<M.length-1;W++){const q=M[W];if(!(b&&["N","B","E","NOON","BOSP","EOSP"].includes(q.type))){for(let Y=W+1;Y<M.length;Y++){const d=M[Y-1],R=M[Y];if(b&&["N","B","E","NOON","BOSP","EOSP"].includes(q.type))continue;const T=R.positionTime-d.positionTime;if(S.calculateDistance(R,d,!0,4)/(T/3600)<z)O||(O=q),Y===M.length-1&&(A=R,W=Y);else{O&&(A=M[Y-1],W=Y);break}}if((A==null?void 0:A.positionTime)>(O==null?void 0:O.positionTime)&&O){const Y={start:{lat:O.lat,lng:O.lng,sog:O.sog,positionTime:O.positionTime,utc:u.unix(O.positionTime).utc().format()},end:{lat:A.lat,lng:A.lng,sog:A.sog,positionTime:A.positionTime,utc:u.unix(A.positionTime).utc().format()},duration:A.positionTime-O.positionTime},d=M.filter(T=>T.positionTime>=Y.start.positionTime&&T.positionTime<=Y.end.positionTime),R=S.divideAccordingToLng(d);Y.distance=S.calculateRouteDistance(R),Y.hours=Math.round(Y.duration/3600*10)/10,Y.avgSog=Math.round(Y.distance/Y.hours*10)/10,c.push(Y)}O=void 0,A=void 0}}return p||M.sort((W,q)=>q.positionTime-W.positionTime),c}}m.AisHelper=a0,m.LaneHelper=S,m.LngLatHelper=a,m.TropicalHelper=d0,Object.defineProperty(m,Symbol.toStringTag,{value:"Module"})});
13
+ `,b}static coordinatesSummary(M){if(M.length>1){const z=M[0],b=M[M.length-1],p=(z==null?void 0:z.positionTime)<(b==null?void 0:b.positionTime)?u.unix(z==null?void 0:z.positionTime):u.unix(b==null?void 0:b.positionTime),c=(z==null?void 0:z.positionTime)>(b==null?void 0:b.positionTime)?u.unix(z==null?void 0:z.positionTime):u.unix(b==null?void 0:b.positionTime),O=Math.round(c.diff(p,"hours",!0)*100)/100,A=this.generateRouteAccordingToWaypoints(M,!0,!0),W=this.calculateRouteDistance(A),q=O?Math.round(W/O*100)/100:0;return{begin:p.utc().format(),end:c.utc().format(),distance:W,hours:O,avgSpeed:q}}return{begin:void 0,end:void 0,distance:0,hours:0,avgSpeed:0}}static pickUTCSampleFromSpeed(M,z){var Y,d,R;if(!((d=(Y=z==null?void 0:z.sample)==null?void 0:Y.hours)!=null&&d.length))return{routes:[],hour:void 0};const b=z.sample.hours.at(0),p=u.utc(M),c=u.utc(z.eta),O=p.isAfter(c)?c:p;let A=z.sample.hours.find(T=>T.eta===O.format());if(!A){const T=z.sample.hours.filter(K=>u.utc(K.eta).isBefore(O)).at(-1),N=this.calculateSubRoute(T,z.route);A=(R=this.calculateNextCoordinateAlongRoute(T,T.speed*O.diff(u(T.etd),"hours",!0),N))==null?void 0:R.coordinate;const{bearing:i,cFactor:r,cog:s,wxFactor:Z,meteo:P}=T,B=Math.round(A.distanceFromPrevious*1e4)/1e4,C=Math.round((B+T.distanceFromStart)*1e4)/1e4;A={...A,cFactor:r,cog:s,speed:T.speed,wxFactor:Z,distanceFromStart:C,distanceFromPrevious:B,meteo:P,eta:O.format(),etd:O.format()}}A.distanceToGo=Math.round((z.distance-A.distanceFromStart)*100)/100,A.timeToGo=Math.round(c.diff(A.etd,"hours",!0)*100)/100;const W=this.calculateRangeWaypoints(b,A,z.route);return{routes:this.generateRouteAccordingToWaypoints(W),hour:A}}static pickUTCSampleFromRoute(M,z,b){var T;const p=this.calculateSubRoute(z,b),c=this.calculateRouteDistance(p),O=c/z.speed,A=u.utc(M),W=u(z.etd),q=(T=this.calculateNextCoordinateAlongRoute(z,z.speed*A.diff(u(z.etd),"hours",!0),p))==null?void 0:T.coordinate;q.speed=z.speed;const Y=W.clone().add(q.hourFromPrevious,"hour");q.eta=Math.abs(Y.diff(A,"second"))<2?A.format():Y.format(),q.etd=q.eta,q.distanceFromStart=Math.round(q.distanceFromPrevious*100)/100,q.distanceToGo=Math.round((c-q.distanceFromStart)*100)/100,q.timeToGo=Math.round(W.clone().add(O,"hour").diff(u(q.etd),"hour")*100)/100;const d=this.calculateRangeWaypoints(z,q,b);return{routes:this.generateRouteAccordingToWaypoints(d),hour:q}}}let G;try{G=y.getLogger("vessel")}catch{}finally{}class d0{static convert2Geojson(M){var b,p,c;const z=f.featureCollection([]);for(const O of M){const A=(b=O.history)==null?void 0:b[0];if(O.forecasts){A&&A.wind&&(A.wind.kts=A.kts);for(const W of O.forecasts){let q;const Y=[],d=[],R=u(W.date).utc(),T=`${O.name}-${W.model}`;for(const i in W==null?void 0:W.hours){const r=W.hours[i];q=q||r;const s=R.clone().add(Number(i),"hour"),Z=f.point([r.lng,r.lat],{model:W.model,name:O.name,nameCn:O.nameCn,date:s.format(),hour:Number(i),format:s.format("MMM-DD/HHmm[Z]"),pressure:r.pressure>1e4?a.roundPrecision(r.pressure/100,0):a.roundPrecision(r.pressure,0),gusts:r.gusts,wind:r.wind||{},movement:r.movement,category:T,type:"forecast"});d.push(Z),Y.push(Z.geometry.coordinates)}const N={kts:void 0,deg:void 0};if(A){const i=u(A.updated).utc();if(q){const s=S.calculateDistance(A,q),Z=u(q.utc||q.updated).diff(i,"h",!0);N.kts=Math.round(s/Z*100)/100,N.deg=S.calculateBearing(A,q,!0,0)}const r=f.point([A.lng,A.lat],{model:W.model,name:O.name,date:i.format(),hour:0,format:i.format("MMM-DD/HHmm[Z]"),pressure:A.pressure>1e4?a.roundPrecision((A==null?void 0:A.pressure)/100,0):a.roundPrecision(A.pressure,0),wind:A.wind,movement:N,category:T,type:"forecast",important:!0});d.unshift(r),Y.unshift(r.geometry.coordinates)}if(z.features.push(...d),(Y==null?void 0:Y.length)>1){const i=f.lineString(a.convertToMonotonicLng2(Y),{date:(A==null?void 0:A.updated)||(R==null?void 0:R.format()),id:O.id||O.name,model:W.model,name:O.name,category:T,type:"forecast",movement:N});z.features.push(i)}}}if(z.features.sort((W,q)=>W.properties.type==="forecast"&&q.properties.type==="forecast"&&W.geometry.type==="Point"&&q.geometry.type==="Point"?u(W.properties.date).valueOf()-u(q.properties.date).valueOf():0),(p=O.history)!=null&&p.length){const W=[],q=u(A==null?void 0:A.updated).utc(),Y=u((c=O.history)==null?void 0:c.at(-1).updated).utc(),d=q.diff(Y,"h")%24>2?24:12;for(const R of O.history){const T=u(R.updated).utc(),N=T.isSameOrBefore(q)||T.isSame(Y);N&&q.add(-d,"h");const i=f.point([R.lng,R.lat],{name:O.name,date:T.format(),format:T.format("MMM-DD/HHmm[Z]"),pressure:R.pressure>1e4?a.roundPrecision(R.pressure/100,0):a.roundPrecision(R.pressure,0),kts:R.kts,level:R.type,type:"history",category:`${O.name}-history`,wind:R.wind,movement:R.movement,important:N});z.features.push(i),W.push(i.geometry.coordinates)}if(W.length===1&&W.push(W[0]),W.length>1){const R=f.lineString(a.convertToMonotonicLng2(W),{name:O.name,type:"history",updated:A==null?void 0:A.updated,pressure:(A==null?void 0:A.pressure)>1e4?a.roundPrecision((A==null?void 0:A.pressure)/100,0):a.roundPrecision(A==null?void 0:A.pressure,0),kts:A==null?void 0:A.kts,level:A==null?void 0:A.type});z.features.push(R)}}}return z}static interpolate(M,z=3){var c,O,A,W;const b=(c=M==null?void 0:M.data)==null?void 0:c.features.filter(q=>q.geometry.type==="LineString"&&q.properties.type==="forecast"),p=[];for(const q of b){const Y=q.properties.name,d=q.properties.model,R=q.properties.showCircle,T=q.properties.disabled,N=u(q.properties.date).utc();let i=z*60;const r=(O=M==null?void 0:M.data)==null?void 0:O.features.filter(P=>P.geometry.type==="Point"&&P.properties.type==="forecast"&&P.properties.category===`${Y}-${d}`);let s,Z=N.clone().add(i,"minute").set({minute:0,second:0,millisecond:0});for(;s=this.pickIndex(r,Z),s<=r.length-1;){if(s>0){const P=r[s],B=s===0?void 0:r[s-1],C=(i/60-((A=B==null?void 0:B.properties)==null?void 0:A.hour))/(P.properties.hour-((W=B==null?void 0:B.properties)==null?void 0:W.hour)),K=this.computeNumber(B==null?void 0:B.geometry.coordinates[0],P.geometry.coordinates[0],C),J=this.computeNumber(B==null?void 0:B.geometry.coordinates[1],P.geometry.coordinates[1],C),$=f.point([K,J],{name:Y,model:d,category:P==null?void 0:P.properties.category,date:Z.format(),format:Z.format("MMM-DD/HHmm[Z]"),gusts:this.computeNumber(B==null?void 0:B.properties.gusts,P.properties.gusts,C),hour:this.computeNumber(B==null?void 0:B.properties.hour,P.properties.hour,C),movement:this.computeNumber(B==null?void 0:B.properties.movement,P.properties.movement,C),pressure:this.computeNumber(B==null?void 0:B.properties.pressure,P.properties.pressure,C),wind:this.computeNumber(B==null?void 0:B.properties.wind,P.properties.wind,C),type:"forecast",disabled:T,showCircle:R});p.push($)}i+=z*60,Z=N.clone().add(i,"minute").set({minute:0,second:0,millisecond:0})}}return p}static accelPassageAt(M,z){const{t1:b,t2:p,hr:c,hours:O}=this.tropicalCenterTwin(M,24,z);return{t1:b,t2:p,hr:c,hours:O}}static diversionPassageAt(M,z,b,p={}){const{t1:c,t2:O,hr:A,hours:W}=this.tropicalCenterTwin(z,24,p);if(c&&O){if(!p.debug){const N=S.calculateDistance(M,c),i=S.calculateDistance(M,O);if(N>2*b&&i>2*b)return G==null||G.info("[%s] the distance between from and t1(%d) and t2(%d) is enough, no need diversion: %j",p.requestId,N,i,{from:M,t1:c,t2:O,hr:A}),{}}const q=S.calculateBearing(M,c),Y=S.calculateBearing(c,O),d=Math.abs(q-Y);let R=0;d<180?R=d+90:d>=180&&(R=d-90);const T=S.calculateCoordinate(c,R,b);return G==null||G.info("[%s] the right tangent position: %j",p.requestId,{from:M,t1:c,t2:O,radius:b,bearing1:q,bearing2:Y,right:T}),{at:T,t1:c,t2:O,hr:Number(A),hours:W}}return{}}static driftPassageAt(M,z,b,p={}){const{t1:c,t2:O,hr:A,hours:W}=this.tropicalCenterTwin(z,24,p);if(c&&O){if(!p.debug){const T=S.calculateDistance(M,c),N=S.calculateDistance(M,O);if(T>2*b&&N>2*b)return G==null||G.info("[%s] the distance between from and t1(%d) and t2(%d) is enough, no need drifting: %j",p.requestId,T,N,{from:M,t1:c,t2:O,hr:A}),{}}const q=S.calculateBearing(M,c),Y=S.calculateBearing(c,O),d=S.calculateDistance(M,c);return{at:S.calculateCoordinate(c,q-Y+180,b<d?b:d),t1:c,t2:O,hr:Number(A),hours:W}}else return G==null||G.info("[%s] no need drift: %j",p.requestId,{from:M,t1:c,t2:O,hr:A}),{}}static tropicalCenterTwin(M,z=24,b={}){var Y,d,R,T,N;let p={};(Y=M.forecasts)==null||Y.forEach(i=>{p={...i.hours,...p}});const c=((d=M==null?void 0:M.history)==null?void 0:d[0])||(p==null?void 0:p[(R=Object.keys(p))==null?void 0:R[0]]);G==null||G.info("[%s] the first tropical center: %j",b.requestId,c);let O=(T=Object.keys(p||{}).filter(i=>Number(i)<=(z<0?24:z)))==null?void 0:T.at(-1);O||(O=(N=Object.keys(p||{}).filter(i=>Number(i)<=(z<0?24:2*z)))==null?void 0:N.at(-1));const A=p==null?void 0:p[O||-1];G==null||G.info("[%s] the second tropical center: %j in %d hrs",b.requestId,A,O);const W=Object.keys(p||{}).filter(i=>Number(i)<=Number(O)),q={0:c};for(const i of W)q[i]=p[i];return{t1:c,t2:A,hr:Number(O),hours:q}}static pickIndex(M,z){let b=0;for(const p of M){if(u(p.properties.date).isAfter(z))return b===0?-1:b;b++}return b}static computeNumber(M,z,b){if(M)if(z){if(isNaN(M)&&isNaN(z)&&typeof M!="string"&&typeof z!="string"){const p={};for(const c in M)p[c]=this.computeNumber(M[c],z[c],b);return p}return Math.round((M+(z-M)*b)*100)/100}else return M;else return z}}class a0{static json2Str(M){const z=M.type?M.type[0].toUpperCase():"A";return`${M.lat}|${M.lng}|${M.positionTime}|${M.sog}|${M.cog}|${M.hdg}|${M.draught}|${z}|${JSON.stringify(M.meteo||{})}|${M.vendor}|${M.deleted}`}static str2Json(M){const[z,b,p,c,O,A,W,q,Y,d,R]=M.split("|");return{lat:Number(z),lng:Number(b),positionTime:Number(p),sog:Number(c),cog:Number(O),hdg:Number(A),draught:isNaN(W)?null:Number(W),type:q,important:q!=="A",meteo:Y?JSON.parse(Y):void 0,vendor:d,deleted:R==="true"}}static inspectStoppages(M,z=1,b=!0){const p=M.at(0).positionTime<M.at(-1).positionTime;p||M.sort((W,q)=>W.positionTime-q.positionTime);const c=[];let O,A;for(let W=0;W<M.length-1;W++){const q=M[W];if(!(b&&["N","B","E","NOON","BOSP","EOSP"].includes(q.type))){for(let Y=W+1;Y<M.length;Y++){const d=M[Y-1],R=M[Y];if(b&&["N","B","E","NOON","BOSP","EOSP"].includes(q.type))continue;const T=R.positionTime-d.positionTime;if(S.calculateDistance(R,d,!0,4)/(T/3600)<z)O||(O=q),Y===M.length-1&&(A=R,W=Y);else{O&&(A=M[Y-1],W=Y);break}}if((A==null?void 0:A.positionTime)>(O==null?void 0:O.positionTime)&&O){const Y={start:{lat:O.lat,lng:O.lng,sog:O.sog,positionTime:O.positionTime,utc:u.unix(O.positionTime).utc().format()},end:{lat:A.lat,lng:A.lng,sog:A.sog,positionTime:A.positionTime,utc:u.unix(A.positionTime).utc().format()},duration:A.positionTime-O.positionTime},d=M.filter(T=>T.positionTime>=Y.start.positionTime&&T.positionTime<=Y.end.positionTime),R=S.divideAccordingToLng(d);Y.distance=S.calculateRouteDistance(R),Y.hours=Math.round(Y.duration/3600*10)/10,Y.avgSog=Math.round(Y.distance/Y.hours*10)/10,c.push(Y)}O=void 0,A=void 0}}return p||M.sort((W,q)=>q.positionTime-W.positionTime),c}}m.AisHelper=a0,m.LaneHelper=S,m.LngLatHelper=a,m.TropicalHelper=d0,Object.defineProperty(m,Symbol.toStringTag,{value:"Module"})});
@@ -362,6 +362,16 @@ export declare class LaneHelper {
362
362
  * }
363
363
  */
364
364
  static pickUTCSampleFromSpeed(utc: string, speed: any): any;
365
+ /**
366
+ * 查询特定时间的船位及航行区间
367
+ * @param utc 目标时间, UTC格式
368
+ * @param from 起点, 包含speed, etd, lat, lng
369
+ * @param route
370
+ * @return {
371
+ * routes: [],
372
+ * hour: Coordinate
373
+ * }
374
+ */
365
375
  static pickUTCSampleFromRoute(utc: string, from: {
366
376
  lat: number;
367
377
  lng: number;
@@ -7,6 +7,7 @@ export declare class TropicalHelper {
7
7
  static convert2Geojson(raw: {
8
8
  id: string;
9
9
  name: string;
10
+ nameCn?: string;
10
11
  forecasts: any[];
11
12
  history: any[];
12
13
  }[]): turf.helpers.FeatureCollection<turf.helpers.Geometry, turf.helpers.Properties>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@idm-plugin/geo",
3
3
  "private": false,
4
- "version": "1.9.4",
4
+ "version": "1.9.5",
5
5
  "description": "idm plugin for geo in browser",
6
6
  "type": "module",
7
7
  "keywords": [