Add method to determine winding order of linear rings

This commit is contained in:
Tim Schaub
2013-06-24 17:43:22 -06:00
parent d1eec80324
commit e292d8fa12
2 changed files with 71 additions and 0 deletions

View File

@@ -27,6 +27,42 @@ ol.geom.LinearRing = function(coordinates, opt_shared) {
goog.inherits(ol.geom.LinearRing, ol.geom.LineString);
/**
* Determine of a vertex array representing a linear ring is in clockwise
* order.
*
* This method comes from Green's Theorem and was mentioned in an answer to a
* a Stack Overflow question (http://tinyurl.com/clockwise-method).
*
* Note that calculating the cross product for each pair of edges could be
* avoided by first finding the lowest, rightmost vertex. See OGR's
* implementation for an example of this.
* https://github.com/OSGeo/gdal/blob/trunk/gdal/ogr/ogrlinearring.cpp
*
* @param {ol.geom.VertexArray} coordinates Linear ring coordinates.
* @return {boolean} The coordinates are in clockwise order.
*/
ol.geom.LinearRing.isClockwise = function(coordinates) {
var length = coordinates.length;
var edge = 0;
var last = coordinates[length - 1];
var x1 = last[0];
var y1 = last[1];
var x2, y2, coord;
for (var i = 0; i < length; ++i) {
coord = coordinates[i];
x2 = coord[0];
y2 = coord[1];
edge += (x2 - x1) * (y2 + y1);
x1 = x2;
y1 = y2;
}
return edge > 0;
};
/**
* @inheritDoc
*/

View File

@@ -108,4 +108,39 @@ describe('ol.geom.LinearRing', function() {
});
describe('ol.geom.LinearRing.isClockwise()', function() {
var isClockwise = ol.geom.LinearRing.isClockwise;
it('returns true for clockwise coordinates', function() {
var coordinates = [
[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]
];
expect(isClockwise(coordinates)).to.be(true);
});
it('returns false for counter-clockwise coordinates', function() {
var coordinates = [
[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]
];
expect(isClockwise(coordinates)).to.be(false);
});
it('returns true for mostly clockwise, self-intersecting ring', function() {
var coordinates = [
[0, 0], [0, 1], [1.5, 1], [1.5, 1.5], [1, 1.5], [1, 0], [0, 0]
];
expect(isClockwise(coordinates)).to.be(true);
});
it('returns false for mostly counter-clockwise, intersecting', function() {
var coordinates = [
[0, 0], [1, 0], [1, 1.5], [1.5, 1.5], [1.5, 1], [0, 1], [0, 0]
];
expect(isClockwise(coordinates)).to.be(false);
});
});
goog.require('ol.geom.LinearRing');