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

Revision 76, 21.1 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/Layer/WMS/Post.js
9 * @requires OpenLayers/Handler/RegularPolygon.js
10 * @requires OpenLayers/Handler/Polygon.js
11 * @requires OpenLayers/Handler/Path.js
12 * @requires OpenLayers/Handler/Click.js
13 * @requires OpenLayers/Filter/Spatial.js
14 */
15
16/**
17 * Class: OpenLayers.Control.SLDSelect
18 * Perform selections on WMS layers using Styled Layer Descriptor (SLD)
19 *
20 * Inherits from:
21 *  - <OpenLayers.Control>
22 */
23OpenLayers.Control.SLDSelect = OpenLayers.Class(OpenLayers.Control, {
24
25    /**
26     * Constant: EVENT_TYPES
27     * {Array(String)} Supported application event types.  Register a listener
28     *     for a particular event with the following syntax:
29     * (code)
30     * control.events.register(type, obj, listener);
31     * (end)
32     *
33     * Listeners will be called with a reference to an event object.  The
34     *     properties of this event depends on exactly what happened.
35     *
36     * Supported control event types (in addition to those from
37     * <OpenLayers.Control>):
38     * selected - Triggered when a selection occurs.  Listeners receive an
39     *     event with *filters* and *layer* properties.  Filters will be an
40     *     array of OpenLayers.Filter objects created in order to perform
41     *     the particular selection.
42     */
43    EVENT_TYPES: ["selected"],
44
45    /**
46     * APIProperty: clearOnDeactivate
47     * {Boolean} Should the selection be cleared when the control is
48     *     deactivated. Default value is false.
49     */
50    clearOnDeactivate: false,
51
52    /**
53     * APIProperty: layers
54     * {Array(<OpenLayers.Layer.WMS>)} The WMS layers this control will work
55     *     on.
56     */
57    layers: null,
58
59    /**
60     * Property: callbacks
61     * {Object} The functions that are sent to the handler for callback
62     */
63    callbacks: null,
64
65    /**
66     * APIProperty: selectionSymbolizer
67     * {Object} Determines the styling of the selected objects. Default is
68     *     a selection in red.
69     */
70    selectionSymbolizer: {
71        'Polygon': {fillColor: '#FF0000', stroke: false},
72        'Line': {strokeColor: '#FF0000', strokeWidth: 2},
73        'Point': {graphicName: 'square', fillColor: '#FF0000', pointRadius: 5}
74    },
75
76    /**
77     * APIProperty: layerOptions
78     * {Object} The options to apply to the selection layer, by default the
79     *     selection layer will be kept out of the layer switcher.
80     */
81    layerOptions: null,
82
83    /**
84     * APIProperty: handlerOptions
85     * {Object} Used to set non-default properties on the control's handler
86     */
87    handlerOptions: null,
88
89    /**
90     * APIProperty: sketchStyle
91     * {<OpenLayers.Style>|Object} Style or symbolizer to use for the sketch
92     * handler. The recommended way of styling the sketch layer, however, is
93     * to configure an <OpenLayers.StyleMap> in the layerOptions of the
94     * <handlerOptions>:
95     *
96     * (code)
97     * new OpenLayers.Control.SLDSelect(OpenLayers.Handler.Path, {
98     *     handlerOptions: {
99     *         layerOptions: {
100     *             styleMap: new OpenLayers.StyleMap({
101     *                 "default": {strokeColor: "yellow"}
102     *             });
103     *         }
104     *     }
105     * });
106     * (end)
107     */
108    sketchStyle: null,
109
110    /**
111     * APIProperty: wfsCache
112     * {Object} Cache to use for storing parsed results from
113     *     <OpenLayers.Format.WFSDescribeFeatureType.read>. If not provided,
114     *     these will be cached on the prototype.
115     */
116    wfsCache: {},
117
118    /**
119     * APIProperty: layerCache
120     * {Object} Cache to use for storing references to the selection layers.
121     *     Normally each source layer will have exactly 1 selection layer of
122     *     type OpenLayers.Layer.WMS.Post. If not provided, layers will
123     *     be cached on the prototype. Note that if <clearOnDeactivate> is
124     *     true, the layer will no longer be cached after deactivating the
125     *     control.
126     */
127    layerCache: {},
128
129    /**
130     * Constructor: OpenLayers.Control.SLDSelect
131     * Create a new control for selecting features in WMS layers using
132     *     Styled Layer Descriptor (SLD).
133     *
134     * Parameters:
135     * handler - {<OpenLayers.Class>} A sketch handler class. This determines
136     *     the type of selection, e.g. box (<OpenLayers.Handler.Box>), point
137     *     (<OpenLayers.Handler.Point>), path (<OpenLayers.Handler.Path>) or
138     *     polygon (<OpenLayers.Handler.Polygon>) selection. To use circle
139     *     type selection, use <OpenLayers.Handler.RegularPolygon> and pass
140     *     the number of desired sides (e.g. 40) as "sides" property to the
141     *     <handlerOptions>.
142     * options - {Object} An object containing all configuration properties for
143     *     the control.
144     *
145     * Valid options:
146     * layers - Array({<OpenLayers.Layer.WMS>}) The layers to perform the
147     *     selection on.
148     */
149    initialize: function(handler, options) {
150        // concatenate events specific to this control with those from the base
151        this.EVENT_TYPES =
152            OpenLayers.Control.SLDSelect.prototype.EVENT_TYPES.concat(
153            OpenLayers.Control.prototype.EVENT_TYPES
154        );
155        OpenLayers.Control.prototype.initialize.apply(this, [options]);
156
157        this.callbacks = OpenLayers.Util.extend({done: this.select, 
158            click: this.select}, this.callbacks);
159        this.handlerOptions = this.handlerOptions || {};
160        this.layerOptions = OpenLayers.Util.applyDefaults(this.layerOptions, {
161            displayInLayerSwitcher: false
162        });
163        if (this.sketchStyle) {
164            this.handlerOptions.layerOptions = OpenLayers.Util.applyDefaults(
165                this.handlerOptions.layerOptions,
166                {styleMap: new OpenLayers.StyleMap({"default": this.sketchStyle})}
167            );
168        }
169        this.handler = new handler(this, this.callbacks, this.handlerOptions);
170    },
171
172    /**
173     * APIMethod: destroy
174     * Take care of things that are not handled in superclass.
175     */
176    destroy: function() {
177        for (var key in this.layerCache) {
178            delete this.layerCache[key];
179        }
180        for (var key in this.wfsCache) {
181            delete this.wfsCache[key];
182        }
183        OpenLayers.Control.prototype.destroy.apply(this, arguments);
184    },
185
186    /**
187     * Method: coupleLayerVisiblity
188     * Couple the selection layer and the source layer with respect to
189     *     layer visibility. So if the source layer is turned off, the
190     *     selection layer is also turned off.
191     *
192     * Parameters:
193     * evt - {Object}
194     */
195    coupleLayerVisiblity: function(evt) {
196        this.setVisibility(evt.object.getVisibility());
197    },
198
199    /**
200     * Method: createSelectionLayer
201     * Creates a "clone" from the source layer in which the selection can
202     * be drawn. This ensures both the source layer and the selection are
203     * visible and not only the selection.
204     *
205     * Parameters:
206     * source - {<OpenLayers.Layer.WMS>} The source layer on which the selection
207     *     is performed.
208     *
209     * Returns:
210     * {<OpenLayers.Layer.WMS.Post>} A WMS Post layer since SLD selections can
211     *     easily get quite long.
212     */
213    createSelectionLayer: function(source) {
214        // check if we already have a selection layer for the source layer
215        var selectionLayer;
216        if (!this.layerCache[source.id]) {
217            selectionLayer = new OpenLayers.Layer.WMS.Post(source.name, 
218                source.url, source.params, 
219                OpenLayers.Util.applyDefaults(
220                    this.layerOptions,
221                    source.getOptions())
222            );
223            this.layerCache[source.id] = selectionLayer;
224            // make sure the layers are coupled wrt visibility, but only
225            // if they are not displayed in the layer switcher, because in
226            // that case the user cannot control visibility.
227            if (this.layerOptions.displayInLayerSwitcher === false) {
228                source.events.on({
229                    "visibilitychanged": this.coupleLayerVisiblity,
230                    scope: selectionLayer});
231            }
232            this.map.addLayer(selectionLayer);
233        } else {
234            selectionLayer = this.layerCache[source.id];
235        }
236        return selectionLayer;
237    },
238
239    /**
240     * Method: createSLD
241     * Create the SLD document for the layer using the supplied filters.
242     *
243     * Parameters:
244     * layer - {<OpenLayers.Layer.WMS>}
245     * filters - Array({<OpenLayers.Filter>}) The filters to be applied.
246     * geometryAttributes - Array({Object}) The geometry attributes of the
247     *     layer.
248     *
249     * Returns:
250     * {String} The SLD document generated as a string.
251     */
252    createSLD: function(layer, filters, geometryAttributes) {
253        var sld = {version: "1.0.0", namedLayers: {}};
254        var layerNames = [layer.params.LAYERS].join(",").split(",");
255        for (var i=0, len=layerNames.length; i<len; i++) { 
256            var name = layerNames[i];
257            sld.namedLayers[name] = {name: name, userStyles: []};
258            var symbolizer = this.selectionSymbolizer;
259            var geometryAttribute = geometryAttributes[i];
260            if (geometryAttribute.type.indexOf('Polygon') >= 0) {
261                symbolizer = {Polygon: this.selectionSymbolizer['Polygon']};
262            } else if (geometryAttribute.type.indexOf('LineString') >= 0) {
263                symbolizer = {Line: this.selectionSymbolizer['Line']};
264            } else if (geometryAttribute.type.indexOf('Point') >= 0) {
265                symbolizer = {Point: this.selectionSymbolizer['Point']};
266            }
267            var filter = filters[i];
268            sld.namedLayers[name].userStyles.push({name: 'default', rules: [
269                new OpenLayers.Rule({symbolizer: symbolizer, 
270                    filter: filter, 
271                    maxScaleDenominator: layer.options.minScale})
272            ]});
273        }
274        return new OpenLayers.Format.SLD().write(sld);
275    },
276
277    /**
278     * Method: parseDescribeLayer
279     * Parse the SLD WMS DescribeLayer response and issue the corresponding
280     *     WFS DescribeFeatureType request
281     *
282     * request - {XMLHttpRequest} The request object.
283     */
284    parseDescribeLayer: function(request) {
285        var format = new OpenLayers.Format.WMSDescribeLayer();
286        var doc = request.responseXML;
287        if(!doc || !doc.documentElement) {
288            doc = request.responseText;
289        }
290        var describeLayer = format.read(doc);
291        var typeNames = [];
292        var url = null;
293        for (var i=0, len=describeLayer.length; i<len; i++) {
294            // perform a WFS DescribeFeatureType request
295            if (describeLayer[i].owsType == "WFS") {
296                typeNames.push(describeLayer[i].typeName);
297                url = describeLayer[i].owsURL;
298            }
299        }
300        var options = {
301            url: url,
302            params: {
303                SERVICE: "WFS",
304                TYPENAME: typeNames.toString(),
305                REQUEST: "DescribeFeatureType",
306                VERSION: "1.0.0"
307            },
308            callback: function(request) {
309                var format = new OpenLayers.Format.WFSDescribeFeatureType();
310                var doc = request.responseXML;
311                if(!doc || !doc.documentElement) {
312                    doc = request.responseText;
313                }
314                var describeFeatureType = format.read(doc);
315                this.control.wfsCache[this.layer.id] = describeFeatureType;
316                this.control._queue && this.control.applySelection();
317            },
318            scope: this
319        };
320        OpenLayers.Request.GET(options);
321    },
322
323   /**
324    * Method: getGeometryAttributes
325    * Look up the geometry attributes from the WFS DescribeFeatureType response
326    *
327    * Parameters:
328    * layer - {<OpenLayers.Layer.WMS>} The layer for which to look up the
329    *     geometry attributes.
330    *
331    * Returns:
332    * Array({Object}) Array of geometry attributes
333    */ 
334   getGeometryAttributes: function(layer) {
335        var result = [];
336        var cache = this.wfsCache[layer.id];
337        for (var i=0, len=cache.featureTypes.length; i<len; i++) {
338            var typeName = cache.featureTypes[i];
339            var properties = typeName.properties;
340            for (var j=0, lenj=properties.length; j < lenj; j++) {
341                var property = properties[j];
342                var type = property.type;
343                if ((type.indexOf('LineString') >= 0) ||
344                    (type.indexOf('GeometryAssociationType') >=0) ||
345                    (type.indexOf('GeometryPropertyType') >= 0) ||
346                    (type.indexOf('Point') >= 0) ||
347                    (type.indexOf('Polygon') >= 0) ) {
348                        result.push(property);
349                }
350            }
351        }
352        return result;
353    },
354
355    /**
356     * APIMethod: activate
357     * Activate the control. Activating the control will perform a SLD WMS
358     *     DescribeLayer request followed by a WFS DescribeFeatureType request
359     *     so that the proper symbolizers can be chosen based on the geometry
360     *     type.
361     */
362    activate: function() {
363        var activated = OpenLayers.Control.prototype.activate.call(this);
364        if(activated) {
365            for (var i=0, len=this.layers.length; i<len; i++) {
366                var layer = this.layers[i];
367                if (layer && !this.wfsCache[layer.id]) {
368                    var options = {
369                        url: layer.url,
370                        params: {
371                            SERVICE: "WMS",
372                            VERSION: layer.params.VERSION,
373                            LAYERS: layer.params.LAYERS,
374                            REQUEST: "DescribeLayer"
375                        },
376                        callback: this.parseDescribeLayer,
377                        scope: {layer: layer, control: this}
378                    };
379                    OpenLayers.Request.GET(options);
380                }
381            }
382        }
383        return activated;
384    },
385
386    /**
387     * APIMethod: deactivate
388     * Deactivate the control. If clearOnDeactivate is true, remove the
389     *     selection layer(s).
390     */
391    deactivate: function() {
392        var deactivated = OpenLayers.Control.prototype.deactivate.call(this);
393        if(deactivated) {
394            for (var i=0, len=this.layers.length; i<len; i++) {
395                var layer = this.layers[i];
396                if (layer && this.clearOnDeactivate === true) {
397                    var layerCache = this.layerCache;
398                    var selectionLayer = layerCache[layer.id];
399                    if (selectionLayer) {
400                        layer.events.un({
401                            "visibilitychanged": this.coupleLayerVisiblity,
402                            scope: selectionLayer});
403                        selectionLayer.destroy();
404                        delete layerCache[layer.id];
405                    }
406                }
407            }
408        }
409        return deactivated;
410    },
411
412    /**
413     * APIMethod: setLayers
414     * Set the layers on which the selection should be performed.  Call the
415     *     setLayers method if the layer(s) to be used change and the same
416     *     control should be used on a new set of layers.
417     *     If the control is already active, it will be active after the new
418     *     set of layers is set.
419     *
420     * Parameters:
421     * layers - {Array(<OpenLayers.Layer.WMS>)}  The new set of layers on which
422     *     the selection should be performed.
423     */
424    setLayers: function(layers) {
425        if(this.active) {
426            this.deactivate();
427            this.layers = layers;
428            this.activate();
429        } else {
430            this.layers = layers;
431        }
432    },
433
434    /**
435     * Function: createFilter
436     * Create the filter to be used in the SLD.
437     *
438     * Parameters:
439     * geometryAttribute - {Object} Used to get the name of the geometry
440     *     attribute which is needed for constructing the spatial filter.
441     * geometry - {<OpenLayers.Geometry>} The geometry to use.
442     *
443     * Returns:
444     * {<OpenLayers.Filter.Spatial>} The spatial filter created.
445     */
446    createFilter: function(geometryAttribute, geometry) {
447        var filter = null;
448        if (this.handler instanceof OpenLayers.Handler.RegularPolygon) {
449            // box
450            if (this.handler.irregular === true) {
451                filter = new OpenLayers.Filter.Spatial({
452                    type: OpenLayers.Filter.Spatial.BBOX,
453                    property: geometryAttribute.name,
454                    value: geometry.getBounds()}
455                );
456            } else {
457                filter = new OpenLayers.Filter.Spatial({
458                    type: OpenLayers.Filter.Spatial.INTERSECTS,
459                    property: geometryAttribute.name,
460                    value: geometry}
461                );
462            }
463        } else if (this.handler instanceof OpenLayers.Handler.Polygon) {
464            filter = new OpenLayers.Filter.Spatial({
465                type: OpenLayers.Filter.Spatial.INTERSECTS,
466                property: geometryAttribute.name,
467                value: geometry}
468            );
469        } else if (this.handler instanceof OpenLayers.Handler.Path) {
470            // if source layer is point based, use DWITHIN instead
471            if (geometryAttribute.type.indexOf('Point') >= 0) {
472                filter = new OpenLayers.Filter.Spatial({
473                    type: OpenLayers.Filter.Spatial.DWITHIN,
474                    property: geometryAttribute.name,
475                    distance: this.map.getExtent().getWidth()*0.01 ,
476                    distanceUnits: this.map.getUnits(),
477                    value: geometry}
478                );
479            } else {
480                filter = new OpenLayers.Filter.Spatial({
481                    type: OpenLayers.Filter.Spatial.INTERSECTS,
482                    property: geometryAttribute.name,
483                    value: geometry}
484                );
485            }
486        } else if (this.handler instanceof OpenLayers.Handler.Click) {
487            if (geometryAttribute.type.indexOf('Polygon') >= 0) {
488                filter = new OpenLayers.Filter.Spatial({
489                    type: OpenLayers.Filter.Spatial.INTERSECTS,
490                    property: geometryAttribute.name,
491                    value: geometry}
492                );
493            } else {
494                filter = new OpenLayers.Filter.Spatial({
495                    type: OpenLayers.Filter.Spatial.DWITHIN,
496                    property: geometryAttribute.name,
497                    distance: this.map.getExtent().getWidth()*0.01 ,
498                    distanceUnits: this.map.getUnits(),
499                    value: geometry}
500                );
501            }
502        }
503        return filter;
504    },
505
506    /**
507     * Method: select
508     * When the handler is done, use SLD_BODY on the selection layer to
509     *     display the selection in the map.
510     *
511     * Parameters:
512     * geometry - {Object} or {<OpenLayers.Geometry>}
513     */
514    select: function(geometry) {
515        this._queue = function() {
516            for (var i=0, len=this.layers.length; i<len; i++) {
517                var layer = this.layers[i];
518                var geometryAttributes = this.getGeometryAttributes(layer);
519                var filters = [];
520                for (var j=0, lenj=geometryAttributes.length; j<lenj; j++) {
521                    var geometryAttribute = geometryAttributes[j];
522                    if (geometryAttribute !== null) {
523                        // from the click handler we will not get an actual
524                        // geometry so transform
525                        if (!(geometry instanceof OpenLayers.Geometry)) {
526                            var point = this.map.getLonLatFromPixel(
527                                geometry.xy);
528                            geometry = new OpenLayers.Geometry.Point(
529                                point.lon, point.lat);
530                        }
531                        var filter = this.createFilter(geometryAttribute,
532                        geometry);
533                        if (filter !== null) {
534                            filters.push(filter);
535                        }
536                    }
537                }
538   
539                var selectionLayer = this.createSelectionLayer(layer);
540                var sld = this.createSLD(layer, filters, geometryAttributes);
541   
542                this.events.triggerEvent("selected", {
543                    layer: layer,
544                    filters: filters
545                });
546   
547                selectionLayer.mergeNewParams({SLD_BODY: sld});
548                delete this._queue;
549            }
550        };
551        this.applySelection();
552    },
553   
554    /**
555     * Method: applySelection
556     * Checks if all required wfs data is cached, and applies the selection
557     */
558    applySelection: function() {
559        var canApply = true;
560        for (var i=0, len=this.layers.length; i<len; i++) {
561            if(!this.wfsCache[this.layers[i].id]) {
562                canApply = false;
563                break;
564            }
565        }
566        canApply && this._queue.call(this);
567    },
568
569    CLASS_NAME: "OpenLayers.Control.SLDSelect"
570});
Note: See TracBrowser for help on using the repository browser.