OpenLayers OpenLayers

Ticket #1241: measure.patch

File measure.patch, 15.8 kB (added by tschaub, 2 years ago)

basic measure control

  • lib/OpenLayers/Control/Measure.js

    old new  
     1/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD 
     2 * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the 
     3 * full text of the license. */ 
     4 
     5/** 
     6 * @requires OpenLayers/Control.js 
     7 * @requires OpenLayers/Feature/Vector.js 
     8 */ 
     9 
     10/** 
     11 * Class: OpenLayers.Control.Measure 
     12 * Allows for drawing of features for measurements. 
     13 * 
     14 * Inherits from: 
     15 *  - <OpenLayers.Control> 
     16 */ 
     17OpenLayers.Control.Measure = OpenLayers.Class(OpenLayers.Control, { 
     18 
     19    /** 
     20     * APIProperty: handlerOptions 
     21     * {Object} Used to set non-default properties on the control's handler 
     22     */ 
     23    handlerOptions: null, 
     24     
     25    /** 
     26     * APIProperty: onMeasure 
     27     * {Function} After a geometry is drawn, onMeasure is called with three 
     28     *     arguments: the geometry, its length, and its area. 
     29     */ 
     30    onMeasure: function() {}, 
     31     
     32    /** 
     33     * Property: callbacks 
     34     * {Object} The functions that are sent to the handler for callback 
     35     */ 
     36    callbacks: null, 
     37     
     38    /** 
     39     * Property: displayUnits 
     40     * {String} Units for output.  Must be one of 'in', 'ft', 'mi', 'm', 'km', 
     41     *     or 'dd'.  If null, displayUnits will be assumed to be the same as 
     42     *     map units. 
     43     */ 
     44    displayUnits: null, 
     45 
     46    /** 
     47     * Constructor: OpenLayers.Control.Measure 
     48     *  
     49     * Parameters: 
     50     * handler - {<OpenLayers.Handler>}  
     51     * options - {Object}  
     52     */ 
     53    initialize: function(handler, options) { 
     54        OpenLayers.Control.prototype.initialize.apply(this, [options]); 
     55        this.callbacks = OpenLayers.Util.extend( 
     56            {done: this.measureGeometry, point: this.partialMeasure}, 
     57            this.callbacks 
     58        ); 
     59        this.handler = new handler(this, this.callbacks, this.handlerOptions); 
     60    }, 
     61 
     62    /** 
     63     * Method: measureGeometry 
     64     */ 
     65    measureGeometry: function(geometry) { 
     66        var area = this.getArea(geometry); 
     67        var length = this.getLength(geometry); 
     68        this.onMeasure(geometry, length, area, this.displayUnits); 
     69    }, 
     70     
     71    /** 
     72     * Method: getArea 
     73     */ 
     74    getArea: function(geometry) { 
     75        var area = geometry.getArea(); 
     76        var inPerDisplayUnit = OpenLayers.INCHES_PER_UNIT[this.displayUnits]; 
     77        if(inPerDisplayUnit) { 
     78            var inPerMapUnit = OpenLayers.INCHES_PER_UNIT[this.map.units]; 
     79            area *= Math.pow((inPerMapUnit / inPerDisplayUnit), 2); 
     80        } 
     81        return area; 
     82    }, 
     83     
     84    /** 
     85     * Method: getLength 
     86     */ 
     87    getLength: function(geometry) { 
     88        var length = geometry.getLength(); 
     89        var inPerDisplayUnit = OpenLayers.INCHES_PER_UNIT[this.displayUnits]; 
     90        if(inPerDisplayUnit) { 
     91            var inPerMapUnit = OpenLayers.INCHES_PER_UNIT[this.map.units]; 
     92            length *= (inPerMapUnit / inPerDisplayUnit); 
     93        } 
     94        return length; 
     95    }, 
     96 
     97    CLASS_NAME: "OpenLayers.Control.Measure" 
     98}); 
  • lib/OpenLayers/Handler/Polygon.js

    old new  
    5959        this.polygon.geometry.addComponent(this.line.geometry); 
    6060        this.point = new OpenLayers.Feature.Vector( 
    6161                                        new OpenLayers.Geometry.Point()); 
     62        this.layer.addFeatures([this.polygon, this.point]); 
    6263    }, 
    6364 
    6465    /** 
     
    6768     */ 
    6869    destroyFeature: function() { 
    6970        OpenLayers.Handler.Path.prototype.destroyFeature.apply(this); 
    70         if(this.polygon) { 
    71             this.polygon.destroy(); 
    72         } 
    7371        this.polygon = null; 
    7472    }, 
    7573 
     
    102100     * {<OpenLayers.Geometry.Polygon>} 
    103101     */ 
    104102    geometryClone: function() { 
    105         return this.polygon.geometry.clone(); 
     103        var geometry = this.polygon.geometry.clone(); 
     104        if(this.multi) { 
     105            geometry = new OpenLayers.Geometry.MultiPolygon([geometry]); 
     106        } 
     107        return geometry; 
    106108    }, 
    107109 
    108110    /** 
     
    118120            // remove the penultimate point 
    119121            var index = this.line.geometry.components.length - 2; 
    120122            this.line.geometry.removeComponent(this.line.geometry.components[index]); 
     123            if(this.persist) { 
     124                this.destroyPoint(); 
     125            } 
    121126            this.finalize(); 
    122127        } 
    123128        return false; 
  • lib/OpenLayers/Handler/Point.js

    old new  
    3333    layer: null, 
    3434     
    3535    /** 
     36     * Property: multi 
     37     * {Boolean} Cast features to multi-part geometries before passing to the 
     38     *     layer.  Default is false. 
     39     */ 
     40    multi: false, 
     41 
     42    /** 
    3643     * Property: drawing  
    3744     * {Boolean} A point is being drawn 
    3845     */ 
     
    5764    lastUp: null, 
    5865 
    5966    /** 
     67     * APIProperty: persist 
     68     * {Boolean} Leave the feature rendered until destroyFeature is called. 
     69     *     Default is false.  If set to true, the feature remains rendered until 
     70     *     destroyFeature is called, typically by deactivating the handler or 
     71     *     starting another drawing. 
     72     */ 
     73    persist: false, 
     74 
     75    /** 
    6076     * Constructor: OpenLayers.Handler.Point 
    6177     * Create a new point handler. 
    6278     * 
     
    108124     */ 
    109125    createFeature: function() { 
    110126        this.point = new OpenLayers.Feature.Vector( 
    111                                               new OpenLayers.Geometry.Point()); 
     127            new OpenLayers.Geometry.Point() 
     128        ); 
     129        this.layer.addFeatures([this.point]); 
    112130    }, 
    113131 
    114132    /** 
     
    123141        if(this.drawing) { 
    124142            this.cancel(); 
    125143        } 
     144        this.destroyFeature(); 
    126145        // If a layer's map property is set to null, it means that that layer 
    127146        // isn't added to the map. Since we ourself added the layer to the map 
    128147        // in activate(), we can assume that if this.layer.map is null it means 
     
    140159     * Destroy the temporary geometries 
    141160     */ 
    142161    destroyFeature: function() { 
    143         if(this.point) { 
    144             this.point.destroy(); 
    145         } 
     162        this.layer.destroyFeatures(); 
    146163        this.point = null; 
    147164    }, 
    148165 
    149166    /** 
    150167     * Method: finalize 
    151168     * Finish the geometry and call the "done" callback. 
     169     * 
     170     * Parameters: 
     171     * cancel - {Boolean} Call cancel instead of done callback.  Default is 
     172     *     false. 
    152173     */ 
    153     finalize: function() { 
    154         this.layer.renderer.clear()
     174    finalize: function(cancel) { 
     175        var key = cancel ? "cancel" : "done"
    155176        this.drawing = false; 
    156177        this.mouseDown = false; 
    157178        this.lastDown = null; 
    158179        this.lastUp = null; 
    159         this.callback("done", [this.geometryClone()]); 
    160         this.destroyFeature(); 
     180        this.callback(key, [this.geometryClone()]); 
     181        if(cancel || !this.persist) { 
     182            this.destroyFeature(); 
     183        } 
    161184    }, 
    162185 
    163186    /** 
     
    165188     * Finish the geometry and call the "cancel" callback. 
    166189     */ 
    167190    cancel: function() { 
    168         this.layer.renderer.clear(); 
    169         this.drawing = false; 
    170         this.mouseDown = false; 
    171         this.lastDown = null; 
    172         this.lastUp = null; 
    173         this.callback("cancel", [this.geometryClone()]); 
    174         this.destroyFeature(); 
     191        this.finalize(true); 
    175192    }, 
    176193 
    177194    /** 
     
    222239     * {<OpenLayers.Geometry.Point>} 
    223240     */ 
    224241    geometryClone: function() { 
    225         return this.point.geometry.clone(); 
     242        var geometry = this.point.geometry.clone(); 
     243        if(this.multi) { 
     244            geometry = new OpenLayers.Geometry.MultiPoint([geometry]); 
     245        } 
     246        return geometry; 
    226247    }, 
    227    
     248 
    228249    /** 
    229250     * Method: mousedown 
    230251     * Handle mouse down.  Adjust the geometry and redraw. 
     
    246267            return true; 
    247268        } 
    248269        if(this.lastDown == null) { 
     270            if(this.persist) { 
     271                this.destroyFeature(); 
     272            } 
    249273            this.createFeature(); 
    250274        } 
    251275        this.lastDown = evt.xy; 
  • lib/OpenLayers/Handler/Path.js

    old new  
    7373                                        new OpenLayers.Geometry.LineString()); 
    7474        this.point = new OpenLayers.Feature.Vector( 
    7575                                        new OpenLayers.Geometry.Point()); 
     76        this.layer.addFeatures([this.line, this.point]); 
    7677    }, 
    7778         
    7879    /** 
     
    8182     */ 
    8283    destroyFeature: function() { 
    8384        OpenLayers.Handler.Point.prototype.destroyFeature.apply(this); 
    84         if(this.line) { 
    85             this.line.destroy(); 
    86         } 
    8785        this.line = null; 
    8886    }, 
     87 
     88    /** 
     89     * Method: destroyPoint 
     90     * Destroy the temporary point. 
     91     */ 
     92    destroyPoint: function() { 
     93        if(this.point) { 
     94            this.layer.destroyFeatures([this.point]); 
     95        } 
     96    }, 
    8997     
    9098    /** 
    9199     * Method: addPoint 
     
    138146     * {<OpenLayers.Geometry.LineString>} 
    139147     */ 
    140148    geometryClone: function() { 
    141         return this.line.geometry.clone(); 
     149        var geometry = this.line.geometry.clone(); 
     150        if(this.multi) { 
     151            geometry = new OpenLayers.Geometry.MultiLineString([geometry]); 
     152        } 
     153        return geometry; 
    142154    }, 
    143155 
    144156    /** 
     
    158170            return false; 
    159171        } 
    160172        if(this.lastDown == null) { 
     173            if(this.persist) { 
     174                this.destroyFeature(); 
     175            } 
    161176            this.createFeature(); 
    162177        } 
    163178        this.mouseDown = true; 
     
    214229        this.mouseDown = false; 
    215230        if(this.drawing) { 
    216231            if(this.freehandMode(evt)) { 
     232                if(this.persist) { 
     233                    this.destroyPoint(); 
     234                } 
    217235                this.finalize(); 
    218236            } else { 
    219237                if(this.lastUp == null) { 
     
    241259        if(!this.freehandMode(evt)) { 
    242260            var index = this.line.geometry.components.length - 1; 
    243261            this.line.geometry.removeComponent(this.line.geometry.components[index]); 
     262            if(this.persist) { 
     263                this.destroyPoint(); 
     264            } 
    244265            this.finalize(); 
    245266        } 
    246267        return false; 
  • lib/OpenLayers.js

    old new  
    147147            "OpenLayers/Control/DragPan.js", 
    148148            "OpenLayers/Control/Navigation.js", 
    149149            "OpenLayers/Control/MouseDefaults.js", 
     150            "OpenLayers/Control/Measure.js", 
    150151            "OpenLayers/Control/MousePosition.js", 
    151152            "OpenLayers/Control/OverviewMap.js", 
    152153            "OpenLayers/Control/KeyboardDefaults.js", 
  • examples/measure.html

    old new  
     1<html xmlns="http://www.w3.org/1999/xhtml"> 
     2  <head> 
     3    <link rel="stylesheet" href="../theme/default/style.css" type="text/css" /> 
     4    <link rel="stylesheet" href="style.css" type="text/css" /> 
     5    <style type="text/css"> 
     6        #controlToggle li { 
     7            list-style: none; 
     8        } 
     9        p { 
     10            width: 512px; 
     11        } 
     12        #options { 
     13            position: relative; 
     14            width: 512px; 
     15        } 
     16        #output { 
     17            float: right; 
     18        } 
     19    </style> 
     20    <script src="../lib/OpenLayers.js"></script> 
     21    <script type="text/javascript"> 
     22        var map, measureControls; 
     23        OpenLayers.Util.onImageLoadErrorColor = "transparent"; 
     24        function init(){ 
     25            map = new OpenLayers.Map('map'); 
     26             
     27            var wmsLayer = new OpenLayers.Layer.WMS( "OpenLayers WMS",  
     28                "http://labs.metacarta.com/wms/vmap0?", {layers: 'basic'});  
     29 
     30            map.addLayers([wmsLayer]); 
     31            map.addControl(new OpenLayers.Control.LayerSwitcher()); 
     32            map.addControl(new OpenLayers.Control.MousePosition()); 
     33             
     34            var options = { 
     35                displayUnits: 'km', 
     36                handlerOptions: { 
     37                    persist: true 
     38                } 
     39            }; 
     40            var circleOptions = { 
     41                displayUnits: 'km', 
     42                handlerOptions: { 
     43                    sides: 35, 
     44                    persist: true 
     45                } 
     46            }; 
     47            measureControls = { 
     48                line: new OpenLayers.Control.Measure( 
     49                  OpenLayers.Handler.Path, options 
     50                ), 
     51                polygon: new OpenLayers.Control.Measure( 
     52                    OpenLayers.Handler.Polygon, options 
     53                ), 
     54                circle: new OpenLayers.Control.Measure( 
     55                    OpenLayers.Handler.RegularPolygon, circleOptions 
     56                ) 
     57            }; 
     58             
     59            var control; 
     60            for(var key in measureControls) { 
     61                control = measureControls[key]; 
     62                control.onMeasure = handleMeasurements; 
     63                map.addControl(control); 
     64            } 
     65             
     66            map.setCenter(new OpenLayers.LonLat(0, 0), 3); 
     67             
     68            document.getElementById('noneToggle').checked = true; 
     69        } 
     70         
     71        function handleMeasurements(geometry, length, area, units) { 
     72            var element = document.getElementById('output'); 
     73            var out = ""; 
     74            if(geometry.CLASS_NAME == "OpenLayers.Geometry.LineString") { 
     75                out += "length: " + length.toFixed(3) + " " + units; 
     76            } else { 
     77                out += "perimeter: " + length.toFixed(3) + " " + units + "<br />"; 
     78                out += "area: " + area.toFixed(3) + " " + units + "<sup>2</" + "sup>"; 
     79            } 
     80            element.innerHTML = out; 
     81        } 
     82 
     83        function toggleControl(element) { 
     84            for(key in measureControls) { 
     85                var control = measureControls[key]; 
     86                if(element.value == key && element.checked) { 
     87                    control.activate(); 
     88                } else { 
     89                    control.deactivate(); 
     90                } 
     91            } 
     92        } 
     93    </script> 
     94  </head> 
     95  <body onload="init()"> 
     96    <h1 id="title">OpenLayers Measure Example</h1> 
     97    <p id="shortdesc"> 
     98        Demonstrates the measure control to measure distances and areas. 
     99    </p> 
     100    <div id="map" class="smallmap"></div> 
     101    <div id="options"> 
     102        <div id="output"> 
     103        </div> 
     104        <ul id="controlToggle"> 
     105            <li> 
     106                <input type="radio" name="type" value="none" id="noneToggle" 
     107                       onclick="toggleControl(this);" checked="checked" /> 
     108                <label for="noneToggle">navigate</label> 
     109            </li> 
     110            <li> 
     111                <input type="radio" name="type" value="line" id="lineToggle" onclick="toggleControl(this);" /> 
     112                <label for="lineToggle">draw line</label> 
     113            </li> 
     114            <li> 
     115                <input type="radio" name="type" value="polygon" id="polygonToggle" onclick="toggleControl(this);" /> 
     116                <label for="polygonToggle">draw polygon</label> 
     117            </li> 
     118            <li> 
     119                <input type="radio" name="type" value="circle" id="circleToggle" onclick="toggleControl(this);" /> 
     120                <label for="circleToggle">draw circle</label> 
     121            </li> 
     122        </ul> 
     123    </div> 
     124  </body> 
     125</html>