ThinkGeo.com    |     Documentation    |     Premium Support

AutoRefreshInterval

Hi,


I'm new to Map Suite and am trying to work out what the AutoRefreshInterval property on a SimpleMarkerOverlay does. I can't find any reference to it in the discussion forums and all the documentation says is "A time interval for the MarkerOverlay to automatically refresh". Just setting this value doesn't seem to achieve anything though.


My goal is to have a marker layer where the positions of the markers will change over time, so this property sounds as though it might be what I need to use. Presumably I need to have some other code that will specify what the new positions are though?


Can anyone shed some light on what this property does, in case I've misinterpretted its purpose?


Best regards,


Gary



Gary,


Currently, this property is not implement which is used for extending our JavaScript function in the future; but to implement your requirements, you can find many posts to refresh your markers dynamically.


1, use UpdatePanel with a Timer control; this solution will have some memory leak on the client side.

2, use OpenLayers library directly to add markers on the client side. Send asynchronize requests to get markers information; then refresh markers on the client side. Please see this post for how to add markers on the client side. It needs write a lot of JavaScript.

gis.thinkgeo.com/Support/Dis....aspx#8323


On the other hand, we'll have a new project release which perfect satisfies your requirement in the nearly two weeks; Please keep an eye on our website.


If you have any questions about this, please let me know.


Thanks,

Howard



Hi Howard, 
  
 Many thanks for your reply. I’d actually tried implementing option 1 and had discovered the memory leak problem, so I’m pleased this is a known issue. Is a fix planned for this? 
  
 In regards to option 2, I’ll take a look at that post today. What I need to be able to do is: 
  
 1. Have multiple markers, each with different icons 
 2. Have different tooltips for each marker when the user hovers over it on the client 
 3. Update the position, icon image, and tooltip information for each of the markers at regular timed intervals 
  
 Will the forthcoming project release you’ve referred to support this? 
  
 I’ve maybe missed something in the documentation but I can’t seem to find any reference to the client-side API, or how it relates to the server-side API. This might explain why I’m finding some of the server-side API confusing though, particularly as I’ve been looking at various examples in the forums. I’ve seen references to MarkerOverlays, InMemoryFeatureLayers, and other classes that seem to do some of these things, but I just can’t work out how they relate to each other, and in some cases they seem to overlap in terms of functionality. 
  
 There’s also some strange anomolies such as the GeoKeyedCollection<> class which is used to hold the Markers in the SimpleMarkerOverlay class. This allows items in the collection to be retrieved by key and index, but I’m baffled as to how you set the key when you add an item to the collection. 
  
 Any pointers you could provide with regards to the client-side of things would be appreciated. I’ve found the OpenLayers website, but this obviously doesn’t explain how the client-side API relates to your server-side component. 
  
 Best regards, 
  
 Gary 


Hi Gary,


To implement your requirement using option 2, you need to use the OpenLayers library to add markers at first. You could specify the icon and position information for each marker; also you could use popup as the tooltip of each marker. The client side code is like this:

var markers = new OpenLayers.Layer.Markers("Markers");
var size = new OpenLayers.Size(32, 32);
var offset = new OpenLayers.Pixel(-(size.w / 2), -size.h);
var icon = new OpenLayers.Icon('../../theme/images/' + LonLat[2], size, offset);
var marker = new OpenLayers.Marker(new OpenLayers.LonLat(lon, lat), icon);
markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(LonLat[0], LonLat[1]), icon));
AddPopup(marker, 'siteId', LonLat[1], LonLat[0], "siteDesc", message.innerText);

Map1.GetOpenLayersMap().addLayer(markers);


 
And then you could use a callback to update each marker in the timer tick event: 
Add a callback handler in the server side:

//Add Callback handler
ClientScriptManager csm = Page.ClientScript;
String reference = csm.GetCallbackEventReference(this, "args", "Success", "context", "Error", false);
String callbackScript = "function CallServerMethod(args, context) {\n" + reference + ";\n }";
csm.RegisterClientScriptBlock(this.GetType(), "CallServerMethod", callbackScript, true);

 
Then in the client side update each marker by the return value of the call back:

function Success(args, context) {
    context.innerText = args;
    LonLat = args.toString().split(",");
    var size = new OpenLayers.Size(32, 32);
    var offset = new OpenLayers.Pixel(-(size.w / 2), -size.h);
    var icon = new OpenLayers.Icon('../../theme/images/' + LonLat[2], size, offset);
    var marker = new OpenLayers.Marker(new OpenLayers.LonLat(LonLat[0], LonLat[1]), icon);
    markers.clearMarkers();
    markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(LonLat[0], LonLat[1]), icon));
    AddPopup(marker, 'siteId', LonLat[1], LonLat[0], "siteDesc", message.innerText);
}

 
Any more questions please let me know.
Thanks,
Sun

Hi Sun,


Thanks for your reply. Whilst I understand the principles behind what you're saying, I'm just getting more confused. One of the key things I'm not clear on is how the client-side OpenLayers classes are related to the server-side ThinkGeo classes. I may be missing something, but I've not been able to find any information on this either in the files installed on my local machine or in the online documentation.


I also can't see how the code you've kindly provided relates to the previously linked example from Howard. There's obviously a missing piece from your example in that I would need to have something on the server generating the response that's parsed by the client-side Success() function. Is there nothing built into Map Suite to handle passing information between client and server, or do I have to roll my own CSV string to do this?


I would have thought that updating markers on the client is a fairly common use case, so I guess I'm just surprised that it requires so much JavaScript to be written.


Best regards,


Gary



Gary,


Sorry for the confusing from my last reply. Actually, the OpenLayers classes are the basic implementation, and the server side ThinkGeo classes is a wrapper of the OpenLayers classes so that you can write your application code more conveniently, also the render part of a map is using ThinkGeo classes which are in MapSuiteCore. However, you’d better use the OpenLayers classes once you want to implement some functionality in the client side.
About this AutoRefreshInterval property, we have a sample to demonstrate how to implement it; you can get it from the attachment. The javascript code in my last reply is a part of this sample, and I just tried to show you how this sample works. 
Any more questions please let me know.
Thanks,
Sun

1475-SampleMarkersAutoRefreshInterval.zip (135 KB)

Hi Sun,


Many thanks for the sample project and your last reply - they've certainly helped my understanding.


Unfortunately though, the sample you've provided seems to suffer from the same sort of memory leak problem that I saw when using an UpdatePanel. I left your example running (unmodified) and gradually saw the memory usage creep up until the point where the browser complained about a script using too much resources. The problem is most apparent in IE (7), but I can see the same happening with Firefox too, albeit a bit more slowly.


I'm not sure if the problem possibly lies somewhere in the OpenLayers Marker class? I commented out the following 3 lines and the problem seemed to disappear, but obviously I don't see any markers on the map.



function Success(args, context) {
  context.innerText = args;
  LonLat = args.toString().split(",");
  var size = new OpenLayers.Size(32, 32);
  var offset = new OpenLayers.Pixel(-(size.w / 2), -size.h);
  var icon = new OpenLayers.Icon('../../theme/images/' + LonLat[2], size, offset);
//  var marker = new OpenLayers.Marker(new OpenLayers.LonLat(LonLat[0], LonLat[1]), icon);
   markers.clearMarkers();
//  markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(LonLat[0], LonLat[1]), icon));
//  AddPopup(marker, 'siteId', LonLat[1], LonLat[0], "siteDesc", message.innerText);
}

As soon as I uncomment either the 1st or 2nd commented line above the memory leak issue returns (I've commented out the AddPopup line as well because it relies on the marker variable).


Do you have any suggestions?


Best regards,


Gary



Gary,


We also recreate this issue in our end using this sample. I think this is because the markers and popup are just been removed but not destroy. So we add the destroy code and the memory problem doesn’t exist any more in our machine. Please take a look at the following code and have a try in your application.

function Success(args, context) {
    context.innerText = args;
    LonLat = args.toString().split(",");
    var size = new OpenLayers.Size(32, 32);
    var offset = new OpenLayers.Pixel(-(size.w / 2), -size.h);
    var icon = new OpenLayers.Icon('../../theme/images/' + LonLat[2], size, offset);

    if (markers.markers != null) {
        while (markers.markers.length > 0) {
            markers.markers[0].destroy();
            markers.removeMarker(markers.markers[0]);
        }
    }

    olMap = Map1.GetOpenLayersMap();
    if (olMap.popups != null) {
        while (olMap.popups.length > 0) {
            olMap.popups[0].destroy();
        }
    }

    var marker = new OpenLayers.Marker(new OpenLayers.LonLat(LonLat[0], LonLat[1]), icon);
    markers.addMarker(marker);
    AddPopup(marker, 'siteId', LonLat[1], LonLat[0], "siteDesc", message.innerText);
}

Any more questions please let me know.
Thanks,
Sun  

Hi Sun,


Many thanks for this - it does seem to stop the memory leak.


I can now progress with my Map Suite evaluation - I expect I'll have more questions as I hit different areas of functionality, but thanks once again for your help getting to the bottom of this particular issue.


Best regards,


Gary


 



Gary, 
  
 Great; please feel free to let us know if you have more queries. 
  
 Thanks, 
 Howard

Hi Howard, 
  
 OK, I’ve hit my next problem. I’m now trying to use a Virtual Earth overlay with this example, but it isn’t working. 
  
 I think the problem might be down to the map units as I’m seeing my marker appear on the map, but in roughly latitude = 0, longitude = 0. The Map Units are set to decimal degrees in the server-side code (as I’m plotting WGS 84 points), but I noticed in the Virtual Earth sample that it’s using meters (which have values several orders of magnitude larger). Do I need to do some sort of conversion when displaying markers on VE? 
  
 Thanks in advance, 
  
 Gary

Gary,



Virtual Earth is using a different projection from 4326 which used in your previous project, so if you want to make your sample works with Virtual Earth, you need to convert the longitude and latitude of markers to projection 900913; here posts two solutions for you.


1, use client side projection “OpenLayers.Projection.transform” method, see the code below:


var point1 = new OpenLayers.Geometry.Point(-20, 20);
var point2 = OpenLayers.Projection.transform(point1, new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913"));

2, server side conversion; please see the code below; what you need to do use callback or other way to convert your marker location:

 
Proj4Projection proj4Projection = new Proj4Projection();proj4Projection.InternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(4326);
proj4Projection.ExternalProjectionParametersString = Proj4Projection.GetGoogleMapParametersString();
PointShape newPoint = proj4Projection .ConvertToExternalProjection(point);


If you have any more questions, please let us know.


Thanks,

Howard



Hi Howard, 
  
 Thanks once again for your help. I’m having problems with the server-side conversion (which is my preferred method). When I use your example code “as-is” it throws an exception: 
  
    Invalid Operation Exception: The projection is not open.  Please open it before calling this method. 
  
 When I then include an explicit call to Open() before the call to ConvertToExternalProjection() it works fine in the built in Visual Studio web server, but running it under IIS7 on Vista causes it to crash the IIS worker process. The following is logged in the Windows Event Log: 
  
 Faulting application w3wp.exe, version 7.0.6002.18005, time stamp 0x49e023cf, faulting module ntdll.dll, version 6.0.6002.18005, time stamp 0x49e03821, exception code 0xc0000374, fault offset 0x000afaf8, process id 0x2f4, application start time 0x01ca7c9bf9b675a0. 
  
 I’ve wrapped it all in a try…catch with explicit calls to Close() and Dispose() in the finally block, but it doesnt’ seem to make any difference. It crashes every time in IIS. 
  
 Any ideas what the problem might be? 
  
 Best regards, 
  
 Gary 


Hi Gary,


We have recreated the problem you mentioned. The Proj4Projection class is a wrapper of a third party assembly, which has some issues in the Close function. We suggest you not to close the projection object and maintain only one projection object in your application. Following is some sample code.
 


Proj4Projection proj4Projection;
if (Session["Projection"] == null)
{
    proj4Projection = new Proj4Projection();
    proj4Projection.InternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(4326);
    proj4Projection.ExternalProjectionParametersString = Proj4Projection.GetGoogleMapParametersString();
    proj4Projection.Open();
    Session["Projection"] = proj4Projection;
}
else
{
    proj4Projection = (Proj4Projection)Session["Projection"];



 
Please have a try to see what happens, and any more questions please let us know.
 
Thanks,
 
Sun

Hi Sun, 
  
 Thanks for confirming the problem. I wasn’t sure if I was doing something wrong as I seem to be hitting one issue after another. Unfortunately the workaround you’ve suggested isn’t going to be suitable for a couple of reasons. 
  
 Firstly, the crash still occurs everytime the app domain is reloaded. This means that every time I make a change to a class in my App_Code directory it kills IIS and I have to wait for it to memory dump and restart. 
  
 Secondly, we try to avoid using session state for performance reasons. We use separate state servers, and although the class is marked as Serializable I wouldn’t be comfortable about having copies of this object in memory for every user, particularly given its instability. 
  
 Can you take the issue up with the 3rd party and get a proper fix for this? It’s going to be a showstopper for us otherwise. 
  
 Best regards, 
  
 Gary

Gary, 
  
   The third party is an open source piece of software so it is difficult to get things fixed.  The software is also C and not very easily modified without expertise.  What we are doing is creating a managed version of this library which will not have these problems.  We are very close to this and I should have more information later this week and hopefully something you can try.  I will talk with Sun in detail tomorrow and see what else we can do in the short term.  Maybe there is something we can do to hold you over. 
  
 David

Hi David, 
  
 I’m still evaluating Map Suite, so I can move on to some of the other functionality I want to check for the time being, and then come back to this when you have something I can try. I presume you have access to my contact details, if you want to take this offline. 
  
 Best regards, 
  
 Gary

Gary,


There is another option which is using the projection system of OpenLayers. This means you need to transform the projection in the client side, and we have a sample to demonstrate how to do this, please take a look at the sample in the attachment.
 
Sorry for the inconvenience and any more questions please let me know.
 
Thanks,
 
Sun

1564-SampleMarkersAutoRefreshInterval.zip (139 KB)

Hi Sun, 
  
 Thanks for this. The reason I’d prefer to have a server-side solution is that I’m using other functionality server-side that also needs locations to be reprojected, such as the “RestrictedExtent” property. 
  
 Best regards, 
  
 Gary

Gary, 
  
   We are really close on the server side.  If you don’t mind maybe we can send you our new managed projection system and you can plug it in a give it a go.  What do you think? 
  
 David