ThinkGeo.com    |     Documentation    |     Premium Support

Display vehicles on the map

Hi,


We have been using the Web Edition for quite a while.  And we have been using javascript with openlayers to handle the vehicle display (.png icons) on the web Browser (IE, web browser control) .  The vehicle display needs to be refreshed every time interval like 30 seconds with their updated locations (different GPS) and states (different colored .png icons).  The display speed is ok when the number of vehicles are not too big. But it will take a few seconds to finish update.. if there are hundreds/thousands .. of vehicles.  We want to improve this, the performance. (refresh thousands of vehicles w/o noticable delay) It'd be great if you can give me some pointers which Web Edition APIs i can use (to replace the Javascript solution/openlayers.Marker to handle the dynamic display).


Thanks a lot!


Lishan


 



 Hello Lishan,


 
Thanks for your post, I think there is a solution.
 
You can use the Inmemoryfeaturelayer simulate the marker, that will improve the speed, and if you need any event on click the vehicles, you can use InmemoryFeatureLayer + Click event to make this.
 
 First create the InMemoryFeatureLayer and set it's default pointshape style as same as your marker image.
 

private void DisplayMap_Load(object sender, EventArgs e)
        {
            winformsMap1.MapUnit = GeographyUnit.DecimalDegree;
            winformsMap1.CurrentExtent = new RectangleShape(-155.733, 95.60, 104.42, -81.9);

            WorldMapKitWmsDesktopOverlay worldMapKitOverlay = new WorldMapKitWmsDesktopOverlay();
            winformsMap1.Overlays.Add(worldMapKitOverlay);
            InMemoryFeatureLayer inmemoryFeatureLayer = new InMemoryFeatureLayer();
            inmemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = new PointStyle(new GeoImage(Properties.Resources.AQUA)); 
            inmemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;

            LayerOverlay markerOverlay = new LayerOverlay();
            markerOverlay.Layers.Add(inmemoryFeatureLayer);
            winformsMap1.Overlays.Add("MarkerOverlay", markerOverlay);
            winformsMap1.Refresh();
        }

 

Then, the Click event to help you find the marker and do something.



private void winformsMap1_MapClick(object sender, MapClickWinformsMapEventArgs e)
        {
            LayerOverlay markerOverlay = (LayerOverlay)winformsMap1.Overlays["MarkerOverlay"];
            InMemoryFeatureLayer inmemoryFeatureLayer = markerOverlay.Layers[0] as InMemoryFeatureLayer;
            inmemoryFeatureLayer.InternalFeatures.Clear();
            MultipolygonShape buffer = e.WorldLocation.Buffer(350, GeographyUnit.DecimalDegree, DistanceUnit.Kilometer);
            Collection<Feature> clickedMarker = inmemoryFeatureLayer.QueryTools.GetFeaturesWithin(buffer, ReturningColumnsType.NoColumns);
            if (clickedMarker.Count > 0)
            {
                Collection<Feature> features = winformsMap1.FindFeatureLayer("WorldLayer").FeatureSource.GetFeaturesNearestTo(new PointShape(e.WorldLocation.X, e.WorldLocation.Y), GeographyUnit.DecimalDegree, 10, ReturningColumnsType.AllColumns);
                //do anything you want to do, like hight it, change the color, show some tooltip.
            }

            winformsMap1.Refresh();
        }
I hope that can be help, please feel free to let us know if you meet problems.


Regards,


Gary



Hi Gary, 



Thank you very much for your reply and the code sample.  

I tried it.   Using the inMemoryFeatureLayer would work, however, we are using the MapEngine to draw..After the Map images are drawn, we can only access the Map object from javascript (the client side.. )   I am trying with the MapEngine.DynamicLayer on the serverside (invoked by client side PageMethod..) .. I probably don't know how to the useMapEngine.DynamicLayer..  Can you show me if there's a way to use MapEngine and InMemoryFeatureLayer to handle it?  


Maybe I don't really need to use MapEngine to draw.. but I do need to use javascript to receive request from remote clients and have the Map Server the draw the vehicles dynamically.. 




Thanks a lot! 



Lishan



Hello Lishan, 
  
 Thanks for your further information. 
  
 Sorry I’m not clear what do you want to do in the Javascript to operation the InMemoryFeatureLayer, but there is a way to access it, you can use  
  
 var layer = tgMap.getLayer(‘MarkerOverlay’); 
  
 And the name is which we set in: winformsMap1.Overlays.Add(“MarkerOverlay”, markerOverlay); 
  
 Please let us know if I misunderstanding something. 
  
 Regards, 
  
 Gary

Hi Gary,  

Thanks for your prompt reply.  I will try to explain in below. 


We are using the ThinkGeo WebEdition. 

In our case and current implementation, the Javascript part on the MapServer side is like a middle person who gets invoked by remote Clients (not the same domain) who sends Vehicle Data etc. and draws the vehicles on the Map with the Openlayers API.   

But since the performance (speed of drawing vehicles is not meeting some customers expectation), we need to change our ways of handling the vehicle display. We want to minimize the change. (as much as possible i think.. ).  So I am thinking to keep that using the WebBroswer control and  javascript to feed the MapServer with Vehicle data (in JSON).. and use ThinkGeo server side API (InMemoryFeaureLayer) to display the Vehicles dynamically instead of Openlayers clientside API.     



My problem now is I can't seem to access the Map object which contains the MarkerOverlay after the Javascript directs the Vehicle Data to the Map Server (C#)... need a way to tell the Map (server side) to draw ..  





Thanks,  

Lishan



 Hello Lishan,


 
Ok, for this scenario, you can use Ajax to pass the data to server side and let the map draw and refresh.
 
First, let your class inherit the ICallbackEventHandler, then implement the RaiseCallbackEvent and GetCallbackResult function.

        public string GetCallbackResult()
        {
            return "returnvalue";
        }

        public void RaiseCallbackEvent(string eventArgument)
        {
            ////do sever side processing here
    if (eventArgument.StartsWith("^"))
            {
LayerOverlay markerOverlay = (LayerOverlay)winformsMap1.Overlays["MarkerOverlay"];
             InMemoryFeatureLayer inmemoryFeatureLayer = markerOverlay.Layers[0] as InMemoryFeatureLayer;
             ////then create the pointshape by your data and added into inmemoryFeatureLayer.InternalFeatures
winformsMap1.Refresh();
    }
        }

 
Then in the client side you call server and pass the parameters, it will raise the RaiseCallbackEvent and return value to js function by GetCallbackResult 

function test() {
            callServer('^'+data);
        }
         function callServer(param){
            <%= ClientScript.GetCallbackEventReference(this, "param", "receiveServerData", null)%>;
        }
        function receiveServerData(columnValue){
            alert(columnValue);
        }

 

Also here I have attached a sample that you can refer, I hope this can help you.


Regards,


Gary



WebEditionSample_InteractWithMapPoints_CS_1201.zip (139 KB)

Hi Gary, 
  
 Thanks for your help. 
  
 I have another question. Is there another the refresh the InMemoryFeatureLayer?  I don’t have the “winformsMap1.Refresh();” MapObj.Refresh()… function for some reason…  
  
 thanks! 
 Lishan

Hello Lishan,
 
In the server side, you can use the code below:
 

            LayerOverlay markerOverlay = (LayerOverlay)winformsMap1.Overlays[“MarkerOverlay”];
            markerOverlay.Redraw();

In the client side, you can use:
 

var layer = tgMap.getLayer(‘WorldOverlay’);
layer.redraw(true);

I hope this can help.
 
Regards,
 
Gary