예제 #1
0
 /// <summary>
 ///     Create a new earth-centered, earth-fixed (ECEF) reference from the given parameters and
 ///     the given reference ellipsoid.
 /// </summary>
 /// <param name="x"> The x co-ordinate. </param>
 /// <param name="y"> The y co-ordinate. </param>
 /// <param name="z"> The z co-ordinate. </param>
 /// <param name="datum"> The datum. </param>
 public ECEFRef(double x, double y, double z, Datum.Datum datum)
     : base(datum)
 {
     X = x;
     Y = y;
     Z = z;
 }
예제 #2
0
        /// <summary>
        /// Create a new UTM reference object. Checks are made to make sure that the
        /// given parameters are roughly valid, but the checks are not exhaustive with
        /// regards to the easting value. Catching a NotDefinedOnUTMGridException does
        /// not necessarily mean that the UTM reference is well-formed. This is because
        /// that valid values for the easting vary depending on the latitude.
        /// </summary>
        /// <param name="lngZone">The longitude zone number.</param>
        /// <param name="latZone">The latitude zone character.</param>
        /// <param name="easting">The easting in metres.</param>
        /// <param name="northing">The northing in metres.</param>
        /// <param name="datum">The datum of the UTM reference</param>
        /// <exception cref="NotDefinedOnUtmGridException">
        /// If any of the parameters are invalid. Be careful that a valid
        /// value for the easting does not necessarily mean that the UTM
        /// reference is well-formed. The current checks do not take into
        /// account the varying range of valid values for the easting for
        /// different latitudes.</exception>
        public UTMRef(int lngZone, char latZone, double easting, double northing,
                      Datum.Datum datum) : base(datum)
        {
            if (lngZone < 1 || lngZone > 60)
            {
                throw new NotDefinedOnUtmGridException("Longitude zone (" + lngZone
                                                       + ") is not defined on the UTM grid.");
            }

            if (latZone < 'C' || latZone > 'X')
            {
                throw new NotDefinedOnUtmGridException("Latitude zone (" + latZone
                                                       + ") is not defined on the UTM grid.");
            }

            if (easting < 0.0 || easting > 1000000.0)
            {
                throw new NotDefinedOnUtmGridException("Easting (" + easting
                                                       + ") is not defined on the UTM grid.");
            }

            if (northing < 0.0 || northing > 10000000.0)
            {
                throw new NotDefinedOnUtmGridException("Northing (" + northing
                                                       + ") is not defined on the UTM grid.");
            }

            Easting  = easting;
            Northing = northing;
            LatZone  = latZone;
            LngZone  = lngZone;
        }
예제 #3
0
        /// <summary>
        /// Create a new LatLng object to represent a latitude/longitude pair using the
        /// specified datum.
        /// </summary>
        /// <param name="latitudeDegrees">The degrees part of the latitude. Must be 0 &lt;= latitudeDegrees &lt;=
        /// 90.0.</param>
        /// <param name="latitudeMinutes">The minutes part of the latitude. Must be 0 &lt;= latitudeMinutes &lt;
        /// 60.0.</param>
        /// <param name="latitudeSeconds">The seconds part of the latitude. Must be 0 &lt;= latitudeSeconds &lt;
        /// 60.0.</param>
        /// <param name="northSouth">Whether the latitude is north or south of the equator.</param>
        /// <param name="longitudeDegrees">The degrees part of the longitude. Must be 0 &lt;= longitudeDegrees &lt;=
        /// 180.0.</param>
        /// <param name="longitudeMinutes">The minutes part of the longitude. Must be 0 &lt;= longitudeMinutes &lt;
        /// 60.0.</param>
        /// <param name="longitudeSeconds">The seconds part of the longitude. Must be 0 &lt;= longitudeSeconds &lt;
        /// 60.0.</param>
        /// <param name="eastWest">Whether the longitude is east or west of the prime meridian.</param>
        /// <param name="height">The perpendicular height above the reference ellipsoid.</param>
        /// <param name="datum">The datum that this reference is based on.</param>
        /// <exception cref="ArgumentException">if any of the parameters are invalid.</exception>
        public LatLng(int latitudeDegrees, int latitudeMinutes,
                      double latitudeSeconds, NorthSouth northSouth, int longitudeDegrees,
                      int longitudeMinutes, double longitudeSeconds, EastWest eastWest,
                      double height, Datum.Datum datum)
        {
            if (latitudeDegrees < 0.0 || latitudeDegrees > 90.0 ||
                latitudeMinutes < 0.0 || latitudeMinutes >= 60.0 ||
                latitudeSeconds < 0.0 || latitudeSeconds >= 60.0)
            {
                throw new ArgumentException("Invalid latitude");
            }

            if (longitudeDegrees < 0.0 || longitudeDegrees > 180.0 ||
                longitudeMinutes < 0.0 || longitudeMinutes >= 60.0 ||
                longitudeSeconds < 0.0 || longitudeSeconds >= 60.0)
            {
                throw new ArgumentException("Invalid longitude");
            }

            Latitude = (int)northSouth
                       * (latitudeDegrees + (latitudeMinutes / 60.0) + (latitudeSeconds / 3600.0));
            Longitude = (int)eastWest
                        * (longitudeDegrees + (longitudeMinutes / 60.0) + (longitudeSeconds / 3600.0));
            Height = height;
            Datum  = datum;
        }
예제 #4
0
 /// <summary>
 ///     Create a new earth-centered, earth-fixed (ECEF) reference from the given parameters and
 ///     the given reference ellipsoid.
 /// </summary>
 /// <param name="x"> The x co-ordinate. </param>
 /// <param name="y"> The y co-ordinate. </param>
 /// <param name="z"> The z co-ordinate. </param>
 /// <param name="datum"> The datum. </param>
 public ECEFRef(double x, double y, double z, Datum.Datum datum)
     : base(datum)
 {
     X = x;
     Y = y;
     Z = z;
 }
예제 #5
0
        private void InternalToDatum(Datum.Datum d, bool toWgs)
        {
            double a        = Datum.ReferenceEllipsoid.SemiMajorAxis;
            double eSquared = Datum.ReferenceEllipsoid.EccentricitySquared;
            double phi      = Util.ToRadians(Latitude);
            double lambda   = Util.ToRadians(Longitude);
            double v        = a / (Math.Sqrt(1 - eSquared * Util.SinSquared(phi)));
            double h        = Height; // height
            double x        = (v + h) * Math.Cos(phi) * Math.Cos(lambda);
            double y        = (v + h) * Math.Cos(phi) * Math.Sin(lambda);
            double z        = ((1 - eSquared) * v + h) * Math.Sin(phi);

            double invert = -1;

            Datum.Datum referenceDatum = d;
            if (toWgs)
            {
                invert         = 1;
                referenceDatum = Datum;
            }

            double dx = invert * referenceDatum.DX;
            double dy = invert * referenceDatum.DY;
            double dz = invert * referenceDatum.DZ;
            double ds = invert * referenceDatum.DS / 1000000.0;
            double rx = invert * Util.ToRadians(referenceDatum.RX / 3600.0);
            double ry = invert * Util.ToRadians(referenceDatum.RY / 3600.0);
            double rz = invert * Util.ToRadians(referenceDatum.RZ / 3600.0);

            double sc = 1 + ds;
            double xB = dx + (x * sc) + ((-rx * y) * sc) + ((ry * z) * sc);
            double yB = dy + ((rz * x) * sc) + (y * sc) + ((-rx * z) * sc);
            double zB = dz + ((-ry * x) * sc) + ((rx * y) * sc) + (z * sc);

            a        = d.ReferenceEllipsoid.SemiMajorAxis;
            eSquared = d.ReferenceEllipsoid.EccentricitySquared;

            double lambdaB = Util.ToDegrees(Math.Atan(yB / xB));
            double p       = Math.Sqrt((xB * xB) + (yB * yB));
            double phiN    = Math.Atan(zB / (p * (1 - eSquared)));

            for (int i = 1; i < 10; i++)
            {
                v = a / (Math.Sqrt(1 - eSquared * Util.SinSquared(phiN)));
                double phiN1 = Math.Atan((zB + (eSquared * v * Math.Sin(phiN))) / p);
                phiN = phiN1;
            }

            double phiB = Util.ToDegrees(phiN);

            Latitude  = phiB;
            Longitude = lambdaB;

            Datum = d;
        }
예제 #6
0
        private void InternalToDatum(Datum.Datum d, bool toWgs)
        {
            var a        = _datum.ReferenceEllipsoid.SemiMajorAxis;
            var eSquared = _datum.ReferenceEllipsoid.EccentricitySquared;
            var phi      = Util.ToRadians(Latitude);
            var lambda   = Util.ToRadians(Longitude);
            var v        = a / Math.Sqrt(1 - eSquared * Util.sinSquared(phi));
            var H        = Height; // height
            var x        = (v + H) * Math.Cos(phi) * Math.Cos(lambda);
            var y        = (v + H) * Math.Cos(phi) * Math.Sin(lambda);
            var z        = ((1 - eSquared) * v + H) * Math.Sin(phi);

            double invert         = -1;
            var    referenceDatum = d;

            if (toWgs)
            {
                invert         = 1;
                referenceDatum = _datum;
            }

            var dx = invert * referenceDatum.DX;
            var dy = invert * referenceDatum.DY;
            var dz = invert * referenceDatum.DZ;
            var ds = invert * referenceDatum.DS / 1000000.0;
            var rx = invert * Util.ToRadians(referenceDatum.RX / 3600.0);
            var ry = invert * Util.ToRadians(referenceDatum.RY / 3600.0);
            var rz = invert * Util.ToRadians(referenceDatum.RZ / 3600.0);

            var sc = 1 + ds;
            var xB = dx + x * sc + -rx * y * sc + ry * z * sc;
            var yB = dy + rz * x * sc + y * sc + -rx * z * sc;
            var zB = dz + -ry * x * sc + rx * y * sc + z * sc;

            a        = d.ReferenceEllipsoid.SemiMajorAxis;
            eSquared = d.ReferenceEllipsoid.EccentricitySquared;

            var lambdaB = Util.ToDegrees(Math.Atan(yB / xB));
            var p       = Math.Sqrt(xB * xB + yB * yB);
            var phiN    = Math.Atan(zB / (p * (1 - eSquared)));

            for (var i = 1; i < 10; i++)
            {
                v = a / Math.Sqrt(1 - eSquared * Util.sinSquared(phiN));
                var phiN1 = Math.Atan((zB + eSquared * v * Math.Sin(phiN)) / p);
                phiN = phiN1;
            }

            var phiB = Util.ToDegrees(phiN);

            Latitude  = phiB;
            Longitude = lambdaB;

            _datum = d;
        }
예제 #7
0
        /// <summary>
        /// Converts this LatLng to another datum.
        /// </summary>
        /// <param name="d">The datum.</param>
        public void ToDatum(Datum.Datum d)
        {
            // first convert to WGS84 if needed
            if (!(Datum is WGS84Datum))
            {
                InternalToDatum(WGS84Datum.Instance, true);
            }

            if (d is WGS84Datum)
            {
                // Don't do anything if datum and d are both WGS84.
                return;
            }

            InternalToDatum(d, false);
        }
예제 #8
0
        /// <summary>
        /// Create a new LatLng object to represent a latitude/longitude pair using the
        /// specified datum.
        /// </summary>
        /// <param name="latitude">The latitude in degrees. Must be between -90.0 and 90.0 inclusive.
        /// -90.0 and 90.0 are effectively equivalent.</param>
        /// <param name="longitude">The longitude in degrees. Must be between -180.0 and 180.0
        /// inclusive. -180.0 and 180.0 are effectively equivalent.</param>
        /// <param name="height">The perpendicular height above the reference ellipsoid.</param>
        /// <param name="datum">The datum that this reference is based on.</param>
        /// <exception cref="ArgumentException">If either the given latitude or the given longitude are invalid.</exception>
        public LatLng(double latitude, double longitude, double height, Datum.Datum datum)
        {
            if (!IsValidLatitude(latitude))
            {
                throw new ArgumentException("Latitude (" + latitude
                                            + ") is invalid. Must be between -90.0 and 90.0 inclusive.");
            }

            if (!IsValidLongitude(longitude))
            {
                throw new ArgumentException("Longitude (" + longitude
                                            + ") is invalid. Must be between -180.0 and 180.0 inclusive.");
            }

            Latitude  = latitude;
            Longitude = longitude;
            Height    = height;
            Datum     = datum;
        }
예제 #9
0
        /// <summary>
        /// Convert this LatLng from the OSGB36 datum to the WGS84 datum using an
        /// approximate Helmert transformation.
        /// </summary>   
        public void ToWGS84()
        {
            double a = Airy1830Ellipsoid.Instance.SemiMajorAxis;
              double eSquared = Airy1830Ellipsoid.Instance.EccentricitySquared;
              double phi = Util.ToRadians(latitude);
              double lambda = Util.ToRadians(longitude);
              double v = a / (Math.Sqrt(1 - eSquared * Util.sinSquared(phi)));
              double H = 0; // height
              double x = (v + H) * Math.Cos(phi) * Math.Cos(lambda);
              double y = (v + H) * Math.Cos(phi) * Math.Sin(lambda);
              double z = ((1 - eSquared) * v + H) * Math.Sin(phi);

              double tx = 446.448;
              // ty : Incorrect value in v1.0 (-124.157). Corrected in v1.1.
              double ty = -125.157;
              double tz = 542.060;
              double s = -0.0000204894;
              double rx = Util.ToRadians(0.00004172222);
              double ry = Util.ToRadians(0.00006861111);
              double rz = Util.ToRadians(0.00023391666);

              double xB = tx + (x * (1 + s)) + (-rx * y) + (ry * z);
              double yB = ty + (rz * x) + (y * (1 + s)) + (-rx * z);
              double zB = tz + (-ry * x) + (rx * y) + (z * (1 + s));

              a = WGS84Ellipsoid.Instance.SemiMajorAxis;
              eSquared = WGS84Ellipsoid.Instance.EccentricitySquared;

              double lambdaB = Util.ToDegrees(Math.Atan(yB / xB));
              double p = Math.Sqrt((xB * xB) + (yB * yB));
              double phiN = Math.Atan(zB / (p * (1 - eSquared)));
              for (int i = 1; i < 10; i++) {
            v = a / (Math.Sqrt(1 - eSquared * Util.sinSquared(phiN)));
            double phiN1 = Math.Atan((zB + (eSquared * v * Math.Sin(phiN))) / p);
            phiN = phiN1;
              }

              double phiB = Util.ToDegrees(phiN);

              latitude = phiB;
              longitude = lambdaB;

              datum = WGS84Datum.Instance;
        }
예제 #10
0
        /// <summary>
        /// Create a new LatLng object to represent a latitude/longitude pair using the
        /// specified datum.
        /// </summary>
        /// <param name="latitude">The latitude in degrees. Must be between -90.0 and 90.0 inclusive.
        /// -90.0 and 90.0 are effectively equivalent.</param>
        /// <param name="longitude">The longitude in degrees. Must be between -180.0 and 180.0
        /// inclusive. -180.0 and 180.0 are effectively equivalent.</param>
        /// <param name="height">The perpendicular height above the reference ellipsoid.</param>
        /// <param name="datum">The datum that this reference is based on.</param>
        /// <exception cref="ArgumentException">If either the given latitude or the given longitude are invalid.</exception>
        public LatLng(double latitude, double longitude, double height, DotNetCoords.Datum.Datum datum)
        {
            if (!IsValidLatitude(latitude))
              {
            throw new ArgumentException("Latitude (" + latitude
            + ") is invalid. Must be between -90.0 and 90.0 inclusive.");
              }

              if (!IsValidLongitude(longitude))
              {
            throw new ArgumentException("Longitude (" + longitude
            + ") is invalid. Must be between -180.0 and 180.0 inclusive.");
              }

              this.latitude = latitude;
              this.longitude = longitude;
              this.height = height;
              this.datum = datum;
        }
예제 #11
0
        /// <summary>
        /// Create a new LatLng object to represent a latitude/longitude pair using the
        /// specified datum.
        /// </summary>
        /// <param name="latitudeDegrees">The degrees part of the latitude. Must be 0 &lt;= latitudeDegrees &lt;=
        /// 90.0.</param>
        /// <param name="latitudeMinutes">The minutes part of the latitude. Must be 0 &lt;= latitudeMinutes &lt;
        /// 60.0.</param>
        /// <param name="latitudeSeconds">The seconds part of the latitude. Must be 0 &lt;= latitudeSeconds &lt;
        /// 60.0.</param>
        /// <param name="northSouth">Whether the latitude is north or south of the equator.</param>
        /// <param name="longitudeDegrees">The degrees part of the longitude. Must be 0 &lt;= longitudeDegrees &lt;=
        /// 180.0.</param>
        /// <param name="longitudeMinutes">The minutes part of the longitude. Must be 0 &lt;= longitudeMinutes &lt;
        /// 60.0.</param>
        /// <param name="longitudeSeconds">The seconds part of the longitude. Must be 0 &lt;= longitudeSeconds &lt;
        /// 60.0.</param>
        /// <param name="eastWest">Whether the longitude is east or west of the prime meridian.</param>
        /// <param name="height">The perpendicular height above the reference ellipsoid.</param>
        /// <param name="datum">The datum that this reference is based on.</param>
        /// <exception cref="ArgumentException">if any of the parameters are invalid.</exception>
        public LatLng(int latitudeDegrees, int latitudeMinutes,
            double latitudeSeconds, NorthSouth northSouth, int longitudeDegrees,
            int longitudeMinutes, double longitudeSeconds, EastWest eastWest,
            double height, DotNetCoords.Datum.Datum datum)
        {
            if (latitudeDegrees < 0.0 || latitudeDegrees > 90.0
              || latitudeMinutes < 0.0 || latitudeMinutes >= 60.0
              || latitudeSeconds < 0.0 || latitudeSeconds >= 60.0)
              {
            throw new ArgumentException("Invalid latitude");
              }

              if (longitudeDegrees < 0.0 || longitudeDegrees > 180.0
              || longitudeMinutes < 0.0 || longitudeMinutes >= 60.0
              || longitudeSeconds < 0.0 || longitudeSeconds >= 60.0)
              {
            throw new ArgumentException("Invalid longitude");
              }

              this.latitude = (int)northSouth
              * (latitudeDegrees + (latitudeMinutes / 60.0) + (latitudeSeconds / 3600.0));
              this.longitude = (int)eastWest
              * (longitudeDegrees + (longitudeMinutes / 60.0) + (longitudeSeconds / 3600.0));
              this.height = height;
              this.datum = datum;
        }
예제 #12
0
        /// <summary>
        ///     Create a new UTM reference object. Checks are made to make sure that the given
        ///     parameters are roughly valid, but the checks are not exhaustive with regards to the
        ///     easting value. Catching a NotDefinedOnUTMGridException does not necessarily mean that
        ///     the UTM reference is well-formed. This is because that valid values for the easting vary
        ///     depending on the latitude.
        /// </summary>
        /// <param name="lngZone"> The longitude zone number. </param>
        /// <param name="latZone"> The latitude zone character. </param>
        /// <param name="easting"> The easting in meters. </param>
        /// <param name="northing"> The northing in meters. </param>
        /// <param name="datum"> The datum of the UTM reference </param>
        /// <exception cref="NotDefinedOnUtmGridException">
        ///     If any of the parameters are invalid. Be careful that a valid value for the easting does
        ///     not necessarily mean that the UTM reference is well-formed. The current checks do not
        ///     take into account the varying range of valid values for the easting for different latitudes.
        /// </exception>
        public UtmRef(int lngZone, char latZone, double easting, double northing,
            Datum.Datum datum)
            : base(datum)
        {
            latZone = char.ToUpper(latZone);

            if (lngZone < 1 || lngZone > 60)
            {
                throw new NotDefinedOnUtmGridException("Longitude zone (" + lngZone
                                                       + ") is not defined on the UTM grid.");
            }

            if (latZone < 'C' || latZone > 'X')
            {
                throw new NotDefinedOnUtmGridException("Latitude zone (" + latZone
                                                       + ") is not defined on the UTM grid.");
            }

            if (easting < 0.0 || easting > 1000000.0)
            {
                throw new NotDefinedOnUtmGridException("Easting (" + easting
                                                       + ") is not defined on the UTM grid.");
            }

            if (northing < 0.0 || northing > 10000000.0)
            {
                throw new NotDefinedOnUtmGridException("Northing (" + northing
                                                       + ") is not defined on the UTM grid.");
            }

            Easting = easting;
            Northing = northing;
            LatZone = latZone;
            LngZone = lngZone;
        }
예제 #13
0
        /// <summary>
        ///     Take a string and make it a LatLng
        /// </summary>
        /// <param name="toConvert"></param>
        /// <exception cref="ArgumentException"></exception>
        public LatLng(string toConvert)
        {
            if (RxLatLngDecimal.IsMatch(toConvert))
            {
                double lat, lng;
                var    latLngMatch = RxLatLngDecimal.Match(toConvert);
                var    strLat      = latLngMatch.Groups["lat"].Value;
                var    strLng      = latLngMatch.Groups["lng"].Value;

                if (double.TryParse(strLat, out lat) && double.TryParse(strLng, out lng))
                {
                    Latitude  = lat;
                    Longitude = lng;
                    Height    = 0;
                }
            }

            if (RxLatLngDms.IsMatch(toConvert))
            {
                var latLngDMSMatch = RxLatLngDms.Match(toConvert);

                int    latDeg, latMin, lngDeg, lngMin;
                double latSec, lngSec;
                char   latDir, lngDir;

                var strLatDeg = latLngDMSMatch.Groups["latDeg"].Value;
                var strLngDeg = latLngDMSMatch.Groups["lngDeg"].Value;

                var strLatMin = latLngDMSMatch.Groups["latMin"].Value;
                var strLngMin = latLngDMSMatch.Groups["lngMin"].Value;

                var strLatSec = latLngDMSMatch.Groups["latSec"].Value;
                var strLngSec = latLngDMSMatch.Groups["lngSec"].Value;

                var strLatDir = latLngDMSMatch.Groups["latDir"].Value;
                var strLngDir = latLngDMSMatch.Groups["lngDir"].Value;

                if (int.TryParse(strLatDeg, out latDeg) && int.TryParse(strLngDeg, out lngDeg) &&
                    int.TryParse(strLatMin, out latMin) && int.TryParse(strLngMin, out lngMin) &&
                    double.TryParse(strLatSec, out latSec) && double.TryParse(strLngSec, out lngSec)
                    )
                {
                    char.TryParse(strLatDir, out latDir);
                    char.TryParse(strLngDir, out lngDir);

                    latDir = char.ToUpper(latDir);
                    lngDir = char.ToUpper(lngDir);

                    var northSouth = NorthSouth.North;
                    var eastWest   = EastWest.East;

                    // deal with the negative numbers
                    if (latDir == 'S')
                    {
                        northSouth = NorthSouth.South;
                    }

                    if (lngDir == 'W')
                    {
                        eastWest = EastWest.West;
                    }

                    if (lngDeg < 0)

                    {
                        lngDeg   = Math.Abs(lngDeg);
                        eastWest = EastWest.West;
                    }

                    if (latDeg < 0)
                    {
                        latDeg     = Math.Abs(latDeg);
                        northSouth = NorthSouth.South;
                    }

                    var lat = latDeg + latMin / 60.0 + latSec / 3600.0;

                    var lng = lngDeg + lngMin / 60.0 + lngSec / 3600.0;
                    Latitude  = (int)northSouth * lat;
                    Longitude = (int)eastWest * lng;

                    Height = 0;
                    _datum = WGS84Datum.Instance;
                }
            }
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="CoordinateSystem"/> class.
 /// </summary>
 /// <param name="datum">The datum.</param>
 protected CoordinateSystem(DotNetCoords.Datum.Datum datum)
 {
     this.datum = datum;
 }
예제 #15
0
 /// <summary>
 /// Initializes a new instance of the <see cref="CoordinateSystem"/> class.
 /// </summary>
 /// <param name="datum">The datum.</param>
 protected CoordinateSystem(DotNetCoords.Datum.Datum datum)
 {
     this.datum = datum;
 }