diff --git a/lib/OpenLayers/Geometry/LinearRing.js b/lib/OpenLayers/Geometry/LinearRing.js index e5d3a89d29..21b5375654 100644 --- a/lib/OpenLayers/Geometry/LinearRing.js +++ b/lib/OpenLayers/Geometry/LinearRing.js @@ -198,15 +198,26 @@ OpenLayers.Geometry.LinearRing = OpenLayers.Class( } else if (len > 2) { var sumX = 0.0; var sumY = 0.0; - for (var i = 0; i < this.components.length - 1; i++) { - var b = this.components[i]; - var c = this.components[i+1]; - sumX += (b.x + c.x) * (b.x * c.y - c.x * b.y); - sumY += (b.y + c.y) * (b.x * c.y - c.x * b.y); - } + var x0 = this.components[0].x; + var y0 = this.components[0].y; var area = -1 * this.getArea(); - var x = sumX / (6 * area); - var y = sumY / (6 * area); + if (area != 0) { + for (var i = 0; i < len - 1; i++) { + var b = this.components[i]; + var c = this.components[i+1]; + sumX += (b.x + c.x - 2 * x0) * ((b.x - x0) * (c.y - y0) - (c.x - x0) * (b.y - y0)); + sumY += (b.y + c.y - 2 * y0) * ((b.x - x0) * (c.y - y0) - (c.x - x0) * (b.y - y0)); + } + var x = x0 + sumX / (6 * area); + var y = y0 + sumY / (6 * area); + } else { + for (var i = 0; i < len - 1; i++) { + sumX += this.components[i].x; + sumY += this.components[i].y; + } + var x = sumX / (len - 1); + var y = sumY / (len - 1); + } return new OpenLayers.Geometry.Point(x, y); } else { return null; diff --git a/tests/Geometry/Polygon.html b/tests/Geometry/Polygon.html index e28484d36e..0df0295d4b 100644 --- a/tests/Geometry/Polygon.html +++ b/tests/Geometry/Polygon.html @@ -386,18 +386,30 @@ } - function testGetCentroid(t) { - t.plan(4); + function test_getCentroid(t) { + t.plan(5); var bounds = new OpenLayers.Bounds(5, 10, 5, 10); var geometry = bounds.toGeometry(); var centroid = geometry.getCentroid(); t.eq(geometry.components[0].components.length, 2, "only two vertices since the box has left=right and bottom=top"); t.ok(centroid && centroid.x === 5 && centroid.y === 10, "getCentroid returns a point geometry even if the ring of the polygon has only 2 vertices"); - bounds = new OpenLayers.Bounds(0, 0, 10, 10); + bounds = new OpenLayers.Bounds(123456789.0, 123456789.0, 123456789.1, 123456789.1); geometry = bounds.toGeometry(); centroid = geometry.getCentroid(); t.eq(geometry.components[0].components.length, 5, "five vertices expected"); - t.ok(centroid && centroid.x === 5 && centroid.y === 5, "getCentroid returns the correct point geometry"); + var dX = Math.abs(centroid.x - 123456789.05); + var dY = Math.abs(centroid.y - 123456789.05); + t.ok(centroid && dX < 0.0001 && dY < 0.0001, " getCentroid returns the correct point geometry dX = " + dX + ", dY = " + dY); + + var components = [ + new OpenLayers.Geometry.Point(0,0), new OpenLayers.Geometry.Point(1,1), + new OpenLayers.Geometry.Point(0,1), new OpenLayers.Geometry.Point(1,0)]; + var linearRing = new OpenLayers.Geometry.LinearRing(components); + polygon = new OpenLayers.Geometry.Polygon([linearRing.clone()]); + centroid = polygon.getCentroid(); + var tX = centroid.x; + var tY = centroid.y; + t.ok( !isNaN(tX) && !isNaN(tY) && tX !== Infinity && tY !== Infinity, " getCentroid for wrong polygon works x = " + tX + ", y = " + tY); }