src/cs/Coordinate/Coordinate.cs

using System;
using System.Collections.ObjectModel;
 
public class Coordinate {
    public const double SemiMajorAxis = 6378137.0;// a (in meters)
    public const double SemiMinorAxis = 6356752.31424518;// b (in meters)
    public const double FlatteningFactor = 298.257223563;// 1/f
    public const double LinearEccentricity = 521854.00842339;// E (in meters)
    public const double Eccentricity = 0.0818191908426215;// e
    public const double EccentricitySquared = 0.006694379990141;// e2
    public const double Radius = 6371001;// mean radius (in meters)
    public const double RadiusAuthalic = 6371007.1810;// radius constant surface area (in meters)
    private double _Latitude;
    private double _Longitude;
    private string[] _Hemisphere = new string[] { "N", "E" };
    public string[] Hemisphere {
        get {
            return _Hemisphere;
        }
        private set {
            _Hemisphere = value;
        }
    }
    public double Latitude {
        get {
            return _Latitude;
        }
        set {
            this.Hemisphere[0] = value < 0 ? "S" : "N";
            _Latitude = value;
        }
    }
    public double Longitude {
        get {
            return _Longitude;
        }
        set {
            this.Hemisphere[1] = value < 0 ? "W" : "E";
            _Longitude = value;
        }
    }
    public double Height;
    private static double ToDegree(double value) {
        return value * (180 / Math.PI);
    }
    private static double ToRadian(double value) {
        return value * (Math.PI / 180);
    }
    private static double Hav(double value) {
        return 0.5 * (1 - Math.Cos(ToRadian(value)));
    }
    public static double[] ToSexagesimal(double value) {
        double fractionalPart = Math.Abs(value - Math.Truncate(value));
        double degree = Math.Truncate(value);
        double minute = Math.Truncate(fractionalPart * 60);
        double second = Math.Round(((fractionalPart * 60) - minute) * 60, 2);
        return new double[] { degree, minute, second };
    }
    public Coordinate() {
        this.Latitude = 0.0;
        this.Longitude = 0.0;
        this.Height = 0.0;
    }
    public Coordinate(double latitude, double longitude, double height = 0.0) {
        this.Latitude = latitude;
        this.Longitude = longitude;
        this.Height = height;
    }
    public static Coordinate FromCartesian(double x, double y, double z) {
        double[] geodetic = ToGeodetic(x, y, z);
        double latitude = geodetic[0];
        double longitude = geodetic[1];
        double height = geodetic[2];
        return new Coordinate(latitude, longitude, height);
    }
    public static double[] ToGeodetic(double x, double y, double z) {
        double a = SemiMajorAxis;
        double b = SemiMinorAxis;
        double E = LinearEccentricity;
        double E2 = Math.Pow(E, 2);
        double x2 = Math.Pow(x, 2), y2 = Math.Pow(y, 2), z2 = Math.Pow(z, 2);
        double r2 = x2 + y2 + z2;
        double Q = Math.Sqrt(x2 + y2);
        double u = Math.Sqrt((0.5 * (r2 - E2)) + (0.5 * Math.Sqrt(Math.Pow(r2 - E2, 2) + (4 * E2 * z2))));
        double u2 = Math.Pow(u, 2);
        double beta = Math.Atan((Math.Sqrt(u2 + E2) * z) / (u * Q));
        double latitude = Math.Atan((a / b) * Math.Tan(beta));
        double longitude = Math.Atan2(y, x);
        double height = Math.Sqrt(Math.Pow(z - (b * Math.Sin(beta)), 2) + Math.Pow(Q - (a * Math.Cos(beta)), 2));
        return new double[] { ToDegree(latitude), ToDegree(longitude), height };
    }
    public static double[] ToCartesian(double latitude, double longitude, double height = 0) {
        double a = SemiMajorAxis;
        double e2 = EccentricitySquared;
        double lat = ToRadian(latitude);
        double lon = ToRadian(longitude);
        double h = height;
        double v = a / Math.Sqrt(1 - (e2 * Math.Pow(Math.Sin(lat), 2)));
        double x = Math.Cos(lat) * Math.Cos(lon) * (v + h);
        double y = Math.Cos(lat) * Math.Sin(lon) * (v + h);
        double z = Math.Sin(lat) * ((v * (1 - e2)) + h);
        return new double[] { x, y, z };
    }
    public override string ToString() {
        double latitude = Math.Abs(this.Latitude);
        double longitude = Math.Abs(this.Longitude);
        string NS = this.Hemisphere[0];
        string WE = this.Hemisphere[1];
        string[] lat = Array.ConvertAll(ToSexagesimal(latitude), Convert.ToString);
        string[] lon = Array.ConvertAll(ToSexagesimal(longitude), Convert.ToString);
        return lat[0] + "°" + lat[1] + "'" + lat[2] + "\"" + NS + " " + lon[0] + "°" + lon[1] + "'" + lon[2] + "\"" + WE;
    }
}