Project

General

Profile

Download (9.17 KB) Statistics
| Branch: | Tag: | Revision:
1
/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
2
 * full list of contributors). Published under the 2-clause BSD license.
3
 * See license.txt in the OpenLayers distribution or repository for the
4
 * full text of the license. */
5

    
6
/**
7
 * @requires OpenLayers/Geometry/Collection.js
8
 * @requires OpenLayers/Geometry/LinearRing.js
9
 */
10

    
11
/**
12
 * Class: OpenLayers.Geometry.Polygon 
13
 * Polygon is a collection of Geometry.LinearRings. 
14
 * 
15
 * Inherits from:
16
 *  - <OpenLayers.Geometry.Collection> 
17
 *  - <OpenLayers.Geometry> 
18
 */
19
OpenLayers.Geometry.Polygon = OpenLayers.Class(
20
  OpenLayers.Geometry.Collection, {
21

    
22
    /**
23
     * Property: componentTypes
24
     * {Array(String)} An array of class names representing the types of
25
     * components that the collection can include.  A null value means the
26
     * component types are not restricted.
27
     */
28
    componentTypes: ["OpenLayers.Geometry.LinearRing"],
29

    
30
    /**
31
     * Constructor: OpenLayers.Geometry.Polygon
32
     * Constructor for a Polygon geometry. 
33
     * The first ring (this.component[0])is the outer bounds of the polygon and 
34
     * all subsequent rings (this.component[1-n]) are internal holes.
35
     *
36
     *
37
     * Parameters:
38
     * components - {Array(<OpenLayers.Geometry.LinearRing>)} 
39
     */
40

    
41
    /** 
42
     * APIMethod: getArea
43
     * Calculated by subtracting the areas of the internal holes from the 
44
     *   area of the outer hole.
45
     * 
46
     * Returns:
47
     * {float} The area of the geometry
48
     */
49
    getArea: function() {
50
        var area = 0.0;
51
        if ( this.components && (this.components.length > 0)) {
52
            area += Math.abs(this.components[0].getArea());
53
            for (var i=1, len=this.components.length; i<len; i++) {
54
                area -= Math.abs(this.components[i].getArea());
55
            }
56
        }
57
        return area;
58
    },
59

    
60
    /** 
61
     * APIMethod: getGeodesicArea
62
     * Calculate the approximate area of the polygon were it projected onto
63
     *     the earth.
64
     *
65
     * Parameters:
66
     * projection - {<OpenLayers.Projection>} The spatial reference system
67
     *     for the geometry coordinates.  If not provided, Geographic/WGS84 is
68
     *     assumed.
69
     * 
70
     * Reference:
71
     * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for
72
     *     Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion
73
     *     Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409
74
     *
75
     * Returns:
76
     * {float} The approximate geodesic area of the polygon in square meters.
77
     */
78
    getGeodesicArea: function(projection) {
79
        var area = 0.0;
80
        if(this.components && (this.components.length > 0)) {
81
            area += Math.abs(this.components[0].getGeodesicArea(projection));
82
            for(var i=1, len=this.components.length; i<len; i++) {
83
                area -= Math.abs(this.components[i].getGeodesicArea(projection));
84
            }
85
        }
86
        return area;
87
    },
88

    
89
    /**
90
     * Method: containsPoint
91
     * Test if a point is inside a polygon.  Points on a polygon edge are
92
     *     considered inside.
93
     *
94
     * Parameters:
95
     * point - {<OpenLayers.Geometry.Point>}
96
     *
97
     * Returns:
98
     * {Boolean | Number} The point is inside the polygon.  Returns 1 if the
99
     *     point is on an edge.  Returns boolean otherwise.
100
     */
101
    containsPoint: function(point) {
102
        var numRings = this.components.length;
103
        var contained = false;
104
        if(numRings > 0) {
105
            // check exterior ring - 1 means on edge, boolean otherwise
106
            contained = this.components[0].containsPoint(point);
107
            if(contained !== 1) {
108
                if(contained && numRings > 1) {
109
                    // check interior rings
110
                    var hole;
111
                    for(var i=1; i<numRings; ++i) {
112
                        hole = this.components[i].containsPoint(point);
113
                        if(hole) {
114
                            if(hole === 1) {
115
                                // on edge
116
                                contained = 1;
117
                            } else {
118
                                // in hole
119
                                contained = false;
120
                            }                            
121
                            break;
122
                        }
123
                    }
124
                }
125
            }
126
        }
127
        return contained;
128
    },
129

    
130
    /**
131
     * APIMethod: intersects
132
     * Determine if the input geometry intersects this one.
133
     *
134
     * Parameters:
135
     * geometry - {<OpenLayers.Geometry>} Any type of geometry.
136
     *
137
     * Returns:
138
     * {Boolean} The input geometry intersects this one.
139
     */
140
    intersects: function(geometry) {
141
        var intersect = false;
142
        var i, len;
143
        if(geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
144
            intersect = this.containsPoint(geometry);
145
        } else if(geometry.CLASS_NAME == "OpenLayers.Geometry.LineString" ||
146
                  geometry.CLASS_NAME == "OpenLayers.Geometry.LinearRing") {
147
            // check if rings/linestrings intersect
148
            for(i=0, len=this.components.length; i<len; ++i) {
149
                intersect = geometry.intersects(this.components[i]);
150
                if(intersect) {
151
                    break;
152
                }
153
            }
154
            if(!intersect) {
155
                // check if this poly contains points of the ring/linestring
156
                for(i=0, len=geometry.components.length; i<len; ++i) {
157
                    intersect = this.containsPoint(geometry.components[i]);
158
                    if(intersect) {
159
                        break;
160
                    }
161
                }
162
            }
163
        } else {
164
            for(i=0, len=geometry.components.length; i<len; ++ i) {
165
                intersect = this.intersects(geometry.components[i]);
166
                if(intersect) {
167
                    break;
168
                }
169
            }
170
        }
171
        // check case where this poly is wholly contained by another
172
        if(!intersect && geometry.CLASS_NAME == "OpenLayers.Geometry.Polygon") {
173
            // exterior ring points will be contained in the other geometry
174
            var ring = this.components[0];
175
            for(i=0, len=ring.components.length; i<len; ++i) {
176
                intersect = geometry.containsPoint(ring.components[i]);
177
                if(intersect) {
178
                    break;
179
                }
180
            }
181
        }
182
        return intersect;
183
    },
184

    
185
    /**
186
     * APIMethod: distanceTo
187
     * Calculate the closest distance between two geometries (on the x-y plane).
188
     *
189
     * Parameters:
190
     * geometry - {<OpenLayers.Geometry>} The target geometry.
191
     * options - {Object} Optional properties for configuring the distance
192
     *     calculation.
193
     *
194
     * Valid options:
195
     * details - {Boolean} Return details from the distance calculation.
196
     *     Default is false.
197
     * edge - {Boolean} Calculate the distance from this geometry to the
198
     *     nearest edge of the target geometry.  Default is true.  If true,
199
     *     calling distanceTo from a geometry that is wholly contained within
200
     *     the target will result in a non-zero distance.  If false, whenever
201
     *     geometries intersect, calling distanceTo will return 0.  If false,
202
     *     details cannot be returned.
203
     *
204
     * Returns:
205
     * {Number | Object} The distance between this geometry and the target.
206
     *     If details is true, the return will be an object with distance,
207
     *     x0, y0, x1, and y1 properties.  The x0 and y0 properties represent
208
     *     the coordinates of the closest point on this geometry. The x1 and y1
209
     *     properties represent the coordinates of the closest point on the
210
     *     target geometry.
211
     */
212
    distanceTo: function(geometry, options) {
213
        var edge = !(options && options.edge === false);
214
        var result;
215
        // this is the case where we might not be looking for distance to edge
216
        if(!edge && this.intersects(geometry)) {
217
            result = 0;
218
        } else {
219
            result = OpenLayers.Geometry.Collection.prototype.distanceTo.apply(
220
                this, [geometry, options]
221
            );
222
        }
223
        return result;
224
    },
225

    
226
    CLASS_NAME: "OpenLayers.Geometry.Polygon"
227
});
228

    
229
/**
230
 * APIMethod: createRegularPolygon
231
 * Create a regular polygon around a radius. Useful for creating circles 
232
 * and the like.
233
 *
234
 * Parameters:
235
 * origin - {<OpenLayers.Geometry.Point>} center of polygon.
236
 * radius - {Float} distance to vertex, in map units.
237
 * sides - {Integer} Number of sides. 20 approximates a circle.
238
 * rotation - {Float} original angle of rotation, in degrees.
239
 */
240
OpenLayers.Geometry.Polygon.createRegularPolygon = function(origin, radius, sides, rotation) {  
241
    var angle = Math.PI * ((1/sides) - (1/2));
242
    if(rotation) {
243
        angle += (rotation / 180) * Math.PI;
244
    }
245
    var rotatedAngle, x, y;
246
    var points = [];
247
    for(var i=0; i<sides; ++i) {
248
        rotatedAngle = angle + (i * 2 * Math.PI / sides);
249
        x = origin.x + (radius * Math.cos(rotatedAngle));
250
        y = origin.y + (radius * Math.sin(rotatedAngle));
251
        points.push(new OpenLayers.Geometry.Point(x, y));
252
    }
253
    var ring = new OpenLayers.Geometry.LinearRing(points);
254
    return new OpenLayers.Geometry.Polygon([ring]);
255
};
(9-9/9)