1+ import { EQUATORIAL_RADIUS , POLAR_RADIUS } from "./const" ;
2+ import { IFloorGps , IInstituteGps , UserGps , UserLocation } from "./interfaces" ;
3+
4+ function approxGps ( data : UserGps [ ] ) : UserGps {
5+ const sumOfData = data . reduce (
6+ ( e , accum ) => ( {
7+ latitude : accum . latitude + e . latitude ,
8+ longtitude : accum . longtitude + e . longtitude ,
9+ altitude : accum . altitude + e . altitude
10+ } ) ,
11+ {
12+ latitude : 0 ,
13+ longtitude : 0 ,
14+ altitude : 0
15+ }
16+ ) ;
17+
18+ return {
19+ latitude : sumOfData . latitude / data . length ,
20+ longtitude : sumOfData . longtitude / data . length ,
21+ altitude : sumOfData . altitude / data . length
22+ }
23+ }
24+
25+ function boundGpsToMap (
26+ loc : { x : number , y : number } ,
27+ mapSize : { width : number , height : number } )
28+ : { x : number , y : number } {
29+ return {
30+ x : Math . min ( mapSize . width , Math . max ( 0 , loc . x ) ) ,
31+ y : Math . min ( mapSize . height , Math . max ( 0 , loc . y ) )
32+ }
33+ }
34+
35+ function deg2rad ( x : number ) : number {
36+ return x * ( Math . PI / 180 ) ;
37+ }
38+
39+ function getClosestFloor ( floors : IInstituteGps [ ] , loc : UserGps ) : IInstituteGps {
40+ let min_index = 1 ;
41+ let min_value = Number . MAX_VALUE ;
42+
43+ for ( let i = 0 ; i < floors . length ; i ++ ) {
44+ const dist = Math . abs ( floors [ i ] . centre - loc . altitude ) ;
45+ if ( dist < min_value ) {
46+ min_value = dist ;
47+ min_index = i ;
48+ }
49+ }
50+
51+ return floors [ min_index ] ;
52+ }
53+
54+ function flattenSphericalCoord ( loc : UserGps ) : UserLocation {
55+ const lat_rad = deg2rad ( loc . latitude ) ;
56+ const long_rad = deg2rad ( loc . longtitude ) ;
57+ // const alt_rad = deg2rad(loc.altitude);
58+
59+ const e2 = ( EQUATORIAL_RADIUS ** 2 - POLAR_RADIUS ** 2 ) / EQUATORIAL_RADIUS ** 2 ;
60+ const nB = EQUATORIAL_RADIUS / Math . sqrt ( 1 - ( e2 * Math . sin ( lat_rad ) ** 2 ) ) ;
61+
62+ return {
63+ x : ( nB + loc . altitude ) * Math . cos ( lat_rad ) * Math . cos ( long_rad ) / 1e+3 ,
64+ y : ( nB + loc . altitude ) * Math . cos ( lat_rad ) * Math . sin ( long_rad ) / 1e+3 ,
65+ z : ( ( Math . pow ( POLAR_RADIUS , 2 ) / Math . pow ( EQUATORIAL_RADIUS , 2 ) ) * nB + loc . altitude ) * Math . sin ( lat_rad )
66+ }
67+ }
68+
69+ function createPredictor ( mapGps : IFloorGps ) : ( loc : UserGps ) => { x : number , y : number } {
70+ function predictor ( loc : UserGps ) : { x : number , y : number } {
71+ const flatCoord = flattenSphericalCoord ( loc ) ;
72+
73+ const linearX = mapGps . linear . x . a + mapGps . linear . x . b1 * flatCoord . x + mapGps . linear . x . b2 * flatCoord . y ;
74+ const linearY = mapGps . linear . y . a + mapGps . linear . y . b1 * flatCoord . x + mapGps . linear . y . b2 * flatCoord . y ;
75+
76+ let sumOfWeigths = 0 ;
77+ const weights = mapGps . forces . map ( ( e ) => {
78+ const dist = Math . sqrt ( Math . pow ( e . point . x - linearX , 2 ) + Math . pow ( e . point . y - linearY , 2 ) ) ;
79+ const weight = 1.0 / Math . pow ( dist + 1e-12 , 2 ) ;
80+ sumOfWeigths += weight ;
81+
82+ return weight ;
83+ } ) ;
84+ const normWeigths = weights . map ( e => e / sumOfWeigths ) ;
85+
86+ return {
87+ x : linearX + normWeigths . reduce (
88+ ( accum , currentValue , index ) => accum + currentValue * mapGps . forces [ index ] . force . x ,
89+ 0.0
90+ ) ,
91+ y : linearY + normWeigths . reduce (
92+ ( accum , currentValue , index ) => accum + currentValue * mapGps . forces [ index ] . force . y ,
93+ 0.0
94+ )
95+ }
96+ }
97+
98+ return predictor ;
99+ }
100+
101+ export {
102+ approxGps ,
103+ boundGpsToMap ,
104+ deg2rad ,
105+ getClosestFloor ,
106+ flattenSphericalCoord ,
107+ createPredictor
108+ }
0 commit comments