ThinkGeo.com    |     Documentation    |     Premium Support

Custom Styles based on Time

Hello ThinkGeo team

I have a Xamarin Forms app where we track a moving feature and need to show to the user if our data is stale.
Lets use a simple example.
We are tracking a delivery van on the map. Updates are coming to the app via Signalr so updates can be very frequent.

When the truck stops moving on the map is it because they have stopped moving or we have ceased getting updates and we are looking at stale data on the map.

Currently on our google maps implementation we have a timestamp on the feature and if it is older than 15 minutes we change the opacity of the feature. Stale data appears “grayed” out. This works well.

I am now looking for the equivalent feature in ThinkGeo.

I have two questions I am asking.

Question 1:
To have the two different styles that are based on a timestamp I am going to use Custom Styles and based on your sample I think this is the correct way to go?

samples/xamarin-forms/HowDoISample/HowDoISample/Samples/Extensibility/ExtendingStylesSample.xaml.cs · master · ThinkGeo / Public / Mobile Maps · GitLab

Question 2:
When is the style evaluated and changes applied on the map?
In my example that within a 15 minute window the feature could be considered stale as we have not received an update. I believe I need to trigger a refresh of the Overlay/Layer that contains the Custom Style to have the timestamp evaluated and correct style applied?

I assume a simple 15 minute timer that triggers the refresh would work fine?

I hope those two questions and my example make sense.

Regards
Chris …

Hey @Chris_Marassovich1,

I think your plan is absolutely on track here. That sample you are looking at is how I would go about it. And you are right in that you need to be able to refresh the overlay in order for the draw to evaluate and update based on the timestamps. I have a feeling that there might be a better way to go about it outside of a 15 min timer though. Because a vehicle may not be responsive in the middle of that 15 min timer and won’t refresh until that timer is up. Maybe you just have that overlay on an auto refresh timer that is like an average of your SignalR updates? We have something like that built-in:

vehicleOverlay.AutoRefreshInterval = TimeSpan.FromMilliseconds(100);

That way, you are continually evaluating and updating the vehicles’ positions every 100ms and once a vehicle stops responding for 15mins, it’ll be updated within 100ms of that time being up. I would keep that overlay pretty bare minimum though: only the vehicle tracking layer and nothing else to keep it performant.

Thanks,
Kyle

Kyle,

Thanks for the quick response.

I do have a little issue with the AutoRefreshInterval suggestion … that property does not appear to be available to me.
The NuGet is ThinkGeo.UI.XamarinForms 12.3.8.
I am using a LayerOverlay and that property is not available.
I am a little confused about this?
In my code I have tried a few of the other Overlay types and the property is not available for them either.

But you do now raise in my mind a few more questions in this space.
The number of vehicles on this layer will be in the hundreds. Will the auto refresh on a 100 millisecond loop still keep performant in your experience?

Another question I have … is about thread safety of your layers, styles etc.
The Scenario
Each of those vehicles will be updating their position to the server on their own determined period. It could be every 5 seconds or every few minutes. The server will send each change out to my app as it receives those updates.
So my app will receive that info as fast as it and signalr can cope.
Now on the app on each instance of the change I form that data into a feature and add it to the vehicle layer. If it is an update I perform a delete feature then add feature process. Then I refresh the overlay.

The style is added in the same way as the example from previous post.
My question is that the 15 minute setting on the style is a user setting and they may choose to increase or decrease that period based on what they are seeing/doing on the map.
In the case of a change to that period by the user I would create a new style and then remove the old styles from the layers CustomStyles property, add the new one and refresh. Is this possible all while the features are already on the layer and are possibly in a tight loop of being added/removed?

I trust you can advise on this.

Cheers
Chris …

Hey @Chris_Marassovich1,

I’m surprised to see this not available in Xamarin.Forms. It is in WPF and WinForms at least. I think maybe something happened that disabled the AutoRefreshInterval from being exposed. I’ll look into that and see if I can get that in place.

I know that we can handle refreshing data subsecond so long as we aren’t talking big images. Points, lines, and simple polygons work well. In one of our samples, we go through redrawing 20k polygons with the backing data changing randomly over time:

That said, that sample isn’t setup to be multithreaded. I can be honest and say that I’m personally not sure how it would handle in multiple threads without locking during the updating of features. That could be tedious if updates are happening constantly. The (semi)good news is that while drawing, we are only concerned about the vehicles on the current map extent, but still I’ll need to ask some of our devs to see if they have any more insight into multithreaded updates and drawing.

As for the TimeBasedCustomStyle, I think it would be better to just expose that TimeoutPeriod as a property on the class. Then when the user adjusts the time in the applications settings, have it update that TimeoutPeriod property and you won’t have to add and remove styles like that in the first place.

Thanks,
Kyle

Hey @Kyle_Day,

Your idea on placing the TimeoutPeriod as a referenced property was a solution I have already considered and I think is the correct path to follow in my situation.

Yes please do look into why the AutoRefreshInterval is not being exposed as I think it will greatly simplify my code.

I would also really appreciate your insight on the multithreaded support of your library. I will at some point get to the volume data testing point but not today. So far my testing has not revealed any issues but the volumes and interactions are just not at scale yet.

To provide you some insight to how I am processing the data …
Each of the delivery trucks send their location changes on a set period. Each of those location updates is sent down to my app via signalr. I do not batch the updates in any way and just rely on signalr to scale.
As my app receives each signalr message I raise good old c# events and the map will update.

I have many overlays with many layers. Some layers are created dynamically.

I also have app side filtering and based on the filter I modify the map in two ways.
In some cases I can simply hide/show the layer and in others I have to add or remove the feature.

I do not perform any threading from those events or the map code.

The “life-cycle” of the app is a constant stream of updates from the server via signalr (when things change) and any user interactions on the app.

I look forward to your thoughts and insight.

Regards
Chris …

Hey @Chris_Marassovich1,

I’m still looking into what happened with AutoRefreshInterval. Apparently, there was a refresh with Xamarin a few updates ago to streamline things, but ended up missing the AutoRefresh part.

As for multithreaded support, I was reminded of the ThreadSafety property on the Layer classes. Setting that to ThreadSafety.Safe will make sure that drawing in a multithreaded application will be fine. The only thing you need to ensure is maintaining the consistency of updates to the InternalFeatures collection during the async updates from your SignalR calls.

I updated our TrackDynamicData sample to move a random feature every 10ms on a new thread to simulate incoming SignalR messages. As I expected, I found that I needed to place a lock on the polygonLayer.InternalFeatures collection in order to prevent errors, but it looks pretty good. I also put in place a timer to do a refresh on the Overlay every 100ms. This is essentially what the AutoRefreshInterval does anyway. You can see what that looks like and the code here:

TrackDynamicData.xaml.cs (12.4 KB)
TrackDynamicData.xaml (3.7 KB)

Thanks,
Kyle

@Kyle_Day

Thanks for looking into my multithreaded support question and you went that one step further and provided a code sample.

You are a legend!

Thank you
Chris …

PS Ping me when you know which release the AutoRefreshInterval property will make it’s return.

Hey @Chris_Marassovich1,

You’re welcome! Hope the code helps you out. I’ll make sure to reach out once the AutoRefreshInterval is available again.

Thanks,
Kyle