Constrain map to only show available data

6 posts, 0 answers
  1. Peter
    Peter avatar
    21 posts
    Member since:
    Oct 2016

    Posted 16 Dec 2016 Link to this post

    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

     

  2. Petar Mladenov
    Admin
    Petar Mladenov avatar
    2934 posts

    Posted 21 Dec 2016 Link to this post

    Hello Peter,

    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
    Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  3. Peter
    Peter avatar
    21 posts
    Member since:
    Oct 2016

    Posted 21 Dec 2016 in reply to Petar Mladenov Link to this post

    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

     

     

  4. Petar Mladenov
    Admin
    Petar Mladenov avatar
    2934 posts

    Posted 23 Dec 2016 Link to this post

    Hello Peter,

    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();
    Make sue you set it before setting the GeoBounds property of the Map. We hope this will make an improvement.




    Regards,
    Petar Mladenov
    Telerik by Progress
    Want to extend the target reach of your WPF applications, leveraging iOS, Android, and UWP? Try UI for Xamarin, a suite of polished and feature-rich components for the Xamarin framework, which allow you to write beautiful native mobile apps using a single shared C# codebase.
  5. Peter
    Peter avatar
    21 posts
    Member since:
    Oct 2016

    Posted 12 Jan in reply to Petar Mladenov Link to this post

    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

  6. Petar Mladenov
    Admin
    Petar Mladenov avatar
    2934 posts

    Posted 17 Jan Link to this post

    Hello Peter,

    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
    Want to extend the target reach of your WPF applications, leveraging iOS, Android, and UWP? Try UI for Xamarin, a suite of polished and feature-rich components for the Xamarin framework, which allow you to write beautiful native mobile apps using a single shared C# codebase.
Back to Top