none
Calculate Location degree in C# RRS feed

  • Question

  • Hi,

    I am trying below code to calculate location degree using C# in order to show it later on a compass

    My target is to make the compass always pointing to this location:

    MakkaLatitude = 21.422487;
    MakkaLongitude = 39.826206;

    but the code seems to be having a problem becaue it's just not point ot the correct location.

    can any one hep please

    using System;
    using System.Collections.Generic;
    using System.Text;
    using Xamarin.Forms;
    using Xamarin.Essentials;
    using System.Threading.Tasks;
    
    namespace EssentialCompass
    {
        public class MyCompassViewModel : MvvmHelpers.BaseViewModel
        {
            public MyCompassViewModel()
            {
                StopCommand = new Command(Stop);
                StartCommand = new Command(Start);
    
                GetLocation();
            }
    
    public double MakkaLatitude = 21.422487;
    public double MakkaLongitude = 39.826206;
    
            // TEMP
            double current_latitude = 25.2624896;
            double current_longitude = 55.325491199999995;
    
            string headingDisplay;
    
            private async void GetLocation()
            {
                var request = new GeolocationRequest(GeolocationAccuracy.Medium);
                var location = await Geolocation.GetLocationAsync(request);
    
                current_latitude = location.Latitude;
                current_longitude = location.Longitude;
    
                System.Diagnostics.Debug.WriteLine(Convert.ToString("current_latitude is " + current_latitude));
                System.Diagnostics.Debug.WriteLine(Convert.ToString("current_longitude is " + current_longitude));
            }
    
            public string HeadingDisplay
            {
                get => headingDisplay;
                set => SetProperty(ref headingDisplay, value);
            }
    
            double heading = 0;
            public double Heading
            {
                get => heading;
                set => SetProperty(ref heading, value);
            }
    
            public Command StopCommand { get; }
    
            void Stop()
            {
                if (!Compass.IsMonitoring)
                    return;
    
                Compass.ReadingChanged -= Compass_ReadingChanged;
                Compass.Stop();
            }
    
    
            public Command StartCommand { get; }
    
            void Start()
            {
                if (Compass.IsMonitoring)
                    return;
    
                // Compass.ApplyLowPassFilter = true;
                Compass.ReadingChanged += Compass_ReadingChanged;
                Compass.Start(SensorSpeed.UI);
    
            }
    
            void Compass_ReadingChanged(object sender, CompassChangedEventArgs e)
            {
                Heading = DegreeBearing(current_latitude, current_longitude, MakkaLatitude, MakkaLongitude);
    
                // Heading = e.Reading.HeadingMagneticNorth;
                // HeadingDisplay = $"Heading: {Heading.ToString()}";
            }
    
            static double DegreeBearing(double lat1, double lon1, double lat2, double lon2)
            {
                var dLon = ToRad(lon2 - lon1);
                var dPhi = Math.Log(Math.Tan(ToRad(lat2) / 2 + Math.PI / 4) / Math.Tan(ToRad(lat1) / 2 + Math.PI / 4));
    
                if (Math.Abs(dLon) > Math.PI) dLon = dLon > 0 ? -(2 * Math.PI - dLon) : (2 * Math.PI + dLon);
    
                return ToBearing(Math.Atan2(dLon, dPhi));
            }
    
            public static double ToRad(double degrees)
            {
                return degrees * (Math.PI / 180);
            }
    
            public static double ToDegrees(double radians)
            {
                return radians * 180 / Math.PI;
            }
    
            public static double ToBearing(double radians)
            {
                return (ToDegrees(radians) + 180) % 180;
            }
        }
    }
    

    Thanks,

    Jassim

    Friday, August 9, 2019 9:47 AM

All replies

  • I tried it but I am getting totally oppisite location as you can see in the attached screenshot

    Here is what I am getting:

    and this is the correct pointing:

    sand here is my updated code:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Xamarin.Essentials;
    using Xamarin.Forms;
    
    namespace TheCompass
    {
        // Learn more about making custom code visible in the Xamarin.Forms previewer
        // by visiting https://aka.ms/xamarinforms-previewer
        [DesignTimeVisible(false)]
        public partial class MainPage : ContentPage
        {
            const double Rad2Deg = 180.0 / Math.PI;
            const double Deg2Rad = Math.PI / 180.0;
    
            double current_latitude;
            double current_longitude;
    
            double HolyPlaceLatitude = 21.422487;
            double HolyPlaceLongitude = 39.826206;
    
            public MainPage()
            {
                InitializeComponent();
    
                Accelerometer.ReadingChanged += Accelerometer_ReadingChanged;
                this.BindingContext = this;
    
                GetLocation();
            }
    
            private void Accelerometer_ReadingChanged(object sender, AccelerometerChangedEventArgs e)
            {
                pointer1.Value = Angle(new Point(current_latitude, current_longitude), new Point(HolyPlaceLatitude, HolyPlaceLongitude));
    
                LabelCurrentLatitude.Text = "Current Latitude: " + Convert.ToString(current_latitude);
                LabelCurrentLongitude.Text = "Current Longitude: " + Convert.ToString(current_longitude);
    
                LabelPointingToLatitude.Text = "Makka Latitude: " + Convert.ToString(HolyPlaceLatitude);
                LabelPointingToLongitude.Text = "Makka Longitude: " + Convert.ToString(HolyPlaceLongitude);
            }
    
            protected override void OnAppearing()
            {
                base.OnAppearing();
    
                pointer1.Value = Angle(new Point(current_latitude, current_longitude), new Point(HolyPlaceLatitude, HolyPlaceLongitude));
    
                Accelerometer.Start(SensorSpeed.UI);
            }
    
            private async void GetLocation()
            {
                var request = new GeolocationRequest(GeolocationAccuracy.Medium);
                var location = await Geolocation.GetLocationAsync(request);
    
                current_latitude = location.Latitude;
                current_longitude = location.Longitude;
    
                System.Diagnostics.Debug.WriteLine(Convert.ToString("current_latitude is " + current_latitude));
                System.Diagnostics.Debug.WriteLine(Convert.ToString("current_longitude is " + current_longitude));
            }
    
            private double Angle(Point start, Point end)
            {
                return Math.Atan2(start.Y - end.Y, end.X - start.X) * Rad2Deg;
            }
    
            private void Scale_LabelCreated(object sender, Syncfusion.SfGauge.XForms.LabelCreatedEventArgs args)
            {
                switch ((string)args.LabelContent)
                {
                    case "0":
                        args.LabelContent = "N";
                        break;
                    case "45":
                        args.LabelContent = "NE";
                        break;
                    case "90":
                        args.LabelContent = "E";
                        break;
                    case "135":
                        args.LabelContent = "SE";
                        break;
                    case "180":
                        args.LabelContent = "S";
                        break;
                    case "225":
                        args.LabelContent = "SW";
                        break;
                    case "270":
                        args.LabelContent = "W";
                        break;
                    case "315":
                        args.LabelContent = "NW";
                        break;
                    case "360":
                        args.LabelContent = "N";
                        break;
                }
            }
        }
    }
    

    Sunday, August 11, 2019 9:28 AM
  •     [DesignTimeVisible(false)]
        public partial class MainPage : ContentPage
        {
            const double Rad2Deg = 180.0 / Math.PI;
            const double Deg2Rad = Math.PI / 180.0;
    
            double current_latitude = 25.2624896;
            double current_longitude = 55.325491199999995;
    
            double HolyPlaceLatitude = 21.422487;
            double HolyPlaceLongitude = 39.826206;
    
            public MainPage()
            {
                InitializeComponent();
    
                this.BindingContext = this;
    
            }
    
    
    
            protected override void OnAppearing()
            {
                base.OnAppearing();
    
                LabelAngle.Text = DegreeBearing(current_latitude, current_longitude, HolyPlaceLatitude,HolyPlaceLongitude).ToString();
    
                LabelCurrentLatitude.Text = "Current Latitude: " + Convert.ToString(current_latitude);
                LabelCurrentLongitude.Text = "Current Longitude: " + Convert.ToString(current_longitude);
    
                LabelPointingToLatitude.Text = "Makka Latitude: " + Convert.ToString(HolyPlaceLatitude);
                LabelPointingToLongitude.Text = "Makka Longitude: " + Convert.ToString(HolyPlaceLongitude);
            }
    
    
            static double DegreeBearing(double lat1, double lon1, double lat2, double lon2)
            {
                var dLon = ToRad(lon2 - lon1);
                var dPhi = Math.Log(Math.Tan(ToRad(lat2) / 2 + Math.PI / 4) / Math.Tan(ToRad(lat1) / 2 + Math.PI / 4));
    
                if (Math.Abs(dLon) > Math.PI) dLon = dLon > 0 ? -(2 * Math.PI - dLon) : (2 * Math.PI + dLon);
    
                return ToBearing(Math.Atan2(dLon, dPhi));
            }
    
            public static double ToRad(double degrees)
            {
                return degrees * (Math.PI / 180);
            }
    
            public static double ToDegrees(double radians)
            {
                return radians * 180 / Math.PI;
            }
    
            public static double ToBearing(double radians)
            {
                return (ToDegrees(radians) + 180) % 180;
            }

    Sunday, August 11, 2019 10:08 AM
  • It's the same problem

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Xamarin.Essentials;
    using Xamarin.Forms;
    
    namespace TheCompass
    {
        // Learn more about making custom code visible in the Xamarin.Forms previewer
        // by visiting https://aka.ms/xamarinforms-previewer
        [DesignTimeVisible(false)]
        public partial class MainPage : ContentPage
        {
            const double Rad2Deg = 180.0 / Math.PI;
            const double Deg2Rad = Math.PI / 180.0;
    
            double current_latitude = 25.2624896;
            double current_longitude = 55.325491199999995;
    
            double HolyPlaceLatitude = 21.422487;
            double HolyPlaceLongitude = 39.826206;
    
            public MainPage()
            {
                InitializeComponent();
    
                // Accelerometer.ReadingChanged += Accelerometer_ReadingChanged;
                this.BindingContext = this;
    
                GetLocation();
            }
    
            private void Accelerometer_ReadingChanged(object sender, AccelerometerChangedEventArgs e)
            {
                Xamarin.Essentials.Geolocation.GetLocationAsync(new Xamarin.Essentials.GeolocationRequest { DesiredAccuracy = Xamarin.Essentials.GeolocationAccuracy.Default, Timeout = TimeSpan.FromSeconds(10) }).ContinueWith((t) =>
                {
                    if (t.Exception != null)
                    {
                        var results = t.Result;
    
                        current_latitude = results.Latitude;
                        current_longitude = results.Longitude;
                    }
                });
    
                pointer1.Value = Angle(new Point(current_latitude, current_longitude), new Point(HolyPlaceLatitude, HolyPlaceLongitude));
    
                LabelCurrentLatitude.Text = "Current Latitude: " + Convert.ToString(current_latitude);
                LabelCurrentLongitude.Text = "Current Longitude: " + Convert.ToString(current_longitude);
    
                LabelPointingToLatitude.Text = "Makka Latitude: " + Convert.ToString(HolyPlaceLatitude);
                LabelPointingToLongitude.Text = "Makka Longitude: " + Convert.ToString(HolyPlaceLongitude);
            }
    
            protected override void OnAppearing()
            {
                base.OnAppearing();
    
                LabelAngle.Text = "Angle: " + DegreeBearing(current_latitude, current_longitude, HolyPlaceLatitude, HolyPlaceLongitude).ToString();
    
                LabelCurrentLatitude.Text = "Current Latitude: " + Convert.ToString(current_latitude);
                LabelCurrentLongitude.Text = "Current Longitude: " + Convert.ToString(current_longitude);
    
                LabelPointingToLatitude.Text = "Makka Latitude: " + Convert.ToString(HolyPlaceLatitude);
                LabelPointingToLongitude.Text = "Makka Longitude: " + Convert.ToString(HolyPlaceLongitude);
    
                pointer1.Value = Angle(new Point(current_latitude, current_longitude), new Point(HolyPlaceLatitude, HolyPlaceLongitude));
    
                // Accelerometer.Start(SensorSpeed.UI);
            }
    
            static double DegreeBearing(double lat1, double lon1, double lat2, double lon2)
            {
                var dLon = ToRad(lon2 - lon1);
                var dPhi = Math.Log(Math.Tan(ToRad(lat2) / 2 + Math.PI / 4) / Math.Tan(ToRad(lat1) / 2 + Math.PI / 4));
    
                if (Math.Abs(dLon) > Math.PI) dLon = dLon > 0 ? -(2 * Math.PI - dLon) : (2 * Math.PI + dLon);
    
                return ToBearing(Math.Atan2(dLon, dPhi));
            }
    
            public static double ToRad(double degrees)
            {
                return degrees * (Math.PI / 180);
            }
    
            public static double ToDegrees(double radians)
            {
                return radians * 180 / Math.PI;
            }
    
            public static double ToBearing(double radians)
            {
                return (ToDegrees(radians) + 180) % 180;
            }
    
            private async void GetLocation()
            {
                var request = new GeolocationRequest(GeolocationAccuracy.Medium);
                var location = await Geolocation.GetLocationAsync(request);
    
                current_latitude = location.Latitude;
                current_longitude = location.Longitude;
    
                System.Diagnostics.Debug.WriteLine(Convert.ToString("current_latitude is " + current_latitude));
                System.Diagnostics.Debug.WriteLine(Convert.ToString("current_longitude is " + current_longitude));
            }
    
            private double Angle(Point start, Point end)
            {
                return Math.Atan2(start.Y - end.Y, end.X - start.X) * Rad2Deg;
            }
    
            private void Scale_LabelCreated(object sender, Syncfusion.SfGauge.XForms.LabelCreatedEventArgs args)
            {
                switch ((string)args.LabelContent)
                {
                    case "0":
                        args.LabelContent = "N";
                        break;
                    case "45":
                        args.LabelContent = "NE";
                        break;
                    case "90":
                        args.LabelContent = "E";
                        break;
                    case "135":
                        args.LabelContent = "SE";
                        break;
                    case "180":
                        args.LabelContent = "S";
                        break;
                    case "225":
                        args.LabelContent = "SW";
                        break;
                    case "270":
                        args.LabelContent = "W";
                        break;
                    case "315":
                        args.LabelContent = "NW";
                        break;
                    case "360":
                        args.LabelContent = "N";
                        break;
                }
            }
        }
    }
    

    Sunday, August 11, 2019 10:16 AM
  • Hi Jassim Rahma, 

    Thank you for posting here.

    According to your description, your issue is more related to Xamarin.Forms. Therefore, it will be more appropriate to ask your question in Xamarin.Forms Forums.

    The CLR Forum discuss and ask questions about .NET Framework Base Classes (BCL) such as Collections, I/O, Regigistry, Globalization, Reflection. Also discuss all the other Microsoft libraries that are built on or extend the .NET Framework, including Managed Extensibility Framework (MEF), Charting Controls, CardSpace, Windows Identity Foundation (WIF), Point of Sale (POS), Transactions.

    Thank you for your understanding.

    Best Regards,

    Xingyu Zhao


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, August 12, 2019 8:36 AM