xamarin / Xamarin.Forms

Xamarin.Forms is no longer supported. Migrate your apps to .NET MAUI.
https://aka.ms/xamarin-upgrade
Other
5.62k stars 1.87k forks source link

[Bug] UWP map crash on MoveToRegion with large span radius #12311

Open Stuart88 opened 4 years ago

Stuart88 commented 4 years ago

Description

UWP map control throws unhandled exception on MoveToRegion() for very large map span radius.

Steps to Reproduce

  1. Instantiate map control
  2. Use Map.MoveToRegion() for a span with radius greater than 5000000m
  3. Debug as UWP project
  4. App crash with UnhandledException,

Expected Behavior

Map zoomed out very far (maximum zoom out?)

Actual Behavior

App crash - UnhandledException

Basic Information

Workaround

For UWP runtime platform, check size of radius and adjust to smaller if needed


 if (Device.RuntimePlatform == Device.UWP && radius.Kilometers > 5000)
     radius = new Distance(4500000); 

 var span = MapSpan.FromCenterAndRadius(centre, radius);

 this.Map.MoveToRegion(span);
Stuart88 commented 4 years ago

Bit of an update to this:

I'm running the same code on a different machine and have found I need to force the map span down to an even smaller size (4000000m seems to work). This is slightly concerning; I guess it depends on screen resolution or something? And this would mean the issue could presumably still appear when the project is released to other devices with different screens.

Sadly it's a bit beyond me at this point, all I can do is continue with my workaround.

hartez commented 4 years ago

It's not a screen size issue, it's an incorrect translation from MapSpan to the Northwest/Southeast coordinates used for the GeoboundingBox constructor.

The renderer isn't taking into account wraparound when translating the values; if the center position of the MapSpan is, say, 89 degrees and the region size is more than 1 degree, it will try to create the GeoboundingBox with a latitude greater than 90 degrees. Which is ... well, that just doesn't work.

Here's an example platform test which currently won't pass:

[Test]
public async Task MapSpanTest()
{
    var map = new Map{ };

    await Device.InvokeOnMainThreadAsync(() =>
    {
        using (var renderer = GetRenderer(map))
        {
            var pos = new Position(89, 179);
            var span = MapSpan.FromCenterAndRadius(pos, new Distance(500000));
            map.MoveToRegion(span);
        }
    });
}