Hi,
I've written a custom provider (using a custom TileMapSource). I'm using EPSG900913Projection but the tile source I'm using does not have data for the entire world. The first problem I have is that when I first render the map it's using GeoBounds for the entire world. The problem is that I don't statically know the extent of the data source until I load the map, so I can't set the GeoBounds for RadMap and my custom provider in xaml. I've tried hooking event handlers for my user control "Loaded" event, also in RadMap.InitializeCompleted where I've tried to set the GeoBounds for both the RadMap and the custom provider but still the first time the map renders it covers the whole world.
I'd also like to limit the zoom range the user can use i.e. I'd like to stop the user zooming out more than one zoom level from the initial data extent. Again, because the data extent is not statically known I can't set the min and max zoom to fixed values. Is there some way to calculate the zoom level corresponding to the available data extent?
I have wired up a refresh button that when clicked calls RadMap.SetView passing a locationRect that I've constructed from the data available, and that correctly sets the view (and zoom level) for the map.
Can you suggest where I might be going wrong?
Thanks,
Pete
5 Answers, 1 is accepted
Is there any chance you can give us an isolation that we can debug locally and eventually end up with some suggestions ? Also, regarding the zoom level , do you have some business points that you display initially. If you have such ones, you can use GetBestView method which will return an optimal zoom level for them . Then you will be able to use it for restricting the zoom. Please elaborate more if this cannot be applied to your scenario.
Regards,
Petar Mladenov
Telerik by Progress
Hi Petar,
It's not easy for me to duplicate the exact scenario but the attached zip file (file extension changed to png) shows basically what I'm trying to do - I need to be able to switch between view models which have properties to control the map extents (i.e. the maximum map extent, and the initial viewed area). This example, which uses OpenStreetMapsProvider, works pretty well and does what I want.
When I use my custom data provider (which uses EPSG900913Projection) the setting of GeoBounds for RadMap does not work as I expect. For example given a viewable rectangle that looks something like this (units in metres):
Northwest {171850.777294977,183087.630289521}
Southeast {94367.714773305,277414.836837643}
And a maximum bounds for the map which looks something like this:
Northwest {627835.792877676,-307217.328747071}
Southeast {-335087.773967735,655706.23809834}
What I want to do is something like this:
var maxBounds =
new
LocationRect(max.Northwest, max.SouthEast);
RadMap.GeoBounds = maxBounds;
RadMap.SetView(
new
LocationRect(viewable.Northwest, viewable.Northeast);
RadMap.MinZoomLevel = maxBounds.ZoomLevel - 1;
Does that make sense? It seems to work ok for OpenStreetMapsProvider (which has MercatorProjection) but not for my custom provider (with EPSG900913Projection). My provider seems to work as expected i.e. it shows the correct viewable area, and constrains the zoom level, but the attempt to limit the RadMap bounds by setting GeoBounds does not work as expected.
I've included the code for my custom provider and source but this isn't hooked up in the sample because I can't give you access to the data source.
I'm using Telerik version 2016.3.914.40
Thanks
Pete
Thank you for your details. The GeoBounds code which limits the panning of the map pretty much limits (coerces) the Center property of the Map. What's happening with the Center property of the RadMap when you apply the pseudo mercator projection ? Also, we noticed in the Center calculations, we use the SpatialReference property of the RadMap. So, when you use the EPSG900913Projection, could you please also add:
RadMap.SpatialReference =
new
EPSG900913Projection();
Regards,
Petar Mladenov
Telerik by Progress
Hi Petar,
I've modified my example so that it uses a provider based on UriImageProvider, with the projection set to EPSG900913Projection. Each of the view models uses a different image, and each view has a viewableArea that fits somewhere within the lat/long limits dictated by the projection. I'm setting the RadMap SpatialProjection to match the provider. I'm having some difficulty understanding the right way to configure the control how I want it to work (i.e. to show the viewmodel viewable area, and constrain the extents of the map - so the user can't zoom out more than would be useful. I'm not clear on whether I should be using GeoBounds and or Min/MaxZoomLevel to do this and if I'm doing it right). If I set the provider GeoBounds to match the lat/long limits of the EPSG900913Projection it zooms in too far (i.e. doesn't show the full image) even though I'm calling RadMap.SetView(viewModel.ViewableRect). If the provider GeoBounds are set to the viewModel.MaximumRect (which is just a little larger than the viewableArea) then the full image is shown.
The example (I've included the images I used in the zip) illustrates the behaviour - buttons marked ViewModel1 and ViewModel2 do pretty much what I expect, buttons marked ViewModel1max and ViewModel2max seem to set the viewable area incorrectly.
Thanks
Pete
Although, your images are missing, I think we understand your issues - ZoomLevel and GeoBounds properties does not produce good results when used in combination in your scenario. Below I will post the SetView method of RadMap and the ZoomLevel property of LocationRect:
public
void
SetView(LocationRect view)
{
view.MapControl =
this
;
this
.Center = view.ViewCenter;
this
.ZoomLevel = view.ZoomLevel;
}
public
int
ZoomLevel
{
get
{
if
(
this
.MapControl !=
null
)
{
Point leftTopPoint =
this
.MapControl.SpatialReference.GeographicToLogical(
this
.Northwest);
Point rightBottomPoint =
this
.MapControl.SpatialReference.GeographicToLogical(
this
.Southeast);
double
viewportWidth = rightBottomPoint.X - leftTopPoint.X;
double
viewportHeight = rightBottomPoint.Y - leftTopPoint.Y;
Size tileSize =
this
.MapControl.Provider ==
null
?
new
Size(256, 256)
:
this
.MapControl.Provider.TileSize;
Size viewportPixelSize =
this
.MapControl.MapViewPixelSize;
int
zoomWidth = (
int
)Math.Log(viewportPixelSize.Width / tileSize.Width / viewportWidth, 2d);
int
zoomHeight = (
int
)Math.Log(viewportPixelSize.Height / tileSize.Height / viewportHeight, 2d);
int
zoomLevel = Math.Min(zoomWidth, zoomHeight);
return
zoomLevel;
}
else
{
return
1;
}
}
}
ZoomLevel is only a getter property. Also the ZoomLevel property of the RadMap is int in the range 1-20. I guess in your scenario you need zoomlevel to support values like 15.5, 13.7 to cover your entire viewport in the way you need. Our advice for you is to set ZoomLevel and Center property manually, ignoring the SetView method.
Regards,
Petar Mladenov
Telerik by Progress