@wemap/geo 1.0.1 → 1.0.2
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/index.js
CHANGED
|
@@ -2,12 +2,14 @@ import Constants from './src/Constants';
|
|
|
2
2
|
|
|
3
3
|
import Attitude from './src/rotations/Attitude';
|
|
4
4
|
|
|
5
|
+
import BoundingBox from './src/coordinates/BoundingBox';
|
|
5
6
|
import Level from './src/coordinates/Level';
|
|
6
7
|
import WGS84 from './src/coordinates/WGS84';
|
|
7
8
|
import WGS84UserPosition from './src/coordinates/WGS84UserPosition';
|
|
8
9
|
|
|
9
10
|
export {
|
|
10
11
|
Attitude,
|
|
12
|
+
BoundingBox,
|
|
11
13
|
Constants,
|
|
12
14
|
Level,
|
|
13
15
|
WGS84,
|
package/package.json
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"directory": "packages/geo"
|
|
13
13
|
},
|
|
14
14
|
"name": "@wemap/geo",
|
|
15
|
-
"version": "1.0.
|
|
15
|
+
"version": "1.0.2",
|
|
16
16
|
"bugs": {
|
|
17
17
|
"url": "https://github.com/wemap/wemap-utils-js/issues"
|
|
18
18
|
},
|
|
@@ -28,8 +28,9 @@
|
|
|
28
28
|
"license": "ISC",
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@wemap/maths": "^0.2.1",
|
|
31
|
+
"lodash.isfinite": "^3.3.2",
|
|
31
32
|
"lodash.isnumber": "^3.0.3",
|
|
32
33
|
"lodash.isstring": "^4.0.1"
|
|
33
34
|
},
|
|
34
|
-
"gitHead": "
|
|
35
|
+
"gitHead": "ba6b8ab6550b6b3bf87eddff821865e3147cfc96"
|
|
35
36
|
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import WGS84 from './WGS84';
|
|
2
|
+
import isNumber from 'lodash.isnumber';
|
|
3
|
+
import isFinite from 'lodash.isfinite';
|
|
4
|
+
|
|
5
|
+
class BoundingBox {
|
|
6
|
+
|
|
7
|
+
northEast;
|
|
8
|
+
southWest;
|
|
9
|
+
|
|
10
|
+
constructor(northEast, southWest) {
|
|
11
|
+
this.southWest = southWest || null;
|
|
12
|
+
this.northEast = northEast || null;
|
|
13
|
+
|
|
14
|
+
if (this.southWest && this.northEast
|
|
15
|
+
&& (
|
|
16
|
+
this.southWest.lat > this.northEast.lat
|
|
17
|
+
|| this.southWest.lng > this.northEast.lng)
|
|
18
|
+
) {
|
|
19
|
+
throw new Error('Incorrect bounding box');
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Returns the geographical coordinate equidistant from the bounding box's corners.
|
|
25
|
+
*
|
|
26
|
+
* @returns {WGS84} The bounding box's center.
|
|
27
|
+
*/
|
|
28
|
+
get center() {
|
|
29
|
+
const latCenter = (this.southWest.lat + this.northEast.lat) / 2;
|
|
30
|
+
const lngCenter = (this.northEast.lng + this.southWest.lng) / 2;
|
|
31
|
+
return new WGS84(latCenter, lngCenter);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Check if a point is contained in the bounding box.
|
|
36
|
+
*
|
|
37
|
+
* @returns {WGS84} The point to analyze.
|
|
38
|
+
*/
|
|
39
|
+
contains(point) {
|
|
40
|
+
return point.lat <= this.northEast.lat
|
|
41
|
+
&& point.lat >= this.southWest.lat
|
|
42
|
+
&& point.lng <= this.northEast.lng
|
|
43
|
+
&& point.lng >= this.southWest.lng;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Extend the bounds to include a given LngLat or LngLatBounds.
|
|
48
|
+
*
|
|
49
|
+
* @param {WGS84|BoundingBox} obj object to extend to
|
|
50
|
+
* @returns {BoundingBox} `this`
|
|
51
|
+
*/
|
|
52
|
+
extend(obj) {
|
|
53
|
+
const sw = this.southWest,
|
|
54
|
+
ne = this.northEast;
|
|
55
|
+
let sw2, ne2;
|
|
56
|
+
|
|
57
|
+
if (obj instanceof WGS84) {
|
|
58
|
+
sw2 = obj;
|
|
59
|
+
ne2 = obj;
|
|
60
|
+
|
|
61
|
+
} else if (obj instanceof BoundingBox) {
|
|
62
|
+
sw2 = obj.southWest;
|
|
63
|
+
ne2 = obj.northEast;
|
|
64
|
+
|
|
65
|
+
if (!sw2 || !ne2) {
|
|
66
|
+
return this;
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
throw new Error('Unknown parameter');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!sw && !ne) {
|
|
73
|
+
this.southWest = new WGS84(sw2.lat, sw2.lng);
|
|
74
|
+
this.northEast = new WGS84(ne2.lat, ne2.lng);
|
|
75
|
+
|
|
76
|
+
} else {
|
|
77
|
+
sw.lat = Math.min(sw2.lat, sw.lat);
|
|
78
|
+
sw.lng = Math.min(sw2.lng, sw.lng);
|
|
79
|
+
ne.lat = Math.max(ne2.lat, ne.lat);
|
|
80
|
+
ne.lng = Math.max(ne2.lng, ne.lng);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return this;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* This method extends the bounding box with a value in meters
|
|
88
|
+
* /*\ This method is not precise as distance differs in function of latitude
|
|
89
|
+
* @param {Number} measure in meters
|
|
90
|
+
*/
|
|
91
|
+
extendsWithMeasure(measure) {
|
|
92
|
+
|
|
93
|
+
if (!isNumber(measure) || !isFinite(measure)) {
|
|
94
|
+
throw new Error('measure is not a number');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
this.northEast = this.northEast
|
|
98
|
+
.destinationPoint(measure, 0)
|
|
99
|
+
.move(measure, Math.PI / 2);
|
|
100
|
+
|
|
101
|
+
this.southWest = this.southWest.clone()
|
|
102
|
+
.destinationPoint(measure, -Math.PI / 2)
|
|
103
|
+
.destinationPoint(measure, Math.PI);
|
|
104
|
+
|
|
105
|
+
return this;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Returns the southwest corner of the bounding box.
|
|
110
|
+
*
|
|
111
|
+
* @returns {WGS84} The southwest corner of the bounding box.
|
|
112
|
+
*/
|
|
113
|
+
getSouthWest() {
|
|
114
|
+
return this.southWest;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Returns the northeast corner of the bounding box.
|
|
119
|
+
*
|
|
120
|
+
* @returns {WGS84} The northeast corner of the bounding box.
|
|
121
|
+
*/
|
|
122
|
+
getNorthEast() {
|
|
123
|
+
return this.northEast;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Returns the northwest corner of the bounding box.
|
|
128
|
+
*
|
|
129
|
+
* @returns {WGS84} The northwest corner of the bounding box.
|
|
130
|
+
*/
|
|
131
|
+
getNorthWest() {
|
|
132
|
+
return new WGS84(this.getNorth(), this.getWest());
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Returns the southeast corner of the bounding box.
|
|
137
|
+
*
|
|
138
|
+
* @returns {LngLat} The southeast corner of the bounding box.
|
|
139
|
+
*/
|
|
140
|
+
getSouthEast() {
|
|
141
|
+
return new WGS84(this.getSouth(), this.getEast());
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Returns the west edge of the bounding box.
|
|
146
|
+
*
|
|
147
|
+
* @returns {number} The west edge of the bounding box.
|
|
148
|
+
*/
|
|
149
|
+
getWest() {
|
|
150
|
+
return this.southWest.lng;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Returns the south edge of the bounding box.
|
|
155
|
+
*
|
|
156
|
+
* @returns {number} The south edge of the bounding box.
|
|
157
|
+
*/
|
|
158
|
+
getSouth() {
|
|
159
|
+
return this.southWest.lat;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Returns the east edge of the bounding box.
|
|
164
|
+
*
|
|
165
|
+
* @returns {number} The east edge of the bounding box.
|
|
166
|
+
*/
|
|
167
|
+
getEast() {
|
|
168
|
+
return this.northEast.lng;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Returns the north edge of the bounding box.
|
|
173
|
+
*
|
|
174
|
+
* @returns {number} The north edge of the bounding box.
|
|
175
|
+
*/
|
|
176
|
+
getNorth() {
|
|
177
|
+
return this.northEast.lat;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
equalsTo(other) {
|
|
181
|
+
return WGS84.equalsTo(this.northEast, other.northEast)
|
|
182
|
+
&& WGS84.equalsTo(this.southWest, other.southWest);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export default BoundingBox;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/* eslint-disable max-nested-callbacks */
|
|
2
|
+
import chai from 'chai';
|
|
3
|
+
import chaiAlmost from 'chai-almost';
|
|
4
|
+
|
|
5
|
+
import BoundingBox from './BoundingBox';
|
|
6
|
+
import Logger from '@wemap/logger';
|
|
7
|
+
import WGS84 from './WGS84';
|
|
8
|
+
|
|
9
|
+
const expect = chai.expect;
|
|
10
|
+
chai.use(chaiAlmost());
|
|
11
|
+
Logger.enable(false);
|
|
12
|
+
|
|
13
|
+
let boundingBox;
|
|
14
|
+
const northEast = new WGS84(10, 40);
|
|
15
|
+
const southWest = new WGS84(-5, -20);
|
|
16
|
+
|
|
17
|
+
const checkBounds = (bb, [north, east, south, west]) => {
|
|
18
|
+
return north === bb.northEast.lat
|
|
19
|
+
&& east === bb.northEast.lng
|
|
20
|
+
&& south === bb.southWest.lat
|
|
21
|
+
&& west === bb.southWest.lng;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
describe('Bounding Box', () => {
|
|
25
|
+
|
|
26
|
+
it('creation', () => {
|
|
27
|
+
boundingBox = new BoundingBox();
|
|
28
|
+
expect(boundingBox.northEast).is.null;
|
|
29
|
+
expect(boundingBox.southWest).is.null;
|
|
30
|
+
|
|
31
|
+
expect(() => new BoundingBox(new WGS84(10, -20), new WGS84(-5, 40))).is.throw(Error);
|
|
32
|
+
|
|
33
|
+
boundingBox = new BoundingBox(northEast, southWest);
|
|
34
|
+
expect(boundingBox.northEast).equals(northEast);
|
|
35
|
+
expect(boundingBox.southWest).equals(southWest);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
it('center', () => {
|
|
40
|
+
boundingBox = new BoundingBox();
|
|
41
|
+
expect(() => boundingBox.center).is.throw(Error);
|
|
42
|
+
|
|
43
|
+
boundingBox = new BoundingBox(northEast, southWest);
|
|
44
|
+
const center = boundingBox.center;
|
|
45
|
+
expect(center.lat).equals(2.5);
|
|
46
|
+
expect(center.lng).equals(10);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
it('contains', () => {
|
|
51
|
+
boundingBox = new BoundingBox();
|
|
52
|
+
expect(() => boundingBox.contains(new WGS84(0, 0))).is.throw(Error);
|
|
53
|
+
|
|
54
|
+
boundingBox = new BoundingBox(northEast, southWest);
|
|
55
|
+
expect(() => boundingBox.contains(null)).is.throw(Error);
|
|
56
|
+
expect(boundingBox.contains(new WGS84(0, 0))).true;
|
|
57
|
+
expect(boundingBox.contains(new WGS84(10, 0))).true;
|
|
58
|
+
expect(boundingBox.contains(new WGS84(0, 10))).true;
|
|
59
|
+
expect(boundingBox.contains(new WGS84(-10, 0))).false;
|
|
60
|
+
expect(boundingBox.contains(new WGS84(0, -10))).true;
|
|
61
|
+
expect(boundingBox.contains(new WGS84(50, 50))).false;
|
|
62
|
+
expect(boundingBox.contains(new WGS84(-50, 50))).false;
|
|
63
|
+
expect(boundingBox.contains(new WGS84(50, -50))).false;
|
|
64
|
+
expect(boundingBox.contains(new WGS84(-50, -50))).false;
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('extend', () => {
|
|
68
|
+
boundingBox = new BoundingBox();
|
|
69
|
+
expect(() => boundingBox.extend(new WGS84(0, 0))).is.throw;
|
|
70
|
+
|
|
71
|
+
boundingBox = new BoundingBox(northEast, southWest);
|
|
72
|
+
expect(() => boundingBox.extend(null)).is.throw(Error);
|
|
73
|
+
expect(checkBounds(
|
|
74
|
+
boundingBox.extend(new WGS84(0, 0)),
|
|
75
|
+
[10, 40, -5, -20]
|
|
76
|
+
)).true;
|
|
77
|
+
expect(checkBounds(
|
|
78
|
+
boundingBox.extend(new WGS84(20, 0)),
|
|
79
|
+
[20, 40, -5, -20]
|
|
80
|
+
)).true;
|
|
81
|
+
expect(checkBounds(
|
|
82
|
+
boundingBox.extend(new WGS84(20, 40)),
|
|
83
|
+
[20, 40, -5, -20]
|
|
84
|
+
)).true;
|
|
85
|
+
expect(checkBounds(
|
|
86
|
+
boundingBox.extend(new WGS84(30, 40)),
|
|
87
|
+
[30, 40, -5, -20]
|
|
88
|
+
)).true;
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
it('extend with measure', () => {
|
|
93
|
+
let measure, extended;
|
|
94
|
+
|
|
95
|
+
boundingBox = new BoundingBox();
|
|
96
|
+
expect(() => boundingBox.extendsWithMeasure(100)).is.throw(Error);
|
|
97
|
+
|
|
98
|
+
boundingBox = new BoundingBox(northEast, southWest);
|
|
99
|
+
expect(() => boundingBox.extendsWithMeasure(null)).is.throw(Error);
|
|
100
|
+
|
|
101
|
+
boundingBox = new BoundingBox(northEast, southWest);
|
|
102
|
+
measure = 50000;
|
|
103
|
+
extended = boundingBox.extendsWithMeasure(measure);
|
|
104
|
+
expect(new WGS84(extended.northEast.lat, northEast.lng).distanceTo(northEast))
|
|
105
|
+
.be.closeTo(measure, 0.05 * measure);
|
|
106
|
+
expect(new WGS84(northEast.lat, extended.northEast.lng).distanceTo(northEast))
|
|
107
|
+
.be.closeTo(measure, 0.05 * measure);
|
|
108
|
+
expect(new WGS84(extended.southWest.lat, southWest.lng).distanceTo(southWest))
|
|
109
|
+
.be.closeTo(measure, 0.05 * measure);
|
|
110
|
+
expect(new WGS84(southWest.lat, extended.southWest.lng).distanceTo(southWest))
|
|
111
|
+
.be.closeTo(measure, 0.05 * measure);
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
boundingBox = new BoundingBox(northEast, southWest);
|
|
115
|
+
measure = 50;
|
|
116
|
+
extended = boundingBox.extendsWithMeasure(measure);
|
|
117
|
+
expect(new WGS84(extended.northEast.lat, northEast.lng).distanceTo(northEast))
|
|
118
|
+
.be.closeTo(measure, 0.05 * measure);
|
|
119
|
+
expect(new WGS84(northEast.lat, extended.northEast.lng).distanceTo(northEast))
|
|
120
|
+
.be.closeTo(measure, 0.05 * measure);
|
|
121
|
+
expect(new WGS84(extended.southWest.lat, southWest.lng).distanceTo(southWest))
|
|
122
|
+
.be.closeTo(measure, 0.05 * measure);
|
|
123
|
+
expect(new WGS84(southWest.lat, extended.southWest.lng).distanceTo(southWest))
|
|
124
|
+
.be.closeTo(measure, 0.05 * measure);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
});
|
package/src/coordinates/Level.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Logger from '@wemap/logger';
|
|
2
|
-
import
|
|
2
|
+
import isFinite from 'lodash.isfinite';
|
|
3
3
|
import isString from 'lodash.isstring';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -17,10 +17,10 @@ class Level {
|
|
|
17
17
|
* @param {Number} arg2 (optional) up value
|
|
18
18
|
*/
|
|
19
19
|
constructor(arg1, arg2) {
|
|
20
|
-
if (!
|
|
20
|
+
if (!isFinite(arg1)) {
|
|
21
21
|
throw new Error('first argument is mandatory');
|
|
22
22
|
}
|
|
23
|
-
if (
|
|
23
|
+
if (isFinite(arg2)) {
|
|
24
24
|
if (arg1 === arg2) {
|
|
25
25
|
this.isRange = false;
|
|
26
26
|
this.val = arg1;
|
|
@@ -29,9 +29,11 @@ class Level {
|
|
|
29
29
|
this.low = Math.min(arg1, arg2);
|
|
30
30
|
this.up = Math.max(arg1, arg2);
|
|
31
31
|
}
|
|
32
|
-
} else {
|
|
32
|
+
} else if (typeof arg2 === 'undefined'){
|
|
33
33
|
this.isRange = false;
|
|
34
34
|
this.val = arg1;
|
|
35
|
+
} else {
|
|
36
|
+
throw new Error('second argument is not a number');
|
|
35
37
|
}
|
|
36
38
|
}
|
|
37
39
|
|
|
@@ -31,7 +31,7 @@ describe('Level', () => {
|
|
|
31
31
|
|
|
32
32
|
listOfLevels.forEach(value1 => {
|
|
33
33
|
if (listOfInvalidLevel.includes(value1)) {
|
|
34
|
-
expect(() => new Level(value1)).is.throw;
|
|
34
|
+
expect(() => new Level(value1)).is.throw(Error);
|
|
35
35
|
} else {
|
|
36
36
|
checkSingle(new Level(value1), value1);
|
|
37
37
|
}
|
|
@@ -39,8 +39,8 @@ describe('Level', () => {
|
|
|
39
39
|
listOfLevels.forEach(value2 => {
|
|
40
40
|
if (listOfInvalidLevel.includes(value1)
|
|
41
41
|
|| listOfInvalidLevel.includes(value2)) {
|
|
42
|
-
expect(() => new Level(value1, value2)).is.throw;
|
|
43
|
-
expect(() => new Level(value2, value1)).is.throw;
|
|
42
|
+
expect(() => new Level(value1, value2)).is.throw(Error);
|
|
43
|
+
expect(() => new Level(value2, value1)).is.throw(Error);
|
|
44
44
|
} else if (value1 === value2) {
|
|
45
45
|
checkSingle(new Level(value1), value1);
|
|
46
46
|
} else {
|
package/src/coordinates/WGS84.js
CHANGED
|
@@ -65,13 +65,17 @@ class WGS84 {
|
|
|
65
65
|
return output;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
equalsTo(
|
|
69
|
-
|
|
70
|
-
if (!(other instanceof WGS84)) {
|
|
68
|
+
static equalsTo(pos1, pos2) {
|
|
69
|
+
if (!(pos1 instanceof WGS84) || !(pos2 instanceof WGS84)) {
|
|
71
70
|
return false;
|
|
72
71
|
}
|
|
72
|
+
return pos2.lat === pos1.lat
|
|
73
|
+
&& pos2.lng === pos1.lng
|
|
74
|
+
&& Level.equalsTo(pos2.level, pos1.level);
|
|
75
|
+
}
|
|
73
76
|
|
|
74
|
-
|
|
77
|
+
equalsTo(other) {
|
|
78
|
+
return WGS84.equalsTo(this, other);
|
|
75
79
|
}
|
|
76
80
|
|
|
77
81
|
toString() {
|
|
@@ -109,6 +113,8 @@ class WGS84 {
|
|
|
109
113
|
this.lat = Utils.rad2deg(φ2);
|
|
110
114
|
this.lng = Utils.rad2deg(λ2);
|
|
111
115
|
this.alt = altitude;
|
|
116
|
+
|
|
117
|
+
return this;
|
|
112
118
|
}
|
|
113
119
|
|
|
114
120
|
/**
|