@mapgis/geojson-vt 3.2.2 → 16.6.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mapgis/geojson-vt",
3
- "version": "3.2.2",
3
+ "version":"16.6.0",
4
4
  "description": "Slice GeoJSON data into vector tiles efficiently",
5
5
  "homepage": "https://github.com/parndeedlit/geojson-vt",
6
6
  "keywords": [
@@ -46,5 +46,8 @@
46
46
  "geojson-vt.js",
47
47
  "geojson-vt-dev.js",
48
48
  "src"
49
- ]
49
+ ],
50
+ "dependencies": {
51
+ "proj4": "^2.9.0"
52
+ }
50
53
  }
@@ -0,0 +1,97 @@
1
+ import proj4 from 'proj4';
2
+ /**
3
+ * @description: 投影坐标系对象
4
+ */
5
+ export default class Projection {
6
+ /**
7
+ * @description 实现投影对象
8
+ * @param {String} code
9
+ * @param {String} def 参考系对象
10
+ * @param {Array<Number>} bounds 投影系范围
11
+ * @param {Number} width 投影系宽度
12
+ * @param {Number} height 投影系高度
13
+ * @return {*}
14
+ */
15
+ constructor(code, def, bounds, width, height) {
16
+ this.bounds = bounds;
17
+ this.width = width;
18
+ this.height = height;
19
+ if (!def) throw new Error('自定义参考系必须指定参数系信息def');
20
+ // 验证proj4库是否存在
21
+ if (!proj4) throw new Error('proj4对象不存在,自定义投影必须引入proj4对象');
22
+ const isP4 = this._isProj4Obj(code);
23
+ this._proj = isP4 ? code : this._projFromCodeDef(code, def);
24
+ }
25
+
26
+ /**
27
+ * @description: 投影方法
28
+ * @param {Array|Object} lnglat
29
+ * @return {*}
30
+ */
31
+ project(lnglat) {
32
+ let lng, lat;
33
+ if (Array.isArray(lnglat)) {
34
+ lng = lnglat[0];
35
+ lat = lnglat[1];
36
+ } else {
37
+ lng = lnglat.lng;
38
+ lat = lnglat.lat;
39
+ }
40
+ const coords = this._proj.forward([lng, lat]);
41
+ const bounds = this.bounds;
42
+ const x = (coords[0] - bounds[0]) / this.width;
43
+ const y = (bounds[3] - coords[1]) / this.height;
44
+ return [x, y];
45
+ }
46
+
47
+
48
+ /**
49
+ * @description: 反投影方法
50
+ * @param {Array|Object} point
51
+ * @return {*}
52
+ */
53
+ unproject(point) {
54
+ let x, y;
55
+ if (Array.isArray(point)) {
56
+ x = point[0];
57
+ y = point[1];
58
+ } else {
59
+ x = point.x;
60
+ y = point.y;
61
+ }
62
+ return this._proj.inverse([x, y]);
63
+ }
64
+
65
+
66
+ /**
67
+ * @description: 定义proj投影
68
+ * @param {*} code
69
+ * @param {*} def
70
+ * @return {*}
71
+ */
72
+ _projFromCodeDef(code, def) {
73
+ if (def) {
74
+ proj4.defs(code, def);
75
+ } else if (proj4.defs[code] === undefined) {
76
+ const urn = code.split(':');
77
+ if (urn.length > 3) {
78
+ code = `${urn[urn.length - 3] }:${ urn[urn.length - 1]}`;
79
+ }
80
+ if (proj4.defs[code] === undefined) {
81
+ throw new Error(`No projection definition for code ${ code}`);
82
+ }
83
+ }
84
+ return proj4(code);
85
+ }
86
+
87
+
88
+ /**
89
+ * @description: 判断是否是proj4
90
+ * @param {*} a
91
+ * @return {*}
92
+ */
93
+ _isProj4Obj(a) {
94
+ return (typeof a.inverse !== 'undefined' &&
95
+ typeof a.forward !== 'undefined');
96
+ }
97
+ }
package/src/convert.js CHANGED
@@ -1,4 +1,4 @@
1
-
1
+ import Projection from './Projection.js';
2
2
  import simplify from './simplify.js';
3
3
  import createFeature from './feature.js';
4
4
 
@@ -10,12 +10,10 @@ export default function convert(data, options) {
10
10
  for (let i = 0; i < data.features.length; i++) {
11
11
  convertFeature(features, data.features[i], options, i);
12
12
  }
13
-
14
13
  } else if (data.type === 'Feature') {
15
14
  convertFeature(features, data, options);
16
-
17
15
  } else {
18
- // single geometry or a geometry collection
16
+ // single geometry or a geometry collection
19
17
  convertFeature(features, {geometry: data}, options);
20
18
  }
21
19
 
@@ -28,15 +26,45 @@ export default function convert(data, options) {
28
26
  * @param {*} geojson 要处理的geojson数据
29
27
  * @param {*} options 参数
30
28
  * @param {*} options.crs 投影参数, 要区分4326以及3857
29
+ * @param {*} options.projectionParams 详细投影参数
31
30
  * @param {*} index 处理的geojson数据的序号
32
31
  */
33
32
  function convertFeature(features, geojson, options, index) {
34
33
  if (!geojson.geometry) return;
35
34
 
36
35
  const crs = options.crs;
36
+
37
+ const projectionParams = options.projectionParams;
38
+ let projection;
39
+ if (projectionParams && projectionParams.def) {
40
+ // projectionParams ={
41
+ // "code": "EPSG:4547",
42
+ // "def": "+proj=tmerc +lat_0=0 +lon_0=114 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs +type=crs",
43
+ // "originX": 401635,
44
+ // "originY": 3542709,
45
+ // "width": 216746.66666666663,
46
+ // "height": 216746.6666666665,
47
+ // "bounds": [
48
+ // 401635,
49
+ // 3325962.3333333335,
50
+ // 618381.6666666666,
51
+ // 3542709
52
+ // ]
53
+ // }
54
+ const code = projectionParams.code;
55
+ const def = projectionParams.def;
56
+ const bounds = projectionParams.bounds;
57
+ const width = projectionParams.width;
58
+ const height = projectionParams.height;
59
+ projection = new Projection(code, def, bounds, width, height);
60
+ }
61
+
37
62
  const coords = geojson.geometry.coordinates;
38
63
  const type = geojson.geometry.type;
39
- const tolerance = Math.pow(options.tolerance / ((1 << options.maxZoom) * options.extent), 2);
64
+ const tolerance = Math.pow(
65
+ options.tolerance / ((1 << options.maxZoom) * options.extent),
66
+ 2
67
+ );
40
68
  let geometry = [];
41
69
  let id = geojson.id;
42
70
  if (options.promoteId) {
@@ -45,45 +73,47 @@ function convertFeature(features, geojson, options, index) {
45
73
  id = index || 0;
46
74
  }
47
75
  if (type === 'Point') {
48
- convertPoint(coords, geometry, crs);
49
-
76
+ convertPoint(coords, geometry, crs, projection);
50
77
  } else if (type === 'MultiPoint') {
51
78
  for (const p of coords) {
52
- convertPoint(p, geometry, crs);
79
+ convertPoint(p, geometry, crs, projection);
53
80
  }
54
-
55
81
  } else if (type === 'LineString') {
56
- convertLine(coords, geometry, tolerance, false, crs);
57
-
82
+ convertLine(coords, geometry, tolerance, false, crs, projection);
58
83
  } else if (type === 'MultiLineString') {
59
84
  if (options.lineMetrics) {
60
85
  // explode into linestrings to be able to track metrics
61
86
  for (const line of coords) {
62
87
  geometry = [];
63
- convertLine(line, geometry, tolerance, false, crs);
64
- features.push(createFeature(id, 'LineString', geometry, geojson.properties));
88
+ convertLine(line, geometry, tolerance, false, crs, projection);
89
+ features.push(
90
+ createFeature(id, 'LineString', geometry, geojson.properties)
91
+ );
65
92
  }
66
93
  return;
67
94
  } else {
68
- convertLines(coords, geometry, tolerance, false, crs);
95
+ convertLines(coords, geometry, tolerance, false, crs, projection);
69
96
  }
70
-
71
97
  } else if (type === 'Polygon') {
72
- convertLines(coords, geometry, tolerance, true, crs);
73
-
98
+ convertLines(coords, geometry, tolerance, true, crs, projection);
74
99
  } else if (type === 'MultiPolygon') {
75
100
  for (const polygon of coords) {
76
101
  const newPolygon = [];
77
- convertLines(polygon, newPolygon, tolerance, true, crs);
102
+ convertLines(polygon, newPolygon, tolerance, true, crs, projection);
78
103
  geometry.push(newPolygon);
79
104
  }
80
105
  } else if (type === 'GeometryCollection') {
81
106
  for (const singleGeometry of geojson.geometry.geometries) {
82
- convertFeature(features, {
83
- id,
84
- geometry: singleGeometry,
85
- properties: geojson.properties
86
- }, options, index);
107
+ convertFeature(
108
+ features,
109
+ {
110
+ id,
111
+ geometry: singleGeometry,
112
+ properties: geojson.properties,
113
+ },
114
+ options,
115
+ index
116
+ );
87
117
  }
88
118
  return;
89
119
  } else {
@@ -93,17 +123,22 @@ function convertFeature(features, geojson, options, index) {
93
123
  features.push(createFeature(id, type, geometry, geojson.properties));
94
124
  }
95
125
 
96
- function convertPoint(coords, out, crs) {
97
- out.push(projectX(coords[0], crs), projectY(coords[1], crs), 0);
126
+ function convertPoint(coords, out, crs, projection) {
127
+ console.log('convertPoint: ', convertPoint);
128
+ const coord = project(coords, crs, projection)
129
+ out.push(
130
+ coord[0],
131
+ coord[1],
132
+ 0
133
+ );
98
134
  }
99
135
 
100
- function convertLine(ring, out, tolerance, isPolygon, crs) {
136
+ function convertLine(ring, out, tolerance, isPolygon, crs, projection) {
101
137
  let x0, y0;
102
138
  let size = 0;
103
139
 
104
140
  for (let j = 0; j < ring.length; j++) {
105
- const x = projectX(ring[j][0], crs);
106
- const y = projectY(ring[j][1], crs);
141
+ const [x,y] = project(ring[j], crs, projection)
107
142
 
108
143
  out.push(x, y, 0);
109
144
 
@@ -128,43 +163,42 @@ function convertLine(ring, out, tolerance, isPolygon, crs) {
128
163
  out.end = out.size;
129
164
  }
130
165
 
131
- function convertLines(rings, out, tolerance, isPolygon, crs) {
166
+ function convertLines(rings, out, tolerance, isPolygon, crs, projection) {
132
167
  for (let i = 0; i < rings.length; i++) {
133
168
  const geom = [];
134
- convertLine(rings[i], geom, tolerance, isPolygon, crs);
169
+ convertLine(rings[i], geom, tolerance, isPolygon, crs, projection);
135
170
  out.push(geom);
136
171
  }
137
172
  }
138
173
 
139
174
  /**
140
- * 针对X方向投影
141
- * @param {*} x
142
- * @param {*} crs
143
- * @returns 返回投影后的坐标,注意这里的坐标不是平面坐标值,而是矩阵值,即 [0 ~ 1]之间
144
- */
145
- function projectX(x, crs) {
146
- let transformX;
147
- if (!crs || crs === 'EPSG:3857'){
148
- transformX = x / 360 + 0.5;
149
- } else {
150
- transformX = x / 360 + 0.5;
151
- }
152
- return transformX;
153
- }
154
-
155
- /**
156
- * 针对y方向投影
157
- * @param {*} y
175
+ * 投影转换,将经纬度转为矩阵范围
176
+ * @param {Array} lnglatArr
158
177
  * @param {*} crs
178
+ * @param {*} projection
159
179
  * @returns 返回投影后的坐标,注意这里的坐标不是平面坐标值,而是矩阵值,即 [0 ~ 1]之间
160
180
  */
161
- function projectY(y, crs) {
162
- let transformY;
163
- if (!crs || crs === 'EPSG:3857'){
164
- const sin = Math.sin(y * Math.PI / 180);
165
- transformY = 0.5 - 0.25 * Math.log((1 + sin) / (1 - sin)) / Math.PI;
181
+ function project(lnglatArr, crs, projection) {
182
+ const [lng, lat] = lnglatArr;
183
+ let coords = [];
184
+ if (projection) {
185
+ coords = projection.project([lng, lat]);
186
+ coords[1] = coords[1] < 0 ? 0 : coords[1] > 1 ? 1 : coords[1];
187
+ } else if (crs === 'EPSG:3857') {
188
+ const [x, y] = lnglatArr
189
+ const transformX = x / 360 + 0.5;
190
+ const sin = Math.sin((y * Math.PI) / 180);
191
+ let transformY = 0.5 - (0.25 * Math.log((1 + sin) / (1 - sin))) / Math.PI;
192
+ transformY = transformY < 0 ? 0 : transformY > 1 ? 1 : transformY;
193
+ coords = [transformX, transformY];
194
+ } else if (crs === 'EPSG:4326') {
195
+ const [x, y] = lnglatArr
196
+ const transformX = x / 360 + 0.5;
197
+ let transformY = (90 - y) / 360;
198
+ transformY = transformY < 0 ? 0 : transformY > 1 ? 1 : transformY;
199
+ coords = [transformX, transformY]
166
200
  } else {
167
- transformY = (90 - y) / 360;
201
+ throw new Error('未预定义投影转换方法');
168
202
  }
169
- return transformY < 0 ? 0 : transformY > 1 ? 1 : transformY;
203
+ return coords
170
204
  }
package/geojson-vt-dev.js DELETED
@@ -1,949 +0,0 @@
1
- (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3
- typeof define === 'function' && define.amd ? define(factory) :
4
- (global = global || self, global.geojsonvt = factory());
5
- }(this, (function () { 'use strict';
6
-
7
- // calculate simplification data using optimized Douglas-Peucker algorithm
8
-
9
- function simplify(coords, first, last, sqTolerance) {
10
- var maxSqDist = sqTolerance;
11
- var mid = (last - first) >> 1;
12
- var minPosToMid = last - first;
13
- var index;
14
-
15
- var ax = coords[first];
16
- var ay = coords[first + 1];
17
- var bx = coords[last];
18
- var by = coords[last + 1];
19
-
20
- for (var i = first + 3; i < last; i += 3) {
21
- var d = getSqSegDist(coords[i], coords[i + 1], ax, ay, bx, by);
22
-
23
- if (d > maxSqDist) {
24
- index = i;
25
- maxSqDist = d;
26
-
27
- } else if (d === maxSqDist) {
28
- // a workaround to ensure we choose a pivot close to the middle of the list,
29
- // reducing recursion depth, for certain degenerate inputs
30
- // https://github.com/mapbox/geojson-vt/issues/104
31
- var posToMid = Math.abs(i - mid);
32
- if (posToMid < minPosToMid) {
33
- index = i;
34
- minPosToMid = posToMid;
35
- }
36
- }
37
- }
38
-
39
- if (maxSqDist > sqTolerance) {
40
- if (index - first > 3) { simplify(coords, first, index, sqTolerance); }
41
- coords[index + 2] = maxSqDist;
42
- if (last - index > 3) { simplify(coords, index, last, sqTolerance); }
43
- }
44
- }
45
-
46
- // square distance from a point to a segment
47
- function getSqSegDist(px, py, x, y, bx, by) {
48
-
49
- var dx = bx - x;
50
- var dy = by - y;
51
-
52
- if (dx !== 0 || dy !== 0) {
53
-
54
- var t = ((px - x) * dx + (py - y) * dy) / (dx * dx + dy * dy);
55
-
56
- if (t > 1) {
57
- x = bx;
58
- y = by;
59
-
60
- } else if (t > 0) {
61
- x += dx * t;
62
- y += dy * t;
63
- }
64
- }
65
-
66
- dx = px - x;
67
- dy = py - y;
68
-
69
- return dx * dx + dy * dy;
70
- }
71
-
72
- function createFeature(id, type, geom, tags) {
73
- var feature = {
74
- id: id == null ? null : id,
75
- type: type,
76
- geometry: geom,
77
- tags: tags,
78
- minX: Infinity,
79
- minY: Infinity,
80
- maxX: -Infinity,
81
- maxY: -Infinity
82
- };
83
-
84
- if (type === 'Point' || type === 'MultiPoint' || type === 'LineString') {
85
- calcLineBBox(feature, geom);
86
-
87
- } else if (type === 'Polygon') {
88
- // the outer ring (ie [0]) contains all inner rings
89
- calcLineBBox(feature, geom[0]);
90
-
91
- } else if (type === 'MultiLineString') {
92
- for (var i = 0, list = geom; i < list.length; i += 1) {
93
- var line = list[i];
94
-
95
- calcLineBBox(feature, line);
96
- }
97
-
98
- } else if (type === 'MultiPolygon') {
99
- for (var i$1 = 0, list$1 = geom; i$1 < list$1.length; i$1 += 1) {
100
- // the outer ring (ie [0]) contains all inner rings
101
- var polygon = list$1[i$1];
102
-
103
- calcLineBBox(feature, polygon[0]);
104
- }
105
- }
106
-
107
- return feature;
108
- }
109
-
110
- function calcLineBBox(feature, geom) {
111
- for (var i = 0; i < geom.length; i += 3) {
112
- feature.minX = Math.min(feature.minX, geom[i]);
113
- feature.minY = Math.min(feature.minY, geom[i + 1]);
114
- feature.maxX = Math.max(feature.maxX, geom[i]);
115
- feature.maxY = Math.max(feature.maxY, geom[i + 1]);
116
- }
117
- }
118
-
119
- // converts GeoJSON feature into an intermediate projected JSON vector format with simplification data
120
-
121
- function convert(data, options) {
122
- var features = [];
123
- if (data.type === 'FeatureCollection') {
124
- for (var i = 0; i < data.features.length; i++) {
125
- convertFeature(features, data.features[i], options, i);
126
- }
127
-
128
- } else if (data.type === 'Feature') {
129
- convertFeature(features, data, options);
130
-
131
- } else {
132
- // single geometry or a geometry collection
133
- convertFeature(features, {geometry: data}, options);
134
- }
135
-
136
- return features;
137
- }
138
-
139
- /**
140
- * 转换要素,主要是坐标投影变换
141
- * @param {*} features 传回外部的数据
142
- * @param {*} geojson 要处理的geojson数据
143
- * @param {*} options 参数
144
- * @param {*} options.crs 投影参数, 要区分4326以及3857
145
- * @param {*} index 处理的geojson数据的序号
146
- */
147
- function convertFeature(features, geojson, options, index) {
148
- if (!geojson.geometry) { return; }
149
-
150
- var crs = options.crs;
151
- var coords = geojson.geometry.coordinates;
152
- var type = geojson.geometry.type;
153
- var tolerance = Math.pow(options.tolerance / ((1 << options.maxZoom) * options.extent), 2);
154
- var geometry = [];
155
- var id = geojson.id;
156
- if (options.promoteId) {
157
- id = geojson.properties[options.promoteId];
158
- } else if (options.generateId) {
159
- id = index || 0;
160
- }
161
- if (type === 'Point') {
162
- convertPoint(coords, geometry, crs);
163
-
164
- } else if (type === 'MultiPoint') {
165
- for (var i = 0, list = coords; i < list.length; i += 1) {
166
- var p = list[i];
167
-
168
- convertPoint(p, geometry, crs);
169
- }
170
-
171
- } else if (type === 'LineString') {
172
- convertLine(coords, geometry, tolerance, false, crs);
173
-
174
- } else if (type === 'MultiLineString') {
175
- if (options.lineMetrics) {
176
- // explode into linestrings to be able to track metrics
177
- for (var i$1 = 0, list$1 = coords; i$1 < list$1.length; i$1 += 1) {
178
- var line = list$1[i$1];
179
-
180
- geometry = [];
181
- convertLine(line, geometry, tolerance, false, crs);
182
- features.push(createFeature(id, 'LineString', geometry, geojson.properties));
183
- }
184
- return;
185
- } else {
186
- convertLines(coords, geometry, tolerance, false, crs);
187
- }
188
-
189
- } else if (type === 'Polygon') {
190
- convertLines(coords, geometry, tolerance, true, crs);
191
-
192
- } else if (type === 'MultiPolygon') {
193
- for (var i$2 = 0, list$2 = coords; i$2 < list$2.length; i$2 += 1) {
194
- var polygon = list$2[i$2];
195
-
196
- var newPolygon = [];
197
- convertLines(polygon, newPolygon, tolerance, true, crs);
198
- geometry.push(newPolygon);
199
- }
200
- } else if (type === 'GeometryCollection') {
201
- for (var i$3 = 0, list$3 = geojson.geometry.geometries; i$3 < list$3.length; i$3 += 1) {
202
- var singleGeometry = list$3[i$3];
203
-
204
- convertFeature(features, {
205
- id: id,
206
- geometry: singleGeometry,
207
- properties: geojson.properties
208
- }, options, index);
209
- }
210
- return;
211
- } else {
212
- throw new Error('Input data is not a valid GeoJSON object.');
213
- }
214
-
215
- features.push(createFeature(id, type, geometry, geojson.properties));
216
- }
217
-
218
- function convertPoint(coords, out, crs) {
219
- out.push(projectX(coords[0], crs), projectY(coords[1], crs), 0);
220
- }
221
-
222
- function convertLine(ring, out, tolerance, isPolygon, crs) {
223
- var x0, y0;
224
- var size = 0;
225
-
226
- for (var j = 0; j < ring.length; j++) {
227
- var x = projectX(ring[j][0], crs);
228
- var y = projectY(ring[j][1], crs);
229
-
230
- out.push(x, y, 0);
231
-
232
- if (j > 0) {
233
- if (isPolygon) {
234
- size += (x0 * y - x * y0) / 2; // area
235
- } else {
236
- size += Math.sqrt(Math.pow(x - x0, 2) + Math.pow(y - y0, 2)); // length
237
- }
238
- }
239
- x0 = x;
240
- y0 = y;
241
- }
242
-
243
- var last = out.length - 3;
244
- out[2] = 1;
245
- simplify(out, 0, last, tolerance);
246
- out[last + 2] = 1;
247
-
248
- out.size = Math.abs(size);
249
- out.start = 0;
250
- out.end = out.size;
251
- }
252
-
253
- function convertLines(rings, out, tolerance, isPolygon, crs) {
254
- for (var i = 0; i < rings.length; i++) {
255
- var geom = [];
256
- convertLine(rings[i], geom, tolerance, isPolygon, crs);
257
- out.push(geom);
258
- }
259
- }
260
-
261
- /**
262
- * 针对X方向投影
263
- * @param {*} x
264
- * @param {*} crs
265
- * @returns 返回投影后的坐标,注意这里的坐标不是平面坐标值,而是矩阵值,即 [0 ~ 1]之间
266
- */
267
- function projectX(x, crs) {
268
- var transformX;
269
- if (!crs || crs === 'EPSG:3857'){
270
- transformX = x / 360 + 0.5;
271
- } else {
272
- transformX = x / 360 + 0.5;
273
- }
274
- return transformX;
275
- }
276
-
277
- /**
278
- * 针对y方向投影
279
- * @param {*} y
280
- * @param {*} crs
281
- * @returns 返回投影后的坐标,注意这里的坐标不是平面坐标值,而是矩阵值,即 [0 ~ 1]之间
282
- */
283
- function projectY(y, crs) {
284
- var transformY;
285
- if (!crs || crs === 'EPSG:3857'){
286
- var sin = Math.sin(y * Math.PI / 180);
287
- transformY = 0.5 - 0.25 * Math.log((1 + sin) / (1 - sin)) / Math.PI;
288
- } else {
289
- transformY = (90 - y) / 360;
290
- }
291
- return transformY < 0 ? 0 : transformY > 1 ? 1 : transformY;
292
- }
293
-
294
- /* clip features between two vertical or horizontal axis-parallel lines:
295
- * | |
296
- * ___|___ | /
297
- * / | \____|____/
298
- * | |
299
- *
300
- * k1 and k2 are the line coordinates
301
- * axis: 0 for x, 1 for y
302
- * minAll and maxAll: minimum and maximum coordinate value for all features
303
- */
304
- function clip(features, scale, k1, k2, axis, minAll, maxAll, options) {
305
- k1 /= scale;
306
- k2 /= scale;
307
-
308
- if (minAll >= k1 && maxAll < k2) { return features; } // trivial accept
309
- else if (maxAll < k1 || minAll >= k2) { return null; } // trivial reject
310
-
311
- var clipped = [];
312
-
313
- for (var i$2 = 0, list$2 = features; i$2 < list$2.length; i$2 += 1) {
314
- var feature = list$2[i$2];
315
-
316
- var geometry = feature.geometry;
317
- var type = feature.type;
318
-
319
- var min = axis === 0 ? feature.minX : feature.minY;
320
- var max = axis === 0 ? feature.maxX : feature.maxY;
321
-
322
- if (min >= k1 && max < k2) { // trivial accept
323
- clipped.push(feature);
324
- continue;
325
- } else if (max < k1 || min >= k2) { // trivial reject
326
- continue;
327
- }
328
-
329
- var newGeometry = [];
330
-
331
- if (type === 'Point' || type === 'MultiPoint') {
332
- clipPoints(geometry, newGeometry, k1, k2, axis);
333
-
334
- } else if (type === 'LineString') {
335
- clipLine(geometry, newGeometry, k1, k2, axis, false, options.lineMetrics);
336
-
337
- } else if (type === 'MultiLineString') {
338
- clipLines(geometry, newGeometry, k1, k2, axis, false);
339
-
340
- } else if (type === 'Polygon') {
341
- clipLines(geometry, newGeometry, k1, k2, axis, true);
342
-
343
- } else if (type === 'MultiPolygon') {
344
- for (var i = 0, list = geometry; i < list.length; i += 1) {
345
- var polygon = list[i];
346
-
347
- var newPolygon = [];
348
- clipLines(polygon, newPolygon, k1, k2, axis, true);
349
- if (newPolygon.length) {
350
- newGeometry.push(newPolygon);
351
- }
352
- }
353
- }
354
-
355
- if (newGeometry.length) {
356
- if (options.lineMetrics && type === 'LineString') {
357
- for (var i$1 = 0, list$1 = newGeometry; i$1 < list$1.length; i$1 += 1) {
358
- var line = list$1[i$1];
359
-
360
- clipped.push(createFeature(feature.id, type, line, feature.tags));
361
- }
362
- continue;
363
- }
364
-
365
- if (type === 'LineString' || type === 'MultiLineString') {
366
- if (newGeometry.length === 1) {
367
- type = 'LineString';
368
- newGeometry = newGeometry[0];
369
- } else {
370
- type = 'MultiLineString';
371
- }
372
- }
373
- if (type === 'Point' || type === 'MultiPoint') {
374
- type = newGeometry.length === 3 ? 'Point' : 'MultiPoint';
375
- }
376
-
377
- clipped.push(createFeature(feature.id, type, newGeometry, feature.tags));
378
- }
379
- }
380
-
381
- return clipped.length ? clipped : null;
382
- }
383
-
384
- function clipPoints(geom, newGeom, k1, k2, axis) {
385
- for (var i = 0; i < geom.length; i += 3) {
386
- var a = geom[i + axis];
387
-
388
- if (a >= k1 && a <= k2) {
389
- addPoint(newGeom, geom[i], geom[i + 1], geom[i + 2]);
390
- }
391
- }
392
- }
393
-
394
- function clipLine(geom, newGeom, k1, k2, axis, isPolygon, trackMetrics) {
395
-
396
- var slice = newSlice(geom);
397
- var intersect = axis === 0 ? intersectX : intersectY;
398
- var len = geom.start;
399
- var segLen, t;
400
-
401
- for (var i = 0; i < geom.length - 3; i += 3) {
402
- var ax$1 = geom[i];
403
- var ay$1 = geom[i + 1];
404
- var az$1 = geom[i + 2];
405
- var bx = geom[i + 3];
406
- var by = geom[i + 4];
407
- var a$1 = axis === 0 ? ax$1 : ay$1;
408
- var b = axis === 0 ? bx : by;
409
- var exited = false;
410
-
411
- if (trackMetrics) { segLen = Math.sqrt(Math.pow(ax$1 - bx, 2) + Math.pow(ay$1 - by, 2)); }
412
-
413
- if (a$1 < k1) {
414
- // ---|--> | (line enters the clip region from the left)
415
- if (b > k1) {
416
- t = intersect(slice, ax$1, ay$1, bx, by, k1);
417
- if (trackMetrics) { slice.start = len + segLen * t; }
418
- }
419
- } else if (a$1 > k2) {
420
- // | <--|--- (line enters the clip region from the right)
421
- if (b < k2) {
422
- t = intersect(slice, ax$1, ay$1, bx, by, k2);
423
- if (trackMetrics) { slice.start = len + segLen * t; }
424
- }
425
- } else {
426
- addPoint(slice, ax$1, ay$1, az$1);
427
- }
428
- if (b < k1 && a$1 >= k1) {
429
- // <--|--- | or <--|-----|--- (line exits the clip region on the left)
430
- t = intersect(slice, ax$1, ay$1, bx, by, k1);
431
- exited = true;
432
- }
433
- if (b > k2 && a$1 <= k2) {
434
- // | ---|--> or ---|-----|--> (line exits the clip region on the right)
435
- t = intersect(slice, ax$1, ay$1, bx, by, k2);
436
- exited = true;
437
- }
438
-
439
- if (!isPolygon && exited) {
440
- if (trackMetrics) { slice.end = len + segLen * t; }
441
- newGeom.push(slice);
442
- slice = newSlice(geom);
443
- }
444
-
445
- if (trackMetrics) { len += segLen; }
446
- }
447
-
448
- // add the last point
449
- var last = geom.length - 3;
450
- var ax = geom[last];
451
- var ay = geom[last + 1];
452
- var az = geom[last + 2];
453
- var a = axis === 0 ? ax : ay;
454
- if (a >= k1 && a <= k2) { addPoint(slice, ax, ay, az); }
455
-
456
- // close the polygon if its endpoints are not the same after clipping
457
- last = slice.length - 3;
458
- if (isPolygon && last >= 3 && (slice[last] !== slice[0] || slice[last + 1] !== slice[1])) {
459
- addPoint(slice, slice[0], slice[1], slice[2]);
460
- }
461
-
462
- // add the final slice
463
- if (slice.length) {
464
- newGeom.push(slice);
465
- }
466
- }
467
-
468
- function newSlice(line) {
469
- var slice = [];
470
- slice.size = line.size;
471
- slice.start = line.start;
472
- slice.end = line.end;
473
- return slice;
474
- }
475
-
476
- function clipLines(geom, newGeom, k1, k2, axis, isPolygon) {
477
- for (var i = 0, list = geom; i < list.length; i += 1) {
478
- var line = list[i];
479
-
480
- clipLine(line, newGeom, k1, k2, axis, isPolygon, false);
481
- }
482
- }
483
-
484
- function addPoint(out, x, y, z) {
485
- out.push(x, y, z);
486
- }
487
-
488
- function intersectX(out, ax, ay, bx, by, x) {
489
- var t = (x - ax) / (bx - ax);
490
- addPoint(out, x, ay + (by - ay) * t, 1);
491
- return t;
492
- }
493
-
494
- function intersectY(out, ax, ay, bx, by, y) {
495
- var t = (y - ay) / (by - ay);
496
- addPoint(out, ax + (bx - ax) * t, y, 1);
497
- return t;
498
- }
499
-
500
- function wrap(features, options) {
501
- var buffer = options.buffer / options.extent;
502
- var merged = features;
503
- var left = clip(features, 1, -1 - buffer, buffer, 0, -1, 2, options); // left world copy
504
- var right = clip(features, 1, 1 - buffer, 2 + buffer, 0, -1, 2, options); // right world copy
505
-
506
- if (left || right) {
507
- merged = clip(features, 1, -buffer, 1 + buffer, 0, -1, 2, options) || []; // center world copy
508
-
509
- if (left) { merged = shiftFeatureCoords(left, 1).concat(merged); } // merge left into center
510
- if (right) { merged = merged.concat(shiftFeatureCoords(right, -1)); } // merge right into center
511
- }
512
-
513
- return merged;
514
- }
515
-
516
- function shiftFeatureCoords(features, offset) {
517
- var newFeatures = [];
518
-
519
- for (var i = 0; i < features.length; i++) {
520
- var feature = features[i];
521
- var type = feature.type;
522
-
523
- var newGeometry = (void 0);
524
-
525
- if (type === 'Point' || type === 'MultiPoint' || type === 'LineString') {
526
- newGeometry = shiftCoords(feature.geometry, offset);
527
-
528
- } else if (type === 'MultiLineString' || type === 'Polygon') {
529
- newGeometry = [];
530
- for (var i$1 = 0, list = feature.geometry; i$1 < list.length; i$1 += 1) {
531
- var line = list[i$1];
532
-
533
- newGeometry.push(shiftCoords(line, offset));
534
- }
535
- } else if (type === 'MultiPolygon') {
536
- newGeometry = [];
537
- for (var i$3 = 0, list$2 = feature.geometry; i$3 < list$2.length; i$3 += 1) {
538
- var polygon = list$2[i$3];
539
-
540
- var newPolygon = [];
541
- for (var i$2 = 0, list$1 = polygon; i$2 < list$1.length; i$2 += 1) {
542
- var line$1 = list$1[i$2];
543
-
544
- newPolygon.push(shiftCoords(line$1, offset));
545
- }
546
- newGeometry.push(newPolygon);
547
- }
548
- }
549
-
550
- newFeatures.push(createFeature(feature.id, type, newGeometry, feature.tags));
551
- }
552
-
553
- return newFeatures;
554
- }
555
-
556
- function shiftCoords(points, offset) {
557
- var newPoints = [];
558
- newPoints.size = points.size;
559
-
560
- if (points.start !== undefined) {
561
- newPoints.start = points.start;
562
- newPoints.end = points.end;
563
- }
564
-
565
- for (var i = 0; i < points.length; i += 3) {
566
- newPoints.push(points[i] + offset, points[i + 1], points[i + 2]);
567
- }
568
- return newPoints;
569
- }
570
-
571
- // Transforms the coordinates of each feature in the given tile from
572
- // mercator-projected space into (extent x extent) tile space.
573
- function transformTile(tile, extent) {
574
- if (tile.transformed) { return tile; }
575
-
576
- var z2 = 1 << tile.z;
577
- var tx = tile.x;
578
- var ty = tile.y;
579
-
580
- for (var i = 0, list = tile.features; i < list.length; i += 1) {
581
- var feature = list[i];
582
-
583
- var geom = feature.geometry;
584
- var type = feature.type;
585
-
586
- feature.geometry = [];
587
-
588
- if (type === 1) {
589
- for (var j = 0; j < geom.length; j += 2) {
590
- feature.geometry.push(transformPoint(geom[j], geom[j + 1], extent, z2, tx, ty));
591
- }
592
- } else {
593
- for (var j$1 = 0; j$1 < geom.length; j$1++) {
594
- var ring = [];
595
- for (var k = 0; k < geom[j$1].length; k += 2) {
596
- ring.push(transformPoint(geom[j$1][k], geom[j$1][k + 1], extent, z2, tx, ty));
597
- }
598
- feature.geometry.push(ring);
599
- }
600
- }
601
- }
602
-
603
- tile.transformed = true;
604
-
605
- return tile;
606
- }
607
-
608
- function transformPoint(x, y, extent, z2, tx, ty) {
609
- return [
610
- Math.round(extent * (x * z2 - tx)),
611
- Math.round(extent * (y * z2 - ty))];
612
- }
613
-
614
- function createTile(features, z, tx, ty, options) {
615
- var tolerance = z === options.maxZoom ? 0 : options.tolerance / ((1 << z) * options.extent);
616
- var tile = {
617
- features: [],
618
- numPoints: 0,
619
- numSimplified: 0,
620
- numFeatures: features.length,
621
- source: null,
622
- x: tx,
623
- y: ty,
624
- z: z,
625
- transformed: false,
626
- minX: 2,
627
- minY: 1,
628
- maxX: -1,
629
- maxY: 0
630
- };
631
- for (var i = 0, list = features; i < list.length; i += 1) {
632
- var feature = list[i];
633
-
634
- addFeature(tile, feature, tolerance, options);
635
- }
636
- return tile;
637
- }
638
-
639
- function addFeature(tile, feature, tolerance, options) {
640
- var geom = feature.geometry;
641
- var type = feature.type;
642
- var simplified = [];
643
-
644
- tile.minX = Math.min(tile.minX, feature.minX);
645
- tile.minY = Math.min(tile.minY, feature.minY);
646
- tile.maxX = Math.max(tile.maxX, feature.maxX);
647
- tile.maxY = Math.max(tile.maxY, feature.maxY);
648
-
649
- if (type === 'Point' || type === 'MultiPoint') {
650
- for (var i = 0; i < geom.length; i += 3) {
651
- simplified.push(geom[i], geom[i + 1]);
652
- tile.numPoints++;
653
- tile.numSimplified++;
654
- }
655
-
656
- } else if (type === 'LineString') {
657
- addLine(simplified, geom, tile, tolerance, false, false);
658
-
659
- } else if (type === 'MultiLineString' || type === 'Polygon') {
660
- for (var i$1 = 0; i$1 < geom.length; i$1++) {
661
- addLine(simplified, geom[i$1], tile, tolerance, type === 'Polygon', i$1 === 0);
662
- }
663
-
664
- } else if (type === 'MultiPolygon') {
665
-
666
- for (var k = 0; k < geom.length; k++) {
667
- var polygon = geom[k];
668
- for (var i$2 = 0; i$2 < polygon.length; i$2++) {
669
- addLine(simplified, polygon[i$2], tile, tolerance, true, i$2 === 0);
670
- }
671
- }
672
- }
673
-
674
- if (simplified.length) {
675
- var tags = feature.tags || null;
676
-
677
- if (type === 'LineString' && options.lineMetrics) {
678
- tags = {};
679
- for (var key in feature.tags) { tags[key] = feature.tags[key]; }
680
- tags['mapbox_clip_start'] = geom.start / geom.size;
681
- tags['mapbox_clip_end'] = geom.end / geom.size;
682
- }
683
-
684
- var tileFeature = {
685
- geometry: simplified,
686
- type: type === 'Polygon' || type === 'MultiPolygon' ? 3 :
687
- (type === 'LineString' || type === 'MultiLineString' ? 2 : 1),
688
- tags: tags
689
- };
690
- if (feature.id !== null) {
691
- tileFeature.id = feature.id;
692
- }
693
- tile.features.push(tileFeature);
694
- }
695
- }
696
-
697
- function addLine(result, geom, tile, tolerance, isPolygon, isOuter) {
698
- var sqTolerance = tolerance * tolerance;
699
-
700
- if (tolerance > 0 && (geom.size < (isPolygon ? sqTolerance : tolerance))) {
701
- tile.numPoints += geom.length / 3;
702
- return;
703
- }
704
-
705
- var ring = [];
706
-
707
- for (var i = 0; i < geom.length; i += 3) {
708
- if (tolerance === 0 || geom[i + 2] > sqTolerance) {
709
- tile.numSimplified++;
710
- ring.push(geom[i], geom[i + 1]);
711
- }
712
- tile.numPoints++;
713
- }
714
-
715
- if (isPolygon) { rewind(ring, isOuter); }
716
-
717
- result.push(ring);
718
- }
719
-
720
- function rewind(ring, clockwise) {
721
- var area = 0;
722
- for (var i = 0, len = ring.length, j = len - 2; i < len; j = i, i += 2) {
723
- area += (ring[i] - ring[j]) * (ring[i + 1] + ring[j + 1]);
724
- }
725
- if (area > 0 === clockwise) {
726
- for (var i$1 = 0, len$1 = ring.length; i$1 < len$1 / 2; i$1 += 2) {
727
- var x = ring[i$1];
728
- var y = ring[i$1 + 1];
729
- ring[i$1] = ring[len$1 - 2 - i$1];
730
- ring[i$1 + 1] = ring[len$1 - 1 - i$1];
731
- ring[len$1 - 2 - i$1] = x;
732
- ring[len$1 - 1 - i$1] = y;
733
- }
734
- }
735
- }
736
-
737
- var defaultOptions = {
738
- crs: 'EPSG:3857', // 默认的投影坐标系 3857 4326走经纬度裁图
739
- maxZoom: 14, // max zoom to preserve detail on
740
- indexMaxZoom: 5, // max zoom in the tile index
741
- indexMaxPoints: 100000, // max number of points per tile in the tile index
742
- tolerance: 3, // simplification tolerance (higher means simpler)
743
- extent: 4096, // tile extent
744
- buffer: 64, // tile buffer on each side
745
- lineMetrics: false, // whether to calculate line metrics
746
- promoteId: null, // name of a feature property to be promoted to feature.id
747
- generateId: false, // whether to generate feature ids. Cannot be used with promoteId
748
- debug: 0 // logging level (0, 1 or 2)
749
- };
750
-
751
- var GeoJSONVT = function GeoJSONVT(data, options) {
752
- options = this.options = extend(Object.create(defaultOptions), options);
753
-
754
- var debug = options.debug;
755
-
756
- if (debug) { console.time('preprocess data'); }
757
-
758
- if (options.maxZoom < 0 || options.maxZoom > 24) { throw new Error('maxZoom should be in the 0-24 range'); }
759
- if (options.promoteId && options.generateId) { throw new Error('promoteId and generateId cannot be used together.'); }
760
-
761
- // projects and adds simplification info
762
- var features = convert(data, options);
763
-
764
- // tiles and tileCoords are part of the public API
765
- this.tiles = {};
766
- this.tileCoords = [];
767
-
768
- if (debug) {
769
- console.timeEnd('preprocess data');
770
- console.log('index: maxZoom: %d, maxPoints: %d', options.indexMaxZoom, options.indexMaxPoints);
771
- console.time('generate tiles');
772
- this.stats = {};
773
- this.total = 0;
774
- }
775
-
776
- // wraps features (ie extreme west and extreme east)
777
- features = wrap(features, options);
778
-
779
- // start slicing from the top tile down
780
- if (features.length) { this.splitTile(features, 0, 0, 0); }
781
-
782
- if (debug) {
783
- if (features.length) { console.log('features: %d, points: %d', this.tiles[0].numFeatures, this.tiles[0].numPoints); }
784
- console.timeEnd('generate tiles');
785
- console.log('tiles generated:', this.total, JSON.stringify(this.stats));
786
- }
787
- };
788
-
789
- // splits features from a parent tile to sub-tiles.
790
- // z, x, and y are the coordinates of the parent tile
791
- // cz, cx, and cy are the coordinates of the target tile
792
- //
793
- // If no target tile is specified, splitting stops when we reach the maximum
794
- // zoom or the number of points is low as specified in the options.
795
- GeoJSONVT.prototype.splitTile = function splitTile (features, z, x, y, cz, cx, cy) {
796
-
797
- var stack = [features, z, x, y];
798
- var options = this.options;
799
- var debug = options.debug;
800
-
801
- // avoid recursion by using a processing queue
802
- while (stack.length) {
803
- y = stack.pop();
804
- x = stack.pop();
805
- z = stack.pop();
806
- features = stack.pop();
807
-
808
- var z2 = 1 << z;
809
- var id = toID(z, x, y);
810
- var tile = this.tiles[id];
811
-
812
- if (!tile) {
813
- if (debug > 1) { console.time('creation'); }
814
-
815
- tile = this.tiles[id] = createTile(features, z, x, y, options);
816
- this.tileCoords.push({z: z, x: x, y: y});
817
-
818
- if (debug) {
819
- if (debug > 1) {
820
- console.log('tile z%d-%d-%d (features: %d, points: %d, simplified: %d)',
821
- z, x, y, tile.numFeatures, tile.numPoints, tile.numSimplified);
822
- console.timeEnd('creation');
823
- }
824
- var key = "z" + z;
825
- this.stats[key] = (this.stats[key] || 0) + 1;
826
- this.total++;
827
- }
828
- }
829
-
830
- // save reference to original geometry in tile so that we can drill down later if we stop now
831
- tile.source = features;
832
-
833
- // if it's the first-pass tiling
834
- if (cz == null) {
835
- // stop tiling if we reached max zoom, or if the tile is too simple
836
- if (z === options.indexMaxZoom || tile.numPoints <= options.indexMaxPoints) { continue; }
837
- // if a drilldown to a specific tile
838
- } else if (z === options.maxZoom || z === cz) {
839
- // stop tiling if we reached base zoom or our target tile zoom
840
- continue;
841
- } else if (cz != null) {
842
- // stop tiling if it's not an ancestor of the target tile
843
- var zoomSteps = cz - z;
844
- if (x !== cx >> zoomSteps || y !== cy >> zoomSteps) { continue; }
845
- }
846
-
847
- // if we slice further down, no need to keep source geometry
848
- tile.source = null;
849
-
850
- if (features.length === 0) { continue; }
851
-
852
- if (debug > 1) { console.time('clipping'); }
853
-
854
- // values we'll use for clipping
855
- var k1 = 0.5 * options.buffer / options.extent;
856
- var k2 = 0.5 - k1;
857
- var k3 = 0.5 + k1;
858
- var k4 = 1 + k1;
859
-
860
- var tl = null;
861
- var bl = null;
862
- var tr = null;
863
- var br = null;
864
-
865
- var left = clip(features, z2, x - k1, x + k3, 0, tile.minX, tile.maxX, options);
866
- var right = clip(features, z2, x + k2, x + k4, 0, tile.minX, tile.maxX, options);
867
- features = null;
868
-
869
- if (left) {
870
- tl = clip(left, z2, y - k1, y + k3, 1, tile.minY, tile.maxY, options);
871
- bl = clip(left, z2, y + k2, y + k4, 1, tile.minY, tile.maxY, options);
872
- left = null;
873
- }
874
-
875
- if (right) {
876
- tr = clip(right, z2, y - k1, y + k3, 1, tile.minY, tile.maxY, options);
877
- br = clip(right, z2, y + k2, y + k4, 1, tile.minY, tile.maxY, options);
878
- right = null;
879
- }
880
-
881
- if (debug > 1) { console.timeEnd('clipping'); }
882
-
883
- stack.push(tl || [], z + 1, x * 2, y * 2);
884
- stack.push(bl || [], z + 1, x * 2, y * 2 + 1);
885
- stack.push(tr || [], z + 1, x * 2 + 1, y * 2);
886
- stack.push(br || [], z + 1, x * 2 + 1, y * 2 + 1);
887
- }
888
- };
889
-
890
- GeoJSONVT.prototype.getTile = function getTile (z, x, y) {
891
- z = +z;
892
- x = +x;
893
- y = +y;
894
-
895
- var options = this.options;
896
- var extent = options.extent;
897
- var debug = options.debug;
898
-
899
- if (z < 0 || z > 24) { return null; }
900
-
901
- var z2 = 1 << z;
902
- x = (x + z2) & (z2 - 1); // wrap tile x coordinate
903
-
904
- var id = toID(z, x, y);
905
- if (this.tiles[id]) { return transformTile(this.tiles[id], extent); }
906
-
907
- if (debug > 1) { console.log('drilling down to z%d-%d-%d', z, x, y); }
908
-
909
- var z0 = z;
910
- var x0 = x;
911
- var y0 = y;
912
- var parent;
913
-
914
- while (!parent && z0 > 0) {
915
- z0--;
916
- x0 = x0 >> 1;
917
- y0 = y0 >> 1;
918
- parent = this.tiles[toID(z0, x0, y0)];
919
- }
920
-
921
- if (!parent || !parent.source) { return null; }
922
-
923
- // if we found a parent tile containing the original geometry, we can drill down from it
924
- if (debug > 1) {
925
- console.log('found parent tile z%d-%d-%d', z0, x0, y0);
926
- console.time('drilling down');
927
- }
928
- this.splitTile(parent.source, z0, x0, y0, z, x, y);
929
- if (debug > 1) { console.timeEnd('drilling down'); }
930
-
931
- return this.tiles[id] ? transformTile(this.tiles[id], extent) : null;
932
- };
933
-
934
- function toID(z, x, y) {
935
- return (((1 << z) * y + x) * 32) + z;
936
- }
937
-
938
- function extend(dest, src) {
939
- for (var i in src) { dest[i] = src[i]; }
940
- return dest;
941
- }
942
-
943
- function geojsonvt(data, options) {
944
- return new GeoJSONVT(data, options);
945
- }
946
-
947
- return geojsonvt;
948
-
949
- })));
package/geojson-vt.js DELETED
@@ -1 +0,0 @@
1
- !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).geojsonvt=e()}(this,(function(){"use strict";function t(t,e,n,i,r,o){var l=r-n,a=o-i;if(0!==l||0!==a){var s=((t-n)*l+(e-i)*a)/(l*l+a*a);s>1?(n=r,i=o):s>0&&(n+=l*s,i+=a*s)}return(l=t-n)*l+(a=e-i)*a}function e(t,e,i,r){var o={id:null==t?null:t,type:e,geometry:i,tags:r,minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0};if("Point"===e||"MultiPoint"===e||"LineString"===e)n(o,i);else if("Polygon"===e)n(o,i[0]);else if("MultiLineString"===e)for(var l=0,a=i;l<a.length;l+=1){n(o,a[l])}else if("MultiPolygon"===e)for(var s=0,u=i;s<u.length;s+=1){n(o,u[s][0])}return o}function n(t,e){for(var n=0;n<e.length;n+=3)t.minX=Math.min(t.minX,e[n]),t.minY=Math.min(t.minY,e[n+1]),t.maxX=Math.max(t.maxX,e[n]),t.maxY=Math.max(t.maxY,e[n+1])}function i(t,n,a,s){if(n.geometry){var u=a.crs,f=n.geometry.coordinates,g=n.geometry.type,h=Math.pow(a.tolerance/((1<<a.maxZoom)*a.extent),2),m=[],p=n.id;if(a.promoteId?p=n.properties[a.promoteId]:a.generateId&&(p=s||0),"Point"===g)r(f,m,u);else if("MultiPoint"===g)for(var d=0,c=f;d<c.length;d+=1){r(c[d],m,u)}else if("LineString"===g)o(f,m,h,!1,u);else if("MultiLineString"===g){if(a.lineMetrics){for(var v=0,x=f;v<x.length;v+=1){o(x[v],m=[],h,!1,u),t.push(e(p,"LineString",m,n.properties))}return}l(f,m,h,!1,u)}else if("Polygon"===g)l(f,m,h,!0,u);else{if("MultiPolygon"!==g){if("GeometryCollection"===g){for(var M=0,y=n.geometry.geometries;M<y.length;M+=1){i(t,{id:p,geometry:y[M],properties:n.properties},a,s)}return}throw new Error("Input data is not a valid GeoJSON object.")}for(var P=0,S=f;P<S.length;P+=1){var Y=[];l(S[P],Y,h,!0,u),m.push(Y)}}t.push(e(p,g,m,n.properties))}}function r(t,e,n){e.push(a(t[0],n),s(t[1],n),0)}function o(e,n,i,r,o){for(var l,u,f=0,g=0;g<e.length;g++){var h=a(e[g][0],o),m=s(e[g][1],o);n.push(h,m,0),g>0&&(f+=r?(l*m-h*u)/2:Math.sqrt(Math.pow(h-l,2)+Math.pow(m-u,2))),l=h,u=m}var p=n.length-3;n[2]=1,function e(n,i,r,o){for(var l,a=o,s=r-i>>1,u=r-i,f=n[i],g=n[i+1],h=n[r],m=n[r+1],p=i+3;p<r;p+=3){var d=t(n[p],n[p+1],f,g,h,m);if(d>a)l=p,a=d;else if(d===a){var c=Math.abs(p-s);c<u&&(l=p,u=c)}}a>o&&(l-i>3&&e(n,i,l,o),n[l+2]=a,r-l>3&&e(n,l,r,o))}(n,0,p,i),n[p+2]=1,n.size=Math.abs(f),n.start=0,n.end=n.size}function l(t,e,n,i,r){for(var l=0;l<t.length;l++){var a=[];o(t[l],a,n,i,r),e.push(a)}}function a(t,e){return t/360+.5}function s(t,e){var n;if(e&&"EPSG:3857"!==e)n=(90-t)/360;else{var i=Math.sin(t*Math.PI/180);n=.5-.25*Math.log((1+i)/(1-i))/Math.PI}return n<0?0:n>1?1:n}function u(t,n,i,r,o,l,a,s){if(r/=n,l>=(i/=n)&&a<r)return t;if(a<i||l>=r)return null;for(var u=[],h=0,p=t;h<p.length;h+=1){var d=p[h],c=d.geometry,v=d.type,x=0===o?d.minX:d.minY,M=0===o?d.maxX:d.maxY;if(x>=i&&M<r)u.push(d);else if(!(M<i||x>=r)){var y=[];if("Point"===v||"MultiPoint"===v)f(c,y,i,r,o);else if("LineString"===v)g(c,y,i,r,o,!1,s.lineMetrics);else if("MultiLineString"===v)m(c,y,i,r,o,!1);else if("Polygon"===v)m(c,y,i,r,o,!0);else if("MultiPolygon"===v)for(var P=0,S=c;P<S.length;P+=1){var Y=[];m(S[P],Y,i,r,o,!0),Y.length&&y.push(Y)}if(y.length){if(s.lineMetrics&&"LineString"===v){for(var X=0,L=y;X<L.length;X+=1){var b=L[X];u.push(e(d.id,v,b,d.tags))}continue}"LineString"!==v&&"MultiLineString"!==v||(1===y.length?(v="LineString",y=y[0]):v="MultiLineString"),"Point"!==v&&"MultiPoint"!==v||(v=3===y.length?"Point":"MultiPoint"),u.push(e(d.id,v,y,d.tags))}}}return u.length?u:null}function f(t,e,n,i,r){for(var o=0;o<t.length;o+=3){var l=t[o+r];l>=n&&l<=i&&p(e,t[o],t[o+1],t[o+2])}}function g(t,e,n,i,r,o,l){for(var a,s,u=h(t),f=0===r?d:c,g=t.start,m=0;m<t.length-3;m+=3){var v=t[m],x=t[m+1],M=t[m+2],y=t[m+3],P=t[m+4],S=0===r?v:x,Y=0===r?y:P,X=!1;l&&(a=Math.sqrt(Math.pow(v-y,2)+Math.pow(x-P,2))),S<n?Y>n&&(s=f(u,v,x,y,P,n),l&&(u.start=g+a*s)):S>i?Y<i&&(s=f(u,v,x,y,P,i),l&&(u.start=g+a*s)):p(u,v,x,M),Y<n&&S>=n&&(s=f(u,v,x,y,P,n),X=!0),Y>i&&S<=i&&(s=f(u,v,x,y,P,i),X=!0),!o&&X&&(l&&(u.end=g+a*s),e.push(u),u=h(t)),l&&(g+=a)}var L=t.length-3,b=t[L],z=t[L+1],w=t[L+2],I=0===r?b:z;I>=n&&I<=i&&p(u,b,z,w),L=u.length-3,o&&L>=3&&(u[L]!==u[0]||u[L+1]!==u[1])&&p(u,u[0],u[1],u[2]),u.length&&e.push(u)}function h(t){var e=[];return e.size=t.size,e.start=t.start,e.end=t.end,e}function m(t,e,n,i,r,o){for(var l=0,a=t;l<a.length;l+=1){g(a[l],e,n,i,r,o,!1)}}function p(t,e,n,i){t.push(e,n,i)}function d(t,e,n,i,r,o){var l=(o-e)/(i-e);return p(t,o,n+(r-n)*l,1),l}function c(t,e,n,i,r,o){var l=(o-n)/(r-n);return p(t,e+(i-e)*l,o,1),l}function v(t,n){for(var i=[],r=0;r<t.length;r++){var o=t[r],l=o.type,a=void 0;if("Point"===l||"MultiPoint"===l||"LineString"===l)a=x(o.geometry,n);else if("MultiLineString"===l||"Polygon"===l){a=[];for(var s=0,u=o.geometry;s<u.length;s+=1){var f=u[s];a.push(x(f,n))}}else if("MultiPolygon"===l){a=[];for(var g=0,h=o.geometry;g<h.length;g+=1){for(var m=[],p=0,d=h[g];p<d.length;p+=1){var c=d[p];m.push(x(c,n))}a.push(m)}}i.push(e(o.id,l,a,o.tags))}return i}function x(t,e){var n=[];n.size=t.size,void 0!==t.start&&(n.start=t.start,n.end=t.end);for(var i=0;i<t.length;i+=3)n.push(t[i]+e,t[i+1],t[i+2]);return n}function M(t,e){if(t.transformed)return t;for(var n=1<<t.z,i=t.x,r=t.y,o=0,l=t.features;o<l.length;o+=1){var a=l[o],s=a.geometry,u=a.type;if(a.geometry=[],1===u)for(var f=0;f<s.length;f+=2)a.geometry.push(y(s[f],s[f+1],e,n,i,r));else for(var g=0;g<s.length;g++){for(var h=[],m=0;m<s[g].length;m+=2)h.push(y(s[g][m],s[g][m+1],e,n,i,r));a.geometry.push(h)}}return t.transformed=!0,t}function y(t,e,n,i,r,o){return[Math.round(n*(t*i-r)),Math.round(n*(e*i-o))]}function P(t,e,n,i,r){for(var o=e===r.maxZoom?0:r.tolerance/((1<<e)*r.extent),l={features:[],numPoints:0,numSimplified:0,numFeatures:t.length,source:null,x:n,y:i,z:e,transformed:!1,minX:2,minY:1,maxX:-1,maxY:0},a=0,s=t;a<s.length;a+=1){S(l,s[a],o,r)}return l}function S(t,e,n,i){var r=e.geometry,o=e.type,l=[];if(t.minX=Math.min(t.minX,e.minX),t.minY=Math.min(t.minY,e.minY),t.maxX=Math.max(t.maxX,e.maxX),t.maxY=Math.max(t.maxY,e.maxY),"Point"===o||"MultiPoint"===o)for(var a=0;a<r.length;a+=3)l.push(r[a],r[a+1]),t.numPoints++,t.numSimplified++;else if("LineString"===o)Y(l,r,t,n,!1,!1);else if("MultiLineString"===o||"Polygon"===o)for(var s=0;s<r.length;s++)Y(l,r[s],t,n,"Polygon"===o,0===s);else if("MultiPolygon"===o)for(var u=0;u<r.length;u++)for(var f=r[u],g=0;g<f.length;g++)Y(l,f[g],t,n,!0,0===g);if(l.length){var h=e.tags||null;if("LineString"===o&&i.lineMetrics){for(var m in h={},e.tags)h[m]=e.tags[m];h.mapbox_clip_start=r.start/r.size,h.mapbox_clip_end=r.end/r.size}var p={geometry:l,type:"Polygon"===o||"MultiPolygon"===o?3:"LineString"===o||"MultiLineString"===o?2:1,tags:h};null!==e.id&&(p.id=e.id),t.features.push(p)}}function Y(t,e,n,i,r,o){var l=i*i;if(i>0&&e.size<(r?l:i))n.numPoints+=e.length/3;else{for(var a=[],s=0;s<e.length;s+=3)(0===i||e[s+2]>l)&&(n.numSimplified++,a.push(e[s],e[s+1])),n.numPoints++;r&&function(t,e){for(var n=0,i=0,r=t.length,o=r-2;i<r;o=i,i+=2)n+=(t[i]-t[o])*(t[i+1]+t[o+1]);if(n>0===e)for(var l=0,a=t.length;l<a/2;l+=2){var s=t[l],u=t[l+1];t[l]=t[a-2-l],t[l+1]=t[a-1-l],t[a-2-l]=s,t[a-1-l]=u}}(a,o),t.push(a)}}var X={crs:"EPSG:3857",maxZoom:14,indexMaxZoom:5,indexMaxPoints:1e5,tolerance:3,extent:4096,buffer:64,lineMetrics:!1,promoteId:null,generateId:!1,debug:0},L=function(t,e){var n=(e=this.options=function(t,e){for(var n in e)t[n]=e[n];return t}(Object.create(X),e)).debug;if(n&&console.time("preprocess data"),e.maxZoom<0||e.maxZoom>24)throw new Error("maxZoom should be in the 0-24 range");if(e.promoteId&&e.generateId)throw new Error("promoteId and generateId cannot be used together.");var r=function(t,e){var n=[];if("FeatureCollection"===t.type)for(var r=0;r<t.features.length;r++)i(n,t.features[r],e,r);else"Feature"===t.type?i(n,t,e):i(n,{geometry:t},e);return n}(t,e);this.tiles={},this.tileCoords=[],n&&(console.timeEnd("preprocess data"),console.log("index: maxZoom: %d, maxPoints: %d",e.indexMaxZoom,e.indexMaxPoints),console.time("generate tiles"),this.stats={},this.total=0),(r=function(t,e){var n=e.buffer/e.extent,i=t,r=u(t,1,-1-n,n,0,-1,2,e),o=u(t,1,1-n,2+n,0,-1,2,e);return(r||o)&&(i=u(t,1,-n,1+n,0,-1,2,e)||[],r&&(i=v(r,1).concat(i)),o&&(i=i.concat(v(o,-1)))),i}(r,e)).length&&this.splitTile(r,0,0,0),n&&(r.length&&console.log("features: %d, points: %d",this.tiles[0].numFeatures,this.tiles[0].numPoints),console.timeEnd("generate tiles"),console.log("tiles generated:",this.total,JSON.stringify(this.stats)))};function b(t,e,n){return 32*((1<<t)*n+e)+t}return L.prototype.splitTile=function(t,e,n,i,r,o,l){for(var a=[t,e,n,i],s=this.options,f=s.debug;a.length;){i=a.pop(),n=a.pop(),e=a.pop(),t=a.pop();var g=1<<e,h=b(e,n,i),m=this.tiles[h];if(!m&&(f>1&&console.time("creation"),m=this.tiles[h]=P(t,e,n,i,s),this.tileCoords.push({z:e,x:n,y:i}),f)){f>1&&(console.log("tile z%d-%d-%d (features: %d, points: %d, simplified: %d)",e,n,i,m.numFeatures,m.numPoints,m.numSimplified),console.timeEnd("creation"));var p="z"+e;this.stats[p]=(this.stats[p]||0)+1,this.total++}if(m.source=t,null==r){if(e===s.indexMaxZoom||m.numPoints<=s.indexMaxPoints)continue}else{if(e===s.maxZoom||e===r)continue;if(null!=r){var d=r-e;if(n!==o>>d||i!==l>>d)continue}}if(m.source=null,0!==t.length){f>1&&console.time("clipping");var c=.5*s.buffer/s.extent,v=.5-c,x=.5+c,M=1+c,y=null,S=null,Y=null,X=null,L=u(t,g,n-c,n+x,0,m.minX,m.maxX,s),z=u(t,g,n+v,n+M,0,m.minX,m.maxX,s);t=null,L&&(y=u(L,g,i-c,i+x,1,m.minY,m.maxY,s),S=u(L,g,i+v,i+M,1,m.minY,m.maxY,s),L=null),z&&(Y=u(z,g,i-c,i+x,1,m.minY,m.maxY,s),X=u(z,g,i+v,i+M,1,m.minY,m.maxY,s),z=null),f>1&&console.timeEnd("clipping"),a.push(y||[],e+1,2*n,2*i),a.push(S||[],e+1,2*n,2*i+1),a.push(Y||[],e+1,2*n+1,2*i),a.push(X||[],e+1,2*n+1,2*i+1)}}},L.prototype.getTile=function(t,e,n){t=+t,e=+e,n=+n;var i=this.options,r=i.extent,o=i.debug;if(t<0||t>24)return null;var l=1<<t,a=b(t,e=e+l&l-1,n);if(this.tiles[a])return M(this.tiles[a],r);o>1&&console.log("drilling down to z%d-%d-%d",t,e,n);for(var s,u=t,f=e,g=n;!s&&u>0;)u--,f>>=1,g>>=1,s=this.tiles[b(u,f,g)];return s&&s.source?(o>1&&(console.log("found parent tile z%d-%d-%d",u,f,g),console.time("drilling down")),this.splitTile(s.source,u,f,g,t,e,n),o>1&&console.timeEnd("drilling down"),this.tiles[a]?M(this.tiles[a],r):null):null},function(t,e){return new L(t,e)}}));