[OpenLayers-Commits] r12237 - in sandbox/mpriour/temporal_map/openlayers/lib: . OpenLayers/Control OpenLayers/Control/TimeManager OpenLayers/Layer

commits-20090109 at openlayers.org commits-20090109 at openlayers.org
Fri Aug 12 00:00:59 EDT 2011


Author: mpriour
Date: 2011-08-11 21:00:58 -0700 (Thu, 11 Aug 2011)
New Revision: 12237

Added:
   sandbox/mpriour/temporal_map/openlayers/lib/OpenLayers/Control/TimeManager.js
   sandbox/mpriour/temporal_map/openlayers/lib/OpenLayers/Control/TimeManager/
   sandbox/mpriour/temporal_map/openlayers/lib/OpenLayers/Control/TimeManager/WMS.js
Modified:
   sandbox/mpriour/temporal_map/openlayers/lib/OpenLayers.js
   sandbox/mpriour/temporal_map/openlayers/lib/OpenLayers/Layer/WMS.js
Log:
Initial commit of TimeManager controls.
OpenLayers.Control.TimeManager contains all the API functions needed to interact with a slider control.
OpenLayers/Control/TimeManager/WMS.js is just skeleton code.

Added: sandbox/mpriour/temporal_map/openlayers/lib/OpenLayers/Control/TimeManager/WMS.js
===================================================================
--- sandbox/mpriour/temporal_map/openlayers/lib/OpenLayers/Control/TimeManager/WMS.js	                        (rev 0)
+++ sandbox/mpriour/temporal_map/openlayers/lib/OpenLayers/Control/TimeManager/WMS.js	2011-08-12 04:00:58 UTC (rev 12237)
@@ -0,0 +1,55 @@
+/* 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/TimeManager.js
+ */
+
+/**
+ * Class: OpenLayers.Control.TimeManager.WMS
+ * Control to display and animate WMS layers across time.
+ * This control is created by {OpenLayers.Control.TimeManager} instances
+ *
+ * Inherits From:
+ *  - <OpenLayers.Control.TimeManager>
+ */
+OpenLayers.Control.TimeManager.WMS = OpenLayers.Class(OpenLayers.Control.TimeManager, {
+	/**
+	 * Property: useLastValidInterval
+	 * {Boolean} If true and a wms layer has distinct valid time intervals,
+	 *     then continue to display it using the last valid time within the
+	 *     overall control time range
+	 */
+	useLastValidInterval:true,
+	
+	/**
+	 * Property: parentControl
+	 * {<OpenLayers.Control.TimeManager>}
+	 */
+	parentControl:null,
+	
+	/**
+     * Constructor: OpenLayers.Control.TimeManager.WMS
+     * Create a new time manager control for temporal WMS layers.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     control.
+     */
+	initialize:function(options){
+		options = options||{};
+		OpenLayers.Util.extend(this,options);
+		this.range = this.buildRange(this.layers);
+	},
+	
+	onTick:function(evt){
+		this.currentTime = evt.currentTime;
+		if(this.currentTime<=this.range[1] && this.currentTime>=this.range[0]){
+			//TODO: Implement time tick for WMS layers
+		}
+	},
+	CLASS_NAME:'OpenLayers.Control.TimeManager.WMS'
+});
\ No newline at end of file

Added: sandbox/mpriour/temporal_map/openlayers/lib/OpenLayers/Control/TimeManager.js
===================================================================
--- sandbox/mpriour/temporal_map/openlayers/lib/OpenLayers/Control/TimeManager.js	                        (rev 0)
+++ sandbox/mpriour/temporal_map/openlayers/lib/OpenLayers/Control/TimeManager.js	2011-08-12 04:00:58 UTC (rev 12237)
@@ -0,0 +1,352 @@
+/* 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
+ */
+
+/**
+ * Class: OpenLayers.Control.TimeManager
+ * Control to display and animate map layers across time.
+ *
+ * Inherits From:
+ *  - <OpenLayers.Control>
+ */
+OpenLayers.Control.TimeManager = OpenLayers.Class(OpenLayers.Control, {
+
+    /**
+     * Constant: EVENT_TYPES
+     *
+     * Supported event types:
+     *  - *tick* Triggered when the control advances one step in time.
+     *      Listeners receive an event object with a *currentTime* parameter.
+     *      Event is fired after the time has been incremented but before the
+     *      map or layer display is modified.
+     *  - *play* Triggered when the control begins a time-series animation.
+     *  - *stop* Triggered when the control stops a time-series animation.
+     *      Listeners receive an event object with a {Boolean} *rangeExceeded*
+     *      property indicating the control stopped due to reaching the end of
+     *      its configured time range (true) or due to the stop function call
+     *      (false). This event will only fire on the stop function call during
+     *      a loop-mode animation.
+     *  - *reset* Triggered when the control resets a time-series animation.
+     *      Listeners receive an event object with a {Boolean} *looped*
+     *      property indicating the control reset due to running in looped mode
+     *      (true) or the reset function call (false)
+     */
+    EVENT_TYPES: ["tick","play","stop","reset"],
+
+
+    /**
+     * Property: layers
+     * {Array(<OpenLayers.Layer.Vector>)}
+     */
+    layers: null,
+	
+    /**
+     * Property: units
+     * {OpenLayers.TimeUnit}
+     */
+	units:null,
+	
+    /**
+     * Property: step
+     * {Number} The number of time units each tick will advance the current 
+     *     animation time. Negative units with tick time in reverse.
+     *     Default : 1.
+     */
+	step:1,
+	
+    /**
+     * Property: range
+     * {Array(Date)} 2 member array containing the minimum and maximum times
+     *     in UTC that the time-series animation will use. (Optional if using
+     *     the intervals property). The 1st value should ALWAYS be less than
+     *     the second value. Use negative step values to do reverse time.
+     */
+	range:null,
+	
+	/**
+	 * Property: intervals
+	 * {Array(Date)} Array of valid distinct UTC dates/times that the time-
+	 * 	   series animation can use. (Optional)
+	 */
+	intervals:null,
+		
+	/**
+	 * Property: frameRate
+	 * {Number} A positive floating point number of frames (or ticks) per 
+	 *     second to use in time-series animations. Values less than 1 will
+	 *     make each tick last for more than 1 second. Example: 0.5 = 1 tick
+	 *     every 2 seconds. 3 = 3 ticks per second.  
+	 *     Default : 1. 
+	 */
+	frameRate:1,
+	
+	/**
+	 * Property: loop
+	 * {Boolean} true to continue running the animation until stop is called
+	 *     Default:false
+	 */
+	loop:false,
+	
+	/**
+	 * Property: snapToIntervals
+	 * {Boolean} If intervals are configured and this property is true then
+	 *     tick will advance to the next time/date in the intervals array
+	 *     regardless of the step value.
+	 */
+	snapToIntervals:false,
+	
+	/**
+	 * Property: currentTime
+	 * {Date} The current time of the time-series animation
+	 */
+	currentTime:null,
+	
+	/**
+	 * Private Property: childControls
+	 * {Array(<OpenLayers.Control.TimeManager>)} An array of the controls that
+	 *     this control "manages". Read-Only
+	 */
+	childControls:null,
+	
+	/**
+	 * Private Property: utcOffset
+	 * {Number} millisecond difference between local & UTC time. Read-Only
+	 */
+	utcOffset:0,
+	
+	/**
+     * Constructor: OpenLayers.Control.TimeManager
+     * Create a new time manager control.
+     *
+     * Parameters:
+     * options - {Object} Optional object whose properties will be set on the
+     *     control.
+     */
+    initialize: function(options){
+		options = options||{};
+		OpenLayers.Control.prototype.initialize.call(this,options);
+		this.utcOffset = new Date().getTimezoneOffset() * -6e4;
+		if(this.intervals){
+			for(var i=0,len=this.intervals.length;i<len;i++){
+				var interval = this.intervals[i];
+				if(!(interval[i] instanceof Date))this.intervals[i]=new Date(Date.parse(interval)+utcOffset);
+			}
+			this.range=[this.intervals[0],this.intervals[this.intervals.length-1]];
+		}else if(this.range){
+			if(!(this.range[0] instanceof Date))this.range[0]=new Date(Date.parse(this.range[0])+utcOffset);
+			if(!(this.range[1] instanceof Date))this.range[1]=new Date(Date.parse(this.range[1])+utcOffset);
+		}
+		this.currentTime = new Date(this.range[0].getTime());
+		this.childControls = this.buildChildControls(options.layers,OpenLayers.Util.applyDefaults({
+			utcOffset: this.utcOffset,
+			intervals:this.intervals,
+			range:this.range
+		},options));
+	},
+	/**
+	 * Method: tick
+	 * Advance/reverse time one step forward/backward. Fires the 'tick' event
+	 * if time can be incremented without exceeding the time range.
+	 * 
+	 */
+	tick:function(){
+		if(this.intervals && this.snapToIntervals){
+			var newIndex = OpenLayers.Util.indexOf(this.intervals,this.currentTime)+(this.step>0)?1:-1;
+			if (newIndex < this.intervals.length && newIndex>-1) {
+				this.currentTime = this.intervals[newIndex];
+			}else{
+				//force the currentTime beyond the range
+				this.currentTime = (this.step>0)?new Date(this.range[1].getTime()+100):new Date(this.range[0].getTime()-100);
+			}
+		}
+		else{
+			this.incrementTime();
+		}
+		//test that we have reached the end of our range
+		if (this.currentTime > this.range[1] || this.currentTime<this.range[0]) {
+			//loop in looping mode
+			if (this.loop) {
+				this.timer && clearInterval(this.timer) && (this.timer=null);
+				this.currentTime = (this.step>0)?new Date(this.range[0].getTime()):new Date(this.range[1].getTime());
+				this.events.triggerEvent('reset',{'looped':true});
+				this.play();
+			}
+			//stop in normal mode
+			else {
+				this.timer && clearInterval(this.timer) && (this.timer=null);
+				this.triggerEvent('stop', {'rangeExceeded': true});
+			}
+		}
+		else {
+			this.events.triggerEvent('tick', {currentTime: this.currentTime});
+		}
+	},
+	/**
+	 * Method: play
+	 * Begins/resumes the time-series animation. Fires the 'play' event,
+	 * then calls 'tick' at the interval set by the frameRate property
+	 */
+	play:function(){
+		//ensure that we don't have multiple timers running
+		this.timer && clearInterval(this.timer) && (this.timer=null);
+		//start playing
+		this.events.triggerEvent('play');
+		this.tick();
+		this.timer = setInterval(this.tick,1000/this.frameRate);
+	},
+	/**
+	 * Method: stop
+	 * Stops the time-series animation. Fires the 'stop' event.
+	 */
+	stop:function(){
+		this.timer && clearInterval(this.timer) && (this.timer=null);
+		this.triggerEvent('stop',{'rangeExceeded':false});
+	},
+	/**
+	 * Method: setRange
+	 * Sets the time range used by this control. Will modify the start time or
+	 * current time only if the animation is not currently running
+	 * 
+	 * Parameters:
+	 * range - {Arrray} UTC time range
+	 */
+	setRange:function(range){
+		if(!(range[0] instanceof Date))range[0]=new Date(Date.parse(range[0])+utcOffset);
+		if(!(range[1] instanceof Date))range[1]=new Date(Date.parse(range[1])+utcOffset);
+		this.range=range;
+		//set current time to correct location if the timer isn't running yet.
+		if(!this.timer){this.currentTime = this.range[(this.step>0)?0:1]}
+	},
+	/**
+	 * Method:setStart
+	 * Sets the start time for an animation. If the step is negative then this
+	 * sets the maximum time in the control's range parameter. Will only effect
+	 * the currentTime if an animation has not begun.
+	 * 
+	 * Parameters:
+	 * time - {Object} UTC start time/date
+	 */
+	setStart:function(time){
+		if(!(time instanceof Date))time=new Date(Date.parse(time)+utcOffset);
+		this.range[(this.step>0)?0:1]=time;
+		//set current time to this start time if we haven't already started
+		!this.timer && (this.currentTime=time);
+	},
+	/**
+	 * Method:setEnd
+	 * Sets the end time for an animation. If the step is negative then this
+	 * sets the minimum time in the control's range parameter. Will not effect
+	 * the current time.
+	 * 
+	 * Parameters:
+	 * time - {Object} UTC stop time/date
+	 */	
+	setEnd:function(time){
+		if(!(time instanceof Date))time=new Date(Date.parse(time)+utcOffset);
+		this.range[(this.step>0)?1:0]=time;
+	},
+	/**
+	 * Method:setTime
+	 * Manually sets the currentTime used in the control's animation.
+	 * 
+	 * Parameters: {Object} time
+	 * time - {Object} UTC current animation time/date
+	 */
+	setTime:function(time){
+		if(!(time instanceof Date))time=new Date(Date.parse(time)+utcOffset);
+		this.currentTime = time;
+	},
+	/**
+	 * Method:reset
+	 * Resets the time to the animation start time. Fires the 'reset' event.
+	 * 
+	 * Returns:
+	 * {Date} the control's currentTime, which is also the control's start time
+	 */
+	reset:function(){
+		this.timer && clearInterval(this.timer);
+		this.currentTime = (this.step>0)?new Date(this.range[0].getTime()):new Date(this.range[1].getTime());
+		this.events.triggerEvent('reset',{'looped':false});
+		return this.currentTime;
+	},
+	/**
+	 * Method: incrementTime 
+	 * Moves the current animation time forward by the specified step & stepUnit
+	 * 
+	 * Parameters:
+	 * step - {Number}
+	 * stepUnit - {<OpenLayers.TimeUnit>}
+	 */
+	incrementTime:function(step,stepUnit){
+		step = step || this.step;
+		stepUnit = stepUnit || this.unit;
+		this.currentTime['setUTC'+stepUnit](this.currentTime['getUTC'+stepUnit]()+step);
+	},
+	/**
+	 * Private Method: buildChildControls
+	 * Creates the controls "managed" by this control.
+	 * 
+	 * Parameters:
+	 * layers - {Array(<OpenLayers.Layer>)}
+	 * options - {Object} Options to pass to the control constructors
+	 * 
+	 * Returns:
+	 * {Array(<OpenLayers.Control.TimeControl>)}
+	 */
+	buildChildControls:function(layers,options){
+		layers = layers || this.layers;
+		var layerTypes = {}, childControls = [];
+		//categorize layers and separate into arrays for use in subclasses
+		for(var i=0,len=layers.length;i<len;i++){
+			var lyr = layers[i];
+			var lyrClass = lyr.CLASS_NAME.match(/\.Layer\.(\w+)/)[1];
+			if(OpenLayers.Control.TimeManager[lyrClass]){
+				!layerTypes[lyrClass] && (layerTypes[lyrClass]=[])
+				layerTypes[lyrClass].push(lyr);
+			}
+		}
+		//create subclassed child controls
+		for(var k in layerTypes){
+			var ctlClass = OpenLayers.Control.TimeManager[k];
+			var ctlOptions = OpenLayers.Util.applyDefaults({
+				layers:layerTypes[k],
+				parentControl:this
+			},options);
+			var ctl = new ctlClass(ctlOptions);
+			ctl.events.on({
+				'tick': ctl.onTick,
+				scope: ctl
+			})
+			childControls.push(new OpenLayers)
+		}
+		return childControls;
+	},
+	/**
+	 * APIMethod: destroy
+	 * Destroys the control
+	 */
+	destroy:function(){
+		for(var i=this.childControls.length-1;i>-1;i--){
+			this.childControls[i].destroy();
+		}
+		this.layers=null;
+		OpenLayers.Control.prototype.destroy.call(this);
+	},
+	
+	CLASS_NAME:'OpenLayers.Control.TimeManager'
+});
+
+OpenLayers.TimeUnit = {
+	SECONDS:'Seconds',
+	MINUTES:'Minutes',
+	HOURS:'Hours',
+	DAYS:'Date',
+	MONTHS:'Month',
+	YEARS:'FullYear'
+}
\ No newline at end of file

Modified: sandbox/mpriour/temporal_map/openlayers/lib/OpenLayers/Layer/WMS.js
===================================================================
--- sandbox/mpriour/temporal_map/openlayers/lib/OpenLayers/Layer/WMS.js	2011-08-11 13:21:04 UTC (rev 12236)
+++ sandbox/mpriour/temporal_map/openlayers/lib/OpenLayers/Layer/WMS.js	2011-08-12 04:00:58 UTC (rev 12237)
@@ -71,8 +71,37 @@
      *     true as value. This is only relevant for WMS versions >= 1.3.0.
      */
     yx: {'EPSG:4326': true},
-    
     /**
+     * Property: timeInterval
+     * {Array(Date)} An array containing at least 2 date values or parseable
+     *     strings.
+     *     An array with 2 values will be assumed to be the time range
+     *     An array with 3 or more values is the distinct times for which the
+     *     layer has data.
+     * (code)
+     *     ex: GetCapabilities response snippet
+     *     <Dimension name="time" units="ISO8601"/>
+     *     <Extent name="time" default="2006-06-23T03:10:00Z" nearestValue="0">1995-01-01/2011-12-31/PT5M</Extent>
+     *     
+     *     translates to:
+     *     timeInterval:['1995-01-01','2011-12-31'],
+     *     timeStep:5,
+     *     timeUnit:OpenLayers.TimeUnit.MINUTES
+     * (end)    
+     */
+	timeInterval:null,
+	/**
+	 * Property: timeStep
+	 * {Number} A floating point number for the grainularity of the time data 
+	 */
+	timeStep:null,
+	/**
+	 * Property: timeUnit
+	 * {<OpenLayers.TimeUnit>} One of the time unit constants describing the
+	 *     grainularity of the time data
+	 */
+	timeUnit:null,
+    /**
      * Constructor: OpenLayers.Layer.WMS
      * Create a new WMS layer object
      *

Modified: sandbox/mpriour/temporal_map/openlayers/lib/OpenLayers.js
===================================================================
--- sandbox/mpriour/temporal_map/openlayers/lib/OpenLayers.js	2011-08-11 13:21:04 UTC (rev 12236)
+++ sandbox/mpriour/temporal_map/openlayers/lib/OpenLayers.js	2011-08-12 04:00:58 UTC (rev 12237)
@@ -213,6 +213,8 @@
                 "OpenLayers/Control/Graticule.js",
                 "OpenLayers/Control/TransformFeature.js",
                 "OpenLayers/Control/SLDSelect.js",
+				"OpenLayers/Control/TimeManager.js",
+				"OpenLayers/Control/TimeManager/WMS.js",
                 "OpenLayers/Geometry.js",
                 "OpenLayers/Geometry/Rectangle.js",
                 "OpenLayers/Geometry/Collection.js",



More information about the Commits mailing list