[OpenLayers-Dev] Live Tracking using Open Layers]

Jo-V Ng Su Wei ngsuwei at stee.stengg.com
Sun Oct 29 19:48:31 EST 2006


Hi,

Thank you for your suggestion. I have even tried with WFS layer and yet
found some limitation due to the WFS GetFeatureInfo request with tiling.
Imagine sending so many requests for each tile where 1 request actually
suffices. It will be too heavy for the server.

Suggestion for improvement is either to have an untiled WFS for tracking
layer or to have an untiled WMS?? Would also want to highlight that WFS
should also support SLD parameter because I think eventually SLD will be be
very needy when it comes to track layer to label and symbolize tracks based
on particular attributes.

I would like to contribute the codes for the untiled WFS track layer. Hope
that you find it useful and feel free to change the codes.


/* Copyright (c) 2006 mCAP, Technical Office, STEE-InfoSoft. 
 * Author Jo-V
 * This class provides function similar to that of WMS Untiled except that
this layer 
 * will not be cached and extra function to deal with styles or sld. 
 * Every time the map is moved, a new map is requested. Thus
 * this layer is suitable for tracking layer to support layer that is
constantly 
 * refreshed.
 */ 
/**
 * @class
 * 
 * @requires OpenLayers/Layer/HTTPRequest.js
 */
OpenLayers.Layer.WMS.Track = Class.create();
OpenLayers.Layer.WMS.Track.prototype = 
  Object.extend( new OpenLayers.Layer.HTTPRequest(), {

    /** Hashtable of default parameter key/value pairs
     * @final @type Object */
    DEFAULT_PARAMS: { service: "WMS",
                      version: "1.1.1",
                      request: "GetMap",
                      exceptions: "application/vnd.ogc.se_inimage",
                      format: "image/jpeg",
                      maprev: ""
                     },

    /** @type DOMElement */
    imgDiv: null,
    

    /**
    * @constructor
    *
    * @param {String} name
    * @param {String} url
    * @param {Object} params
    */
    initialize: function(name, url, params, options) {
        var newArguments = new Array();
        if (arguments.length > 0) {
            //uppercase params
            params = OpenLayers.Util.upperCaseObject(params);
            newArguments.push(name, url, params, options);
        }
        OpenLayers.Layer.HTTPRequest.prototype.initialize.apply(this, 
 
newArguments);
        
        if (arguments.length > 0) {
            OpenLayers.Util.applyDefaults(
                           this.params, 
 
OpenLayers.Util.upperCaseObject(this.DEFAULT_PARAMS)
                           );
        }

        // unless explicitly set in options, if the layer is transparent, 
        // it will be an overlay        
        if ((options == null) || (options.isBaseLayer == null)) {
            this.isBaseLayer = ((this.params.TRANSPARENT != "true") && 
                                (this.params.TRANSPARENT != true));
        }
        /**
        if (options != null) {
        	var styleparam;
        	var styletype = this.params.STYLE_TYPE.toLowerCase();
        	var styletype = this.params.STYLE_VALUE.toLowerCase();
            if(style){
            	if (style == 'styles'){
            		styleparam = {styles:};
            	}else{
            	}
            }else{
            	this.params.
            	//this.mergeNewParams({STYLES:''});
            }
       		var allParams = Object.extend(new Object(), this.params);
      		var allParams = Object.extend(allParams, newParams);
        }
        **/
    },    

    /**
     * 
     */
    destroy: function() {
        this.imgDiv = null;    
        OpenLayers.Layer.HTTPRequest.prototype.destroy.apply(this,
arguments);
    },
    
    /**
     * @param {Object} obj
     * 
     * @returns An exact clone of this OpenLayers.Track.WMS
     * @type OpenLayers.Track.WMS
     */
    clone: function (obj) {
        
        if (obj == null) {
            obj = new OpenLayers.Track.WMS(this.name,
                                                   this.url,
                                                   this.params,
                                                   this.options);
        }

        //get all additions from superclasses
        obj = OpenLayers.Layer.HTTPRequest.prototype.clone.apply(this,
[obj]);

        // copy/set any non-init, non-simple values here

        return obj;
    },    
    
    
    /** Once HTTPRequest has set the map, we can load the image div
     * 
     * @param {OpenLayers.Map} map
     */
    setMap: function(map) {
        OpenLayers.Layer.HTTPRequest.prototype.setMap.apply(this,
arguments);
        this.loadImageDiv();
    },

    /** When it is not a minor move (ie when panning or when done dragging)
     *   reload and recenter the div.
     * 
     * @param {OpenLayers.Bounds} bounds
     * @param {Boolean} zoomChanged
     * @param {Boolean} minor
     */
    moveTo:function(bounds, zoomChanged, minor) {

        if (!minor) {
        
            if (bounds == null) {
                bounds = this.map.getExtent();
            }
            
            var size = this.map.getSize().clone();

            // get the url
            var url = this.getFullRequestString( {BBOX: bounds.toBBOX(),
                                                  WIDTH: size.w,
                                                  HEIGHT: size.h} );
        

            // always position at upper left corner of current viewspace
            var tl = new OpenLayers.Pixel(0,0);
            var pos = this.map.getLayerPxFromViewPortPx(tl);

            // first hide before all modifications            
            Element.hide(this.imgDiv);
            
            // update div
            var img = this.imgDiv;
            if (this.params.TRANSPARENT == 'true') {
                OpenLayers.Util.modifyAlphaImageDiv(this.imgDiv, 
                                                    null, 
                                                    pos, 
                                                    size,
                                                    url);
                img = this.imgDiv.childNodes[0];
            } else {
                OpenLayers.Util.modifyDOMElement(this.imgDiv, 
                                                 null, 
                                                 pos, 
                                                 size);
                this.imgDiv.src = url;
            }
    
            // wait until image is done loading to show again
            Event.observe(img, 
                          "load", 
                          this.showDiv.bindAsEventListener(this));
        }
    },
    
    /** Helper function that allows us to first hide the imgDiv, then make
all 
     *   the changes (position, size, url). Then when the url is done
loading,
     *   we call this function to show the imgDiv.
     * 
     * @private
     */
    showDiv: function() {
        Element.show(this.imgDiv);
    },
    
    /** Once HTTPRequest has updated the url, reload the image div
     * @param {String} newUrl
     */
    setUrl: function(newUrl) {
        OpenLayers.Layer.HTTPRequest.prototype.setUrl.apply(this,
arguments);
        this.moveTo();
    },

    /** Once HTTPRequest has updated new params, reload the image div
     * @param {Object} newParams
     */
    mergeNewParams:function(newParams) {
        var upperParams = OpenLayers.Util.upperCaseObject(newParams);
        var newArguments = [upperParams];
        OpenLayers.Layer.HTTPRequest.prototype.mergeNewParams.apply(this, 
 
newArguments);
        //redraw
        this.moveTo();
    },
    
    /** combine the layer's url with its params and these newParams. 
    *   
    *    Add the SRS parameter from 'projection' -- this is probably
    *     more eloquently done via a setProjection() method, but this 
    *     works for now and always.
    * 
    * @param {Object} newParams
    * 
    * @type String
    */
    getFullRequestString:function(newParams) {
        var projection = this.map.getProjection();
        this.params.SRS = (projection == "none") ? null : projection;

        //JoV
		var s = Math.round(1000000*Math.random()).toString();
		this.params.MAPREV = s;
        return OpenLayers.Layer.Grid.prototype.getFullRequestString.apply(
                                                    this, arguments);
    },
    
    /** This function first removes the previous image div, then adds a new
     *   one according to the transparency property.
     * 
     * @private
     */
    loadImageDiv: function() {
        
        var size = this.map.getSize().clone();
        var bounds = this.map.getExtent();

        var url = "";            
        if (bounds != null) {
            url = this.getFullRequestString( {BBOX: bounds.toBBOX(),
                                              WIDTH: size.w,
                                              HEIGHT: size.h} );
        }
        
        //clear previous wms image (removes imgDiv)
        this.div.innerHTML = "";
        
        //always position at upper left corner of current viewspace
        var tl = new OpenLayers.Pixel(0,0);
        var pos = this.map.getLayerPxFromViewPortPx(tl);
        
        //create div
        if (this.params.TRANSPARENT == 'true') {
            this.imgDiv = OpenLayers.Util.createAlphaImageDiv(null,
                                                              pos,
                                                              size,
                                                              url,
                                                              "absolute");
        } else {
            this.imgDiv = OpenLayers.Util.createImage(null,
                                                      pos,
                                                      size,
                                                      url,
                                                      "absolute");
        }
        
        this.div.appendChild(this.imgDiv);
    },
        
    /** @final @type String */
    CLASS_NAME: "OpenLayers.Layer.WMS.Track"
});

-----Original Message-----
From: Erik Uzureau [mailto:euzuro at gmail.com] 
Sent: Thursday, October 19, 2006 12:35 PM
To: ngsuwei at stee.stengg.com
Cc: dev at openlayers.org
Subject: Re: [OpenLayers-Dev] Live Tracking using Open Layers]


Dear ngsuwei,

My first reaction is that removing and adding maxTrack markers every ten
seconds seems like not the best way to go about this.

Currently in the OL Marker library, there is no code to change a marker's
lonlat, though perhaps there should be. I have added a ticket to trac
(http://trac.openlayers.org/ticket/358) with a suggested (though
untested) fix.

The idea then is that instead of storing the separate lon[] and lat[]
arrays, you would call markers.addMarker() *once* in your init function, and
then in your move() function, you would iterate through the
markers.markers[] array, calling setLonLat() to update each marker's
position dynamically.

If you can get that suggested bit of code I put in the ticket to work, it
would be awesome if you could build that into a patch and attach it to the
ticket...

See: http://trac.openlayers.org/wiki/CreatingPatches

Thanks, and hope that helps!

Erik

On 9/30/06, ngsuwei at stee.stengg.com <ngsuwei at stee.stengg.com> wrote:
> I am trying to simulate a web based so-called "live" tracking of 
> resources on the map using OL. For this i am using markers. What i do 
> was to retrieve the latest lat lon of the tracked resources thru ajax 
> (at 10 seconds interval) and then remove all the existing markers on 
> the map and add new markers with the latest lat lon as to reflect the 
> latest resources position.
>
> Before i tried using ajax. I had tried simulating the resources 
> movement but adding and removing the markers on the map. After some 
> time, i found that there was serious memory leaks problem.
>
> Can anyone advice me on what has gone wrong. Or are there any better 
> resolution to achieve this?
>
> Following is the code that i use.
>
>   var zoom = 3;
>   var map, markers;
>   var latlon;
>   var lat = new Array();
>   var lon = new Array();
>   var forward = true;
>   var timerID;
>   var maxTrack = 100
>
>   function init(){
>     map = new OpenLayers.Map('map');
>     wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
>                 "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'}
);
>     map.addLayer(wms);
>
>     markers = new OpenLayers.Layer.Markers("markers");
>     map.addLayer(markers);
>     map.setCenter(new OpenLayers.LonLat(5, 40), zoom);
>     map.addControl( new OpenLayers.Control.LayerSwitcher() );
>
>     var i = 0;
>     lon[0] = 3;
>     lat[0] = -40;
>     for (i=1;i<maxTrack;i++){
>       lon[i] = lon[i-1] + 3;
>       lat[i] = lat[i-1] + 3;
>
>     }
>
>     timerID = window.setInterval('move()',2000);
>   }
>
>   function move(){
>     var i = 0;
>     markers.clearMarkers();
>     for (i=0;i<maxTrack;i++){
>         add(i);
>     }
>   }
>
>   function add(i) {
>     markers.addMarker(new OpenLayers.Marker(getLonLat(i), null));
>   }
>
>   function getLonLat(i){
>     if (lat[i] >= 80 && lon[i] >= 10){
>       forward = false;
>     }else if (lat[i] <= 40 && lon[i] <= 3){
>       forward = true;
>     }
>     if (forward == false){
>       lat[i] = lat[i] - 2;
>       lon[i] = lon[i] - 1;
>     }else{
>       lat[i] = lat[i] + 2;
>       lon[i] = lon[i] + 1;
>     }
>     return new OpenLayers.LonLat(lon[i],lat[i]);
>   }
>
>   function doUnload(){
>     if(timerID) {
>       clearTimeout(timerID);
>       timerID  = 0;
>      }
>   }
>
>
>
> [This e-mail is confidential and may be priviledged. If you are not 
> the intended recipient, please kindly notify us immediately and delete 
> the message from your system; please do not copy or use it for any 
> purpose, nor disclose its contents to any other person. Thank you.]
> ---ST Electronics Group---
>
> _______________________________________________
> Users mailing list
> Users at openlayers.org http://openlayers.org/mailman/listinfo/users
>
> _______________________________________________
> Dev mailing list
> Dev at openlayers.org
> http://openlayers.org/mailman/listinfo/dev
>



More information about the Dev mailing list