Bienvenue sur PostGIS.fr

Bienvenue sur PostGIS.fr , le site de la communauté des utilisateurs francophones de PostGIS.

PostGIS ajoute le support d'objets géographique à la base de données PostgreSQL. En effet, PostGIS "spatialise" le serverur PostgreSQL, ce qui permet de l'utiliser comme une base de données SIG.

Maintenu à jour, en fonction de nos disponibilités et des diverses sorties des outils que nous testons, nous vous proposons l'ensemble de nos travaux publiés en langue française.

source: trunk/workshop-routing-foss4g/web/OpenLayers/lib/OpenLayers/Geometry/LinearRing.js @ 76

Revision 76, 14.7 KB checked in by djay, 12 years ago (diff)

Ajout du répertoire web

  • Property svn:executable set to *
Line 
1/* Copyright (c) 2006-2010 by OpenLayers Contributors (see authors.txt for
2 * full list of contributors). Published under the Clear BSD license. 
3 * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
4 * full text of the license. */
5
6/**
7 * @requires OpenLayers/Geometry/LineString.js
8 */
9
10/**
11 * Class: OpenLayers.Geometry.LinearRing
12 *
13 * A Linear Ring is a special LineString which is closed. It closes itself
14 * automatically on every addPoint/removePoint by adding a copy of the first
15 * point as the last point.
16 *
17 * Also, as it is the first in the line family to close itself, a getArea()
18 * function is defined to calculate the enclosed area of the linearRing
19 *
20 * Inherits:
21 *  - <OpenLayers.Geometry.LineString>
22 */
23OpenLayers.Geometry.LinearRing = OpenLayers.Class(
24  OpenLayers.Geometry.LineString, {
25
26    /**
27     * Property: componentTypes
28     * {Array(String)} An array of class names representing the types of
29     *                 components that the collection can include.  A null
30     *                 value means the component types are not restricted.
31     */
32    componentTypes: ["OpenLayers.Geometry.Point"],
33
34    /**
35     * Constructor: OpenLayers.Geometry.LinearRing
36     * Linear rings are constructed with an array of points.  This array
37     *     can represent a closed or open ring.  If the ring is open (the last
38     *     point does not equal the first point), the constructor will close
39     *     the ring.  If the ring is already closed (the last point does equal
40     *     the first point), it will be left closed.
41     *
42     * Parameters:
43     * points - {Array(<OpenLayers.Geometry.Point>)} points
44     */
45    initialize: function(points) {
46        OpenLayers.Geometry.LineString.prototype.initialize.apply(this, 
47                                                                  arguments);
48    },
49
50    /**
51     * APIMethod: addComponent
52     * Adds a point to geometry components.  If the point is to be added to
53     *     the end of the components array and it is the same as the last point
54     *     already in that array, the duplicate point is not added.  This has
55     *     the effect of closing the ring if it is not already closed, and
56     *     doing the right thing if it is already closed.  This behavior can
57     *     be overridden by calling the method with a non-null index as the
58     *     second argument.
59     *
60     * Parameter:
61     * point - {<OpenLayers.Geometry.Point>}
62     * index - {Integer} Index into the array to insert the component
63     *
64     * Returns:
65     * {Boolean} Was the Point successfully added?
66     */
67    addComponent: function(point, index) {
68        var added = false;
69
70        //remove last point
71        var lastPoint = this.components.pop();
72
73        // given an index, add the point
74        // without an index only add non-duplicate points
75        if(index != null || !point.equals(lastPoint)) {
76            added = OpenLayers.Geometry.Collection.prototype.addComponent.apply(this, 
77                                                                    arguments);
78        }
79
80        //append copy of first point
81        var firstPoint = this.components[0];
82        OpenLayers.Geometry.Collection.prototype.addComponent.apply(this, 
83                                                                [firstPoint]);
84       
85        return added;
86    },
87   
88    /**
89     * APIMethod: removeComponent
90     * Removes a point from geometry components.
91     *
92     * Parameters:
93     * point - {<OpenLayers.Geometry.Point>}
94     */
95    removeComponent: function(point) {
96        if (this.components.length > 4) {
97
98            //remove last point
99            this.components.pop();
100           
101            //remove our point
102            OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this, 
103                                                                    arguments);
104            //append copy of first point
105            var firstPoint = this.components[0];
106            OpenLayers.Geometry.Collection.prototype.addComponent.apply(this, 
107                                                                [firstPoint]);
108        }
109    },
110   
111    /**
112     * APIMethod: move
113     * Moves a geometry by the given displacement along positive x and y axes.
114     *     This modifies the position of the geometry and clears the cached
115     *     bounds.
116     *
117     * Parameters:
118     * x - {Float} Distance to move geometry in positive x direction.
119     * y - {Float} Distance to move geometry in positive y direction.
120     */
121    move: function(x, y) {
122        for(var i = 0, len=this.components.length; i<len - 1; i++) {
123            this.components[i].move(x, y);
124        }
125    },
126
127    /**
128     * APIMethod: rotate
129     * Rotate a geometry around some origin
130     *
131     * Parameters:
132     * angle - {Float} Rotation angle in degrees (measured counterclockwise
133     *                 from the positive x-axis)
134     * origin - {<OpenLayers.Geometry.Point>} Center point for the rotation
135     */
136    rotate: function(angle, origin) {
137        for(var i=0, len=this.components.length; i<len - 1; ++i) {
138            this.components[i].rotate(angle, origin);
139        }
140    },
141
142    /**
143     * APIMethod: resize
144     * Resize a geometry relative to some origin.  Use this method to apply
145     *     a uniform scaling to a geometry.
146     *
147     * Parameters:
148     * scale - {Float} Factor by which to scale the geometry.  A scale of 2
149     *                 doubles the size of the geometry in each dimension
150     *                 (lines, for example, will be twice as long, and polygons
151     *                 will have four times the area).
152     * origin - {<OpenLayers.Geometry.Point>} Point of origin for resizing
153     * ratio - {Float} Optional x:y ratio for resizing.  Default ratio is 1.
154     *
155     * Returns:
156     * {OpenLayers.Geometry} - The current geometry.
157     */
158    resize: function(scale, origin, ratio) {
159        for(var i=0, len=this.components.length; i<len - 1; ++i) {
160            this.components[i].resize(scale, origin, ratio);
161        }
162        return this;
163    },
164   
165    /**
166     * APIMethod: transform
167     * Reproject the components geometry from source to dest.
168     *
169     * Parameters:
170     * source - {<OpenLayers.Projection>}
171     * dest - {<OpenLayers.Projection>}
172     *
173     * Returns:
174     * {<OpenLayers.Geometry>}
175     */
176    transform: function(source, dest) {
177        if (source && dest) {
178            for (var i=0, len=this.components.length; i<len - 1; i++) {
179                var component = this.components[i];
180                component.transform(source, dest);
181            }
182            this.bounds = null;
183        }
184        return this;
185    },
186   
187    /**
188     * APIMethod: getCentroid
189     *
190     * Returns:
191     * {<OpenLayers.Geometry.Point>} The centroid of the collection
192     */
193    getCentroid: function() {
194        if (this.components && (this.components.length > 2)) {
195            var sumX = 0.0;
196            var sumY = 0.0;
197            for (var i = 0; i < this.components.length - 1; i++) {
198                var b = this.components[i];
199                var c = this.components[i+1];
200                sumX += (b.x + c.x) * (b.x * c.y - c.x * b.y);
201                sumY += (b.y + c.y) * (b.x * c.y - c.x * b.y);
202            }
203            var area = -1 * this.getArea();
204            var x = sumX / (6 * area);
205            var y = sumY / (6 * area);
206            return new OpenLayers.Geometry.Point(x, y);
207        } else {
208            return null;
209        }
210    },
211
212    /**
213     * APIMethod: getArea
214     * Note - The area is positive if the ring is oriented CW, otherwise
215     *         it will be negative.
216     *
217     * Returns:
218     * {Float} The signed area for a ring.
219     */
220    getArea: function() {
221        var area = 0.0;
222        if ( this.components && (this.components.length > 2)) {
223            var sum = 0.0;
224            for (var i=0, len=this.components.length; i<len - 1; i++) {
225                var b = this.components[i];
226                var c = this.components[i+1];
227                sum += (b.x + c.x) * (c.y - b.y);
228            }
229            area = - sum / 2.0;
230        }
231        return area;
232    },
233   
234    /**
235     * APIMethod: getGeodesicArea
236     * Calculate the approximate area of the polygon were it projected onto
237     *     the earth.  Note that this area will be positive if ring is oriented
238     *     clockwise, otherwise it will be negative.
239     *
240     * Parameters:
241     * projection - {<OpenLayers.Projection>} The spatial reference system
242     *     for the geometry coordinates.  If not provided, Geographic/WGS84 is
243     *     assumed.
244     *
245     * Reference:
246     * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for
247     *     Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion
248     *     Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409
249     *
250     * Returns:
251     * {float} The approximate signed geodesic area of the polygon in square
252     *     meters.
253     */
254    getGeodesicArea: function(projection) {
255        var ring = this;  // so we can work with a clone if needed
256        if(projection) {
257            var gg = new OpenLayers.Projection("EPSG:4326");
258            if(!gg.equals(projection)) {
259                ring = this.clone().transform(projection, gg);
260            }
261        }
262        var area = 0.0;
263        var len = ring.components && ring.components.length;
264        if(len > 2) {
265            var p1, p2;
266            for(var i=0; i<len-1; i++) {
267                p1 = ring.components[i];
268                p2 = ring.components[i+1];
269                area += OpenLayers.Util.rad(p2.x - p1.x) *
270                        (2 + Math.sin(OpenLayers.Util.rad(p1.y)) +
271                        Math.sin(OpenLayers.Util.rad(p2.y)));
272            }
273            area = area * 6378137.0 * 6378137.0 / 2.0;
274        }
275        return area;
276    },
277   
278    /**
279     * Method: containsPoint
280     * Test if a point is inside a linear ring.  For the case where a point
281     *     is coincident with a linear ring edge, returns 1.  Otherwise,
282     *     returns boolean.
283     *
284     * Parameters:
285     * point - {<OpenLayers.Geometry.Point>}
286     *
287     * Returns:
288     * {Boolean | Number} The point is inside the linear ring.  Returns 1 if
289     *     the point is coincident with an edge.  Returns boolean otherwise.
290     */
291    containsPoint: function(point) {
292        var approx = OpenLayers.Number.limitSigDigs;
293        var digs = 14;
294        var px = approx(point.x, digs);
295        var py = approx(point.y, digs);
296        function getX(y, x1, y1, x2, y2) {
297            return (((x1 - x2) * y) + ((x2 * y1) - (x1 * y2))) / (y1 - y2);
298        }
299        var numSeg = this.components.length - 1;
300        var start, end, x1, y1, x2, y2, cx, cy;
301        var crosses = 0;
302        for(var i=0; i<numSeg; ++i) {
303            start = this.components[i];
304            x1 = approx(start.x, digs);
305            y1 = approx(start.y, digs);
306            end = this.components[i + 1];
307            x2 = approx(end.x, digs);
308            y2 = approx(end.y, digs);
309           
310            /**
311             * The following conditions enforce five edge-crossing rules:
312             *    1. points coincident with edges are considered contained;
313             *    2. an upward edge includes its starting endpoint, and
314             *    excludes its final endpoint;
315             *    3. a downward edge excludes its starting endpoint, and
316             *    includes its final endpoint;
317             *    4. horizontal edges are excluded; and
318             *    5. the edge-ray intersection point must be strictly right
319             *    of the point P.
320             */
321            if(y1 == y2) {
322                // horizontal edge
323                if(py == y1) {
324                    // point on horizontal line
325                    if(x1 <= x2 && (px >= x1 && px <= x2) || // right or vert
326                       x1 >= x2 && (px <= x1 && px >= x2)) { // left or vert
327                        // point on edge
328                        crosses = -1;
329                        break;
330                    }
331                }
332                // ignore other horizontal edges
333                continue;
334            }
335            cx = approx(getX(py, x1, y1, x2, y2), digs);
336            if(cx == px) {
337                // point on line
338                if(y1 < y2 && (py >= y1 && py <= y2) || // upward
339                   y1 > y2 && (py <= y1 && py >= y2)) { // downward
340                    // point on edge
341                    crosses = -1;
342                    break;
343                }
344            }
345            if(cx <= px) {
346                // no crossing to the right
347                continue;
348            }
349            if(x1 != x2 && (cx < Math.min(x1, x2) || cx > Math.max(x1, x2))) {
350                // no crossing
351                continue;
352            }
353            if(y1 < y2 && (py >= y1 && py < y2) || // upward
354               y1 > y2 && (py < y1 && py >= y2)) { // downward
355                ++crosses;
356            }
357        }
358        var contained = (crosses == -1) ?
359            // on edge
360            1 :
361            // even (out) or odd (in)
362            !!(crosses & 1);
363
364        return contained;
365    },
366
367    /**
368     * APIMethod: intersects
369     * Determine if the input geometry intersects this one.
370     *
371     * Parameters:
372     * geometry - {<OpenLayers.Geometry>} Any type of geometry.
373     *
374     * Returns:
375     * {Boolean} The input geometry intersects this one.
376     */
377    intersects: function(geometry) {
378        var intersect = false;
379        if(geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
380            intersect = this.containsPoint(geometry);
381        } else if(geometry.CLASS_NAME == "OpenLayers.Geometry.LineString") {
382            intersect = geometry.intersects(this);
383        } else if(geometry.CLASS_NAME == "OpenLayers.Geometry.LinearRing") {
384            intersect = OpenLayers.Geometry.LineString.prototype.intersects.apply(
385                this, [geometry]
386            );
387        } else {
388            // check for component intersections
389            for(var i=0, len=geometry.components.length; i<len; ++ i) {
390                intersect = geometry.components[i].intersects(this);
391                if(intersect) {
392                    break;
393                }
394            }
395        }
396        return intersect;
397    },
398
399    /**
400     * APIMethod: getVertices
401     * Return a list of all points in this geometry.
402     *
403     * Parameters:
404     * nodes - {Boolean} For lines, only return vertices that are
405     *     endpoints.  If false, for lines, only vertices that are not
406     *     endpoints will be returned.  If not provided, all vertices will
407     *     be returned.
408     *
409     * Returns:
410     * {Array} A list of all vertices in the geometry.
411     */
412    getVertices: function(nodes) {
413        return (nodes === true) ? [] : this.components.slice(0, this.components.length-1);
414    },
415
416    CLASS_NAME: "OpenLayers.Geometry.LinearRing"
417});
Note: See TracBrowser for help on using the repository browser.