From f935c599d1d114328438acc44e0240f3862e1aec Mon Sep 17 00:00:00 2001 From: euzuro Date: Fri, 5 Sep 2008 15:07:59 +0000 Subject: [PATCH] Added a control for drawing geometries and returning basic metrics (length / area). Patch by tschaub, review by elemoine. (Closes #1241) git-svn-id: http://svn.openlayers.org/trunk/openlayers@7965 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf --- examples/measure.html | 149 ++++++++++++++++++ lib/OpenLayers/Control/Measure.js | 246 ++++++++++++++++++++++++++++++ 2 files changed, 395 insertions(+) create mode 100644 examples/measure.html create mode 100644 lib/OpenLayers/Control/Measure.js diff --git a/examples/measure.html b/examples/measure.html new file mode 100644 index 0000000000..94bc4000e1 --- /dev/null +++ b/examples/measure.html @@ -0,0 +1,149 @@ + + + + + + + + + +

OpenLayers Measure Example

+

+ Demonstrates the measure control to measure distances and areas. +

+
+
+
+
+ +
+ + diff --git a/lib/OpenLayers/Control/Measure.js b/lib/OpenLayers/Control/Measure.js new file mode 100644 index 0000000000..0a5be55e5a --- /dev/null +++ b/lib/OpenLayers/Control/Measure.js @@ -0,0 +1,246 @@ +/* Copyright (c) 2006-2008 MetaCarta, Inc., 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.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 ): + * - *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. 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: 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'] + }, + + /** + * Constructor: OpenLayers.Control.Measure + * + * Parameters: + * 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]); + this.callbacks = OpenLayers.Util.extend( + {done: this.measureComplete, point: this.measurePartial}, + this.callbacks + ); + this.handler = new handler(this, this.callbacks, this.handlerOptions); + }, + + /** + * 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 - {} + */ + measureComplete: function(geometry) { + this.measure(geometry, "measure"); + }, + + /** + * Method: measurePartial + * Called each time a new point is added to the measurement sketch. + * + * Parameters: + * point - {} The last point added. + * geometry - {} The sketch geometry. + */ + measurePartial: function(point, geometry) { + this.measure(geometry, "measurepartial"); + }, + + /** + * Method: measure + * + * Parameters: + * 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 returns the area of a geometry. + * + * Parameters: + * 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 1) { + break; + } + } + return [area, unit]; + }, + + /** + * Method: getArea + * + * Parameters: + * geometry - {} + * units - {String} Unit abbreviation + * + * Returns: + * {Float} The geometry area in the given units. + */ + getArea: function(geometry, units) { + var area = geometry.getArea(); + var inPerDisplayUnit = OpenLayers.INCHES_PER_UNIT[units]; + if(inPerDisplayUnit) { + var inPerMapUnit = OpenLayers.INCHES_PER_UNIT[this.map.getUnits()]; + area *= Math.pow((inPerMapUnit / inPerDisplayUnit), 2); + } + return area; + }, + + /** + * Method: getBestLength + * Based on the returns the length of a geometry. + * + * Parameters: + * 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 1) { + break; + } + } + return [length, unit]; + }, + + /** + * Method: getLength + * + * Parameters: + * geometry - {} + * units - {String} Unit abbreviation + * + * Returns: + * {Float} The geometry length in the given units. + */ + getLength: function(geometry, units) { + var length = geometry.getLength(); + var inPerDisplayUnit = OpenLayers.INCHES_PER_UNIT[units]; + if(inPerDisplayUnit) { + var inPerMapUnit = OpenLayers.INCHES_PER_UNIT[this.map.getUnits()]; + length *= (inPerMapUnit / inPerDisplayUnit); + } + return length; + }, + + CLASS_NAME: "OpenLayers.Control.Measure" +});