Mike Phares cd88e340a3 Format
Try when running synchronously
2024-05-19 22:30:33 -07:00

122 lines
4.6 KiB
C#

using MetadataExtractor;
using View_by_Distance.Metadata.Models.Stateless.Methods;
using View_by_Distance.Shared.Models;
namespace View_by_Distance.Metadata.Models.Stateless;
internal abstract class GPS
{
private static bool CoordinateValidatorValidate(double latitude, double longitude)
{
if (latitude is < (-90) or > 90)
return false;
if (longitude is < (-180) or > 180)
return false;
return true;
}
private static double GetRadius(IMetadata.DistanceUnit distanceUnit)
{
return distanceUnit switch
{
IMetadata.DistanceUnit.Kilometers => 6371.0, // EarthRadiusInKilometers;
IMetadata.DistanceUnit.Meters => 6371000.0, // EarthRadiusInMeters;
IMetadata.DistanceUnit.NauticalMiles => 3440.0, // EarthRadiusInNauticalMiles;
IMetadata.DistanceUnit.Miles => 3959.0, // EarthRadiusInMiles;
_ => throw new NotSupportedException()
};
}
private static double ToRadian(double d) =>
d * (Math.PI / 180);
private static double DiffRadian(double val1, double val2) =>
ToRadian(val2) - ToRadian(val1);
internal static double GetDistance(double originLatitude, double originLongitude, double destinationLatitude, double destinationLongitude, int decimalPlaces = 1, IMetadata.DistanceUnit distanceUnit = IMetadata.DistanceUnit.Miles)
{
if (!CoordinateValidatorValidate(originLatitude, originLongitude))
throw new ArgumentException("Invalid origin coordinates supplied.");
if (!CoordinateValidatorValidate(destinationLatitude, destinationLongitude))
throw new ArgumentException("Invalid destination coordinates supplied.");
double radius = GetRadius(distanceUnit);
return Math.Round(
radius * 2 *
Math.Asin(Math.Min(1,
Math.Sqrt(
Math.Pow(Math.Sin(DiffRadian(originLatitude, destinationLatitude) / 2.0), 2.0) +
(Math.Cos(ToRadian(originLatitude)) * Math.Cos(ToRadian(destinationLatitude)) *
Math.Pow(Math.Sin(DiffRadian(originLongitude, destinationLongitude) / 2.0),
2.0))))), decimalPlaces);
}
private static double ParseValueFromDmsString(string value)
{
double result;
if (string.IsNullOrEmpty(value))
return double.MinValue;
double secondsValue;
string[] degrees = value.Split('°');
if (degrees.Length != 2)
return double.MinValue;
if (!double.TryParse(degrees[0], out double degreesValue))
return double.MinValue;
string[] minutes = degrees[1].Split('\'');
if (minutes.Length != 2)
return double.MinValue;
if (!double.TryParse(minutes[0], out double minutesValue))
return double.MinValue;
string[] seconds = minutes[1].Split('"');
if (seconds.Length != 2)
secondsValue = 0;
else
{
if (!double.TryParse(seconds[0], out secondsValue))
return double.MinValue;
}
result = Math.Abs(degreesValue) + (minutesValue / 60) + (secondsValue / 3600);
if (degreesValue < 0)
result *= -1;
return result;
}
internal static GeoLocation? GeoLocation(GpsDirectory[]? gpsDirectories)
{
GeoLocation? result = null;
if (gpsDirectories is not null)
{
foreach (GpsDirectory gpsDirectory in gpsDirectories)
{
if (string.IsNullOrEmpty(gpsDirectory?.Latitude))
result = null;
else
{
string latitudeDMS = gpsDirectory.Latitude;
double latitude = ParseValueFromDmsString(latitudeDMS);
if (string.IsNullOrEmpty(gpsDirectory.Longitude))
result = null;
else
{
string longitudeDMS = gpsDirectory.Longitude;
double longitude = ParseValueFromDmsString(longitudeDMS);
result = new(latitude, longitude);
string dms = result.ToDmsString();
if ($"{latitudeDMS}, {longitudeDMS}" != dms)
result = null;
}
}
if (result is not null)
break;
}
}
return result;
}
}