2016-09-16 38 views
1

我知道,我问的是Google Map的存在,但我正在与Xamarin.Forms.Map所以..我必须通过我自己的。确定缩放级别以覆盖所有关于纬度/经度的标记

但是,我知道如何让我的一点,POI(兴趣点)的中心,但我不知道如何确定相机的变焦..

我搜查网络和from this post,我被重定向到Haversine的algorory。

不过,我想给出的代码,但它不工作。我知道如何找到兴趣点,2点farest,但我不能确定变焦..

任何想法吗? :/

注:有代码,如果你想了解一下我的尝试

#region Camera focus method 
    private static void OnCustomPinsPropertyChanged(BindableObject bindable, object oldValue, object newValue) 
    { 
     CustomMap customMap = ((CustomMap)bindable); 

     if (customMap.CameraFocusParameter == CameraFocusReference.OnPins) 
     { 
      List<Position> PositionPins = new List<Position>(); 
      bool onlyOnePointPresent; 

      foreach (CustomPin pin in (newValue as List<CustomPin>)) 
      { 
       PositionPins.Add(pin.Position); 
      } 
      Position CentralPosition = GetCentralPosition(PositionPins); 
      if (PositionPins.Count > 1) 
      { 
       Position[] FarestPoints = GetTwoFarestPointsOfCenterPointReference(PositionPins, CentralPosition); 
       customMap.CameraFocus = GetPositionAndZoomLevelForCameraAboutPositions(FarestPoints); 
       onlyOnePointPresent = false; 
      } 
      else 
      { 
       customMap.CameraFocus = new CameraFocusData() { Position = CentralPosition }; 
       onlyOnePointPresent = true; 
      } 
      customMap.MoveToRegion(MapSpan.FromCenterAndRadius(customMap.CameraFocus.Position, 
      (!onlyOnePointPresent) ? (customMap.CameraFocus.Distance) : (new Distance(5)))); 
     } 
    } 
    public static Position GetCentralPosition(List<Position> positions) 
    { 
     if (positions.Count == 1) 
     { 
      foreach (Position pos in positions) 
      { 
       return (pos); 
      } 
     } 

     double lat = 0; 
     double lng = 0; 

     foreach (var pos in positions) 
     { 
      lat += pos.Latitude; 
      lng += pos.Longitude; 
     } 

     var total = positions.Count; 

     lat = lat/total; 
     lng = lng/total; 

     return new Position(lat, lng); 
    } 
    public class DataCalc 
    { 
     public Position Pos { get; set; } 
     public double Distance { get; set; } 
    } 
    public static Position[] GetTwoFarestPointsOfCenterPointReference(List<Position> farestPosition, Position centerPosition) 
    { 
     Position[] FarestPos = new Position[2]; 
     List<DataCalc> dataCalc = new List<DataCalc>(); 

     Debug.WriteLine("So the center is on [{0}]/[{1}]", centerPosition.Latitude, centerPosition.Longitude); 

     foreach (Position pos in farestPosition) 
     { 
      dataCalc.Add(new DataCalc() 
      { 
       Pos = pos, 
       Distance = Math.Sqrt(Math.Pow(pos.Latitude - centerPosition.Latitude, 2) + Math.Pow(pos.Longitude - centerPosition.Longitude, 2)) 
      }); 
     } 

     DataCalc First = new DataCalc() { Distance = 0 }; 
     foreach (DataCalc dc in dataCalc) 
     { 
      if (dc.Distance > First.Distance) 
      { 
       First = dc; 
      } 
     } 
     Debug.WriteLine("The farest one is on [{0}]/[{1}]", First.Pos.Latitude, First.Pos.Longitude); 

     DataCalc Second = new DataCalc() { Distance = 0 }; 
     foreach (DataCalc dc in dataCalc) 
     { 
      if (dc.Distance > Second.Distance 
       && (dc.Pos.Latitude != First.Pos.Latitude && dc.Pos.Longitude != First.Pos.Longitude)) 
      { 
       Second = dc; 
      } 
     } 
     Debug.WriteLine("the second is on [{0}]/[{1}]", Second.Pos.Latitude, Second.Pos.Longitude); 

     FarestPos[0] = First.Pos; 
     FarestPos[1] = Second.Pos; 

     return (FarestPos); 
    } 
    public class CameraFocusData 
    { 
     public Position Position { get; set; } 
     public Distance Distance { get; set; } 
    } 

    //HAVERSINE 
    public static CameraFocusData GetPositionAndZoomLevelForCameraAboutPositions(Position[] FarestPoints) 
    { 
     double earthRadius = 6371000; //metros 

     Position pos1 = FarestPoints[0]; 
     Position pos2 = FarestPoints[1]; 

     double latitud1Radianes = pos1.Latitude * (Math.PI/180.0); 
     double latitud2Radianes = pos2.Latitude * (Math.PI/180.0); 
     double longitud1Radianes = pos2.Longitude * (Math.PI/180.0); 
     double longitud2Radianes = pos2.Longitude * (Math.PI/180.0); 

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

     double sum1 = Math.Sin(deltaLatitud/2) * Math.Sin(deltaLatitud/2); 
     double sum2 = Math.Cos(latitud1Radianes) * Math.Cos(latitud2Radianes) * Math.Sin(deltaLongitud/2) * Math.Sin(deltaLongitud/2); 

     var a = sum1 + sum2; 
     var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a)); 

     var distance = earthRadius * c; 

     /* lt is deltaLatitud 
     * lng is deltaLongitud*/ 
     var Bx = Math.Cos(latitud2Radianes) * Math.Cos(deltaLongitud); 
     var By = Math.Cos(latitud2Radianes) * Math.Sin(deltaLongitud); 
     var lt = 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 lng = longitud1Radianes + Math.Atan2(By, Math.Cos(longitud1Radianes) + Bx);//Longitud del punto medio 

     Debug.WriteLine("the final pos of the camera is on [{0}]/[{1}]", lt, lng); 

     return (new CameraFocusData() { Position = new Position(lt, lng), Distance = new Distance(distance + 0.2) }); 
    } 
    #endregion 

回答

1

然后我找到了解决办法,有它的代码,它已被写为放入您的自定义地图。

这里,private static void OnCustomPinsPropertyChanged(BindableObject bindable, object oldValue, object newValue)是一个方法,我的List<CustomPins>调用,但您可以使用不同的方法。

public static readonly BindableProperty CustomPinsProperty = 
     BindableProperty.Create(nameof(CustomPins), typeof(IList<CustomPin>), typeof(CustomMap), null, 
      propertyChanged: OnCustomPinsPropertyChanged); 

此外,您还可以添加经/纬的用户,我没有做到这一点的,因为我需要它是没有用户:)的POS机。

Finaly,你可以添加一个乘数的放大,我的意思是,你可能会说,嗯,变焦是迄今为止对我来说,那好吧,不喜欢我和多样信息的东西作为0.70.6double distance值: )

#region Camera focus definition 
    public class CameraFocusData 
    { 
     public Position Position { get; set; } 
     public Distance Distance { get; set; } 
    } 
    private static void OnCustomPinsPropertyChanged(BindableObject bindable, object oldValue, object newValue) 
    { 
     CustomMap customMap = ((CustomMap)bindable); 

     if (customMap.CameraFocusParameter == CameraFocusReference.OnPins) 
     { 
      List<double> latitudes = new List<double>(); 
      List<double> longitudes = new List<double>(); 

      foreach (CustomPin pin in (newValue as List<CustomPin>)) 
      { 
       latitudes.Add(pin.Position.Latitude); 
       longitudes.Add(pin.Position.Longitude); 
      } 

      double lowestLat = latitudes.Min(); 
      double highestLat = latitudes.Max(); 
      double lowestLong = longitudes.Min(); 
      double highestLong = longitudes.Max(); 
      double finalLat = (lowestLat + highestLat)/2; 
      double finalLong = (lowestLong + highestLong)/2; 

      double distance = DistanceCalculation.GeoCodeCalc.CalcDistance(lowestLat, lowestLong, highestLat, highestLong, DistanceCalculation.GeoCodeCalcMeasurement.Kilometers); 

      customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(finalLat, finalLong), Distance.FromKilometers(distance * 0.7))); 
     } 
    } 
    private class DistanceCalculation 
    { 
     public static class GeoCodeCalc 
     { 
      public const double EarthRadiusInMiles = 3956.0; 
      public const double EarthRadiusInKilometers = 6367.0; 

      public static double ToRadian(double val) { return val * (Math.PI/180); } 
      public static double DiffRadian(double val1, double val2) { return ToRadian(val2) - ToRadian(val1); } 

      public static double CalcDistance(double lat1, double lng1, double lat2, double lng2) 
      { 
       return CalcDistance(lat1, lng1, lat2, lng2, GeoCodeCalcMeasurement.Miles); 
      } 

      public static double CalcDistance(double lat1, double lng1, double lat2, double lng2, GeoCodeCalcMeasurement m) 
      { 
       double radius = GeoCodeCalc.EarthRadiusInMiles; 

       if (m == GeoCodeCalcMeasurement.Kilometers) { radius = GeoCodeCalc.EarthRadiusInKilometers; } 
       return radius * 2 * Math.Asin(Math.Min(1, Math.Sqrt((Math.Pow(Math.Sin((DiffRadian(lat1, lat2))/2.0), 2.0) + Math.Cos(ToRadian(lat1)) * Math.Cos(ToRadian(lat2)) * Math.Pow(Math.Sin((DiffRadian(lng1, lng2))/2.0), 2.0))))); 
      } 
     } 

     public enum GeoCodeCalcMeasurement : int 
     { 
      Miles = 0, 
      Kilometers = 1 
     } 
    } 
    #endregion 

玩得开心!

相关问题