fix GeoJSON roundtripping

This commit is contained in:
Vladimir Agafonkin 2013-12-13 12:32:26 -05:00
parent 87bf1ff144
commit dc5151b81a
5 changed files with 88 additions and 94 deletions

View File

@ -147,7 +147,7 @@ var deps = {
GeoJSON: {
src: ['layer/GeoJSON.js'],
deps: ['Polygon', 'Circle', 'Marker', 'FeatureGroup'],
deps: ['Polygon', 'Circle', 'CircleMarker', 'Marker', 'FeatureGroup'],
desc: 'GeoJSON layer, parses the data and adds corresponding layers above.'
},

View File

@ -36,7 +36,7 @@
var circle = L.circle([35, 0], 700000, {color: 'green', renderer: canvas}).addTo(map).bindPopup('Hello Circle');
map.fitBounds(path);
map.setView([36, 52], 3);
</script>
</body>
</html>

View File

@ -95,9 +95,9 @@ describe("L.Polyline#toGeoJSON", function () {
});
});
describe("L.MultiPolyline#toGeoJSON", function () {
describe("L.Polyline (multi) #toGeoJSON", function () {
it("returns a 2D MultiLineString object", function () {
var multiPolyline = new L.MultiPolyline([[[10, 20], [2, 5]], [[1, 2], [3, 4]]]);
var multiPolyline = new L.Polyline([[[10, 20], [2, 5]], [[1, 2], [3, 4]]]);
expect(multiPolyline.toGeoJSON().geometry).to.eql({
type: 'MultiLineString',
coordinates: [
@ -108,7 +108,7 @@ describe("L.MultiPolyline#toGeoJSON", function () {
});
it("returns a 3D MultiLineString object", function () {
var multiPolyline = new L.MultiPolyline([[[10, 20, 30], [2, 5, 10]], [[1, 2, 3], [4, 5, 6]]]);
var multiPolyline = new L.Polyline([[[10, 20, 30], [2, 5, 10]], [[1, 2, 3], [4, 5, 6]]]);
expect(multiPolyline.toGeoJSON().geometry).to.eql({
type: 'MultiLineString',
coordinates: [
@ -159,9 +159,9 @@ describe("L.Polygon#toGeoJSON", function () {
});
});
describe("L.MultiPolygon#toGeoJSON", function () {
describe("L.Polygon (multi) #toGeoJSON", function () {
it("returns a 2D MultiPolygon object", function () {
var multiPolygon = new L.MultiPolygon([[[1, 2], [3, 4], [5, 6]]]);
var multiPolygon = new L.Polygon([[[1, 2], [3, 4], [5, 6]]]);
expect(multiPolygon.toGeoJSON().geometry).to.eql({
type: 'MultiPolygon',
coordinates: [
@ -171,7 +171,7 @@ describe("L.MultiPolygon#toGeoJSON", function () {
});
it("returns a 3D MultiPolygon object", function () {
var multiPolygon = new L.MultiPolygon([[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]);
var multiPolygon = new L.Polygon([[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]);
expect(multiPolygon.toGeoJSON().geometry).to.eql({
type: 'MultiPolygon',
coordinates: [

View File

@ -99,23 +99,14 @@ L.extend(L.GeoJSON, {
return new L.FeatureGroup(layers);
case 'LineString':
latlngs = this.coordsToLatLngs(coords, 0, coordsToLatLng);
case 'MultiLineString':
latlngs = this.coordsToLatLngs(coords, geometry.type === 'LineString' ? 0 : 1, coordsToLatLng);
return new L.Polyline(latlngs, options);
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, options);
case 'MultiLineString':
latlngs = this.coordsToLatLngs(coords, 1, coordsToLatLng);
return new L.MultiPolyline(latlngs, options);
case 'MultiPolygon':
latlngs = this.coordsToLatLngs(coords, 2, coordsToLatLng);
return new L.MultiPolygon(latlngs, options);
latlngs = this.coordsToLatLngs(coords, geometry.type === 'Polygon' ? 1 : 2, coordsToLatLng);
return new L.Polygon(latlngs, options);
case 'GeometryCollection':
for (i = 0, len = geometry.geometries.length; i < len; i++) {
@ -157,11 +148,17 @@ L.extend(L.GeoJSON, {
[latlng.lng, latlng.lat];
},
latLngsToCoords: function (latLngs) {
latLngsToCoords: function (latlngs, levelsDeep, closed) {
var coords = [];
for (var i = 0, len = latLngs.length; i < len; i++) {
coords.push(L.GeoJSON.latLngToCoords(latLngs[i]));
for (var i = 0, len = latlngs.length; i < len; i++) {
coords.push(levelsDeep ?
L.GeoJSON.latLngsToCoords(latlngs[i], levelsDeep - 1, closed):
L.GeoJSON.latLngToCoords(latlngs[i]));
}
if (!levelsDeep && closed) {
coords.push(coords[0]);
}
return coords;
@ -199,90 +196,83 @@ 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.Polyline.prototype.toGeoJSON = function () {
var multi = !this._flat(this._latlngs);
var coords = L.GeoJSON.latLngsToCoords(this._latlngs, multi ? 1 : 0);
return L.GeoJSON.getFeature(this, {
type: (multi ? 'Multi' : '') + 'LineString',
coordinates: coords
});
};
L.Polygon.prototype.toGeoJSON = function () {
var holes = !this._flat(this._latlngs),
multi = holes && !this._flat(this._latlngs[0]);
var coords = L.GeoJSON.latLngsToCoords(this._latlngs, multi ? 2 : holes ? 1 : 0, true);
if (holes && this._latlngs.length === 1) {
multi = true;
coords = [coords];
}
if (!holes) {
coords = [coords];
}
});
L.Polygon.include({
toGeoJSON: function () {
var coords = [L.GeoJSON.latLngsToCoords(this.getLatLngs())],
i, len, hole;
return L.GeoJSON.getFeature(this, {
type: (multi ? 'Multi' : '') + 'Polygon',
coordinates: coords
});
};
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);
}
}
L.LayerGroup.include({
toMultiPoint: function () {
var coords = [];
this.eachLayer(function (layer) {
coords.push(layer.toGeoJSON().geometry.coordinates);
});
return L.GeoJSON.getFeature(this, {
type: 'Polygon',
type: 'MultiPoint',
coordinates: coords
});
}
});
},
(function () {
function multiToGeoJSON(type) {
return function () {
var coords = [];
toGeoJSON: function () {
this.eachLayer(function (layer) {
coords.push(layer.toGeoJSON().geometry.coordinates);
});
var type = this.feature && this.feature.geometry && this.feature.geometry.type;
if (type === 'MultiPoint') {
return this.toMultiPoint();
}
var isGeometryCollection = type === 'GeometryCollection',
jsons = [];
this.eachLayer(function (layer) {
if (layer.toGeoJSON) {
var json = layer.toGeoJSON();
jsons.push(isGeometryCollection ? json.geometry : L.GeoJSON.asFeature(json));
}
});
if (isGeometryCollection) {
return L.GeoJSON.getFeature(this, {
type: type,
coordinates: coords
geometries: jsons,
type: 'GeometryCollection'
});
}
return {
type: 'FeatureCollection',
features: jsons
};
}
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);

View File

@ -72,7 +72,7 @@ L.Polyline = L.Path.extend({
_convertLatLngs: function (latlngs) {
var result = [],
flat = !L.Util.isArray(latlngs[0]) || typeof latlngs[0][0] === 'number';
flat = this._flat(latlngs);
for (var i = 0, len = latlngs.length; i < len; i++) {
result[i] = flat ? L.latLng(latlngs[i]) : this._convertLatLngs(latlngs[i]);
@ -81,6 +81,10 @@ L.Polyline = L.Path.extend({
return result;
},
_flat: function (latlngs) {
return !L.Util.isArray(latlngs[0]) || typeof latlngs[0][0] === 'number';
},
_project: function () {
this._rings = [];
this._projectLatlngs(this._latlngs, this._rings);