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/LineString.js @ 76

Revision 76, 21.4 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/Curve.js
8 */
9
10/**
11 * Class: OpenLayers.Geometry.LineString
12 * A LineString is a Curve which, once two points have been added to it, can
13 * never be less than two points long.
14 *
15 * Inherits from:
16 *  - <OpenLayers.Geometry.Curve>
17 */
18OpenLayers.Geometry.LineString = OpenLayers.Class(OpenLayers.Geometry.Curve, {
19
20    /**
21     * Constructor: OpenLayers.Geometry.LineString
22     * Create a new LineString geometry
23     *
24     * Parameters:
25     * points - {Array(<OpenLayers.Geometry.Point>)} An array of points used to
26     *          generate the linestring
27     *
28     */
29    initialize: function(points) {
30        OpenLayers.Geometry.Curve.prototype.initialize.apply(this, arguments);       
31    },
32
33    /**
34     * APIMethod: removeComponent
35     * Only allows removal of a point if there are three or more points in
36     * the linestring. (otherwise the result would be just a single point)
37     *
38     * Parameters:
39     * point - {<OpenLayers.Geometry.Point>} The point to be removed
40     */
41    removeComponent: function(point) {
42        if ( this.components && (this.components.length > 2)) {
43            OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this, 
44                                                                  arguments);
45        }
46    },
47   
48    /**
49     * APIMethod: intersects
50     * Test for instersection between two geometries.  This is a cheapo
51     *     implementation of the Bently-Ottmann algorigithm.  It doesn't
52     *     really keep track of a sweep line data structure.  It is closer
53     *     to the brute force method, except that segments are sorted and
54     *     potential intersections are only calculated when bounding boxes
55     *     intersect.
56     *
57     * Parameters:
58     * geometry - {<OpenLayers.Geometry>}
59     *
60     * Returns:
61     * {Boolean} The input geometry intersects this geometry.
62     */
63    intersects: function(geometry) {
64        var intersect = false;
65        var type = geometry.CLASS_NAME;
66        if(type == "OpenLayers.Geometry.LineString" ||
67           type == "OpenLayers.Geometry.LinearRing" ||
68           type == "OpenLayers.Geometry.Point") {
69            var segs1 = this.getSortedSegments();
70            var segs2;
71            if(type == "OpenLayers.Geometry.Point") {
72                segs2 = [{
73                    x1: geometry.x, y1: geometry.y,
74                    x2: geometry.x, y2: geometry.y
75                }];
76            } else {
77                segs2 = geometry.getSortedSegments();
78            }
79            var seg1, seg1x1, seg1x2, seg1y1, seg1y2,
80                seg2, seg2y1, seg2y2;
81            // sweep right
82            outer: for(var i=0, len=segs1.length; i<len; ++i) {
83                seg1 = segs1[i];
84                seg1x1 = seg1.x1;
85                seg1x2 = seg1.x2;
86                seg1y1 = seg1.y1;
87                seg1y2 = seg1.y2;
88                inner: for(var j=0, jlen=segs2.length; j<jlen; ++j) {
89                    seg2 = segs2[j];
90                    if(seg2.x1 > seg1x2) {
91                        // seg1 still left of seg2
92                        break;
93                    }
94                    if(seg2.x2 < seg1x1) {
95                        // seg2 still left of seg1
96                        continue;
97                    }
98                    seg2y1 = seg2.y1;
99                    seg2y2 = seg2.y2;
100                    if(Math.min(seg2y1, seg2y2) > Math.max(seg1y1, seg1y2)) {
101                        // seg2 above seg1
102                        continue;
103                    }
104                    if(Math.max(seg2y1, seg2y2) < Math.min(seg1y1, seg1y2)) {
105                        // seg2 below seg1
106                        continue;
107                    }
108                    if(OpenLayers.Geometry.segmentsIntersect(seg1, seg2)) {
109                        intersect = true;
110                        break outer;
111                    }
112                }
113            }
114        } else {
115            intersect = geometry.intersects(this);
116        }
117        return intersect;
118    },
119   
120    /**
121     * Method: getSortedSegments
122     *
123     * Returns:
124     * {Array} An array of segment objects.  Segment objects have properties
125     *     x1, y1, x2, and y2.  The start point is represented by x1 and y1.
126     *     The end point is represented by x2 and y2.  Start and end are
127     *     ordered so that x1 < x2.
128     */
129    getSortedSegments: function() {
130        var numSeg = this.components.length - 1;
131        var segments = new Array(numSeg), point1, point2;
132        for(var i=0; i<numSeg; ++i) {
133            point1 = this.components[i];
134            point2 = this.components[i + 1];
135            if(point1.x < point2.x) {
136                segments[i] = {
137                    x1: point1.x,
138                    y1: point1.y,
139                    x2: point2.x,
140                    y2: point2.y
141                };
142            } else {
143                segments[i] = {
144                    x1: point2.x,
145                    y1: point2.y,
146                    x2: point1.x,
147                    y2: point1.y
148                };
149            }
150        }
151        // more efficient to define this somewhere static
152        function byX1(seg1, seg2) {
153            return seg1.x1 - seg2.x1;
154        }
155        return segments.sort(byX1);
156    },
157   
158    /**
159     * Method: splitWithSegment
160     * Split this geometry with the given segment.
161     *
162     * Parameters:
163     * seg - {Object} An object with x1, y1, x2, and y2 properties referencing
164     *     segment endpoint coordinates.
165     * options - {Object} Properties of this object will be used to determine
166     *     how the split is conducted.
167     *
168     * Valid options:
169     * edge - {Boolean} Allow splitting when only edges intersect.  Default is
170     *     true.  If false, a vertex on the source segment must be within the
171     *     tolerance distance of the intersection to be considered a split.
172     * tolerance - {Number} If a non-null value is provided, intersections
173     *     within the tolerance distance of one of the source segment's
174     *     endpoints will be assumed to occur at the endpoint.
175     *
176     * Returns:
177     * {Object} An object with *lines* and *points* properties.  If the given
178     *     segment intersects this linestring, the lines array will reference
179     *     geometries that result from the split.  The points array will contain
180     *     all intersection points.  Intersection points are sorted along the
181     *     segment (in order from x1,y1 to x2,y2).
182     */
183    splitWithSegment: function(seg, options) {
184        var edge = !(options && options.edge === false);
185        var tolerance = options && options.tolerance;
186        var lines = [];
187        var verts = this.getVertices();
188        var points = [];
189        var intersections = [];
190        var split = false;
191        var vert1, vert2, point;
192        var node, vertex, target;
193        var interOptions = {point: true, tolerance: tolerance};
194        var result = null;
195        for(var i=0, stop=verts.length-2; i<=stop; ++i) {
196            vert1 = verts[i];
197            points.push(vert1.clone());
198            vert2 = verts[i+1];
199            target = {x1: vert1.x, y1: vert1.y, x2: vert2.x, y2: vert2.y};
200            point = OpenLayers.Geometry.segmentsIntersect(
201                seg, target, interOptions
202            );
203            if(point instanceof OpenLayers.Geometry.Point) {
204                if((point.x === seg.x1 && point.y === seg.y1) ||
205                   (point.x === seg.x2 && point.y === seg.y2) ||
206                   point.equals(vert1) || point.equals(vert2)) {
207                    vertex = true;
208                } else {
209                    vertex = false;
210                }
211                if(vertex || edge) {
212                    // push intersections different than the previous
213                    if(!point.equals(intersections[intersections.length-1])) {
214                        intersections.push(point.clone());
215                    }
216                    if(i === 0) {
217                        if(point.equals(vert1)) {
218                            continue;
219                        }
220                    }
221                    if(point.equals(vert2)) {
222                        continue;
223                    }
224                    split = true;
225                    if(!point.equals(vert1)) {
226                        points.push(point);
227                    }
228                    lines.push(new OpenLayers.Geometry.LineString(points));
229                    points = [point.clone()];
230                }
231            }
232        }
233        if(split) {
234            points.push(vert2.clone());
235            lines.push(new OpenLayers.Geometry.LineString(points));
236        }
237        if(intersections.length > 0) {
238            // sort intersections along segment
239            var xDir = seg.x1 < seg.x2 ? 1 : -1;
240            var yDir = seg.y1 < seg.y2 ? 1 : -1;
241            result = {
242                lines: lines,
243                points: intersections.sort(function(p1, p2) {
244                    return (xDir * p1.x - xDir * p2.x) || (yDir * p1.y - yDir * p2.y);
245                })
246            };
247        }
248        return result;
249    },
250
251    /**
252     * Method: split
253     * Use this geometry (the source) to attempt to split a target geometry.
254     *
255     * Parameters:
256     * target - {<OpenLayers.Geometry>} The target geometry.
257     * options - {Object} Properties of this object will be used to determine
258     *     how the split is conducted.
259     *
260     * Valid options:
261     * mutual - {Boolean} Split the source geometry in addition to the target
262     *     geometry.  Default is false.
263     * edge - {Boolean} Allow splitting when only edges intersect.  Default is
264     *     true.  If false, a vertex on the source must be within the tolerance
265     *     distance of the intersection to be considered a split.
266     * tolerance - {Number} If a non-null value is provided, intersections
267     *     within the tolerance distance of an existing vertex on the source
268     *     will be assumed to occur at the vertex.
269     *
270     * Returns:
271     * {Array} A list of geometries (of this same type as the target) that
272     *     result from splitting the target with the source geometry.  The
273     *     source and target geometry will remain unmodified.  If no split
274     *     results, null will be returned.  If mutual is true and a split
275     *     results, return will be an array of two arrays - the first will be
276     *     all geometries that result from splitting the source geometry and
277     *     the second will be all geometries that result from splitting the
278     *     target geometry.
279     */
280    split: function(target, options) {
281        var results = null;
282        var mutual = options && options.mutual;
283        var sourceSplit, targetSplit, sourceParts, targetParts;
284        if(target instanceof OpenLayers.Geometry.LineString) {
285            var verts = this.getVertices();
286            var vert1, vert2, seg, splits, lines, point;
287            var points = [];
288            sourceParts = [];
289            for(var i=0, stop=verts.length-2; i<=stop; ++i) {
290                vert1 = verts[i];
291                vert2 = verts[i+1];
292                seg = {
293                    x1: vert1.x, y1: vert1.y,
294                    x2: vert2.x, y2: vert2.y
295                };
296                targetParts = targetParts || [target];
297                if(mutual) {
298                    points.push(vert1.clone());
299                }
300                for(var j=0; j<targetParts.length; ++j) {
301                    splits = targetParts[j].splitWithSegment(seg, options);
302                    if(splits) {
303                        // splice in new features
304                        lines = splits.lines;
305                        if(lines.length > 0) {
306                            lines.unshift(j, 1);
307                            Array.prototype.splice.apply(targetParts, lines);
308                            j += lines.length - 2;
309                        }
310                        if(mutual) {
311                            for(var k=0, len=splits.points.length; k<len; ++k) {
312                                point = splits.points[k];
313                                if(!point.equals(vert1)) {
314                                    points.push(point);
315                                    sourceParts.push(new OpenLayers.Geometry.LineString(points));
316                                    if(point.equals(vert2)) {
317                                        points = [];
318                                    } else {
319                                        points = [point.clone()];
320                                    }
321                                }
322                            }
323                        }
324                    }
325                }
326            }
327            if(mutual && sourceParts.length > 0 && points.length > 0) {
328                points.push(vert2.clone());
329                sourceParts.push(new OpenLayers.Geometry.LineString(points));
330            }
331        } else {
332            results = target.splitWith(this, options);
333        }
334        if(targetParts && targetParts.length > 1) {
335            targetSplit = true;
336        } else {
337            targetParts = [];
338        }
339        if(sourceParts && sourceParts.length > 1) {
340            sourceSplit = true;
341        } else {
342            sourceParts = [];
343        }
344        if(targetSplit || sourceSplit) {
345            if(mutual) {
346                results = [sourceParts, targetParts];
347            } else {
348                results = targetParts;
349            }
350        }
351        return results;
352    },
353
354    /**
355     * Method: splitWith
356     * Split this geometry (the target) with the given geometry (the source).
357     *
358     * Parameters:
359     * geometry - {<OpenLayers.Geometry>} A geometry used to split this
360     *     geometry (the source).
361     * options - {Object} Properties of this object will be used to determine
362     *     how the split is conducted.
363     *
364     * Valid options:
365     * mutual - {Boolean} Split the source geometry in addition to the target
366     *     geometry.  Default is false.
367     * edge - {Boolean} Allow splitting when only edges intersect.  Default is
368     *     true.  If false, a vertex on the source must be within the tolerance
369     *     distance of the intersection to be considered a split.
370     * tolerance - {Number} If a non-null value is provided, intersections
371     *     within the tolerance distance of an existing vertex on the source
372     *     will be assumed to occur at the vertex.
373     *
374     * Returns:
375     * {Array} A list of geometries (of this same type as the target) that
376     *     result from splitting the target with the source geometry.  The
377     *     source and target geometry will remain unmodified.  If no split
378     *     results, null will be returned.  If mutual is true and a split
379     *     results, return will be an array of two arrays - the first will be
380     *     all geometries that result from splitting the source geometry and
381     *     the second will be all geometries that result from splitting the
382     *     target geometry.
383     */
384    splitWith: function(geometry, options) {
385        return geometry.split(this, options);
386
387    },
388
389    /**
390     * APIMethod: getVertices
391     * Return a list of all points in this geometry.
392     *
393     * Parameters:
394     * nodes - {Boolean} For lines, only return vertices that are
395     *     endpoints.  If false, for lines, only vertices that are not
396     *     endpoints will be returned.  If not provided, all vertices will
397     *     be returned.
398     *
399     * Returns:
400     * {Array} A list of all vertices in the geometry.
401     */
402    getVertices: function(nodes) {
403        var vertices;
404        if(nodes === true) {
405            vertices = [
406                this.components[0],
407                this.components[this.components.length-1]
408            ];
409        } else if (nodes === false) {
410            vertices = this.components.slice(1, this.components.length-1);
411        } else {
412            vertices = this.components.slice();
413        }
414        return vertices;
415    },
416
417    /**
418     * APIMethod: distanceTo
419     * Calculate the closest distance between two geometries (on the x-y plane).
420     *
421     * Parameters:
422     * geometry - {<OpenLayers.Geometry>} The target geometry.
423     * options - {Object} Optional properties for configuring the distance
424     *     calculation.
425     *
426     * Valid options:
427     * details - {Boolean} Return details from the distance calculation.
428     *     Default is false.
429     * edge - {Boolean} Calculate the distance from this geometry to the
430     *     nearest edge of the target geometry.  Default is true.  If true,
431     *     calling distanceTo from a geometry that is wholly contained within
432     *     the target will result in a non-zero distance.  If false, whenever
433     *     geometries intersect, calling distanceTo will return 0.  If false,
434     *     details cannot be returned.
435     *
436     * Returns:
437     * {Number | Object} The distance between this geometry and the target.
438     *     If details is true, the return will be an object with distance,
439     *     x0, y0, x1, and x2 properties.  The x0 and y0 properties represent
440     *     the coordinates of the closest point on this geometry. The x1 and y1
441     *     properties represent the coordinates of the closest point on the
442     *     target geometry.
443     */
444    distanceTo: function(geometry, options) {
445        var edge = !(options && options.edge === false);
446        var details = edge && options && options.details;
447        var result, best = {};
448        var min = Number.POSITIVE_INFINITY;
449        if(geometry instanceof OpenLayers.Geometry.Point) {
450            var segs = this.getSortedSegments();
451            var x = geometry.x;
452            var y = geometry.y;
453            var seg;
454            for(var i=0, len=segs.length; i<len; ++i) {
455                seg = segs[i];
456                result = OpenLayers.Geometry.distanceToSegment(geometry, seg);
457                if(result.distance < min) {
458                    min = result.distance;
459                    best = result;
460                    if(min === 0) {
461                        break;
462                    }
463                } else {
464                    // if distance increases and we cross y0 to the right of x0, no need to keep looking.
465                    if(seg.x2 > x && ((y > seg.y1 && y < seg.y2) || (y < seg.y1 && y > seg.y2))) {
466                        break;
467                    }
468                }
469            }
470            if(details) {
471                best = {
472                    distance: best.distance,
473                    x0: best.x, y0: best.y,
474                    x1: x, y1: y
475                };
476            } else {
477                best = best.distance;
478            }
479        } else if(geometry instanceof OpenLayers.Geometry.LineString) { 
480            var segs0 = this.getSortedSegments();
481            var segs1 = geometry.getSortedSegments();
482            var seg0, seg1, intersection, x0, y0;
483            var len1 = segs1.length;
484            var interOptions = {point: true};
485            outer: for(var i=0, len=segs0.length; i<len; ++i) {
486                seg0 = segs0[i];
487                x0 = seg0.x1;
488                y0 = seg0.y1;
489                for(var j=0; j<len1; ++j) {
490                    seg1 = segs1[j];
491                    intersection = OpenLayers.Geometry.segmentsIntersect(seg0, seg1, interOptions);
492                    if(intersection) {
493                        min = 0;
494                        best = {
495                            distance: 0,
496                            x0: intersection.x, y0: intersection.y,
497                            x1: intersection.x, y1: intersection.y
498                        };
499                        break outer;
500                    } else {
501                        result = OpenLayers.Geometry.distanceToSegment({x: x0, y: y0}, seg1);
502                        if(result.distance < min) {
503                            min = result.distance;
504                            best = {
505                                distance: min,
506                                x0: x0, y0: y0,
507                                x1: result.x, y1: result.y
508                            };
509                        }
510                    }
511                }
512            }
513            if(!details) {
514                best = best.distance;
515            }
516            if(min !== 0) {
517                // check the final vertex in this line's sorted segments
518                if(seg0) {
519                    result = geometry.distanceTo(
520                        new OpenLayers.Geometry.Point(seg0.x2, seg0.y2),
521                        options
522                    );
523                    var dist = details ? result.distance : result;
524                    if(dist < min) {
525                        if(details) {
526                            best = {
527                                distance: min,
528                                x0: result.x1, y0: result.y1,
529                                x1: result.x0, y1: result.y0
530                            };
531                        } else {
532                            best = dist;
533                        }
534                    }
535                }
536            }
537        } else {
538            best = geometry.distanceTo(this, options);
539            // swap since target comes from this line
540            if(details) {
541                best = {
542                    distance: best.distance,
543                    x0: best.x1, y0: best.y1,
544                    x1: best.x0, y1: best.y0
545                };
546            }
547        }
548        return best;
549    },
550
551    CLASS_NAME: "OpenLayers.Geometry.LineString"
552});
Note: See TracBrowser for help on using the repository browser.