2
votes

I am setting multiple markers to My Map

I can set statically the zoom levels and the center

but what i want is To Center to all markers and zoom level to fill all visible markers

I can use the Gmaps.MoveToRegion method which receives a MapSpan. The thing is, I don't know how to calculate the MapSpan needed to show all the markers.

I'm using Xamarin.Forms.Maps and Xam.Plugin.MapExtend.Abstractions

Thanks in advance!

3
There is a function called map.fitBounds() that does what you describe for javascript API and android API. Here's a link for further explanation. Not sure how you would do it in Xamarin, but hope this is a good start.so_jin_ee

3 Answers

3
votes

First you need to add custom map render to your android project that will inherit MapRenderer, GoogleMap.IInfoWindowAdapter

    public class MyMapRenderer : MapRenderer, GoogleMap.IInfoWindowAdapter

I have added 2 private fields

    private GoogleMap _map;
    private LatLngBounds.Builder _builder;

In the constructor initialize your _builder:

    public MyMapRenderer(Context context) : base(context)
    {
        _builder = new LatLngBounds.Builder();
    }

When override OnMapReady method set GoogleMap property as this:

    protected override void OnMapReady(GoogleMap map)
    {
        base.OnMapReady(map);

        NativeMap.InfoWindowClick += OnInfoWindowClick;
        NativeMap.SetInfoWindowAdapter(this);
        if (_map == null)
        {
            _map = map;
        }
    }

And you need to override CreateMarker method so you can change your zoom level

    protected override MarkerOptions CreateMarker(Pin pin)
    {
        var p = (THHPin)pin;

        var marker = new MarkerOptions();
        LatLng position = new LatLng(pin.Position.Latitude, pin.Position.Longitude);
        marker.SetPosition(position);
        marker.SetTitle(pin.Label);
        marker.SetSnippet(pin.Address);

        _builder.Include(position);
        LatLngBounds bounds = _builder.Build();

        CameraUpdate cu = CameraUpdateFactory.NewLatLngBounds(bounds, 20);

        _map.MoveCamera(cu);
        return marker;
    }
3
votes

I solved the damn thing using an algorithm I found here: http://www.movable-type.co.uk/scripts/latlong.html

In Xamarin is smth like this:

var radioTierra = 6371000; //metros
        var latitud1Radianes = pos1.Latitude * (Math.PI / 180.0);
        var latitud2Radianes = pos2.Latitude * (Math.PI / 180.0);
        var longitud1Radianes = pos1.Longitude * (Math.PI / 180.0);

        var deltaLatitud = (pos2.Latitude - pos1.Latitude) * (Math.PI / 180.0);
        var deltaLongitud = (pos2.Longitude - pos1.Longitude) * (Math.PI / 180.0);


        var sumando1 = Math.Sin(deltaLatitud / 2) * Math.Sin(deltaLatitud / 2);
        var sumando2 = Math.Cos(latitud1Radianes) * Math.Cos(latitud2Radianes) * Math.Sin(deltaLongitud / 2) * Math.Sin(deltaLongitud / 2);
        List<double> sumandos = new List<double>();
        sumandos.Add(sumando1);
        sumandos.Add(sumando2);
        var a = sumandos.Sum();
        var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));

        var distance = radioTierra * c;

        /* Δφ es deltaLatitud
         * Δλ es deltaLongitud*/
        var Bx = Math.Cos(latitud2Radianes) * Math.Cos(deltaLongitud);
        var By = Math.Cos(latitud2Radianes) * Math.Sin(deltaLongitud);
        var φ3 = Math.Atan2(Math.Sin(latitud1Radianes) + Math.Sin(latitud2Radianes),
                            Math.Sqrt((Math.Cos(latitud1Radianes) + Bx) * (Math.Cos(latitud2Radianes) + Bx) + By * By));//Latitud del punto medio
        var λ3 = longitud1Radianes + Math.Atan2(By, Math.Cos(longitud1Radianes) + Bx);//Longitud del punto medio

        var centro = new Xamarin.Forms.Maps.Position(φ3, λ3);
        Distance distancia = new Xamarin.Forms.Maps.Distance(distance + 0.2);

        Gmaps.MoveToRegion(MapSpan.FromCenterAndRadius(centro, distancia));
1
votes

I had success with the below c# code. Just record the position of each marker as a LatLng object.

locationManager = (LocationManager)GetSystemService(Context.LocationService);

Criteria criteria = new Criteria();

criteria.Accuracy = Accuracy.Fine;
criteria.PowerRequirement = Power.Low;

provider = locationManager.GetBestProvider(criteria, true);

location = locationManager.GetLastKnownLocation(provider);

marker1lat = location.Latitude;
marker1lng = location.Longitude;

marker2lat = location.Latitude;
marker2lng = location.Longitude;

LatLng marker1LatLng = new LatLng(marker1lat, marker1lng);
Latlng marker2LatLng = new LatLng(marker2lat, marker2lng);

LatLngBounds.Builder b = new LatLngBounds.Builder()
                    .Include(marker1LatLng)
                    .Include(marker2LatLng);

mMap.MoveCamera(CameraUpdateFactory.NewLatLngBounds(b.Build(), 120));