@wemap/geo 12.10.4 → 12.10.8-alpha.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.
- package/package.json +6 -2
- package/src/Constants.ts +0 -26
- package/src/Utils.spec.ts +0 -183
- package/src/Utils.ts +0 -218
- package/src/coordinates/BoundingBox.spec.ts +0 -198
- package/src/coordinates/BoundingBox.ts +0 -199
- package/src/coordinates/Coordinates.spec.ts +0 -278
- package/src/coordinates/Coordinates.ts +0 -401
- package/src/coordinates/GeoRef.spec.ts +0 -41
- package/src/coordinates/GeoRef.ts +0 -135
- package/src/coordinates/GeoRelativePosition.ts +0 -9
- package/src/coordinates/Level.spec.ts +0 -216
- package/src/coordinates/Level.ts +0 -348
- package/src/coordinates/RelativePosition.spec.ts +0 -153
- package/src/coordinates/RelativePosition.ts +0 -94
- package/src/coordinates/UserPosition.spec.ts +0 -213
- package/src/coordinates/UserPosition.ts +0 -132
- package/src/rotations/AbsoluteHeading.spec.ts +0 -98
- package/src/rotations/AbsoluteHeading.ts +0 -86
- package/src/rotations/Attitude.spec.ts +0 -285
- package/src/rotations/Attitude.ts +0 -162
- package/src/types.ts +0 -61
- package/tsconfig.json +0 -3
- package/vite.config.ts +0 -4
package/package.json
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"directory": "packages/geo"
|
|
14
14
|
},
|
|
15
15
|
"name": "@wemap/geo",
|
|
16
|
-
"version": "12.10.
|
|
16
|
+
"version": "12.10.8-alpha.0",
|
|
17
17
|
"bugs": {
|
|
18
18
|
"url": "https://github.com/wemap/wemap-modules-js/issues"
|
|
19
19
|
},
|
|
@@ -40,6 +40,10 @@
|
|
|
40
40
|
"@types/geojson": "^7946.0.14",
|
|
41
41
|
"jsdom-global": "^3.0.2"
|
|
42
42
|
},
|
|
43
|
+
"files": [
|
|
44
|
+
"dist",
|
|
45
|
+
"index.ts"
|
|
46
|
+
],
|
|
43
47
|
"exports": {
|
|
44
48
|
".": {
|
|
45
49
|
"types": "./index.ts",
|
|
@@ -48,5 +52,5 @@
|
|
|
48
52
|
},
|
|
49
53
|
"./tests/*": "./tests/*"
|
|
50
54
|
},
|
|
51
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "fcf82e31b4b60a8fb006488b337a800f79304722"
|
|
52
56
|
}
|
package/src/Constants.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
export const R_MAJOR = 6378137.0;
|
|
2
|
-
export const R_MINOR = 6356752.3142;
|
|
3
|
-
export const EARTH_GRAVITY = 9.80665;
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* latitude and longitude epsilon in degrees
|
|
7
|
-
* 1e-8° correspond to ~1mm at latitude = 0
|
|
8
|
-
*/
|
|
9
|
-
export const EPS_DEG_MM = 1e-8;
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* epsilon in meters which corresponds to 1 millimeter
|
|
13
|
-
*/
|
|
14
|
-
export const EPS_MM = 1e-3;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
export const ELLIPSOID_FLATNESS = (R_MAJOR - R_MINOR) / R_MAJOR;
|
|
18
|
-
|
|
19
|
-
export const ECCENTRICITY = Math.sqrt(ELLIPSOID_FLATNESS * (2 - ELLIPSOID_FLATNESS));
|
|
20
|
-
export const ECCENTRICITY_2 = ECCENTRICITY * ECCENTRICITY;
|
|
21
|
-
|
|
22
|
-
export const R_MAJOR_2 = R_MAJOR * R_MAJOR;
|
|
23
|
-
export const R_MAJOR_4 = R_MAJOR_2 * R_MAJOR_2;
|
|
24
|
-
export const R_MINOR_2 = R_MINOR * R_MINOR;
|
|
25
|
-
export const R_MINOR_4 = R_MINOR_2 * R_MINOR_2;
|
|
26
|
-
export const CIRCUMFERENCE = R_MAJOR * 2 * Math.PI;
|
package/src/Utils.spec.ts
DELETED
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
/* eslint-disable max-statements */
|
|
2
|
-
import chai from 'chai';
|
|
3
|
-
import chaiAlmost from 'chai-almost';
|
|
4
|
-
|
|
5
|
-
import { sampleRoute, simplifyRoute, trimRoute } from './Utils.js';
|
|
6
|
-
import Coordinates from './coordinates/Coordinates.js';
|
|
7
|
-
|
|
8
|
-
const expect = chai.expect;
|
|
9
|
-
|
|
10
|
-
describe('Geo Utils', () => {
|
|
11
|
-
|
|
12
|
-
it('sampleRoute', () => {
|
|
13
|
-
|
|
14
|
-
chai.use(chaiAlmost(1e-3));
|
|
15
|
-
|
|
16
|
-
let samples;
|
|
17
|
-
|
|
18
|
-
const p1 = new Coordinates(45.0, 5.0);
|
|
19
|
-
const p2 = p1.destinationPoint(100, Math.PI / 4);
|
|
20
|
-
const p3 = p2.destinationPoint(49.9, Math.PI / 2);
|
|
21
|
-
const route = [p1, p2, p3];
|
|
22
|
-
|
|
23
|
-
samples = sampleRoute(route);
|
|
24
|
-
expect(samples.length).equals(Math.ceil(149.9 / 0.7));
|
|
25
|
-
for (let i = 0; i < samples.length - 1; i++) {
|
|
26
|
-
// Ignore the crow flies for the turn
|
|
27
|
-
if (i === Math.floor(100 / 0.7)) {
|
|
28
|
-
i++;
|
|
29
|
-
}
|
|
30
|
-
expect(samples[i].distanceTo(samples[i + 1])).to.almost.equal(0.7);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
samples = sampleRoute(route, 10);
|
|
34
|
-
expect(samples.length).equals(15);
|
|
35
|
-
for (let i = 0; i < samples.length - 1; i++) {
|
|
36
|
-
expect(samples[i].distanceTo(samples[i + 1])).to.almost.equal(i === 14 ? 9.9 : 10);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
samples = sampleRoute(route, 10, 0, 99.9);
|
|
40
|
-
expect(samples.length).equals(10);
|
|
41
|
-
|
|
42
|
-
samples = sampleRoute(route, 10, 50, 12);
|
|
43
|
-
expect(samples.length).equals(2);
|
|
44
|
-
|
|
45
|
-
samples = sampleRoute(route, 10, 50, 100);
|
|
46
|
-
expect(samples.length).equals(10);
|
|
47
|
-
|
|
48
|
-
samples = sampleRoute(route, 10, 110, 12);
|
|
49
|
-
expect(samples.length).equals(2);
|
|
50
|
-
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('trimRoute', () => {
|
|
54
|
-
|
|
55
|
-
chai.use(chaiAlmost(1e-3));
|
|
56
|
-
|
|
57
|
-
let newRoute;
|
|
58
|
-
|
|
59
|
-
const p1 = new Coordinates(45.0, 5.0);
|
|
60
|
-
const p2 = p1.destinationPoint(100, Math.PI / 4);
|
|
61
|
-
const p3 = p2.destinationPoint(49.9, Math.PI / 2);
|
|
62
|
-
const route = [p1, p2, p3];
|
|
63
|
-
|
|
64
|
-
expect(() => trimRoute(route, new Coordinates(0, 0))).throw(Error);
|
|
65
|
-
expect(() => trimRoute([p1], p1)).throw(Error);
|
|
66
|
-
|
|
67
|
-
newRoute = trimRoute(route);
|
|
68
|
-
expect(newRoute.length).equals(3);
|
|
69
|
-
for (let i = 0; i < newRoute.length - 1; i++) {
|
|
70
|
-
expect(newRoute[i].equals(route[i])).true;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
newRoute = trimRoute(route, p1, 100);
|
|
74
|
-
expect(newRoute.length).equals(2);
|
|
75
|
-
expect(newRoute[0].equals(p1)).true;
|
|
76
|
-
expect(newRoute[1].equals(p2)).true;
|
|
77
|
-
|
|
78
|
-
newRoute = trimRoute(route, p1, 90);
|
|
79
|
-
expect(newRoute.length).equals(2);
|
|
80
|
-
expect(newRoute[0].equals(p1)).true;
|
|
81
|
-
expect(newRoute[1].equals(p1.destinationPoint(90, Math.PI / 4))).true;
|
|
82
|
-
|
|
83
|
-
newRoute = trimRoute(route, p2, 10);
|
|
84
|
-
expect(newRoute.length).equals(2);
|
|
85
|
-
expect(newRoute[0].equals(p2)).true;
|
|
86
|
-
expect(newRoute[1].equals(p2.destinationPoint(10, Math.PI / 2))).true;
|
|
87
|
-
|
|
88
|
-
const p4 = p1.destinationPoint(20, Math.PI / 4);
|
|
89
|
-
newRoute = trimRoute(route, p4);
|
|
90
|
-
expect(newRoute.length).equals(3);
|
|
91
|
-
expect(newRoute[0].equals(p4)).true;
|
|
92
|
-
expect(newRoute[1].equals(p2)).true;
|
|
93
|
-
expect(newRoute[2].equals(p3)).true;
|
|
94
|
-
|
|
95
|
-
const p5 = p2.destinationPoint(20, Math.PI / 2);
|
|
96
|
-
newRoute = trimRoute(route, p4, 100);
|
|
97
|
-
expect(newRoute.length).equals(3);
|
|
98
|
-
expect(newRoute[0].equals(p4)).true;
|
|
99
|
-
expect(newRoute[1].equals(p2)).true;
|
|
100
|
-
expect(newRoute[2].equals(p5)).true;
|
|
101
|
-
|
|
102
|
-
newRoute = trimRoute(route, p4, 200);
|
|
103
|
-
expect(newRoute.length).equals(3);
|
|
104
|
-
expect(newRoute[0].equals(p4)).true;
|
|
105
|
-
expect(newRoute[1].equals(p2)).true;
|
|
106
|
-
expect(newRoute[2].equals(p3)).true;
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it('simplifyRoute', () => {
|
|
110
|
-
|
|
111
|
-
let route, routeSimplified;
|
|
112
|
-
|
|
113
|
-
route = [
|
|
114
|
-
new Coordinates(48.756308386983484, 2.0549525696601694),
|
|
115
|
-
new Coordinates(48.75630194782273, 2.054987452552288),
|
|
116
|
-
new Coordinates(48.756294588780854, 2.055026521391461),
|
|
117
|
-
new Coordinates(48.7563159759933, 2.0550474511267316),
|
|
118
|
-
new Coordinates(48.756350241508265, 2.0550837293345348)
|
|
119
|
-
];
|
|
120
|
-
|
|
121
|
-
routeSimplified = simplifyRoute(route);
|
|
122
|
-
expect(routeSimplified.length).equal(3);
|
|
123
|
-
expect(routeSimplified).to.include(route[0]);
|
|
124
|
-
expect(routeSimplified).to.not.include(route[1]);
|
|
125
|
-
expect(routeSimplified).to.include(route[2]);
|
|
126
|
-
expect(routeSimplified).to.not.include(route[3]);
|
|
127
|
-
expect(routeSimplified).to.include(route[4]);
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
route = [
|
|
131
|
-
new Coordinates(48.75627274161895, 2.054974197053283),
|
|
132
|
-
new Coordinates(48.756269751891594, 2.0549905921869933),
|
|
133
|
-
new Coordinates(48.756274912970845, 2.054992757591672),
|
|
134
|
-
new Coordinates(48.75628117553095, 2.0549584148199345),
|
|
135
|
-
new Coordinates(48.756276014452325, 2.054956249415256),
|
|
136
|
-
new Coordinates(48.75627274161895, 2.054974197053283)
|
|
137
|
-
];
|
|
138
|
-
|
|
139
|
-
routeSimplified = simplifyRoute(route);
|
|
140
|
-
expect(routeSimplified.length).equal(5);
|
|
141
|
-
expect(routeSimplified).to.not.include(route[0]);
|
|
142
|
-
expect(routeSimplified).to.not.include(route[5]);
|
|
143
|
-
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
it('geolocationPositionToUserPosition', () => {
|
|
148
|
-
|
|
149
|
-
let route, routeSimplified;
|
|
150
|
-
|
|
151
|
-
route = [
|
|
152
|
-
new Coordinates(48.756308386983484, 2.0549525696601694),
|
|
153
|
-
new Coordinates(48.75630194782273, 2.054987452552288),
|
|
154
|
-
new Coordinates(48.756294588780854, 2.055026521391461),
|
|
155
|
-
new Coordinates(48.7563159759933, 2.0550474511267316),
|
|
156
|
-
new Coordinates(48.756350241508265, 2.0550837293345348)
|
|
157
|
-
];
|
|
158
|
-
|
|
159
|
-
routeSimplified = simplifyRoute(route);
|
|
160
|
-
expect(routeSimplified.length).equal(3);
|
|
161
|
-
expect(routeSimplified).to.include(route[0]);
|
|
162
|
-
expect(routeSimplified).to.not.include(route[1]);
|
|
163
|
-
expect(routeSimplified).to.include(route[2]);
|
|
164
|
-
expect(routeSimplified).to.not.include(route[3]);
|
|
165
|
-
expect(routeSimplified).to.include(route[4]);
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
route = [
|
|
169
|
-
new Coordinates(48.75627274161895, 2.054974197053283),
|
|
170
|
-
new Coordinates(48.756269751891594, 2.0549905921869933),
|
|
171
|
-
new Coordinates(48.756274912970845, 2.054992757591672),
|
|
172
|
-
new Coordinates(48.75628117553095, 2.0549584148199345),
|
|
173
|
-
new Coordinates(48.756276014452325, 2.054956249415256),
|
|
174
|
-
new Coordinates(48.75627274161895, 2.054974197053283)
|
|
175
|
-
];
|
|
176
|
-
|
|
177
|
-
routeSimplified = simplifyRoute(route);
|
|
178
|
-
expect(routeSimplified.length).equal(5);
|
|
179
|
-
expect(routeSimplified).to.not.include(route[0]);
|
|
180
|
-
expect(routeSimplified).to.not.include(route[5]);
|
|
181
|
-
|
|
182
|
-
});
|
|
183
|
-
});
|
package/src/Utils.ts
DELETED
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
/* eslint-disable max-statements */
|
|
2
|
-
|
|
3
|
-
import { deg2rad, positiveMod } from '@wemap/maths';
|
|
4
|
-
import { EPS_MM } from './Constants.js';
|
|
5
|
-
|
|
6
|
-
import Coordinates from './coordinates/Coordinates.js';
|
|
7
|
-
import UserPosition from './coordinates/UserPosition.js';
|
|
8
|
-
import Level from './coordinates/Level.js';
|
|
9
|
-
import { Level_t } from './types.js';
|
|
10
|
-
|
|
11
|
-
export type RouteSample = Coordinates & { bearing: number };
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Sample a route of Coordinates
|
|
15
|
-
* @param route ordered points
|
|
16
|
-
* @param stepSize step size to sample
|
|
17
|
-
* @param maxLength max route length to sample
|
|
18
|
-
*/
|
|
19
|
-
export function sampleRoute(
|
|
20
|
-
route: Coordinates[],
|
|
21
|
-
stepSize = 0.7,
|
|
22
|
-
startSampling = 0,
|
|
23
|
-
length = Number.MAX_VALUE
|
|
24
|
-
) {
|
|
25
|
-
|
|
26
|
-
const endSampling = startSampling + length;
|
|
27
|
-
|
|
28
|
-
const sampledRoute = [];
|
|
29
|
-
|
|
30
|
-
let lastSample: RouteSample;
|
|
31
|
-
|
|
32
|
-
let totalDistanceTraveled = 0;
|
|
33
|
-
let distanceToNextSample = 0;
|
|
34
|
-
let startFound = false;
|
|
35
|
-
|
|
36
|
-
for (let segmentIndex = 0; segmentIndex < route.length - 1; segmentIndex++) {
|
|
37
|
-
|
|
38
|
-
const p1 = route[segmentIndex];
|
|
39
|
-
const p2 = route[segmentIndex + 1];
|
|
40
|
-
const segmentSize = p1.distanceTo(p2);
|
|
41
|
-
const segmentBearing = p1.bearingTo(p2);
|
|
42
|
-
|
|
43
|
-
let distanceTraveledOnSegment = 0;
|
|
44
|
-
|
|
45
|
-
if (!startFound) {
|
|
46
|
-
if (startSampling < totalDistanceTraveled + segmentSize) {
|
|
47
|
-
startFound = true;
|
|
48
|
-
distanceToNextSample = startSampling - totalDistanceTraveled;
|
|
49
|
-
} else {
|
|
50
|
-
totalDistanceTraveled += segmentSize;
|
|
51
|
-
continue;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
lastSample = Object.assign(p1.clone(), { bearing: segmentBearing });
|
|
56
|
-
while (distanceTraveledOnSegment + distanceToNextSample < segmentSize
|
|
57
|
-
&& totalDistanceTraveled + distanceToNextSample <= endSampling) {
|
|
58
|
-
|
|
59
|
-
const newPoint = lastSample.destinationPoint(distanceToNextSample, segmentBearing) as RouteSample;
|
|
60
|
-
newPoint.bearing = segmentBearing;
|
|
61
|
-
sampledRoute.push(newPoint);
|
|
62
|
-
lastSample = newPoint;
|
|
63
|
-
|
|
64
|
-
distanceTraveledOnSegment += distanceToNextSample;
|
|
65
|
-
totalDistanceTraveled += distanceToNextSample;
|
|
66
|
-
distanceToNextSample = stepSize;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (totalDistanceTraveled + distanceToNextSample > endSampling) {
|
|
70
|
-
break;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const rest = segmentSize - distanceTraveledOnSegment;
|
|
74
|
-
totalDistanceTraveled += rest;
|
|
75
|
-
distanceToNextSample -= rest;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return sampledRoute;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Trim a route of Coordinates
|
|
83
|
-
* @param {Array.<Coordinates>} route ordered points
|
|
84
|
-
* @param {Coordinates} startPosition position where the trim starts. startPosition has to be on the route.
|
|
85
|
-
* @param {*} maxLength max route length
|
|
86
|
-
*/
|
|
87
|
-
export function trimRoute(route: Coordinates[], startPosition = route[0], length = Number.MAX_VALUE) {
|
|
88
|
-
|
|
89
|
-
const newRoute = [];
|
|
90
|
-
let previousPoint: Coordinates | null = null;
|
|
91
|
-
|
|
92
|
-
let currentPointIndex;
|
|
93
|
-
let cumulativeDistance = 0;
|
|
94
|
-
|
|
95
|
-
if (route.length <= 1) {
|
|
96
|
-
throw new Error('Route must have at least 2 points');
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
for (currentPointIndex = 1; currentPointIndex < route.length; currentPointIndex++) {
|
|
100
|
-
|
|
101
|
-
const p1 = route[currentPointIndex - 1];
|
|
102
|
-
const p2 = route[currentPointIndex];
|
|
103
|
-
|
|
104
|
-
if (Coordinates.equals(startPosition, p1)) {
|
|
105
|
-
newRoute.push(p1);
|
|
106
|
-
previousPoint = p1;
|
|
107
|
-
break;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const proj = startPosition.getSegmentProjection(p1, p2);
|
|
111
|
-
if (proj && Coordinates.equals(startPosition, proj) && !proj.equals(p2)) {
|
|
112
|
-
newRoute.push(proj);
|
|
113
|
-
previousPoint = proj;
|
|
114
|
-
break;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if (!newRoute.length) {
|
|
119
|
-
throw new Error('startPosition is not on the route');
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
while (previousPoint && currentPointIndex < route.length) {
|
|
123
|
-
const currentPoint = route[currentPointIndex];
|
|
124
|
-
const dist = previousPoint.distanceTo(currentPoint);
|
|
125
|
-
if (cumulativeDistance + dist >= length
|
|
126
|
-
|| Math.abs(cumulativeDistance + dist - length) <= EPS_MM) {
|
|
127
|
-
const bearing = previousPoint.bearingTo(currentPoint);
|
|
128
|
-
const remainingLength = length - cumulativeDistance;
|
|
129
|
-
const end = previousPoint.destinationPoint(remainingLength, bearing);
|
|
130
|
-
newRoute.push(end);
|
|
131
|
-
break;
|
|
132
|
-
}
|
|
133
|
-
newRoute.push(currentPoint);
|
|
134
|
-
previousPoint = currentPoint;
|
|
135
|
-
cumulativeDistance += dist;
|
|
136
|
-
currentPointIndex++;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return newRoute;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
export function simplifyRoute(coords: Coordinates[], precisionAngle = deg2rad(5)) {
|
|
144
|
-
|
|
145
|
-
const isClosed = (coords[0].equals(coords[coords.length - 1]));
|
|
146
|
-
|
|
147
|
-
let newRoute = coords.slice(0, coords.length - (isClosed ? 1 : 0));
|
|
148
|
-
|
|
149
|
-
const len = newRoute.length;
|
|
150
|
-
for (let i = isClosed ? 0 : 1; i < len; i++) {
|
|
151
|
-
|
|
152
|
-
const p0 = coords[positiveMod(i - 1, len)];
|
|
153
|
-
const p1 = coords[i];
|
|
154
|
-
const p2 = coords[positiveMod(i + 1, len)];
|
|
155
|
-
|
|
156
|
-
const seg1Dir = p0.bearingTo(p1);
|
|
157
|
-
const seg2Dir = p1.bearingTo(p2);
|
|
158
|
-
|
|
159
|
-
if (Math.abs(seg2Dir - seg1Dir) < precisionAngle) {
|
|
160
|
-
newRoute = newRoute.filter(coord => coord !== p1);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
if (isClosed) {
|
|
165
|
-
newRoute.push(newRoute[0]);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
return newRoute;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
export function geolocationPositionToUserPosition(geolocationPosition: GeolocationPosition) {
|
|
172
|
-
if (geolocationPosition === null) {
|
|
173
|
-
return null;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const { latitude, longitude, accuracy, heading } = geolocationPosition.coords;
|
|
177
|
-
|
|
178
|
-
const userPosition = new UserPosition(latitude, longitude);
|
|
179
|
-
userPosition.time = geolocationPosition.timestamp;
|
|
180
|
-
userPosition.accuracy = accuracy;
|
|
181
|
-
userPosition.bearing = heading ? deg2rad(heading) : null;
|
|
182
|
-
return userPosition;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
export function calcDistance(coords: Coordinates[]) {
|
|
186
|
-
return coords.reduce((acc, coords, idx, arr) =>
|
|
187
|
-
acc + (idx ? arr[idx - 1].distanceTo(coords) : 0), 0);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
export function createSegmentsAtLevel(itineraryCoords: Coordinates[], segmentsLevel: Level_t, useMultiLevelSegments = true) {
|
|
192
|
-
|
|
193
|
-
const itineraryCoordsLength = itineraryCoords.length;
|
|
194
|
-
let previousLevelCorrespond = false;
|
|
195
|
-
|
|
196
|
-
const segments: Coordinates[][] = [];
|
|
197
|
-
let coordinates: Coordinates[] = [];
|
|
198
|
-
for (let i = 0; i < itineraryCoordsLength; i++) {
|
|
199
|
-
const coords = itineraryCoords[i];
|
|
200
|
-
const levelCorrespond = Level.intersect(segmentsLevel, coords.level);
|
|
201
|
-
|
|
202
|
-
if (useMultiLevelSegments && !levelCorrespond && previousLevelCorrespond) {
|
|
203
|
-
coordinates.push(coords);
|
|
204
|
-
} else if (levelCorrespond) {
|
|
205
|
-
if (!previousLevelCorrespond) {
|
|
206
|
-
coordinates = [];
|
|
207
|
-
segments.push(coordinates);
|
|
208
|
-
if (useMultiLevelSegments && i !== 0) {
|
|
209
|
-
coordinates.push(itineraryCoords[i - 1]);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
coordinates.push(coords);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
previousLevelCorrespond = levelCorrespond;
|
|
216
|
-
}
|
|
217
|
-
return segments;
|
|
218
|
-
}
|
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
/* eslint-disable max-nested-callbacks */
|
|
2
|
-
import { Vector4_t } from '@wemap/maths';
|
|
3
|
-
import chai from 'chai';
|
|
4
|
-
import chaiAlmost from 'chai-almost';
|
|
5
|
-
|
|
6
|
-
import BoundingBox from './BoundingBox.js';
|
|
7
|
-
import Coordinates from './Coordinates.js';
|
|
8
|
-
|
|
9
|
-
const expect = chai.expect;
|
|
10
|
-
chai.use(chaiAlmost());
|
|
11
|
-
|
|
12
|
-
let boundingBox: BoundingBox;
|
|
13
|
-
const northEast = new Coordinates(10, 40);
|
|
14
|
-
const southWest = new Coordinates(-5, -20);
|
|
15
|
-
|
|
16
|
-
const checkBounds = (bb: BoundingBox, [north, east, south, west]: Vector4_t) => {
|
|
17
|
-
return north === bb.northEast.lat
|
|
18
|
-
&& east === bb.northEast.lng
|
|
19
|
-
&& south === bb.southWest.lat
|
|
20
|
-
&& west === bb.southWest.lng;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
describe('Bounding Box', () => {
|
|
24
|
-
|
|
25
|
-
it('creation', () => {
|
|
26
|
-
expect(() => new BoundingBox(new Coordinates(10, -20), new Coordinates(-5, 40))).not.throw(Error);
|
|
27
|
-
expect(() => new BoundingBox(new Coordinates(-5, -20), new Coordinates(10, 40))).is.throw(Error);
|
|
28
|
-
|
|
29
|
-
boundingBox = new BoundingBox(northEast, southWest);
|
|
30
|
-
expect(boundingBox.northEast).equals(northEast);
|
|
31
|
-
expect(boundingBox.southWest).equals(southWest);
|
|
32
|
-
|
|
33
|
-
const boundingBox2 = BoundingBox.fromArray([-20, -5, 40, 10]);
|
|
34
|
-
expect(boundingBox2.equals(boundingBox)).is.true;
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
it('equals', () => {
|
|
39
|
-
boundingBox = new BoundingBox(northEast, southWest);
|
|
40
|
-
expect(boundingBox.equals(new BoundingBox(
|
|
41
|
-
new Coordinates(10, 40), new Coordinates(-5, -20)
|
|
42
|
-
))).true;
|
|
43
|
-
expect(BoundingBox.equals(boundingBox, new BoundingBox(
|
|
44
|
-
new Coordinates(10, 40), new Coordinates(-5, -20)
|
|
45
|
-
))).true;
|
|
46
|
-
expect(BoundingBox.equals(boundingBox, new BoundingBox(
|
|
47
|
-
new Coordinates(10, 10), new Coordinates(-5, -20)
|
|
48
|
-
))).false;
|
|
49
|
-
expect(BoundingBox.equals(boundingBox, new BoundingBox(
|
|
50
|
-
new Coordinates(10, 40), new Coordinates(-15, -20)
|
|
51
|
-
))).false;
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('bounds', () => {
|
|
55
|
-
boundingBox = new BoundingBox(northEast, southWest);
|
|
56
|
-
expect(boundingBox.getNorth()).equals(northEast.lat);
|
|
57
|
-
expect(boundingBox.getEast()).equals(northEast.lng);
|
|
58
|
-
expect(boundingBox.getSouth()).equals(southWest.lat);
|
|
59
|
-
expect(boundingBox.getWest()).equals(southWest.lng);
|
|
60
|
-
expect(Coordinates.equals(boundingBox.getNorthEast(), northEast)).true;
|
|
61
|
-
expect(Coordinates.equals(boundingBox.getSouthWest(), southWest)).true;
|
|
62
|
-
expect(Coordinates.equals(boundingBox.getNorthWest(),
|
|
63
|
-
new Coordinates(northEast.lat, southWest.lng))).true;
|
|
64
|
-
expect(Coordinates.equals(boundingBox.getSouthEast(),
|
|
65
|
-
new Coordinates(southWest.lat, northEast.lng))).true;
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
it('center', () => {
|
|
70
|
-
boundingBox = new BoundingBox(northEast, southWest);
|
|
71
|
-
const center = boundingBox.center;
|
|
72
|
-
expect(center.lat).equals(2.5);
|
|
73
|
-
expect(center.lng).equals(10);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
it('contains', () => {
|
|
78
|
-
boundingBox = new BoundingBox(northEast, southWest);
|
|
79
|
-
expect(boundingBox.contains(new Coordinates(0, 0))).true;
|
|
80
|
-
expect(boundingBox.contains(new Coordinates(10, 0))).true;
|
|
81
|
-
expect(boundingBox.contains(new Coordinates(0, 10))).true;
|
|
82
|
-
expect(boundingBox.contains(new Coordinates(-10, 0))).false;
|
|
83
|
-
expect(boundingBox.contains(new Coordinates(0, -10))).true;
|
|
84
|
-
expect(boundingBox.contains(new Coordinates(50, 50))).false;
|
|
85
|
-
expect(boundingBox.contains(new Coordinates(-50, 50))).false;
|
|
86
|
-
expect(boundingBox.contains(new Coordinates(50, -50))).false;
|
|
87
|
-
expect(boundingBox.contains(new Coordinates(-50, -50))).false;
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it('extend', () => {
|
|
91
|
-
boundingBox = new BoundingBox(northEast, southWest);
|
|
92
|
-
expect(checkBounds(
|
|
93
|
-
boundingBox.extend(new Coordinates(0, 0)),
|
|
94
|
-
[10, 40, -5, -20]
|
|
95
|
-
)).true;
|
|
96
|
-
expect(checkBounds(
|
|
97
|
-
boundingBox.extend(new Coordinates(20, 0)),
|
|
98
|
-
[20, 40, -5, -20]
|
|
99
|
-
)).true;
|
|
100
|
-
expect(checkBounds(
|
|
101
|
-
boundingBox.extend(new Coordinates(20, 40)),
|
|
102
|
-
[20, 40, -5, -20]
|
|
103
|
-
)).true;
|
|
104
|
-
expect(checkBounds(
|
|
105
|
-
boundingBox.extend(new Coordinates(30, 40)),
|
|
106
|
-
[30, 40, -5, -20]
|
|
107
|
-
)).true;
|
|
108
|
-
|
|
109
|
-
boundingBox = new BoundingBox(northEast, southWest);
|
|
110
|
-
boundingBox.extend(new BoundingBox(
|
|
111
|
-
new Coordinates(10, 10), new Coordinates(-10, -10)
|
|
112
|
-
));
|
|
113
|
-
expect(checkBounds(boundingBox, [10, 40, -10, -20])).true;
|
|
114
|
-
|
|
115
|
-
boundingBox = new BoundingBox(northEast, northEast);
|
|
116
|
-
boundingBox.extend(new BoundingBox(northEast, southWest));
|
|
117
|
-
expect(checkBounds(boundingBox, [10, 40, -5, -20])).true;
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
it('extend with measure', () => {
|
|
122
|
-
let measure, extended;
|
|
123
|
-
|
|
124
|
-
boundingBox = new BoundingBox(northEast, southWest);
|
|
125
|
-
measure = 50000;
|
|
126
|
-
extended = boundingBox.extendsWithMeasure(measure);
|
|
127
|
-
expect(new Coordinates(extended.northEast.lat, northEast.lng).distanceTo(northEast))
|
|
128
|
-
.be.closeTo(measure, 0.05 * measure);
|
|
129
|
-
expect(new Coordinates(northEast.lat, extended.northEast.lng).distanceTo(northEast))
|
|
130
|
-
.be.closeTo(measure, 0.05 * measure);
|
|
131
|
-
expect(new Coordinates(extended.southWest.lat, southWest.lng).distanceTo(southWest))
|
|
132
|
-
.be.closeTo(measure, 0.05 * measure);
|
|
133
|
-
expect(new Coordinates(southWest.lat, extended.southWest.lng).distanceTo(southWest))
|
|
134
|
-
.be.closeTo(measure, 0.05 * measure);
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
boundingBox = new BoundingBox(northEast, southWest);
|
|
138
|
-
measure = 50;
|
|
139
|
-
extended = boundingBox.extendsWithMeasure(measure);
|
|
140
|
-
expect(new Coordinates(extended.northEast.lat, northEast.lng).distanceTo(northEast))
|
|
141
|
-
.be.closeTo(measure, 0.05 * measure);
|
|
142
|
-
expect(new Coordinates(northEast.lat, extended.northEast.lng).distanceTo(northEast))
|
|
143
|
-
.be.closeTo(measure, 0.05 * measure);
|
|
144
|
-
expect(new Coordinates(extended.southWest.lat, southWest.lng).distanceTo(southWest))
|
|
145
|
-
.be.closeTo(measure, 0.05 * measure);
|
|
146
|
-
expect(new Coordinates(southWest.lat, extended.southWest.lng).distanceTo(southWest))
|
|
147
|
-
.be.closeTo(measure, 0.05 * measure);
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
it('pad', () => {
|
|
151
|
-
|
|
152
|
-
let distBefore, distAfter;
|
|
153
|
-
|
|
154
|
-
boundingBox = new BoundingBox(northEast, southWest);
|
|
155
|
-
const bufferRatio = 0.3;
|
|
156
|
-
const extended = new BoundingBox(northEast, southWest).pad(bufferRatio);
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
distBefore = new Coordinates(boundingBox.getNorth(), boundingBox.getWest()).distanceTo(
|
|
160
|
-
new Coordinates(boundingBox.getNorth(), boundingBox.getEast())
|
|
161
|
-
);
|
|
162
|
-
distAfter = new Coordinates(extended.getNorth(), extended.getWest()).distanceTo(
|
|
163
|
-
new Coordinates(extended.getNorth(), extended.getEast())
|
|
164
|
-
);
|
|
165
|
-
expect(distAfter).be.closeTo(distBefore * (1 + bufferRatio * 2), distAfter * 0.05);
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
distBefore = new Coordinates(boundingBox.getSouth(), boundingBox.getWest()).distanceTo(
|
|
169
|
-
new Coordinates(boundingBox.getSouth(), boundingBox.getEast())
|
|
170
|
-
);
|
|
171
|
-
distAfter = new Coordinates(extended.getSouth(), extended.getWest()).distanceTo(
|
|
172
|
-
new Coordinates(extended.getSouth(), extended.getEast())
|
|
173
|
-
);
|
|
174
|
-
expect(distAfter).be.closeTo(distBefore * (1 + bufferRatio * 2), distAfter * 0.05);
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
distBefore = new Coordinates(boundingBox.getNorth(), boundingBox.getEast()).distanceTo(
|
|
178
|
-
new Coordinates(boundingBox.getSouth(), boundingBox.getEast())
|
|
179
|
-
);
|
|
180
|
-
distAfter = new Coordinates(extended.getNorth(), extended.getEast()).distanceTo(
|
|
181
|
-
new Coordinates(extended.getSouth(), extended.getEast())
|
|
182
|
-
);
|
|
183
|
-
expect(distAfter).be.closeTo(distBefore * (1 + bufferRatio * 2), distAfter * 0.05);
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
distBefore = new Coordinates(boundingBox.getNorth(), boundingBox.getWest()).distanceTo(
|
|
187
|
-
new Coordinates(boundingBox.getSouth(), boundingBox.getWest())
|
|
188
|
-
);
|
|
189
|
-
distAfter = new Coordinates(extended.getNorth(), extended.getWest()).distanceTo(
|
|
190
|
-
new Coordinates(extended.getSouth(), extended.getWest())
|
|
191
|
-
);
|
|
192
|
-
expect(distAfter).be.closeTo(distBefore * (1 + bufferRatio * 2), distAfter * 0.05);
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
it('toArray', () => {
|
|
196
|
-
expect(new BoundingBox(northEast, southWest).toArray()).deep.equals([-20, -5, 40, 10]);
|
|
197
|
-
});
|
|
198
|
-
});
|