/*
* Author: G. Monz (DK7IO), 2016-07-30
* This file is distributed without any warranty.
*
*/
using System;
using System.Collections.Generic;
namespace ScoutBase.Core
{
///
/// The position of a geographical coordinate in a rectangle.
///
public enum PositionInRectangle
{
///
/// TopLeft
///
TopLeft,
///
/// TopMiddle
///
TopMiddle,
///
/// TopRight
///
TopRight,
///
/// BottomLeft
///
BottomLeft,
///
/// BottomMiddle
///
BottomMiddle,
///
/// BottomRight
///
BottomRight,
///
/// MiddleLeft
///
MiddleLeft,
///
/// MiddleRight
///
MiddleRight,
///
/// MiddleMiddle
///
MiddleMiddle,
}
///
/// The options to format a degree value.
///
public enum AngleFormat
{
///
/// Sign, degrees (at least one integer digit).
///
sD,
///
/// Sign, degrees (at least two integer digits).
///
sDD,
///
/// Sign, degrees (at least one integer digit), minutes (at least one integer digit).
///
sDM,
///
/// Sign, degrees (at least two integer digits), minutes (two integer digits).
///
sDDMM,
///
/// Sign, degrees (at least one integer digit), minutes (at least one integer digit), seconds (at least one integer digit).
///
sDMS,
///
/// Sign, degrees (at least two integer digits), minutes (two integer digits), seconds (two integer digits).
///
sDDMMSS,
}
///
/// A representation of a geographical point.
///
[Serializable]
public class GeographicalPoint
{
#region Constants
#region Earth
///
/// Mean Earth radius in km, according WGS84.
///
public const double MeanEarthRadius_WGS84 = 6371.0008;
#endregion
#region Units
///
/// The length of a statute mile in kilometres.
///
public const double StatuteMilesToKilometres = 1.609344;
///
/// The length of a nautical mile in kilometres.
///
public const double NauticalMilesToKilometres = 1.852;
#endregion
#region Coordinate limits
///
/// Lower latitude limit.
///
public const int LowerLatitudeLimit = -90;
///
/// Upper latitude limit.
///
public const int UpperLatitudeLimit = +90;
///
/// Lower longitude limit.
///
public const int LowerLongitudeLimit = -180;
///
/// Upper longitude limit.
///
public const int UpperLongitudeLimit = +180;
#endregion
#endregion
#region Information texts
///
/// Information about an invalid value of the latitude.
///
internal static string InvalidLatitudeText = "Invalid value. " +
"Allowed interval: [-" + Math.Abs(LowerLatitudeLimit) + "...+" + Math.Abs(UpperLatitudeLimit) + "]";
///
/// Information about an invalid value of the longitude.
///
internal static string InvalidLongitudeText = "Invalid value. " +
"Allowed interval: [-" + Math.Abs(LowerLongitudeLimit) + "...+" + Math.Abs(UpperLongitudeLimit) + "]";
#endregion
double _latitude;
///
/// The geographical latitude, in degrees.
///
///
/// If the latitude exceeds its allowed interval
/// (can occur in setter only).
///
public double Latitude
{
get
{
return _latitude;
}
set
{
CheckLatitude(value);
_latitude = value;
}
}
double _longitude;
///
/// The geographical longitude, in degrees.
///
///
/// If the longitude exceeds its allowed interval
/// (can occur in setter only).
///
public double Longitude
{
get
{
return _longitude;
}
set
{
CheckLongitude(value);
_longitude = value;
}
}
///
/// The name of the instance.
///
public string Name
{
get;
set;
}
///
/// Creates a new instance.
/// Geographical latitude and longitude is 0.
///
public GeographicalPoint()
{
}
///
/// Creates a new instance, based on geographical coordinates.
///
/// The geographical latitude.
/// The geographical longitude.
/// If latitude or longitude exceeds its allowed interval.
public GeographicalPoint(double latitude, double longitude)
: this()
{
Latitude = latitude;
Longitude = longitude;
}
///
/// Creates a new instance, based on geographical coordinates in degrees and minutes.
/// There is no check on the numerical correctness of the arguments.
///
/// True if the sign of the latitude is negative. False if positive.
/// The degrees of the latitude.
/// The minutes of the latitude.
/// True if the sign of the longitude is negative. False if positive.
/// The degrees of the longitude.
/// The minutes of the longitude.
/// If the resulting latitude or longitude exceeds its allowed interval.
public GeographicalPoint(
bool latitudeIsNegative, int latitudeDegrees, double latitudeMinutes,
bool longitudeIsNegative, int longitudeDegrees, double longitudeMinutes
)
: this()
{
Latitude = Utilities.GetDegrees(latitudeIsNegative, latitudeDegrees, latitudeMinutes);
Longitude = Utilities.GetDegrees(longitudeIsNegative, longitudeDegrees, longitudeMinutes);
}
///
/// Creates a new instance, based on geographical coordinates in degrees, minutes and seconds.
/// There is no check on the numerical correctness of the arguments.
///
/// True if the sign of the latitude is negative. False if positive.
/// The degrees of the latitude.
/// The minutes of the latitude.
/// The seconds of the latitude.
/// True if the sign of the longitude is negative. False if positive.
/// The degrees of the longitude.
/// The minutes of the longitude.
/// The seconds of the longitude.
/// If the resulting latitude or longitude exceeds its allowed interval.
public GeographicalPoint(
bool latitudeIsNegative, int latitudeDegrees, int latitudeMinutes, double latitudeSeconds,
bool longitudeIsNegative, int longitudeDegrees, int longitudeMinutes, double longitudeSeconds
)
: this()
{
Latitude = Utilities.GetDegrees(latitudeIsNegative, latitudeDegrees, latitudeMinutes, latitudeSeconds);
Longitude = Utilities.GetDegrees(longitudeIsNegative, longitudeDegrees, longitudeMinutes, longitudeSeconds);
}
///
/// Creates a new instance, based on a 'Maidenhead Locator'.
///
/// The 'Maidenhead Locator'.
/// The position of the geographical coordinates in the locator.
///
/// If the length of the locator text is null or not an even number.
/// If the locator text contains invalid characters.
///
public GeographicalPoint(string maidenheadLocator, PositionInRectangle positionInRectangle)
: this()
{
double latitude;
double longitude;
MaidenheadLocator.LatLonFromLoc(maidenheadLocator, positionInRectangle, out latitude, out longitude);
Latitude = latitude;
Longitude = longitude;
}
///
/// Gives a precision sorted list of 'Maidenhead Locators', based on the geographical coordinates.
///
/// If true: generate small (if false: big) letters for 'Subsquares', 'Subsubsquare', etc.
/// The list of 'Maidenhead Locators'.
/// If the latitude or longitude exceeds its allowed interval.
public List GetMaidenheadLocators(bool smallLettersForSubsquares)
{
var result = new List(MaidenheadLocator.MaxPrecision);
{
for (int precision = MaidenheadLocator.MinPrecision; precision <= MaidenheadLocator.MaxPrecision; precision++)
{
string maidenheadLocator = GetMaidenheadLocator(smallLettersForSubsquares, precision);
result.Add(maidenheadLocator);
}
}
return result;
}
///
/// Converts the geographical coordinates to a 'Maidenhead Locator'.
///
/// If true: generate small (if false: big) letters for 'Subsquares', 'Subsubsquare', etc.
/// The precision for conversion, must be >=1 and <=10.
/// The 'Maidenhead Locator'.
/// If the latitude or longitude exceeds its allowed interval.
public string GetMaidenheadLocator(bool smallLettersForSubsquares, int precision)
{
string result = MaidenheadLocator.LocFromLatLon(Latitude, Longitude, smallLettersForSubsquares, precision);
return result;
}
///
/// Gives a text representation of the instance.
///
/// A member.
/// The number of decimal places (after decimal point) for the last unit.
/// The text between latitude and longitude.
/// If true: Use 7 Bit ASCII characters only instead of special characters.
/// The text representation.
public string ToString(
AngleFormat angleFormat, int decimalPlaces,
string separator, bool forceAsciiCharacters
)
{
string result =
GetFormattedText(Latitude, angleFormat, decimalPlaces, forceAsciiCharacters) + " N" +
separator +
GetFormattedText(Longitude, angleFormat, decimalPlaces, forceAsciiCharacters) + " E"
;
return result;
}
///
/// Shifts geographical coordinates within a rectangle.
///
/// The geographical latitude.
/// The geographical longitude.
/// The desired value.
/// The rectangle height.
/// The rectangle width.
internal static void ShiftPositionInRectangle(
ref double latitude, ref double longitude,
PositionInRectangle positionInRectangle,
double height, double width
)
{
switch (positionInRectangle)
{
case PositionInRectangle.TopLeft:
case PositionInRectangle.TopMiddle:
case PositionInRectangle.TopRight:
latitude += height;
break;
}
switch (positionInRectangle)
{
case PositionInRectangle.MiddleLeft:
case PositionInRectangle.MiddleMiddle:
case PositionInRectangle.MiddleRight:
latitude += height / 2;
break;
}
switch (positionInRectangle)
{
case PositionInRectangle.TopRight:
case PositionInRectangle.MiddleRight:
case PositionInRectangle.BottomRight:
longitude += width;
break;
}
switch (positionInRectangle)
{
case PositionInRectangle.TopMiddle:
case PositionInRectangle.MiddleMiddle:
case PositionInRectangle.BottomMiddle:
longitude += width / 2;
break;
}
}
///
/// Checks geographical coordinates.
///
/// The geographical latitude.
/// The geographical longitude.
/// If latitude or longitude exceeds its allowed interval.
public static bool Check(double latitude, double longitude)
{
return CheckLatitude(latitude) && CheckLongitude(longitude);
}
///
/// Checks a geographical latitude.
///
/// The geographical latitude.
/// If the latitude exceeds its allowed interval.
public static bool CheckLatitude(double latitude)
{
return (latitude >= LowerLatitudeLimit) && (latitude <= UpperLatitudeLimit);
}
///
/// Checks a geographical longitude.
///
/// The geographical longitude.
/// If the longitude exceeds its allowed interval.
public static bool CheckLongitude(double longitude)
{
return (longitude >= LowerLongitudeLimit) && (longitude <= UpperLongitudeLimit);
}
#region GetDistance
///
/// Calculates the distance to a 'Maidenhead Locator'.
///
/// The 'Maidenhead Locator'.
/// >The position of the geographical coordinates in the locator.
/// The distance in km.
///
/// If the length of the locator text is null or not an even number.
/// If the locator text contains invalid characters.
///
public double GetDistance(string maidenheadLocator, PositionInRectangle positionInRectangle)
{
GeographicalPoint geographicalPoint = new GeographicalPoint(maidenheadLocator, positionInRectangle);
double result = GetDistance(geographicalPoint);
return result;
}
///
/// Calculates the distance to another instance.
///
/// The instance.
/// The distance in km.
/// If the another instance is null.
public double GetDistance(GeographicalPoint geographicalPoint)
{
if (geographicalPoint == null)
{
throw new ArgumentNullException("geographicalPoint");
}
else
{
double result = GetDistance(geographicalPoint.Latitude, geographicalPoint.Longitude);
return result;
}
}
///
/// Calculates the distance to another geographical coordinate.
///
/// The latitude of the another geographical coordinate.
/// The longitude of the another geographical coordinate.
/// The distance in km.
public double GetDistance(double latitude, double longitude)
{
double result = GetDistance(
Latitude, Longitude,
latitude, longitude
);
return result;
}
///
/// Calculates the distance from a 'Maidenhead Locator' 1 to a 'Maidenhead Locator' 2.
///
/// The 'Maidenhead Locator' 1.
/// The position of the geographical coordinates in the locator 1.
/// The 'Maidenhead Locator' 2.
/// >The position of the geographical coordinates in the locator 2.
/// The distance in km.
///
/// If the length of any locator text is null or not an even number.
/// If any locator text contains invalid characters.
///
public static double GetDistance(
string maidenheadLocator1, PositionInRectangle positionInRectangle1,
string maidenheadLocator2, PositionInRectangle positionInRectangle2
)
{
var geographicalPoint1 = new GeographicalPoint(maidenheadLocator1, positionInRectangle1);
var geographicalPoint2 = new GeographicalPoint(maidenheadLocator2, positionInRectangle2);
double result = GetDistance(geographicalPoint1, geographicalPoint2);
return result;
}
///
/// Calculates the distance between two instances.
///
/// The 1.
/// The 2.
/// The distance in km.
/// If any of the instances is null.
public static double GetDistance(
GeographicalPoint geographicalPoint1,
GeographicalPoint geographicalPoint2
)
{
if (geographicalPoint1 == null)
{
throw new ArgumentNullException("geographicalPoint1");
}
else if (geographicalPoint2 == null)
{
throw new ArgumentNullException("geographicalPoint2");
}
else
{
double result = GetDistance(
geographicalPoint1.Latitude, geographicalPoint1.Longitude,
geographicalPoint2.Latitude, geographicalPoint2.Longitude
);
return result;
}
}
///
/// Calculates the distance between two geographical coordinates.
///
/// The latitude of coordinate 1.
/// The longitude of coordinate 1.
/// The latitude of coordinate 2.
/// The longitude of coordinate 2.
/// The distance in km.
public static double GetDistance(
double latitude1, double longitude1,
double latitude2, double longitude2
)
{
const double degreeToRadians = Math.PI / 180;
double latitude1Radians = latitude1 * degreeToRadians;
double longitude1Radians = longitude1 * degreeToRadians;
double latitude2Radians = latitude2 * degreeToRadians;
double longitude2Radians = longitude2 * degreeToRadians;
double cosD =
Math.Sin(latitude1Radians) * Math.Sin(latitude2Radians) +
Math.Cos(longitude1Radians - longitude2Radians) * Math.Cos(latitude1Radians) * Math.Cos(latitude2Radians)
;
double dUnitCircle;
{
//Limit for use of more precisely formula
const double limitArcMinutes = 10.0;
if (
Math.Abs(cosD) <
Math.Cos(limitArcMinutes / 60.0 * degreeToRadians)
)
{
//Common formula
dUnitCircle = Math.Acos(cosD);
}
else
{
//More precisely formula for angles near 0 or 180 degrees, respectively.
//Warning: Formula is valid for exactely these cases only!
dUnitCircle = Math.Sqrt(
Math.Pow(
(longitude2Radians - longitude1Radians) * Math.Cos((latitude1Radians + latitude2Radians) / 2),
2
) +
Math.Pow(
latitude2Radians - latitude1Radians,
2
)
);
}
}
double result = dUnitCircle * MeanEarthRadius_WGS84;
return result;
}
#endregion
#region GetAzimuth
///
/// Calculates the azimuth to a 'Maidenhead Locator'.
///
/// The 'Maidenhead Locator'.
/// >The position of the geographical coordinates in the locator.
/// The azimuth in degrees.
///
/// If the length of the locator text is null or not an even number.
/// If the locator text contains invalid characters.
///
public double GetAzimuth(string maidenheadLocator, PositionInRectangle positionInRectangle)
{
var geographicalPoint = new GeographicalPoint(maidenheadLocator, positionInRectangle);
double result = GetAzimuth(geographicalPoint);
return result;
}
///
/// Calculates the azimuth to another instance.
///
/// The instance.
/// The azimuth in degrees.
/// If the another instance is null.
public double GetAzimuth(GeographicalPoint geographicalPoint)
{
if (geographicalPoint == null)
{
throw new ArgumentNullException("geographicalPoint");
}
else
{
double result = GetAzimuth(geographicalPoint.Latitude, geographicalPoint.Longitude);
return result;
}
}
///
/// Calculates the azimuth to another geographical coordinate.
///
/// The latitude of the another geographical coordinate.
/// The longitude of the another geographical coordinate.
/// The azimuth in degrees.
public double GetAzimuth(double latitude, double longitude)
{
double result = GetAzimuth(
Latitude, Longitude,
latitude, longitude
);
return result;
}
///
/// Calculates the azimuth from a 'Maidenhead Locator' 1 to a 'Maidenhead Locator' 2.
///
/// The 'Maidenhead Locator' 1.
/// The position of the geographical coordinates in the locator 1.
/// The 'Maidenhead Locator' 2.
/// >The position of the geographical coordinates in the locator 2.
/// The azimuth in degrees.
///
/// If the length of any locator text is null or not an even number.
/// If any locator text contains invalid characters.
///
public static double GetAzimuth(
string maidenheadLocator1, PositionInRectangle positionInRectangle1,
string maidenheadLocator2, PositionInRectangle positionInRectangle2
)
{
var geographicalPoint1 = new GeographicalPoint(maidenheadLocator1, positionInRectangle1);
var geographicalPoint2 = new GeographicalPoint(maidenheadLocator2, positionInRectangle2);
double result = GetAzimuth(geographicalPoint1, geographicalPoint2);
return result;
}
///
/// Calculates the azimuth between two instances.
///
/// The 1.
/// The 2.
/// The azimuth in degrees.
/// If any of the instances is null.
public static double GetAzimuth(
GeographicalPoint geographicalPoint1,
GeographicalPoint geographicalPoint2
)
{
if (geographicalPoint1 == null)
{
throw new ArgumentNullException("geographicalPoint1");
}
else if (geographicalPoint2 == null)
{
throw new ArgumentNullException("geographicalPoint2");
}
else
{
double result = GetAzimuth(
geographicalPoint1.Latitude, geographicalPoint1.Longitude,
geographicalPoint2.Latitude, geographicalPoint2.Longitude
);
return result;
}
}
///
/// Calculates the azimuth from a geographical coordinate 1 to a geographical coordinate 2.
///
/// The latitude of coordinate 1.
/// The longitude of coordinate 1.
/// The latitude of coordinate 2.
/// The longitude of coordinate 2.
/// The azimuth in degrees.
public static double GetAzimuth(
double latitude1, double longitude1,
double latitude2, double longitude2
)
{
double result;
{
if (
(latitude1 == latitude2 && longitude1 == longitude2) ||
(latitude1 == UpperLatitudeLimit && latitude2 == UpperLatitudeLimit) ||
(latitude1 == LowerLatitudeLimit && latitude2 == LowerLatitudeLimit)
)
{
result = double.NaN;
}
else
{
const double degreeToRadians = Math.PI / 180;
double latitude1Radians = latitude1 * degreeToRadians;
double longitude1Radians = longitude1 * degreeToRadians;
double latitude2Radians = latitude2 * degreeToRadians;
double longitude2Radians = longitude2 * degreeToRadians;
double x =
Math.Cos(latitude1Radians) * Math.Sin(latitude2Radians) -
Math.Sin(latitude1Radians) * Math.Cos(latitude2Radians) * Math.Cos(longitude2Radians - longitude1Radians);
double y = Math.Cos(latitude2Radians) * Math.Sin(longitude2Radians - longitude1Radians);
double z = Math.Atan2(y, x);
if (z < 0)
{
z += 2 * Math.PI;
}
result = z / degreeToRadians;
}
}
return result;
}
#endregion
#region GetWaypointProjection
///
/// Gets a waypoint projection, based on a azimuth and a distance, respectively.
///
/// The azimuth in degrees [0...360).
/// The distance in km.
/// The waypoint projection as a instance.
/// If the azimuth exceeds its allowed interval.
public GeographicalPoint GetWaypointProjection(
double azimuth, double distance
)
{
var geographicalPoint = new GeographicalPoint(Latitude, Longitude);
var result = GetWaypointProjection(
geographicalPoint,
azimuth, distance
);
return result;
}
///
/// Gets a waypoint projection, based on a 'Maidenhead Locator',
/// a azimuth and a distance, respectively.
///
/// The 'Maidenhead Locator'.
/// The position of the geographical coordinates in the locator.
/// The azimuth in degrees [0...360).
/// The distance in km.
/// The waypoint projection as a instance.
///
/// If the length of the locator text is null or not an even number.
/// If the locator text contains invalid characters.
///
/// If the azimuth exceeds its allowed interval.
public static GeographicalPoint GetWaypointProjection(
string maidenheadLocator, PositionInRectangle positionInRectangle,
double azimuth, double distance
)
{
var geographicalPoint = new GeographicalPoint(maidenheadLocator, positionInRectangle);
var result = GetWaypointProjection(
geographicalPoint,
azimuth, distance
);
return result;
}
///
/// Gets a waypoint projection, based on a geographical coordinate,
/// a azimuth and a distance, respectively.
///
/// The latitude of the geographical coordinate.
/// The longitude of the geographical coordinate.
/// The azimuth in degrees [0...360).
/// The distance in km.
/// The waypoint projection as a instance.
/// If the azimuth exceeds its allowed interval.
public static GeographicalPoint GetWaypointProjection(
double latitude, double longitude,
double azimuth, double distance
)
{
var geographicalPoint = new GeographicalPoint(latitude, longitude);
var result = GetWaypointProjection(
geographicalPoint,
azimuth, distance
);
return result;
}
///
/// Gets a waypoint projection, based on a instance,
/// a azimuth and a distance, respectively.
///
/// The instance.
/// The azimuth in degrees [0...360).
/// The distance in km.
/// The waypoint projection as a instance.
/// If the instance is null.
/// If the azimuth exceeds its allowed interval.
public static GeographicalPoint GetWaypointProjection(
GeographicalPoint geographicalPoint,
double azimuth, double distance
)
{
if (geographicalPoint == null)
{
throw new ArgumentNullException("geographicalPoint");
}
else if (azimuth < 0 || azimuth >= 360)
{
throw new ArgumentException("Allowed interval: [0...360)", "azimuth");
}
else
{
const double degreeToRadians = Math.PI / 180;
double latitude1 = geographicalPoint.Latitude;
double longitude1 = geographicalPoint.Longitude;
double c = distance / MeanEarthRadius_WGS84;
double a = Math.Acos(
Math.Sin(latitude1 * degreeToRadians) * Math.Cos(c) +
Math.Cos(latitude1 * degreeToRadians) * Math.Sin(c) * Math.Cos(azimuth * degreeToRadians)
);
double gamma = Math.Acos(
(Math.Cos(c) - Math.Cos(a) * Math.Sin(latitude1 * degreeToRadians)) /
(Math.Sin(a) * Math.Cos(latitude1 * degreeToRadians))
);
double latitude2 = Math.PI / 2 - a;
double longitude2 = longitude1 * degreeToRadians;
if (!double.IsNaN(gamma))
{
if (azimuth * degreeToRadians < Math.PI)
{
longitude2 += gamma;
}
else if (azimuth * degreeToRadians > Math.PI)
{
longitude2 -= gamma;
}
}
var result = new GeographicalPoint(
latitude2 / degreeToRadians,
longitude2 / degreeToRadians);
return result;
}
}
#endregion
///
/// Retrieves the symbol for a mathematical sign.
///
/// True if the sign is negative. False if positive.
/// The symbol.
public static string GetSignSymbol(bool isNegative)
{
string result = isNegative ? "-" : "+";
return result;
}
///
/// Retrieves a formatted text for a degree value
/// according to a given angle format.
///
/// The degree value (with decimal places).
/// A member.
/// The number of decimal places (after decimal point) for the last unit.
/// If true: Use 7 Bit ASCII characters only instead of special characters.
/// The formatted text.
public static string GetFormattedText(double decDegrees, AngleFormat angleFormat, int decimalPlaces, bool forceAsciiCharacters)
{
string degreeSymbol, minuteSymbol, secondsSymbol;
if (forceAsciiCharacters)
{
degreeSymbol = "d";
minuteSymbol = "'";
secondsSymbol = "\"";
}
else
{
degreeSymbol = "\x00B0".ToString(); //DEGREE SIGN
minuteSymbol = "\x2032".ToString(); //PRIME
secondsSymbol = "\x2033".ToString(); //DOUBLE PRIME
}
string separator = " ";
string result;
switch (angleFormat)
{
case AngleFormat.sD:
{
bool isNegative;
double degrees;
Utilities.DegreesToD(decDegrees, out isNegative, out degrees);
result =
GetSignSymbol(isNegative) +
string.Format(Utilities.GetFormatString(1, decimalPlaces), degrees) + degreeSymbol
;
}
break;
case AngleFormat.sDD:
{
bool isNegative;
double degrees;
Utilities.DegreesToD(decDegrees, out isNegative, out degrees);
result =
GetSignSymbol(isNegative) +
string.Format(Utilities.GetFormatString(2, decimalPlaces), degrees) + degreeSymbol
;
}
break;
case AngleFormat.sDM:
{
bool isNegative;
int degrees;
double minutes;
Utilities.DegreesToDM(decDegrees, out isNegative, out degrees, out minutes);
Utilities.Round(decimalPlaces, ref degrees, ref minutes);
result =
GetSignSymbol(isNegative) +
string.Format(Utilities.GetFormatString(1, 0), degrees) + degreeSymbol + separator +
string.Format(Utilities.GetFormatString(1, decimalPlaces), minutes) + minuteSymbol
;
}
break;
case AngleFormat.sDDMM:
{
bool isNegative;
int degrees;
double minutes;
Utilities.DegreesToDM(decDegrees, out isNegative, out degrees, out minutes);
Utilities.Round(decimalPlaces, ref degrees, ref minutes);
result =
GetSignSymbol(isNegative) +
string.Format(Utilities.GetFormatString(2, 0), degrees) + degreeSymbol + separator +
string.Format(Utilities.GetFormatString(2, decimalPlaces), minutes) + minuteSymbol
;
}
break;
case AngleFormat.sDMS:
{
bool isNegative;
int degrees;
int minutes;
double seconds;
Utilities.DegreesToDMS(decDegrees, out isNegative, out degrees, out minutes, out seconds);
Utilities.Round(decimalPlaces, ref degrees, ref minutes, ref seconds);
result =
GetSignSymbol(isNegative) +
string.Format(Utilities.GetFormatString(1, 0), degrees) + degreeSymbol + separator +
string.Format(Utilities.GetFormatString(1, 0), minutes) + minuteSymbol + separator +
string.Format(Utilities.GetFormatString(1, decimalPlaces), seconds) + secondsSymbol
;
}
break;
case AngleFormat.sDDMMSS:
{
bool isNegative;
int degrees;
int minutes;
double seconds;
Utilities.DegreesToDMS(decDegrees, out isNegative, out degrees, out minutes, out seconds);
Utilities.Round(decimalPlaces, ref degrees, ref minutes, ref seconds);
result =
GetSignSymbol(isNegative) +
string.Format(Utilities.GetFormatString(2, 0), degrees) + degreeSymbol + separator +
string.Format(Utilities.GetFormatString(2, 0), minutes) + minuteSymbol + separator +
string.Format(Utilities.GetFormatString(2, decimalPlaces), seconds) + secondsSymbol
;
}
break;
default:
throw new NotSupportedException(angleFormat.ToString());
}
return result;
}
///
/// Checks if two given locations (by GeographicalPoint) are equal
///
/// The 1st location.
/// The 2nd location.
/// True if the given locations are equal .
public static bool IsEqual(GeographicalPoint point1, GeographicalPoint point2)
{
return IsEqual(point1.Latitude, point1.Longitude, point2.Latitude, point2.Longitude);
}
///
/// Checks if two given locations (by lat/lon) are equal
///
/// The geographic latitude of 1st location.
/// The geographic longitude of 1st location.
/// The geographic latitude of 2nd location.
/// The geographic longitude of 2nd location.
/// True if the given locations are equal .
public static bool IsEqual(double latitude1, double longitude1, double latitude2, double longitude2)
{
if ((latitude1 == double.NaN) || (longitude1 == double.NaN) || (latitude2 == double.NaN) || (longitude2 == double.NaN))
return false;
return (Math.Abs(latitude1 - latitude2) < 0.00001) && (Math.Abs(longitude1 - longitude2) < 0.00001);
}
///
/// Gives a new List instance for a single instance.
///
/// The instance.
/// The new List instance.
public static IEnumerable GetNewList(GeographicalPoint geographicalPoint)
{
var result = new List();
if (geographicalPoint != null)
{
result.Add(geographicalPoint);
}
return result;
}
}
}