1 | import {LayerGroup} from './LayerGroup';
|
2 | import {FeatureGroup} from './FeatureGroup';
|
3 | import * as Util from '../core/Util';
|
4 | import {Marker} from './marker/Marker';
|
5 | import {Circle} from './vector/Circle';
|
6 | import {CircleMarker} from './vector/CircleMarker';
|
7 | import {Polyline} from './vector/Polyline';
|
8 | import {Polygon} from './vector/Polygon';
|
9 | import {LatLng} from '../geo/LatLng';
|
10 | import * as LineUtil from '../geometry/LineUtil';
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 | export var GeoJSON = FeatureGroup.extend({
|
35 |
|
36 | |
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 |
|
82 |
|
83 | initialize: function (geojson, options) {
|
84 | Util.setOptions(this, options);
|
85 |
|
86 | this._layers = {};
|
87 |
|
88 | if (geojson) {
|
89 | this.addData(geojson);
|
90 | }
|
91 | },
|
92 |
|
93 |
|
94 |
|
95 | addData: function (geojson) {
|
96 | var features = Util.isArray(geojson) ? geojson : geojson.features,
|
97 | i, len, feature;
|
98 |
|
99 | if (features) {
|
100 | for (i = 0, len = features.length; i < len; i++) {
|
101 |
|
102 | feature = features[i];
|
103 | if (feature.geometries || feature.geometry || feature.features || feature.coordinates) {
|
104 | this.addData(feature);
|
105 | }
|
106 | }
|
107 | return this;
|
108 | }
|
109 |
|
110 | var options = this.options;
|
111 |
|
112 | if (options.filter && !options.filter(geojson)) { return this; }
|
113 |
|
114 | var layer = geometryToLayer(geojson, options);
|
115 | if (!layer) {
|
116 | return this;
|
117 | }
|
118 | layer.feature = asFeature(geojson);
|
119 |
|
120 | layer.defaultOptions = layer.options;
|
121 | this.resetStyle(layer);
|
122 |
|
123 | if (options.onEachFeature) {
|
124 | options.onEachFeature(geojson, layer);
|
125 | }
|
126 |
|
127 | return this.addLayer(layer);
|
128 | },
|
129 |
|
130 |
|
131 |
|
132 | resetStyle: function (layer) {
|
133 |
|
134 | layer.options = Util.extend({}, layer.defaultOptions);
|
135 | this._setLayerStyle(layer, this.options.style);
|
136 | return this;
|
137 | },
|
138 |
|
139 |
|
140 |
|
141 | setStyle: function (style) {
|
142 | return this.eachLayer(function (layer) {
|
143 | this._setLayerStyle(layer, style);
|
144 | }, this);
|
145 | },
|
146 |
|
147 | _setLayerStyle: function (layer, style) {
|
148 | if (layer.setStyle) {
|
149 | if (typeof style === 'function') {
|
150 | style = style(layer.feature);
|
151 | }
|
152 | layer.setStyle(style);
|
153 | }
|
154 | }
|
155 | });
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 | export function geometryToLayer(geojson, options) {
|
165 |
|
166 | var geometry = geojson.type === 'Feature' ? geojson.geometry : geojson,
|
167 | coords = geometry ? geometry.coordinates : null,
|
168 | layers = [],
|
169 | pointToLayer = options && options.pointToLayer,
|
170 | _coordsToLatLng = options && options.coordsToLatLng || coordsToLatLng,
|
171 | latlng, latlngs, i, len;
|
172 |
|
173 | if (!coords && !geometry) {
|
174 | return null;
|
175 | }
|
176 |
|
177 | switch (geometry.type) {
|
178 | case 'Point':
|
179 | latlng = _coordsToLatLng(coords);
|
180 | return pointToLayer ? pointToLayer(geojson, latlng) : new Marker(latlng);
|
181 |
|
182 | case 'MultiPoint':
|
183 | for (i = 0, len = coords.length; i < len; i++) {
|
184 | latlng = _coordsToLatLng(coords[i]);
|
185 | layers.push(pointToLayer ? pointToLayer(geojson, latlng) : new Marker(latlng));
|
186 | }
|
187 | return new FeatureGroup(layers);
|
188 |
|
189 | case 'LineString':
|
190 | case 'MultiLineString':
|
191 | latlngs = coordsToLatLngs(coords, geometry.type === 'LineString' ? 0 : 1, _coordsToLatLng);
|
192 | return new Polyline(latlngs, options);
|
193 |
|
194 | case 'Polygon':
|
195 | case 'MultiPolygon':
|
196 | latlngs = coordsToLatLngs(coords, geometry.type === 'Polygon' ? 1 : 2, _coordsToLatLng);
|
197 | return new Polygon(latlngs, options);
|
198 |
|
199 | case 'GeometryCollection':
|
200 | for (i = 0, len = geometry.geometries.length; i < len; i++) {
|
201 | var layer = geometryToLayer({
|
202 | geometry: geometry.geometries[i],
|
203 | type: 'Feature',
|
204 | properties: geojson.properties
|
205 | }, options);
|
206 |
|
207 | if (layer) {
|
208 | layers.push(layer);
|
209 | }
|
210 | }
|
211 | return new FeatureGroup(layers);
|
212 |
|
213 | default:
|
214 | throw new Error('Invalid GeoJSON object.');
|
215 | }
|
216 | }
|
217 |
|
218 |
|
219 |
|
220 |
|
221 | export function coordsToLatLng(coords) {
|
222 | return new LatLng(coords[1], coords[0], coords[2]);
|
223 | }
|
224 |
|
225 |
|
226 |
|
227 |
|
228 |
|
229 | export function coordsToLatLngs(coords, levelsDeep, _coordsToLatLng) {
|
230 | var latlngs = [];
|
231 |
|
232 | for (var i = 0, len = coords.length, latlng; i < len; i++) {
|
233 | latlng = levelsDeep ?
|
234 | coordsToLatLngs(coords[i], levelsDeep - 1, _coordsToLatLng) :
|
235 | (_coordsToLatLng || coordsToLatLng)(coords[i]);
|
236 |
|
237 | latlngs.push(latlng);
|
238 | }
|
239 |
|
240 | return latlngs;
|
241 | }
|
242 |
|
243 |
|
244 |
|
245 | export function latLngToCoords(latlng, precision) {
|
246 | precision = typeof precision === 'number' ? precision : 6;
|
247 | return latlng.alt !== undefined ?
|
248 | [Util.formatNum(latlng.lng, precision), Util.formatNum(latlng.lat, precision), Util.formatNum(latlng.alt, precision)] :
|
249 | [Util.formatNum(latlng.lng, precision), Util.formatNum(latlng.lat, precision)];
|
250 | }
|
251 |
|
252 |
|
253 |
|
254 |
|
255 | export function latLngsToCoords(latlngs, levelsDeep, closed, precision) {
|
256 | var coords = [];
|
257 |
|
258 | for (var i = 0, len = latlngs.length; i < len; i++) {
|
259 | coords.push(levelsDeep ?
|
260 | latLngsToCoords(latlngs[i], levelsDeep - 1, closed, precision) :
|
261 | latLngToCoords(latlngs[i], precision));
|
262 | }
|
263 |
|
264 | if (!levelsDeep && closed) {
|
265 | coords.push(coords[0]);
|
266 | }
|
267 |
|
268 | return coords;
|
269 | }
|
270 |
|
271 | export function getFeature(layer, newGeometry) {
|
272 | return layer.feature ?
|
273 | Util.extend({}, layer.feature, {geometry: newGeometry}) :
|
274 | asFeature(newGeometry);
|
275 | }
|
276 |
|
277 |
|
278 |
|
279 | export function asFeature(geojson) {
|
280 | if (geojson.type === 'Feature' || geojson.type === 'FeatureCollection') {
|
281 | return geojson;
|
282 | }
|
283 |
|
284 | return {
|
285 | type: 'Feature',
|
286 | properties: {},
|
287 | geometry: geojson
|
288 | };
|
289 | }
|
290 |
|
291 | var PointToGeoJSON = {
|
292 | toGeoJSON: function (precision) {
|
293 | return getFeature(this, {
|
294 | type: 'Point',
|
295 | coordinates: latLngToCoords(this.getLatLng(), precision)
|
296 | });
|
297 | }
|
298 | };
|
299 |
|
300 |
|
301 |
|
302 |
|
303 |
|
304 |
|
305 | Marker.include(PointToGeoJSON);
|
306 |
|
307 |
|
308 |
|
309 |
|
310 |
|
311 |
|
312 | Circle.include(PointToGeoJSON);
|
313 | CircleMarker.include(PointToGeoJSON);
|
314 |
|
315 |
|
316 |
|
317 |
|
318 |
|
319 |
|
320 |
|
321 | Polyline.include({
|
322 | toGeoJSON: function (precision) {
|
323 | var multi = !LineUtil.isFlat(this._latlngs);
|
324 |
|
325 | var coords = latLngsToCoords(this._latlngs, multi ? 1 : 0, false, precision);
|
326 |
|
327 | return getFeature(this, {
|
328 | type: (multi ? 'Multi' : '') + 'LineString',
|
329 | coordinates: coords
|
330 | });
|
331 | }
|
332 | });
|
333 |
|
334 |
|
335 |
|
336 |
|
337 |
|
338 |
|
339 | Polygon.include({
|
340 | toGeoJSON: function (precision) {
|
341 | var holes = !LineUtil.isFlat(this._latlngs),
|
342 | multi = holes && !LineUtil.isFlat(this._latlngs[0]);
|
343 |
|
344 | var coords = latLngsToCoords(this._latlngs, multi ? 2 : holes ? 1 : 0, true, precision);
|
345 |
|
346 | if (!holes) {
|
347 | coords = [coords];
|
348 | }
|
349 |
|
350 | return getFeature(this, {
|
351 | type: (multi ? 'Multi' : '') + 'Polygon',
|
352 | coordinates: coords
|
353 | });
|
354 | }
|
355 | });
|
356 |
|
357 |
|
358 |
|
359 | LayerGroup.include({
|
360 | toMultiPoint: function (precision) {
|
361 | var coords = [];
|
362 |
|
363 | this.eachLayer(function (layer) {
|
364 | coords.push(layer.toGeoJSON(precision).geometry.coordinates);
|
365 | });
|
366 |
|
367 | return getFeature(this, {
|
368 | type: 'MultiPoint',
|
369 | coordinates: coords
|
370 | });
|
371 | },
|
372 |
|
373 |
|
374 |
|
375 |
|
376 |
|
377 | toGeoJSON: function (precision) {
|
378 |
|
379 | var type = this.feature && this.feature.geometry && this.feature.geometry.type;
|
380 |
|
381 | if (type === 'MultiPoint') {
|
382 | return this.toMultiPoint(precision);
|
383 | }
|
384 |
|
385 | var isGeometryCollection = type === 'GeometryCollection',
|
386 | jsons = [];
|
387 |
|
388 | this.eachLayer(function (layer) {
|
389 | if (layer.toGeoJSON) {
|
390 | var json = layer.toGeoJSON(precision);
|
391 | if (isGeometryCollection) {
|
392 | jsons.push(json.geometry);
|
393 | } else {
|
394 | var feature = asFeature(json);
|
395 |
|
396 | if (feature.type === 'FeatureCollection') {
|
397 | jsons.push.apply(jsons, feature.features);
|
398 | } else {
|
399 | jsons.push(feature);
|
400 | }
|
401 | }
|
402 | }
|
403 | });
|
404 |
|
405 | if (isGeometryCollection) {
|
406 | return getFeature(this, {
|
407 | geometries: jsons,
|
408 | type: 'GeometryCollection'
|
409 | });
|
410 | }
|
411 |
|
412 | return {
|
413 | type: 'FeatureCollection',
|
414 | features: jsons
|
415 | };
|
416 | }
|
417 | });
|
418 |
|
419 |
|
420 |
|
421 |
|
422 |
|
423 |
|
424 | export function geoJSON(geojson, options) {
|
425 | return new GeoJSON(geojson, options);
|
426 | }
|
427 |
|
428 |
|
429 | export var geoJson = geoJSON;
|