| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385 |
- /* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the Clear BSD license.
- * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
- * full text of the license. */
- /**
- * @requires OpenLayers/Control.js
- * @requires OpenLayers/Feature/Vector.js
- */
- /**
- * Class: OpenLayers.Control.Measure
- * Allows for drawing of features for measurements.
- *
- * Inherits from:
- * - <OpenLayers.Control>
- */
- OpenLayers.Control.Measure = OpenLayers.Class(OpenLayers.Control, {
- /**
- * Constant: EVENT_TYPES
- * {Array(String)} Supported application event types. Register a listener
- * for a particular event with the following syntax:
- * (code)
- * control.events.register(type, obj, listener);
- * (end)
- *
- * Listeners will be called with a reference to an event object. The
- * properties of this event depends on exactly what happened.
- *
- * Supported control event types (in addition to those from <OpenLayers.Control>):
- * measure - Triggered when a measurement sketch is complete. Listeners
- * will receive an event with measure, units, order, and geometry
- * properties.
- * measurepartial - Triggered when a new point is added to the
- * measurement sketch or if the <immediate> property is true and the
- * measurement sketch is modified. Listeners receive an event with measure,
- * units, order, and geometry.
- */
- EVENT_TYPES: ['measure', 'measurepartial'],
- /**
- * APIProperty: handlerOptions
- * {Object} Used to set non-default properties on the control's handler
- */
- handlerOptions: null,
-
- /**
- * Property: callbacks
- * {Object} The functions that are sent to the handler for callback
- */
- callbacks: null,
-
- /**
- * Property: displaySystem
- * {String} Display system for output measurements. Supported values
- * are 'english', 'metric', and 'geographic'. Default is 'metric'.
- */
- displaySystem: 'metric',
-
- /**
- * Property: geodesic
- * {Boolean} Calculate geodesic metrics instead of planar metrics. This
- * requires that geometries can be transformed into Geographic/WGS84
- * (if that is not already the map projection). Default is false.
- */
- geodesic: false,
-
- /**
- * Property: displaySystemUnits
- * {Object} Units for various measurement systems. Values are arrays
- * of unit abbreviations (from OpenLayers.INCHES_PER_UNIT) in decreasing
- * order of length.
- */
- displaySystemUnits: {
- geographic: ['dd'],
- english: ['mi', 'ft', 'in'],
- metric: ['km', 'm']
- },
- /**
- * Property: delay
- * {Number} Number of milliseconds between clicks before the event is
- * considered a double-click. The "measurepartial" event will not
- * be triggered if the sketch is completed within this time. This
- * is required for IE where creating a browser reflow (if a listener
- * is modifying the DOM by displaying the measurement values) messes
- * with the dblclick listener in the sketch handler.
- */
- partialDelay: 300,
- /**
- * Property: delayedTrigger
- * {Number} Timeout id of trigger for measurepartial.
- */
- delayedTrigger: null,
- /**
- * APIProperty: persist
- * {Boolean} Keep the temporary measurement sketch drawn after the
- * measurement is complete. The geometry will persist until a new
- * measurement is started, the control is deactivated, or <cancel> is
- * called.
- */
- persist: false,
- /**
- * APIProperty: immediate
- * {Boolean} Activates the immediate measurement so that the "measurepartial"
- * event is also fired once the measurement sketch is modified.
- * Default is false.
- */
- immediate : false,
- /**
- * Constructor: OpenLayers.Control.Measure
- *
- * Parameters:
- * handler - {<OpenLayers.Handler>}
- * options - {Object}
- */
- initialize: function(handler, options) {
- // concatenate events specific to measure with those from the base
- this.EVENT_TYPES =
- OpenLayers.Control.Measure.prototype.EVENT_TYPES.concat(
- OpenLayers.Control.prototype.EVENT_TYPES
- );
- OpenLayers.Control.prototype.initialize.apply(this, [options]);
- var callbacks = {done: this.measureComplete,
- point: this.measurePartial};
- if (this.immediate){
- callbacks.modify = this.measureImmediate;
- }
- this.callbacks = OpenLayers.Util.extend(callbacks, this.callbacks);
- // let the handler options override, so old code that passes 'persist'
- // directly to the handler does not need an update
- this.handlerOptions = OpenLayers.Util.extend(
- {persist: this.persist}, this.handlerOptions
- );
- this.handler = new handler(this, this.callbacks, this.handlerOptions);
- },
-
- /**
- * APIMethod: deactivate
- */
- deactivate: function() {
- this.cancelDelay();
- return OpenLayers.Control.prototype.deactivate.apply(this, arguments);
- },
- /**
- * APIMethod: cancel
- * Stop the control from measuring. If <persist> is true, the temporary
- * sketch will be erased.
- */
- cancel: function() {
- this.cancelDelay();
- this.handler.cancel();
- },
- /**
- * APIMethod: setImmediate
- * Sets the <immediate> property. Changes the activity of immediate
- * measurement.
- */
- setImmediate: function(immediate) {
- this.immediate = immediate;
- if (this.immediate){
- this.callbacks.modify = this.measureImmediate;
- } else {
- delete this.callbacks.modify;
- }
- },
-
- /**
- * Method: updateHandler
- *
- * Parameters:
- * handler - {Function} One of the sketch handler constructors.
- * options - {Object} Options for the handler.
- */
- updateHandler: function(handler, options) {
- var active = this.active;
- if(active) {
- this.deactivate();
- }
- this.handler = new handler(this, this.callbacks, options);
- if(active) {
- this.activate();
- }
- },
- /**
- * Method: measureComplete
- * Called when the measurement sketch is done.
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>}
- */
- measureComplete: function(geometry) {
- this.cancelDelay();
- this.measure(geometry, "measure");
- },
-
- /**
- * Method: measurePartial
- * Called each time a new point is added to the measurement sketch.
- *
- * Parameters:
- * point - {<OpenLayers.Geometry.Point>} The last point added.
- * geometry - {<OpenLayers.Geometry>} The sketch geometry.
- */
- measurePartial: function(point, geometry) {
- this.cancelDelay();
- geometry = geometry.clone();
- // when we're wating for a dblclick, we have to trigger measurepartial
- // after some delay to deal with reflow issues in IE
- if (this.handler.freehandMode(this.handler.evt)) {
- // no dblclick in freehand mode
- this.measure(geometry, "measurepartial");
- } else {
- this.delayedTrigger = window.setTimeout(
- OpenLayers.Function.bind(function() {
- this.delayedTrigger = null;
- this.measure(geometry, "measurepartial");
- }, this),
- this.partialDelay
- );
- }
- },
- /**
- * Method: measureImmediate
- * Called each time the measurement sketch is modified.
- *
- * Parameters: point - {<OpenLayers.Geometry.Point>} The point at the
- * mouseposition. feature - {<OpenLayers.Feature.Vector>} The sketch feature.
- */
- measureImmediate : function(point, feature, drawing) {
- if (drawing && this.delayedTrigger === null &&
- !this.handler.freehandMode(this.handler.evt)) {
- this.measure(feature.geometry, "measurepartial");
- }
- },
- /**
- * Method: cancelDelay
- * Cancels the delay measurement that measurePartial began.
- */
- cancelDelay: function() {
- if (this.delayedTrigger !== null) {
- window.clearTimeout(this.delayedTrigger);
- this.delayedTrigger = null;
- }
- },
- /**
- * Method: measure
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>}
- * eventType - {String}
- */
- measure: function(geometry, eventType) {
- var stat, order;
- if(geometry.CLASS_NAME.indexOf('LineString') > -1) {
- stat = this.getBestLength(geometry);
- order = 1;
- } else {
- stat = this.getBestArea(geometry);
- order = 2;
- }
- this.events.triggerEvent(eventType, {
- measure: stat[0],
- units: stat[1],
- order: order,
- geometry: geometry
- });
- },
-
- /**
- * Method: getBestArea
- * Based on the <displaySystem> returns the area of a geometry.
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {Array([Float, String])} Returns a two item array containing the
- * area and the units abbreviation.
- */
- getBestArea: function(geometry) {
- var units = this.displaySystemUnits[this.displaySystem];
- var unit, area;
- for(var i=0, len=units.length; i<len; ++i) {
- unit = units[i];
- area = this.getArea(geometry, unit);
- if(area > 1) {
- break;
- }
- }
- return [area, unit];
- },
-
- /**
- * Method: getArea
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>}
- * units - {String} Unit abbreviation
- *
- * Returns:
- * {Float} The geometry area in the given units.
- */
- getArea: function(geometry, units) {
- var area, geomUnits;
- if(this.geodesic) {
- area = geometry.getGeodesicArea(this.map.getProjectionObject());
- geomUnits = "m";
- } else {
- area = geometry.getArea();
- geomUnits = this.map.getUnits();
- }
- var inPerDisplayUnit = OpenLayers.INCHES_PER_UNIT[units];
- if(inPerDisplayUnit) {
- var inPerMapUnit = OpenLayers.INCHES_PER_UNIT[geomUnits];
- area *= Math.pow((inPerMapUnit / inPerDisplayUnit), 2);
- }
- return area;
- },
-
- /**
- * Method: getBestLength
- * Based on the <displaySystem> returns the length of a geometry.
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {Array([Float, String])} Returns a two item array containing the
- * length and the units abbreviation.
- */
- getBestLength: function(geometry) {
- var units = this.displaySystemUnits[this.displaySystem];
- var unit, length;
- for(var i=0, len=units.length; i<len; ++i) {
- unit = units[i];
- length = this.getLength(geometry, unit);
- if(length > 1) {
- break;
- }
- }
- return [length, unit];
- },
- /**
- * Method: getLength
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>}
- * units - {String} Unit abbreviation
- *
- * Returns:
- * {Float} The geometry length in the given units.
- */
- getLength: function(geometry, units) {
- var length, geomUnits;
- if(this.geodesic) {
- length = geometry.getGeodesicLength(this.map.getProjectionObject());
- geomUnits = "m";
- } else {
- length = geometry.getLength();
- geomUnits = this.map.getUnits();
- }
- var inPerDisplayUnit = OpenLayers.INCHES_PER_UNIT[units];
- if(inPerDisplayUnit) {
- var inPerMapUnit = OpenLayers.INCHES_PER_UNIT[geomUnits];
- length *= (inPerMapUnit / inPerDisplayUnit);
- }
- return length;
- },
- CLASS_NAME: "OpenLayers.Control.Measure"
- });
|