Merge pull request #3401 from tschaub/geojson-orientation
Allow GeoJSON to be serialized according to the right-hand rule.
This commit is contained in:
@@ -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_,
|
||||
|
||||
@@ -29,22 +29,34 @@ ol.geom.flat.orient.linearRingIsClockwise =
|
||||
|
||||
|
||||
/**
|
||||
* Determines if linear rings are oriented. By default, left-hand orientation
|
||||
* is tested (first ring must be clockwise, remaining rings counter-clockwise).
|
||||
* To test for right-hand orientation, use the `opt_right` argument.
|
||||
*
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<number>} ends Ends.
|
||||
* @param {Array.<number>} ends Array of end indexes.
|
||||
* @param {number} stride Stride.
|
||||
* @return {boolean} `true` if all rings are correctly oriented, `false`
|
||||
* otherwise.
|
||||
* @param {boolean=} opt_right Test for right-hand orientation
|
||||
* (counter-clockwise exterior ring and clockwise interior rings).
|
||||
* @return {boolean} Rings are correctly oriented.
|
||||
*/
|
||||
ol.geom.flat.orient.linearRingsAreOriented =
|
||||
function(flatCoordinates, offset, ends, stride) {
|
||||
function(flatCoordinates, offset, ends, stride, opt_right) {
|
||||
var right = goog.isDef(opt_right) ? opt_right : false;
|
||||
var i, ii;
|
||||
for (i = 0, ii = ends.length; i < ii; ++i) {
|
||||
var end = ends[i];
|
||||
var isClockwise = ol.geom.flat.orient.linearRingIsClockwise(
|
||||
flatCoordinates, offset, end, stride);
|
||||
if (i === 0 ? !isClockwise : isClockwise) {
|
||||
return false;
|
||||
if (i === 0) {
|
||||
if ((right && isClockwise) || (!right && !isClockwise)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if ((right && !isClockwise) || (!right && isClockwise)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
offset = end;
|
||||
}
|
||||
@@ -53,19 +65,24 @@ ol.geom.flat.orient.linearRingsAreOriented =
|
||||
|
||||
|
||||
/**
|
||||
* Determines if linear rings are oriented. By default, left-hand orientation
|
||||
* is tested (first ring must be clockwise, remaining rings counter-clockwise).
|
||||
* To test for right-hand orientation, use the `opt_right` argument.
|
||||
*
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<Array.<number>>} endss Endss.
|
||||
* @param {Array.<Array.<number>>} endss Array of array of end indexes.
|
||||
* @param {number} stride Stride.
|
||||
* @return {boolean} `true` if all rings are correctly oriented, `false`
|
||||
* otherwise.
|
||||
* @param {boolean=} opt_right Test for right-hand orientation
|
||||
* (counter-clockwise exterior ring and clockwise interior rings).
|
||||
* @return {boolean} Rings are correctly oriented.
|
||||
*/
|
||||
ol.geom.flat.linearRingssAreOriented =
|
||||
function(flatCoordinates, offset, endss, stride) {
|
||||
ol.geom.flat.orient.linearRingssAreOriented =
|
||||
function(flatCoordinates, offset, endss, stride, opt_right) {
|
||||
var i, ii;
|
||||
for (i = 0, ii = endss.length; i < ii; ++i) {
|
||||
if (!ol.geom.flat.orient.linearRingsAreOriented(
|
||||
flatCoordinates, offset, endss[i], stride)) {
|
||||
flatCoordinates, offset, endss[i], stride, opt_right)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -74,20 +91,29 @@ ol.geom.flat.linearRingssAreOriented =
|
||||
|
||||
|
||||
/**
|
||||
* Orient coordinates in a flat array of linear rings. By default, rings
|
||||
* are oriented following the left-hand rule (clockwise for exterior and
|
||||
* counter-clockwise for interior rings). To orient according to the
|
||||
* right-hand rule, use the `opt_right` argument.
|
||||
*
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<number>} ends Ends.
|
||||
* @param {number} stride Stride.
|
||||
* @param {boolean=} opt_right Follow the right-hand rule for orientation.
|
||||
* @return {number} End.
|
||||
*/
|
||||
ol.geom.flat.orient.orientLinearRings =
|
||||
function(flatCoordinates, offset, ends, stride) {
|
||||
function(flatCoordinates, offset, ends, stride, opt_right) {
|
||||
var right = goog.isDef(opt_right) ? opt_right : false;
|
||||
var i, ii;
|
||||
for (i = 0, ii = ends.length; i < ii; ++i) {
|
||||
var end = ends[i];
|
||||
var isClockwise = ol.geom.flat.orient.linearRingIsClockwise(
|
||||
flatCoordinates, offset, end, stride);
|
||||
var reverse = i === 0 ? !isClockwise : isClockwise;
|
||||
var reverse = i === 0 ?
|
||||
(right && isClockwise) || (!right && !isClockwise) :
|
||||
(right && !isClockwise) || (!right && isClockwise);
|
||||
if (reverse) {
|
||||
ol.geom.flat.reverse.coordinates(flatCoordinates, offset, end, stride);
|
||||
}
|
||||
@@ -98,18 +124,24 @@ ol.geom.flat.orient.orientLinearRings =
|
||||
|
||||
|
||||
/**
|
||||
* Orient coordinates in a flat array of linear rings. By default, rings
|
||||
* are oriented following the left-hand rule (clockwise for exterior and
|
||||
* counter-clockwise for interior rings). To orient according to the
|
||||
* right-hand rule, use the `opt_right` argument.
|
||||
*
|
||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {Array.<Array.<number>>} endss Endss.
|
||||
* @param {Array.<Array.<number>>} endss Array of array of end indexes.
|
||||
* @param {number} stride Stride.
|
||||
* @param {boolean=} opt_right Follow the right-hand rule for orientation.
|
||||
* @return {number} End.
|
||||
*/
|
||||
ol.geom.flat.orient.orientLinearRingss =
|
||||
function(flatCoordinates, offset, endss, stride) {
|
||||
function(flatCoordinates, offset, endss, stride, opt_right) {
|
||||
var i, ii;
|
||||
for (i = 0, ii = endss.length; i < ii; ++i) {
|
||||
offset = ol.geom.flat.orient.orientLinearRings(
|
||||
flatCoordinates, offset, endss[i], stride);
|
||||
flatCoordinates, offset, endss[i], stride, opt_right);
|
||||
}
|
||||
return offset;
|
||||
};
|
||||
|
||||
@@ -162,12 +162,30 @@ ol.geom.MultiPolygon.prototype.getArea = function() {
|
||||
|
||||
|
||||
/**
|
||||
* Get the coordinate array for this geometry. This array has the structure
|
||||
* of a GeoJSON coordinate array for multi-polygons.
|
||||
*
|
||||
* @param {boolean=} opt_right Orient coordinates according to the right-hand
|
||||
* rule (counter-clockwise for exterior and clockwise for interior rings).
|
||||
* If `false`, coordinates will be oriented according to the left-hand rule
|
||||
* (clockwise for exterior and counter-clockwise for interior rings).
|
||||
* By default, coordinate orientation will depend on how the geometry was
|
||||
* constructed.
|
||||
* @return {Array.<Array.<Array.<ol.Coordinate>>>} Coordinates.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.MultiPolygon.prototype.getCoordinates = function() {
|
||||
ol.geom.MultiPolygon.prototype.getCoordinates = function(opt_right) {
|
||||
var flatCoordinates;
|
||||
if (goog.isDef(opt_right)) {
|
||||
flatCoordinates = this.getOrientedFlatCoordinates().slice();
|
||||
ol.geom.flat.orient.orientLinearRingss(
|
||||
flatCoordinates, 0, this.endss_, this.stride, opt_right);
|
||||
} else {
|
||||
flatCoordinates = this.flatCoordinates;
|
||||
}
|
||||
|
||||
return ol.geom.flat.inflate.coordinatesss(
|
||||
this.flatCoordinates, 0, this.endss_, this.stride);
|
||||
flatCoordinates, 0, this.endss_, this.stride);
|
||||
};
|
||||
|
||||
|
||||
@@ -213,7 +231,7 @@ ol.geom.MultiPolygon.prototype.getInteriorPoints = function() {
|
||||
ol.geom.MultiPolygon.prototype.getOrientedFlatCoordinates = function() {
|
||||
if (this.orientedRevision_ != this.getRevision()) {
|
||||
var flatCoordinates = this.flatCoordinates;
|
||||
if (ol.geom.flat.linearRingssAreOriented(
|
||||
if (ol.geom.flat.orient.linearRingssAreOriented(
|
||||
flatCoordinates, 0, this.endss_, this.stride)) {
|
||||
this.orientedFlatCoordinates_ = flatCoordinates;
|
||||
} else {
|
||||
|
||||
@@ -151,12 +151,30 @@ ol.geom.Polygon.prototype.getArea = function() {
|
||||
|
||||
|
||||
/**
|
||||
* Get the coordinate array for this geometry. This array has the structure
|
||||
* of a GeoJSON coordinate array for polygons.
|
||||
*
|
||||
* @param {boolean=} opt_right Orient coordinates according to the right-hand
|
||||
* rule (counter-clockwise for exterior and clockwise for interior rings).
|
||||
* If `false`, coordinates will be oriented according to the left-hand rule
|
||||
* (clockwise for exterior and counter-clockwise for interior rings).
|
||||
* By default, coordinate orientation will depend on how the geometry was
|
||||
* constructed.
|
||||
* @return {Array.<Array.<ol.Coordinate>>} Coordinates.
|
||||
* @api stable
|
||||
*/
|
||||
ol.geom.Polygon.prototype.getCoordinates = function() {
|
||||
ol.geom.Polygon.prototype.getCoordinates = function(opt_right) {
|
||||
var flatCoordinates;
|
||||
if (goog.isDef(opt_right)) {
|
||||
flatCoordinates = this.getOrientedFlatCoordinates().slice();
|
||||
ol.geom.flat.orient.orientLinearRings(
|
||||
flatCoordinates, 0, this.ends_, this.stride, opt_right);
|
||||
} else {
|
||||
flatCoordinates = this.flatCoordinates;
|
||||
}
|
||||
|
||||
return ol.geom.flat.inflate.coordinatess(
|
||||
this.flatCoordinates, 0, this.ends_, this.stride);
|
||||
flatCoordinates, 0, this.ends_, this.stride);
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user