diff --git a/src/ol/geom/polygon.js b/src/ol/geom/polygon.js index 4a8d3b6ac8..4d113ed4e3 100644 --- a/src/ol/geom/polygon.js +++ b/src/ol/geom/polygon.js @@ -2,6 +2,7 @@ goog.provide('ol.geom.Polygon'); goog.require('goog.array'); goog.require('goog.asserts'); +goog.require('goog.math'); goog.require('ol.extent'); goog.require('ol.geom.GeometryLayout'); goog.require('ol.geom.GeometryType'); @@ -422,3 +423,52 @@ ol.geom.Polygon.fromExtent = function(extent) { ol.geom.GeometryLayout.XY, flatCoordinates, [flatCoordinates.length]); return polygon; }; + + +/** + * Create a regular polygon from a circle. + * @param {ol.geom.Circle} circle Circle geometry. + * @param {number=} opt_sides Number of sides of the polygon. Default is 32. + * @param {number=} opt_angle Start angle for the first vertex of the polygon in + * radians. Default is 0. + * @return {ol.geom.Polygon} Polygon geometry. + */ +ol.geom.Polygon.fromCircle = function(circle, opt_sides, opt_angle) { + var sides = goog.isDef(opt_sides) ? opt_sides : 32; + var stride = circle.getStride(); + var layout = circle.getLayout(); + var polygon = new ol.geom.Polygon(null, layout); + var flatCoordinates = goog.array.repeat(0, stride * (sides + 1)); + var ends = [flatCoordinates.length]; + polygon.setFlatCoordinates(layout, flatCoordinates, ends); + ol.geom.Polygon.makeRegular( + polygon, circle.getCenter(), circle.getRadius(), opt_angle); + return polygon; +}; + + +/** + * Modify the coordinates of a polygon to make it a regular polygon. + * @param {ol.geom.Polygon} polygon Polygon geometry. + * @param {ol.Coordinate} center Center of the regular polygon. + * @param {number} radius Radius of the regular polygon. + * @param {number=} opt_angle Start angle for the first vertex of the polygon in + * radians. Default is 0. + */ +ol.geom.Polygon.makeRegular = function(polygon, center, radius, opt_angle) { + var flatCoordinates = polygon.getFlatCoordinates(); + var layout = polygon.getLayout(); + var stride = polygon.getStride(); + var ends = polygon.getEnds(); + goog.asserts.assert(ends.length === 1, 'only 1 ring is supported'); + var sides = flatCoordinates.length / stride - 1; + var startAngle = goog.isDef(opt_angle) ? opt_angle : 0; + var angle, coord, offset; + for (var i = 0; i <= sides; ++i) { + offset = i * stride; + angle = startAngle + (goog.math.modulo(i, sides) * 2 * Math.PI / sides); + flatCoordinates[offset] = center[0] + (radius * Math.cos(angle)); + flatCoordinates[offset + 1] = center[1] + (radius * Math.sin(angle)); + } + polygon.setFlatCoordinates(layout, flatCoordinates, ends); +}; diff --git a/test/spec/ol/geom/polygon.test.js b/test/spec/ol/geom/polygon.test.js index 25e99faf1b..2b42111f91 100644 --- a/test/spec/ol/geom/polygon.test.js +++ b/test/spec/ol/geom/polygon.test.js @@ -436,10 +436,44 @@ describe('ol.geom.Polygon', function() { }); }); + describe('ol.geom.Polygon.fromCircle', function() { + + it('creates a regular polygon', function() { + var circle = new ol.geom.Circle([0, 0, 0], 1, ol.geom.GeometryLayout.XYZ); + var polygon = ol.geom.Polygon.fromCircle(circle); + var coordinates = polygon.getLinearRing(0).getCoordinates(); + expect(coordinates[0].length).to.eql(3); + expect(coordinates[0][2]).to.eql(0); + expect(coordinates[32]).to.eql(coordinates[0]); + // east + expect(coordinates[0][0]).to.roughlyEqual(1, 1e-9); + expect(coordinates[0][1]).to.roughlyEqual(0, 1e-9); + // south + expect(coordinates[8][0]).to.roughlyEqual(0, 1e-9); + expect(coordinates[8][1]).to.roughlyEqual(1, 1e-9); + // west + expect(coordinates[16][0]).to.roughlyEqual(-1, 1e-9); + expect(coordinates[16][1]).to.roughlyEqual(0, 1e-9); + // north + expect(coordinates[24][0]).to.roughlyEqual(0, 1e-9); + expect(coordinates[24][1]).to.roughlyEqual(-1, 1e-9); + }); + + it('creates a regular polygon with custom sides and angle', function() { + var circle = new ol.geom.Circle([0, 0], 1); + var polygon = ol.geom.Polygon.fromCircle(circle, 4, Math.PI / 2); + var coordinates = polygon.getLinearRing(0).getCoordinates(); + expect(coordinates[4]).to.eql(coordinates[0]); + expect(coordinates[0][0]).to.roughlyEqual(0, 1e-9); + expect(coordinates[0][1]).to.roughlyEqual(1, 1e-9); + }); + }); + }); goog.require('ol.extent'); +goog.require('ol.geom.Circle'); goog.require('ol.geom.GeometryLayout'); goog.require('ol.geom.LinearRing'); goog.require('ol.geom.Polygon');