@wemap/geo 1.0.1 → 1.0.3

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.1",
15
+ "version": "1.0.3",
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": "f4d8fe98fff281533d884e0479894662c4dec9fe"
35
+ "gitHead": "ecc9848b178778edd77176fc4c329faccdde032a"
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
+ });
@@ -1,5 +1,5 @@
1
1
  import Logger from '@wemap/logger';
2
- import isNumber from 'lodash.isnumber';
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 (!isNumber(arg1)) {
20
+ if (!isFinite(arg1)) {
21
21
  throw new Error('first argument is mandatory');
22
22
  }
23
- if (isNumber(arg2)) {
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 {
@@ -65,13 +65,17 @@ class WGS84 {
65
65
  return output;
66
66
  }
67
67
 
68
- equalsTo(other) {
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
- return other.lat === this.lat && other.lng === this.lng && Level.equalsTo(other.level, this.level);
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
  /**