コード例 #1
0
ファイル: GeoHash.cs プロジェクト: Vanaheimr/Aegir
        /// <summary>
        /// Encode the given latitude and longitude as geohash.
        /// </summary>
        /// <param name="Latitude">The latitude.</param>
        /// <param name="Longitude">The longitude.</param>
        /// <param name="Precision">An optional precision aka number of characters of the resulting geohash.</param>
        /// <returns>The latitude and longitude encoded as geohash.</returns>
        private static String Encode(Latitude Latitude, Longitude Longitude, Byte Precision = 12)
        {
            var    even = true;
            var    bit = 0;
            var    character = 0;
            var    GeoHash = new StringBuilder();
            var    bitmask = 16;
            Double midLat, midLon;

            var _MinLatitude  = GeoCoordinate.MinLatitude.Value;
            var _MaxLatitude  = GeoCoordinate.MaxLatitude.Value;
            var _MinLongitude = GeoCoordinate.MinLongitude.Value;
            var _MaxLongitude = GeoCoordinate.MaxLongitude.Value;

            if (Precision < 1 || Precision > 20)
            {
                Precision = 12;
            }

            for (var i = 0; i < 5 * Precision; i++)
            {
                if (even)
                {
                    midLon = (_MinLongitude + _MaxLongitude) / 2;

                    if (Longitude.Value > midLon)
                    {
                        // Set 1!
                        character    |= bitmask;
                        _MinLongitude = midLon;
                    }
                    else
                    {
                        // Set 0!
                        _MaxLongitude = midLon;
                    }
                }
                else
                {
                    midLat = (_MinLatitude + _MaxLatitude) / 2;

                    if (Latitude.Value > midLat)
                    {
                        // Set 1!
                        character   |= bitmask;
                        _MinLatitude = midLat;
                    }
                    else
                    {
                        // Set 0!
                        _MaxLatitude = midLat;
                    }
                }

                even = !even;

                if (bit == 4)
                {
                    GeoHash.Append(GeoHashAlphabet[character]);
                    bit       = 0;
                    bitmask   = 16;
                    character = 0;
                }
                else
                {
                    bit++;
                    bitmask >>= 1;
                }
            }

            return(GeoHash.ToString());
        }
コード例 #2
0
ファイル: GeoHash32.cs プロジェクト: lanicon/Styx
        /// <summary>
        /// Encode the given latitude and longitude as geohash.
        /// </summary>
        /// <param name="Latitude">The latitude.</param>
        /// <param name="Longitude">The longitude.</param>
        /// <param name="Precision">An optional precision aka number of bits of the resulting geohash.</param>
        /// <returns>The latitude and longitude encoded as geohash.</returns>
        private static UInt32 Encode(Latitude Latitude, Longitude Longitude, Byte Precision = 16)
        {
            var _GeoHash      = 0U;
            var _MidLatitude  = 0.0;
            var _MidLongitude = 0.0;
            var _MinLatitude  = -90.0;
            var _MaxLatitude  = 90.0;
            var _MinLongitude = -180.0;
            var _MaxLongitude = 180.0;

            if (Precision > 16)
            {
                Precision = 16;
            }

            for (var i = 0; i < Precision; i++)
            {
                // Shrink latitude intervall
                if (_MinLatitude < _MaxLatitude)
                {
                    _MidLatitude = (_MinLatitude + _MaxLatitude) / 2;

                    if (Latitude.Value > _MidLatitude)
                    {
                        _GeoHash    |= 1;
                        _MinLatitude = _MidLatitude;
                    }

                    else
                    {
                        _MaxLatitude = _MidLatitude;
                    }
                }

                _GeoHash <<= 1;

                // Shrink longitude intervall
                if (_MinLongitude < _MaxLongitude)
                {
                    _MidLongitude = (_MinLongitude + _MaxLongitude) / 2;

                    if (Longitude.Value > _MidLongitude)
                    {
                        _GeoHash     |= 1;
                        _MinLongitude = _MidLongitude;
                    }

                    else
                    {
                        _MaxLongitude = _MidLongitude;
                    }
                }

                if (i < Precision - 1)
                {
                    _GeoHash <<= 1;
                }
            }

            return(_GeoHash);
        }
コード例 #3
0
ファイル: GeoHash.cs プロジェクト: Vanaheimr/Aegir
 /// <summary>
 /// Create a new base32-encoded alphanumeric geohash.
 /// </summary>
 /// <param name="Latitude">The latitude.</param>
 /// <param name="Longitude">The longitude.</param>
 /// <param name="Precision">An optional precision aka number of characters of the resulting geohash.</param>
 public GeoHash(Latitude Latitude, Longitude Longitude, Byte Precision = 12)
     : this(Encode(Latitude, Longitude, Precision))
 {
 }
コード例 #4
0
        /// <summary>
        /// Create a new geographical coordinate or position on a map.
        /// </summary>
        /// <param name="Latitude">The Latitude (south to nord).</param>
        /// <param name="Longitude">The Longitude (parallel to equator).</param>
        /// <param name="Altitude">The (optional) Altitude.</param>
        public static GeoCoordinate Create(Latitude Latitude,
                                           Longitude Longitude,
                                           Altitude?Altitude = null)

        => new GeoCoordinate(Latitude, Longitude, Altitude);
コード例 #5
0
        /// <summary>
        /// Encode the given latitude and longitude as geohash.
        /// </summary>
        /// <param name="Latitude">The latitude.</param>
        /// <param name="Longitude">The longitude.</param>
        /// <param name="Precision">An optional precision aka number of bits of the resulting geohash (1-32 bit).</param>
        /// <returns>The latitude and longitude encoded as geohash.</returns>
        private static UInt64 Encode(Latitude Latitude, Longitude Longitude, Byte Precision = 32)
        {
            var _GeoHash      = 0UL;
            var _MidLatitude  = 0.0;
            var _MidLongitude = 0.0;
            var _MinLatitude  = GeoCoordinate.MinLatitude.Value;
            var _MaxLatitude  = GeoCoordinate.MaxLatitude.Value;
            var _MinLongitude = GeoCoordinate.MinLongitude.Value;
            var _MaxLongitude = GeoCoordinate.MaxLongitude.Value;

            if (Precision > 32)
            {
                Precision = 32;
            }

            for (var i = 0; i < Precision; i++)
            {
                // Shrink latitude intervall
                if (_MinLatitude < _MaxLatitude)
                {
                    _MidLatitude = (_MinLatitude + _MaxLatitude) / 2;

                    if (Latitude.Value > _MidLatitude)
                    {
                        _GeoHash    |= 1;
                        _MinLatitude = _MidLatitude;
                    }

                    else
                    {
                        _MaxLatitude = _MidLatitude;
                    }
                }

                _GeoHash <<= 1;

                // Shrink longitude intervall
                if (_MinLongitude < _MaxLongitude)
                {
                    _MidLongitude = (_MinLongitude + _MaxLongitude) / 2;

                    if (Longitude.Value > _MidLongitude)
                    {
                        _GeoHash     |= 1;
                        _MinLongitude = _MidLongitude;
                    }

                    else
                    {
                        _MaxLongitude = _MidLongitude;
                    }
                }

                if (i < Precision - 1)
                {
                    _GeoHash <<= 1;
                }
            }

            return(_GeoHash);
        }
コード例 #6
0
        /// <summary>
        /// Checks if and where the given lines intersect.
        /// </summary>
        /// <param name="Line">A line.</param>
        /// <param name="IntersectionGeoCoordinate">The intersection of both lines.</param>
        /// <param name="InfiniteLines">Whether the lines should be treated as infinite or not.</param>
        /// <returns>True if the lines intersect; False otherwise.</returns>
        public Boolean IntersectsWith(GeoLine Line, out GeoCoordinate IntersectionGeoCoordinate, Boolean InfiniteLines = false, Boolean ExcludeEdges = false)
        {
            #region Initial Checks

            if (Line == null)
            {
                IntersectionGeoCoordinate = default(GeoCoordinate);
                return(false);
            }

            #endregion

            // Assume both lines are infinite in order to get their intersection...

            #region This line is just a pixel

            if (this.IsJustAPixel())
            {
                if (Line.Contains(P1))
                {
                    IntersectionGeoCoordinate = P1;
                    return(true);
                }

                IntersectionGeoCoordinate = default(GeoCoordinate);
                return(false);
            }

            #endregion

            #region The given line is just a pixel

            else if (Line.IsJustAPixel())
            {
                if (this.Contains(Line.P1))
                {
                    IntersectionGeoCoordinate = Line.P1;
                    return(true);
                }

                IntersectionGeoCoordinate = default(GeoCoordinate);
                return(false);
            }

            #endregion

            #region Both lines are parallel

            else if (this.Gradient == Line.Gradient)
            {
                IntersectionGeoCoordinate = default(GeoCoordinate);
                return(false);
            }

            #endregion

            #region Both lines are antiparallel

            else if (this.Gradient == -1 * Line.Gradient)
            {
                IntersectionGeoCoordinate = default(GeoCoordinate);
                return(false);
            }

            #endregion

            #region This line is parallel to the y-axis

            else if (Double.IsInfinity(Gradient))
            {
                IntersectionGeoCoordinate = new GeoCoordinate(
                    Latitude.Parse(Line.Gradient * P1.Longitude.Value + Line.YIntercept),
                    P1.Longitude
                    );
            }

            #endregion

            #region The given line is parallel to the y-axis

            else if (Double.IsInfinity(Line.Gradient))
            {
                IntersectionGeoCoordinate = new GeoCoordinate(
                    Latitude.Parse(Gradient * Line.P1.Longitude.Value + YIntercept),
                    Line.P1.Longitude
                    );
            }

            #endregion

            #region There is a real intersection

            else
            {
                //IntersectionGeoCoordinate = null;
                //// this Line
                //var A1 = this.P2.Latitude. Value - this.P1.Latitude. Value;
                //var B1 = this.P2.Longitude.Value - this.P1.Longitude.Value;
                //var C1 = A1 * this.P1.Longitude.Value + B1 * this.P1.Latitude.Value;

                //// Line2
                //var A2 = Line.P2.Latitude. Value - Line.P1.Latitude. Value;
                //var B2 = Line.P2.Longitude.Value - Line.P1.Longitude.Value;
                //var C2 = A2 * Line.P1.Longitude.Value + B2 * Line.P1.Latitude.Value;

                //var det = A1 * B2 - A2 * B1;
                //if (det == 0)
                //{
                //    //parallel lines
                //}
                //else
                //{
                //    var x = (B2 * C1 - B1 * C2) / det;
                //    var y = (A1 * C2 - A2 * C1) / det;
                //    IntersectionGeoCoordinate = new GeoCoordinate(new Latitude (y),
                //                                                  new Longitude(x));
                //}

                IntersectionGeoCoordinate = new GeoCoordinate(
                    Latitude.Parse((this.YIntercept * Line.Gradient - Line.YIntercept * this.Gradient) / (Line.Gradient - this.Gradient)),
                    Longitude.Parse((Line.YIntercept - this.YIntercept) / (this.Gradient - Line.Gradient))
                    );
            }

            #endregion

            if (InfiniteLines)
            {
                return(true);
            }

            else if (!ExcludeEdges)
            {
                return(this.Contains(IntersectionGeoCoordinate));
            }

            else
            {
                if (this.Contains(IntersectionGeoCoordinate))
                {
                    if (IntersectionGeoCoordinate.Equals(P1) ||
                        IntersectionGeoCoordinate.Equals(P2) ||
                        IntersectionGeoCoordinate.Equals(Line.P1) ||
                        IntersectionGeoCoordinate.Equals(Line.P2))
                    {
                        return(false);
                    }

                    return(true);
                }

                return(false);
            }
        }
コード例 #7
0
 public static Double ToDegree(this Latitude Latitude)
 {
     return(Latitude.Value * (180 / Math.PI));
 }
コード例 #8
0
 public static Double ToRadians(this Latitude Latitude)
 {
     return(Latitude.Value * (Math.PI / 180));
 }
コード例 #9
0
ファイル: Polyfile2ShapeInfo.cs プロジェクト: lanicon/Styx
        public static ShapeInfo Polyfile2ShapeInfo(IEnumerable <String> InputData, UInt32 min_resolution, UInt32 max_resolution)
        {
            #region Init

            var Integer     = 1U;
            var ShapeNumber = 1U;
            var IsFirstLine = true;
            var Description = String.Empty;

            var min_lat = Double.MaxValue;
            var min_lng = Double.MaxValue;
            var max_lat = Double.MinValue;
            var max_lng = Double.MinValue;

            var Shapes = new Dictionary <UInt32, Tuple <List <GeoCoordinate>,
                                                        Dictionary <UInt32,
                                                                    Tuple <List <ScreenXY>, StringBuilder> > > >();

            GeoCoordinate GeoCoordinate = default(GeoCoordinate);

            #endregion

            foreach (var Line in InputData)
            {
                #region Process first line

                if (IsFirstLine)
                {
                    Description = Line;
                    IsFirstLine = false;
                }

                #endregion

                #region A single Integer on a line indicates the start of a new shape

                else if (UInt32.TryParse(Line, out Integer))
                {
                    ShapeNumber = Integer;
                    Shapes.Add(ShapeNumber, new Tuple <List <GeoCoordinate>, Dictionary <UInt32, Tuple <List <ScreenXY>, StringBuilder> > >(
                                   new List <GeoCoordinate>(),
                                   new Dictionary <UInt32, Tuple <List <ScreenXY>, StringBuilder> >()));
                }

                #endregion

                #region "END" indicates the end of a shape

                else if (Line == "END")
                {
                    continue;
                }

                #endregion

                #region The rest of the file are "Longitude Latitude" encoded geo coordinates

                else if (GeoCoordinate.TryParseString(Line, out GeoCoordinate))
                {
                    // Polyfiles store "Longitude Latitude"!!!
                    Shapes[ShapeNumber].Item1.Add(new GeoCoordinate(
                                                      Latitude.Parse(GeoCoordinate.Longitude.Value),
                                                      Longitude.Parse(GeoCoordinate.Latitude.Value)
                                                      ));

                    if (min_lat > GeoCoordinate.Longitude.Value)
                    {
                        min_lat = GeoCoordinate.Longitude.Value;
                    }

                    if (min_lng > GeoCoordinate.Latitude.Value)
                    {
                        min_lng = GeoCoordinate.Latitude.Value;
                    }

                    if (max_lat < GeoCoordinate.Longitude.Value)
                    {
                        max_lat = GeoCoordinate.Longitude.Value;
                    }

                    if (max_lng < GeoCoordinate.Latitude.Value)
                    {
                        max_lng = GeoCoordinate.Latitude.Value;
                    }
                }

                #endregion

                #region Unknown data found...

                else
                {
                    throw new Exception("Unknown data found!");
                }

                #endregion
            }


            //var Output1 = new StreamWriter("PolyfileReader/" + Filename.Name.Replace(".poly", ".data"));
            //var Array = new StringBuilder();

            //var Output2 = new StreamWriter("PolyfileReader/" + "ghjk".Replace(".poly", ".geo"));
            //var Language = new StringBuilder();

            //Shapes.ForEach((shape) =>
            //{
            //    Array.AppendLine(shape.Key.ToString());
            //    shape.Value.Item1.ForEach(c =>
            //    {
            //        Array.AppendLine("            { " + c.Latitude.ToString("00.000000").Replace(",", ".") + ", " + c.Longitude.ToString("00.000000").Replace(",", ".") + " },");
            //    });
            //});

            //Output1.WriteLine(Array.ToString());
            //Output1.Flush();
            //Output1.Close();


            var diff_lat = Math.Abs(min_lat - max_lat);
            var diff_lng = Math.Abs(min_lng - max_lng);

            //Output2.WriteLine("From:       " + max_lat.ToString("00.000000").Replace(",", ".")  + ", " +  min_lng.ToString("00.000000").Replace(",", "."));
            //Output2.WriteLine("To:         " + min_lat.ToString("00.000000").Replace(",", ".")  + ", " +  max_lng.ToString("00.000000").Replace(",", "."));
            //Output2.WriteLine("Diff:       " + diff_lat.ToString("00.000000").Replace(",", ".") + ", " + diff_lng.ToString("00.000000").Replace(",", "."));
            //Output2.WriteLine("Resolution: " + min_resolution + " -> " + max_resolution);

            Shapes.ForEach(shape => {
                for (var resolution = min_resolution; resolution <= max_resolution; resolution++)
                {
                    shape.Value.Item2.Add(resolution, new Tuple <List <ScreenXY>, StringBuilder>(new List <ScreenXY>(), new StringBuilder()));

                    shape.Value.Item1.ForEach(GeoCoord =>
                                              shape.Value.Item2[resolution].Item1.Add(GeoCalculations.GeoCoordinate2ScreenXY(GeoCoord, resolution))
                                              );
                }
            });

            var min_x = 0L;
            var min_y = 0L;

            for (var resolution = min_resolution; resolution <= max_resolution; resolution++)
            {
                min_x = Int64.MaxValue;
                min_y = Int64.MaxValue;

                Shapes.ForEach((shape) => {
                    shape.Value.Item2[resolution].Item1.ForEach(XY => {
                        if (XY.X < min_x)
                        {
                            min_x = XY.X;
                        }
                        if (XY.Y < min_y)
                        {
                            min_y = XY.Y;
                        }
                    });
                });

                Shapes.ForEach((shape) =>
                {
                    var Char = "M ";

                    shape.Value.Item2[resolution].Item1.ForEach(XY => {
                        shape.Value.Item2[resolution].Item2.Append(Char + (XY.X - min_x) + " " + (XY.Y - min_y) + " ");
                        if (Char == "L ")
                        {
                            Char = "";
                        }
                        if (Char == "M ")
                        {
                            Char = "L ";
                        }
                    });

                    shape.Value.Item2[resolution].Item2.Append("Z ");
                });
            }


            var ShapeLanguage = String.Empty;

            var ShapeDic = new Dictionary <UInt32, String>();

            for (var resolution = min_resolution; resolution <= max_resolution; resolution++)
            {
                ShapeLanguage = "\"";
                Shapes.ForEach((shape) => ShapeLanguage += shape.Value.Item2[resolution].Item2.ToString().Trim() + " ");
                ShapeDic.Add(resolution, ShapeLanguage.TrimEnd() + "\",");
            }

            return(new ShapeInfo(Description, max_lat, max_lng, min_lat, min_lng, ShapeDic));
        }
コード例 #10
0
        public GeoCoordinate Transform(Double Hochwert,
                                       Double Rechtswert,
                                       Double Hoehe,
                                       String Bezugsmeridian = "Automatische Ermittlung")

        {
            //  Based on: GK_in_WGS84.cs
            //  Copyright (c) 2008 by Ingo Peczynski
            //  http://www.sky-maps.de
            //  [email protected]

            // Compare to http://calc.gknavigation.de/


            #region Konstante Parameter

            // WGS84 Ellipsoid
            var WGS84_a  = 6378137.0;                                                               // große Halbachse
            var WGS84_b  = 6356752.3141;                                                            // kleine Halbachse
            var WGS84_e2 = (Math.Pow(WGS84_a, 2) - Math.Pow(WGS84_b, 2)) / Math.Pow(WGS84_a, 2);    // 1.Numerische Exzentrität
            var WGS84_f  = (WGS84_a - WGS84_b) / WGS84_a;                                           // Abplattung 1: fW

            // Bessel Ellipsoid
            var Bessel_a  = 6377397.155;
            var Bessel_b  = 6356078.962;
            var Bessel_e2 = (Bessel_a * Bessel_a - Bessel_b * Bessel_b) / (Bessel_a * Bessel_a);

            #endregion

            #region MeridianUmrechnung

            Int32 Meridianneu;

            if (Bezugsmeridian == "Automatische Ermittlung")
            {
                Meridianneu = 3 * Convert.ToInt32(Rechtswert.ToString().Substring(0, 1));
            }

            else
            {
                Meridianneu = Convert.ToInt32(Bezugsmeridian);
            }

            #endregion

            #region GK nach BL

            // Bessel Ellipsoid
            var n       = (Bessel_a - Bessel_b) / (Bessel_a + Bessel_b);
            var alpha   = (Bessel_a + Bessel_b) / 2.0 * (1.0 + 1.0 / 4.0 * n * n + 1.0 / 64.0 * Math.Pow(n, 4));
            var beta    = 3.0 / 2.0 * n - 27.0 / 32.0 * Math.Pow(n, 3) + 269.0 / 512.0 * Math.Pow(n, 5);
            var gamma   = 21.0 / 16.0 * n * n - 55.0 / 32.0 * Math.Pow(n, 4);
            var delta   = 151.0 / 96.0 * Math.Pow(n, 3) - 417.0 / 128.0 * Math.Pow(n, 5);
            var epsilon = 1097.0 / 512.0 * Math.Pow(n, 4);

            var y0 = Meridianneu / 3.0;
            var y  = Rechtswert - y0 * 1000000 - 500000;

            var B0 = Hochwert / alpha;
            var Bf = B0 + beta * Math.Sin(2 * B0) + gamma * Math.Sin(4 * B0) + delta * Math.Sin(6 * B0) + epsilon * Math.Sin(8 * B0);

            var Nf   = Bessel_a / Math.Sqrt(1.0 - Bessel_e2 * Math.Pow(Math.Sin(Bf), 2));
            var ETAf = Math.Sqrt((Bessel_a * Bessel_a) / (Bessel_b * Bessel_b) * Bessel_e2 * Math.Pow(Math.Cos(Bf), 2));
            var tf   = Math.Tan(Bf);

            var b1 = tf / 2.0 / (Nf * Nf) * (-1.0 - (ETAf * ETAf)) * (y * y);
            var b2 = tf / 24.0 / Math.Pow(Nf, 4) * (5.0 + 3.0 * (tf * tf) + 6.0 * (ETAf * ETAf) - 6.0 * (tf * tf) * (ETAf * ETAf) - 4.0 * Math.Pow(ETAf, 4) - 9.0 * (tf * tf) * Math.Pow(ETAf, 4)) * Math.Pow(y, 4);

            var g_B = (Bf + b1 + b2) * 180 / Math.PI;

            var l1 = 1.0 / Nf / Math.Cos(Bf) * y;
            var l2 = 1.0 / 6.0 / Math.Pow(Nf, 3) / Math.Cos(Bf) * (-1.0 - 2.0 * (tf * tf) - (ETAf * ETAf)) * Math.Pow(y, 3);

            var g_L = Meridianneu + (l1 + l2) * 180 / Math.PI;

            #endregion

            #region Ellipsoid Vektoren in DHDN

            // Querkrümmunsradius
            var N = Bessel_a / Math.Sqrt(1.0 - Bessel_e2 * Math.Pow(Math.Sin(g_B / 180 * Math.PI), 2));

            // Ergebnis Vektoren
            var Bessel_x = (N + Hoehe) * Math.Cos(g_B / 180 * Math.PI) * Math.Cos(g_L / 180 * Math.PI);
            var Bessel_y = (N + Hoehe) * Math.Cos(g_B / 180 * Math.PI) * Math.Sin(g_L / 180 * Math.PI);
            var Bessel_z = (N * (Bessel_b * Bessel_b) / (Bessel_a * Bessel_a) + Hoehe) * Math.Sin(g_B / 180 * Math.PI);

            #endregion

            #region Parameter HelmertTransformation

            Double g_dx;
            Double g_dy;
            Double g_dz;
            Double g_ex;
            Double g_ey;
            Double g_ez;
            Double g_m;

            // HelmertTransformation
            switch (HelmerttransformationsArt)
            {
            // Deutschland von WGS84 nach DNDH/Potsdamm2001
            default:
                g_dx = 598.1;           // Translation in X
                g_dy = 73.7;            // Translation in Y
                g_dz = 418.2;           // Translation in Z
                g_ex = -0.202;          // Drehwinkel in Bogensekunden un die x-Achse
                g_ey = -0.045;          // Drehwinkel in Bogensekunden un die y-Achse
                g_ez = 2.455;           // Drehwinkel in Bogensekunden un die z-Achse
                g_m  = 6.7;             // Maßstabsfaktor in ppm
                break;

            // Österreich von WGS84 nach MGI Ferro
            case HelmerttransformationsArt.OesterreichWGS84nachMGIFerro:
                g_dx = 577.326;         // Translation in X
                g_dy = 90.129;          // Translation in Y
                g_dz = 463.919;         // Translation in Z
                g_ex = -5.137;          // Drehwinkel in Bogensekunden un die x-Achse
                g_ey = -1.474;          // Drehwinkel in Bogensekunden un die y-Achse
                g_ez = -5.297;          // Drehwinkel in Bogensekunden un die z-Achse
                g_m  = 2.423;           // Maßstabsfaktor  in ppm
                break;
            }

            #endregion

            #region Helmert

            // Umrechnung der Drehwinkel in Bogenmaß
            var exRad = (g_ex * Math.PI / 180.0) / 3600.0;
            var eyRad = (g_ey * Math.PI / 180.0) / 3600.0;
            var ezRad = (g_ez * Math.PI / 180.0) / 3600.0;

            // Maßstabsumrechnung
            var mEXP = 1 - g_m * Math.Pow(10, -6);

            // Drehmatrix
            //   1       Ez    -Ez
            // -Ez        1     Ex
            //  Ey      -Ex      1

            // Rotierende Vektoren = Drehmatrix * Vektoren in WGS84
            var RotVektor1 = 1.0 * Bessel_x + ezRad * Bessel_y + (-1.0 * eyRad * Bessel_z);
            var RotVektor2 = (-1.0 * ezRad) * Bessel_x + 1 * Bessel_y + exRad * Bessel_z;
            var RotVektor3 = (eyRad) * Bessel_x + (-1.0 * exRad) * Bessel_y + 1 * Bessel_z;

            // Maßstab berücksichtigen
            var RotVectorM1 = RotVektor1 * mEXP;
            var RotVectorM2 = RotVektor2 * mEXP;
            var RotVectorM3 = RotVektor3 * mEXP;

            // Translation anbringen
            // dxT = Drehmatrix * dx * m
            var dxT = 1.0 * g_dx * mEXP + ezRad * g_dy * mEXP + (-1.0 * eyRad) * g_dz * mEXP;
            var dyT = (-1.0 * ezRad) * g_dx * mEXP + 1.0 * g_dy * mEXP + exRad * g_dz * mEXP;
            var dzT = (eyRad) * g_dx * mEXP + (-1.0 * exRad) * g_dy * mEXP + 1 * g_dz * mEXP;

            // Vektoren jetzt in WGS84
            var WGS84_x = RotVectorM1 + dxT;
            var WGS84_y = RotVectorM2 + dyT;
            var WGS84_z = RotVectorM3 + dzT;

            #endregion

            #region Vektorenumrechnung

            var s  = Math.Sqrt(WGS84_x * WGS84_x + WGS84_y * WGS84_y);
            var T  = Math.Atan(WGS84_z * WGS84_a / (s * WGS84_b));
            var Bz = Math.Atan((WGS84_z + WGS84_e2 * (WGS84_a * WGS84_a) / WGS84_b * Math.Pow(Math.Sin(T), 3)) / (s - WGS84_e2 * WGS84_a * Math.Pow(Math.Cos(T), 3)));

            var Lz = Math.Atan(WGS84_y / WGS84_x);
            var N2 = WGS84_a / Math.Sqrt(1 - WGS84_e2 * Math.Pow(Math.Sin(Bz), 2));

            #endregion

            return(new GeoCoordinate(Latitude.Parse(Bz * 180 / Math.PI),
                                     Longitude.Parse(Lz * 180 / Math.PI),
                                     Altitude.Parse(s / Math.Cos(Bz))));
        }