UNPKG

2.49 kBJavaScriptView Raw
1const extent = require('geojson-extent');
2const Constants = require('../constants');
3
4const {
5 LAT_MIN,
6 LAT_MAX,
7 LAT_RENDERED_MIN,
8 LAT_RENDERED_MAX,
9 LNG_MIN,
10 LNG_MAX
11} = Constants;
12
13// Ensure that we do not drag north-south far enough for
14// - any part of any feature to exceed the poles
15// - any feature to be completely lost in the space between the projection's
16// edge and the poles, such that it couldn't be re-selected and moved back
17module.exports = function(geojsonFeatures, delta) {
18 // "inner edge" = a feature's latitude closest to the equator
19 let northInnerEdge = LAT_MIN;
20 let southInnerEdge = LAT_MAX;
21 // "outer edge" = a feature's latitude furthest from the equator
22 let northOuterEdge = LAT_MIN;
23 let southOuterEdge = LAT_MAX;
24
25 let westEdge = LNG_MAX;
26 let eastEdge = LNG_MIN;
27
28 geojsonFeatures.forEach(feature => {
29 const bounds = extent(feature);
30 const featureSouthEdge = bounds[1];
31 const featureNorthEdge = bounds[3];
32 const featureWestEdge = bounds[0];
33 const featureEastEdge = bounds[2];
34 if (featureSouthEdge > northInnerEdge) northInnerEdge = featureSouthEdge;
35 if (featureNorthEdge < southInnerEdge) southInnerEdge = featureNorthEdge;
36 if (featureNorthEdge > northOuterEdge) northOuterEdge = featureNorthEdge;
37 if (featureSouthEdge < southOuterEdge) southOuterEdge = featureSouthEdge;
38 if (featureWestEdge < westEdge) westEdge = featureWestEdge;
39 if (featureEastEdge > eastEdge) eastEdge = featureEastEdge;
40 });
41
42
43 // These changes are not mutually exclusive: we might hit the inner
44 // edge but also have hit the outer edge and therefore need
45 // another readjustment
46 const constrainedDelta = delta;
47 if (northInnerEdge + constrainedDelta.lat > LAT_RENDERED_MAX) {
48 constrainedDelta.lat = LAT_RENDERED_MAX - northInnerEdge;
49 }
50 if (northOuterEdge + constrainedDelta.lat > LAT_MAX) {
51 constrainedDelta.lat = LAT_MAX - northOuterEdge;
52 }
53 if (southInnerEdge + constrainedDelta.lat < LAT_RENDERED_MIN) {
54 constrainedDelta.lat = LAT_RENDERED_MIN - southInnerEdge;
55 }
56 if (southOuterEdge + constrainedDelta.lat < LAT_MIN) {
57 constrainedDelta.lat = LAT_MIN - southOuterEdge;
58 }
59 if (westEdge + constrainedDelta.lng <= LNG_MIN) {
60 constrainedDelta.lng += Math.ceil(Math.abs(constrainedDelta.lng) / 360) * 360;
61 }
62 if (eastEdge + constrainedDelta.lng >= LNG_MAX) {
63 constrainedDelta.lng -= Math.ceil(Math.abs(constrainedDelta.lng) / 360) * 360;
64 }
65
66 return constrainedDelta;
67};