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/Control/Split.js @ 81

Revision 76, 19.5 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/Control.js
8 * @requires OpenLayers/Handler/Path.js
9 * @requires OpenLayers/Layer/Vector.js
10 */
11
12/**
13 * Class: OpenLayers.Control.Split
14 * Acts as a split feature agent while editing vector features.
15 *
16 * Inherits from:
17 *  - <OpenLayers.Control>
18 */
19OpenLayers.Control.Split = OpenLayers.Class(OpenLayers.Control, {
20
21    /**
22     * Constant: EVENT_TYPES
23     * {Array(String)} Supported application event types.  Register a listener
24     *     for a particular event with the following syntax:
25     * (code)
26     * control.events.register(type, obj, listener);
27     * (end)
28     *
29     * Listeners will be called with a reference to an event object.  The
30     *     properties of this event depends on exactly what happened.
31     *
32     * Supported control event types (in addition to those from <OpenLayers.Control>):
33     * beforesplit - Triggered before a split occurs.  Listeners receive an
34     *     event object with *source* and *target* properties.
35     * split - Triggered when a split occurs.  Listeners receive an event with
36     *     an *original* property and a *features* property.  The original
37     *     is a reference to the target feature that the sketch or modified
38     *     feature intersects.  The features property is a list of all features
39     *     that result from this single split.  This event is triggered before
40     *     the resulting features are added to the layer (while the layer still
41     *     has a reference to the original).
42     * aftersplit - Triggered after all splits resulting from a single sketch
43     *     or feature modification have occurred.  The original features
44     *     have been destroyed and features that result from the split
45     *     have already been added to the layer.  Listeners receive an event
46     *     with a *source* and *features* property.  The source references the
47     *     sketch or modified feature used as a splitter.  The features
48     *     property is a list of all resulting features.
49     */
50    EVENT_TYPES: ["beforesplit", "split", "aftersplit"],
51   
52    /**
53     * APIProperty: layer
54     * {<OpenLayers.Layer.Vector>} The target layer with features to be split.
55     *     Set at construction or after construction with <setLayer>.
56     */
57    layer: null,
58   
59    /**
60     * Property: source
61     * {<OpenLayers.Layer.Vector>} Optional source layer.  Any newly created
62     *     or modified features from this layer will be used to split features
63     *     on the target layer.  If not provided, a temporary sketch layer will
64     *     be created.
65     */
66    source: null,
67   
68    /**
69     * Property: sourceOptions
70     * {Options} If a temporary sketch layer is created, these layer options
71     *     will be applied.
72     */
73    sourceOptions: null,
74
75    /**
76     * APIProperty: tolerance
77     * {Number} Distance between the calculated intersection and a vertex on
78     *     the source geometry below which the existing vertex will be used
79     *     for the split.  Default is null.
80     */
81    tolerance: null,
82   
83    /**
84     * APIProperty: edge
85     * {Boolean} Allow splits given intersection of edges only.  Default is
86     *     true.  If false, a vertex on the source must be within the
87     *     <tolerance> distance of the calculated intersection for a split
88     *     to occur.
89     */
90    edge: true,
91   
92    /**
93     * APIProperty: deferDelete
94     * {Boolean} Instead of removing features from the layer, set feature
95     *     states of split features to DELETE.  This assumes a save strategy
96     *     or other component is in charge of removing features from the
97     *     layer.  Default is false.  If false, split features will be
98     *     immediately deleted from the layer.
99     */
100    deferDelete: false,
101   
102    /**
103     * APIProperty: mutual
104     * {Boolean} If source and target layers are the same, split source
105     *     features and target features where they intersect.  Default is
106     *     true.  If false, only target features will be split.
107     */
108    mutual: true,
109   
110    /**
111     * APIProperty: targetFilter
112     * {OpenLayers.Filter} Optional filter that will be evaluated
113     *     to determine if a feature from the target layer is eligible for
114     *     splitting.
115     */
116    targetFilter: null,
117   
118    /**
119     * APIProperty: sourceFilter
120     * {OpenLayers.Filter} Optional filter that will be evaluated
121     *     to determine if a feature from the target layer is eligible for
122     *     splitting.
123     */
124    sourceFilter: null,
125   
126    /**
127     * Property: handler
128     * {<OpenLayers.Handler.Path>} The temporary sketch handler created if
129     *     no source layer is provided.
130     */
131    handler: null,
132
133    /**
134     * Constructor: OpenLayers.Control.Split
135     * Creates a new split control. A control is constructed with a target
136     *     layer and an optional source layer. While the control is active,
137     *     creating new features or modifying existing features on the source
138     *     layer will result in splitting any eligible features on the target
139     *     layer.  If no source layer is provided, a temporary sketch layer will
140     *     be created to create lines for splitting features on the target.
141     *
142     * Parameters:
143     * options - {Object} An object containing all configuration properties for
144     *     the control.
145     *
146     * Valid options:
147     * layer - {OpenLayers.Layer.Vector} The target layer.  Features from this
148     *     layer will be split by new or modified features on the source layer
149     *     or temporary sketch layer.
150     * source - {OpenLayers.Layer.Vector} Optional source layer.  If provided
151     *     newly created features or modified features will be used to split
152     *     features on the target layer.  If not provided, a temporary sketch
153     *     layer will be created for drawing lines.
154     * tolerance - {Number} Optional value for the distance between a source
155     *     vertex and the calculated intersection below which the split will
156     *     occur at the vertex.
157     * edge - {Boolean} Allow splits given intersection of edges only.  Default
158     *     is true.  If false, a vertex on the source must be within the
159     *     <tolerance> distance of the calculated intersection for a split
160     *     to occur.
161     * mutual - {Boolean} If source and target are the same, split source
162     *     features and target features where they intersect.  Default is
163     *     true.  If false, only target features will be split.
164     * targetFilter - {OpenLayers.Filter} Optional filter that will be evaluated
165     *     to determine if a feature from the target layer is eligible for
166     *     splitting.
167     * sourceFilter - {OpenLayers.Filter} Optional filter that will be evaluated
168     *     to determine if a feature from the target layer is eligible for
169     *     splitting.
170     */
171    initialize: function(options) {
172        // concatenate events specific to measure with those from the base
173        Array.prototype.push.apply(
174            this.EVENT_TYPES, OpenLayers.Control.prototype.EVENT_TYPES
175        );
176        OpenLayers.Control.prototype.initialize.apply(this, [options]);
177        this.options = options || {}; // TODO: this could be done by the super
178       
179        // set the source layer if provided
180        if(this.options.source) {
181            this.setSource(this.options.source);
182        }
183    },
184   
185    /**
186     * APIMethod: setSource
187     * Set the source layer for edits layer.
188     *
189     * Parameters:
190     * layer - {OpenLayers.Layer.Vector}  The new source layer layer.  If
191     *     null, a temporary sketch layer will be created.
192     */
193    setSource: function(layer) {
194        if(this.active) {
195            this.deactivate();
196            if(this.handler) {
197                this.handler.destroy();
198                delete this.handler;
199            }
200            this.source = layer;
201            this.activate();
202        } else {
203            this.source = layer;
204        }
205    },
206   
207    /**
208     * APIMethod: activate
209     * Activate the control.  Activating the control registers listeners for
210     *     editing related events so that during feature creation and
211     *     modification, features in the target will be considered for
212     *     splitting.
213     */
214    activate: function() {
215        var activated = OpenLayers.Control.prototype.activate.call(this);
216        if(activated) {
217            if(!this.source) {
218                if(!this.handler) {
219                    this.handler = new OpenLayers.Handler.Path(this,
220                        {done: function(geometry) {
221                            this.onSketchComplete({
222                                feature: new OpenLayers.Feature.Vector(geometry)
223                            });
224                        }},
225                        {layerOptions: this.sourceOptions}
226                    );
227                }
228                this.handler.activate();
229            } else if(this.source.events) {
230                this.source.events.on({
231                    sketchcomplete: this.onSketchComplete,
232                    afterfeaturemodified: this.afterFeatureModified,
233                    scope: this
234                });
235            }
236        }
237        return activated;
238    },
239   
240    /**
241     * APIMethod: deactivate
242     * Deactivate the control.  Deactivating the control unregisters listeners
243     *     so feature editing may proceed without engaging the split agent.
244     */
245    deactivate: function() {
246        var deactivated = OpenLayers.Control.prototype.deactivate.call(this);
247        if(deactivated) {
248            if(this.source && this.source.events) {
249                this.layer.events.un({
250                    sketchcomplete: this.onSketchComplete,
251                    afterfeaturemodified: this.afterFeatureModified,
252                    scope: this
253                });
254            }
255        }
256        return deactivated;
257    },
258   
259    /**
260     * Method: onSketchComplete
261     * Registered as a listener for the sketchcomplete event on the editable
262     *     layer.
263     *
264     * Parameters:
265     * event - {Object} The sketch complete event.
266     *
267     * Returns:
268     * {Boolean} Stop the sketch from being added to the layer (it has been
269     *     split).
270     */
271    onSketchComplete: function(event) {
272        this.feature = null;
273        return !this.considerSplit(event.feature);
274    },
275   
276    /**
277     * Method: afterFeatureModified
278     * Registered as a listener for the afterfeaturemodified event on the
279     *     editable layer.
280     *
281     * Parameters:
282     * event - {Object} The after feature modified event.
283     */
284    afterFeatureModified: function(event) {
285        if(event.modified) {
286            var feature = event.feature;
287            if(feature.geometry instanceof OpenLayers.Geometry.LineString ||
288               feature.geometry instanceof OpenLayers.Geometry.MultiLineString) {
289                this.feature = event.feature;
290                this.considerSplit(event.feature);
291            }
292        }
293    },
294   
295    /**
296     * Method: removeByGeometry
297     * Remove a feature from a list based on the given geometry.
298     *
299     * Parameters:
300     * features - {Array(<OpenLayers.Feature.Vector>} A list of features.
301     * geometry - {<OpenLayers.Geometry>} A geometry.
302     */
303    removeByGeometry: function(features, geometry) {
304        for(var i=0, len=features.length; i<len; ++i) {
305            if(features[i].geometry === geometry) {
306                features.splice(i, 1);
307                break;
308            }
309        }
310    },
311   
312    /**
313     * Method: isEligible
314     * Test if a target feature is eligible for splitting.
315     *
316     * Parameters:
317     * target - {<OpenLayers.Feature.Vector>} The target feature.
318     *
319     * Returns:
320     * {Boolean} The target is eligible for splitting.
321     */
322    isEligible: function(target) {
323        return (
324            target.state !== OpenLayers.State.DELETE
325        ) && (
326            target.geometry instanceof OpenLayers.Geometry.LineString ||
327            target.geometry instanceof OpenLayers.Geometry.MultiLineString
328        ) && (
329            this.feature !== target
330        ) && (
331            !this.targetFilter ||
332            this.targetFilter.evaluate(target.attributes)
333        );
334    },
335
336    /**
337     * Method: considerSplit
338     * Decide whether or not to split target features with the supplied
339     *     feature.  If <mutual> is true, both the source and target features
340     *     will be split if eligible.
341     *
342     * Parameters:
343     * feature - {<OpenLayers.Feature.Vector}} The newly created or modified
344     *     feature.
345     *
346     * Returns:
347     * {Boolean} The supplied feature was split (and destroyed).
348     */
349    considerSplit: function(feature) {
350        var sourceSplit = false;
351        var targetSplit = false;
352        if(!this.sourceFilter ||
353           this.sourceFilter.evaluate(feature.attributes)) {
354            var features = this.layer && this.layer.features || [];
355            var target, results, proceed;
356            var additions = [], removals = [];
357            var mutual = (this.layer === this.source) && this.mutual;
358            var options = {
359                edge: this.edge,
360                tolerance: this.tolerance,
361                mutual: mutual
362            };
363            var sourceParts = [feature.geometry];
364            var targetFeature, targetParts;
365            var source, parts;
366            for(var i=0, len=features.length; i<len; ++i) {
367                targetFeature = features[i];
368                if(this.isEligible(targetFeature)) {
369                    targetParts = [targetFeature.geometry];
370                    // work through source geoms - this array may change
371                    for(var j=0; j<sourceParts.length; ++j) { 
372                        source = sourceParts[j];
373                        // work through target parts - this array may change
374                        for(var k=0; k<targetParts.length; ++k) {
375                            target = targetParts[k];
376                            if(source.getBounds().intersectsBounds(target.getBounds())) {
377                                results = source.split(target, options);
378                                if(results) {
379                                    proceed = this.events.triggerEvent(
380                                        "beforesplit", {source: feature, target: targetFeature}
381                                    );
382                                    if(proceed !== false) {
383                                        if(mutual) {
384                                            parts = results[0];
385                                            // handle parts that result from source splitting
386                                            if(parts.length > 1) {
387                                                // splice in new source parts
388                                                parts.unshift(j, 1); // add args for splice below
389                                                Array.prototype.splice.apply(sourceParts, parts);
390                                                j += parts.length - 3;
391                                            }
392                                            results = results[1];
393                                        }
394                                        // handle parts that result from target splitting
395                                        if(results.length > 1) {
396                                            // splice in new target parts
397                                            results.unshift(k, 1); // add args for splice below
398                                            Array.prototype.splice.apply(targetParts, results);
399                                            k += results.length - 3;
400                                        }
401                                    }
402                                }
403                            }
404                        }
405                    }
406                    if(targetParts && targetParts.length > 1) {
407                        this.geomsToFeatures(targetFeature, targetParts);
408                        this.events.triggerEvent("split", {
409                            original: targetFeature,
410                            features: targetParts
411                        });
412                        Array.prototype.push.apply(additions, targetParts);
413                        removals.push(targetFeature);
414                        targetSplit = true;
415                    }
416                }
417            }
418            if(sourceParts && sourceParts.length > 1) {
419                this.geomsToFeatures(feature, sourceParts);
420                this.events.triggerEvent("split", {
421                    original: feature,
422                    features: sourceParts
423                });
424                Array.prototype.push.apply(additions, sourceParts);
425                removals.push(feature);
426                sourceSplit = true;
427            }
428            if(sourceSplit || targetSplit) {
429                // remove and add feature events are suppressed
430                // listen for split event on this control instead
431                if(this.deferDelete) {
432                    // Set state instead of removing.  Take care to avoid
433                    // setting delete for features that have not yet been
434                    // inserted - those should be destroyed immediately.
435                    var feat, destroys = [];
436                    for(var i=0, len=removals.length; i<len; ++i) {
437                        feat = removals[i];
438                        if(feat.state === OpenLayers.State.INSERT) {
439                            destroys.push(feat);
440                        } else {
441                            feat.state = OpenLayers.State.DELETE;
442                            this.layer.drawFeature(feat);
443                        }
444                    }
445                    this.layer.destroyFeatures(destroys, {silent: true});
446                    for(var i=0, len=additions.length; i<len; ++i) {
447                        additions[i].state = OpenLayers.State.INSERT;
448                    }
449                } else {
450                    this.layer.destroyFeatures(removals, {silent: true});
451                }
452                this.layer.addFeatures(additions, {silent: true});
453                this.events.triggerEvent("aftersplit", {
454                    source: feature,
455                    features: additions
456                });
457            }
458        }
459        return sourceSplit;
460    },
461   
462    /**
463     * Method: geomsToFeatures
464     * Create new features given a template feature and a list of geometries.
465     *     The list of geometries is modified in place.  The result will be
466     *     a list of new features.
467     *
468     * Parameters:
469     * feature - {<OpenLayers.Feature.Vector>} The feature to be cloned.
470     * geoms - {Array(<OpenLayers.Geometry>)} List of goemetries.  This will
471     *     become a list of new features.
472     */
473    geomsToFeatures: function(feature, geoms) {
474        var clone = feature.clone();
475        delete clone.geometry;
476        var newFeature;
477        for(var i=0, len=geoms.length; i<len; ++i) {
478            // turn results list from geoms to features
479            newFeature = clone.clone();
480            newFeature.geometry = geoms[i];
481            newFeature.state = OpenLayers.State.INSERT;
482            geoms[i] = newFeature;
483        }
484    },
485   
486    /**
487     * Method: destroy
488     * Clean up the control.
489     */
490    destroy: function() {
491        if(this.active) {
492            this.deactivate(); // TODO: this should be handled by the super
493        }
494        OpenLayers.Control.prototype.destroy.call(this);
495    },
496
497    CLASS_NAME: "OpenLayers.Control.Split"
498});
Note: See TracBrowser for help on using the repository browser.