Allow orienting coordinates when serializing GeoJSON
This commit is contained in:
@@ -1538,7 +1538,8 @@ olx.format;
|
||||
|
||||
/**
|
||||
* @typedef {{dataProjection: ol.proj.ProjectionLike,
|
||||
* featureProjection: ol.proj.ProjectionLike}}
|
||||
* featureProjection: ol.proj.ProjectionLike,
|
||||
* rightHanded: (boolean|undefined)}}
|
||||
* @api
|
||||
*/
|
||||
olx.format.ReadOptions;
|
||||
@@ -1567,7 +1568,8 @@ olx.format.ReadOptions.prototype.featureProjection;
|
||||
|
||||
/**
|
||||
* @typedef {{dataProjection: ol.proj.ProjectionLike,
|
||||
* featureProjection: ol.proj.ProjectionLike}}
|
||||
* featureProjection: ol.proj.ProjectionLike,
|
||||
* rightHanded: (boolean|undefined)}}
|
||||
* @api
|
||||
*/
|
||||
olx.format.WriteOptions;
|
||||
@@ -1593,6 +1595,22 @@ olx.format.WriteOptions.prototype.dataProjection;
|
||||
olx.format.WriteOptions.prototype.featureProjection;
|
||||
|
||||
|
||||
/**
|
||||
* When writing geometries, follow the right-hand rule for linear ring
|
||||
* orientation. This means that polygons will have counter-clockwise exterior
|
||||
* rings and clockwise interior rings. By default, coordinates are serialized
|
||||
* as they are provided at construction. If `true`, the right-hand rule will
|
||||
* be applied. If `false`, the left-hand rule will be applied (clockwise for
|
||||
* exterior and counter-clockwise for interior rings). Note that not all
|
||||
* formats support this. The GeoJSON format does use this property when writing
|
||||
* geometries.
|
||||
*
|
||||
* @type {boolean|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.format.WriteOptions.prototype.rightHanded;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{defaultDataProjection: ol.proj.ProjectionLike,
|
||||
* geometryName: (string|undefined)}}
|
||||
|
||||
@@ -68,7 +68,8 @@ ol.format.Feature.prototype.adaptOptions = function(options) {
|
||||
updatedOptions = {
|
||||
featureProjection: options.featureProjection,
|
||||
dataProjection: goog.isDefAndNotNull(options.dataProjection) ?
|
||||
options.dataProjection : this.defaultDataProjection
|
||||
options.dataProjection : this.defaultDataProjection,
|
||||
rightHanded: options.rightHanded
|
||||
};
|
||||
}
|
||||
return updatedOptions;
|
||||
|
||||
@@ -178,7 +178,8 @@ ol.format.GeoJSON.writeGeometry_ = function(geometry, opt_options) {
|
||||
var geometryWriter = ol.format.GeoJSON.GEOMETRY_WRITERS_[geometry.getType()];
|
||||
goog.asserts.assert(goog.isDef(geometryWriter));
|
||||
return geometryWriter(/** @type {ol.geom.Geometry} */ (
|
||||
ol.format.Feature.transformWithOptions(geometry, true, opt_options)));
|
||||
ol.format.Feature.transformWithOptions(geometry, true, opt_options)),
|
||||
opt_options);
|
||||
};
|
||||
|
||||
|
||||
@@ -217,10 +218,11 @@ ol.format.GeoJSON.writeGeometryCollectionGeometry_ = function(
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @private
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
ol.format.GeoJSON.writeLineStringGeometry_ = function(geometry) {
|
||||
ol.format.GeoJSON.writeLineStringGeometry_ = function(geometry, opt_options) {
|
||||
goog.asserts.assertInstanceof(geometry, ol.geom.LineString);
|
||||
return /** @type {GeoJSONGeometry} */ ({
|
||||
'type': 'LineString',
|
||||
@@ -231,10 +233,12 @@ ol.format.GeoJSON.writeLineStringGeometry_ = function(geometry) {
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @private
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
ol.format.GeoJSON.writeMultiLineStringGeometry_ = function(geometry) {
|
||||
ol.format.GeoJSON.writeMultiLineStringGeometry_ =
|
||||
function(geometry, opt_options) {
|
||||
goog.asserts.assertInstanceof(geometry, ol.geom.MultiLineString);
|
||||
goog.asserts.assert(
|
||||
geometry.getType() == ol.geom.GeometryType.MULTI_LINE_STRING);
|
||||
@@ -247,10 +251,11 @@ ol.format.GeoJSON.writeMultiLineStringGeometry_ = function(geometry) {
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @private
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
ol.format.GeoJSON.writeMultiPointGeometry_ = function(geometry) {
|
||||
ol.format.GeoJSON.writeMultiPointGeometry_ = function(geometry, opt_options) {
|
||||
goog.asserts.assertInstanceof(geometry, ol.geom.MultiPoint);
|
||||
return /** @type {GeoJSONGeometry} */ ({
|
||||
'type': 'MultiPoint',
|
||||
@@ -261,24 +266,30 @@ ol.format.GeoJSON.writeMultiPointGeometry_ = function(geometry) {
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @private
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
ol.format.GeoJSON.writeMultiPolygonGeometry_ = function(geometry) {
|
||||
ol.format.GeoJSON.writeMultiPolygonGeometry_ = function(geometry, opt_options) {
|
||||
goog.asserts.assertInstanceof(geometry, ol.geom.MultiPolygon);
|
||||
var right;
|
||||
if (goog.isDef(opt_options)) {
|
||||
right = opt_options.rightHanded;
|
||||
}
|
||||
return /** @type {GeoJSONGeometry} */ ({
|
||||
'type': 'MultiPolygon',
|
||||
'coordinates': geometry.getCoordinates()
|
||||
'coordinates': geometry.getCoordinates(right)
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @private
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
ol.format.GeoJSON.writePointGeometry_ = function(geometry) {
|
||||
ol.format.GeoJSON.writePointGeometry_ = function(geometry, opt_options) {
|
||||
goog.asserts.assertInstanceof(geometry, ol.geom.Point);
|
||||
return /** @type {GeoJSONGeometry} */ ({
|
||||
'type': 'Point',
|
||||
@@ -289,14 +300,19 @@ ol.format.GeoJSON.writePointGeometry_ = function(geometry) {
|
||||
|
||||
/**
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @param {olx.format.WriteOptions=} opt_options Write options.
|
||||
* @private
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
ol.format.GeoJSON.writePolygonGeometry_ = function(geometry) {
|
||||
ol.format.GeoJSON.writePolygonGeometry_ = function(geometry, opt_options) {
|
||||
goog.asserts.assertInstanceof(geometry, ol.geom.Polygon);
|
||||
var right;
|
||||
if (goog.isDef(opt_options)) {
|
||||
right = opt_options.rightHanded;
|
||||
}
|
||||
return /** @type {GeoJSONGeometry} */ ({
|
||||
'type': 'Polygon',
|
||||
'coordinates': geometry.getCoordinates()
|
||||
'coordinates': geometry.getCoordinates(right)
|
||||
});
|
||||
};
|
||||
|
||||
@@ -320,7 +336,7 @@ ol.format.GeoJSON.GEOMETRY_READERS_ = {
|
||||
/**
|
||||
* @const
|
||||
* @private
|
||||
* @type {Object.<string, function(ol.geom.Geometry): (GeoJSONGeometry|GeoJSONGeometryCollection)>}
|
||||
* @type {Object.<string, function(ol.geom.Geometry, olx.format.WriteOptions=): (GeoJSONGeometry|GeoJSONGeometryCollection)>}
|
||||
*/
|
||||
ol.format.GeoJSON.GEOMETRY_WRITERS_ = {
|
||||
'Point': ol.format.GeoJSON.writePointGeometry_,
|
||||
|
||||
@@ -558,6 +558,106 @@ describe('ol.format.GeoJSON', function() {
|
||||
format.readGeometry(geojson).getCoordinates());
|
||||
});
|
||||
|
||||
it('maintains coordinate order by default', function() {
|
||||
|
||||
var cw = [[-180, -90], [-180, 90], [180, 90], [180, -90], [-180, -90]];
|
||||
var ccw = [[-180, -90], [180, -90], [180, 90], [-180, 90], [-180, -90]];
|
||||
|
||||
var right = new ol.geom.Polygon([ccw, cw]);
|
||||
var rightMulti = new ol.geom.MultiPolygon([[ccw, cw]]);
|
||||
var left = new ol.geom.Polygon([cw, ccw]);
|
||||
var leftMulti = new ol.geom.MultiPolygon([[cw, ccw]]);
|
||||
|
||||
var rightObj = {
|
||||
type: 'Polygon',
|
||||
coordinates: [ccw, cw]
|
||||
};
|
||||
|
||||
var rightMultiObj = {
|
||||
type: 'MultiPolygon',
|
||||
coordinates: [[ccw, cw]]
|
||||
};
|
||||
|
||||
var leftObj = {
|
||||
type: 'Polygon',
|
||||
coordinates: [cw, ccw]
|
||||
};
|
||||
|
||||
var leftMultiObj = {
|
||||
type: 'MultiPolygon',
|
||||
coordinates: [[cw, ccw]]
|
||||
};
|
||||
|
||||
expect(JSON.parse(format.writeGeometry(right))).to.eql(rightObj);
|
||||
expect(
|
||||
JSON.parse(format.writeGeometry(rightMulti))).to.eql(rightMultiObj);
|
||||
expect(JSON.parse(format.writeGeometry(left))).to.eql(leftObj);
|
||||
expect(JSON.parse(format.writeGeometry(leftMulti))).to.eql(leftMultiObj);
|
||||
|
||||
});
|
||||
|
||||
it('allows serializing following the right-hand rule', function() {
|
||||
|
||||
var cw = [[-180, -90], [-180, 90], [180, 90], [180, -90], [-180, -90]];
|
||||
var ccw = [[-180, -90], [180, -90], [180, 90], [-180, 90], [-180, -90]];
|
||||
var right = new ol.geom.Polygon([ccw, cw]);
|
||||
var rightMulti = new ol.geom.MultiPolygon([[ccw, cw]]);
|
||||
var left = new ol.geom.Polygon([cw, ccw]);
|
||||
var leftMulti = new ol.geom.MultiPolygon([[cw, ccw]]);
|
||||
|
||||
var rightObj = {
|
||||
type: 'Polygon',
|
||||
coordinates: [ccw, cw]
|
||||
};
|
||||
|
||||
var rightMultiObj = {
|
||||
type: 'MultiPolygon',
|
||||
coordinates: [[ccw, cw]]
|
||||
};
|
||||
|
||||
var json = format.writeGeometry(right, {rightHanded: true});
|
||||
expect(JSON.parse(json)).to.eql(rightObj);
|
||||
json = format.writeGeometry(rightMulti, {rightHanded: true});
|
||||
expect(JSON.parse(json)).to.eql(rightMultiObj);
|
||||
|
||||
json = format.writeGeometry(left, {rightHanded: true});
|
||||
expect(JSON.parse(json)).to.eql(rightObj);
|
||||
json = format.writeGeometry(leftMulti, {rightHanded: true});
|
||||
expect(JSON.parse(json)).to.eql(rightMultiObj);
|
||||
|
||||
});
|
||||
|
||||
it('allows serializing following the left-hand rule', function() {
|
||||
|
||||
var cw = [[-180, -90], [-180, 90], [180, 90], [180, -90], [-180, -90]];
|
||||
var ccw = [[-180, -90], [180, -90], [180, 90], [-180, 90], [-180, -90]];
|
||||
var right = new ol.geom.Polygon([ccw, cw]);
|
||||
var rightMulti = new ol.geom.MultiPolygon([[ccw, cw]]);
|
||||
var left = new ol.geom.Polygon([cw, ccw]);
|
||||
var leftMulti = new ol.geom.MultiPolygon([[cw, ccw]]);
|
||||
|
||||
var leftObj = {
|
||||
type: 'Polygon',
|
||||
coordinates: [cw, ccw]
|
||||
};
|
||||
|
||||
var leftMultiObj = {
|
||||
type: 'MultiPolygon',
|
||||
coordinates: [[cw, ccw]]
|
||||
};
|
||||
|
||||
var json = format.writeGeometry(right, {rightHanded: false});
|
||||
expect(JSON.parse(json)).to.eql(leftObj);
|
||||
json = format.writeGeometry(rightMulti, {rightHanded: false});
|
||||
expect(JSON.parse(json)).to.eql(leftMultiObj);
|
||||
|
||||
json = format.writeGeometry(left, {rightHanded: false});
|
||||
expect(JSON.parse(json)).to.eql(leftObj);
|
||||
json = format.writeGeometry(leftMulti, {rightHanded: false});
|
||||
expect(JSON.parse(json)).to.eql(leftMultiObj);
|
||||
|
||||
});
|
||||
|
||||
it('encodes geometry collection', function() {
|
||||
var collection = new ol.geom.GeometryCollection([
|
||||
new ol.geom.Point([10, 20]),
|
||||
@@ -611,6 +711,7 @@ goog.require('ol.geom.Circle');
|
||||
goog.require('ol.geom.GeometryCollection');
|
||||
goog.require('ol.geom.LineString');
|
||||
goog.require('ol.geom.LinearRing');
|
||||
goog.require('ol.geom.MultiPolygon');
|
||||
goog.require('ol.geom.Point');
|
||||
goog.require('ol.geom.Polygon');
|
||||
goog.require('ol.proj');
|
||||
|
||||
Reference in New Issue
Block a user