| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- /* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the Clear BSD license.
- * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
- * full text of the license. */
- /**
- * @requires OpenLayers/Geometry/Collection.js
- * @requires OpenLayers/Geometry/LinearRing.js
- */
- /**
- * Class: OpenLayers.Geometry.Polygon
- * Polygon is a collection of Geometry.LinearRings.
- *
- * Inherits from:
- * - <OpenLayers.Geometry.Collection>
- * - <OpenLayers.Geometry>
- */
- OpenLayers.Geometry.Polygon = OpenLayers.Class(
- OpenLayers.Geometry.Collection, {
- /**
- * Property: componentTypes
- * {Array(String)} An array of class names representing the types of
- * components that the collection can include. A null value means the
- * component types are not restricted.
- */
- componentTypes: ["OpenLayers.Geometry.LinearRing"],
- /**
- * Constructor: OpenLayers.Geometry.Polygon
- * Constructor for a Polygon geometry.
- * The first ring (this.component[0])is the outer bounds of the polygon and
- * all subsequent rings (this.component[1-n]) are internal holes.
- *
- *
- * Parameters:
- * components - {Array(<OpenLayers.Geometry.LinearRing>)}
- */
- initialize: function(components) {
- OpenLayers.Geometry.Collection.prototype.initialize.apply(this,
- arguments);
- },
-
- /**
- * APIMethod: getArea
- * Calculated by subtracting the areas of the internal holes from the
- * area of the outer hole.
- *
- * Returns:
- * {float} The area of the geometry
- */
- getArea: function() {
- var area = 0.0;
- if ( this.components && (this.components.length > 0)) {
- area += Math.abs(this.components[0].getArea());
- for (var i=1, len=this.components.length; i<len; i++) {
- area -= Math.abs(this.components[i].getArea());
- }
- }
- return area;
- },
- /**
- * APIMethod: getGeodesicArea
- * Calculate the approximate area of the polygon were it projected onto
- * the earth.
- *
- * Parameters:
- * projection - {<OpenLayers.Projection>} The spatial reference system
- * for the geometry coordinates. If not provided, Geographic/WGS84 is
- * assumed.
- *
- * Reference:
- * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for
- * Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion
- * Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409
- *
- * Returns:
- * {float} The approximate geodesic area of the polygon in square meters.
- */
- getGeodesicArea: function(projection) {
- var area = 0.0;
- if(this.components && (this.components.length > 0)) {
- area += Math.abs(this.components[0].getGeodesicArea(projection));
- for(var i=1, len=this.components.length; i<len; i++) {
- area -= Math.abs(this.components[i].getGeodesicArea(projection));
- }
- }
- return area;
- },
- /**
- * Method: containsPoint
- * Test if a point is inside a polygon. Points on a polygon edge are
- * considered inside.
- *
- * Parameters:
- * point - {<OpenLayers.Geometry.Point>}
- *
- * Returns:
- * {Boolean | Number} The point is inside the polygon. Returns 1 if the
- * point is on an edge. Returns boolean otherwise.
- */
- containsPoint: function(point) {
- var numRings = this.components.length;
- var contained = false;
- if(numRings > 0) {
- // check exterior ring - 1 means on edge, boolean otherwise
- contained = this.components[0].containsPoint(point);
- if(contained !== 1) {
- if(contained && numRings > 1) {
- // check interior rings
- var hole;
- for(var i=1; i<numRings; ++i) {
- hole = this.components[i].containsPoint(point);
- if(hole) {
- if(hole === 1) {
- // on edge
- contained = 1;
- } else {
- // in hole
- contained = false;
- }
- break;
- }
- }
- }
- }
- }
- return contained;
- },
- /**
- * APIMethod: intersects
- * Determine if the input geometry intersects this one.
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>} Any type of geometry.
- *
- * Returns:
- * {Boolean} The input geometry intersects this one.
- */
- intersects: function(geometry) {
- var intersect = false;
- var i, len;
- if(geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
- intersect = this.containsPoint(geometry);
- } else if(geometry.CLASS_NAME == "OpenLayers.Geometry.LineString" ||
- geometry.CLASS_NAME == "OpenLayers.Geometry.LinearRing") {
- // check if rings/linestrings intersect
- for(i=0, len=this.components.length; i<len; ++i) {
- intersect = geometry.intersects(this.components[i]);
- if(intersect) {
- break;
- }
- }
- if(!intersect) {
- // check if this poly contains points of the ring/linestring
- for(i=0, len=geometry.components.length; i<len; ++i) {
- intersect = this.containsPoint(geometry.components[i]);
- if(intersect) {
- break;
- }
- }
- }
- } else {
- for(i=0, len=geometry.components.length; i<len; ++ i) {
- intersect = this.intersects(geometry.components[i]);
- if(intersect) {
- break;
- }
- }
- }
- // check case where this poly is wholly contained by another
- if(!intersect && geometry.CLASS_NAME == "OpenLayers.Geometry.Polygon") {
- // exterior ring points will be contained in the other geometry
- var ring = this.components[0];
- for(i=0, len=ring.components.length; i<len; ++i) {
- intersect = geometry.containsPoint(ring.components[i]);
- if(intersect) {
- break;
- }
- }
- }
- return intersect;
- },
- /**
- * APIMethod: distanceTo
- * Calculate the closest distance between two geometries (on the x-y plane).
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>} The target geometry.
- * options - {Object} Optional properties for configuring the distance
- * calculation.
- *
- * Valid options:
- * details - {Boolean} Return details from the distance calculation.
- * Default is false.
- * edge - {Boolean} Calculate the distance from this geometry to the
- * nearest edge of the target geometry. Default is true. If true,
- * calling distanceTo from a geometry that is wholly contained within
- * the target will result in a non-zero distance. If false, whenever
- * geometries intersect, calling distanceTo will return 0. If false,
- * details cannot be returned.
- *
- * Returns:
- * {Number | Object} The distance between this geometry and the target.
- * If details is true, the return will be an object with distance,
- * x0, y0, x1, and y1 properties. The x0 and y0 properties represent
- * the coordinates of the closest point on this geometry. The x1 and y1
- * properties represent the coordinates of the closest point on the
- * target geometry.
- */
- distanceTo: function(geometry, options) {
- var edge = !(options && options.edge === false);
- var result;
- // this is the case where we might not be looking for distance to edge
- if(!edge && this.intersects(geometry)) {
- result = 0;
- } else {
- result = OpenLayers.Geometry.Collection.prototype.distanceTo.apply(
- this, [geometry, options]
- );
- }
- return result;
- },
- CLASS_NAME: "OpenLayers.Geometry.Polygon"
- });
- /**
- * APIMethod: createRegularPolygon
- * Create a regular polygon around a radius. Useful for creating circles
- * and the like.
- *
- * Parameters:
- * origin - {<OpenLayers.Geometry.Point>} center of polygon.
- * radius - {Float} distance to vertex, in map units.
- * sides - {Integer} Number of sides. 20 approximates a circle.
- * rotation - {Float} original angle of rotation, in degrees.
- */
- OpenLayers.Geometry.Polygon.createRegularPolygon = function(origin, radius, sides, rotation) {
- var angle = Math.PI * ((1/sides) - (1/2));
- if(rotation) {
- angle += (rotation / 180) * Math.PI;
- }
- var rotatedAngle, x, y;
- var points = [];
- for(var i=0; i<sides; ++i) {
- rotatedAngle = angle + (i * 2 * Math.PI / sides);
- x = origin.x + (radius * Math.cos(rotatedAngle));
- y = origin.y + (radius * Math.sin(rotatedAngle));
- points.push(new OpenLayers.Geometry.Point(x, y));
- }
- var ring = new OpenLayers.Geometry.LinearRing(points);
- return new OpenLayers.Geometry.Polygon([ring]);
- };
|