287 lines
7.0 KiB
JavaScript
287 lines
7.0 KiB
JavaScript
/*
|
|
* L.GeoJSON turns any GeoJSON data into a Leaflet layer.
|
|
*/
|
|
|
|
L.GeoJSON = L.FeatureGroup.extend({
|
|
|
|
initialize: function (geojson, options) {
|
|
L.setOptions(this, options);
|
|
|
|
this._layers = {};
|
|
|
|
if (geojson) {
|
|
this.addData(geojson);
|
|
}
|
|
},
|
|
|
|
addData: function (geojson) {
|
|
var features = L.Util.isArray(geojson) ? geojson : geojson.features,
|
|
i, len, feature;
|
|
|
|
if (features) {
|
|
for (i = 0, len = features.length; i < len; i++) {
|
|
// Only add this if geometry or geometries are set and not null
|
|
feature = features[i];
|
|
if (feature.geometries || feature.geometry || feature.features || feature.coordinates) {
|
|
this.addData(features[i]);
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
|
|
var options = this.options;
|
|
|
|
if (options.filter && !options.filter(geojson)) { return; }
|
|
|
|
var layer = L.GeoJSON.geometryToLayer(geojson, options.pointToLayer, options.coordsToLatLng, options);
|
|
layer.feature = L.GeoJSON.asFeature(geojson);
|
|
|
|
layer.defaultOptions = layer.options;
|
|
this.resetStyle(layer);
|
|
|
|
if (options.onEachFeature) {
|
|
options.onEachFeature(geojson, layer);
|
|
}
|
|
|
|
return this.addLayer(layer);
|
|
},
|
|
|
|
resetStyle: function (layer) {
|
|
var style = this.options.style;
|
|
if (style) {
|
|
// reset any custom styles
|
|
L.Util.extend(layer.options, layer.defaultOptions);
|
|
|
|
this._setLayerStyle(layer, style);
|
|
}
|
|
},
|
|
|
|
setStyle: function (style) {
|
|
this.eachLayer(function (layer) {
|
|
this._setLayerStyle(layer, style);
|
|
}, this);
|
|
},
|
|
|
|
_setLayerStyle: function (layer, style) {
|
|
if (typeof style === 'function') {
|
|
style = style(layer.feature);
|
|
}
|
|
if (layer.setStyle) {
|
|
layer.setStyle(style);
|
|
}
|
|
}
|
|
});
|
|
|
|
L.extend(L.GeoJSON, {
|
|
geometryToLayer: function (geojson, pointToLayer, coordsToLatLng, vectorOptions) {
|
|
var geometry = geojson.type === 'Feature' ? geojson.geometry : geojson,
|
|
coords = geometry.coordinates,
|
|
layers = [],
|
|
latlng, latlngs, i, len;
|
|
|
|
coordsToLatLng = coordsToLatLng || this.coordsToLatLng;
|
|
|
|
switch (geometry.type) {
|
|
case 'Point':
|
|
latlng = coordsToLatLng(coords);
|
|
return pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng);
|
|
|
|
case 'MultiPoint':
|
|
for (i = 0, len = coords.length; i < len; i++) {
|
|
latlng = coordsToLatLng(coords[i]);
|
|
layers.push(pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng));
|
|
}
|
|
return new L.FeatureGroup(layers);
|
|
|
|
case 'LineString':
|
|
latlngs = this.coordsToLatLngs(coords, 0, coordsToLatLng);
|
|
return new L.Polyline(latlngs, vectorOptions);
|
|
|
|
case 'Polygon':
|
|
if (coords.length === 2 && !coords[1].length) {
|
|
throw new Error('Invalid GeoJSON object.');
|
|
}
|
|
latlngs = this.coordsToLatLngs(coords, 1, coordsToLatLng);
|
|
return new L.Polygon(latlngs, vectorOptions);
|
|
|
|
case 'MultiLineString':
|
|
latlngs = this.coordsToLatLngs(coords, 1, coordsToLatLng);
|
|
return new L.MultiPolyline(latlngs, vectorOptions);
|
|
|
|
case 'MultiPolygon':
|
|
latlngs = this.coordsToLatLngs(coords, 2, coordsToLatLng);
|
|
return new L.MultiPolygon(latlngs, vectorOptions);
|
|
|
|
case 'GeometryCollection':
|
|
for (i = 0, len = geometry.geometries.length; i < len; i++) {
|
|
|
|
layers.push(this.geometryToLayer({
|
|
geometry: geometry.geometries[i],
|
|
type: 'Feature',
|
|
properties: geojson.properties
|
|
}, pointToLayer, coordsToLatLng, vectorOptions));
|
|
}
|
|
return new L.FeatureGroup(layers);
|
|
|
|
default:
|
|
throw new Error('Invalid GeoJSON object.');
|
|
}
|
|
},
|
|
|
|
coordsToLatLng: function (coords) { // (Array[, Boolean]) -> LatLng
|
|
return new L.LatLng(coords[1], coords[0], coords[2]);
|
|
},
|
|
|
|
coordsToLatLngs: function (coords, levelsDeep, coordsToLatLng) { // (Array[, Number, Function]) -> Array
|
|
var latlng, i, len,
|
|
latlngs = [];
|
|
|
|
for (i = 0, len = coords.length; i < len; i++) {
|
|
latlng = levelsDeep ?
|
|
this.coordsToLatLngs(coords[i], levelsDeep - 1, coordsToLatLng) :
|
|
(coordsToLatLng || this.coordsToLatLng)(coords[i]);
|
|
|
|
latlngs.push(latlng);
|
|
}
|
|
|
|
return latlngs;
|
|
},
|
|
|
|
latLngToCoords: function (latlng) {
|
|
var coords = [latlng.lng, latlng.lat];
|
|
|
|
if (latlng.alt !== undefined) {
|
|
coords.push(latlng.alt);
|
|
}
|
|
return coords;
|
|
},
|
|
|
|
latLngsToCoords: function (latLngs) {
|
|
var coords = [];
|
|
|
|
for (var i = 0, len = latLngs.length; i < len; i++) {
|
|
coords.push(L.GeoJSON.latLngToCoords(latLngs[i]));
|
|
}
|
|
|
|
return coords;
|
|
},
|
|
|
|
getFeature: function (layer, newGeometry) {
|
|
return layer.feature ? L.extend({}, layer.feature, {geometry: newGeometry}) : L.GeoJSON.asFeature(newGeometry);
|
|
},
|
|
|
|
asFeature: function (geoJSON) {
|
|
if (geoJSON.type === 'Feature') {
|
|
return geoJSON;
|
|
}
|
|
|
|
return {
|
|
type: 'Feature',
|
|
properties: {},
|
|
geometry: geoJSON
|
|
};
|
|
}
|
|
});
|
|
|
|
var PointToGeoJSON = {
|
|
toGeoJSON: function () {
|
|
return L.GeoJSON.getFeature(this, {
|
|
type: 'Point',
|
|
coordinates: L.GeoJSON.latLngToCoords(this.getLatLng())
|
|
});
|
|
}
|
|
};
|
|
|
|
L.Marker.include(PointToGeoJSON);
|
|
L.Circle.include(PointToGeoJSON);
|
|
L.CircleMarker.include(PointToGeoJSON);
|
|
|
|
L.Polyline.include({
|
|
toGeoJSON: function () {
|
|
return L.GeoJSON.getFeature(this, {
|
|
type: 'LineString',
|
|
coordinates: L.GeoJSON.latLngsToCoords(this.getLatLngs())
|
|
});
|
|
}
|
|
});
|
|
|
|
L.Polygon.include({
|
|
toGeoJSON: function () {
|
|
var coords = [L.GeoJSON.latLngsToCoords(this.getLatLngs())],
|
|
i, len, hole;
|
|
|
|
coords[0].push(coords[0][0]);
|
|
|
|
if (this._holes) {
|
|
for (i = 0, len = this._holes.length; i < len; i++) {
|
|
hole = L.GeoJSON.latLngsToCoords(this._holes[i]);
|
|
hole.push(hole[0]);
|
|
coords.push(hole);
|
|
}
|
|
}
|
|
|
|
return L.GeoJSON.getFeature(this, {
|
|
type: 'Polygon',
|
|
coordinates: coords
|
|
});
|
|
}
|
|
});
|
|
|
|
(function () {
|
|
function multiToGeoJSON(type) {
|
|
return function () {
|
|
var coords = [];
|
|
|
|
this.eachLayer(function (layer) {
|
|
coords.push(layer.toGeoJSON().geometry.coordinates);
|
|
});
|
|
|
|
return L.GeoJSON.getFeature(this, {
|
|
type: type,
|
|
coordinates: coords
|
|
});
|
|
};
|
|
}
|
|
|
|
L.MultiPolyline.include({toGeoJSON: multiToGeoJSON('MultiLineString')});
|
|
L.MultiPolygon.include({toGeoJSON: multiToGeoJSON('MultiPolygon')});
|
|
|
|
L.LayerGroup.include({
|
|
toGeoJSON: function () {
|
|
|
|
var geometry = this.feature && this.feature.geometry,
|
|
jsons = [],
|
|
json;
|
|
|
|
if (geometry && geometry.type === 'MultiPoint') {
|
|
return multiToGeoJSON('MultiPoint').call(this);
|
|
}
|
|
|
|
var isGeometryCollection = geometry && geometry.type === 'GeometryCollection';
|
|
|
|
this.eachLayer(function (layer) {
|
|
if (layer.toGeoJSON) {
|
|
json = layer.toGeoJSON();
|
|
jsons.push(isGeometryCollection ? json.geometry : L.GeoJSON.asFeature(json));
|
|
}
|
|
});
|
|
|
|
if (isGeometryCollection) {
|
|
return L.GeoJSON.getFeature(this, {
|
|
geometries: jsons,
|
|
type: 'GeometryCollection'
|
|
});
|
|
}
|
|
|
|
return {
|
|
type: 'FeatureCollection',
|
|
features: jsons
|
|
};
|
|
}
|
|
});
|
|
}());
|
|
|
|
L.geoJson = function (geojson, options) {
|
|
return new L.GeoJSON(geojson, options);
|
|
};
|