Add netcore

This commit is contained in:
Philip Schell 2019-12-09 14:46:34 +01:00
parent 2b0fbff159
commit 3843109a62
23 changed files with 6884 additions and 8333 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,7 @@
using System;
using System.Collections.Generic;
namespace CoordinateSharp
{
namespace CoordinateSharp {
//CURRENT ALTITUDE IS SET CONSTANT AT 100M. POSSIBLY NEED TO ADJUST TO ALLOW USER PASS.
//Altitude adjustments appear to have minimal effect on eclipse timing. These were mainly used
//to signify eclipses that had already started during rise and set times on the NASA calculator
@ -15,80 +14,51 @@ namespace CoordinateSharp
//This can be modified if need to allow users to pass custom number with the Coordinate SetDatum() functions.
//CURRENT RANGE 1601-2600.
internal class LunarEclipseCalc
{
public static List<List<string>> CalculateLunarEclipse(DateTime d, double latRad, double longRad)
{
return Calculate(d, latRad, longRad);
}
public static List<LunarEclipseDetails> CalculateLunarEclipse(DateTime d, double latRad, double longRad, double[] events)
{
List<List<string>> evs = Calculate(d, latRad, longRad, events);
internal class LunarEclipseCalc {
public static List<List<String>> CalculateLunarEclipse(DateTime d, Double latRad, Double longRad) => Calculate(d, latRad, longRad);
public static List<LunarEclipseDetails> CalculateLunarEclipse(DateTime d, Double latRad, Double longRad, Double[] events) {
List<List<String>> evs = Calculate(d, latRad, longRad, events);
List<LunarEclipseDetails> deetsList = new List<LunarEclipseDetails>();
foreach (List<string> ls in evs)
{
foreach (List<String> ls in evs) {
LunarEclipseDetails deets = new LunarEclipseDetails(ls);
deetsList.Add(deets);
}
return deetsList;
}
public static List<List<string>> CalculateLunarEclipse(DateTime d, Coordinate coord)
{
return Calculate(d, coord.Latitude.ToRadians(), coord.Longitude.ToRadians());
}
public static List<List<String>> CalculateLunarEclipse(DateTime d, Coordinate coord) => Calculate(d, coord.Latitude.ToRadians(), coord.Longitude.ToRadians());
// CALCULATE!
private static List<List<string>> Calculate(DateTime d, double latRad, double longRad, double[] ev = null)
{
private static List<List<String>> Calculate(DateTime d, Double latRad, Double longRad, Double[] ev = null) {
//DECLARE ARRAYS
double[] obsvconst = new double[6];
double[] mid = new double[41];
double[] p1 = new double[41];
double[] u1 = new double[41];
double[] u2 = new double[41];
double[] u3 = new double[41];
double[] u4 = new double[41];
double[] p4 = new double[41];
Double[] obsvconst = new Double[6];
Double[] mid = new Double[41];
Double[] p1 = new Double[41];
Double[] u1 = new Double[41];
Double[] u2 = new Double[41];
Double[] u3 = new Double[41];
Double[] u4 = new Double[41];
Double[] p4 = new Double[41];
List<List<string>> events = new List<List<string>>();
double[] el;
if (ev == null)
{
el = Eclipse.LunarData.LunarDateData(d);//Get 100 year solar data;
}
else
{
el = ev;
}
events = new List<List<string>>();
Double[] el = ev ?? Eclipse.LunarData.LunarDateData(d);
List<List<String>> events = new List<List<String>>();
ReadData(latRad, longRad, obsvconst);
for (int i = 0; i < el.Length; i += 22)
{
if (el[5 + i] <= obsvconst[5])
{
List<string> values = new List<string>();
for (Int32 i = 0; i < el.Length; i += 22) {
if (el[5 + i] <= obsvconst[5]) {
List<String> values = new List<String>();
obsvconst[4] = i;
GetAll(el, obsvconst, mid, p1, u1, u2,u3,u4,p4);
GetAll(el, obsvconst, mid, p1, u1, u2, u3, u4, p4);
// Is there an event...
if (mid[5] != 1)
{
if (mid[5] != 1) {
values.Add(GetDate(el, p1, obsvconst));
if (el[5 + i] == 1)
{
if (el[5 + i] == 1) {
values.Add("T");
}
else if (el[5 + i] == 2)
{
} else if (el[5 + i] == 2) {
values.Add("P");
}
else
{
} else {
values.Add("N");
}
@ -104,26 +74,20 @@ namespace CoordinateSharp
// P1 alt
values.Add(GetAlt(p1));
if (u1[5] == 1)
{
if (u1[5] == 1) {
values.Add("-");
values.Add("-");
}
else
{
} else {
// U1
values.Add(GetTime(el, u1, obsvconst));
// U1 alt
values.Add(GetAlt(u1));
}
if (u2[5] == 1)
{
if (u2[5] == 1) {
values.Add("-");
values.Add("-");
}
else
{
} else {
// U2
values.Add(GetTime(el, u2, obsvconst));
@ -138,26 +102,20 @@ namespace CoordinateSharp
values.Add(GetAlt(mid));
if (u3[5] == 1)
{
if (u3[5] == 1) {
values.Add("-");
values.Add("-");
}
else
{
} else {
// u3
values.Add(GetTime(el, u3, obsvconst));
// u3 alt
values.Add(GetAlt(u3));
}
if (u4[5] == 1)
{
if (u4[5] == 1) {
values.Add("-");
values.Add("-");
}
else
{
} else {
// u4
values.Add(GetTime(el, u4, obsvconst));
@ -177,8 +135,7 @@ namespace CoordinateSharp
return events;
}
// Read the data that's in the form, and populate the obsvconst array
private static void ReadData(double latRad, double longRad, double[] obsvconst)
{
private static void ReadData(Double latRad, Double longRad, Double[] obsvconst) {
// Get the latitude
obsvconst[0] = latRad;
@ -199,53 +156,44 @@ namespace CoordinateSharp
}
// Populate the p1, u1, u2, mid, u3, u4 and p4 arrays
private static void GetAll(double[] elements, double[] obsvconst, double[] mid, double[] p1, double[] u1, double[] u2, double[] u3, double[] u4, double[] p4)
{
int index = (int)obsvconst[4];
private static void GetAll(Double[] elements, Double[] obsvconst, Double[] mid, Double[] p1, Double[] u1, Double[] u2, Double[] u3, Double[] u4, Double[] p4) {
Int32 index = (Int32)obsvconst[4];
p1[1] = elements[index + 9];
PopulateCircumstances(elements, p1, obsvconst);
mid[1] = elements[index + 12];
PopulateCircumstances(elements, mid, obsvconst);
p4[1] = elements[index + 15];
PopulateCircumstances(elements, p4, obsvconst);
if (elements[index + 5] < 3)
{
if (elements[index + 5] < 3) {
u1[1] = elements[index + 10];
PopulateCircumstances(elements, u1, obsvconst);
u4[1] = elements[index + 14];
PopulateCircumstances(elements, u4, obsvconst);
if (elements[index + 5] < 2)
{
if (elements[index + 5] < 2) {
u2[1] = elements[index + 11];
u3[1] = elements[index + 13];
PopulateCircumstances(elements, u2, obsvconst);
PopulateCircumstances(elements, u3, obsvconst);
}
else
{
} else {
u2[5] = 1;
u3[5] = 1;
}
}
else
{
} else {
u1[5] = 1;
u2[5] = 1;
u3[5] = 1;
u4[5] = 1;
}
if ((p1[5] != 0) && (u1[5] != 0) && (u2[5] != 0) && (mid[5] != 0) && (u3[5] != 0) && (u4[5] != 0) && (p4[5] != 0))
{
if (p1[5] != 0 && u1[5] != 0 && u2[5] != 0 && mid[5] != 0 && u3[5] != 0 && u4[5] != 0 && p4[5] != 0) {
mid[5] = 1;
}
}
// Populate the circumstances array
// entry condition - circumstances[1] must contain the correct value
private static void PopulateCircumstances(double[] elements, double[] circumstances, double[] obsvconst)
{
double t, ra, dec, h;
private static void PopulateCircumstances(Double[] elements, Double[] circumstances, Double[] obsvconst) {
Double t, ra, dec, h;
int index = (int)obsvconst[4];
Int32 index = (Int32)obsvconst[4];
t = circumstances[1];
ra = elements[18 + index] * t + elements[17 + index];
ra = ra * t + elements[16 + index];
@ -258,47 +206,35 @@ namespace CoordinateSharp
circumstances[2] = h;
circumstances[4] = Math.Asin(Math.Sin(obsvconst[0]) * Math.Sin(dec) + Math.Cos(obsvconst[0]) * Math.Cos(dec) * Math.Cos(h));
circumstances[4] -= Math.Asin(Math.Sin(elements[7 + index] * Math.PI / 180.0) * Math.Cos(circumstances[4]));
if (circumstances[4] * 180.0 / Math.PI < elements[8 + index] - 0.5667)
{
if (circumstances[4] * 180.0 / Math.PI < elements[8 + index] - 0.5667) {
circumstances[5] = 2;
}
else if (circumstances[4] < 0.0)
{
} else if (circumstances[4] < 0.0) {
circumstances[4] = 0.0;
circumstances[5] = 0;
}
else
{
} else {
circumstances[5] = 0;
}
}
// Get the date of an event
private static string GetDate(double[] elements, double[] circumstances, double[] obsvconst)
{
string[] month = new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };//Month string array
double t, jd, a, b, c, d, e;
string ans = "";
int index = (int)obsvconst[4];
private static String GetDate(Double[] elements, Double[] circumstances, Double[] obsvconst) {
String[] month = new String[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };//Month string array
Double t, jd, a, b, c, d, e;
Int32 index = (Int32)obsvconst[4];
// Calculate the JD for noon (TDT) the day before the day that contains T0
jd = Math.Floor(elements[index] - (elements[1 + index] / 24.0));
jd = Math.Floor(elements[index] - elements[1 + index] / 24.0);
// Calculate the local time (ie the offset in hours since midnight TDT on the day containing T0).
t = circumstances[1] + elements[1 + index] - obsvconst[3] - (elements[2 + index] - 30.0) / 3600.0;
if (t < 0.0)
{
if (t < 0.0) {
jd--;
}
if (t >= 24.0)
{
if (t >= 24.0) {
jd++;
}
if (jd >= 2299160.0)
{
if (jd >= 2299160.0) {
a = Math.Floor((jd - 1867216.25) / 36524.25);
a = jd + 1 + a - Math.Floor(a / 4.0);
}
else
{
} else {
a = jd;
}
b = a + 1525.0;
@ -306,104 +242,77 @@ namespace CoordinateSharp
d = Math.Floor(365.25 * c);
e = Math.Floor((b - d) / 30.6001);
d = b - d - Math.Floor(30.6001 * e);
if (e < 13.5)
{
e = e - 1;
}
else
{
e = e - 13;
}
double year;
if (e > 2.5)
{
e = e < 13.5 ? e - 1 : e - 13;
Double year;
String ans;
if (e > 2.5) {
ans = c - 4716 + "-";
year = c - 4716;
}
else
{
} else {
ans = c - 4715 + "-";
year = c - 4715;
}
string m = month[(int)e - 1];
ans += m+ "-";
if (d < 10)
{
ans = ans + "0";
String m = month[(Int32)e - 1];
ans += m + "-";
if (d < 10) {
ans += "0";
}
ans = ans + d;
ans += d;
//Leap Year Integrity Check
if (m == "Feb" && d == 29 && !DateTime.IsLeapYear((int)year))
{
if (m == "Feb" && d == 29 && !DateTime.IsLeapYear((Int32)year)) {
ans = year.ToString() + "-Mar-01";
}
return ans;
}
// Get the time of an event
private static string GetTime(double[] elements, double[] circumstances, double[] obsvconst)
{
double t;
string ans = "";
private static String GetTime(Double[] elements, Double[] circumstances, Double[] obsvconst) {
Double t;
String ans = "";
int index = (int)obsvconst[4];
Int32 index = (Int32)obsvconst[4];
t = circumstances[1] + elements[1 + index] - obsvconst[3] - (elements[2 + index] - 30.0) / 3600.0;
if (t < 0.0)
{
t = t + 24.0;
if (t < 0.0) {
t += 24.0;
}
if (t >= 24.0)
{
t = t - 24.0;
if (t >= 24.0) {
t -= 24.0;
}
if (t < 10.0)
{
ans = ans + "0";
if (t < 10.0) {
ans += "0";
}
ans = ans + Math.Floor(t) + ":";
t = (t * 60.0) - 60.0 * Math.Floor(t);
if (t < 10.0)
{
ans = ans + "0";
t = t * 60.0 - 60.0 * Math.Floor(t);
if (t < 10.0) {
ans += "0";
}
ans = ans + Math.Floor(t);
if (circumstances[5] == 2)
{
ans += Math.Floor(t);
if (circumstances[5] == 2) {
return ans; //RETURNED IN ITAL DETERMINE WHY
}
else
{
} else {
return ans;
}
}
// Get the altitude
private static string GetAlt(double[] circumstances)
{
double t;
string ans = "";
private static String GetAlt(Double[] circumstances) {
Double t;
t = circumstances[4] * 180.0 / Math.PI;
t = Math.Floor(t + 0.5);
if (t < 0.0)
{
String ans;
if (t < 0.0) {
ans = "-";
t = -t;
}
else
{
} else {
ans = "+";
}
if (t < 10.0)
{
ans = ans + "0";
if (t < 10.0) {
ans += "0";
}
ans = ans + t;
if (circumstances[5] == 2)
{
ans += t;
if (circumstances[5] == 2) {
return ans; //returned in italics determine why
}
else
{
} else {
return ans;
}
}

View File

@ -1,14 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CoordinateSharp
{
internal partial class MeeusTables
{
namespace CoordinateSharp {
internal partial class MeeusTables {
//Ch 47
private static double[] Table47A_Arguments = new double[]
private static readonly Double[] Table47A_Arguments = new Double[]
{
0,0,1,0,
2,0,-1,0,
@ -72,7 +67,7 @@ namespace CoordinateSharp
2,0,3,0,
2,0,-1,-2
};
private static double[] Table47B_Arguments = new double[]
private static readonly Double[] Table47B_Arguments = new Double[]
{
0,0,0,1,
0,0,1,1,
@ -136,7 +131,7 @@ namespace CoordinateSharp
4,-1,0,-1,
2,-2,0,1,
};
private static double[] Table47A_El_Er = new double[]
private static readonly Double[] Table47A_El_Er = new Double[]
{
//El
6288774, 1274027,658314,213618,-185116,-114332,58793,57066,53322,45758,
@ -151,7 +146,7 @@ namespace CoordinateSharp
2616,-1897,-2117,2354,0,0,-1423,-1117,-1571,-1739,0,-4421,0,0,0,0,1165,0,0,8752
};
private static double[] Table47B_Eb = new double[]
private static readonly Double[] Table47B_Eb = new Double[]
{
5128122,280602,277693,173237,55413,46271,32573,17198,9266,8822,
8216,4324,4200,-3359,2463,2211,2065,-1870,1828,-1794,-1749,-1565,-1491,
@ -160,62 +155,48 @@ namespace CoordinateSharp
777,671,607,596,491,-451,439,422,421,-366,-351,331,315,302,-283,-229,
223,223,-220,-220,-185,181,-177,176,166,-164,132,-119,115,107
};
private static double Get_Table47A_Values(double[] values, int l, double t, bool sine)
{
private static Double Get_Table47A_Values(Double[] values, Int32 l, Double t, Boolean sine) {
//sine true returns El
//sine false return Er
//Er values start at 60 in the Table47A_El_Er array.
int nl = l * 4;
Int32 nl = l * 4;
if (sine)
{
double e = 1;
if (sine) {
Double e = 1;
if (Table47A_Arguments[nl + 1] != 0)
{
if (Table47A_Arguments[nl + 1] != 0) {
e = 1 - .002516 * t - .0000074 * Math.Pow(t, 2);
if (Math.Abs(Table47A_Arguments[nl + 1]) == 2)
{
if (Math.Abs(Table47A_Arguments[nl + 1]) == 2) {
e *= e;
}
}
return (Table47A_El_Er[l] * e) * Math.Sin(Table47A_Arguments[nl] * values[0] + Table47A_Arguments[nl + 1] * values[1] +
Table47A_Arguments[nl + 2] * values[2] + Table47A_Arguments[nl + 3] * values[3]);
}
else
{
double e = 1;
if (Table47A_Arguments[nl + 1] != 0)
{
return Table47A_El_Er[l] * e * Math.Sin(Table47A_Arguments[nl] * values[0] + Table47A_Arguments[nl + 1] * values[1] + Table47A_Arguments[nl + 2] * values[2] + Table47A_Arguments[nl + 3] * values[3]);
} else {
Double e = 1;
if (Table47A_Arguments[nl + 1] != 0) {
e = 1 - .002516 * t - .0000074 * Math.Pow(t, 2);
if (Math.Abs(Table47A_Arguments[nl + 1]) == 2)
{
if (Math.Abs(Table47A_Arguments[nl + 1]) == 2) {
e *= e;
}
}
return (Table47A_El_Er[l + 60] * e) * Math.Cos(Table47A_Arguments[nl] * values[0] + Table47A_Arguments[nl + 1] * values[1] +
Table47A_Arguments[nl + 2] * values[2] + Table47A_Arguments[nl + 3] * values[3]);
return Table47A_El_Er[l + 60] * e * Math.Cos(Table47A_Arguments[nl] * values[0] + Table47A_Arguments[nl + 1] * values[1] + Table47A_Arguments[nl + 2] * values[2] + Table47A_Arguments[nl + 3] * values[3]);
}
}
private static double Get_Table47B_Values(double[] values, int l, double t)
{
int nl = l * 4;
double e = 1;
private static Double Get_Table47B_Values(Double[] values, Int32 l, Double t) {
Int32 nl = l * 4;
Double e = 1;
if (Table47B_Arguments[nl + 1] != 0)
{
if (Table47B_Arguments[nl + 1] != 0) {
e = 1 - .002516 * t - .0000074 * Math.Pow(t, 2);
if (Math.Abs(Table47B_Arguments[nl + 1]) == 2)
{
if (Math.Abs(Table47B_Arguments[nl + 1]) == 2) {
e *= e;
}
}
return (Table47B_Eb[l] * e) * Math.Sin(Table47B_Arguments[nl] * values[0] + Table47B_Arguments[nl + 1] * values[1] +
Table47B_Arguments[nl + 2] * values[2] + Table47B_Arguments[nl + 3] * values[3]);
return Table47B_Eb[l] * e * Math.Sin(Table47B_Arguments[nl] * values[0] + Table47B_Arguments[nl + 1] * values[1] + Table47B_Arguments[nl + 2] * values[2] + Table47B_Arguments[nl + 3] * values[3]);
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +1,17 @@
using System;
using System.Collections.Generic;
namespace CoordinateSharp
{
internal class SunCalc
{
public static void CalculateSunTime(double lat, double longi, DateTime date, Celestial c,double offset = 0)
{
namespace CoordinateSharp {
internal class SunCalc {
public static void CalculateSunTime(Double lat, Double longi, DateTime date, Celestial c, Double _ = 0) {
if (date.Year == 0001) { return; } //Return if date vaue hasn't been established.
DateTime actualDate = new DateTime(date.Year,date.Month,date.Day,0, 0, 0, DateTimeKind.Utc);
DateTime actualDate = new DateTime(date.Year, date.Month, date.Day, 0, 0, 0, DateTimeKind.Utc);
////Sun Time Calculations
//Get Julian
double lw = rad * -longi;
double phi = rad * lat;
Double lw = rad * -longi;
Double phi = rad * lat;
//Rise Set
DateTime?[] evDate = Get_Event_Time(lw, phi, -.8333, actualDate);
@ -24,28 +22,16 @@ namespace CoordinateSharp
//Azimuth and Altitude
CalculateSunAngle(date, longi, lat, c);
// neither sunrise nor sunset
if ((!c.SunRise.HasValue) && (!c.SunSet.HasValue))
{
if (c.SunAltitude < 0)
{
c.sunCondition = CelestialStatus.DownAllDay;
}
else
{
c.sunCondition = CelestialStatus.UpAllDay;
}
if (!c.SunRise.HasValue && !c.SunSet.HasValue) {
c.sunCondition = c.SunAltitude < 0 ? CelestialStatus.DownAllDay : CelestialStatus.UpAllDay;
}
// sunrise or sunset
else
{
if (!c.SunRise.HasValue)
{
else {
if (!c.SunRise.HasValue) {
// No sunrise this date
c.sunCondition = CelestialStatus.NoRise;
}
else if (!c.SunSet.HasValue)
{
} else if (!c.SunSet.HasValue) {
// No sunset this date
c.sunCondition = CelestialStatus.NoSet;
}
@ -86,34 +72,32 @@ namespace CoordinateSharp
/// <param name="h">Angle in Degrees</param>
/// <param name="date">Date of Event</param>
/// <returns>DateTime?[]{rise, set}</returns>
private static DateTime?[] Get_Event_Time(double lw, double phi, double h,DateTime date)
{
private static DateTime?[] Get_Event_Time(Double lw, Double phi, Double h, DateTime date) {
//Create arrays. Index 0 = Day -1, 1 = Day, 2 = Day + 1;
//These will be used to find exact day event occurs for comparison
DateTime?[] sets = new DateTime?[] { null, null, null, null, null };
DateTime?[] rises = new DateTime?[] { null, null, null,null, null };
DateTime?[] rises = new DateTime?[] { null, null, null, null, null };
//Iterate starting with day -1;
for (int x = 0; x < 5; x++)
{
double d = JulianConversions.GetJulian(date.AddDays(x-2)) - j2000 + .5; //LESS PRECISE JULIAN NEEDED
for (Int32 x = 0; x < 5; x++) {
Double d = JulianConversions.GetJulian(date.AddDays(x - 2)) - j2000 + .5; //LESS PRECISE JULIAN NEEDED
double n = julianCycle(d, lw);
double ds = approxTransit(0, lw, n);
Double n = JulianCycle(d, lw);
Double ds = ApproxTransit(0, lw, n);
double M = solarMeanAnomaly(ds);
double L = eclipticLongitude(M);
Double M = SolarMeanAnomaly(ds);
Double L = EclipticLongitude(M);
double dec = declination(L, 0);
Double dec = Declination(L, 0);
double Jnoon = solarTransitJ(ds, M, L);
Double Jnoon = SolarTransitJ(ds, M, L);
double Jset;
double Jrise;
Double Jset;
Double Jrise;
DateTime? solarNoon = JulianConversions.GetDate_FromJulian(Jnoon);
DateTime? nadir = JulianConversions.GetDate_FromJulian(Jnoon - 0.5);
//DateTime? solarNoon = JulianConversions.GetDate_FromJulian(Jnoon);
//DateTime? nadir = JulianConversions.GetDate_FromJulian(Jnoon - 0.5);
//Rise Set
Jset = GetTime(h * rad, lw, phi, dec, n, M, L);
@ -128,24 +112,18 @@ namespace CoordinateSharp
//Compare and send
DateTime? tRise = null;
for(int x=0;x<5;x++)
{
if(rises[x].HasValue)
{
if(rises[x].Value.Day == date.Day)
{
for (Int32 x = 0; x < 5; x++) {
if (rises[x].HasValue) {
if (rises[x].Value.Day == date.Day) {
tRise = rises[x];
break;
}
}
}
DateTime? tSet = null;
for (int x = 0; x < 5; x++)
{
if (sets[x].HasValue)
{
if (sets[x].Value.Day == date.Day)
{
for (Int32 x = 0; x < 5; x++) {
if (sets[x].HasValue) {
if (sets[x].Value.Day == date.Day) {
tSet = sets[x];
break;
}
@ -154,8 +132,7 @@ namespace CoordinateSharp
return new DateTime?[] { tRise, tSet };
}
public static void CalculateZodiacSign(DateTime date, Celestial c)
{
public static void CalculateZodiacSign(DateTime date, Celestial c) {
//Aquarius (January 20 to February 18)
//Pisces (February 19 to March 20)
//Aries (March 21-April 19)
@ -168,202 +145,169 @@ namespace CoordinateSharp
//Scorpio (October 23-November 21)
//Sagittarius (November 22-December 21)
//Capricorn (December 22-January 19)
if (date >= new DateTime(date.Year, 1, 1) && date <= new DateTime(date.Year, 1, 19, 23, 59, 59))
{
if (date >= new DateTime(date.Year, 1, 1) && date <= new DateTime(date.Year, 1, 19, 23, 59, 59)) {
c.AstrologicalSigns.ZodiacSign = "Capricorn";
return;
}
if (date >= new DateTime(date.Year, 1, 20) && date <= new DateTime(date.Year, 2, 18, 23, 59, 59))
{
if (date >= new DateTime(date.Year, 1, 20) && date <= new DateTime(date.Year, 2, 18, 23, 59, 59)) {
c.AstrologicalSigns.ZodiacSign = "Aquarius";
return;
}
if (date >= new DateTime(date.Year, 2, 19) && date <= new DateTime(date.Year, 3, 20, 23, 59, 59))
{
if (date >= new DateTime(date.Year, 2, 19) && date <= new DateTime(date.Year, 3, 20, 23, 59, 59)) {
c.AstrologicalSigns.ZodiacSign = "Pisces";
return;
}
if (date >= new DateTime(date.Year, 3, 21) && date <= new DateTime(date.Year, 4, 19, 23, 59, 59))
{
if (date >= new DateTime(date.Year, 3, 21) && date <= new DateTime(date.Year, 4, 19, 23, 59, 59)) {
c.AstrologicalSigns.ZodiacSign = "Aries";
return;
}
if (date >= new DateTime(date.Year, 4, 20) && date <= new DateTime(date.Year, 5, 20, 23, 59, 59))
{
if (date >= new DateTime(date.Year, 4, 20) && date <= new DateTime(date.Year, 5, 20, 23, 59, 59)) {
c.AstrologicalSigns.ZodiacSign = "Taurus";
return;
}
if (date >= new DateTime(date.Year, 5, 21) && date <= new DateTime(date.Year, 6, 20,23,59,59))
{
if (date >= new DateTime(date.Year, 5, 21) && date <= new DateTime(date.Year, 6, 20, 23, 59, 59)) {
c.AstrologicalSigns.ZodiacSign = "Gemini";
return;
}
if (date >= new DateTime(date.Year, 6, 21) && date <= new DateTime(date.Year, 7, 22, 23, 59, 59))
{
if (date >= new DateTime(date.Year, 6, 21) && date <= new DateTime(date.Year, 7, 22, 23, 59, 59)) {
c.AstrologicalSigns.ZodiacSign = "Cancer";
return;
}
if (date >= new DateTime(date.Year, 7, 23) && date <= new DateTime(date.Year, 8, 22, 23, 59, 59))
{
if (date >= new DateTime(date.Year, 7, 23) && date <= new DateTime(date.Year, 8, 22, 23, 59, 59)) {
c.AstrologicalSigns.ZodiacSign = "Leo";
return;
}
if (date >= new DateTime(date.Year, 8, 23) && date <= new DateTime(date.Year, 9, 22, 23, 59, 59))
{
if (date >= new DateTime(date.Year, 8, 23) && date <= new DateTime(date.Year, 9, 22, 23, 59, 59)) {
c.AstrologicalSigns.ZodiacSign = "Virgo";
return;
}
if (date >= new DateTime(date.Year, 9, 23) && date <= new DateTime(date.Year, 10, 22, 23, 59, 59))
{
if (date >= new DateTime(date.Year, 9, 23) && date <= new DateTime(date.Year, 10, 22, 23, 59, 59)) {
c.AstrologicalSigns.ZodiacSign = "Libra";
return;
}
if (date >= new DateTime(date.Year, 9, 23) && date <= new DateTime(date.Year, 11, 21, 23, 59, 59))
{
if (date >= new DateTime(date.Year, 9, 23) && date <= new DateTime(date.Year, 11, 21, 23, 59, 59)) {
c.AstrologicalSigns.ZodiacSign = "Scorpio";
return;
}
if (date >= new DateTime(date.Year, 11, 21) && date <= new DateTime(date.Year, 12, 21, 23, 59, 59))
{
if (date >= new DateTime(date.Year, 11, 21) && date <= new DateTime(date.Year, 12, 21, 23, 59, 59)) {
c.AstrologicalSigns.ZodiacSign = "Sagittarius";
return;
}
if (date >= new DateTime(date.Year, 12, 22) && date <= new DateTime(date.Year, 12, 31, 23, 59, 59))
{
if (date >= new DateTime(date.Year, 12, 22) && date <= new DateTime(date.Year, 12, 31, 23, 59, 59)) {
c.AstrologicalSigns.ZodiacSign = "Capricorn";
return;
}
}
public static void CalculateSolarEclipse(DateTime date, double lat, double longi, Celestial c)
{
public static void CalculateSolarEclipse(DateTime date, Double lat, Double longi, Celestial c) {
//Convert to Radian
double latR = lat * Math.PI / 180;
double longR = longi * Math.PI / 180;
List<List<string>> se = SolarEclipseCalc.CalculateSolarEclipse(date, latR, longR);
Double latR = lat * Math.PI / 180;
Double longR = longi * Math.PI / 180;
List<List<String>> se = SolarEclipseCalc.CalculateSolarEclipse(date, latR, longR);
//RETURN FIRST AND LAST
if (se.Count == 0) { return; }
//FIND LAST AND NEXT ECLIPSE
int lastE = -1;
int nextE = -1;
int currentE = 0;
Int32 lastE = -1;
Int32 nextE = -1;
Int32 currentE = 0;
DateTime lastDate = new DateTime();
DateTime nextDate = new DateTime(3300, 1, 1);
//Iterate to get last and next eclipse
foreach(List<string> values in se)
{
foreach (List<String> values in se) {
DateTime ld = DateTime.ParseExact(values[0], "yyyy-MMM-dd", System.Globalization.CultureInfo.InvariantCulture);
if (ld < date && ld>lastDate) { lastDate = ld;lastE = currentE; }
if(ld>= date && ld < nextDate) { nextDate = ld;nextE = currentE; }
if (ld < date && ld > lastDate) { lastDate = ld; lastE = currentE; }
if (ld >= date && ld < nextDate) { nextDate = ld; nextE = currentE; }
currentE++;
}
//SET ECLIPSE DATA
if (lastE >= 0)
{
if (lastE >= 0) {
c.SolarEclipse.LastEclipse = new SolarEclipseDetails(se[lastE]);
}
if (nextE >= 0)
{
if (nextE >= 0) {
c.SolarEclipse.NextEclipse = new SolarEclipseDetails(se[nextE]);
}
}
#region Private Suntime Members
private static readonly double dayMS = 1000 * 60 * 60 * 24, j1970 = 2440588, j2000 = 2451545;
private static readonly double rad = Math.PI / 180;
private static readonly Double dayMS = 1000 * 60 * 60 * 24, j1970 = 2440588, j2000 = 2451545;
private static readonly Double rad = Math.PI / 180;
private static double LocalSiderealTimeForTimeZone(double lon, double jd, double z)
/*private static Double LocalSiderealTimeForTimeZone(Double lon, Double jd, Double z)
{
double s = 24110.5 + 8640184.812999999 * jd / 36525 + 86636.6 * z + 86400 * lon;
Double s = 24110.5 + 8640184.812999999 * jd / 36525 + 86636.6 * z + 86400 * lon;
s = s / 86400;
s = s - Math.Truncate(s);
double lst = s * 360 *rad;
Double lst = s * 360 *rad;
return lst;
}
private static double SideRealTime(double d, double lw)
{
double s = rad * (280.16 + 360.9856235 * d) - lw;
}*/
private static Double SideRealTime(Double d, Double lw) {
Double s = rad * (280.16 + 360.9856235 * d) - lw;
return s;
}
private static double solarTransitJ(double ds, double M, double L)
{
return j2000 + ds + 0.0053 * Math.Sin(M) - 0.0069 * Math.Sin(2 * L);
}
private static Double SolarTransitJ(Double ds, Double M, Double L) => j2000 + ds + 0.0053 * Math.Sin(M) - 0.0069 * Math.Sin(2 * L);
//CH15
//Formula 15.1
//Returns Approximate Time
private static double hourAngle(double h, double phi, double d)
{
private static Double HourAngle(Double h, Double phi, Double d) {
//NUMBER RETURNING > and < 1 NaN;
double d1 = Math.Sin(h) - Math.Sin(phi) * Math.Sin(d);
double d2 = Math.Cos(phi) * Math.Cos(d);
double d3 = (d1 / d2);
Double d1 = Math.Sin(h) - Math.Sin(phi) * Math.Sin(d);
Double d2 = Math.Cos(phi) * Math.Cos(d);
Double d3 = d1 / d2;
return Math.Acos(d3);
}
private static double approxTransit(double Ht, double lw, double n)
{
return 0.0009 + (Ht + lw) / (2 * Math.PI) + n;
}
private static Double ApproxTransit(Double Ht, Double lw, Double n) => 0.0009 + (Ht + lw) / (2 * Math.PI) + n;
private static double julianCycle(double d, double lw) { return Math.Round(d - 0.0009 - lw / (2 * Math.PI)); }
private static Double JulianCycle(Double d, Double lw) => Math.Round(d - 0.0009 - lw / (2 * Math.PI));
//Returns Time of specified event based on suns angle
private static double GetTime(double h, double lw, double phi, double dec, double n,double M, double L)
{
double approxTime = hourAngle(h, phi, dec); //Ch15 Formula 15.1
private static Double GetTime(Double h, Double lw, Double phi, Double dec, Double n, Double M, Double L) {
Double approxTime = HourAngle(h, phi, dec); //Ch15 Formula 15.1
double a = approxTransit(approxTime, lw, n);
double st = solarTransitJ(a, M, L);
Double a = ApproxTransit(approxTime, lw, n);
Double st = SolarTransitJ(a, M, L);
return st;
}
private static double declination(double l, double b)
{
double e = (Math.PI/180) * 23.4392911; // obliquity of the Earth
private static Double Declination(Double l, Double b) {
Double e = Math.PI / 180 * 23.4392911; // obliquity of the Earth
return Math.Asin(Math.Sin(b) * Math.Cos(e) + Math.Cos(b) * Math.Sin(e) * Math.Sin(l));
}
private static void CalculateSunAngle(DateTime date, double longi, double lat, Celestial c)
{
TimeSpan ts = date - new DateTime(1970, 1, 1,0,0,0, DateTimeKind.Utc);
double dms = (ts.TotalMilliseconds / dayMS -.5 + j1970)-j2000;
private static void CalculateSunAngle(DateTime date, Double longi, Double lat, Celestial c) {
TimeSpan ts = date - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
Double dms = ts.TotalMilliseconds / dayMS - .5 + j1970 - j2000;
double lw = rad * -longi;
double phi = rad * lat;
double e = rad * 23.4397;
Double lw = rad * -longi;
Double phi = rad * lat;
//Double e = rad * 23.4397;
double[] sc = sunCoords(dms);
Double[] sc = SunCoords(dms);
double H = SideRealTime(dms, lw) - sc[1];
Double H = SideRealTime(dms, lw) - sc[1];
c.sunAzimuth = Math.Atan2(Math.Sin(H), Math.Cos(H) * Math.Sin(phi) - Math.Tan(sc[0]) * Math.Cos(phi)) * 180 / Math.PI + 180;
c.sunAltitude = Math.Asin(Math.Sin(phi) * Math.Sin(sc[0]) + Math.Cos(phi) * Math.Cos(sc[0]) * Math.Cos(H)) * 180 / Math.PI;
}
private static double solarMeanAnomaly(double d)
{
return rad * (357.5291 + 0.98560028 * d);
}
private static Double SolarMeanAnomaly(Double d) => rad * (357.5291 + 0.98560028 * d);
private static double eclipticLongitude(double m)
{
double c = rad * (1.9148 * Math.Sin(m) + 0.02 * Math.Sin(2 * m) + 0.0003 * Math.Sin(3 * m)); // equation of center
double p = rad * 102.9372; // perihelion of the Earth
private static Double EclipticLongitude(Double m) {
Double c = rad * (1.9148 * Math.Sin(m) + 0.02 * Math.Sin(2 * m) + 0.0003 * Math.Sin(3 * m)); // equation of center
Double p = rad * 102.9372; // perihelion of the Earth
return m + c + p + Math.PI;
}
private static double[] sunCoords(double d)
{
private static Double[] SunCoords(Double d) {
double m = solarMeanAnomaly(d);
double l = eclipticLongitude(m);
double[] sc = new double[2];
double b = 0;
double e = rad * 23.4397; // obliquity of the Earth
Double m = SolarMeanAnomaly(d);
Double l = EclipticLongitude(m);
Double[] sc = new Double[2];
Double b = 0;
Double e = rad * 23.4397; // obliquity of the Earth
sc[0] = Math.Asin(Math.Sin(b) * Math.Cos(e) + Math.Cos(b) * Math.Sin(e) * Math.Sin(l)); //declination
sc[1] = Math.Atan2(Math.Sin(l) * Math.Cos(e) - Math.Tan(b) * Math.Sin(e), Math.Cos(l)); //rightAscension
return sc;

View File

@ -1,8 +1,7 @@
using System;
using System.ComponentModel;
using System.Collections.Generic;
namespace CoordinateSharp
{
namespace CoordinateSharp {
/// <summary>
/// The main class for handling location based celestial information.
/// </summary>
@ -10,29 +9,26 @@ namespace CoordinateSharp
/// This class can calculate various pieces of solar and lunar data, based on location and date
/// </remarks>
[Serializable]
public class Celestial
{
public class Celestial {
//When a rise or a set does not occur, the DateTime will return null
/// <summary>
/// Creates an empty Celestial.
/// </summary>
public Celestial()
{
astrologicalSigns = new AstrologicalSigns();
lunarEclipse = new LunarEclipse();
solarEclipse = new SolarEclipse();
CalculateCelestialTime(0, 0, new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc));
public Celestial() {
this.astrologicalSigns = new AstrologicalSigns();
this.lunarEclipse = new LunarEclipse();
this.solarEclipse = new SolarEclipse();
this.CalculateCelestialTime(0, 0, new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc));
}
private Celestial(bool hasCalcs)
{
private Celestial(Boolean hasCalcs) {
astrologicalSigns = new AstrologicalSigns();
lunarEclipse = new LunarEclipse();
solarEclipse = new SolarEclipse();
if (hasCalcs) { CalculateCelestialTime(0, 0, new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc)); }
this.astrologicalSigns = new AstrologicalSigns();
this.lunarEclipse = new LunarEclipse();
this.solarEclipse = new SolarEclipse();
if (hasCalcs) { this.CalculateCelestialTime(0, 0, new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc)); }
}
/// <summary>
@ -41,13 +37,12 @@ namespace CoordinateSharp
/// <param name="lat">latitude</param>
/// <param name="longi">longitude</param>
/// <param name="geoDate">DateTime (UTC)</param>
public Celestial(double lat, double longi, DateTime geoDate)
{
public Celestial(Double lat, Double longi, DateTime geoDate) {
DateTime d = new DateTime(geoDate.Year, geoDate.Month, geoDate.Day, geoDate.Hour, geoDate.Minute, geoDate.Second, DateTimeKind.Utc);
astrologicalSigns = new AstrologicalSigns();
lunarEclipse = new LunarEclipse();
solarEclipse = new SolarEclipse();
CalculateCelestialTime(lat, longi, d);
this.astrologicalSigns = new AstrologicalSigns();
this.lunarEclipse = new LunarEclipse();
this.solarEclipse = new SolarEclipse();
this.CalculateCelestialTime(lat, longi, d);
}
/// <summary>
@ -55,11 +50,10 @@ namespace CoordinateSharp
/// </summary>
/// <param name="c">Coordinate</param>
/// <returns>Celestial</returns>
public static Celestial LoadCelestial(Coordinate c)
{
DateTime geoDate = c.GeoDate;
public static Celestial LoadCelestial(Coordinate c) {
//DateTime geoDate = c.GeoDate;
DateTime d = new DateTime(geoDate.Year, geoDate.Month, geoDate.Day, geoDate.Hour, geoDate.Minute, geoDate.Second, DateTimeKind.Utc);
//DateTime d = new DateTime(geoDate.Year, geoDate.Month, geoDate.Day, geoDate.Hour, geoDate.Minute, geoDate.Second, DateTimeKind.Utc);
Celestial cel = new Celestial(c.Latitude.ToDouble(), c.Longitude.ToDouble(), c.GeoDate);
return cel;
@ -71,9 +65,8 @@ namespace CoordinateSharp
/// <param name="c">Coordinate</param>
/// <param name="offset">UTC offset</param>
/// <returns></returns>
public static Celestial Celestial_LocalTime(Coordinate c, double offset)
{
if(offset < -12 || offset > 12) { throw new ArgumentOutOfRangeException("Time offsets cannot be greater 12 or less than -12."); }
public static Celestial Celestial_LocalTime(Coordinate c, Double offset) {
if (offset < -12 || offset > 12) { throw new ArgumentOutOfRangeException("Time offsets cannot be greater 12 or less than -12."); }
//Probably need to offset initial UTC date so user can op in local
//Determine best way to do this.
DateTime d = c.GeoDate.AddHours(offset);
@ -89,7 +82,7 @@ namespace CoordinateSharp
celPost.Local_Convert(c, offset);
//Get SunSet
int i = Determine_Slipped_Event_Index(cel.SunSet, celPre.SunSet, celPost.SunSet, d);
Int32 i = Determine_Slipped_Event_Index(cel.SunSet, celPre.SunSet, celPost.SunSet, d);
cel.sunSet = Get_Correct_Slipped_Date(cel.SunSet, celPre.SunSet, celPost.SunSet, i);
cel.AdditionalSolarTimes.CivilDusk = Get_Correct_Slipped_Date(cel.AdditionalSolarTimes.CivilDusk,
celPre.AdditionalSolarTimes.CivilDusk, celPost.AdditionalSolarTimes.CivilDusk, i);
@ -129,15 +122,12 @@ namespace CoordinateSharp
return cel;
}
private static CelestialStatus GetStatus(DateTime? rise, DateTime? set, CelestialStatus[] cels)
{
private static CelestialStatus GetStatus(DateTime? rise, DateTime? set, CelestialStatus[] cels) {
if (set.HasValue && rise.HasValue) { return CelestialStatus.RiseAndSet; }
if (set.HasValue && !rise.HasValue) { return CelestialStatus.NoRise; }
if (!set.HasValue && rise.HasValue) { return CelestialStatus.NoSet; }
for (int x=0; x < 3;x++)
{
if(cels[x] == CelestialStatus.DownAllDay || cels[x] == CelestialStatus.UpAllDay)
{
for (Int32 x = 0; x < 3; x++) {
if (cels[x] == CelestialStatus.DownAllDay || cels[x] == CelestialStatus.UpAllDay) {
return cels[x];
}
}
@ -149,31 +139,30 @@ namespace CoordinateSharp
/// </summary>
/// <param name="c">Coordinate</param>
/// <param name="offset">hour offset</param>
private void Local_Convert(Coordinate c, double offset)
{
private void Local_Convert(Coordinate c, Double offset) {
//Find new lunar set rise times
if (MoonSet.HasValue) { moonSet = moonSet.Value.AddHours(offset); }
if (MoonRise.HasValue) { moonRise = moonRise.Value.AddHours(offset); }
if (this.MoonSet.HasValue) { this.moonSet = this.moonSet.Value.AddHours(offset); }
if (this.MoonRise.HasValue) { this.moonRise = this.moonRise.Value.AddHours(offset); }
//Perigee
Perigee.ConvertTo_Local_Time(offset);
this.Perigee.ConvertTo_Local_Time(offset);
//Apogee
Apogee.ConvertTo_Local_Time(offset);
this.Apogee.ConvertTo_Local_Time(offset);
//Eclipse
LunarEclipse.ConvertTo_LocalTime(offset);
this.LunarEclipse.ConvertTo_LocalTime(offset);
////Solar
if (sunSet.HasValue) { sunSet = sunSet.Value.AddHours(offset); }
if (SunRise.HasValue) { sunRise = SunRise.Value.AddHours(offset); }
AdditionalSolarTimes.Convert_To_Local_Time(offset);
if (this.sunSet.HasValue) { this.sunSet = this.sunSet.Value.AddHours(offset); }
if (this.SunRise.HasValue) { this.sunRise = this.SunRise.Value.AddHours(offset); }
this.AdditionalSolarTimes.Convert_To_Local_Time(offset);
//Eclipse
SolarEclipse.ConvertTo_LocalTime(offset);
this.SolarEclipse.ConvertTo_LocalTime(offset);
SunCalc.CalculateZodiacSign(c.GeoDate.AddHours(offset), this);
MoonCalc.GetMoonSign(c.GeoDate.AddHours(offset), this);
}
private PerigeeApogee Get_Correct_Slipped_Date(PerigeeApogee actual, PerigeeApogee pre, PerigeeApogee post, int i)
/*private PerigeeApogee Get_Correct_Slipped_Date(PerigeeApogee actual, PerigeeApogee pre, PerigeeApogee post, Int32 i)
{
switch (i)
{
@ -186,47 +175,31 @@ namespace CoordinateSharp
default:
return actual;
}
}
private static DateTime? Get_Correct_Slipped_Date(DateTime? actual, DateTime? pre, DateTime? post, int i)
{
switch(i)
{
case 0:
return pre;
case 1:
return actual;
case 2:
return post;
default:
return null;
}
}
private static int Determine_Slipped_Event_Index(DateTime? actual, DateTime? pre, DateTime? post, DateTime d)
}*/
private static DateTime? Get_Correct_Slipped_Date(DateTime? actual, DateTime? pre, DateTime? post, Int32 i) => i switch
{
0 => pre,
1 => actual,
2 => post,
_ => null,
};
private static Int32 Determine_Slipped_Event_Index(DateTime? actual, DateTime? pre, DateTime? post, DateTime d) {
if (actual.HasValue)
{
if (actual.Value.Day != d.Day)
{
if (pre.HasValue)
{
if (actual.HasValue) {
if (actual.Value.Day != d.Day) {
if (pre.HasValue) {
if (pre.Value.Day == d.Day) { return 0; }
}
if (post.HasValue)
{
if (post.HasValue) {
if (post.Value.Day == d.Day) { return 2; }
}
return 3;
}
}
else
{
if (pre.HasValue)
{
} else {
if (pre.HasValue) {
if (pre.Value.Day == d.Day) { return 0; }
}
if (post.HasValue)
{
if (post.HasValue) {
if (post.Value.Day == d.Day) { return 2; }
}
}
@ -238,18 +211,18 @@ namespace CoordinateSharp
internal DateTime? moonSet;
internal DateTime? moonRise;
internal double sunAltitude;
internal double sunAzimuth;
internal double moonAltitude;
internal double moonAzimuth;
internal Double sunAltitude;
internal Double sunAzimuth;
internal Double moonAltitude;
internal Double moonAzimuth;
internal Distance moonDistance;
internal CelestialStatus sunCondition;
internal CelestialStatus moonCondition;
internal bool isSunUp;
internal bool isMoonUp;
internal Boolean isSunUp;
internal Boolean isMoonUp;
internal MoonIllum moonIllum;
internal Perigee perigee;
@ -262,59 +235,59 @@ namespace CoordinateSharp
/// <summary>
/// Sunset time.
/// </summary>
public DateTime? SunSet { get { return sunSet; } }
public DateTime? SunSet => this.sunSet;
/// <summary>
/// Sunrise time.
/// </summary>
public DateTime? SunRise { get { return sunRise; } }
public DateTime? SunRise => this.sunRise;
/// <summary>
/// Moonset time.
/// </summary>
public DateTime? MoonSet { get { return moonSet; } }
public DateTime? MoonSet => this.moonSet;
/// <summary>
/// Moonrise time.
/// </summary>
public DateTime? MoonRise { get { return moonRise; } }
public DateTime? MoonRise => this.moonRise;
/// <summary>
/// Sun altitude in degrees (E of N).
/// </summary>
public double SunAltitude { get { return sunAltitude; } }
public Double SunAltitude => this.sunAltitude;
/// <summary>
/// Sun azimuth in degrees (E of N).
/// </summary>
public double SunAzimuth { get { return sunAzimuth; } }
public Double SunAzimuth => this.sunAzimuth;
/// <summary>
/// Moon altitude in degrees (corrected for parallax and refraction).
/// </summary>
public double MoonAltitude { get { return moonAltitude; } }
public Double MoonAltitude => this.moonAltitude;
/// <summary>
/// Moon azimuth in degrees (E of N).
/// </summary>
public double MoonAzimuth { get { return moonAzimuth; } }
public Double MoonAzimuth => this.moonAzimuth;
/// <summary>
/// Estimated moon distance from the earth.
/// </summary>
public Distance MoonDistance { get { return moonDistance; } }
public Distance MoonDistance => this.moonDistance;
/// <summary>
/// Sun's Condition based on the provided date.
/// </summary>
public CelestialStatus SunCondition { get { return sunCondition; } }
public CelestialStatus SunCondition => this.sunCondition;
/// <summary>
/// Moon's condition based on the provided date.
/// </summary>
public CelestialStatus MoonCondition { get { return moonCondition; } }
public CelestialStatus MoonCondition => this.moonCondition;
/// <summary>
/// Determine if the sun is currently up, based on sunset and sunrise time at the provided location and date.
/// </summary>
public bool IsSunUp{ get { return isSunUp; } }
public Boolean IsSunUp => this.isSunUp;
/// <summary>
/// Determine if the moon is currently up, based on moonset and moonrise time at the provided location and date.
/// </summary>
public bool IsMoonUp { get { return isMoonUp; } }
public Boolean IsMoonUp => this.isMoonUp;
/// <summary>
/// Moon ilumination details based on the provided date.
@ -322,37 +295,37 @@ namespace CoordinateSharp
/// <remarks>
/// Contains phase, phase name, fraction and angle
/// </remarks>
public MoonIllum MoonIllum { get { return moonIllum; } }
public MoonIllum MoonIllum => this.moonIllum;
/// <summary>
/// Moons perigee details based on the provided date.
/// </summary>
public Perigee Perigee { get { return perigee; } }
public Perigee Perigee => this.perigee;
/// <summary>
/// Moons apogee details based on the provided date.
/// </summary>
public Apogee Apogee { get { return apogee; } }
public Apogee Apogee => this.apogee;
/// <summary>
/// Additional solar event times based on the provided date and location.
/// </summary>
/// <remarks>Contains civil and nautical dawn and dusk times.</remarks>
public AdditionalSolarTimes AdditionalSolarTimes { get { return additionalSolarTimes; } }
public AdditionalSolarTimes AdditionalSolarTimes => this.additionalSolarTimes;
/// <summary>
/// Astrological signs based on the provided date.
/// </summary>
/// <remarks>
/// Contains zodiac, moon sign and moon name during full moon events
/// </remarks>
public AstrologicalSigns AstrologicalSigns { get { return astrologicalSigns; } }
public AstrologicalSigns AstrologicalSigns => this.astrologicalSigns;
/// <summary>
/// Returns a SolarEclipse.
/// </summary>
public SolarEclipse SolarEclipse { get { return solarEclipse; } }
public SolarEclipse SolarEclipse => this.solarEclipse;
/// <summary>
/// Returns a LunarEclipse.
/// </summary>
public LunarEclipse LunarEclipse { get { return lunarEclipse; } }
public LunarEclipse LunarEclipse => this.lunarEclipse;
/// <summary>
/// Calculates all celestial data. Coordinates will notify as changes occur
@ -360,8 +333,7 @@ namespace CoordinateSharp
/// <param name="lat">Decimal format latitude</param>
/// <param name="longi">Decimal format longitude</param>
/// <param name="date">Geographic DateTime</param>
internal void CalculateCelestialTime(double lat, double longi, DateTime date)
{
internal void CalculateCelestialTime(Double lat, Double longi, DateTime date) {
date = new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, DateTimeKind.Utc);
SunCalc.CalculateSunTime(lat, longi, date, this);
MoonCalc.GetMoonTimes(date, lat, longi, this);
@ -370,11 +342,11 @@ namespace CoordinateSharp
SunCalc.CalculateZodiacSign(date, this);
MoonCalc.GetMoonSign(date, this);
MoonCalc.GetMoonIllumination(date, this,lat,longi);
MoonCalc.GetMoonIllumination(date, this, lat, longi);
perigee = MoonCalc.GetPerigeeEvents(date);
apogee = MoonCalc.GetApogeeEvents(date);
this.perigee = MoonCalc.GetPerigeeEvents(date);
this.apogee = MoonCalc.GetApogeeEvents(date);
Calculate_Celestial_IsUp_Booleans(date, this);
@ -386,8 +358,7 @@ namespace CoordinateSharp
/// <param name="longi">Decimal format longitude</param>
/// <param name="date">Geographic DateTime</param>
/// <returns>Fully populated Celestial object</returns>
public static Celestial CalculateCelestialTimes(double lat, double longi, DateTime date)
{
public static Celestial CalculateCelestialTimes(Double lat, Double longi, DateTime date) {
date = new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, DateTimeKind.Utc);
Celestial c = new Celestial(false);
@ -397,7 +368,7 @@ namespace CoordinateSharp
MoonCalc.GetMoonDistance(date, c);
SunCalc.CalculateZodiacSign(date, c);
MoonCalc.GetMoonSign(date, c);
MoonCalc.GetMoonIllumination(date, c,lat,longi);
MoonCalc.GetMoonIllumination(date, c, lat, longi);
c.perigee = MoonCalc.GetPerigeeEvents(date);
c.apogee = MoonCalc.GetApogeeEvents(date);
@ -414,8 +385,7 @@ namespace CoordinateSharp
/// <param name="longi">longitude</param>
/// <param name="date">DateTime</param>
/// <returns>Celestial (Partially Populated)</returns>
public static Celestial CalculateSunData(double lat, double longi, DateTime date)
{
public static Celestial CalculateSunData(Double lat, Double longi, DateTime date) {
date = new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, DateTimeKind.Utc);
Celestial c = new Celestial(false);
@ -431,8 +401,7 @@ namespace CoordinateSharp
/// <param name="longi">longitude</param>
/// <param name="date">DateTime</param>
/// <returns>Celestial (Partially Populated)</returns>
public static Celestial CalculateMoonData(double lat, double longi, DateTime date)
{
public static Celestial CalculateMoonData(Double lat, Double longi, DateTime date) {
date = new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, DateTimeKind.Utc);
Celestial c = new Celestial(false);
@ -440,7 +409,7 @@ namespace CoordinateSharp
MoonCalc.GetMoonTimes(date, lat, longi, c);
MoonCalc.GetMoonDistance(date, c);
MoonCalc.GetMoonSign(date, c);
MoonCalc.GetMoonIllumination(date, c,lat,longi);
MoonCalc.GetMoonIllumination(date, c, lat, longi);
c.perigee = MoonCalc.GetPerigeeEvents(date);
c.apogee = MoonCalc.GetApogeeEvents(date);
@ -456,13 +425,12 @@ namespace CoordinateSharp
/// <param name="longi">longitude</param>
/// <param name="date">DateTime</param>
/// <returns></returns>
public static List<SolarEclipseDetails> Get_Solar_Eclipse_Table(double lat, double longi, DateTime date)
{
public static List<SolarEclipseDetails> Get_Solar_Eclipse_Table(Double lat, Double longi, DateTime date) {
//Convert to Radians
double latR = lat * Math.PI / 180;
double longR = longi * Math.PI / 180;
Double latR = lat * Math.PI / 180;
Double longR = longi * Math.PI / 180;
//Get solar data based on date
double[] events = Eclipse.SolarData.SolarDateData_100Year(date);
Double[] events = Eclipse.SolarData.SolarDateData_100Year(date);
//Return list of solar data.
return SolarEclipseCalc.CalculateSolarEclipse(date, latR, longR, events);
}
@ -474,13 +442,12 @@ namespace CoordinateSharp
/// <param name="longi">longitude</param>
/// <param name="date">DateTime</param>
/// <returns></returns>
public static List<LunarEclipseDetails> Get_Lunar_Eclipse_Table(double lat, double longi, DateTime date)
{
public static List<LunarEclipseDetails> Get_Lunar_Eclipse_Table(Double lat, Double longi, DateTime date) {
//Convert to Radians
double latR = lat * Math.PI / 180;
double longR = longi * Math.PI / 180;
Double latR = lat * Math.PI / 180;
Double longR = longi * Math.PI / 180;
//Get solar data based on date
double[] events = Eclipse.LunarData.LunarDateData_100Year(date);
Double[] events = Eclipse.LunarData.LunarDateData_100Year(date);
//Return list of solar data.
return LunarEclipseCalc.CalculateLunarEclipse(date, latR, longR, events);
}
@ -490,11 +457,9 @@ namespace CoordinateSharp
/// </summary>
/// <param name="date">Coordinate GeoDate</param>
/// <param name="cel">Celestial Object</param>
private static void Calculate_Celestial_IsUp_Booleans(DateTime date, Celestial cel)
{
private static void Calculate_Celestial_IsUp_Booleans(DateTime date, Celestial cel) {
//SUN
switch (cel.SunCondition)
{
switch (cel.SunCondition) {
case CelestialStatus.DownAllDay:
cel.isSunUp = false;
break;
@ -502,42 +467,13 @@ namespace CoordinateSharp
cel.isSunUp = true;
break;
case CelestialStatus.NoRise:
if(date<cel.SunSet)
{
cel.isSunUp = true;
}
else { cel.isSunUp = false; }
cel.isSunUp = date < cel.SunSet;
break;
case CelestialStatus.NoSet:
if (date > cel.SunRise)
{
cel.isSunUp = true;
}
else { cel.isSunUp = false; }
cel.isSunUp = date > cel.SunRise;
break;
case CelestialStatus.RiseAndSet:
if (cel.SunRise < cel.SunSet)
{
if (date > cel.SunRise && date < cel.SunSet)
{
cel.isSunUp = true;
}
else
{
cel.isSunUp = false;
}
}
else
{
if (date > cel.SunRise || date < cel.SunSet)
{
cel.isSunUp = true;
}
else
{
cel.isSunUp = false;
}
}
cel.isSunUp = cel.SunRise < cel.SunSet ? date > cel.SunRise && date < cel.SunSet : date > cel.SunRise || date < cel.SunSet;
break;
default:
//Should never be reached. If reached, previous calculations failed somewhere.
@ -545,8 +481,7 @@ namespace CoordinateSharp
}
//MOON
switch (cel.MoonCondition)
{
switch (cel.MoonCondition) {
case CelestialStatus.DownAllDay:
cel.isMoonUp = false;
break;
@ -554,42 +489,13 @@ namespace CoordinateSharp
cel.isMoonUp = true;
break;
case CelestialStatus.NoRise:
if (date < cel.MoonSet)
{
cel.isMoonUp = true;
}
else { cel.isMoonUp = false; }
cel.isMoonUp = date < cel.MoonSet;
break;
case CelestialStatus.NoSet:
if (date > cel.MoonRise)
{
cel.isMoonUp = true;
}
else { cel.isMoonUp = false; }
cel.isMoonUp = date > cel.MoonRise;
break;
case CelestialStatus.RiseAndSet:
if (cel.MoonRise < cel.MoonSet)
{
if (date > cel.MoonRise && date < cel.MoonSet)
{
cel.isMoonUp = true;
}
else
{
cel.isMoonUp = false;
}
}
else
{
if (date > cel.MoonRise || date < cel.MoonSet)
{
cel.isMoonUp = true;
}
else
{
cel.isMoonUp = false;
}
}
cel.isMoonUp = cel.MoonRise < cel.MoonSet ? date > cel.MoonRise && date < cel.MoonSet : date > cel.MoonRise || date < cel.MoonSet;
break;
default:
//Should never be reached. If reached, previous calculations failed somewhere.
@ -602,19 +508,13 @@ namespace CoordinateSharp
/// </summary>
/// <param name="d">DateTime</param>
/// <returns>Apogee</returns>
public static Apogee GetApogees(DateTime d)
{
return MoonCalc.GetApogeeEvents(d);
}
public static Apogee GetApogees(DateTime d) => MoonCalc.GetApogeeEvents(d);
/// <summary>
/// Returns Perigee object containing last and next perigee based on the specified date.
/// </summary>
/// <param name="d">DateTime</param>
/// <returns>Perigee</returns>
public static Perigee GetPerigees(DateTime d)
{
return MoonCalc.GetPerigeeEvents(d);
}
public static Perigee GetPerigees(DateTime d) => MoonCalc.GetPerigeeEvents(d);
}
}

View File

@ -2,8 +2,7 @@
using System.Collections.Generic;
using System.Linq;
namespace CoordinateSharp
{
namespace CoordinateSharp {
@ -11,87 +10,78 @@ namespace CoordinateSharp
/// Used for UTM/MGRS Conversions
/// </summary>
[Serializable]
internal class LatZones
{
public static List<string> longZongLetters = new List<string>(new string[]{"C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T",
internal class LatZones {
public static List<String> longZongLetters = new List<String>(new String[]{"C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T",
"U", "V", "W", "X"});
}
/// <summary>
/// Used for handling diagraph determination
/// </summary>
[Serializable]
internal class Digraphs
{
private List<Digraph> digraph1;
private List<Digraph> digraph2;
internal class Digraphs {
private readonly List<Digraph> digraph1;
private readonly List<Digraph> digraph2;
private String[] digraph1Array = { "A", "B", "C", "D", "E", "F", "G", "H",
"J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X",
"Y", "Z" };
private readonly String[] digraph1Array = { "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
private String[] digraph2Array = { "V", "A", "B", "C", "D", "E", "F", "G",
"H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V" };
private readonly String[] digraph2Array = { "V", "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V" };
public Digraphs()
{
digraph1 = new List<Digraph>();
digraph2 = new List<Digraph>();
public Digraphs() {
this.digraph1 = new List<Digraph>();
this.digraph2 = new List<Digraph>();
digraph1.Add(new Digraph() { Zone = 1, Letter = "A" });
digraph1.Add(new Digraph() { Zone = 2, Letter = "B" });
digraph1.Add(new Digraph() { Zone = 3, Letter = "C" });
digraph1.Add(new Digraph() { Zone = 4, Letter = "D" });
digraph1.Add(new Digraph() { Zone = 5, Letter = "E" });
digraph1.Add(new Digraph() { Zone = 6, Letter = "F" });
digraph1.Add(new Digraph() { Zone = 7, Letter = "G" });
digraph1.Add(new Digraph() { Zone = 8, Letter = "H" });
digraph1.Add(new Digraph() { Zone = 9, Letter = "J" });
digraph1.Add(new Digraph() { Zone = 10, Letter = "K" });
digraph1.Add(new Digraph() { Zone = 11, Letter = "L" });
digraph1.Add(new Digraph() { Zone = 12, Letter = "M" });
digraph1.Add(new Digraph() { Zone = 13, Letter = "N" });
digraph1.Add(new Digraph() { Zone = 14, Letter = "P" });
digraph1.Add(new Digraph() { Zone = 15, Letter = "Q" });
digraph1.Add(new Digraph() { Zone = 16, Letter = "R" });
digraph1.Add(new Digraph() { Zone = 17, Letter = "S" });
digraph1.Add(new Digraph() { Zone = 18, Letter = "T" });
digraph1.Add(new Digraph() { Zone = 19, Letter = "U" });
digraph1.Add(new Digraph() { Zone = 20, Letter = "V" });
digraph1.Add(new Digraph() { Zone = 21, Letter = "W" });
digraph1.Add(new Digraph() { Zone = 22, Letter = "X" });
digraph1.Add(new Digraph() { Zone = 23, Letter = "Y" });
digraph1.Add(new Digraph() { Zone = 24, Letter = "Z" });
digraph1.Add(new Digraph() { Zone = 1, Letter = "A" });
this.digraph1.Add(new Digraph() { Zone = 1, Letter = "A" });
this.digraph1.Add(new Digraph() { Zone = 2, Letter = "B" });
this.digraph1.Add(new Digraph() { Zone = 3, Letter = "C" });
this.digraph1.Add(new Digraph() { Zone = 4, Letter = "D" });
this.digraph1.Add(new Digraph() { Zone = 5, Letter = "E" });
this.digraph1.Add(new Digraph() { Zone = 6, Letter = "F" });
this.digraph1.Add(new Digraph() { Zone = 7, Letter = "G" });
this.digraph1.Add(new Digraph() { Zone = 8, Letter = "H" });
this.digraph1.Add(new Digraph() { Zone = 9, Letter = "J" });
this.digraph1.Add(new Digraph() { Zone = 10, Letter = "K" });
this.digraph1.Add(new Digraph() { Zone = 11, Letter = "L" });
this.digraph1.Add(new Digraph() { Zone = 12, Letter = "M" });
this.digraph1.Add(new Digraph() { Zone = 13, Letter = "N" });
this.digraph1.Add(new Digraph() { Zone = 14, Letter = "P" });
this.digraph1.Add(new Digraph() { Zone = 15, Letter = "Q" });
this.digraph1.Add(new Digraph() { Zone = 16, Letter = "R" });
this.digraph1.Add(new Digraph() { Zone = 17, Letter = "S" });
this.digraph1.Add(new Digraph() { Zone = 18, Letter = "T" });
this.digraph1.Add(new Digraph() { Zone = 19, Letter = "U" });
this.digraph1.Add(new Digraph() { Zone = 20, Letter = "V" });
this.digraph1.Add(new Digraph() { Zone = 21, Letter = "W" });
this.digraph1.Add(new Digraph() { Zone = 22, Letter = "X" });
this.digraph1.Add(new Digraph() { Zone = 23, Letter = "Y" });
this.digraph1.Add(new Digraph() { Zone = 24, Letter = "Z" });
this.digraph1.Add(new Digraph() { Zone = 1, Letter = "A" });
digraph2.Add(new Digraph() { Zone = 0, Letter = "V"});
digraph2.Add(new Digraph() { Zone = 1, Letter = "A" });
digraph2.Add(new Digraph() { Zone = 2, Letter = "B" });
digraph2.Add(new Digraph() { Zone = 3, Letter = "C" });
digraph2.Add(new Digraph() { Zone = 4, Letter = "D" });
digraph2.Add(new Digraph() { Zone = 5, Letter = "E" });
digraph2.Add(new Digraph() { Zone = 6, Letter = "F" });
digraph2.Add(new Digraph() { Zone = 7, Letter = "G" });
digraph2.Add(new Digraph() { Zone = 8, Letter = "H" });
digraph2.Add(new Digraph() { Zone = 9, Letter = "J" });
digraph2.Add(new Digraph() { Zone = 10, Letter = "K" });
digraph2.Add(new Digraph() { Zone = 11, Letter = "L" });
digraph2.Add(new Digraph() { Zone = 12, Letter = "M" });
digraph2.Add(new Digraph() { Zone = 13, Letter = "N" });
digraph2.Add(new Digraph() { Zone = 14, Letter = "P" });
digraph2.Add(new Digraph() { Zone = 15, Letter = "Q" });
digraph2.Add(new Digraph() { Zone = 16, Letter = "R" });
digraph2.Add(new Digraph() { Zone = 17, Letter = "S" });
digraph2.Add(new Digraph() { Zone = 18, Letter = "T" });
digraph2.Add(new Digraph() { Zone = 19, Letter = "U" });
digraph2.Add(new Digraph() { Zone = 20, Letter = "V" });
this.digraph2.Add(new Digraph() { Zone = 0, Letter = "V" });
this.digraph2.Add(new Digraph() { Zone = 1, Letter = "A" });
this.digraph2.Add(new Digraph() { Zone = 2, Letter = "B" });
this.digraph2.Add(new Digraph() { Zone = 3, Letter = "C" });
this.digraph2.Add(new Digraph() { Zone = 4, Letter = "D" });
this.digraph2.Add(new Digraph() { Zone = 5, Letter = "E" });
this.digraph2.Add(new Digraph() { Zone = 6, Letter = "F" });
this.digraph2.Add(new Digraph() { Zone = 7, Letter = "G" });
this.digraph2.Add(new Digraph() { Zone = 8, Letter = "H" });
this.digraph2.Add(new Digraph() { Zone = 9, Letter = "J" });
this.digraph2.Add(new Digraph() { Zone = 10, Letter = "K" });
this.digraph2.Add(new Digraph() { Zone = 11, Letter = "L" });
this.digraph2.Add(new Digraph() { Zone = 12, Letter = "M" });
this.digraph2.Add(new Digraph() { Zone = 13, Letter = "N" });
this.digraph2.Add(new Digraph() { Zone = 14, Letter = "P" });
this.digraph2.Add(new Digraph() { Zone = 15, Letter = "Q" });
this.digraph2.Add(new Digraph() { Zone = 16, Letter = "R" });
this.digraph2.Add(new Digraph() { Zone = 17, Letter = "S" });
this.digraph2.Add(new Digraph() { Zone = 18, Letter = "T" });
this.digraph2.Add(new Digraph() { Zone = 19, Letter = "U" });
this.digraph2.Add(new Digraph() { Zone = 20, Letter = "V" });
}
internal int getDigraph1Index(String letter)
{
for (int i = 0; i < digraph1Array.Length; i++)
{
if (digraph1Array[i].Equals(letter))
{
internal Int32 GetDigraph1Index(String letter) {
for (Int32 i = 0; i < this.digraph1Array.Length; i++) {
if (this.digraph1Array[i].Equals(letter)) {
return i + 1;
}
}
@ -99,12 +89,9 @@ namespace CoordinateSharp
return -1;
}
internal int getDigraph2Index(String letter)
{
for (int i = 0; i < digraph2Array.Length; i++)
{
if (digraph2Array[i].Equals(letter))
{
internal Int32 GetDigraph2Index(String letter) {
for (Int32 i = 0; i < this.digraph2Array.Length; i++) {
if (this.digraph2Array[i].Equals(letter)) {
return i;
}
}
@ -112,29 +99,26 @@ namespace CoordinateSharp
return -1;
}
internal String getDigraph1(int longZone, double easting)
{
int a1 = longZone;
double a2 = 8 * ((a1 - 1) % 3) + 1;
internal String GetDigraph1(Int32 longZone, Double easting) {
Int32 a1 = longZone;
Double a2 = 8 * ((a1 - 1) % 3) + 1;
double a3 = easting;
double a4 = a2 + ((int)(a3 / 100000)) - 1;
return digraph1.Where(x=>x.Zone == Math.Floor(a4)).FirstOrDefault().Letter;
Double a3 = easting;
Double a4 = a2 + (Int32)(a3 / 100000) - 1;
return this.digraph1.Where(x => x.Zone == Math.Floor(a4)).FirstOrDefault().Letter;
}
internal String getDigraph2(int longZone, double northing)
{
int a1 = longZone;
double a2 = 1 + 5 * ((a1 - 1) % 2);
double a3 = northing;
double a4 = (a2 + ((int)(a3 / 100000)));
a4 = (a2 + ((int)(a3 / 100000.0))) % 20;
internal String GetDigraph2(Int32 longZone, Double northing) {
Int32 a1 = longZone;
Double a2 = 1 + 5 * ((a1 - 1) % 2);
Double a3 = northing;
Double a4 = a2 + (Int32)(a3 / 100000);
a4 = (a2 + (Int32)(a3 / 100000.0)) % 20;
a4 = Math.Floor(a4);
if (a4 < 0)
{
a4 = a4 + 19;
if (a4 < 0) {
a4 += 19;
}
return digraph2.Where(x => x.Zone == Math.Floor(a4)).FirstOrDefault().Letter;
return this.digraph2.Where(x => x.Zone == Math.Floor(a4)).FirstOrDefault().Letter;
}
}
@ -142,17 +126,15 @@ namespace CoordinateSharp
/// Diagraph model
/// </summary>
[Serializable]
internal class Digraph
{
public int Zone { get; set; }
public string Letter { get; set; }
internal class Digraph {
public Int32 Zone { get; set; }
public String Letter { get; set; }
}
/// <summary>
/// Used for setting whether a coordinate part is latitudinal or longitudinal.
/// </summary>
[Serializable]
public enum CoordinateType
{
public enum CoordinateType {
/// <summary>
/// Latitude
/// </summary>
@ -166,8 +148,7 @@ namespace CoordinateSharp
/// Used to set a coordinate part position.
/// </summary>
[Serializable]
public enum CoordinatesPosition :int
{
public enum CoordinatesPosition : Int32 {
/// <summary>
/// North
/// </summary>
@ -192,8 +173,7 @@ namespace CoordinateSharp
/// </summary>
[Serializable]
[Flags]
public enum Coordinate_Datum
{
public enum Coordinate_Datum {
/// <summary>
/// Lat Long GeoDetic
/// </summary>
@ -211,8 +191,7 @@ namespace CoordinateSharp
/// <summary>
/// Cartesian Coordinate Type
/// </summary>
public enum CartesianType
{
public enum CartesianType {
/// <summary>
/// Spherical Cartesian
/// </summary>
@ -226,35 +205,21 @@ namespace CoordinateSharp
/// Used for easy read math functions
/// </summary>
[Serializable]
internal static class ModM
{
public static double Mod(double x, double y)
{
return x - y * Math.Floor(x / y);
}
internal static class ModM {
public static Double Mod(Double x, Double y) => x - y * Math.Floor(x / y);
public static double ModLon(double x)
{
return Mod(x + Math.PI, 2 * Math.PI) - Math.PI;
}
public static Double ModLon(Double x) => Mod(x + Math.PI, 2 * Math.PI) - Math.PI;
public static double ModCrs(double x)
{
return Mod(x, 2 * Math.PI);
}
public static Double ModCrs(Double x) => Mod(x, 2 * Math.PI);
public static double ModLat(double x)
{
return Mod(x + Math.PI / 2, 2 * Math.PI) - Math.PI / 2;
}
public static Double ModLat(Double x) => Mod(x + Math.PI / 2, 2 * Math.PI) - Math.PI / 2;
}
/// <summary>
/// Earth Shape for Calculations.
/// </summary>
[Serializable]
public enum Shape
{
public enum Shape {
/// <summary>
/// Calculate as sphere (less accurate, more efficient).
/// </summary>

View File

@ -1,23 +1,21 @@
using System;
using System.ComponentModel;
namespace CoordinateSharp
{
namespace CoordinateSharp {
/// <summary>
/// Cartesian (X, Y, Z) Coordinate
/// </summary>
[Serializable]
public class Cartesian : INotifyPropertyChanged
{
public class Cartesian : INotifyPropertyChanged {
/// <summary>
/// Create a Cartesian Object
/// </summary>
/// <param name="c"></param>
public Cartesian(Coordinate c)
{
public Cartesian(Coordinate c) {
//formulas:
x = Math.Cos(c.Latitude.ToRadians()) * Math.Cos(c.Longitude.ToRadians());
y = Math.Cos(c.Latitude.ToRadians()) * Math.Sin(c.Longitude.ToRadians());
z = Math.Sin(c.Latitude.ToRadians());
this.x = Math.Cos(c.Latitude.ToRadians()) * Math.Cos(c.Longitude.ToRadians());
this.y = Math.Cos(c.Latitude.ToRadians()) * Math.Sin(c.Longitude.ToRadians());
this.z = Math.Sin(c.Latitude.ToRadians());
}
/// <summary>
/// Create a Cartesian Object
@ -25,69 +23,58 @@ namespace CoordinateSharp
/// <param name="xc">X</param>
/// <param name="yc">Y</param>
/// <param name="zc">Z</param>
public Cartesian(double xc, double yc, double zc)
{
public Cartesian(Double xc, Double yc, Double zc) {
//formulas:
x = xc;
y = yc;
z = zc;
this.x = xc;
this.y = yc;
this.z = zc;
}
/// <summary>
/// Updates Cartesian Values
/// </summary>
/// <param name="c"></param>
public void ToCartesian(Coordinate c)
{
x = Math.Cos(c.Latitude.ToRadians()) * Math.Cos(c.Longitude.ToRadians());
y = Math.Cos(c.Latitude.ToRadians()) * Math.Sin(c.Longitude.ToRadians());
z = Math.Sin(c.Latitude.ToRadians());
public void ToCartesian(Coordinate c) {
this.x = Math.Cos(c.Latitude.ToRadians()) * Math.Cos(c.Longitude.ToRadians());
this.y = Math.Cos(c.Latitude.ToRadians()) * Math.Sin(c.Longitude.ToRadians());
this.z = Math.Sin(c.Latitude.ToRadians());
}
private double x;
private double y;
private double z;
private Double x;
private Double y;
private Double z;
/// <summary>
/// X Coordinate
/// </summary>
public double X
{
get { return x; }
set
{
if(x != value)
{
x = value;
NotifyPropertyChanged("X");
public Double X {
get => this.x;
set {
if (this.x != value) {
this.x = value;
this.NotifyPropertyChanged("X");
}
}
}
/// <summary>
/// y Coordinate
/// </summary>
public double Y
{
get { return y; }
set
{
if (y != value)
{
y = value;
NotifyPropertyChanged("Y");
public Double Y {
get => this.y;
set {
if (this.y != value) {
this.y = value;
this.NotifyPropertyChanged("Y");
}
}
}
/// <summary>
/// Z Coordinate
/// </summary>
public double Z
{
get { return z; }
set
{
if (z != value)
{
z = value;
NotifyPropertyChanged("Z");
public Double Z {
get => this.z;
set {
if (this.z != value) {
this.z = value;
this.NotifyPropertyChanged("Z");
}
}
}
@ -98,14 +85,13 @@ namespace CoordinateSharp
/// <param name="y">Y</param>
/// <param name="z">Z</param>
/// <returns></returns>
public static Coordinate CartesianToLatLong(double x, double y, double z)
{
double lon = Math.Atan2(y, x);
double hyp = Math.Sqrt(x * x + y * y);
double lat = Math.Atan2(z, hyp);
public static Coordinate CartesianToLatLong(Double x, Double y, Double z) {
Double lon = Math.Atan2(y, x);
Double hyp = Math.Sqrt(x * x + y * y);
Double lat = Math.Atan2(z, hyp);
double Lat = lat * (180 / Math.PI);
double Lon = lon * (180 / Math.PI);
Double Lat = lat * (180 / Math.PI);
Double Lon = lon * (180 / Math.PI);
return new Coordinate(Lat, Lon);
}
/// <summary>
@ -113,18 +99,17 @@ namespace CoordinateSharp
/// </summary>
/// <param name="cart">Cartesian Coordinate</param>
/// <returns></returns>
public static Coordinate CartesianToLatLong(Cartesian cart)
{
double x = cart.X;
double y = cart.Y;
double z = cart.Z;
public static Coordinate CartesianToLatLong(Cartesian cart) {
Double x = cart.X;
Double y = cart.Y;
Double z = cart.Z;
double lon = Math.Atan2(y, x);
double hyp = Math.Sqrt(x * x + y * y);
double lat = Math.Atan2(z, hyp);
Double lon = Math.Atan2(y, x);
Double hyp = Math.Sqrt(x * x + y * y);
Double lat = Math.Atan2(z, hyp);
double Lat = lat * (180 / Math.PI);
double Lon = lon * (180 / Math.PI);
Double Lat = lat * (180 / Math.PI);
Double Lon = lon * (180 / Math.PI);
return new Coordinate(Lat, Lon);
}
/// <summary>
@ -132,10 +117,7 @@ namespace CoordinateSharp
/// </summary>
/// <returns>Cartesian Formatted Coordinate String</returns>
/// <returns>Values rounded to the 8th place</returns>
public override string ToString()
{
return Math.Round(x,8).ToString() + " " + Math.Round(y, 8).ToString() + " " + Math.Round(z, 8).ToString();
}
public override String ToString() => Math.Round(this.x, 8).ToString() + " " + Math.Round(this.y, 8).ToString() + " " + Math.Round(this.z, 8).ToString();
/// <summary>
/// Property changed event
/// </summary>
@ -144,10 +126,8 @@ namespace CoordinateSharp
/// Notify property changed
/// </summary>
/// <param name="propName">Property name</param>
public void NotifyPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
{
public void NotifyPropertyChanged(String propName) {
if (this.PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}

View File

@ -1,46 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
namespace CoordinateSharp
{
namespace CoordinateSharp {
/// <summary>
/// Earth Centered - Earth Fixed (X,Y,Z) Coordinate
/// </summary>
[Serializable]
public class ECEF : INotifyPropertyChanged
{
public class ECEF : INotifyPropertyChanged {
/// <summary>
/// Create an ECEF Object
/// </summary>
/// <param name="c">Coordinate</param>
public ECEF(Coordinate c)
{
equatorial_radius = 6378137.0;
inverse_flattening = 298.257223563;
WGS84();
geodetic_height = new Distance(0);
double[] ecef = LatLong_To_ECEF(c.Latitude.DecimalDegree, c.Longitude.DecimalDegree, geodetic_height.Kilometers);
x = ecef[0];
y = ecef[1];
z = ecef[2];
public ECEF(Coordinate c) {
this.equatorial_radius = 6378137.0;
this.inverse_flattening = 298.257223563;
this.WGS84();
this.geodetic_height = new Distance(0);
Double[] ecef = this.LatLong_To_ECEF(c.Latitude.DecimalDegree, c.Longitude.DecimalDegree, this.geodetic_height.Kilometers);
this.x = ecef[0];
this.y = ecef[1];
this.z = ecef[2];
}
/// <summary>
/// Create an ECEF Object
/// </summary>
/// <param name="c">Coordinate</param>
/// <param name="height">Coordinate</param>
public ECEF(Coordinate c, Distance height)
{
equatorial_radius = 6378137.0;
inverse_flattening = 298.257223563;
WGS84();
geodetic_height = height;
double[] ecef = LatLong_To_ECEF(c.Latitude.DecimalDegree, c.Longitude.DecimalDegree, geodetic_height.Kilometers);
x = ecef[0];
y = ecef[1];
z = ecef[2];
public ECEF(Coordinate c, Distance height) {
this.equatorial_radius = 6378137.0;
this.inverse_flattening = 298.257223563;
this.WGS84();
this.geodetic_height = height;
Double[] ecef = this.LatLong_To_ECEF(c.Latitude.DecimalDegree, c.Longitude.DecimalDegree, this.geodetic_height.Kilometers);
this.x = ecef[0];
this.y = ecef[1];
this.z = ecef[2];
}
/// <summary>
/// Create an ECEF Object
@ -48,106 +42,89 @@ namespace CoordinateSharp
/// <param name="xc">X</param>
/// <param name="yc">Y</param>
/// <param name="zc">Z</param>
public ECEF(double xc, double yc, double zc)
{
equatorial_radius = 6378137.0;
inverse_flattening = 298.257223563;
WGS84();
geodetic_height = new Distance(0);
x = xc;
y = yc;
z = zc;
public ECEF(Double xc, Double yc, Double zc) {
this.equatorial_radius = 6378137.0;
this.inverse_flattening = 298.257223563;
this.WGS84();
this.geodetic_height = new Distance(0);
this.x = xc;
this.y = yc;
this.z = zc;
}
/// <summary>
/// Updates ECEF Values
/// </summary>
/// <param name="c">Coordinate</param>
public void ToECEF(Coordinate c)
{
equatorial_radius = 6378137.0;
inverse_flattening = 298.257223563;
WGS84();
double[] ecef = LatLong_To_ECEF(c.Latitude.DecimalDegree, c.Longitude.DecimalDegree, geodetic_height.Kilometers);
x = ecef[0];
y = ecef[1];
z = ecef[2];
public void ToECEF(Coordinate c) {
this.equatorial_radius = 6378137.0;
this.inverse_flattening = 298.257223563;
this.WGS84();
Double[] ecef = this.LatLong_To_ECEF(c.Latitude.DecimalDegree, c.Longitude.DecimalDegree, this.geodetic_height.Kilometers);
this.x = ecef[0];
this.y = ecef[1];
this.z = ecef[2];
}
//Globals for calucations
private double EARTH_A;
private double EARTH_B;
private double EARTH_F;
private double EARTH_Ecc;
private double EARTH_Esq;
private Double EARTH_A;
private Double EARTH_B;
//private Double EARTH_F;
private Double EARTH_Ecc;
private Double EARTH_Esq;
//ECEF Values
private double x;
private double y;
private double z;
private Double x;
private Double y;
private Double z;
private Distance geodetic_height;
//Datum
internal double equatorial_radius;
internal double inverse_flattening;
internal Double equatorial_radius;
internal Double inverse_flattening;
/// <summary>
/// Datum Equatorial Radius / Semi Major Axis
/// </summary>
public double Equatorial_Radius
{
get { return equatorial_radius; }
}
public Double Equatorial_Radius => this.equatorial_radius;
/// <summary>
/// Datum Flattening
/// </summary>
public double Inverse_Flattening
{
get { return inverse_flattening; }
}
public Double Inverse_Flattening => this.inverse_flattening;
/// <summary>
/// X Coordinate
/// </summary>
public double X
{
get { return x; }
set
{
if (x != value)
{
x = value;
NotifyPropertyChanged("X");
public Double X {
get => this.x;
set {
if (this.x != value) {
this.x = value;
this.NotifyPropertyChanged("X");
}
}
}
/// <summary>
/// y Coordinate
/// </summary>
public double Y
{
get { return y; }
set
{
if (y != value)
{
y = value;
NotifyPropertyChanged("Y");
public Double Y {
get => this.y;
set {
if (this.y != value) {
this.y = value;
this.NotifyPropertyChanged("Y");
}
}
}
/// <summary>
/// Z Coordinate
/// </summary>
public double Z
{
get { return z; }
set
{
if (z != value)
{
z = value;
NotifyPropertyChanged("Z");
public Double Z {
get => this.z;
set {
if (this.z != value) {
this.z = value;
this.NotifyPropertyChanged("Z");
}
}
}
@ -157,15 +134,12 @@ namespace CoordinateSharp
/// Used for converting Lat Long / ECEF.
/// Default value is 0. Adjust as needed.
/// </summary>
public Distance GeoDetic_Height
{
get { return geodetic_height; }
internal set
{
if (geodetic_height != value)
{
geodetic_height = value;
NotifyPropertyChanged("Height");
public Distance GeoDetic_Height {
get => this.geodetic_height;
internal set {
if (this.geodetic_height != value) {
this.geodetic_height = value;
this.NotifyPropertyChanged("Height");
}
}
@ -177,13 +151,12 @@ namespace CoordinateSharp
/// </summary>
/// <param name="c">Coordinate</param>
/// <param name="dist">Height</param>
public void Set_GeoDetic_Height(Coordinate c, Distance dist)
{
geodetic_height = dist;
double[] values = LatLong_To_ECEF(c.Latitude.DecimalDegree, c.Longitude.DecimalDegree, dist.Kilometers);
x = values[0];
y = values[1];
z = values[2];
public void Set_GeoDetic_Height(Coordinate c, Distance dist) {
this.geodetic_height = dist;
Double[] values = this.LatLong_To_ECEF(c.Latitude.DecimalDegree, c.Longitude.DecimalDegree, dist.Kilometers);
this.x = values[0];
this.y = values[1];
this.z = values[2];
}
@ -194,14 +167,14 @@ namespace CoordinateSharp
/// <param name="y">Y</param>
/// <param name="z">Z</param>
/// <returns>Coordinate</returns>
public static Coordinate ECEFToLatLong(double x, double y, double z)
{
public static Coordinate ECEFToLatLong(Double x, Double y, Double z) {
ECEF ecef = new ECEF(x, y, z);
double[] values = ecef.ECEF_To_LatLong(x, y, z);
ecef.geodetic_height =new Distance(values[2]);
Double[] values = ecef.ECEF_To_LatLong(x, y, z);
ecef.geodetic_height = new Distance(values[2]);
Coordinate c = new Coordinate(values[0], values[1]);
c.ECEF = ecef;
Coordinate c = new Coordinate(values[0], values[1]) {
ECEF = ecef
};
return c;
}
/// <summary>
@ -209,12 +182,11 @@ namespace CoordinateSharp
/// </summary>
/// <param name="ecef">ECEF Coordinate</param>
/// <returns>Coordinate</returns>
public static Coordinate ECEFToLatLong(ECEF ecef)
{
double[] values = ecef.ECEF_To_LatLong(ecef.X, ecef.Y, ecef.Z);
public static Coordinate ECEFToLatLong(ECEF ecef) {
Double[] values = ecef.ECEF_To_LatLong(ecef.X, ecef.Y, ecef.Z);
Coordinate c = new Coordinate(values[0], values[1]);
Distance height = new Distance(values[2]);
//Distance height = new Distance(values[2]);
ecef.geodetic_height = new Distance(values[2]);
c.ECEF = ecef;
@ -226,10 +198,7 @@ namespace CoordinateSharp
/// </summary>
/// <returns>ECEF Formatted Coordinate String</returns>
/// <returns>Values rounded to the 3rd place</returns>
public override string ToString()
{
return Math.Round(x, 3).ToString() + " km, " + Math.Round(y, 3).ToString() + " km, " + Math.Round(z, 3).ToString() + " km";
}
public override String ToString() => Math.Round(this.x, 3).ToString() + " km, " + Math.Round(this.y, 3).ToString() + " km, " + Math.Round(this.z, 3).ToString() + " km";
/// <summary>
/// Property changed event
@ -239,25 +208,18 @@ namespace CoordinateSharp
/// Notify property changed
/// </summary>
/// <param name="propName">Property name</param>
public void NotifyPropertyChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
public void NotifyPropertyChanged(String propName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
//CONVERSION LOGIC
/// <summary>
/// Initialize EARTH global variables based on the Datum
/// </summary>
private void WGS84()
{
double wgs84a = equatorial_radius / 1000;
double wgs84f = 1.0 / inverse_flattening;
double wgs84b = wgs84a * (1.0 - wgs84f);
private void WGS84() {
Double wgs84a = this.equatorial_radius / 1000;
Double wgs84f = 1.0 / this.inverse_flattening;
Double wgs84b = wgs84a * (1.0 - wgs84f);
EarthCon(wgs84a, wgs84b);
this.EarthCon(wgs84a, wgs84b);
}
/// <summary>
@ -265,17 +227,16 @@ namespace CoordinateSharp
/// </summary>
/// <param name="a">a</param>
/// <param name="b">b</param>
private void EarthCon(double a, double b)
{
double f = 1 - b / a;
double eccsq = 1 - b * b / (a * a);
double ecc = Math.Sqrt(eccsq);
private void EarthCon(Double a, Double b) {
//Double f = 1 - b / a;
Double eccsq = 1 - b * b / (a * a);
Double ecc = Math.Sqrt(eccsq);
EARTH_A = a;
EARTH_B = b;
EARTH_F = f;
EARTH_Ecc = ecc;
EARTH_Esq = eccsq;
this.EARTH_A = a;
this.EARTH_B = b;
//this.EARTH_F = f;
this.EARTH_Ecc = ecc;
this.EARTH_Esq = eccsq;
}
/// <summary>
@ -283,39 +244,38 @@ namespace CoordinateSharp
/// </summary>
/// <param name="lat">Latitude in degres</param>
/// <returns>double[]</returns>
private double[] radcur(double lat)
{
double[] rrnrm = new double[3];
private Double[] Radcur(Double lat) {
Double[] rrnrm = new Double[3];
double dtr = Math.PI / 180.0;
Double dtr = Math.PI / 180.0;
double a = EARTH_A;
double b = EARTH_B;
Double a = this.EARTH_A;
Double b = this.EARTH_B;
double asq = a * a;
double bsq = b * b;
double eccsq = 1 - bsq / asq;
double ecc = Math.Sqrt(eccsq);
Double asq = a * a;
Double bsq = b * b;
Double eccsq = 1 - bsq / asq;
//Double ecc = Math.Sqrt(eccsq);
double clat = Math.Cos(dtr * lat);
double slat = Math.Sin(dtr * lat);
Double clat = Math.Cos(dtr * lat);
Double slat = Math.Sin(dtr * lat);
double dsq = 1.0 - eccsq * slat * slat;
double d = Math.Sqrt(dsq);
Double dsq = 1.0 - eccsq * slat * slat;
Double d = Math.Sqrt(dsq);
double rn = a / d;
double rm = rn * (1.0 - eccsq) / dsq;
Double rn = a / d;
Double rm = rn * (1.0 - eccsq) / dsq;
double rho = rn * clat;
double z = (1.0 - eccsq) * rn * slat;
double rsq = rho * rho + z * z;
double r = Math.Sqrt(rsq);
Double rho = rn * clat;
Double z = (1.0 - eccsq) * rn * slat;
Double rsq = rho * rho + z * z;
Double r = Math.Sqrt(rsq);
rrnrm[0] = r;
rrnrm[1] = rn;
rrnrm[2] = rm;
return (rrnrm);
return rrnrm;
}
@ -324,11 +284,10 @@ namespace CoordinateSharp
/// </summary>
/// <param name="lat">Latidude in degrees</param>
/// <returns>double</returns>
private double rearth(double lat)
{
double[] rrnrm;
rrnrm = radcur(lat);
double r = rrnrm[0];
private Double Rearth(Double lat) {
Double[] rrnrm;
rrnrm = this.Radcur(lat);
Double r = rrnrm[0];
return r;
}
@ -339,30 +298,29 @@ namespace CoordinateSharp
/// <param name="flatgc">Geocentric latitude</param>
/// <param name="altkm">Altitude in KM</param>
/// <returns>double</returns>
private double gc2gd(double flatgc, double altkm)
{
var dtr = Math.PI / 180.0;
var rtd = 1 / dtr;
private Double Gc2gd(Double flatgc, Double altkm) {
Double dtr = Math.PI / 180.0;
Double rtd = 1 / dtr;
double ecc = EARTH_Ecc;
double esq = ecc * ecc;
Double ecc = this.EARTH_Ecc;
Double esq = ecc * ecc;
//approximation by stages
//1st use gc-lat as if is gd, then correct alt dependence
double altnow = altkm;
Double altnow = altkm;
double[] rrnrm = radcur(flatgc);
double rn = rrnrm[1];
Double[] rrnrm = this.Radcur(flatgc);
Double rn = rrnrm[1];
double ratio = 1 - esq * rn / (rn + altnow);
Double ratio = 1 - esq * rn / (rn + altnow);
double tlat = Math.Tan(dtr * flatgc) / ratio;
double flatgd = rtd * Math.Atan(tlat);
Double tlat = Math.Tan(dtr * flatgc) / ratio;
Double flatgd = rtd * Math.Atan(tlat);
//now use this approximation for gd-lat to get rn etc.
rrnrm = radcur(flatgd);
rrnrm = this.Radcur(flatgd);
rn = rrnrm[1];
ratio = 1 - esq * rn / (rn + altnow);
@ -378,26 +336,25 @@ namespace CoordinateSharp
/// <param name="flatgd">Geodetic latitude tp geocentric latitide</param>
/// <param name="altkm">Altitude in KM</param>
/// <returns>double</returns>
private double gd2gc(double flatgd, double altkm)
{
double dtr = Math.PI / 180.0;
double rtd = 1 / dtr;
/*private Double gd2gc(Double flatgd, Double altkm) {
Double dtr = Math.PI / 180.0;
Double rtd = 1 / dtr;
double ecc = EARTH_Ecc;
double esq = ecc * ecc;
Double ecc = this.EARTH_Ecc;
Double esq = ecc * ecc;
double altnow = altkm;
Double altnow = altkm;
double[] rrnrm = radcur(flatgd);
double rn = rrnrm[1];
Double[] rrnrm = this.Radcur(flatgd);
Double rn = rrnrm[1];
double ratio = 1 - esq * rn / (rn + altnow);
Double ratio = 1 - esq * rn / (rn + altnow);
double tlat = Math.Tan(dtr * flatgd) * ratio;
double flatgc = rtd * Math.Atan(tlat);
Double tlat = Math.Tan(dtr * flatgd) * ratio;
Double flatgc = rtd * Math.Atan(tlat);
return flatgc;
}
}*/
/// <summary>
/// Converts lat / long to east, north, up vectors
@ -405,16 +362,15 @@ namespace CoordinateSharp
/// <param name="flat">Latitude</param>
/// <param name="flon">Longitude</param>
/// <returns>Array[] of double[]</returns>
private Array[] llenu(double flat, double flon)
{
double clat, slat, clon, slon;
double[] ee = new double[3];
double[] en = new double[3];
double[] eu = new double[3];
/*private Array[] llenu(Double flat, Double flon) {
Double clat, slat, clon, slon;
Double[] ee = new Double[3];
Double[] en = new Double[3];
Double[] eu = new Double[3];
Array[] enu = new Array[3];
double dtr = Math.PI / 180.0;
Double dtr = Math.PI / 180.0;
clat = Math.Cos(dtr * flat);
slat = Math.Sin(dtr * flat);
@ -438,7 +394,7 @@ namespace CoordinateSharp
enu[2] = eu;
return enu;
}
}*/
/// <summary>
/// Gets ECEF vector in KM
@ -447,27 +403,26 @@ namespace CoordinateSharp
/// <param name="longi">Longitude</param>
/// <param name="altkm">Altitude in KM</param>
/// <returns>double[]</returns>
private double[] LatLong_To_ECEF(double lat, double longi, double altkm)
{
double dtr = Math.PI / 180.0;
private Double[] LatLong_To_ECEF(Double lat, Double longi, Double altkm) {
Double dtr = Math.PI / 180.0;
double clat = Math.Cos(dtr * lat);
double slat = Math.Sin(dtr * lat);
double clon = Math.Cos(dtr * longi);
double slon = Math.Sin(dtr * longi);
Double clat = Math.Cos(dtr * lat);
Double slat = Math.Sin(dtr * lat);
Double clon = Math.Cos(dtr * longi);
Double slon = Math.Sin(dtr * longi);
double[] rrnrm = radcur(lat);
double rn = rrnrm[1];
double re = rrnrm[0];
Double[] rrnrm = this.Radcur(lat);
Double rn = rrnrm[1];
//Double re = rrnrm[0];
double ecc = EARTH_Ecc;
double esq = ecc * ecc;
Double ecc = this.EARTH_Ecc;
Double esq = ecc * ecc;
double x = (rn + altkm) * clat * clon;
double y = (rn + altkm) * clat * slon;
double z = ((1 - esq) * rn + altkm) * slat;
Double x = (rn + altkm) * clat * clon;
Double y = (rn + altkm) * clat * slon;
Double z = ((1 - esq) * rn + altkm) * slat;
double[] xvec = new double[3];
Double[] xvec = new Double[3];
xvec[0] = x;
xvec[1] = y;
@ -483,39 +438,34 @@ namespace CoordinateSharp
/// <param name="y"></param>
/// <param name="z"></param>
/// <returns></returns>
private double[] ECEF_To_LatLong(double x, double y, double z)
{
var dtr = Math.PI / 180.0;
private Double[] ECEF_To_LatLong(Double x, Double y, Double z) {
Double dtr = Math.PI / 180.0;
double[] rrnrm = new double[3];
double[] llhvec = new double[3];
double slat, tangd, flatn, dlat, clat;
double flat;
double altkm;
//_ = new Double[3];
Double[] llhvec = new Double[3];
Double slat, tangd, flatn, dlat, clat;
Double flat;
Double altkm;
double esq = EARTH_Esq;
Double esq = this.EARTH_Esq;
double rp = Math.Sqrt(x * x + y * y + z * z);
Double rp = Math.Sqrt(x * x + y * y + z * z);
double flatgc = Math.Asin(z / rp) / dtr;
double flon;
double testval = Math.Abs(x) + Math.Abs(y);
if (testval < 1.0e-10)
{ flon = 0.0; }
else
{ flon = Math.Atan2(y, x) / dtr; }
if (flon < 0.0) { flon = flon + 360.0; }
Double flatgc = Math.Asin(z / rp) / dtr;
Double flon;
Double testval = Math.Abs(x) + Math.Abs(y);
flon = testval < 1.0e-10 ? 0.0 : Math.Atan2(y, x) / dtr;
if (flon < 0.0) { flon += 360.0; }
double p = Math.Sqrt(x * x + y * y);
Double p = Math.Sqrt(x * x + y * y);
//Pole special case
if (p < 1.0e-10)
{
if (p < 1.0e-10) {
flat = 90.0;
if (z < 0.0) { flat = -90.0; }
altkm = rp - rearth(flat);
altkm = rp - this.Rearth(flat);
llhvec[0] = flat;
llhvec[1] = flon;
llhvec[2] = altkm;
@ -526,15 +476,14 @@ namespace CoordinateSharp
//first iteration, use flatgc to get altitude
//and alt needed to convert gc to gd lat.
double rnow = rearth(flatgc);
Double rnow = this.Rearth(flatgc);
altkm = rp - rnow;
flat = gc2gd(flatgc, altkm);
flat = this.Gc2gd(flatgc, altkm);
rrnrm = radcur(flat);
double rn = rrnrm[1];
Double[] rrnrm = this.Radcur(flat);
Double rn = rrnrm[1];
for (int kount = 0; kount < 5; kount++)
{
for (Int32 kount = 0; kount < 5; kount++) {
slat = Math.Sin(dtr * flat);
tangd = (z + rn * esq * slat) / p;
flatn = Math.Atan(tangd) / dtr;
@ -543,17 +492,17 @@ namespace CoordinateSharp
flat = flatn;
clat = Math.Cos(dtr * flat);
rrnrm = radcur(flat);
rrnrm = this.Radcur(flat);
rn = rrnrm[1];
altkm = (p / clat) - rn;
altkm = p / clat - rn;
if (Math.Abs(dlat) < 1.0e-12) { break; }
}
//CONVERTER WORKS IN E LAT ONLY, IF E LAT > 180 LAT IS WEST SO IT MUCST BE CONVERTED TO Decimal
if (flon > 180) { flon = flon - 360; }
if (flon > 180) { flon -= 360; }
llhvec[0] = flat;
llhvec[1] = flon;
llhvec[2] = altkm;

View File

@ -1,65 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CoordinateSharp
{
namespace CoordinateSharp {
/// <summary>
/// Turn on/off eager loading of certain properties.
/// </summary>
[Serializable]
public class EagerLoad
{
public class EagerLoad {
/// <summary>
/// Create an EagerLoad object
/// </summary>
public EagerLoad()
{
Celestial = true;
UTM_MGRS = true;
Cartesian = true;
ECEF = true;
public EagerLoad() {
this.Celestial = true;
this.UTM_MGRS = true;
this.Cartesian = true;
this.ECEF = true;
}
/// <summary>
/// Create an EagerLoad object with all options on or off
/// </summary>
/// <param name="isOn">Turns EagerLoad on or off</param>
public EagerLoad(bool isOn)
{
Celestial = isOn;
UTM_MGRS = isOn;
Cartesian = isOn;
ECEF = isOn;
public EagerLoad(Boolean isOn) {
this.Celestial = isOn;
this.UTM_MGRS = isOn;
this.Cartesian = isOn;
this.ECEF = isOn;
}
/// <summary>
/// Create an EagerLoad object with only the specified flag options turned on.
/// </summary>
/// <param name="et">EagerLoadType</param>
public EagerLoad(EagerLoadType et)
{
Cartesian = false;
Celestial = false;
UTM_MGRS = false;
ECEF = false;
public EagerLoad(EagerLoadType et) {
this.Cartesian = false;
this.Celestial = false;
this.UTM_MGRS = false;
this.ECEF = false;
if (et.HasFlag(EagerLoadType.Cartesian))
{
Cartesian = true;
if (et.HasFlag(EagerLoadType.Cartesian)) {
this.Cartesian = true;
}
if (et.HasFlag(EagerLoadType.Celestial))
{
Celestial = true;
if (et.HasFlag(EagerLoadType.Celestial)) {
this.Celestial = true;
}
if (et.HasFlag(EagerLoadType.UTM_MGRS))
{
UTM_MGRS = true;
if (et.HasFlag(EagerLoadType.UTM_MGRS)) {
this.UTM_MGRS = true;
}
if (et.HasFlag(EagerLoadType.ECEF))
{
ECEF = true;
if (et.HasFlag(EagerLoadType.ECEF)) {
this.ECEF = true;
}
}
@ -68,8 +56,7 @@ namespace CoordinateSharp
/// </summary>
/// <param name="et">EagerLoadType</param>
/// <returns>EagerLoad</returns>
public static EagerLoad Create(EagerLoadType et)
{
public static EagerLoad Create(EagerLoadType et) {
EagerLoad el = new EagerLoad(et);
return el;
}
@ -77,27 +64,26 @@ namespace CoordinateSharp
/// <summary>
/// Eager load celestial information.
/// </summary>
public bool Celestial { get; set; }
public Boolean Celestial { get; set; }
/// <summary>
/// Eager load UTM and MGRS information
/// </summary>
public bool UTM_MGRS { get; set; }
public Boolean UTM_MGRS { get; set; }
/// <summary>
/// Eager load Cartesian information
/// </summary>
public bool Cartesian { get; set; }
public Boolean Cartesian { get; set; }
/// <summary>
/// Eager load ECEF information
/// </summary>
public bool ECEF { get; set; }
public Boolean ECEF { get; set; }
}
/// <summary>
/// EagerLoad Enumerator
/// </summary>
[Serializable]
[Flags]
public enum EagerLoadType
{
public enum EagerLoadType {
/// <summary>
/// UTM and MGRS
/// </summary>

View File

@ -1,31 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CoordinateSharp
{
namespace CoordinateSharp {
/// <summary>
/// Coordinate formatting options for a Coordinate object.
/// </summary>
[Serializable]
public class CoordinateFormatOptions
{
public class CoordinateFormatOptions {
/// <summary>
/// Set default values with the constructor.
/// </summary>
public CoordinateFormatOptions()
{
Format = CoordinateFormatType.Degree_Minutes_Seconds;
Round = 3;
Display_Leading_Zeros = false;
Display_Trailing_Zeros = false;
Display_Symbols = true;
Display_Degree_Symbol = true;
Display_Minute_Symbol = true;
Display_Seconds_Symbol = true;
Display_Hyphens = false;
Position_First = true;
public CoordinateFormatOptions() {
this.Format = CoordinateFormatType.Degree_Minutes_Seconds;
this.Round = 3;
this.Display_Leading_Zeros = false;
this.Display_Trailing_Zeros = false;
this.Display_Symbols = true;
this.Display_Degree_Symbol = true;
this.Display_Minute_Symbol = true;
this.Display_Seconds_Symbol = true;
this.Display_Hyphens = false;
this.Position_First = true;
}
/// <summary>
/// Coordinate format type.
@ -34,47 +28,46 @@ namespace CoordinateSharp
/// <summary>
/// Rounds Coordinates to the set value.
/// </summary>
public int Round { get; set; }
public Int32 Round { get; set; }
/// <summary>
/// Displays leading zeros.
/// </summary>
public bool Display_Leading_Zeros { get; set; }
public Boolean Display_Leading_Zeros { get; set; }
/// <summary>
/// Display trailing zeros.
/// </summary>
public bool Display_Trailing_Zeros { get; set; }
public Boolean Display_Trailing_Zeros { get; set; }
/// <summary>
/// Allow symbols to display.
/// </summary>
public bool Display_Symbols { get; set; }
public Boolean Display_Symbols { get; set; }
/// <summary>
/// Display degree symbols.
/// </summary>
public bool Display_Degree_Symbol { get; set; }
public Boolean Display_Degree_Symbol { get; set; }
/// <summary>
/// Display minute symbols.
/// </summary>
public bool Display_Minute_Symbol { get; set; }
public Boolean Display_Minute_Symbol { get; set; }
/// <summary>
/// Display secons symbol.
/// </summary>
public bool Display_Seconds_Symbol { get; set; }
public Boolean Display_Seconds_Symbol { get; set; }
/// <summary>
/// Display hyphens between values.
/// </summary>
public bool Display_Hyphens { get; set; }
public Boolean Display_Hyphens { get; set; }
/// <summary>
/// Show coordinate position first.
/// Will show last if set 'false'.
/// </summary>
public bool Position_First { get; set; }
public Boolean Position_First { get; set; }
}
/// <summary>
/// Coordinate Format Types.
/// </summary>
[Serializable]
public enum CoordinateFormatType
{
public enum CoordinateFormatType {
/// <summary>
/// Decimal Degree Format
/// </summary>

View File

@ -1,17 +1,15 @@
using System;
using System.Linq;
using System.Diagnostics;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
namespace CoordinateSharp
{
namespace CoordinateSharp {
/// <summary>
/// Military Grid Reference System (MGRS). Uses the WGS 84 Datum.
/// Relies upon values from the UniversalTransverseMercator class
/// </summary>
[Serializable]
public class MilitaryGridReferenceSystem : INotifyPropertyChanged
{
public class MilitaryGridReferenceSystem : INotifyPropertyChanged {
/// <summary>
/// Create an MGRS object with WGS84 datum
/// </summary>
@ -20,24 +18,23 @@ namespace CoordinateSharp
/// <param name="d">Digraph</param>
/// <param name="e">Easting</param>
/// <param name="n">Northing</param>
public MilitaryGridReferenceSystem(string latz, int longz, string d, double e, double n)
{
string digraphLettersE = "ABCDEFGHJKLMNPQRSTUVWXYZ";
string digraphLettersN = "ABCDEFGHJKLMNPQRSTUV";
public MilitaryGridReferenceSystem(String latz, Int32 longz, String d, Double e, Double n) {
String digraphLettersE = "ABCDEFGHJKLMNPQRSTUVWXYZ";
String digraphLettersN = "ABCDEFGHJKLMNPQRSTUV";
if (longz < 1 || longz > 60) { Debug.WriteLine("Longitudinal zone out of range", "UTM longitudinal zones must be between 1-60."); }
if (!Verify_Lat_Zone(latz)) { throw new ArgumentException("Latitudinal zone invalid", "UTM latitudinal zone was unrecognized."); }
if (!this.Verify_Lat_Zone(latz)) { throw new ArgumentException("Latitudinal zone invalid", "UTM latitudinal zone was unrecognized."); }
if (n < 0 || n > 10000000) { throw new ArgumentOutOfRangeException("Northing out of range", "Northing must be between 0-10,000,000."); }
if (d.Count() < 2 || d.Count() > 2) { throw new ArgumentException("Digraph invalid", "MGRS Digraph was unrecognized."); }
if (digraphLettersE.ToCharArray().ToList().Where(x => x.ToString() == d.ToUpper()[0].ToString()).Count() == 0) { throw new ArgumentException("Digraph invalid", "MGRS Digraph was unrecognized."); }
if (digraphLettersN.ToCharArray().ToList().Where(x => x.ToString() == d.ToUpper()[1].ToString()).Count() == 0) { throw new ArgumentException("Digraph invalid", "MGRS Digraph was unrecognized."); }
latZone = latz;
longZone = longz;
digraph = d;
easting = e;
northing = n;
this.LatZone = latz;
this.LongZone = longz;
this.Digraph = d;
this.Easting = e;
this.Northing = n;
//WGS84
equatorialRadius = 6378137.0;
inverseFlattening = 298.257223563;
this.equatorialRadius = 6378137.0;
this.inverseFlattening = 298.257223563;
}
/// <summary>
@ -50,132 +47,89 @@ namespace CoordinateSharp
/// <param name="n">Northing</param>
/// <param name="rad">Equatorial Radius</param>
/// <param name="flt">Inverse Flattening</param>
public MilitaryGridReferenceSystem(string latz, int longz, string d, double e, double n,double rad, double flt)
{
string digraphLettersE = "ABCDEFGHJKLMNPQRSTUVWXYZ";
string digraphLettersN = "ABCDEFGHJKLMNPQRSTUV";
public MilitaryGridReferenceSystem(String latz, Int32 longz, String d, Double e, Double n, Double rad, Double flt) {
String digraphLettersE = "ABCDEFGHJKLMNPQRSTUVWXYZ";
String digraphLettersN = "ABCDEFGHJKLMNPQRSTUV";
if (longz < 1 || longz > 60) { Debug.WriteLine("Longitudinal zone out of range", "UTM longitudinal zones must be between 1-60."); }
if (!Verify_Lat_Zone(latz)) { throw new ArgumentException("Latitudinal zone invalid", "UTM latitudinal zone was unrecognized."); }
if (!this.Verify_Lat_Zone(latz)) { throw new ArgumentException("Latitudinal zone invalid", "UTM latitudinal zone was unrecognized."); }
if (n < 0 || n > 10000000) { throw new ArgumentOutOfRangeException("Northing out of range", "Northing must be between 0-10,000,000."); }
if (d.Count() < 2 || d.Count() > 2) { throw new ArgumentException("Digraph invalid", "MGRS Digraph was unrecognized."); }
if (digraphLettersE.ToCharArray().ToList().Where(x => x.ToString() == d.ToUpper()[0].ToString()).Count() == 0) { throw new ArgumentException("Digraph invalid", "MGRS Digraph was unrecognized."); }
if (digraphLettersN.ToCharArray().ToList().Where(x => x.ToString() == d.ToUpper()[1].ToString()).Count() == 0) { throw new ArgumentException("Digraph invalid", "MGRS Digraph was unrecognized."); }
latZone = latz;
longZone = longz;
digraph = d;
easting = e;
northing = n;
this.LatZone = latz;
this.LongZone = longz;
this.Digraph = d;
this.Easting = e;
this.Northing = n;
equatorialRadius = rad;
inverseFlattening = flt;
this.equatorialRadius = rad;
this.inverseFlattening = flt;
}
private double equatorialRadius;
private double inverseFlattening;
private string latZone;
private int longZone;
private double easting;
private double northing;
private string digraph;
private Double equatorialRadius;
private Double inverseFlattening;
private bool withinCoordinateSystemBounds=true;
private bool Verify_Lat_Zone(string l)
{
if (LatZones.longZongLetters.Where(x => x == l.ToUpper()).Count() != 1)
{
return false;
}
return true;
}
private Boolean Verify_Lat_Zone(String l) => LatZones.longZongLetters.Where(x => x == l.ToUpper()).Count() == 1;
/// <summary>
/// MGRS Zone Letter
/// </summary>
public string LatZone
{
get { return latZone; }
}
public String LatZone { get; private set; }
/// <summary>
/// MGRS Zone Number
/// </summary>
public int LongZone
{
get { return longZone; }
}
public Int32 LongZone { get; private set; }
/// <summary>
/// MGRS Easting
/// </summary>
public double Easting
{
get { return easting; }
}
public Double Easting { get; private set; }
/// <summary>
/// MGRS Northing
/// </summary>
public double Northing
{
get { return northing; }
}
public Double Northing { get; private set; }
/// <summary>
/// MGRS Digraph
/// </summary>
public string Digraph
{
get { return digraph; }
}
public String Digraph { get; private set; }
/// <summary>
/// Is MGRS conversion within the coordinate system's accurate boundaries after conversion from Lat/Long.
/// </summary>
public bool WithinCoordinateSystemBounds
{
get { return withinCoordinateSystemBounds; }
}
public Boolean WithinCoordinateSystemBounds { get; private set; } = true;
internal MilitaryGridReferenceSystem(UniversalTransverseMercator utm)
{
ToMGRS(utm);
}
internal void ToMGRS(UniversalTransverseMercator utm)
{
internal MilitaryGridReferenceSystem(UniversalTransverseMercator utm) => this.ToMGRS(utm);
internal void ToMGRS(UniversalTransverseMercator utm) {
Digraphs digraphs = new Digraphs();
string digraph1 = digraphs.getDigraph1(utm.LongZone, utm.Easting);
string digraph2 = digraphs.getDigraph2(utm.LongZone, utm.Northing);
String digraph1 = digraphs.GetDigraph1(utm.LongZone, utm.Easting);
String digraph2 = digraphs.GetDigraph2(utm.LongZone, utm.Northing);
digraph = digraph1 + digraph2;
latZone = utm.LatZone;
longZone = utm.LongZone;
this.Digraph = digraph1 + digraph2;
this.LatZone = utm.LatZone;
this.LongZone = utm.LongZone;
//String easting = String.valueOf((int)_easting);
string e = ((int)utm.Easting).ToString();
if (e.Length < 5)
{
e = "00000" + ((int)utm.Easting).ToString();
String e = ((Int32)utm.Easting).ToString();
if (e.Length < 5) {
e = "00000" + ((Int32)utm.Easting).ToString();
}
e = e.Substring(e.Length - 5);
easting = Convert.ToInt32(e);
this.Easting = Convert.ToInt32(e);
string n = ((int)utm.Northing).ToString();
if (n.Length < 5)
{
n = "0000" + ((int)utm.Northing).ToString();
String n = ((Int32)utm.Northing).ToString();
if (n.Length < 5) {
n = "0000" + ((Int32)utm.Northing).ToString();
}
n = n.Substring(n.Length - 5);
northing = Convert.ToInt32(n);
equatorialRadius = utm.equatorial_radius;
inverseFlattening = utm.inverse_flattening;
this.Northing = Convert.ToInt32(n);
this.equatorialRadius = utm.equatorial_radius;
this.inverseFlattening = utm.inverse_flattening;
withinCoordinateSystemBounds = utm.WithinCoordinateSystemBounds;
this.WithinCoordinateSystemBounds = utm.WithinCoordinateSystemBounds;
}
/// <summary>
@ -183,81 +137,64 @@ namespace CoordinateSharp
/// </summary>
/// <param name="mgrs">MilitaryGridReferenceSystem</param>
/// <returns>Coordinate object</returns>
public static Coordinate MGRStoLatLong(MilitaryGridReferenceSystem mgrs)
{
string latz = mgrs.LatZone;
string digraph = mgrs.Digraph;
public static Coordinate MGRStoLatLong(MilitaryGridReferenceSystem mgrs) {
String latz = mgrs.LatZone;
String digraph = mgrs.Digraph;
char eltr = digraph[0];
char nltr = digraph[1];
Char eltr = digraph[0];
Char nltr = digraph[1];
string digraphLettersE = "ABCDEFGHJKLMNPQRSTUVWXYZ";
string digraphLettersN = "ABCDEFGHJKLMNPQRSTUV";
string digraphLettersAll="";
for (int lt = 1; lt < 25; lt++)
{
String digraphLettersE = "ABCDEFGHJKLMNPQRSTUVWXYZ";
//String digraphLettersN = "ABCDEFGHJKLMNPQRSTUV";
String digraphLettersAll = "";
for (Int32 lt = 1; lt < 25; lt++) {
digraphLettersAll += "ABCDEFGHJKLMNPQRSTUV";
}
var eidx = digraphLettersE.IndexOf(eltr);
var nidx = digraphLettersN.IndexOf(nltr);
if (mgrs.LongZone / 2.0 == Math.Floor(mgrs.LongZone / 2.0))
{
nidx -= 5; // correction for even numbered zones
Int32 eidx = digraphLettersE.IndexOf(eltr);
//Int32 nidx = digraphLettersN.IndexOf(nltr);
if (mgrs.LongZone / 2.0 == Math.Floor(mgrs.LongZone / 2.0)) {
//nidx -= 5; // correction for even numbered zones
}
var ebase = 100000 * (1 + eidx - 8 * Math.Floor(Convert.ToDouble(eidx) / 8));
var latBand = digraphLettersE.IndexOf(latz);
var latBandLow = 8 * latBand - 96;
var latBandHigh = 8 * latBand - 88;
Double ebase = 100000 * (1 + eidx - 8 * Math.Floor(Convert.ToDouble(eidx) / 8));
Int32 latBand = digraphLettersE.IndexOf(latz);
Int32 latBandLow = 8 * latBand - 96;
Int32 latBandHigh = 8 * latBand - 88;
if (latBand < 2)
{
if (latBand < 2) {
latBandLow = -90;
latBandHigh = -80;
}
else if (latBand == 21)
{
} else if (latBand == 21) {
latBandLow = 72;
latBandHigh = 84;
}
else if (latBand > 21)
{
} else if (latBand > 21) {
latBandLow = 84;
latBandHigh = 90;
}
var lowLetter = Math.Floor(100 + 1.11 * latBandLow);
var highLetter = Math.Round(100 + 1.11 * latBandHigh);
Double lowLetter = Math.Floor(100 + 1.11 * latBandLow);
Double highLetter = Math.Round(100 + 1.11 * latBandHigh);
Int32 l = Convert.ToInt32(lowLetter);
Int32 h = Convert.ToInt32(highLetter);
string latBandLetters = null;
int l = Convert.ToInt32(lowLetter);
int h = Convert.ToInt32(highLetter);
if (mgrs.LongZone / 2.0 == Math.Floor(mgrs.LongZone / 2.0))
{
latBandLetters = digraphLettersAll.Substring(l + 5, h + 5).ToString();
}
else
{
latBandLetters = digraphLettersAll.Substring(l, h).ToString();
}
var nbase = 100000 * (lowLetter + latBandLetters.IndexOf(nltr));
String latBandLetters = mgrs.LongZone / 2.0 == Math.Floor(mgrs.LongZone / 2.0) ? digraphLettersAll.Substring(l + 5, h + 5).ToString() : digraphLettersAll.Substring(l, h).ToString();
Double nbase = 100000 * (lowLetter + latBandLetters.IndexOf(nltr));
//latBandLetters.IndexOf(nltr) value causing incorrect Northing below -80
var x = ebase + mgrs.Easting;
var y = nbase + mgrs.Northing;
if (y > 10000000)
{
y = y - 10000000;
Double x = ebase + mgrs.Easting;
Double y = nbase + mgrs.Northing;
if (y > 10000000) {
y -= 10000000;
}
if (nbase >= 10000000)
{
y = nbase + mgrs.northing - 10000000;
if (nbase >= 10000000) {
y = nbase + mgrs.Northing - 10000000;
}
var southern = nbase < 10000000;
UniversalTransverseMercator utm = new UniversalTransverseMercator(mgrs.LatZone, mgrs.LongZone, x, y);
utm.equatorial_radius = mgrs.equatorialRadius;
utm.inverse_flattening = mgrs.inverseFlattening;
_ = nbase < 10000000;
UniversalTransverseMercator utm = new UniversalTransverseMercator(mgrs.LatZone, mgrs.LongZone, x, y) {
equatorial_radius = mgrs.equatorialRadius,
inverse_flattening = mgrs.inverseFlattening
};
Coordinate c = UniversalTransverseMercator.ConvertUTMtoLatLong(utm);
c.Set_Datum(mgrs.equatorialRadius, mgrs.inverseFlattening);
@ -269,11 +206,8 @@ namespace CoordinateSharp
/// MGRS Default String Format
/// </summary>
/// <returns>MGRS Formatted Coordinate String</returns>
public override string ToString()
{
if (!withinCoordinateSystemBounds) { return ""; }//MGRS Coordinate is outside its reliable boundaries. Return empty.
return longZone.ToString() + LatZone + " " + digraph + " " + ((int)easting).ToString("00000") + " " + ((int)northing).ToString("00000");
}
public override String ToString() => !this.WithinCoordinateSystemBounds ? "" : this.LongZone.ToString() + this.LatZone + " " + this.Digraph + " " + ((Int32)this.Easting).ToString("00000") + " " + ((Int32)this.Northing).ToString("00000");
//MGRS Coordinate is outside its reliable boundaries. Return empty.
/// <summary>
/// Property changed event
/// </summary>
@ -282,12 +216,6 @@ namespace CoordinateSharp
/// Notify property changed
/// </summary>
/// <param name="propName">Property name</param>
public void NotifyPropertyChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
public void NotifyPropertyChanged(String propName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,14 @@
using System;
using System.Linq;
using System.Diagnostics;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
namespace CoordinateSharp
{
namespace CoordinateSharp {
/// <summary>
/// Universal Transverse Mercator (UTM) coordinate system. Uses the WGS 84 Datum.
/// </summary>
[Serializable]
public class UniversalTransverseMercator : INotifyPropertyChanged
{
public class UniversalTransverseMercator : INotifyPropertyChanged {
/// <summary>
/// Creates a UniversalTransverMercator object with a WGS84 Datum.
/// </summary>
@ -18,20 +16,19 @@ namespace CoordinateSharp
/// <param name="longz">Longitude zone</param>
/// <param name="est">Easting</param>
/// <param name="nrt">Northing</param>
public UniversalTransverseMercator(string latz, int longz, double est, double nrt)
{
public UniversalTransverseMercator(String latz, Int32 longz, Double est, Double nrt) {
if (longz < 1 || longz > 60) { Debug.WriteLine("Longitudinal zone out of range", "UTM longitudinal zones must be between 1-60."); }
if (!Verify_Lat_Zone(latz)) { Debug.WriteLine("Latitudinal zone invalid", "UTM latitudinal zone was unrecognized."); }
if (!this.Verify_Lat_Zone(latz)) { Debug.WriteLine("Latitudinal zone invalid", "UTM latitudinal zone was unrecognized."); }
if (est < 160000 || est > 834000) { Debug.WriteLine("The Easting value provided is outside the max allowable range. Use with caution."); }
if (nrt < 0 || nrt > 10000000) { Debug.WriteLine("Northing out of range", "Northing must be between 0-10,000,000."); }
latZone = latz;
longZone =longz;
easting = est;
northing = nrt;
this.latZone = latz;
this.longZone = longz;
this.easting = est;
this.northing = nrt;
equatorial_radius = 6378137.0;
inverse_flattening = 298.257223563;
this.equatorial_radius = 6378137.0;
this.inverse_flattening = 298.257223563;
}
/// <summary>
/// Creates a UniversalTransverMercator object with a custom Datum.
@ -42,87 +39,72 @@ namespace CoordinateSharp
/// <param name="nrt">Northing</param>
/// <param name="radius">Equatorial Radius</param>
/// <param name="flaten">Inverse Flattening</param>
public UniversalTransverseMercator(string latz, int longz, double est, double nrt, double radius, double flaten)
{
public UniversalTransverseMercator(String latz, Int32 longz, Double est, Double nrt, Double radius, Double flaten) {
if (longz < 1 || longz > 60) { Debug.WriteLine("Longitudinal zone out of range", "UTM longitudinal zones must be between 1-60."); }
if (!Verify_Lat_Zone(latz)) { Debug.WriteLine("Latitudinal zone invalid", "UTM latitudinal zone was unrecognized."); }
if (!this.Verify_Lat_Zone(latz)) { Debug.WriteLine("Latitudinal zone invalid", "UTM latitudinal zone was unrecognized."); }
if (est < 160000 || est > 834000) { Debug.WriteLine("The Easting value provided is outside the max allowable range. Use with caution."); }
if (nrt < 0 || nrt > 10000000) { Debug.WriteLine("Northing out of range", "Northing must be between 0-10,000,000."); }
latZone = latz;
longZone = longz;
easting = est;
northing = nrt;
this.latZone = latz;
this.longZone = longz;
this.easting = est;
this.northing = nrt;
equatorial_radius = radius;
inverse_flattening = flaten;
this.equatorial_radius = radius;
this.inverse_flattening = flaten;
}
private Coordinate coordinate;
//private readonly Coordinate coordinate;
internal double equatorial_radius;
internal double inverse_flattening;
private string latZone;
private int longZone;
internal Double equatorial_radius;
internal Double inverse_flattening;
private String latZone;
private Int32 longZone;
private double easting;
private double northing;
private bool withinCoordinateSystemBounds = true;
private Double easting;
private Double northing;
/// <summary>
/// UTM Zone Letter
/// </summary>
public string LatZone
{
get { return latZone; }
set
{
if (latZone != value)
{
latZone = value;
public String LatZone {
get => this.latZone;
set {
if (this.latZone != value) {
this.latZone = value;
}
}
}
/// <summary>
/// UTM Zone Number
/// </summary>
public int LongZone
{
get { return longZone; }
set
{
if (longZone != value)
{
longZone = value;
public Int32 LongZone {
get => this.longZone;
set {
if (this.longZone != value) {
this.longZone = value;
}
}
}
/// <summary>
/// UTM Easting
/// </summary>
public double Easting
{
get { return easting; }
set
{
if (easting != value)
{
easting = value;
public Double Easting {
get => this.easting;
set {
if (this.easting != value) {
this.easting = value;
}
}
}
/// <summary>
/// UTM Northing
/// </summary>
public double Northing
{
get { return northing; }
set
{
if (northing != value)
{
northing = value;
public Double Northing {
get => this.northing;
set {
if (this.northing != value) {
this.northing = value;
}
}
}
@ -130,25 +112,16 @@ namespace CoordinateSharp
/// <summary>
/// Datum Equatorial Radius / Semi Major Axis
/// </summary>
public double Equatorial_Radius
{
get { return equatorial_radius; }
}
public Double Equatorial_Radius => this.equatorial_radius;
/// <summary>
/// Datum Flattening
/// </summary>
public double Inverse_Flattening
{
get { return inverse_flattening; }
}
public Double Inverse_Flattening => this.inverse_flattening;
/// <summary>
/// Is the UTM conversion within the coordinate system's accurate boundaries after conversion from Lat/Long.
/// </summary>
public bool WithinCoordinateSystemBounds
{
get { return withinCoordinateSystemBounds; }
}
public Boolean WithinCoordinateSystemBounds { get; private set; } = true;
/// <summary>
/// Constructs a UTM object based off DD Lat/Long
@ -156,8 +129,7 @@ namespace CoordinateSharp
/// <param name="lat">DD Latitude</param>
/// <param name="longi">DD Longitide</param>
/// <param name="c">Parent Coordinate Object</param>
internal UniversalTransverseMercator(double lat, double longi, Coordinate c)
{
internal UniversalTransverseMercator(Double lat, Double longi, Coordinate _) {
//validate coords
//if (lat > 180) { throw new ArgumentOutOfRangeException("Degrees out of range", "Longitudinal coordinate decimal cannot be greater than 180."); }
@ -165,11 +137,11 @@ namespace CoordinateSharp
//if (longi > 90) { throw new ArgumentOutOfRangeException("Degrees out of range", "Latitudinal coordinate decimal cannot be greater than 90."); }
//if (longi < -90) { throw new ArgumentOutOfRangeException("Degrees out of range", "Latitudinal coordinate decimal cannot be less than 90."); }
equatorial_radius = 6378137.0;
inverse_flattening = 298.257223563;
ToUTM(lat, longi, this);
this.equatorial_radius = 6378137.0;
this.inverse_flattening = 298.257223563;
this.ToUTM(lat, longi, this);
coordinate = c;
//this.coordinate = c;
}
/// <summary>
/// Constructs a UTM object based off DD Lat/Long
@ -179,13 +151,12 @@ namespace CoordinateSharp
/// <param name="c">Parent Coordinate Object</param>
/// <param name="rad">Equatorial Radius</param>
/// <param name="flt">Flattening</param>
internal UniversalTransverseMercator(double lat, double longi, Coordinate c,double rad,double flt)
{
equatorial_radius = rad;
inverse_flattening = flt;
ToUTM(lat, longi, this);
internal UniversalTransverseMercator(Double lat, Double longi, Coordinate _, Double rad, Double flt) {
this.equatorial_radius = rad;
this.inverse_flattening = flt;
this.ToUTM(lat, longi, this);
coordinate = c;
//this.coordinate = c;
}
/// <summary>
/// Constructs a UTM object based off a UTM coordinate
@ -198,24 +169,22 @@ namespace CoordinateSharp
/// <param name="c">Parent Coordinate Object</param>
/// <param name="rad">Equatorial Radius</param>
/// <param name="flt">Inverse Flattening</param>
internal UniversalTransverseMercator(string latz, int longz, double e, double n, Coordinate c, double rad, double flt)
{
internal UniversalTransverseMercator(String latz, Int32 longz, Double e, Double n, Coordinate c, Double rad, Double flt) {
//validate utm
if (longz < 1 || longz > 60) { Debug.WriteLine("Longitudinal zone out of range", "UTM longitudinal zones must be between 1-60."); }
if (!Verify_Lat_Zone(latz)) { throw new ArgumentException("Latitudinal zone invalid", "UTM latitudinal zone was unrecognized."); }
if (!this.Verify_Lat_Zone(latz)) { throw new ArgumentException("Latitudinal zone invalid", "UTM latitudinal zone was unrecognized."); }
if (e < 160000 || e > 834000) { Debug.WriteLine("The Easting value provided is outside the max allowable range. If this is intentional, use with caution."); }
if (n < 0 || n > 10000000) { throw new ArgumentOutOfRangeException("Northing out of range", "Northing must be between 0-10,000,000."); }
equatorial_radius = rad;
inverse_flattening = flt;
latZone = latz;
longZone = longz;
this.equatorial_radius = rad;
this.inverse_flattening = flt;
this.latZone = latz;
this.longZone = longz;
easting = e;
northing = n;
this.easting = e;
this.northing = n;
coordinate = c;
if (c.Latitude.DecimalDegree <= -80 || c.Latitude.DecimalDegree >= 84) { withinCoordinateSystemBounds = false; }
else { withinCoordinateSystemBounds = true; }
//this.coordinate = c;
this.WithinCoordinateSystemBounds = c.Latitude.DecimalDegree > -80 && c.Latitude.DecimalDegree < 84;
}
/// <summary>
@ -223,160 +192,115 @@ namespace CoordinateSharp
/// </summary>
/// <param name="l">Zone Letter</param>
/// <returns>boolean</returns>
private bool Verify_Lat_Zone(string l)
{
if (LatZones.longZongLetters.Where(x => x == l.ToUpper()).Count() != 1)
{
return false;
}
return true;
}
private double degreeToRadian(double degree)
{
return degree * Math.PI / 180;
}
private Boolean Verify_Lat_Zone(String l) => LatZones.longZongLetters.Where(x => x == l.ToUpper()).Count() == 1;
//private Double degreeToRadian(Double degree) => degree * Math.PI / 180;
/// <summary>
/// Assigns UTM values based of Lat/Long
/// </summary>
/// <param name="lat">DD Latitude</param>
/// <param name="longi">DD longitude</param>
/// <param name="utm">UTM Object to modify</param>
internal void ToUTM(double lat, double longi, UniversalTransverseMercator utm)
{
string letter = "";
double easting = 0;
double northing = 0;
int zone = (int)Math.Floor(longi / 6 + 31);
if (lat < -72)
letter = "C";
else if (lat < -64)
letter = "D";
else if (lat < -56)
letter = "E";
else if (lat < -48)
letter = "F";
else if (lat < -40)
letter = "G";
else if (lat < -32)
letter = "H";
else if (lat < -24)
letter = "J";
else if (lat < -16)
letter = "K";
else if (lat < -8)
letter = "L";
else if (lat < 0)
letter = "M";
else if (lat < 8)
letter = "N";
else if (lat < 16)
letter = "P";
else if (lat < 24)
letter = "Q";
else if (lat < 32)
letter = "R";
else if (lat < 40)
letter = "S";
else if (lat < 48)
letter = "T";
else if (lat < 56)
letter = "U";
else if (lat < 64)
letter = "V";
else if (lat < 72)
letter = "W";
else
letter = "X";
internal void ToUTM(Double lat, Double longi, UniversalTransverseMercator utm) {
Int32 zone = (Int32)Math.Floor(longi / 6 + 31);
String letter = lat < -72 ? "C"
: lat < -64 ? "D"
: lat < -56 ? "E"
: lat < -48 ? "F"
: lat < -40 ? "G"
: lat < -32 ? "H"
: lat < -24 ? "J"
: lat < -16 ? "K"
: lat < -8 ? "L"
: lat < 0 ? "M"
: lat < 8 ? "N"
: lat < 16 ? "P"
: lat < 24 ? "Q"
: lat < 32 ? "R"
: lat < 40 ? "S"
: lat < 48 ? "T"
: lat < 56 ? "U"
: lat < 64 ? "V"
: lat < 72 ? "W" : "X";
Double a = utm.equatorial_radius;
Double f = 1.0 / utm.inverse_flattening;
Double b = a * (1 - f); // polar radius
double a = utm.equatorial_radius;
double f = 1.0 / utm.inverse_flattening;
double b = a * (1 - f); // polar radius
Double e = Math.Sqrt(1 - Math.Pow(b, 2) / Math.Pow(a, 2));
_ = e / Math.Sqrt(1 - Math.Pow(e, 1));
double e = Math.Sqrt(1 - Math.Pow(b, 2) / Math.Pow(a, 2));
double e0 = e / Math.Sqrt(1 - Math.Pow(e, 1));
Double drad = Math.PI / 180;
Double k0 = 0.9996;
double drad = Math.PI / 180;
double k0 = 0.9996;
double phi = lat * drad; // convert latitude to radians
double lng = longi * drad; // convert longitude to radians
double utmz = 1 + Math.Floor((longi + 180) / 6.0); // longitude to utm zone
double zcm = 3 + 6.0 * (utmz - 1) - 180; // central meridian of a zone
Double phi = lat * drad; // convert latitude to radians
_ = longi * drad; // convert longitude to radians
Double utmz = 1 + Math.Floor((longi + 180) / 6.0); // longitude to utm zone
Double zcm = 3 + 6.0 * (utmz - 1) - 180; // central meridian of a zone
// this gives us zone A-B for below 80S
double esq = (1 - (b / a) * (b / a));
double e0sq = e * e / (1 - Math.Pow(e, 2));
double M = 0;
double N = a / Math.Sqrt(1 - Math.Pow(e * Math.Sin(phi), 2));
double T = Math.Pow(Math.Tan(phi), 2);
double C = e0sq * Math.Pow(Math.Cos(phi), 2);
double A = (longi - zcm) * drad * Math.Cos(phi);
Double esq = 1 - b / a * (b / a);
Double e0sq = e * e / (1 - Math.Pow(e, 2));
Double N = a / Math.Sqrt(1 - Math.Pow(e * Math.Sin(phi), 2));
Double T = Math.Pow(Math.Tan(phi), 2);
Double C = e0sq * Math.Pow(Math.Cos(phi), 2);
Double A = (longi - zcm) * drad * Math.Cos(phi);
// calculate M (USGS style)
M = phi * (1 - esq * (1.0 / 4.0 + esq * (3.0 / 64.0 + 5.0 * esq / 256.0)));
M = M - Math.Sin(2.0 * phi) * (esq * (3.0 / 8.0 + esq * (3.0 / 32.0 + 45.0 * esq / 1024.0)));
M = M + Math.Sin(4.0 * phi) * (esq * esq * (15.0 / 256.0 + esq * 45.0 / 1024.0));
M = M - Math.Sin(6.0 * phi) * (esq * esq * esq * (35.0 / 3072.0));
M = M * a;//Arc length along standard meridian
Double M = phi * (1 - esq * (1.0 / 4.0 + esq * (3.0 / 64.0 + 5.0 * esq / 256.0)));
M -= Math.Sin(2.0 * phi) * (esq * (3.0 / 8.0 + esq * (3.0 / 32.0 + 45.0 * esq / 1024.0)));
M += Math.Sin(4.0 * phi) * (esq * esq * (15.0 / 256.0 + esq * 45.0 / 1024.0));
M -= Math.Sin(6.0 * phi) * (esq * esq * esq * (35.0 / 3072.0));
M *= a;//Arc length along standard meridian
double M0 = 0;// if another point of origin is used than the equator
Double M0 = 0;// if another point of origin is used than the equator
// Calculate the UTM values...
// first the easting
var x = k0 * N * A * (1 + A * A * ((1 - T + C) / 6 + A * A * (5 - 18 * T + T * T + 72.0 * C - 58 * e0sq) / 120.0)); //Easting relative to CM
x = x + 500000; // standard easting
Double x = k0 * N * A * (1 + A * A * ((1 - T + C) / 6 + A * A * (5 - 18 * T + T * T + 72.0 * C - 58 * e0sq) / 120.0)); //Easting relative to CM
x += 500000; // standard easting
// Northing
double y = k0 * (M - M0 + N * Math.Tan(phi) * (A * A * (1 / 2.0 + A * A * ((5 - T + 9 * C + 4 * C * C) / 24.0 + A * A * (61 - 58 * T + T * T + 600 * C - 330 * e0sq) / 720.0)))); // first from the equator
double yg = y + 10000000; //yg = y global, from S. Pole
if (y < 0)
{
Double y = k0 * (M - M0 + N * Math.Tan(phi) * (A * A * (1 / 2.0 + A * A * ((5 - T + 9 * C + 4 * C * C) / 24.0 + A * A * (61 - 58 * T + T * T + 600 * C - 330 * e0sq) / 720.0)))); // first from the equator
_ = y + 10000000; //yg = y global, from S. Pole
if (y < 0) {
y = 10000000 + y; // add in false northing if south of the equator
}
easting = Math.Round(10 * (x)) / 10.0;
northing = Math.Round(10 * y) / 10.0;
Double easting = Math.Round(10 * x) / 10.0;
Double northing = Math.Round(10 * y) / 10.0;
utm.latZone = letter;
utm.longZone = zone;
utm.easting = easting;
utm.northing = northing;
if(lat<=-80 || lat >= 84) { withinCoordinateSystemBounds = false; }
else { withinCoordinateSystemBounds = true; }
this.WithinCoordinateSystemBounds = lat > -80 && lat < 84;
}
/// <summary>
/// UTM Default String Format
/// </summary>
/// <returns>UTM Formatted Coordinate String</returns>
public override string ToString()
{
if (!withinCoordinateSystemBounds) { return ""; }//MGRS Coordinate is outside its reliable boundaries. Return empty.
return longZone.ToString() + LatZone + " " + (int)easting + "mE " + (int)northing + "mN";
}
public override String ToString() => !this.WithinCoordinateSystemBounds ? "" : this.longZone.ToString() + this.LatZone + " " + (Int32)this.easting + "mE " + (Int32)this.northing + "mN";
//MGRS Coordinate is outside its reliable boundaries. Return empty.
private static Coordinate UTMtoLatLong(double x, double y, double zone, double equatorialRadius, double flattening)
{
private static Coordinate UTMtoLatLong(Double x, Double y, Double zone, Double equatorialRadius, Double flattening) {
//x easting
//y northing
//http://home.hiwaay.net/~taylorc/toolbox/geography/geoutm.html
double phif, Nf, Nfpow, nuf2, ep2, tf, tf2, tf4, cf;
double x1frac, x2frac, x3frac, x4frac, x5frac, x6frac, x7frac, x8frac;
double x2poly, x3poly, x4poly, x5poly, x6poly, x7poly, x8poly;
Double phif, Nf, Nfpow, nuf2, ep2, tf, tf2, tf4, cf;
Double x1frac, x2frac, x3frac, x4frac, x5frac, x6frac, x7frac, x8frac;
Double x2poly, x3poly, x4poly, x5poly, x6poly, x7poly, x8poly;
double sm_a = equatorialRadius;
double sm_b = equatorialRadius * (1 - (1.0 / flattening)); //Polar Radius
Double sm_a = equatorialRadius;
Double sm_b = equatorialRadius * (1 - 1.0 / flattening); //Polar Radius
/* Get the value of phif, the footpoint latitude. */
phif = FootpointLatitude(y,equatorialRadius,flattening);
phif = FootpointLatitude(y, equatorialRadius, flattening);
/* Precalculate ep2 */
ep2 = (Math.Pow(sm_a, 2.0) - Math.Pow(sm_b, 2.0))
/ Math.Pow(sm_b, 2.0);
ep2 = (Math.Pow(sm_a, 2.0) - Math.Pow(sm_b, 2.0)) / Math.Pow(sm_b, 2.0);
/* Precalculate cos (phif) */
cf = Math.Cos(phif);
@ -424,38 +348,30 @@ namespace CoordinateSharp
x3poly = -1.0 - 2 * tf2 - nuf2;
x4poly = 5.0 + 3.0 * tf2 + 6.0 * nuf2 - 6.0 * tf2 * nuf2
- 3.0 * (nuf2 * nuf2) - 9.0 * tf2 * (nuf2 * nuf2);
x4poly = 5.0 + 3.0 * tf2 + 6.0 * nuf2 - 6.0 * tf2 * nuf2 - 3.0 * (nuf2 * nuf2) - 9.0 * tf2 * (nuf2 * nuf2);
x5poly = 5.0 + 28.0 * tf2 + 24.0 * tf4 + 6.0 * nuf2 + 8.0 * tf2 * nuf2;
x6poly = -61.0 - 90.0 * tf2 - 45.0 * tf4 - 107.0 * nuf2
+ 162.0 * tf2 * nuf2;
x6poly = -61.0 - 90.0 * tf2 - 45.0 * tf4 - 107.0 * nuf2 + 162.0 * tf2 * nuf2;
x7poly = -61.0 - 662.0 * tf2 - 1320.0 * tf4 - 720.0 * (tf4 * tf2);
x8poly = 1385.0 + 3633.0 * tf2 + 4095.0 * tf4 + 1575 * (tf4 * tf2);
/* Calculate latitude */
double nLat = phif + x2frac * x2poly * (x * x)
+ x4frac * x4poly * Math.Pow(x, 4.0)
+ x6frac * x6poly * Math.Pow(x, 6.0)
+ x8frac * x8poly * Math.Pow(x, 8.0);
Double nLat = phif + x2frac * x2poly * (x * x) + x4frac * x4poly * Math.Pow(x, 4.0) + x6frac * x6poly * Math.Pow(x, 6.0) + x8frac * x8poly * Math.Pow(x, 8.0);
/* Calculate longitude */
double nLong = zone + x1frac * x
+ x3frac * x3poly * Math.Pow(x, 3.0)
+ x5frac * x5poly * Math.Pow(x, 5.0)
+ x7frac * x7poly * Math.Pow(x, 7.0);
Double nLong = zone + x1frac * x + x3frac * x3poly * Math.Pow(x, 3.0) + x5frac * x5poly * Math.Pow(x, 5.0) + x7frac * x7poly * Math.Pow(x, 7.0);
double dLat = RadToDeg(nLat);
double dLong = RadToDeg(nLong);
Double dLat = RadToDeg(nLat);
Double dLong = RadToDeg(nLong);
if (dLat > 90) { dLat = 90; }
if (dLat < -90) { dLat = -90; }
if (dLong > 180) { dLong = 180; }
if (dLong < -180) { dLong = -180; }
Coordinate c = new Coordinate(equatorialRadius,flattening, true);
Coordinate c = new Coordinate(equatorialRadius, flattening, true);
CoordinatePart cLat = new CoordinatePart(dLat, CoordinateType.Lat);
CoordinatePart cLng = new CoordinatePart(dLong, CoordinateType.Long);
@ -465,25 +381,22 @@ namespace CoordinateSharp
return c;
}
private static double RadToDeg(double rad)
{
double pi = 3.14159265358979;
return (rad / pi * 180.0);
private static Double RadToDeg(Double rad) {
Double pi = 3.14159265358979;
return rad / pi * 180.0;
}
private static double DegToRad(double deg)
{
double pi = 3.14159265358979;
return (deg / 180.0 * pi);
private static Double DegToRad(Double deg) {
Double pi = 3.14159265358979;
return deg / 180.0 * pi;
}
private static double FootpointLatitude(double y, double equatorialRadius, double flattening)
{
double y_, alpha_, beta_, gamma_, delta_, epsilon_, n;
double result;
private static Double FootpointLatitude(Double y, Double equatorialRadius, Double flattening) {
Double y_, alpha_, beta_, gamma_, delta_, epsilon_, n;
Double result;
/* Ellipsoid model constants (actual values here are for WGS84) */
double sm_a = equatorialRadius;
double sm_b = equatorialRadius * (1 - (1.0 / flattening));
Double sm_a = equatorialRadius;
Double sm_b = equatorialRadius * (1 - 1.0 / flattening);
/* Precalculate n (Eq. 10.18) */
@ -491,31 +404,25 @@ namespace CoordinateSharp
/* Precalculate alpha_ (Eq. 10.22) */
/* (Same as alpha in Eq. 10.17) */
alpha_ = ((sm_a + sm_b) / 2.0) * (1 + (Math.Pow(n, 2.0) / 4) + (Math.Pow(n, 4.0) / 64));
alpha_ = (sm_a + sm_b) / 2.0 * (1 + Math.Pow(n, 2.0) / 4 + Math.Pow(n, 4.0) / 64);
/* Precalculate y_ (Eq. 10.23) */
y_ = y / alpha_;
/* Precalculate beta_ (Eq. 10.22) */
beta_ = (3.0 * n / 2.0) + (-27.0 * Math.Pow(n, 3.0) / 32.0)
+ (269.0 * Math.Pow(n, 5.0) / 512.0);
beta_ = 3.0 * n / 2.0 + -27.0 * Math.Pow(n, 3.0) / 32.0 + 269.0 * Math.Pow(n, 5.0) / 512.0;
/* Precalculate gamma_ (Eq. 10.22) */
gamma_ = (21.0 * Math.Pow(n, 2.0) / 16.0)
+ (-55.0 * Math.Pow(n, 4.0) / 32.0);
gamma_ = 21.0 * Math.Pow(n, 2.0) / 16.0 + -55.0 * Math.Pow(n, 4.0) / 32.0;
/* Precalculate delta_ (Eq. 10.22) */
delta_ = (151.0 * Math.Pow(n, 3.0) / 96.0)
+ (-417.0 * Math.Pow(n, 5.0) / 128.0);
delta_ = 151.0 * Math.Pow(n, 3.0) / 96.0 + -417.0 * Math.Pow(n, 5.0) / 128.0;
/* Precalculate epsilon_ (Eq. 10.22) */
epsilon_ = (1097.0 * Math.Pow(n, 4.0) / 512.0);
epsilon_ = 1097.0 * Math.Pow(n, 4.0) / 512.0;
/* Now calculate the sum of the series (Eq. 10.21) */
result = y_ + (beta_ * Math.Sin(2.0 * y_))
+ (gamma_ * Math.Sin(4.0 * y_))
+ (delta_ * Math.Sin(6.0 * y_))
+ (epsilon_ * Math.Sin(8.0 * y_));
result = y_ + beta_ * Math.Sin(2.0 * y_) + gamma_ * Math.Sin(4.0 * y_) + delta_ * Math.Sin(6.0 * y_) + epsilon_ * Math.Sin(8.0 * y_);
return result;
}
@ -525,26 +432,22 @@ namespace CoordinateSharp
/// </summary>
/// <param name="utm">utm</param>
/// <returns>Coordinate object</returns>
public static Coordinate ConvertUTMtoLatLong(UniversalTransverseMercator utm)
{
public static Coordinate ConvertUTMtoLatLong(UniversalTransverseMercator utm) {
bool southhemi = false;
if (utm.latZone == "A" || utm.latZone == "B" || utm.latZone == "C" || utm.latZone == "D" || utm.latZone == "E" || utm.latZone == "F" || utm.latZone == "G" || utm.latZone == "H" || utm.latZone == "J" ||
utm.latZone == "K" || utm.latZone == "L" || utm.latZone == "M")
{
Boolean southhemi = false;
if (utm.latZone == "A" || utm.latZone == "B" || utm.latZone == "C" || utm.latZone == "D" || utm.latZone == "E" || utm.latZone == "F" || utm.latZone == "G" || utm.latZone == "H" || utm.latZone == "J" || utm.latZone == "K" || utm.latZone == "L" || utm.latZone == "M") {
southhemi = true;
}
double cmeridian;
Double cmeridian;
double x = utm.Easting - 500000.0;
double UTMScaleFactor = 0.9996;
Double x = utm.Easting - 500000.0;
Double UTMScaleFactor = 0.9996;
x /= UTMScaleFactor;
/* If in southern hemisphere, adjust y accordingly. */
double y = utm.Northing;
if (southhemi)
{
Double y = utm.Northing;
if (southhemi) {
y -= 10000000.0;
}
@ -554,8 +457,7 @@ namespace CoordinateSharp
Coordinate c = UTMtoLatLong(x, y, cmeridian, utm.equatorial_radius, utm.inverse_flattening);
if (c.Latitude.ToDouble() > 85 || c.Latitude.ToDouble() < -85)
{
if (c.Latitude.ToDouble() > 85 || c.Latitude.ToDouble() < -85) {
Debug.WriteLine("UTM conversions greater than 85 degrees or less than -85 degree latitude contain major deviations and should be used with caution.");
}
return c;
@ -563,11 +465,10 @@ namespace CoordinateSharp
}
private static double UTMCentralMeridian(double zone)
{
double cmeridian;
private static Double UTMCentralMeridian(Double zone) {
Double cmeridian;
cmeridian = DegToRad(-183.0 + (zone * 6.0));
cmeridian = DegToRad(-183.0 + zone * 6.0);
return cmeridian;
}
@ -580,10 +481,8 @@ namespace CoordinateSharp
/// Notify property changed
/// </summary>
/// <param name="propName">Property name</param>
public void NotifyPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
{
public void NotifyPropertyChanged(String propName) {
if (this.PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}

View File

@ -34,8 +34,7 @@ SOFTWARE.
using System;
using System.ComponentModel;
namespace CoordinateSharp
{
namespace CoordinateSharp {
/// <summary>
/// Observable class for handling all location based information.
/// This is the main class for CoordinateSharp.
@ -44,16 +43,14 @@ namespace CoordinateSharp
/// All information should be pulled from this class to include celestial information
/// </remarks>
[Serializable]
public class Coordinate : INotifyPropertyChanged
{
public class Coordinate : INotifyPropertyChanged {
/// <summary>
/// Creates an empty Coordinate.
/// </summary>
/// <remarks>
/// Values will need to be provided to latitude/longitude CoordinateParts manually
/// </remarks>
public Coordinate()
{
public Coordinate() {
this.FormatOptions = new CoordinateFormatOptions();
this.geoDate = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc);
this.latitude = new CoordinatePart(CoordinateType.Lat);
@ -77,8 +74,7 @@ namespace CoordinateSharp
/// <remarks>
/// Values will need to be provided to latitude/longitude CoordinateParts manually
/// </remarks>
internal Coordinate(Double equatorialRadius, Double inverseFlattening, Boolean t)
{
internal Coordinate(Double equatorialRadius, Double inverseFlattening, Boolean _) {
this.FormatOptions = new CoordinateFormatOptions();
this.geoDate = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc);
this.latitude = new CoordinatePart(CoordinateType.Lat);
@ -102,8 +98,7 @@ namespace CoordinateSharp
/// <remarks>
/// Geodate will default to 1/1/1900 GMT until provided
/// </remarks>
public Coordinate(Double lat, Double longi)
{
public Coordinate(Double lat, Double longi) {
this.FormatOptions = new CoordinateFormatOptions();
this.geoDate = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc);
this.latitude = new CoordinatePart(lat, CoordinateType.Lat);
@ -126,8 +121,7 @@ namespace CoordinateSharp
/// <param name="lat">latitude</param>
/// <param name="longi">longitude</param>
/// <param name="date">DateTime (UTC)</param>
public Coordinate(Double lat, Double longi, DateTime date)
{
public Coordinate(Double lat, Double longi, DateTime date) {
this.FormatOptions = new CoordinateFormatOptions();
this.latitude = new CoordinatePart(lat, CoordinateType.Lat);
this.longitude = new CoordinatePart(longi, CoordinateType.Long);
@ -152,8 +146,7 @@ namespace CoordinateSharp
/// Values will need to be provided to latitude/longitude manually
/// </remarks>
/// <param name="eagerLoad">Eager loading options</param>
public Coordinate(EagerLoad eagerLoad)
{
public Coordinate(EagerLoad eagerLoad) {
this.FormatOptions = new CoordinateFormatOptions();
this.geoDate = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc);
this.latitude = new CoordinatePart(CoordinateType.Lat);
@ -188,8 +181,7 @@ namespace CoordinateSharp
/// <param name="lat">latitude</param>
/// <param name="longi">longitude</param>
/// <param name="eagerLoad">Eager loading options</param>
public Coordinate(Double lat, Double longi, EagerLoad eagerLoad)
{
public Coordinate(Double lat, Double longi, EagerLoad eagerLoad) {
this.FormatOptions = new CoordinateFormatOptions();
this.geoDate = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc);
this.latitude = new CoordinatePart(lat, CoordinateType.Lat);
@ -223,8 +215,7 @@ namespace CoordinateSharp
/// <param name="longi">Decimal format longitude</param>
/// <param name="date">DateTime you wish to use for celestial calculation</param>
/// <param name="eagerLoad">Eager loading options</param>
public Coordinate(Double lat, Double longi, DateTime date, EagerLoad eagerLoad)
{
public Coordinate(Double lat, Double longi, DateTime date, EagerLoad eagerLoad) {
this.FormatOptions = new CoordinateFormatOptions();
this.latitude = new CoordinatePart(lat, CoordinateType.Lat);
this.longitude = new CoordinatePart(longi, CoordinateType.Long);
@ -261,8 +252,7 @@ namespace CoordinateSharp
/// <summary>
/// Latitudinal Coordinate Part
/// </summary>
public CoordinatePart Latitude
{
public CoordinatePart Latitude {
get => this.latitude;
set {
if (this.latitude != value) {
@ -292,8 +282,7 @@ namespace CoordinateSharp
/// <summary>
/// Longitudinal Coordinate Part
/// </summary>
public CoordinatePart Longitude
{
public CoordinatePart Longitude {
get => this.longitude;
set {
if (this.longitude != value) {
@ -325,8 +314,7 @@ namespace CoordinateSharp
/// <remarks>
/// Assumes all times are in UTC
/// </remarks>
public DateTime GeoDate
{
public DateTime GeoDate {
get => this.geoDate;
set {
if (this.geoDate != value) {
@ -357,8 +345,7 @@ namespace CoordinateSharp
/// Uses Ellipsoidal height with no geoid model included.
/// 0 = Mean Sea Level based on the provided Datum.
/// </summary>
public ECEF ECEF
{
public ECEF ECEF {
get => this.ecef;
//Required due to GeoDetic Height
@ -376,8 +363,7 @@ namespace CoordinateSharp
/// Used to determine what format the coordinate was parsed from.
/// Will equal "None" if Coordinate was not initialzed via a TryParse() method.
/// </summary>
public Parse_Format_Type Parse_Format
{
public Parse_Format_Type Parse_Format {
get => this.parse_Format;
internal set {
if (this.parse_Format != value) {
@ -399,8 +385,7 @@ namespace CoordinateSharp
/// <summary>
/// Initialize UTM and MGRS information (required if eager loading is turned off).
/// </summary>
public void LoadUTM_MGRS_Info()
{
public void LoadUTM_MGRS_Info() {
this.UTM = new UniversalTransverseMercator(this.latitude.ToDouble(), this.longitude.ToDouble(), this);
this.MGRS = new MilitaryGridReferenceSystem(this.UTM);
}
@ -431,8 +416,7 @@ namespace CoordinateSharp
/// Overridden Coordinate ToString() method.
/// </summary>
/// <returns>string (formatted).</returns>
public override String ToString()
{
public override String ToString() {
String latString = this.latitude.ToString();
String longSting = this.longitude.ToString();
return latString + " " + longSting;
@ -444,8 +428,7 @@ namespace CoordinateSharp
/// </summary>
/// <param name="options">CoordinateFormatOptions</param>
/// <returns>Custom formatted coordinate</returns>
public String ToString(CoordinateFormatOptions options)
{
public String ToString(CoordinateFormatOptions options) {
String latString = this.latitude.ToString(options);
String longSting = this.longitude.ToString(options);
return latString + " " + longSting;
@ -458,8 +441,7 @@ namespace CoordinateSharp
/// </summary>
/// <param name="radius">Equatorial Radius</param>
/// <param name="flat">Inverse Flattening</param>
public void Set_Datum(Double radius, Double flat)
{
public void Set_Datum(Double radius, Double flat) {
//WGS84
//RADIUS 6378137.0;
//FLATTENING 298.257223563;
@ -487,8 +469,7 @@ namespace CoordinateSharp
/// <param name="radius">Equatorial Radius</param>
/// <param name="flat">Inverse Flattening</param>
/// <param name="cd">Coordinate_Datum</param>
public void Set_Datum(Double radius, Double flat, Coordinate_Datum cd)
{
public void Set_Datum(Double radius, Double flat, Coordinate_Datum cd) {
//WGS84
//RADIUS 6378137.0;
//FLATTENING 298.257223563;
@ -554,8 +535,7 @@ namespace CoordinateSharp
/// //New Coordinate - N 25º 4' 54.517" E 24º 57' 29.189"
/// </code>
/// </example>
public void Move(Double distance, Double bearing, Shape shape)
{
public void Move(Double distance, Double bearing, Shape shape) {
//Convert to Radians for formula
Double lat1 = this.latitude.ToRadians();
Double lon1 = this.longitude.ToRadians();
@ -605,8 +585,7 @@ namespace CoordinateSharp
/// //New Coordinate - N 24º 56' 21.526" E 25º 4' 23.944"
/// </code>
/// </example>
public void Move(Coordinate target, Double distance, Shape shape)
{
public void Move(Coordinate target, Double distance, Shape shape) {
Distance d = new Distance(this, target, shape);
//Convert to Radians for formula
Double lat1 = this.latitude.ToRadians();
@ -656,8 +635,7 @@ namespace CoordinateSharp
/// //New Coordinate - N 25º 4' 54.517" E 24º 57' 29.189"
/// </code>
/// </example>
public void Move(Distance distance, Double bearing, Shape shape)
{
public void Move(Distance distance, Double bearing, Shape shape) {
//Convert to Radians for formula
Double lat1 = this.latitude.ToRadians();
Double lon1 = this.longitude.ToRadians();
@ -708,8 +686,7 @@ namespace CoordinateSharp
/// //New Coordinate - N 24º 56' 21.526" E 25º 4' 23.944"
/// </code>
/// </example>
public void Move(Coordinate target, Distance distance, Shape shape)
{
public void Move(Coordinate target, Distance distance, Shape shape) {
Distance d = new Distance(this, target, shape);
//Convert to Radians for formula
Double lat1 = this.latitude.ToRadians();
@ -752,9 +729,7 @@ namespace CoordinateSharp
/// }
/// </code>
/// </example>
public static Boolean TryParse(String s, out Coordinate c)
{
c = null;
public static Boolean TryParse(String s, out Coordinate c) {
if (FormatFinder.TryParse(s, CartesianType.Cartesian, out c)) {
Parse_Format_Type pft = c.Parse_Format;
c = new Coordinate(c.Latitude.ToDouble(), c.Longitude.ToDouble()) {
@ -781,9 +756,7 @@ namespace CoordinateSharp
/// }
/// </code>
/// </example>
public static Boolean TryParse(String s, DateTime geoDate, out Coordinate c)
{
c = null;
public static Boolean TryParse(String s, DateTime geoDate, out Coordinate c) {
if (FormatFinder.TryParse(s, CartesianType.Cartesian, out c)) {
Parse_Format_Type pft = c.Parse_Format;
c = new Coordinate(c.Latitude.ToDouble(), c.Longitude.ToDouble(), geoDate) {
@ -810,9 +783,7 @@ namespace CoordinateSharp
/// }
/// </code>
/// </example>
public static Boolean TryParse(String s, CartesianType ct, out Coordinate c)
{
c = null;
public static Boolean TryParse(String s, CartesianType ct, out Coordinate c) {
if (FormatFinder.TryParse(s, ct, out c)) {
Parse_Format_Type pft = c.Parse_Format;
if (ct == CartesianType.ECEF) {
@ -845,9 +816,7 @@ namespace CoordinateSharp
/// }
/// </code>
/// </example>
public static Boolean TryParse(String s, DateTime geoDate, CartesianType ct, out Coordinate c)
{
c = null;
public static Boolean TryParse(String s, DateTime geoDate, CartesianType ct, out Coordinate c) {
if (FormatFinder.TryParse(s, ct, out c)) {
Parse_Format_Type pft = c.Parse_Format;
if (ct == CartesianType.ECEF) {
@ -872,8 +841,7 @@ namespace CoordinateSharp
/// Notify property changed
/// </summary>
/// <param name="propName">Property name</param>
public void NotifyPropertyChanged(String propName)
{
public void NotifyPropertyChanged(String propName) {
switch (propName) {
case "CelestialInfo":
if (!this.EagerLoadSettings.Celestial || this.CelestialInfo == null) { return; } //Prevent Null Exceptions and calls while eagerloading is off
@ -913,8 +881,7 @@ namespace CoordinateSharp
/// Objects can be passed to Coordinate object Latitude and Longitude properties.
/// </remarks>
[Serializable]
public class CoordinatePart : INotifyPropertyChanged
{
public class CoordinatePart : INotifyPropertyChanged {
//Defaults:
//Format: Degrees Minutes Seconds
//Rounding: Dependent upon selected format
@ -941,8 +908,7 @@ namespace CoordinateSharp
/// <summary>
/// Observable decimal format coordinate.
/// </summary>
public Double DecimalDegree
{
public Double DecimalDegree {
get => this.decimalDegree;
set {
//If changing, notify the needed property changes
@ -1018,8 +984,7 @@ namespace CoordinateSharp
/// <summary>
/// Observable decimal format minute.
/// </summary>
public Double DecimalMinute
{
public Double DecimalMinute {
get => this.decimalMinute;
set {
if (this.decimalMinute != value) {
@ -1048,7 +1013,7 @@ namespace CoordinateSharp
Decimal newDM = decValue / 60; //divide decimalMinute by 60 to get storage value
Decimal newDD = this.degrees + newDM;//Add new decimal value to the floor degree value to get new decimalDegree;
if (this.decimalDegree < 0) { newDD = newDD * -1; } //Restore negative if needed
if (this.decimalDegree < 0) { newDD *= -1; } //Restore negative if needed
this.decimalDegree = Convert.ToDouble(newDD); //Convert back to double for storage
@ -1064,8 +1029,7 @@ namespace CoordinateSharp
/// <summary>
/// Observable coordinate degree.
/// </summary>
public Int32 Degrees
{
public Int32 Degrees {
get => this.degrees;
set {
//Validate Value
@ -1105,8 +1069,7 @@ namespace CoordinateSharp
/// <summary>
/// Observable coordinate minute.
/// </summary>
public Int32 Minutes
{
public Int32 Minutes {
get => this.minutes;
set {
if (this.minutes != value) {
@ -1114,9 +1077,9 @@ namespace CoordinateSharp
//Validate the minutes
Decimal vMin = Convert.ToDecimal(value);
if (this.type == CoordinateType.Lat) {
if (this.degrees + (vMin / 60) > 90) { throw new ArgumentOutOfRangeException("Degrees out of range", "Latitudinal degrees cannot be greater than 90"); }
if (this.degrees + vMin / 60 > 90) { throw new ArgumentOutOfRangeException("Degrees out of range", "Latitudinal degrees cannot be greater than 90"); }
} else {
if (this.degrees + (vMin / 60) > 180) { throw new ArgumentOutOfRangeException("Degrees out of range", "Longitudinal degrees cannot be greater than 180"); }
if (this.degrees + vMin / 60 > 180) { throw new ArgumentOutOfRangeException("Degrees out of range", "Longitudinal degrees cannot be greater than 180"); }
}
if (value >= 60) {
throw new ArgumentOutOfRangeException("Minutes out of range", "Minutes cannot be greater than or equal to 60");
@ -1154,8 +1117,7 @@ namespace CoordinateSharp
/// <summary>
/// Observable coordinate second.
/// </summary>
public Double Seconds
{
public Double Seconds {
get => this.seconds;
set {
if (value < 0) { value *= -1; }//Adjust accidental negative input
@ -1182,9 +1144,9 @@ namespace CoordinateSharp
this.seconds = value;
Double degABS = Math.Abs(this.decimalDegree); //Make decimalDegree positive
Double degFloor = Math.Truncate(degABS); //Truncate the number left of the decimal
Decimal f = Convert.ToDecimal(degFloor); //Convert to decimal to keep precision
//Double degABS = Math.Abs(this.decimalDegree); //Make decimalDegree positive
//Double degFloor = Math.Truncate(degABS); //Truncate the number left of the decimal
//Decimal f = Convert.ToDecimal(degFloor); //Convert to decimal to keep precision
Decimal secs = Convert.ToDecimal(this.seconds); //Convert seconds to decimal for calculations
secs /= 60; //Convert to storage format
@ -1207,8 +1169,7 @@ namespace CoordinateSharp
/// <summary>
/// Observable coordinate position.
/// </summary>
public CoordinatesPosition Position
{
public CoordinatesPosition Position {
get => this.position;
set {
if (this.position != value) {
@ -1231,8 +1192,7 @@ namespace CoordinateSharp
/// <param name="t">CoordinateType</param>
/// <param name="c">Parent Coordinate object</param>
[Obsolete("Method is deprecated. You no longer need to pass a Coordinate object through the constructor.")]
public CoordinatePart(CoordinateType t, Coordinate c)
{
public CoordinatePart(CoordinateType t, Coordinate c) {
this.parent = c;
this.type = t;
this.decimalDegree = 0;
@ -1248,8 +1208,7 @@ namespace CoordinateSharp
/// <param name="t">Coordinate type</param>
/// <param name="c">Parent Coordinate object</param>
[Obsolete("Method is deprecated. You no longer need to pass a Coordinate object through the constructor.")]
public CoordinatePart(Double value, CoordinateType t, Coordinate c)
{
public CoordinatePart(Double value, CoordinateType t, Coordinate c) {
this.parent = c;
this.type = t;
@ -1287,8 +1246,7 @@ namespace CoordinateSharp
/// <param name="pos">Coordinate Part Position</param>
/// <param name="c">Parent Coordinate</param>
[Obsolete("Method is deprecated. You no longer need to pass a Coordinate object through the constructor.")]
public CoordinatePart(Int32 deg, Int32 min, Double sec, CoordinatesPosition pos, Coordinate c)
{
public CoordinatePart(Int32 deg, Int32 min, Double sec, CoordinatesPosition pos, Coordinate c) {
this.parent = c;
this.type = pos == CoordinatesPosition.N || pos == CoordinatesPosition.S ? CoordinateType.Lat : CoordinateType.Long;
@ -1308,12 +1266,12 @@ namespace CoordinateSharp
minD += secD; //Decimal Minutes
if (this.type == CoordinateType.Long) {
if (deg + (minD / 60) > 180) { throw new ArgumentOutOfRangeException("Degrees out of range", "Longitudinal Degrees cannot be greater than 180."); }
if (deg + minD / 60 > 180) { throw new ArgumentOutOfRangeException("Degrees out of range", "Longitudinal Degrees cannot be greater than 180."); }
} else {
if (deg + (minD / 60) > 90) { throw new ArgumentOutOfRangeException("Degrees out of range", "Latitudinal Degrees cannot be greater than 90."); }
if (deg + minD / 60 > 90) { throw new ArgumentOutOfRangeException("Degrees out of range", "Latitudinal Degrees cannot be greater than 90."); }
}
this.decimalMinute = Convert.ToDouble(minD);
Decimal dd = Convert.ToDecimal(deg) + (minD / 60);
Decimal dd = Convert.ToDecimal(deg) + minD / 60;
if (pos == CoordinatesPosition.S || pos == CoordinatesPosition.W) {
@ -1329,8 +1287,7 @@ namespace CoordinateSharp
/// <param name="pos">Coordinate Part Position</param>
/// <param name="c">Parent Coordinate object</param>
[Obsolete("Method is deprecated. You no longer need to pass a Coordinate object through the constructor.")]
public CoordinatePart(Int32 deg, Double minSec, CoordinatesPosition pos, Coordinate c)
{
public CoordinatePart(Int32 deg, Double minSec, CoordinatesPosition pos, Coordinate c) {
this.parent = c;
this.type = pos == CoordinatesPosition.N || pos == CoordinatesPosition.S ? CoordinateType.Lat : CoordinateType.Long;
@ -1341,9 +1298,9 @@ namespace CoordinateSharp
if (minSec >= 60) { throw new ArgumentOutOfRangeException("Minutes out of range", "Minutes cannot be greater than or equal to 60."); }
if (this.type == CoordinateType.Lat) {
if (deg + (minSec / 60) > 90) { throw new ArgumentOutOfRangeException("Degree out of range", "Latitudinal degrees cannot be greater than 90."); }
if (deg + minSec / 60 > 90) { throw new ArgumentOutOfRangeException("Degree out of range", "Latitudinal degrees cannot be greater than 90."); }
} else {
if (deg + (minSec / 60) > 180) { throw new ArgumentOutOfRangeException("Degree out of range", "Longitudinal degrees cannot be greater than 180."); }
if (deg + minSec / 60 > 180) { throw new ArgumentOutOfRangeException("Degree out of range", "Longitudinal degrees cannot be greater than 180."); }
}
this.degrees = deg;
this.decimalMinute = minSec;
@ -1356,7 +1313,7 @@ namespace CoordinateSharp
sec *= 60;
Decimal secD = Convert.ToDecimal(sec);
this.seconds = Convert.ToDouble(secD);
Decimal dd = deg + (minD / 60);
Decimal dd = deg + minD / 60;
if (pos == CoordinatesPosition.S || pos == CoordinatesPosition.W) {
dd *= -1;
@ -1368,8 +1325,7 @@ namespace CoordinateSharp
/// Creates an empty CoordinatePart.
/// </summary>
/// <param name="t">CoordinateType</param>
public CoordinatePart(CoordinateType t)
{
public CoordinatePart(CoordinateType t) {
this.type = t;
this.decimalDegree = 0;
this.degrees = 0;
@ -1382,8 +1338,7 @@ namespace CoordinateSharp
/// </summary>
/// <param name="value">Coordinate decimal value</param>
/// <param name="t">Coordinate type</param>
public CoordinatePart(Double value, CoordinateType t)
{
public CoordinatePart(Double value, CoordinateType t) {
this.type = t;
if (this.type == CoordinateType.Long) {
@ -1418,8 +1373,7 @@ namespace CoordinateSharp
/// <param name="min">Minutes</param>
/// <param name="sec">Seconds</param>
/// <param name="pos">Coordinate Part Position</param>
public CoordinatePart(Int32 deg, Int32 min, Double sec, CoordinatesPosition pos)
{
public CoordinatePart(Int32 deg, Int32 min, Double sec, CoordinatesPosition pos) {
this.type = pos == CoordinatesPosition.N || pos == CoordinatesPosition.S ? CoordinateType.Lat : CoordinateType.Long;
if (deg < 0) { throw new ArgumentOutOfRangeException("Degrees out of range", "Degrees cannot be less than 0."); }
@ -1438,12 +1392,12 @@ namespace CoordinateSharp
minD += secD; //Decimal Minutes
if (this.type == CoordinateType.Long) {
if (deg + (minD / 60) > 180) { throw new ArgumentOutOfRangeException("Degrees out of range", "Longitudinal Degrees cannot be greater than 180."); }
if (deg + minD / 60 > 180) { throw new ArgumentOutOfRangeException("Degrees out of range", "Longitudinal Degrees cannot be greater than 180."); }
} else {
if (deg + (minD / 60) > 90) { throw new ArgumentOutOfRangeException("Degrees out of range", "Latitudinal Degrees cannot be greater than 90."); }
if (deg + minD / 60 > 90) { throw new ArgumentOutOfRangeException("Degrees out of range", "Latitudinal Degrees cannot be greater than 90."); }
}
this.decimalMinute = Convert.ToDouble(minD);
Decimal dd = Convert.ToDecimal(deg) + (minD / 60);
Decimal dd = Convert.ToDecimal(deg) + minD / 60;
if (pos == CoordinatesPosition.S || pos == CoordinatesPosition.W) {
@ -1457,8 +1411,7 @@ namespace CoordinateSharp
/// <param name="deg">Degrees</param>
/// <param name="minSec">Decimal Minutes</param>
/// <param name="pos">Coordinate Part Position</param>
public CoordinatePart(Int32 deg, Double minSec, CoordinatesPosition pos)
{
public CoordinatePart(Int32 deg, Double minSec, CoordinatesPosition pos) {
this.type = pos == CoordinatesPosition.N || pos == CoordinatesPosition.S ? CoordinateType.Lat : CoordinateType.Long;
if (deg < 0) { throw new ArgumentOutOfRangeException("Degree out of range", "Degree cannot be less than 0."); }
@ -1467,9 +1420,9 @@ namespace CoordinateSharp
if (minSec >= 60) { throw new ArgumentOutOfRangeException("Minutes out of range", "Minutes cannot be greater than or equal to 60."); }
if (this.type == CoordinateType.Lat) {
if (deg + (minSec / 60) > 90) { throw new ArgumentOutOfRangeException("Degree out of range", "Latitudinal degrees cannot be greater than 90."); }
if (deg + minSec / 60 > 90) { throw new ArgumentOutOfRangeException("Degree out of range", "Latitudinal degrees cannot be greater than 90."); }
} else {
if (deg + (minSec / 60) > 180) { throw new ArgumentOutOfRangeException("Degree out of range", "Longitudinal degrees cannot be greater than 180."); }
if (deg + minSec / 60 > 180) { throw new ArgumentOutOfRangeException("Degree out of range", "Longitudinal degrees cannot be greater than 180."); }
}
this.degrees = deg;
this.decimalMinute = minSec;
@ -1482,7 +1435,7 @@ namespace CoordinateSharp
sec *= 60;
Decimal secD = Convert.ToDecimal(sec);
this.seconds = Convert.ToDouble(secD);
Decimal dd = deg + (minD / 60);
Decimal dd = deg + minD / 60;
if (pos == CoordinatesPosition.S || pos == CoordinatesPosition.W) {
dd *= -1;
@ -1513,46 +1466,25 @@ namespace CoordinateSharp
/// </summary>
/// <param name="options">CoordinateFormatOptions</param>
/// <returns>Formatted coordinate part string</returns>
private String FormatString(CoordinateFormatOptions options)
{
ToStringType type = ToStringType.Degree_Minute_Second;
Int32? rounding = null;
Boolean lead = false;
Boolean trail = false;
Boolean hyphen = false;
Boolean symbols = true;
Boolean degreeSymbol = true;
Boolean minuteSymbol = true;
Boolean secondsSymbol = true;
Boolean positionFirst = true;
private String FormatString(CoordinateFormatOptions options) {
#region Assign Formatting Rules
switch (options.Format) {
case CoordinateFormatType.Degree_Minutes_Seconds:
type = ToStringType.Degree_Minute_Second;
break;
case CoordinateFormatType.Degree_Decimal_Minutes:
type = ToStringType.Degree_Decimal_Minute;
break;
case CoordinateFormatType.Decimal_Degree:
type = ToStringType.Decimal_Degree;
break;
case CoordinateFormatType.Decimal:
type = ToStringType.Decimal;
break;
default:
type = ToStringType.Degree_Minute_Second;
break;
}
rounding = options.Round;
lead = options.Display_Leading_Zeros;
trail = options.Display_Trailing_Zeros;
symbols = options.Display_Symbols;
degreeSymbol = options.Display_Degree_Symbol;
minuteSymbol = options.Display_Minute_Symbol;
secondsSymbol = options.Display_Seconds_Symbol;
hyphen = options.Display_Hyphens;
positionFirst = options.Position_First;
ToStringType type = options.Format switch
{
CoordinateFormatType.Degree_Minutes_Seconds => ToStringType.Degree_Minute_Second,
CoordinateFormatType.Degree_Decimal_Minutes => ToStringType.Degree_Decimal_Minute,
CoordinateFormatType.Decimal_Degree => ToStringType.Decimal_Degree,
CoordinateFormatType.Decimal => ToStringType.Decimal,
_ => ToStringType.Degree_Minute_Second,
};
Int32? rounding = options.Round;
Boolean lead = options.Display_Leading_Zeros;
Boolean trail = options.Display_Trailing_Zeros;
Boolean symbols = options.Display_Symbols;
Boolean degreeSymbol = options.Display_Degree_Symbol;
Boolean minuteSymbol = options.Display_Minute_Symbol;
Boolean secondsSymbol = options.Display_Seconds_Symbol;
Boolean hyphen = options.Display_Hyphens;
Boolean positionFirst = options.Position_First;
#endregion
switch (type) {
@ -1576,8 +1508,7 @@ namespace CoordinateSharp
return String.Empty;
}
//DMS Coordinate Format
private String ToDegreeMinuteSecondString(Int32 rounding, Boolean lead, Boolean trail, Boolean symbols, Boolean degreeSymbol, Boolean minuteSymbol, Boolean secondSymbol, Boolean hyphen, Boolean positionFirst)
{
private String ToDegreeMinuteSecondString(Int32 rounding, Boolean lead, Boolean trail, Boolean symbols, Boolean degreeSymbol, Boolean minuteSymbol, Boolean secondSymbol, Boolean hyphen, Boolean positionFirst) {
String leadString = this.Leading_Trailing_Format(lead, false, rounding, this.Position);
String d = String.Format(leadString, this.Degrees); // Degree String
@ -1602,8 +1533,7 @@ namespace CoordinateSharp
: d + ds + hs + minute + ms + hs + second + ss + hs + this.Position.ToString();
}
//DDM Coordinate Format
private String ToDegreeDecimalMinuteString(Int32 rounding, Boolean lead, Boolean trail, Boolean symbols, Boolean degreeSymbol, Boolean minuteSymbol, Boolean hyphen, Boolean positionFirst)
{
private String ToDegreeDecimalMinuteString(Int32 rounding, Boolean lead, Boolean trail, Boolean symbols, Boolean degreeSymbol, Boolean minuteSymbol, Boolean hyphen, Boolean positionFirst) {
String leadString = "{0:0";
if (lead) {
if (this.Position == CoordinatesPosition.E || this.Position == CoordinatesPosition.W) {
@ -1646,8 +1576,7 @@ namespace CoordinateSharp
}
////DD Coordinate Format
private String ToDecimalDegreeString(Int32 rounding, Boolean lead, Boolean trail, Boolean symbols, Boolean degreeSymbol, Boolean positionFirst, Boolean hyphen)
{
private String ToDecimalDegreeString(Int32 rounding, Boolean lead, Boolean trail, Boolean symbols, Boolean degreeSymbol, Boolean positionFirst, Boolean hyphen) {
String degreeS = "";
String hyph = " ";
if (degreeSymbol) { degreeS = "º"; }
@ -1672,15 +1601,14 @@ namespace CoordinateSharp
}
leadTrail += "}";
Double result = (this.Degrees) + (Convert.ToDouble(this.Minutes)) / 60 + (Convert.ToDouble(this.Seconds)) / 3600;
Double result = this.Degrees + Convert.ToDouble(this.Minutes) / 60 + Convert.ToDouble(this.Seconds) / 3600;
result = Math.Round(result, rounding);
String d = String.Format(leadTrail, Math.Abs(result));
return positionFirst ? this.Position.ToString() + hyph + d + degreeS : d + degreeS + hyph + this.Position.ToString();
}
private String Leading_Trailing_Format(Boolean isLead, Boolean isTrail, Int32 rounding, CoordinatesPosition? p = null)
{
private String Leading_Trailing_Format(Boolean isLead, Boolean isTrail, Int32 rounding, CoordinatesPosition? p = null) {
String leadString = "{0:0";
if (isLead) {
if (p != null) {
@ -1706,18 +1634,16 @@ namespace CoordinateSharp
}
private String FormatError(String argument, String rule) => "'" + argument + "' is not a valid argument for string format rule: " + rule + ".";
//private String FormatError(String argument, String rule) => "'" + argument + "' is not a valid argument for string format rule: " + rule + ".";
private enum ToStringType
{
private enum ToStringType {
Decimal_Degree, Degree_Decimal_Minute, Degree_Minute_Second, Decimal
}
/// <summary>
/// Notify the correct properties and parent properties.
/// </summary>
/// <param name="p">Property Type</param>
private void NotifyProperties(PropertyTypes p)
{
private void NotifyProperties(PropertyTypes p) {
switch (p) {
case PropertyTypes.DecimalDegree:
this.NotifyPropertyChanged("DecimalDegree");
@ -1786,8 +1712,7 @@ namespace CoordinateSharp
/// <summary>
/// Used for notifying the correct properties.
/// </summary>
private enum PropertyTypes
{
private enum PropertyTypes {
DecimalDegree, DecimalMinute, Position, Degree, Minute, Second, FormatChange
}
@ -1811,12 +1736,7 @@ namespace CoordinateSharp
/// }
/// </code>
/// </example>
public static Boolean TryParse(String s, out CoordinatePart cp)
{
cp = null;
return FormatFinder_CoordPart.TryParse(s, out cp) ? true : false;
}
public static Boolean TryParse(String s, out CoordinatePart cp) => FormatFinder_CoordPart.TryParse(s, out cp) ? true : false;
/// <summary>
/// Attempts to parse a string into a CoordinatePart.
/// </summary>
@ -1833,9 +1753,7 @@ namespace CoordinateSharp
/// }
/// </code>
/// </example>
public static Boolean TryParse(String s, CoordinateType t, out CoordinatePart cp)
{
cp = null;
public static Boolean TryParse(String s, CoordinateType t, out CoordinatePart cp) {
//Comma at beginning parses to long
//Asterik forces lat
s = t == CoordinateType.Long ? "," + s : "*" + s;

View File

@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<AssemblyName>CoordinateSharp</AssemblyName>
<RootNamespace>CoordinateSharp</RootNamespace>
<Description>A simple .NET standard library that is designed to assist with geographic coordinate conversions, formatting and location based celestial calculations.</Description>
<Copyright>Copyright 2019</Copyright>
<Version>1.1.5.2</Version>
</PropertyGroup>
</Project>

View File

@ -1,58 +1,43 @@
using System;
using System.Diagnostics;
namespace CoordinateSharp
{
namespace CoordinateSharp {
/// <summary>
/// Contains distance values between two coordinates.
/// </summary>
[Serializable]
public class Distance
{
private double kilometers;
private double miles;
private double feet;
private double meters;
private double bearing;
private double nauticalMiles;
public class Distance {
/// <summary>
/// Initializes a distance object using Haversine (Spherical Earth).
/// </summary>
/// <param name="c1">Coordinate 1</param>
/// <param name="c2">Coordinate 2</param>
public Distance(Coordinate c1, Coordinate c2)
{
Haversine(c1, c2);
}
public Distance(Coordinate c1, Coordinate c2) => this.Haversine(c1, c2);
/// <summary>
/// Initializes a distance object using Haversine (Spherical Earth) or Vincenty (Elliptical Earth).
/// </summary>
/// <param name="c1">Coordinate 1</param>
/// <param name="c2">Coordinate 2</param>
/// <param name="shape">Shape of earth</param>
public Distance(Coordinate c1, Coordinate c2, Shape shape)
{
if (shape == Shape.Sphere)
{
Haversine(c1, c2);
}
else
{
Vincenty(c1, c2);
public Distance(Coordinate c1, Coordinate c2, Shape shape) {
if (shape == Shape.Sphere) {
this.Haversine(c1, c2);
} else {
this.Vincenty(c1, c2);
}
}
/// <summary>
/// Initializes distance object based on distance in KM
/// </summary>
/// <param name="km">Kilometers</param>
public Distance(double km)
{
kilometers = km;
meters = km * 1000;
feet = meters * 3.28084;
miles = meters * 0.000621371;
nauticalMiles = meters * 0.0005399565;
bearing = 0;//None specified
public Distance(Double km) {
this.Kilometers = km;
this.Meters = km * 1000;
this.Feet = this.Meters * 3.28084;
this.Miles = this.Meters * 0.000621371;
this.NauticalMiles = this.Meters * 0.0005399565;
this.Bearing = 0;//None specified
}
/// <summary>
/// Initializaes distance object based on specified distance and measurement type
@ -60,59 +45,56 @@ namespace CoordinateSharp
/// <param name="distance">Distance</param>
/// <param name="type">Measurement type</param>
public Distance(double distance, DistanceType type)
{
bearing = 0;
switch (type)
{
public Distance(Double distance, DistanceType type) {
this.Bearing = 0;
switch (type) {
case DistanceType.Feet:
feet = distance;
meters = feet * 0.3048;
kilometers = meters / 1000;
miles = meters * 0.000621371;
nauticalMiles = meters * 0.0005399565;
this.Feet = distance;
this.Meters = this.Feet * 0.3048;
this.Kilometers = this.Meters / 1000;
this.Miles = this.Meters * 0.000621371;
this.NauticalMiles = this.Meters * 0.0005399565;
break;
case DistanceType.Kilometers:
kilometers = distance;
meters = kilometers * 1000;
feet = meters * 3.28084;
miles = meters * 0.000621371;
nauticalMiles = meters * 0.0005399565;
this.Kilometers = distance;
this.Meters = this.Kilometers * 1000;
this.Feet = this.Meters * 3.28084;
this.Miles = this.Meters * 0.000621371;
this.NauticalMiles = this.Meters * 0.0005399565;
break;
case DistanceType.Meters:
meters = distance;
kilometers = meters / 1000;
feet = meters * 3.28084;
miles = meters * 0.000621371;
nauticalMiles = meters * 0.0005399565;
this.Meters = distance;
this.Kilometers = this.Meters / 1000;
this.Feet = this.Meters * 3.28084;
this.Miles = this.Meters * 0.000621371;
this.NauticalMiles = this.Meters * 0.0005399565;
break;
case DistanceType.Miles:
miles = distance;
meters = miles * 1609.344;
feet = meters * 3.28084;
kilometers = meters / 1000;
nauticalMiles = meters * 0.0005399565;
this.Miles = distance;
this.Meters = this.Miles * 1609.344;
this.Feet = this.Meters * 3.28084;
this.Kilometers = this.Meters / 1000;
this.NauticalMiles = this.Meters * 0.0005399565;
break;
case DistanceType.NauticalMiles:
nauticalMiles = distance;
meters = nauticalMiles * 1852.001;
feet = meters * 3.28084;
kilometers = meters / 1000;
miles = meters * 0.000621371;
this.NauticalMiles = distance;
this.Meters = this.NauticalMiles * 1852.001;
this.Feet = this.Meters * 3.28084;
this.Kilometers = this.Meters / 1000;
this.Miles = this.Meters * 0.000621371;
break;
default:
kilometers = distance;
meters = distance * 1000;
feet = meters * 3.28084;
miles = meters * 0.000621371;
nauticalMiles = meters * 0.0005399565;
this.Kilometers = distance;
this.Meters = distance * 1000;
this.Feet = this.Meters * 3.28084;
this.Miles = this.Meters * 0.000621371;
this.NauticalMiles = this.Meters * 0.0005399565;
break;
}
}
private void Vincenty(Coordinate coord1, Coordinate coord2)
{
double lat1, lat2, lon1, lon2;
double d, crs12, crs21;
private void Vincenty(Coordinate coord1, Coordinate coord2) {
Double lat1, lat2, lon1, lon2;
Double d, crs12;
lat1 = coord1.Latitude.ToRadians();
@ -121,111 +103,90 @@ namespace CoordinateSharp
lon2 = coord2.Longitude.ToRadians() * -1; //REVERSE FOR CALC 2.1.1.1
//Ensure datums match between coords
if ((coord1.equatorial_radius != coord2.equatorial_radius) || (coord1.inverse_flattening != coord2.inverse_flattening))
{
if (coord1.equatorial_radius != coord2.equatorial_radius || coord1.inverse_flattening != coord2.inverse_flattening) {
throw new InvalidOperationException("The datum set does not match between Coordinate objects.");
}
double[] ellipse = new double[] { coord1.equatorial_radius, coord1.inverse_flattening };
Double[] ellipse = new Double[] { coord1.equatorial_radius, coord1.inverse_flattening };
// elliptic code
double[] cde = Distance_Assistant.Dist_Ell(lat1, -lon1, lat2, -lon2, ellipse); // ellipse uses East negative
Double[] cde = Distance_Assistant.Dist_Ell(lat1, -lon1, lat2, -lon2, ellipse); // ellipse uses East negative
crs12 = cde[1] * (180 / Math.PI); //Bearing
crs21 = cde[2] * (180 / Math.PI); //Reverse Bearing
_ = cde[2] * (180 / Math.PI); //Reverse Bearing
d = cde[0]; //Distance
bearing = crs12;
this.Bearing = crs12;
//reverseBearing = crs21;
meters = d;
kilometers = d / 1000;
feet = d * 3.28084;
miles = d * 0.000621371;
nauticalMiles = d * 0.0005399565;
this.Meters = d;
this.Kilometers = d / 1000;
this.Feet = d * 3.28084;
this.Miles = d * 0.000621371;
this.NauticalMiles = d * 0.0005399565;
}
private void Haversine(Coordinate coord1, Coordinate coord2)
{
private void Haversine(Coordinate coord1, Coordinate coord2) {
////RADIANS
double lat1 = coord1.Latitude.ToRadians();
double long1 = coord1.Longitude.ToRadians();
double lat2 = coord2.Latitude.ToRadians();
double long2 = coord2.Longitude.ToRadians();
Double lat1 = coord1.Latitude.ToRadians();
Double long1 = coord1.Longitude.ToRadians();
Double lat2 = coord2.Latitude.ToRadians();
Double long2 = coord2.Longitude.ToRadians();
//Distance Calcs
double R = 6371000; //6378137.0;//6371e3; //meters
double latRad = coord2.Latitude.ToRadians() - coord1.Latitude.ToRadians();
double longRad = coord2.Longitude.ToRadians() - coord1.Longitude.ToRadians();
Double R = 6371000; //6378137.0;//6371e3; //meters
Double latRad = coord2.Latitude.ToRadians() - coord1.Latitude.ToRadians();
Double longRad = coord2.Longitude.ToRadians() - coord1.Longitude.ToRadians();
double a = Math.Sin(latRad / 2.0) * Math.Sin(latRad / 2.0) +
Double a = Math.Sin(latRad / 2.0) * Math.Sin(latRad / 2.0) +
Math.Cos(lat1) * Math.Cos(lat2) * Math.Sin(longRad / 2.0) * Math.Sin(longRad / 2.0);
double cl = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
double dist = R * cl;
Double cl = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
Double dist = R * cl;
//Get bearing
double dLong = long2 - long1;
double y = Math.Sin(dLong) * Math.Cos(lat2);
double x = Math.Cos(lat1) * Math.Sin(lat2) - Math.Sin(lat1) * Math.Cos(lat2) * Math.Cos(dLong);
double brng = Math.Atan2(y, x) * (180 / Math.PI); //Convert bearing back to degrees.
Double dLong = long2 - long1;
Double y = Math.Sin(dLong) * Math.Cos(lat2);
Double x = Math.Cos(lat1) * Math.Sin(lat2) - Math.Sin(lat1) * Math.Cos(lat2) * Math.Cos(dLong);
Double brng = Math.Atan2(y, x) * (180 / Math.PI); //Convert bearing back to degrees.
//if (brng < 0) { brng -= 180; brng = Math.Abs(brng); }
brng = (brng + 360) % 360; //v2.1.1.1 NORMALIZE HEADING
kilometers = dist / 1000;
meters = dist;
feet = dist * 3.28084;
miles = dist * 0.000621371;
nauticalMiles = dist * 0.0005399565;
bearing = brng;
this.Kilometers = dist / 1000;
this.Meters = dist;
this.Feet = dist * 3.28084;
this.Miles = dist * 0.000621371;
this.NauticalMiles = dist * 0.0005399565;
this.Bearing = brng;
}
/// <summary>
/// Distance in Kilometers
/// </summary>
public double Kilometers
{
get { return kilometers; }
}
public Double Kilometers { get; private set; }
/// <summary>
/// Distance in Statute Miles
/// </summary>
public double Miles
{
get { return miles; }
}
public Double Miles { get; private set; }
/// <summary>
/// Distance in Nautical Miles
/// </summary>
public double NauticalMiles
{
get { return nauticalMiles; }
}
public Double NauticalMiles { get; private set; }
/// <summary>
/// Distance in Meters
/// </summary>
public double Meters
{
get { return meters; }
}
public Double Meters { get; private set; }
/// <summary>
/// Distance in Feet
/// </summary>
public double Feet
{
get { return feet; }
}
public Double Feet { get; private set; }
/// <summary>
/// Initial Bearing from Coordinate 1 to Coordinate 2
/// </summary>
public double Bearing
{
get { return bearing; }
}
public Double Bearing { get; private set; }
}
/// <summary>
/// Distance measurement type
/// </summary>
public enum DistanceType
{
public enum DistanceType {
/// <summary>
/// Distance in Meters
/// </summary>
@ -249,8 +210,7 @@ namespace CoordinateSharp
}
[Serializable]
internal class Distance_Assistant
{
internal class Distance_Assistant {
/// <summary>
/// Returns new geodetic coordinate in radians
/// </summary>
@ -260,34 +220,25 @@ namespace CoordinateSharp
/// <param name="s">Distance</param>
/// <param name="ellipse">Earth Ellipse Values</param>
/// <returns>double[]</returns>
public static double[] Direct_Ell(double glat1, double glon1, double faz, double s, double[] ellipse)
{
public static Double[] Direct_Ell(Double glat1, Double glon1, Double faz, Double s, Double[] ellipse) {
glon1 *= -1; //REVERSE LONG FOR CALC 2.1.1.1
double EPS = 0.00000000005;//Used to determine if starting at pole.
double r, tu, sf, cf, b, cu, su, sa, c2a, x, c, d, y, sy = 0, cy = 0, cz = 0, e = 0;
double glat2, glon2, f;
Double EPS = 0.00000000005;//Used to determine if starting at pole.
Double r, tu, sf, cf, b, cu, su, sa, c2a, x, c, d, y, sy = 0, cy = 0, cz = 0, e = 0;
Double glat2, glon2, f;
//Determine if near pole
if ((Math.Abs(Math.Cos(glat1)) < EPS) && !(Math.Abs(Math.Sin(faz)) < EPS))
{
if (Math.Abs(Math.Cos(glat1)) < EPS && !(Math.Abs(Math.Sin(faz)) < EPS)) {
Debug.WriteLine("Warning: Location is at earth's pole. Only N-S courses are meaningful at this location.");
}
double a = ellipse[0];//Equitorial Radius
Double a = ellipse[0];//Equitorial Radius
f = 1 / ellipse[1];//Flattening
r = 1 - f;
tu = r * Math.Tan(glat1);
sf = Math.Sin(faz);
cf = Math.Cos(faz);
if (cf == 0)
{
b = 0.0;
}
else
{
b = 2.0 * Math.Atan2(tu, cf);
}
b = cf == 0 ? 0.0 : 2.0 * Math.Atan2(tu, cf);
cu = 1.0 / Math.Sqrt(1 + tu * tu);
su = tu * cu;
sa = cu * sf;
@ -300,8 +251,7 @@ namespace CoordinateSharp
tu = s / (r * a * c);
y = tu;
c = y + 1;
while (Math.Abs(y - c) > EPS)
{
while (Math.Abs(y - c) > EPS) {
sy = Math.Sin(y);
cy = Math.Cos(y);
cz = Math.Cos(b + y);
@ -324,7 +274,7 @@ namespace CoordinateSharp
d = ((e * cy * c + cz) * sy * c + y) * sa;
glon2 = ModM.ModLon(glon1 + x - (1.0 - c) * d * f); //Adjust for IDL
//baz = ModM.ModCrs(Math.Atan2(sa, b) + Math.PI);
return new double[] { glat2, glon2 };
return new Double[] { glat2, glon2 };
}
/// <summary>
/// Returns new geodetic coordinate in radians
@ -334,57 +284,49 @@ namespace CoordinateSharp
/// <param name="crs12">Bearing</param>
/// <param name="d12">Distance</param>
/// <returns>double[]</returns>
public static double[] Direct(double lat1, double lon1, double crs12, double d12)
{
public static Double[] Direct(Double lat1, Double lon1, Double crs12, Double d12) {
lon1 *= -1; //REVERSE LONG FOR CALC 2.1.1.1
var EPS = 0.00000000005;//Used to determine if near pole.
double dlon, lat, lon;
d12 = d12 * 0.0005399565; //convert meter to nm
d12 = d12 / (180 * 60 / Math.PI);//Convert to Radian
Double EPS = 0.00000000005;//Used to determine if near pole.
Double dlon, lat, lon;
d12 *= 0.0005399565; //convert meter to nm
d12 /= 180 * 60 / Math.PI;//Convert to Radian
//Determine if near pole
if ((Math.Abs(Math.Cos(lat1)) < EPS) && !(Math.Abs(Math.Sin(crs12)) < EPS))
{
if (Math.Abs(Math.Cos(lat1)) < EPS && !(Math.Abs(Math.Sin(crs12)) < EPS)) {
Debug.WriteLine("Warning: Location is at earth's pole. Only N-S courses are meaningful at this location.");
}
lat = Math.Asin(Math.Sin(lat1) * Math.Cos(d12) +
Math.Cos(lat1) * Math.Sin(d12) * Math.Cos(crs12));
if (Math.Abs(Math.Cos(lat)) < EPS)
{
if (Math.Abs(Math.Cos(lat)) < EPS) {
lon = 0.0; //endpoint a pole
}
else
{
} else {
dlon = Math.Atan2(Math.Sin(crs12) * Math.Sin(d12) * Math.Cos(lat1),
Math.Cos(d12) - Math.Sin(lat1) * Math.Sin(lat));
lon = ModM.Mod(lon1 - dlon + Math.PI, 2 * Math.PI) - Math.PI;
}
return new double[] { lat, lon };
return new Double[] { lat, lon };
}
public static double[] Dist_Ell(double glat1, double glon1, double glat2, double glon2, double[] ellipse)
{
double a = ellipse[0]; //Equitorial Radius
double f = 1 / ellipse[1]; //Flattening
public static Double[] Dist_Ell(Double glat1, Double glon1, Double glat2, Double glon2, Double[] ellipse) {
Double a = ellipse[0]; //Equitorial Radius
Double f = 1 / ellipse[1]; //Flattening
double r, tu1, tu2, cu1, su1, cu2, s1, b1, f1;
double x = 0, sx = 0, cx = 0, sy = 0, cy = 0, y = 0, sa = 0, c2a = 0, cz = 0, e = 0, c = 0, d = 0;
double EPS = 0.00000000005;
double faz, baz, s;
double iter = 1;
double MAXITER = 100;
if ((glat1 + glat2 == 0.0) && (Math.Abs(glon1 - glon2) == Math.PI))
{
Double r, tu1, tu2, cu1, su1, cu2, s1, b1, f1;
Double sx = 0, cx = 0, sy = 0, cy = 0, y = 0, c2a = 0, cz = 0, e = 0;
Double EPS = 0.00000000005;
Double faz, baz, s;
Double iter = 1;
Double MAXITER = 100;
if (glat1 + glat2 == 0.0 && Math.Abs(glon1 - glon2) == Math.PI) {
Debug.WriteLine("Warning: Course and distance between antipodal points is undefined");
glat1 = glat1 + 0.00001; // allow algorithm to complete
glat1 += 0.00001; // allow algorithm to complete
}
if (glat1 == glat2 && (glon1 == glon2 || Math.Abs(Math.Abs(glon1 - glon2) - 2 * Math.PI) < EPS))
{
if (glat1 == glat2 && (glon1 == glon2 || Math.Abs(Math.Abs(glon1 - glon2) - 2 * Math.PI) < EPS)) {
Debug.WriteLine("Warning: Points 1 and 2 are identical- course undefined");
//D
//crs12
//crs21
return new double[] { 0, 0, Math.PI };
return new Double[] { 0, 0, Math.PI };
}
r = 1 - f;
tu1 = r * Math.Tan(glat1);
@ -395,11 +337,11 @@ namespace CoordinateSharp
s1 = cu1 * cu2;
b1 = s1 * tu2;
f1 = b1 * tu1;
x = glon2 - glon1;
d = x + 1; // force one pass
while ((Math.Abs(d - x) > EPS) && (iter < MAXITER))
{
iter = iter + 1;
Double x = glon2 - glon1;
Double d = x + 1;
Double c;
while (Math.Abs(d - x) > EPS && iter < MAXITER) {
iter += 1;
sx = Math.Sin(x);
cx = Math.Cos(x);
tu1 = cu2 * sx;
@ -407,11 +349,10 @@ namespace CoordinateSharp
sy = Math.Sqrt(tu1 * tu1 + tu2 * tu2);
cy = s1 * cx + f1;
y = Math.Atan2(sy, cy);
sa = s1 * sx / sy;
Double sa = s1 * sx / sy;
c2a = 1 - sa * sa;
cz = f1 + f1;
if (c2a > 0.0)
{
if (c2a > 0.0) {
cz = cy - cz / c2a;
}
e = cz * cz * 2.0 - 1.0;
@ -431,12 +372,11 @@ namespace CoordinateSharp
x = e * cy;
s = ((((sy * sy * 4.0 - 3.0) * (1.0 - e - e) * cz * d / 6.0 - x) * d / 4.0 + cz) * sy * d + y) * c * a * r;
if (Math.Abs(iter - MAXITER) < EPS)
{
if (Math.Abs(iter - MAXITER) < EPS) {
Debug.WriteLine("Warning: Distance algorithm did not converge");
}
return new double[] { s, faz, baz };
return new Double[] { s, faz, baz };
}
}
}

View File

@ -2,11 +2,9 @@
using System.Collections.Generic;
using System.Linq;
namespace CoordinateSharp.Eclipse
{
internal class LunarData
{
static double[] LE1601 = new double[] {
namespace CoordinateSharp.Eclipse {
internal class LunarData {
static readonly Double[] LE1601 = new Double[] {
// 1601 1 18
2305831.105839, 15.0, 117.3, 0.033, -0.978, 3,
-1.13536, 0.98335, 0.26794,
@ -1501,7 +1499,7 @@ namespace CoordinateSharp.Eclipse
-3.09161, -1.92390, -0.82385, 0.02344, 0.87082, 1.97089, 3.13800,
337.8589683, 0.48164, -1.510e-04,
-9.4195702, 0.13945, 3.390e-04 };
static double[] LE1701 = new double[]
static readonly Double[] LE1701 = new Double[]
{
// 1701 2 22
2342390.479120, 23.0, 8.2, 1.428, 0.463, 2,
@ -3040,7 +3038,7 @@ namespace CoordinateSharp.Eclipse
9.1688605, 0.46956, -7.000e-05,
3.0790301, 0.25315, -2.000e-04
};
static double[] LE1801 = new double[]
static readonly Double[] LE1801 = new Double[]
{
// 1801 3 30
2378949.725057, 5.0, 13.0, 2.857, 1.840, 1,
@ -4537,7 +4535,7 @@ namespace CoordinateSharp.Eclipse
72.2570493, 0.64062, -1.660e-04,
21.3680795, 0.01873, -1.222e-03
};
static double[] LE1901 = new double[]
static readonly Double[] LE1901 = new Double[]
{
// 1901 5 3
2415508.271269, 19.0, -0.9, 1.043, -0.033, 3,
@ -5914,7 +5912,7 @@ namespace CoordinateSharp.Eclipse
296.2552752, 0.52835, -1.150e-04,
-21.2212594, 0.04170, 8.250e-04
};
static double[] LE2001 = new double[]
static readonly Double[] LE2001 = new Double[]
{
// 2001 1 9
2451919.348374, 20.0, 64.1, 2.162, 1.189, 1,
@ -7285,7 +7283,7 @@ namespace CoordinateSharp.Eclipse
329.8184696, 0.49978, -6.760e-04,
-13.3626205, 0.22960, 3.990e-04
};
static double[] LE2101 = new double[]
static readonly Double[] LE2101 = new Double[]
{
// 2101 2 14
2488478.618055, 3.0, 205.1, 2.218, 1.183, 1,
@ -8716,7 +8714,7 @@ namespace CoordinateSharp.Eclipse
28.0294400, 0.59158, 9.000e-05,
10.7019400, 0.15900, -6.160e-04
};
static double[] LE2201 = new double[]
static readonly Double[] LE2201 = new Double[]
{
// 2201 3 20
2525037.204912, 17.0, 444.3, 0.532, -0.560, 3,
@ -10231,7 +10229,7 @@ namespace CoordinateSharp.Eclipse
63.0500500, 0.65278, 8.590e-04,
21.0508309, 0.17085, -1.218e-03
};
static double[] LE2301 = new double[]
static readonly Double[] LE2301 = new Double[]
{
// 2301 5 23
2561625.186996, 16.0, 720.0, 1.809, 0.754, 2,
@ -11752,7 +11750,7 @@ namespace CoordinateSharp.Eclipse
101.2753539, 0.59275, -1.730e-04,
23.7726800, -0.09243, -1.170e-03
};
static double[] LE2401 = new double[] {
static readonly Double[] LE2401 = new Double[] {
// 2401 6 26
2598183.958214, 11.0, 1059.4, 2.107, 1.139, 1,
5.31800, 0.99489, 0.27108,
@ -13176,7 +13174,7 @@ namespace CoordinateSharp.Eclipse
348.3334732, 0.58130, -3.870e-04,
-5.5431301, 0.18349, 2.190e-04
};
static double[] LE2501 = new double[] {
static readonly Double[] LE2501 = new Double[] {
// 2501 3 6
2634595.801080, 7.0, 1461.0, 0.491, -0.599, 3,
17.93340, 0.90700, 0.24714,
@ -14541,66 +14539,45 @@ namespace CoordinateSharp.Eclipse
8.0835801, 0.28700, -3.300e-04
};
public static double[] LunarDateData(DateTime d)
{
public static Double[] LunarDateData(DateTime d) {
//Return combined 100 year arrays so in order to grab Last and Next exlipLE.
List<double[]> data = new List<double[]>()
List<Double[]> data = new List<Double[]>()
{
LE1601, LE1701,LE1801, LE1901, LE2001,
LE2101,LE2201, LE2301, LE2401, LE2501
};
double cent = Math.Floor(d.Year * .01) * 100; //Gets turn of century year.
int index = GetIndex(cent); //Gets index for calling data list.
Double cent = Math.Floor(d.Year * .01) * 100; //Gets turn of century year.
Int32 index = GetIndex(cent); //Gets index for calling data list.
if (index == -1) { return new double[] { }; } //RETURN EMPTY ARRAY IF OUTSIDE DB RANGE
if (index == -1) { return new Double[] { }; } //RETURN EMPTY ARRAY IF OUTSIDE DB RANGE
//Determine data to LEnd if year is near beginning or end of databaLE
int halfCent = d.Year - (int)cent;
if (index == 0 || index == data.Count - 1)
{
if (index == 0)
{
if (halfCent <= 50) { return data[0]; }
else { return data[0].Concat(data[1]).ToArray(); }
}
else
{
if (halfCent <= 50) { return data[index - 1].Concat(data[index]).ToArray(); }
else { return data[index]; }
}
}
else
{
if (halfCent <= 50) { return data[index - 1].Concat(data[index]).ToArray(); }
else { return data[index].Concat(data[index + 1]).ToArray(); }
}
Int32 halfCent = d.Year - (Int32)cent;
return index == 0 || index == data.Count - 1 ? index == 0 ? halfCent <= 50 ? data[0] : data[0].Concat(data[1]).ToArray() : halfCent <= 50 ? data[index - 1].Concat(data[index]).ToArray() : data[index] : halfCent <= 50 ? data[index - 1].Concat(data[index]).ToArray() : data[index].Concat(data[index + 1]).ToArray();
}
public static double[] LunarDateData_100Year(DateTime d)
{
public static Double[] LunarDateData_100Year(DateTime d) {
//Return combined 100 year arrays
List<double[]> data = new List<double[]>()
List<Double[]> data = new List<Double[]>()
{
LE1601, LE1701,LE1801, LE1901, LE2001,
LE2101,LE2201, LE2301, LE2401, LE2501
};
double cent = Math.Floor(d.Year * .01) * 100; //Gets turn of century year.
int index = GetIndex(cent); //Gets index for calling data list.
Double cent = Math.Floor(d.Year * .01) * 100; //Gets turn of century year.
Int32 index = GetIndex(cent); //Gets index for calling data list.
if (index == -1) { return new double[] { }; } //RETURN EMPTY ARRAY IF OUTSIDE DB RANGE
if (index == -1) { return new Double[] { }; } //RETURN EMPTY ARRAY IF OUTSIDE DB RANGE
//Return proper 100 year table.
return data[index];
}
private static int GetIndex(double cent)
{
int dex = 0;
int c = Convert.ToInt32(cent * .01);
private static Int32 GetIndex(Double cent) {
Int32 dex = 0;
Int32 c = Convert.ToInt32(cent * .01);
//START CENTURY 16
//END CENTRURY 26
//AJDUST AS DATABALE GROWS
for (int i = 16; i < 26; i++)
{
for (Int32 i = 16; i < 26; i++) {
if (i == c) { return dex; }
dex++;
}

View File

@ -2,12 +2,10 @@
using System.Collections.Generic;
using System.Linq;
namespace CoordinateSharp.Eclipse
{
internal class SolarData
{
namespace CoordinateSharp.Eclipse {
internal class SolarData {
//ECLIPSE DATA FROM 1701-2400
static double[] SE1601 = new double[]
static readonly Double[] SE1601 = new Double[]
{
// 1601 1 4
2305817.017109, 12.0, -4.0, 4.0, 117.4, 117.4,
@ -2242,7 +2240,7 @@ namespace CoordinateSharp.Eclipse
-0.0114460, 0.0000434, -1.270e-05,
0.0046524, 0.0046293
};
static double[] SE1701 = new double[]
static readonly Double[] SE1701 = new Double[]
{
// 1701 2 7
2342375.461729, 23.0, -4.0, 4.0, 8.2, 8.2,
@ -4504,7 +4502,7 @@ namespace CoordinateSharp.Eclipse
-0.0039760, -0.0000963, -1.230e-05,
0.0046973, 0.0046739
};
static double[] SE1801 = new double[]
static readonly Double[] SE1801 = new Double[]
{
// 1801 3 14
2378934.156652, 16.0, -4.0, 4.0, 13.0, 13.0,
@ -6684,7 +6682,7 @@ namespace CoordinateSharp.Eclipse
0.5676560, -0.0000826, -1.030e-05,
0.0214110, -0.0000822, -1.030e-05,
0.0047365, 0.0047129};
static double[] SE1901 = new double[]
static readonly Double[] SE1901 = new Double[]
{
// 1901 5 18
2415522.731807, 6.0, -4.0, 4.0, -0.9, -0.9,
@ -8739,7 +8737,7 @@ namespace CoordinateSharp.Eclipse
0.0268200, 0.0000511, -1.000e-05,
0.0047553, 0.0047316
};
static double[] SE2001 = new double[]
static readonly Double[] SE2001 = new Double[]
{
// 2001 6 21
2452082.003314, 12.0, -4.0, 4.0, 64.2, 64.2,
@ -10758,7 +10756,7 @@ namespace CoordinateSharp.Eclipse
-0.0062330, -0.0001026, -1.200e-05,
0.0046346, 0.0046116
};
static double[] SE2101 = new double[]
static readonly Double[] SE2101 = new Double[]
{
// 2101 2 28
2488492.594741, 2.0, -4.0, 4.0, 205.2, 205.2,
@ -12876,7 +12874,7 @@ namespace CoordinateSharp.Eclipse
0.0190180, -0.0000736, -1.010e-05,
0.0046769, 0.0046536
};
static double[] SE2201 = new double[]
static readonly Double[] SE2201 = new Double[]
{
// 2201 4 4
2525051.763849, 6.0, -4.0, 4.0, 444.4, 444.4,
@ -15111,7 +15109,7 @@ namespace CoordinateSharp.Eclipse
0.0284480, 0.0000235, -9.800e-06,
0.0047462, 0.0047226
};
static double[] SE2301 = new double[]
static readonly Double[] SE2301 = new Double[]
{
// 2301 5 9
2561611.084014, 14.0, -4.0, 4.0, 719.9, 719.9,
@ -17346,7 +17344,7 @@ namespace CoordinateSharp.Eclipse
-0.0071310, -0.0001059, -1.190e-05,
0.0046006, 0.0045776
};
static double[] SE2401 = new double[] {
static readonly Double[] SE2401 = new Double[] {
// 2401 1 14
2598021.427310, 22.0, -4.0, 4.0, 1057.8, 1057.8,
-0.2870830, 0.5189539, -4.590e-05, -7.000e-06,
@ -19481,7 +19479,7 @@ namespace CoordinateSharp.Eclipse
0.0163870, -0.0000706, -1.000e-05,
0.0046201, 0.0045971
};
static double[] SE2501 = new double[] {
static readonly Double[] SE2501 = new Double[] {
// 2501 2 19
2634580.691215, 5.0, -4.0, 4.0, 1460.8, 1460.8,
0.1813720, 0.5619451, -3.330e-05, -9.490e-06,
@ -21508,68 +21506,47 @@ namespace CoordinateSharp.Eclipse
0.0248230, 0.0000365, -9.800e-06,
0.0046944, 0.0046710 };
public static double[] SolarDateData(DateTime d)
{
public static Double[] SolarDateData(DateTime d) {
//Return combined 100 year arrays so in order to grab Last and Next exlipse.
List<double[]> data = new List<double[]>()
List<Double[]> data = new List<Double[]>()
{
SE1601, SE1701, SE1801, SE1901, SE2001,
SE2101, SE2201, SE2301, SE2401, SE2501
};
double cent = Math.Floor(d.Year * .01) * 100; //Gets turn of century year.
int index = GetIndex(cent); //Gets index for calling data list.
Double cent = Math.Floor(d.Year * .01) * 100; //Gets turn of century year.
Int32 index = GetIndex(cent); //Gets index for calling data list.
if (index == -1) { return new double[] { };} //RETURN EMPTY ARRAY IF OUTSIDE DB RANGE
if (index == -1) { return new Double[] { }; } //RETURN EMPTY ARRAY IF OUTSIDE DB RANGE
//Determine data to send if year is near beginning or end of database
int halfCent = d.Year - (int)cent;
Int32 halfCent = d.Year - (Int32)cent;
if (index == 0 || index == data.Count - 1)
{
if(index == 0)
{
if (halfCent <= 50) { return data[0]; }
else { return data[0].Concat(data[1]).ToArray(); }
}
else
{
if (halfCent <= 50) { return data[index - 1].Concat(data[index]).ToArray(); }
else { return data[index]; }
}
}
else
{
if (halfCent <= 50) { return data[index - 1].Concat(data[index]).ToArray(); }
else { return data[index].Concat(data[index+1]).ToArray(); }
}
return index == 0 || index == data.Count - 1 ? index == 0 ? halfCent <= 50 ? data[0] : data[0].Concat(data[1]).ToArray() : halfCent <= 50 ? data[index - 1].Concat(data[index]).ToArray() : data[index] : halfCent <= 50 ? data[index - 1].Concat(data[index]).ToArray() : data[index].Concat(data[index + 1]).ToArray();
}
public static double[] SolarDateData_100Year(DateTime d)
{
public static Double[] SolarDateData_100Year(DateTime d) {
//Return combined 100 year arrays
List<double[]> data = new List<double[]>()
List<Double[]> data = new List<Double[]>()
{
SE1601, SE1701, SE1801, SE1901, SE2001,
SE2101, SE2201, SE2301, SE2401, SE2501
};
double cent = Math.Floor(d.Year * .01) * 100; //Gets turn of century year.
int index = GetIndex(cent); //Gets index for calling data list.
Double cent = Math.Floor(d.Year * .01) * 100; //Gets turn of century year.
Int32 index = GetIndex(cent); //Gets index for calling data list.
if (index == -1) { return new double[] { }; } //RETURN EMPTY ARRAY IF OUTSIDE DB RANGE
if (index == -1) { return new Double[] { }; } //RETURN EMPTY ARRAY IF OUTSIDE DB RANGE
//Return proper 100 year table.
return data[index];
}
private static int GetIndex(double cent)
{
int dex = 0;
int c = Convert.ToInt32(cent * .01);
private static Int32 GetIndex(Double cent) {
Int32 dex = 0;
Int32 c = Convert.ToInt32(cent * .01);
//START CENTURY 16
//END CENTRURY 26
//AJDUST AS DATABASE GROWS
for(int i = 16; i<26;i++)
{
if(i == c) { return dex; }
for (Int32 i = 16; i < 26; i++) {
if (i == c) { return dex; }
dex++;
}
return -1;

View File

@ -1,59 +1,48 @@
using System.Collections.Generic;
using System.Linq;
using System;
using System.Collections.Generic;
namespace CoordinateSharp
{
namespace CoordinateSharp {
/// <summary>
/// Geo Fence class. It helps to check if points/coordinates are inside a polygon,
/// Next to a polyline, and counting...
/// </summary>
public class GeoFence
{
public class GeoFence {
#region Fields
private List<Point> _points = new List<Point>();
private readonly List<Point> _points = new List<Point>();
#endregion
/// <summary>
/// Prepare GeoFence with a list of points
/// </summary>
/// <param name="points">List of points</param>
public GeoFence(List<Point> points)
{
_points = points;
}
public GeoFence(List<Point> points) => this._points = points;
/// <summary>
/// Prepare Geofence with a list of coordinates
/// </summary>
/// <param name="coordinates">List of coordinates</param>
public GeoFence(List<Coordinate> coordinates)
{
foreach (var c in coordinates)
{
_points.Add(new Point { Latitude = c.Latitude.ToDouble(), Longitude = c.Longitude.ToDouble() });
public GeoFence(List<Coordinate> coordinates) {
foreach (Coordinate c in coordinates) {
this._points.Add(new Point { Latitude = c.Latitude.ToDouble(), Longitude = c.Longitude.ToDouble() });
}
}
#region Utils
private Coordinate ClosestPointOnSegment(Point a, Point b, Coordinate p)
{
var d = new Point
{
private Coordinate ClosestPointOnSegment(Point a, Point b, Coordinate p) {
Point d = new Point {
Longitude = b.Longitude - a.Longitude,
Latitude = b.Latitude - a.Latitude,
};
double number = (p.Longitude.ToDouble() - a.Longitude) * d.Longitude + (p.Latitude.ToDouble() - a.Latitude) * d.Latitude;
Double number = (p.Longitude.ToDouble() - a.Longitude) * d.Longitude + (p.Latitude.ToDouble() - a.Latitude) * d.Latitude;
if (number <= 0.0)
if (number <= 0.0) {
return new Coordinate(a.Latitude, a.Longitude);
}
double denom = d.Longitude * d.Longitude + d.Latitude * d.Latitude;
Double denom = d.Longitude * d.Longitude + d.Latitude * d.Latitude;
if (number >= denom)
return new Coordinate(b.Latitude, b.Longitude);
return new Coordinate(a.Latitude + (number / denom) * d.Latitude, a.Longitude + (number / denom) * d.Longitude);
return number >= denom ? new Coordinate(b.Latitude, b.Longitude) : new Coordinate(a.Latitude + number / denom * d.Latitude, a.Longitude + number / denom * d.Longitude);
}
#endregion
@ -64,22 +53,19 @@ namespace CoordinateSharp
/// </summary>
/// <param name="point">The point to test</param>
/// <returns>bool</returns>
public bool IsPointInPolygon(Coordinate point)
{
if (point == null)
public Boolean IsPointInPolygon(Coordinate point) {
if (point == null) {
return false;
}
double latitude = point.Latitude.ToDouble();
double longitude = point.Longitude.ToDouble();
int sides = _points.Count;
int j = sides - 1;
bool pointStatus = false;
for (int i = 0; i < sides; i++)
{
if (_points[i].Latitude < latitude && _points[j].Latitude >= latitude || _points[j].Latitude < latitude && _points[i].Latitude >= latitude)
{
if (_points[i].Longitude + (latitude - _points[i].Latitude) / (_points[j].Latitude - _points[i].Latitude) * (_points[j].Longitude - _points[i].Longitude) < longitude)
{
Double latitude = point.Latitude.ToDouble();
Double longitude = point.Longitude.ToDouble();
Int32 sides = this._points.Count;
Int32 j = sides - 1;
Boolean pointStatus = false;
for (Int32 i = 0; i < sides; i++) {
if (this._points[i].Latitude < latitude && this._points[j].Latitude >= latitude || this._points[j].Latitude < latitude && this._points[i].Latitude >= latitude) {
if (this._points[i].Longitude + (latitude - this._points[i].Latitude) / (this._points[j].Latitude - this._points[i].Latitude) * (this._points[j].Longitude - this._points[i].Longitude) < longitude) {
pointStatus = !pointStatus;
}
}
@ -95,17 +81,17 @@ namespace CoordinateSharp
/// <param name="point">The point to test</param>
/// <param name="range">The range in meters</param>
/// <returns>bool</returns>
public bool IsPointInRangeOfLine(Coordinate point, double range)
{
if (point == null)
public Boolean IsPointInRangeOfLine(Coordinate point, Double range) {
if (point == null) {
return false;
}
for (int i = 0; i < _points.Count - 1; i++)
{
Coordinate c = ClosestPointOnSegment(_points[i], _points[i + 1], point);
if (c.Get_Distance_From_Coordinate(point).Meters <= range)
for (Int32 i = 0; i < this._points.Count - 1; i++) {
Coordinate c = this.ClosestPointOnSegment(this._points[i], this._points[i + 1], point);
if (c.Get_Distance_From_Coordinate(point).Meters <= range) {
return true;
}
}
return false;
}
@ -117,25 +103,17 @@ namespace CoordinateSharp
/// <param name="point">The point to test</param>
/// <param name="range">The range is a distance object</param>
/// <returns>bool</returns>
public bool IsPointInRangeOfLine(Coordinate point, Distance range)
{
if (point == null || range == null)
return false;
return IsPointInRangeOfLine(point, range.Meters);
}
public Boolean IsPointInRangeOfLine(Coordinate point, Distance range) => point == null || range == null ? false : this.IsPointInRangeOfLine(point, range.Meters);
/// <summary>
/// This class is a help class to simplify GeoFence calculus
/// </summary>
public class Point
{
public class Point {
/// <summary>
/// Initialize empty point
/// </summary>
public Point()
{
public Point() {
}
/// <summary>
@ -143,19 +121,18 @@ namespace CoordinateSharp
/// </summary>
/// <param name="lat">Latitude (signed)</param>
/// <param name="lng">Longitude (signed)</param>
public Point(double lat, double lng)
{
Latitude = lat;
Longitude = lng;
public Point(Double lat, Double lng) {
this.Latitude = lat;
this.Longitude = lng;
}
/// <summary>
/// The longitude in degrees
/// </summary>
public double Longitude;
public Double Longitude;
/// <summary>
/// The latitude in degrees
/// </summary>
public double Latitude;
public Double Latitude;
}
}
}

View File

@ -1,4 +1,5 @@
using System.Reflection;
#if !NETCOREAPP
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@ -34,3 +35,4 @@ using System.Runtime.InteropServices;
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.1.5.2")]
[assembly: AssemblyFileVersion("1.1.5.2")]
#endif

25
CoordinateSharp_Core.sln Normal file
View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29519.87
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoordinateSharp", "CoordinateSharp\CoordinateSharp_Core.csproj", "{127E1C0F-06DC-492C-B124-19A89D44B47C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{127E1C0F-06DC-492C-B124-19A89D44B47C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{127E1C0F-06DC-492C-B124-19A89D44B47C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{127E1C0F-06DC-492C-B124-19A89D44B47C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{127E1C0F-06DC-492C-B124-19A89D44B47C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {667C979D-42C3-4EE8-9B2B-D85EFC09940A}
EndGlobalSection
EndGlobal