/// <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, DotNetCoords.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."); } this.easting = easting; this.northing = northing; this.latZone = latZone; this.lngZone = lngZone; }
/// <summary> /// Create a new earth-centred, 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, DotNetCoords.Datum.Datum datum) : base(datum) { X = x; Y = y; Z = z; }
/// <summary> /// Converts this LatLng to another datum. /// </summary> /// <param name="d">The datum.</param> public void ToDatum(DotNetCoords.Datum.Datum d) { double invert = 1; if (!(datum is WGS84Datum) && !(d is WGS84Datum)) { ToDatum(WGS84Datum.Instance); } else { if (d is WGS84Datum) { // Don't do anything if datum and d are both WGS84. return; } invert = -1; } 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 dx = invert * d.DX;// 446.448; double dy = invert * d.DY;// -125.157; double dz = invert * d.DZ;// 542.060; double ds = invert * d.DS / 1000000.0;// -0.0000204894; double rx = invert * Util.ToRadians(d.RX / 3600.0); double ry = invert * Util.ToRadians(d.RY / 3600.0); double rz = invert * Util.ToRadians(d.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; }
/// <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; }
/// <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 <= latitudeDegrees <= /// 90.0.</param> /// <param name="latitudeMinutes">The minutes part of the latitude. Must be 0 <= latitudeMinutes < /// 60.0.</param> /// <param name="latitudeSeconds">The seconds part of the latitude. Must be 0 <= latitudeSeconds < /// 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 <= longitudeDegrees <= /// 180.0.</param> /// <param name="longitudeMinutes">The minutes part of the longitude. Must be 0 <= longitudeMinutes < /// 60.0.</param> /// <param name="longitudeSeconds">The seconds part of the longitude. Must be 0 <= longitudeSeconds < /// 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; }
/// <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; }