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

View File

@ -1,14 +1,9 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CoordinateSharp namespace CoordinateSharp {
{ internal partial class MeeusTables {
internal partial class MeeusTables
{
//Ch 47 //Ch 47
private static double[] Table47A_Arguments = new double[] private static readonly Double[] Table47A_Arguments = new Double[]
{ {
0,0,1,0, 0,0,1,0,
2,0,-1,0, 2,0,-1,0,
@ -72,7 +67,7 @@ namespace CoordinateSharp
2,0,3,0, 2,0,3,0,
2,0,-1,-2 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,0,1,
0,0,1,1, 0,0,1,1,
@ -136,7 +131,7 @@ namespace CoordinateSharp
4,-1,0,-1, 4,-1,0,-1,
2,-2,0,1, 2,-2,0,1,
}; };
private static double[] Table47A_El_Er = new double[] private static readonly Double[] Table47A_El_Er = new Double[]
{ {
//El //El
6288774, 1274027,658314,213618,-185116,-114332,58793,57066,53322,45758, 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 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, 5128122,280602,277693,173237,55413,46271,32573,17198,9266,8822,
8216,4324,4200,-3359,2463,2211,2065,-1870,1828,-1794,-1749,-1565,-1491, 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, 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 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 true returns El
//sine false return Er //sine false return Er
//Er values start at 60 in the Table47A_El_Er array. //Er values start at 60 in the Table47A_El_Er array.
int nl = l * 4; Int32 nl = l * 4;
if (sine) if (sine) {
{ Double e = 1;
double e = 1;
if (Table47A_Arguments[nl + 1] != 0) if (Table47A_Arguments[nl + 1] != 0) {
{
e = 1 - .002516 * t - .0000074 * Math.Pow(t, 2); 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; e *= e;
} }
} }
return (Table47A_El_Er[l] * e) * Math.Sin(Table47A_Arguments[nl] * values[0] + Table47A_Arguments[nl + 1] * values[1] + 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]);
Table47A_Arguments[nl + 2] * values[2] + Table47A_Arguments[nl + 3] * values[3]); } else {
} Double e = 1;
else if (Table47A_Arguments[nl + 1] != 0) {
{
double e = 1;
if (Table47A_Arguments[nl + 1] != 0)
{
e = 1 - .002516 * t - .0000074 * Math.Pow(t, 2); 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; e *= e;
} }
} }
return (Table47A_El_Er[l + 60] * e) * Math.Cos(Table47A_Arguments[nl] * values[0] + Table47A_Arguments[nl + 1] * values[1] + 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]);
Table47A_Arguments[nl + 2] * values[2] + Table47A_Arguments[nl + 3] * values[3]);
} }
} }
private static double Get_Table47B_Values(double[] values, int l, double t) private static Double Get_Table47B_Values(Double[] values, Int32 l, Double t) {
{ Int32 nl = l * 4;
int nl = l * 4; Double e = 1;
double e = 1;
if (Table47B_Arguments[nl + 1] != 0) if (Table47B_Arguments[nl + 1] != 0) {
{
e = 1 - .002516 * t - .0000074 * Math.Pow(t, 2); 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; e *= e;
} }
} }
return (Table47B_Eb[l] * e) * Math.Sin(Table47B_Arguments[nl] * values[0] + Table47B_Arguments[nl + 1] * values[1] + 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]);
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;
using System.Collections.Generic; using System.Collections.Generic;
namespace CoordinateSharp
{ namespace CoordinateSharp {
internal class SunCalc internal class SunCalc {
{ public static void CalculateSunTime(Double lat, Double longi, DateTime date, Celestial c, Double _ = 0) {
public static void CalculateSunTime(double lat, double longi, DateTime date, Celestial c,double offset = 0)
{
if (date.Year == 0001) { return; } //Return if date vaue hasn't been established. 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 ////Sun Time Calculations
//Get Julian //Get Julian
double lw = rad * -longi; Double lw = rad * -longi;
double phi = rad * lat; Double phi = rad * lat;
//Rise Set //Rise Set
DateTime?[] evDate = Get_Event_Time(lw, phi, -.8333, actualDate); DateTime?[] evDate = Get_Event_Time(lw, phi, -.8333, actualDate);
@ -24,28 +22,16 @@ namespace CoordinateSharp
//Azimuth and Altitude //Azimuth and Altitude
CalculateSunAngle(date, longi, lat, c); CalculateSunAngle(date, longi, lat, c);
// neither sunrise nor sunset // neither sunrise nor sunset
if ((!c.SunRise.HasValue) && (!c.SunSet.HasValue)) if (!c.SunRise.HasValue && !c.SunSet.HasValue) {
{ c.sunCondition = c.SunAltitude < 0 ? CelestialStatus.DownAllDay : CelestialStatus.UpAllDay;
if (c.SunAltitude < 0)
{
c.sunCondition = CelestialStatus.DownAllDay;
}
else
{
c.sunCondition = CelestialStatus.UpAllDay;
}
} }
// sunrise or sunset // sunrise or sunset
else else {
{ if (!c.SunRise.HasValue) {
if (!c.SunRise.HasValue)
{
// No sunrise this date // No sunrise this date
c.sunCondition = CelestialStatus.NoRise; c.sunCondition = CelestialStatus.NoRise;
} } else if (!c.SunSet.HasValue) {
else if (!c.SunSet.HasValue)
{
// No sunset this date // No sunset this date
c.sunCondition = CelestialStatus.NoSet; c.sunCondition = CelestialStatus.NoSet;
} }
@ -86,34 +72,32 @@ namespace CoordinateSharp
/// <param name="h">Angle in Degrees</param> /// <param name="h">Angle in Degrees</param>
/// <param name="date">Date of Event</param> /// <param name="date">Date of Event</param>
/// <returns>DateTime?[]{rise, set}</returns> /// <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; //Create arrays. Index 0 = Day -1, 1 = Day, 2 = Day + 1;
//These will be used to find exact day event occurs for comparison //These will be used to find exact day event occurs for comparison
DateTime?[] sets = new DateTime?[] { null, null, null, null, null }; 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; //Iterate starting with day -1;
for (int x = 0; x < 5; x++) for (Int32 x = 0; x < 5; x++) {
{ Double d = JulianConversions.GetJulian(date.AddDays(x - 2)) - j2000 + .5; //LESS PRECISE JULIAN NEEDED
double d = JulianConversions.GetJulian(date.AddDays(x-2)) - j2000 + .5; //LESS PRECISE JULIAN NEEDED
double n = julianCycle(d, lw); Double n = JulianCycle(d, lw);
double ds = approxTransit(0, lw, n); Double ds = ApproxTransit(0, lw, n);
double M = solarMeanAnomaly(ds); Double M = SolarMeanAnomaly(ds);
double L = eclipticLongitude(M); 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 Jset;
double Jrise; Double Jrise;
DateTime? solarNoon = JulianConversions.GetDate_FromJulian(Jnoon); //DateTime? solarNoon = JulianConversions.GetDate_FromJulian(Jnoon);
DateTime? nadir = JulianConversions.GetDate_FromJulian(Jnoon - 0.5); //DateTime? nadir = JulianConversions.GetDate_FromJulian(Jnoon - 0.5);
//Rise Set //Rise Set
Jset = GetTime(h * rad, lw, phi, dec, n, M, L); Jset = GetTime(h * rad, lw, phi, dec, n, M, L);
@ -128,24 +112,18 @@ namespace CoordinateSharp
//Compare and send //Compare and send
DateTime? tRise = null; DateTime? tRise = null;
for(int x=0;x<5;x++) for (Int32 x = 0; x < 5; x++) {
{ if (rises[x].HasValue) {
if(rises[x].HasValue) if (rises[x].Value.Day == date.Day) {
{
if(rises[x].Value.Day == date.Day)
{
tRise = rises[x]; tRise = rises[x];
break; break;
} }
} }
} }
DateTime? tSet = null; DateTime? tSet = null;
for (int x = 0; x < 5; x++) for (Int32 x = 0; x < 5; x++) {
{ if (sets[x].HasValue) {
if (sets[x].HasValue) if (sets[x].Value.Day == date.Day) {
{
if (sets[x].Value.Day == date.Day)
{
tSet = sets[x]; tSet = sets[x];
break; break;
} }
@ -154,8 +132,7 @@ namespace CoordinateSharp
return new DateTime?[] { tRise, tSet }; 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) //Aquarius (January 20 to February 18)
//Pisces (February 19 to March 20) //Pisces (February 19 to March 20)
//Aries (March 21-April 19) //Aries (March 21-April 19)
@ -168,202 +145,169 @@ namespace CoordinateSharp
//Scorpio (October 23-November 21) //Scorpio (October 23-November 21)
//Sagittarius (November 22-December 21) //Sagittarius (November 22-December 21)
//Capricorn (December 22-January 19) //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"; c.AstrologicalSigns.ZodiacSign = "Capricorn";
return; 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"; c.AstrologicalSigns.ZodiacSign = "Aquarius";
return; 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"; c.AstrologicalSigns.ZodiacSign = "Pisces";
return; 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"; c.AstrologicalSigns.ZodiacSign = "Aries";
return; 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"; c.AstrologicalSigns.ZodiacSign = "Taurus";
return; 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"; c.AstrologicalSigns.ZodiacSign = "Gemini";
return; 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"; c.AstrologicalSigns.ZodiacSign = "Cancer";
return; 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"; c.AstrologicalSigns.ZodiacSign = "Leo";
return; 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"; c.AstrologicalSigns.ZodiacSign = "Virgo";
return; 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"; c.AstrologicalSigns.ZodiacSign = "Libra";
return; 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"; c.AstrologicalSigns.ZodiacSign = "Scorpio";
return; 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"; c.AstrologicalSigns.ZodiacSign = "Sagittarius";
return; 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"; c.AstrologicalSigns.ZodiacSign = "Capricorn";
return; 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 //Convert to Radian
double latR = lat * Math.PI / 180; Double latR = lat * Math.PI / 180;
double longR = longi * Math.PI / 180; Double longR = longi * Math.PI / 180;
List<List<string>> se = SolarEclipseCalc.CalculateSolarEclipse(date, latR, longR); List<List<String>> se = SolarEclipseCalc.CalculateSolarEclipse(date, latR, longR);
//RETURN FIRST AND LAST //RETURN FIRST AND LAST
if (se.Count == 0) { return; } if (se.Count == 0) { return; }
//FIND LAST AND NEXT ECLIPSE //FIND LAST AND NEXT ECLIPSE
int lastE = -1; Int32 lastE = -1;
int nextE = -1; Int32 nextE = -1;
int currentE = 0; Int32 currentE = 0;
DateTime lastDate = new DateTime(); DateTime lastDate = new DateTime();
DateTime nextDate = new DateTime(3300, 1, 1); DateTime nextDate = new DateTime(3300, 1, 1);
//Iterate to get last and next eclipse //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); 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 > lastDate) { lastDate = ld; lastE = currentE; }
if(ld>= date && ld < nextDate) { nextDate = ld;nextE = currentE; } if (ld >= date && ld < nextDate) { nextDate = ld; nextE = currentE; }
currentE++; currentE++;
} }
//SET ECLIPSE DATA //SET ECLIPSE DATA
if (lastE >= 0) if (lastE >= 0) {
{
c.SolarEclipse.LastEclipse = new SolarEclipseDetails(se[lastE]); c.SolarEclipse.LastEclipse = new SolarEclipseDetails(se[lastE]);
} }
if (nextE >= 0) if (nextE >= 0) {
{
c.SolarEclipse.NextEclipse = new SolarEclipseDetails(se[nextE]); c.SolarEclipse.NextEclipse = new SolarEclipseDetails(se[nextE]);
} }
} }
#region Private Suntime Members #region Private Suntime Members
private static readonly double dayMS = 1000 * 60 * 60 * 24, j1970 = 2440588, j2000 = 2451545; 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 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 / 86400;
s = s - Math.Truncate(s); s = s - Math.Truncate(s);
double lst = s * 360 *rad; Double lst = s * 360 *rad;
return lst; return lst;
} }*/
private static double SideRealTime(double d, double lw) private static Double SideRealTime(Double d, Double lw) {
{ Double s = rad * (280.16 + 360.9856235 * d) - lw;
double s = rad * (280.16 + 360.9856235 * d) - lw;
return s; return s;
} }
private static double solarTransitJ(double ds, double M, double L) private static Double SolarTransitJ(Double ds, Double M, Double L) => j2000 + ds + 0.0053 * Math.Sin(M) - 0.0069 * Math.Sin(2 * L);
{
return j2000 + ds + 0.0053 * Math.Sin(M) - 0.0069 * Math.Sin(2 * L);
}
//CH15 //CH15
//Formula 15.1 //Formula 15.1
//Returns Approximate Time //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; //NUMBER RETURNING > and < 1 NaN;
double d1 = Math.Sin(h) - Math.Sin(phi) * Math.Sin(d); Double d1 = Math.Sin(h) - Math.Sin(phi) * Math.Sin(d);
double d2 = Math.Cos(phi) * Math.Cos(d); Double d2 = Math.Cos(phi) * Math.Cos(d);
double d3 = (d1 / d2); Double d3 = d1 / d2;
return Math.Acos(d3); return Math.Acos(d3);
} }
private static double approxTransit(double Ht, double lw, double n) private static Double ApproxTransit(Double Ht, Double lw, Double n) => 0.0009 + (Ht + lw) / (2 * Math.PI) + n;
{
return 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 //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) 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 approxTime = hourAngle(h, phi, dec); //Ch15 Formula 15.1
double a = approxTransit(approxTime, lw, n); Double a = ApproxTransit(approxTime, lw, n);
double st = solarTransitJ(a, M, L); Double st = SolarTransitJ(a, M, L);
return st; return st;
} }
private static double declination(double l, double b) private static Double Declination(Double l, Double b) {
{ Double e = Math.PI / 180 * 23.4392911; // obliquity of the Earth
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)); 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) 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);
TimeSpan ts = date - new DateTime(1970, 1, 1,0,0,0, DateTimeKind.Utc); Double dms = ts.TotalMilliseconds / dayMS - .5 + j1970 - j2000;
double dms = (ts.TotalMilliseconds / dayMS -.5 + j1970)-j2000;
double lw = rad * -longi; Double lw = rad * -longi;
double phi = rad * lat; Double phi = rad * lat;
double e = rad * 23.4397; //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.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; 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) private static Double SolarMeanAnomaly(Double d) => rad * (357.5291 + 0.98560028 * d);
{
return rad * (357.5291 + 0.98560028 * d);
}
private static double eclipticLongitude(double m) 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 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
double p = rad * 102.9372; // perihelion of the Earth
return m + c + p + Math.PI; return m + c + p + Math.PI;
} }
private static double[] sunCoords(double d) private static Double[] SunCoords(Double d) {
{
double m = solarMeanAnomaly(d); Double m = SolarMeanAnomaly(d);
double l = eclipticLongitude(m); Double l = EclipticLongitude(m);
double[] sc = new double[2]; Double[] sc = new Double[2];
double b = 0; Double b = 0;
double e = rad * 23.4397; // obliquity of the Earth 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[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 sc[1] = Math.Atan2(Math.Sin(l) * Math.Cos(e) - Math.Tan(b) * Math.Sin(e), Math.Cos(l)); //rightAscension
return sc; return sc;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -34,8 +34,7 @@ SOFTWARE.
using System; using System;
using System.ComponentModel; using System.ComponentModel;
namespace CoordinateSharp namespace CoordinateSharp {
{
/// <summary> /// <summary>
/// Observable class for handling all location based information. /// Observable class for handling all location based information.
/// This is the main class for CoordinateSharp. /// 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 /// All information should be pulled from this class to include celestial information
/// </remarks> /// </remarks>
[Serializable] [Serializable]
public class Coordinate : INotifyPropertyChanged public class Coordinate : INotifyPropertyChanged {
{
/// <summary> /// <summary>
/// Creates an empty Coordinate. /// Creates an empty Coordinate.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Values will need to be provided to latitude/longitude CoordinateParts manually /// Values will need to be provided to latitude/longitude CoordinateParts manually
/// </remarks> /// </remarks>
public Coordinate() public Coordinate() {
{
this.FormatOptions = new CoordinateFormatOptions(); this.FormatOptions = new CoordinateFormatOptions();
this.geoDate = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc); this.geoDate = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc);
this.latitude = new CoordinatePart(CoordinateType.Lat); this.latitude = new CoordinatePart(CoordinateType.Lat);
@ -77,8 +74,7 @@ namespace CoordinateSharp
/// <remarks> /// <remarks>
/// Values will need to be provided to latitude/longitude CoordinateParts manually /// Values will need to be provided to latitude/longitude CoordinateParts manually
/// </remarks> /// </remarks>
internal Coordinate(Double equatorialRadius, Double inverseFlattening, Boolean t) internal Coordinate(Double equatorialRadius, Double inverseFlattening, Boolean _) {
{
this.FormatOptions = new CoordinateFormatOptions(); this.FormatOptions = new CoordinateFormatOptions();
this.geoDate = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc); this.geoDate = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc);
this.latitude = new CoordinatePart(CoordinateType.Lat); this.latitude = new CoordinatePart(CoordinateType.Lat);
@ -102,8 +98,7 @@ namespace CoordinateSharp
/// <remarks> /// <remarks>
/// Geodate will default to 1/1/1900 GMT until provided /// Geodate will default to 1/1/1900 GMT until provided
/// </remarks> /// </remarks>
public Coordinate(Double lat, Double longi) public Coordinate(Double lat, Double longi) {
{
this.FormatOptions = new CoordinateFormatOptions(); this.FormatOptions = new CoordinateFormatOptions();
this.geoDate = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc); this.geoDate = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc);
this.latitude = new CoordinatePart(lat, CoordinateType.Lat); this.latitude = new CoordinatePart(lat, CoordinateType.Lat);
@ -126,8 +121,7 @@ namespace CoordinateSharp
/// <param name="lat">latitude</param> /// <param name="lat">latitude</param>
/// <param name="longi">longitude</param> /// <param name="longi">longitude</param>
/// <param name="date">DateTime (UTC)</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.FormatOptions = new CoordinateFormatOptions();
this.latitude = new CoordinatePart(lat, CoordinateType.Lat); this.latitude = new CoordinatePart(lat, CoordinateType.Lat);
this.longitude = new CoordinatePart(longi, CoordinateType.Long); this.longitude = new CoordinatePart(longi, CoordinateType.Long);
@ -152,8 +146,7 @@ namespace CoordinateSharp
/// Values will need to be provided to latitude/longitude manually /// Values will need to be provided to latitude/longitude manually
/// </remarks> /// </remarks>
/// <param name="eagerLoad">Eager loading options</param> /// <param name="eagerLoad">Eager loading options</param>
public Coordinate(EagerLoad eagerLoad) public Coordinate(EagerLoad eagerLoad) {
{
this.FormatOptions = new CoordinateFormatOptions(); this.FormatOptions = new CoordinateFormatOptions();
this.geoDate = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc); this.geoDate = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc);
this.latitude = new CoordinatePart(CoordinateType.Lat); this.latitude = new CoordinatePart(CoordinateType.Lat);
@ -188,8 +181,7 @@ namespace CoordinateSharp
/// <param name="lat">latitude</param> /// <param name="lat">latitude</param>
/// <param name="longi">longitude</param> /// <param name="longi">longitude</param>
/// <param name="eagerLoad">Eager loading options</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.FormatOptions = new CoordinateFormatOptions();
this.geoDate = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc); this.geoDate = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc);
this.latitude = new CoordinatePart(lat, CoordinateType.Lat); this.latitude = new CoordinatePart(lat, CoordinateType.Lat);
@ -223,8 +215,7 @@ namespace CoordinateSharp
/// <param name="longi">Decimal format longitude</param> /// <param name="longi">Decimal format longitude</param>
/// <param name="date">DateTime you wish to use for celestial calculation</param> /// <param name="date">DateTime you wish to use for celestial calculation</param>
/// <param name="eagerLoad">Eager loading options</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.FormatOptions = new CoordinateFormatOptions();
this.latitude = new CoordinatePart(lat, CoordinateType.Lat); this.latitude = new CoordinatePart(lat, CoordinateType.Lat);
this.longitude = new CoordinatePart(longi, CoordinateType.Long); this.longitude = new CoordinatePart(longi, CoordinateType.Long);
@ -261,8 +252,7 @@ namespace CoordinateSharp
/// <summary> /// <summary>
/// Latitudinal Coordinate Part /// Latitudinal Coordinate Part
/// </summary> /// </summary>
public CoordinatePart Latitude public CoordinatePart Latitude {
{
get => this.latitude; get => this.latitude;
set { set {
if (this.latitude != value) { if (this.latitude != value) {
@ -292,8 +282,7 @@ namespace CoordinateSharp
/// <summary> /// <summary>
/// Longitudinal Coordinate Part /// Longitudinal Coordinate Part
/// </summary> /// </summary>
public CoordinatePart Longitude public CoordinatePart Longitude {
{
get => this.longitude; get => this.longitude;
set { set {
if (this.longitude != value) { if (this.longitude != value) {
@ -325,8 +314,7 @@ namespace CoordinateSharp
/// <remarks> /// <remarks>
/// Assumes all times are in UTC /// Assumes all times are in UTC
/// </remarks> /// </remarks>
public DateTime GeoDate public DateTime GeoDate {
{
get => this.geoDate; get => this.geoDate;
set { set {
if (this.geoDate != value) { if (this.geoDate != value) {
@ -357,8 +345,7 @@ namespace CoordinateSharp
/// Uses Ellipsoidal height with no geoid model included. /// Uses Ellipsoidal height with no geoid model included.
/// 0 = Mean Sea Level based on the provided Datum. /// 0 = Mean Sea Level based on the provided Datum.
/// </summary> /// </summary>
public ECEF ECEF public ECEF ECEF {
{
get => this.ecef; get => this.ecef;
//Required due to GeoDetic Height //Required due to GeoDetic Height
@ -376,8 +363,7 @@ namespace CoordinateSharp
/// Used to determine what format the coordinate was parsed from. /// Used to determine what format the coordinate was parsed from.
/// Will equal "None" if Coordinate was not initialzed via a TryParse() method. /// Will equal "None" if Coordinate was not initialzed via a TryParse() method.
/// </summary> /// </summary>
public Parse_Format_Type Parse_Format public Parse_Format_Type Parse_Format {
{
get => this.parse_Format; get => this.parse_Format;
internal set { internal set {
if (this.parse_Format != value) { if (this.parse_Format != value) {
@ -399,8 +385,7 @@ namespace CoordinateSharp
/// <summary> /// <summary>
/// Initialize UTM and MGRS information (required if eager loading is turned off). /// Initialize UTM and MGRS information (required if eager loading is turned off).
/// </summary> /// </summary>
public void LoadUTM_MGRS_Info() public void LoadUTM_MGRS_Info() {
{
this.UTM = new UniversalTransverseMercator(this.latitude.ToDouble(), this.longitude.ToDouble(), this); this.UTM = new UniversalTransverseMercator(this.latitude.ToDouble(), this.longitude.ToDouble(), this);
this.MGRS = new MilitaryGridReferenceSystem(this.UTM); this.MGRS = new MilitaryGridReferenceSystem(this.UTM);
} }
@ -431,8 +416,7 @@ namespace CoordinateSharp
/// Overridden Coordinate ToString() method. /// Overridden Coordinate ToString() method.
/// </summary> /// </summary>
/// <returns>string (formatted).</returns> /// <returns>string (formatted).</returns>
public override String ToString() public override String ToString() {
{
String latString = this.latitude.ToString(); String latString = this.latitude.ToString();
String longSting = this.longitude.ToString(); String longSting = this.longitude.ToString();
return latString + " " + longSting; return latString + " " + longSting;
@ -444,8 +428,7 @@ namespace CoordinateSharp
/// </summary> /// </summary>
/// <param name="options">CoordinateFormatOptions</param> /// <param name="options">CoordinateFormatOptions</param>
/// <returns>Custom formatted coordinate</returns> /// <returns>Custom formatted coordinate</returns>
public String ToString(CoordinateFormatOptions options) public String ToString(CoordinateFormatOptions options) {
{
String latString = this.latitude.ToString(options); String latString = this.latitude.ToString(options);
String longSting = this.longitude.ToString(options); String longSting = this.longitude.ToString(options);
return latString + " " + longSting; return latString + " " + longSting;
@ -458,8 +441,7 @@ namespace CoordinateSharp
/// </summary> /// </summary>
/// <param name="radius">Equatorial Radius</param> /// <param name="radius">Equatorial Radius</param>
/// <param name="flat">Inverse Flattening</param> /// <param name="flat">Inverse Flattening</param>
public void Set_Datum(Double radius, Double flat) public void Set_Datum(Double radius, Double flat) {
{
//WGS84 //WGS84
//RADIUS 6378137.0; //RADIUS 6378137.0;
//FLATTENING 298.257223563; //FLATTENING 298.257223563;
@ -487,8 +469,7 @@ namespace CoordinateSharp
/// <param name="radius">Equatorial Radius</param> /// <param name="radius">Equatorial Radius</param>
/// <param name="flat">Inverse Flattening</param> /// <param name="flat">Inverse Flattening</param>
/// <param name="cd">Coordinate_Datum</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 //WGS84
//RADIUS 6378137.0; //RADIUS 6378137.0;
//FLATTENING 298.257223563; //FLATTENING 298.257223563;
@ -554,8 +535,7 @@ namespace CoordinateSharp
/// //New Coordinate - N 25º 4' 54.517" E 24º 57' 29.189" /// //New Coordinate - N 25º 4' 54.517" E 24º 57' 29.189"
/// </code> /// </code>
/// </example> /// </example>
public void Move(Double distance, Double bearing, Shape shape) public void Move(Double distance, Double bearing, Shape shape) {
{
//Convert to Radians for formula //Convert to Radians for formula
Double lat1 = this.latitude.ToRadians(); Double lat1 = this.latitude.ToRadians();
Double lon1 = this.longitude.ToRadians(); Double lon1 = this.longitude.ToRadians();
@ -605,8 +585,7 @@ namespace CoordinateSharp
/// //New Coordinate - N 24º 56' 21.526" E 25º 4' 23.944" /// //New Coordinate - N 24º 56' 21.526" E 25º 4' 23.944"
/// </code> /// </code>
/// </example> /// </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); Distance d = new Distance(this, target, shape);
//Convert to Radians for formula //Convert to Radians for formula
Double lat1 = this.latitude.ToRadians(); Double lat1 = this.latitude.ToRadians();
@ -656,8 +635,7 @@ namespace CoordinateSharp
/// //New Coordinate - N 25º 4' 54.517" E 24º 57' 29.189" /// //New Coordinate - N 25º 4' 54.517" E 24º 57' 29.189"
/// </code> /// </code>
/// </example> /// </example>
public void Move(Distance distance, Double bearing, Shape shape) public void Move(Distance distance, Double bearing, Shape shape) {
{
//Convert to Radians for formula //Convert to Radians for formula
Double lat1 = this.latitude.ToRadians(); Double lat1 = this.latitude.ToRadians();
Double lon1 = this.longitude.ToRadians(); Double lon1 = this.longitude.ToRadians();
@ -708,8 +686,7 @@ namespace CoordinateSharp
/// //New Coordinate - N 24º 56' 21.526" E 25º 4' 23.944" /// //New Coordinate - N 24º 56' 21.526" E 25º 4' 23.944"
/// </code> /// </code>
/// </example> /// </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); Distance d = new Distance(this, target, shape);
//Convert to Radians for formula //Convert to Radians for formula
Double lat1 = this.latitude.ToRadians(); Double lat1 = this.latitude.ToRadians();
@ -752,9 +729,7 @@ namespace CoordinateSharp
/// } /// }
/// </code> /// </code>
/// </example> /// </example>
public static Boolean TryParse(String s, out Coordinate c) public static Boolean TryParse(String s, out Coordinate c) {
{
c = null;
if (FormatFinder.TryParse(s, CartesianType.Cartesian, out c)) { if (FormatFinder.TryParse(s, CartesianType.Cartesian, out c)) {
Parse_Format_Type pft = c.Parse_Format; Parse_Format_Type pft = c.Parse_Format;
c = new Coordinate(c.Latitude.ToDouble(), c.Longitude.ToDouble()) { c = new Coordinate(c.Latitude.ToDouble(), c.Longitude.ToDouble()) {
@ -781,9 +756,7 @@ namespace CoordinateSharp
/// } /// }
/// </code> /// </code>
/// </example> /// </example>
public static Boolean TryParse(String s, DateTime geoDate, out Coordinate c) public static Boolean TryParse(String s, DateTime geoDate, out Coordinate c) {
{
c = null;
if (FormatFinder.TryParse(s, CartesianType.Cartesian, out c)) { if (FormatFinder.TryParse(s, CartesianType.Cartesian, out c)) {
Parse_Format_Type pft = c.Parse_Format; Parse_Format_Type pft = c.Parse_Format;
c = new Coordinate(c.Latitude.ToDouble(), c.Longitude.ToDouble(), geoDate) { c = new Coordinate(c.Latitude.ToDouble(), c.Longitude.ToDouble(), geoDate) {
@ -810,9 +783,7 @@ namespace CoordinateSharp
/// } /// }
/// </code> /// </code>
/// </example> /// </example>
public static Boolean TryParse(String s, CartesianType ct, out Coordinate c) public static Boolean TryParse(String s, CartesianType ct, out Coordinate c) {
{
c = null;
if (FormatFinder.TryParse(s, ct, out c)) { if (FormatFinder.TryParse(s, ct, out c)) {
Parse_Format_Type pft = c.Parse_Format; Parse_Format_Type pft = c.Parse_Format;
if (ct == CartesianType.ECEF) { if (ct == CartesianType.ECEF) {
@ -845,9 +816,7 @@ namespace CoordinateSharp
/// } /// }
/// </code> /// </code>
/// </example> /// </example>
public static Boolean TryParse(String s, DateTime geoDate, CartesianType ct, out Coordinate c) public static Boolean TryParse(String s, DateTime geoDate, CartesianType ct, out Coordinate c) {
{
c = null;
if (FormatFinder.TryParse(s, ct, out c)) { if (FormatFinder.TryParse(s, ct, out c)) {
Parse_Format_Type pft = c.Parse_Format; Parse_Format_Type pft = c.Parse_Format;
if (ct == CartesianType.ECEF) { if (ct == CartesianType.ECEF) {
@ -872,8 +841,7 @@ namespace CoordinateSharp
/// Notify property changed /// Notify property changed
/// </summary> /// </summary>
/// <param name="propName">Property name</param> /// <param name="propName">Property name</param>
public void NotifyPropertyChanged(String propName) public void NotifyPropertyChanged(String propName) {
{
switch (propName) { switch (propName) {
case "CelestialInfo": case "CelestialInfo":
if (!this.EagerLoadSettings.Celestial || this.CelestialInfo == null) { return; } //Prevent Null Exceptions and calls while eagerloading is off 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. /// Objects can be passed to Coordinate object Latitude and Longitude properties.
/// </remarks> /// </remarks>
[Serializable] [Serializable]
public class CoordinatePart : INotifyPropertyChanged public class CoordinatePart : INotifyPropertyChanged {
{
//Defaults: //Defaults:
//Format: Degrees Minutes Seconds //Format: Degrees Minutes Seconds
//Rounding: Dependent upon selected format //Rounding: Dependent upon selected format
@ -941,8 +908,7 @@ namespace CoordinateSharp
/// <summary> /// <summary>
/// Observable decimal format coordinate. /// Observable decimal format coordinate.
/// </summary> /// </summary>
public Double DecimalDegree public Double DecimalDegree {
{
get => this.decimalDegree; get => this.decimalDegree;
set { set {
//If changing, notify the needed property changes //If changing, notify the needed property changes
@ -1018,8 +984,7 @@ namespace CoordinateSharp
/// <summary> /// <summary>
/// Observable decimal format minute. /// Observable decimal format minute.
/// </summary> /// </summary>
public Double DecimalMinute public Double DecimalMinute {
{
get => this.decimalMinute; get => this.decimalMinute;
set { set {
if (this.decimalMinute != value) { if (this.decimalMinute != value) {
@ -1048,7 +1013,7 @@ namespace CoordinateSharp
Decimal newDM = decValue / 60; //divide decimalMinute by 60 to get storage value 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; 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 this.decimalDegree = Convert.ToDouble(newDD); //Convert back to double for storage
@ -1064,8 +1029,7 @@ namespace CoordinateSharp
/// <summary> /// <summary>
/// Observable coordinate degree. /// Observable coordinate degree.
/// </summary> /// </summary>
public Int32 Degrees public Int32 Degrees {
{
get => this.degrees; get => this.degrees;
set { set {
//Validate Value //Validate Value
@ -1105,8 +1069,7 @@ namespace CoordinateSharp
/// <summary> /// <summary>
/// Observable coordinate minute. /// Observable coordinate minute.
/// </summary> /// </summary>
public Int32 Minutes public Int32 Minutes {
{
get => this.minutes; get => this.minutes;
set { set {
if (this.minutes != value) { if (this.minutes != value) {
@ -1114,9 +1077,9 @@ namespace CoordinateSharp
//Validate the minutes //Validate the minutes
Decimal vMin = Convert.ToDecimal(value); Decimal vMin = Convert.ToDecimal(value);
if (this.type == CoordinateType.Lat) { 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 { } 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) { if (value >= 60) {
throw new ArgumentOutOfRangeException("Minutes out of range", "Minutes cannot be greater than or equal to 60"); throw new ArgumentOutOfRangeException("Minutes out of range", "Minutes cannot be greater than or equal to 60");
@ -1154,8 +1117,7 @@ namespace CoordinateSharp
/// <summary> /// <summary>
/// Observable coordinate second. /// Observable coordinate second.
/// </summary> /// </summary>
public Double Seconds public Double Seconds {
{
get => this.seconds; get => this.seconds;
set { set {
if (value < 0) { value *= -1; }//Adjust accidental negative input if (value < 0) { value *= -1; }//Adjust accidental negative input
@ -1182,9 +1144,9 @@ namespace CoordinateSharp
this.seconds = value; this.seconds = value;
Double degABS = Math.Abs(this.decimalDegree); //Make decimalDegree positive //Double degABS = Math.Abs(this.decimalDegree); //Make decimalDegree positive
Double degFloor = Math.Truncate(degABS); //Truncate the number left of the decimal //Double degFloor = Math.Truncate(degABS); //Truncate the number left of the decimal
Decimal f = Convert.ToDecimal(degFloor); //Convert to decimal to keep precision //Decimal f = Convert.ToDecimal(degFloor); //Convert to decimal to keep precision
Decimal secs = Convert.ToDecimal(this.seconds); //Convert seconds to decimal for calculations Decimal secs = Convert.ToDecimal(this.seconds); //Convert seconds to decimal for calculations
secs /= 60; //Convert to storage format secs /= 60; //Convert to storage format
@ -1207,8 +1169,7 @@ namespace CoordinateSharp
/// <summary> /// <summary>
/// Observable coordinate position. /// Observable coordinate position.
/// </summary> /// </summary>
public CoordinatesPosition Position public CoordinatesPosition Position {
{
get => this.position; get => this.position;
set { set {
if (this.position != value) { if (this.position != value) {
@ -1231,8 +1192,7 @@ namespace CoordinateSharp
/// <param name="t">CoordinateType</param> /// <param name="t">CoordinateType</param>
/// <param name="c">Parent Coordinate object</param> /// <param name="c">Parent Coordinate object</param>
[Obsolete("Method is deprecated. You no longer need to pass a Coordinate object through the constructor.")] [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.parent = c;
this.type = t; this.type = t;
this.decimalDegree = 0; this.decimalDegree = 0;
@ -1248,8 +1208,7 @@ namespace CoordinateSharp
/// <param name="t">Coordinate type</param> /// <param name="t">Coordinate type</param>
/// <param name="c">Parent Coordinate object</param> /// <param name="c">Parent Coordinate object</param>
[Obsolete("Method is deprecated. You no longer need to pass a Coordinate object through the constructor.")] [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.parent = c;
this.type = t; this.type = t;
@ -1287,8 +1246,7 @@ namespace CoordinateSharp
/// <param name="pos">Coordinate Part Position</param> /// <param name="pos">Coordinate Part Position</param>
/// <param name="c">Parent Coordinate</param> /// <param name="c">Parent Coordinate</param>
[Obsolete("Method is deprecated. You no longer need to pass a Coordinate object through the constructor.")] [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.parent = c;
this.type = pos == CoordinatesPosition.N || pos == CoordinatesPosition.S ? CoordinateType.Lat : CoordinateType.Long; this.type = pos == CoordinatesPosition.N || pos == CoordinatesPosition.S ? CoordinateType.Lat : CoordinateType.Long;
@ -1308,12 +1266,12 @@ namespace CoordinateSharp
minD += secD; //Decimal Minutes minD += secD; //Decimal Minutes
if (this.type == CoordinateType.Long) { 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 { } 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); 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) { if (pos == CoordinatesPosition.S || pos == CoordinatesPosition.W) {
@ -1329,8 +1287,7 @@ namespace CoordinateSharp
/// <param name="pos">Coordinate Part Position</param> /// <param name="pos">Coordinate Part Position</param>
/// <param name="c">Parent Coordinate object</param> /// <param name="c">Parent Coordinate object</param>
[Obsolete("Method is deprecated. You no longer need to pass a Coordinate object through the constructor.")] [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.parent = c;
this.type = pos == CoordinatesPosition.N || pos == CoordinatesPosition.S ? CoordinateType.Lat : CoordinateType.Long; 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 (minSec >= 60) { throw new ArgumentOutOfRangeException("Minutes out of range", "Minutes cannot be greater than or equal to 60."); }
if (this.type == CoordinateType.Lat) { 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 { } 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.degrees = deg;
this.decimalMinute = minSec; this.decimalMinute = minSec;
@ -1356,7 +1313,7 @@ namespace CoordinateSharp
sec *= 60; sec *= 60;
Decimal secD = Convert.ToDecimal(sec); Decimal secD = Convert.ToDecimal(sec);
this.seconds = Convert.ToDouble(secD); this.seconds = Convert.ToDouble(secD);
Decimal dd = deg + (minD / 60); Decimal dd = deg + minD / 60;
if (pos == CoordinatesPosition.S || pos == CoordinatesPosition.W) { if (pos == CoordinatesPosition.S || pos == CoordinatesPosition.W) {
dd *= -1; dd *= -1;
@ -1368,8 +1325,7 @@ namespace CoordinateSharp
/// Creates an empty CoordinatePart. /// Creates an empty CoordinatePart.
/// </summary> /// </summary>
/// <param name="t">CoordinateType</param> /// <param name="t">CoordinateType</param>
public CoordinatePart(CoordinateType t) public CoordinatePart(CoordinateType t) {
{
this.type = t; this.type = t;
this.decimalDegree = 0; this.decimalDegree = 0;
this.degrees = 0; this.degrees = 0;
@ -1382,8 +1338,7 @@ namespace CoordinateSharp
/// </summary> /// </summary>
/// <param name="value">Coordinate decimal value</param> /// <param name="value">Coordinate decimal value</param>
/// <param name="t">Coordinate type</param> /// <param name="t">Coordinate type</param>
public CoordinatePart(Double value, CoordinateType t) public CoordinatePart(Double value, CoordinateType t) {
{
this.type = t; this.type = t;
if (this.type == CoordinateType.Long) { if (this.type == CoordinateType.Long) {
@ -1418,8 +1373,7 @@ namespace CoordinateSharp
/// <param name="min">Minutes</param> /// <param name="min">Minutes</param>
/// <param name="sec">Seconds</param> /// <param name="sec">Seconds</param>
/// <param name="pos">Coordinate Part Position</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; 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."); } 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 minD += secD; //Decimal Minutes
if (this.type == CoordinateType.Long) { 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 { } 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); 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) { if (pos == CoordinatesPosition.S || pos == CoordinatesPosition.W) {
@ -1457,8 +1411,7 @@ namespace CoordinateSharp
/// <param name="deg">Degrees</param> /// <param name="deg">Degrees</param>
/// <param name="minSec">Decimal Minutes</param> /// <param name="minSec">Decimal Minutes</param>
/// <param name="pos">Coordinate Part Position</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; 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."); } 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 (minSec >= 60) { throw new ArgumentOutOfRangeException("Minutes out of range", "Minutes cannot be greater than or equal to 60."); }
if (this.type == CoordinateType.Lat) { 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 { } 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.degrees = deg;
this.decimalMinute = minSec; this.decimalMinute = minSec;
@ -1482,7 +1435,7 @@ namespace CoordinateSharp
sec *= 60; sec *= 60;
Decimal secD = Convert.ToDecimal(sec); Decimal secD = Convert.ToDecimal(sec);
this.seconds = Convert.ToDouble(secD); this.seconds = Convert.ToDouble(secD);
Decimal dd = deg + (minD / 60); Decimal dd = deg + minD / 60;
if (pos == CoordinatesPosition.S || pos == CoordinatesPosition.W) { if (pos == CoordinatesPosition.S || pos == CoordinatesPosition.W) {
dd *= -1; dd *= -1;
@ -1513,46 +1466,25 @@ namespace CoordinateSharp
/// </summary> /// </summary>
/// <param name="options">CoordinateFormatOptions</param> /// <param name="options">CoordinateFormatOptions</param>
/// <returns>Formatted coordinate part string</returns> /// <returns>Formatted coordinate part string</returns>
private String FormatString(CoordinateFormatOptions options) 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;
#region Assign Formatting Rules #region Assign Formatting Rules
switch (options.Format) { ToStringType type = options.Format switch
case CoordinateFormatType.Degree_Minutes_Seconds: {
type = ToStringType.Degree_Minute_Second; CoordinateFormatType.Degree_Minutes_Seconds => ToStringType.Degree_Minute_Second,
break; CoordinateFormatType.Degree_Decimal_Minutes => ToStringType.Degree_Decimal_Minute,
case CoordinateFormatType.Degree_Decimal_Minutes: CoordinateFormatType.Decimal_Degree => ToStringType.Decimal_Degree,
type = ToStringType.Degree_Decimal_Minute; CoordinateFormatType.Decimal => ToStringType.Decimal,
break; _ => ToStringType.Degree_Minute_Second,
case CoordinateFormatType.Decimal_Degree: };
type = ToStringType.Decimal_Degree; Int32? rounding = options.Round;
break; Boolean lead = options.Display_Leading_Zeros;
case CoordinateFormatType.Decimal: Boolean trail = options.Display_Trailing_Zeros;
type = ToStringType.Decimal; Boolean symbols = options.Display_Symbols;
break; Boolean degreeSymbol = options.Display_Degree_Symbol;
default: Boolean minuteSymbol = options.Display_Minute_Symbol;
type = ToStringType.Degree_Minute_Second; Boolean secondsSymbol = options.Display_Seconds_Symbol;
break; Boolean hyphen = options.Display_Hyphens;
} Boolean positionFirst = options.Position_First;
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;
#endregion #endregion
switch (type) { switch (type) {
@ -1576,8 +1508,7 @@ namespace CoordinateSharp
return String.Empty; return String.Empty;
} }
//DMS Coordinate Format //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 leadString = this.Leading_Trailing_Format(lead, false, rounding, this.Position);
String d = String.Format(leadString, this.Degrees); // Degree String 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(); : d + ds + hs + minute + ms + hs + second + ss + hs + this.Position.ToString();
} }
//DDM Coordinate Format //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"; String leadString = "{0:0";
if (lead) { if (lead) {
if (this.Position == CoordinatesPosition.E || this.Position == CoordinatesPosition.W) { if (this.Position == CoordinatesPosition.E || this.Position == CoordinatesPosition.W) {
@ -1646,8 +1576,7 @@ namespace CoordinateSharp
} }
////DD Coordinate Format ////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 degreeS = "";
String hyph = " "; String hyph = " ";
if (degreeSymbol) { degreeS = "º"; } if (degreeSymbol) { degreeS = "º"; }
@ -1672,15 +1601,14 @@ namespace CoordinateSharp
} }
leadTrail += "}"; 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); result = Math.Round(result, rounding);
String d = String.Format(leadTrail, Math.Abs(result)); String d = String.Format(leadTrail, Math.Abs(result));
return positionFirst ? this.Position.ToString() + hyph + d + degreeS : d + degreeS + hyph + this.Position.ToString(); 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"; String leadString = "{0:0";
if (isLead) { if (isLead) {
if (p != null) { 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 Decimal_Degree, Degree_Decimal_Minute, Degree_Minute_Second, Decimal
} }
/// <summary> /// <summary>
/// Notify the correct properties and parent properties. /// Notify the correct properties and parent properties.
/// </summary> /// </summary>
/// <param name="p">Property Type</param> /// <param name="p">Property Type</param>
private void NotifyProperties(PropertyTypes p) private void NotifyProperties(PropertyTypes p) {
{
switch (p) { switch (p) {
case PropertyTypes.DecimalDegree: case PropertyTypes.DecimalDegree:
this.NotifyPropertyChanged("DecimalDegree"); this.NotifyPropertyChanged("DecimalDegree");
@ -1786,8 +1712,7 @@ namespace CoordinateSharp
/// <summary> /// <summary>
/// Used for notifying the correct properties. /// Used for notifying the correct properties.
/// </summary> /// </summary>
private enum PropertyTypes private enum PropertyTypes {
{
DecimalDegree, DecimalMinute, Position, Degree, Minute, Second, FormatChange DecimalDegree, DecimalMinute, Position, Degree, Minute, Second, FormatChange
} }
@ -1811,12 +1736,7 @@ namespace CoordinateSharp
/// } /// }
/// </code> /// </code>
/// </example> /// </example>
public static Boolean TryParse(String s, out CoordinatePart cp) public static Boolean TryParse(String s, out CoordinatePart cp) => FormatFinder_CoordPart.TryParse(s, out cp) ? true : false;
{
cp = null;
return FormatFinder_CoordPart.TryParse(s, out cp) ? true : false;
}
/// <summary> /// <summary>
/// Attempts to parse a string into a CoordinatePart. /// Attempts to parse a string into a CoordinatePart.
/// </summary> /// </summary>
@ -1833,9 +1753,7 @@ namespace CoordinateSharp
/// } /// }
/// </code> /// </code>
/// </example> /// </example>
public static Boolean TryParse(String s, CoordinateType t, out CoordinatePart cp) public static Boolean TryParse(String s, CoordinateType t, out CoordinatePart cp) {
{
cp = null;
//Comma at beginning parses to long //Comma at beginning parses to long
//Asterik forces lat //Asterik forces lat
s = t == CoordinateType.Long ? "," + s : "*" + s; 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;
using System.Diagnostics; using System.Diagnostics;
namespace CoordinateSharp
{ namespace CoordinateSharp {
/// <summary> /// <summary>
/// Contains distance values between two coordinates. /// Contains distance values between two coordinates.
/// </summary> /// </summary>
[Serializable] [Serializable]
public class Distance public class Distance {
{
private double kilometers;
private double miles;
private double feet;
private double meters;
private double bearing;
private double nauticalMiles;
/// <summary> /// <summary>
/// Initializes a distance object using Haversine (Spherical Earth). /// Initializes a distance object using Haversine (Spherical Earth).
/// </summary> /// </summary>
/// <param name="c1">Coordinate 1</param> /// <param name="c1">Coordinate 1</param>
/// <param name="c2">Coordinate 2</param> /// <param name="c2">Coordinate 2</param>
public Distance(Coordinate c1, Coordinate c2) public Distance(Coordinate c1, Coordinate c2) => this.Haversine(c1, c2);
{
Haversine(c1, c2);
}
/// <summary> /// <summary>
/// Initializes a distance object using Haversine (Spherical Earth) or Vincenty (Elliptical Earth). /// Initializes a distance object using Haversine (Spherical Earth) or Vincenty (Elliptical Earth).
/// </summary> /// </summary>
/// <param name="c1">Coordinate 1</param> /// <param name="c1">Coordinate 1</param>
/// <param name="c2">Coordinate 2</param> /// <param name="c2">Coordinate 2</param>
/// <param name="shape">Shape of earth</param> /// <param name="shape">Shape of earth</param>
public Distance(Coordinate c1, Coordinate c2, Shape shape) public Distance(Coordinate c1, Coordinate c2, Shape shape) {
{ if (shape == Shape.Sphere) {
if (shape == Shape.Sphere) this.Haversine(c1, c2);
{ } else {
Haversine(c1, c2); this.Vincenty(c1, c2);
}
else
{
Vincenty(c1, c2);
} }
} }
/// <summary> /// <summary>
/// Initializes distance object based on distance in KM /// Initializes distance object based on distance in KM
/// </summary> /// </summary>
/// <param name="km">Kilometers</param> /// <param name="km">Kilometers</param>
public Distance(double km) public Distance(Double km) {
{ this.Kilometers = km;
kilometers = km; this.Meters = km * 1000;
meters = km * 1000; this.Feet = this.Meters * 3.28084;
feet = meters * 3.28084; this.Miles = this.Meters * 0.000621371;
miles = meters * 0.000621371; this.NauticalMiles = this.Meters * 0.0005399565;
nauticalMiles = meters * 0.0005399565; this.Bearing = 0;//None specified
bearing = 0;//None specified
} }
/// <summary> /// <summary>
/// Initializaes distance object based on specified distance and measurement type /// Initializaes distance object based on specified distance and measurement type
@ -60,59 +45,56 @@ namespace CoordinateSharp
/// <param name="distance">Distance</param> /// <param name="distance">Distance</param>
/// <param name="type">Measurement type</param> /// <param name="type">Measurement type</param>
public Distance(double distance, DistanceType type) public Distance(Double distance, DistanceType type) {
{ this.Bearing = 0;
bearing = 0; switch (type) {
switch (type)
{
case DistanceType.Feet: case DistanceType.Feet:
feet = distance; this.Feet = distance;
meters = feet * 0.3048; this.Meters = this.Feet * 0.3048;
kilometers = meters / 1000; this.Kilometers = this.Meters / 1000;
miles = meters * 0.000621371; this.Miles = this.Meters * 0.000621371;
nauticalMiles = meters * 0.0005399565; this.NauticalMiles = this.Meters * 0.0005399565;
break; break;
case DistanceType.Kilometers: case DistanceType.Kilometers:
kilometers = distance; this.Kilometers = distance;
meters = kilometers * 1000; this.Meters = this.Kilometers * 1000;
feet = meters * 3.28084; this.Feet = this.Meters * 3.28084;
miles = meters * 0.000621371; this.Miles = this.Meters * 0.000621371;
nauticalMiles = meters * 0.0005399565; this.NauticalMiles = this.Meters * 0.0005399565;
break; break;
case DistanceType.Meters: case DistanceType.Meters:
meters = distance; this.Meters = distance;
kilometers = meters / 1000; this.Kilometers = this.Meters / 1000;
feet = meters * 3.28084; this.Feet = this.Meters * 3.28084;
miles = meters * 0.000621371; this.Miles = this.Meters * 0.000621371;
nauticalMiles = meters * 0.0005399565; this.NauticalMiles = this.Meters * 0.0005399565;
break; break;
case DistanceType.Miles: case DistanceType.Miles:
miles = distance; this.Miles = distance;
meters = miles * 1609.344; this.Meters = this.Miles * 1609.344;
feet = meters * 3.28084; this.Feet = this.Meters * 3.28084;
kilometers = meters / 1000; this.Kilometers = this.Meters / 1000;
nauticalMiles = meters * 0.0005399565; this.NauticalMiles = this.Meters * 0.0005399565;
break; break;
case DistanceType.NauticalMiles: case DistanceType.NauticalMiles:
nauticalMiles = distance; this.NauticalMiles = distance;
meters = nauticalMiles * 1852.001; this.Meters = this.NauticalMiles * 1852.001;
feet = meters * 3.28084; this.Feet = this.Meters * 3.28084;
kilometers = meters / 1000; this.Kilometers = this.Meters / 1000;
miles = meters * 0.000621371; this.Miles = this.Meters * 0.000621371;
break; break;
default: default:
kilometers = distance; this.Kilometers = distance;
meters = distance * 1000; this.Meters = distance * 1000;
feet = meters * 3.28084; this.Feet = this.Meters * 3.28084;
miles = meters * 0.000621371; this.Miles = this.Meters * 0.000621371;
nauticalMiles = meters * 0.0005399565; this.NauticalMiles = this.Meters * 0.0005399565;
break; break;
} }
} }
private void Vincenty(Coordinate coord1, Coordinate coord2) private void Vincenty(Coordinate coord1, Coordinate coord2) {
{ Double lat1, lat2, lon1, lon2;
double lat1, lat2, lon1, lon2; Double d, crs12;
double d, crs12, crs21;
lat1 = coord1.Latitude.ToRadians(); lat1 = coord1.Latitude.ToRadians();
@ -121,111 +103,90 @@ namespace CoordinateSharp
lon2 = coord2.Longitude.ToRadians() * -1; //REVERSE FOR CALC 2.1.1.1 lon2 = coord2.Longitude.ToRadians() * -1; //REVERSE FOR CALC 2.1.1.1
//Ensure datums match between coords //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."); 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 // 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 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 d = cde[0]; //Distance
bearing = crs12; this.Bearing = crs12;
//reverseBearing = crs21; //reverseBearing = crs21;
meters = d; this.Meters = d;
kilometers = d / 1000; this.Kilometers = d / 1000;
feet = d * 3.28084; this.Feet = d * 3.28084;
miles = d * 0.000621371; this.Miles = d * 0.000621371;
nauticalMiles = d * 0.0005399565; this.NauticalMiles = d * 0.0005399565;
} }
private void Haversine(Coordinate coord1, Coordinate coord2) private void Haversine(Coordinate coord1, Coordinate coord2) {
{
////RADIANS ////RADIANS
double lat1 = coord1.Latitude.ToRadians(); Double lat1 = coord1.Latitude.ToRadians();
double long1 = coord1.Longitude.ToRadians(); Double long1 = coord1.Longitude.ToRadians();
double lat2 = coord2.Latitude.ToRadians(); Double lat2 = coord2.Latitude.ToRadians();
double long2 = coord2.Longitude.ToRadians(); Double long2 = coord2.Longitude.ToRadians();
//Distance Calcs //Distance Calcs
double R = 6371000; //6378137.0;//6371e3; //meters Double R = 6371000; //6378137.0;//6371e3; //meters
double latRad = coord2.Latitude.ToRadians() - coord1.Latitude.ToRadians(); Double latRad = coord2.Latitude.ToRadians() - coord1.Latitude.ToRadians();
double longRad = coord2.Longitude.ToRadians() - coord1.Longitude.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); 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 cl = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
double dist = R * cl; Double dist = R * cl;
//Get bearing //Get bearing
double dLong = long2 - long1; Double dLong = long2 - long1;
double y = Math.Sin(dLong) * Math.Cos(lat2); 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 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 brng = Math.Atan2(y, x) * (180 / Math.PI); //Convert bearing back to degrees.
//if (brng < 0) { brng -= 180; brng = Math.Abs(brng); } //if (brng < 0) { brng -= 180; brng = Math.Abs(brng); }
brng = (brng + 360) % 360; //v2.1.1.1 NORMALIZE HEADING brng = (brng + 360) % 360; //v2.1.1.1 NORMALIZE HEADING
kilometers = dist / 1000; this.Kilometers = dist / 1000;
meters = dist; this.Meters = dist;
feet = dist * 3.28084; this.Feet = dist * 3.28084;
miles = dist * 0.000621371; this.Miles = dist * 0.000621371;
nauticalMiles = dist * 0.0005399565; this.NauticalMiles = dist * 0.0005399565;
bearing = brng; this.Bearing = brng;
} }
/// <summary> /// <summary>
/// Distance in Kilometers /// Distance in Kilometers
/// </summary> /// </summary>
public double Kilometers public Double Kilometers { get; private set; }
{
get { return kilometers; }
}
/// <summary> /// <summary>
/// Distance in Statute Miles /// Distance in Statute Miles
/// </summary> /// </summary>
public double Miles public Double Miles { get; private set; }
{
get { return miles; }
}
/// <summary> /// <summary>
/// Distance in Nautical Miles /// Distance in Nautical Miles
/// </summary> /// </summary>
public double NauticalMiles public Double NauticalMiles { get; private set; }
{
get { return nauticalMiles; }
}
/// <summary> /// <summary>
/// Distance in Meters /// Distance in Meters
/// </summary> /// </summary>
public double Meters public Double Meters { get; private set; }
{
get { return meters; }
}
/// <summary> /// <summary>
/// Distance in Feet /// Distance in Feet
/// </summary> /// </summary>
public double Feet public Double Feet { get; private set; }
{
get { return feet; }
}
/// <summary> /// <summary>
/// Initial Bearing from Coordinate 1 to Coordinate 2 /// Initial Bearing from Coordinate 1 to Coordinate 2
/// </summary> /// </summary>
public double Bearing public Double Bearing { get; private set; }
{
get { return bearing; }
}
} }
/// <summary> /// <summary>
/// Distance measurement type /// Distance measurement type
/// </summary> /// </summary>
public enum DistanceType public enum DistanceType {
{
/// <summary> /// <summary>
/// Distance in Meters /// Distance in Meters
/// </summary> /// </summary>
@ -249,8 +210,7 @@ namespace CoordinateSharp
} }
[Serializable] [Serializable]
internal class Distance_Assistant internal class Distance_Assistant {
{
/// <summary> /// <summary>
/// Returns new geodetic coordinate in radians /// Returns new geodetic coordinate in radians
/// </summary> /// </summary>
@ -260,34 +220,25 @@ namespace CoordinateSharp
/// <param name="s">Distance</param> /// <param name="s">Distance</param>
/// <param name="ellipse">Earth Ellipse Values</param> /// <param name="ellipse">Earth Ellipse Values</param>
/// <returns>double[]</returns> /// <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 glon1 *= -1; //REVERSE LONG FOR CALC 2.1.1.1
double EPS = 0.00000000005;//Used to determine if starting at pole. 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 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 glat2, glon2, f;
//Determine if near pole //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."); 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 f = 1 / ellipse[1];//Flattening
r = 1 - f; r = 1 - f;
tu = r * Math.Tan(glat1); tu = r * Math.Tan(glat1);
sf = Math.Sin(faz); sf = Math.Sin(faz);
cf = Math.Cos(faz); cf = Math.Cos(faz);
if (cf == 0) b = cf == 0 ? 0.0 : 2.0 * Math.Atan2(tu, cf);
{
b = 0.0;
}
else
{
b = 2.0 * Math.Atan2(tu, cf);
}
cu = 1.0 / Math.Sqrt(1 + tu * tu); cu = 1.0 / Math.Sqrt(1 + tu * tu);
su = tu * cu; su = tu * cu;
sa = cu * sf; sa = cu * sf;
@ -300,8 +251,7 @@ namespace CoordinateSharp
tu = s / (r * a * c); tu = s / (r * a * c);
y = tu; y = tu;
c = y + 1; c = y + 1;
while (Math.Abs(y - c) > EPS) while (Math.Abs(y - c) > EPS) {
{
sy = Math.Sin(y); sy = Math.Sin(y);
cy = Math.Cos(y); cy = Math.Cos(y);
cz = Math.Cos(b + y); cz = Math.Cos(b + y);
@ -324,7 +274,7 @@ namespace CoordinateSharp
d = ((e * cy * c + cz) * sy * c + y) * sa; d = ((e * cy * c + cz) * sy * c + y) * sa;
glon2 = ModM.ModLon(glon1 + x - (1.0 - c) * d * f); //Adjust for IDL glon2 = ModM.ModLon(glon1 + x - (1.0 - c) * d * f); //Adjust for IDL
//baz = ModM.ModCrs(Math.Atan2(sa, b) + Math.PI); //baz = ModM.ModCrs(Math.Atan2(sa, b) + Math.PI);
return new double[] { glat2, glon2 }; return new Double[] { glat2, glon2 };
} }
/// <summary> /// <summary>
/// Returns new geodetic coordinate in radians /// Returns new geodetic coordinate in radians
@ -334,57 +284,49 @@ namespace CoordinateSharp
/// <param name="crs12">Bearing</param> /// <param name="crs12">Bearing</param>
/// <param name="d12">Distance</param> /// <param name="d12">Distance</param>
/// <returns>double[]</returns> /// <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 lon1 *= -1; //REVERSE LONG FOR CALC 2.1.1.1
var EPS = 0.00000000005;//Used to determine if near pole. Double EPS = 0.00000000005;//Used to determine if near pole.
double dlon, lat, lon; Double dlon, lat, lon;
d12 = d12 * 0.0005399565; //convert meter to nm d12 *= 0.0005399565; //convert meter to nm
d12 = d12 / (180 * 60 / Math.PI);//Convert to Radian d12 /= 180 * 60 / Math.PI;//Convert to Radian
//Determine if near pole //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."); 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) + lat = Math.Asin(Math.Sin(lat1) * Math.Cos(d12) +
Math.Cos(lat1) * Math.Sin(d12) * Math.Cos(crs12)); 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 lon = 0.0; //endpoint a pole
} } else {
else
{
dlon = Math.Atan2(Math.Sin(crs12) * Math.Sin(d12) * Math.Cos(lat1), dlon = Math.Atan2(Math.Sin(crs12) * Math.Sin(d12) * Math.Cos(lat1),
Math.Cos(d12) - Math.Sin(lat1) * Math.Sin(lat)); Math.Cos(d12) - Math.Sin(lat1) * Math.Sin(lat));
lon = ModM.Mod(lon1 - dlon + Math.PI, 2 * Math.PI) - Math.PI; 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) public static Double[] Dist_Ell(Double glat1, Double glon1, Double glat2, Double glon2, Double[] ellipse) {
{ Double a = ellipse[0]; //Equitorial Radius
double a = ellipse[0]; //Equitorial Radius Double f = 1 / ellipse[1]; //Flattening
double f = 1 / ellipse[1]; //Flattening
double r, tu1, tu2, cu1, su1, cu2, s1, b1, f1; 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 sx = 0, cx = 0, sy = 0, cy = 0, y = 0, c2a = 0, cz = 0, e = 0;
double EPS = 0.00000000005; Double EPS = 0.00000000005;
double faz, baz, s; Double faz, baz, s;
double iter = 1; Double iter = 1;
double MAXITER = 100; Double MAXITER = 100;
if ((glat1 + glat2 == 0.0) && (Math.Abs(glon1 - glon2) == Math.PI)) if (glat1 + glat2 == 0.0 && Math.Abs(glon1 - glon2) == Math.PI) {
{
Debug.WriteLine("Warning: Course and distance between antipodal points is undefined"); 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"); Debug.WriteLine("Warning: Points 1 and 2 are identical- course undefined");
//D //D
//crs12 //crs12
//crs21 //crs21
return new double[] { 0, 0, Math.PI }; return new Double[] { 0, 0, Math.PI };
} }
r = 1 - f; r = 1 - f;
tu1 = r * Math.Tan(glat1); tu1 = r * Math.Tan(glat1);
@ -395,11 +337,11 @@ namespace CoordinateSharp
s1 = cu1 * cu2; s1 = cu1 * cu2;
b1 = s1 * tu2; b1 = s1 * tu2;
f1 = b1 * tu1; f1 = b1 * tu1;
x = glon2 - glon1; Double x = glon2 - glon1;
d = x + 1; // force one pass Double d = x + 1;
while ((Math.Abs(d - x) > EPS) && (iter < MAXITER)) Double c;
{ while (Math.Abs(d - x) > EPS && iter < MAXITER) {
iter = iter + 1; iter += 1;
sx = Math.Sin(x); sx = Math.Sin(x);
cx = Math.Cos(x); cx = Math.Cos(x);
tu1 = cu2 * sx; tu1 = cu2 * sx;
@ -407,11 +349,10 @@ namespace CoordinateSharp
sy = Math.Sqrt(tu1 * tu1 + tu2 * tu2); sy = Math.Sqrt(tu1 * tu1 + tu2 * tu2);
cy = s1 * cx + f1; cy = s1 * cx + f1;
y = Math.Atan2(sy, cy); y = Math.Atan2(sy, cy);
sa = s1 * sx / sy; Double sa = s1 * sx / sy;
c2a = 1 - sa * sa; c2a = 1 - sa * sa;
cz = f1 + f1; cz = f1 + f1;
if (c2a > 0.0) if (c2a > 0.0) {
{
cz = cy - cz / c2a; cz = cy - cz / c2a;
} }
e = cz * cz * 2.0 - 1.0; e = cz * cz * 2.0 - 1.0;
@ -431,12 +372,11 @@ namespace CoordinateSharp
x = e * cy; 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; 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"); 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.Collections.Generic;
using System.Linq; using System.Linq;
namespace CoordinateSharp.Eclipse namespace CoordinateSharp.Eclipse {
{ internal class LunarData {
internal class LunarData static readonly Double[] LE1601 = new Double[] {
{
static double[] LE1601 = new double[] {
// 1601 1 18 // 1601 1 18
2305831.105839, 15.0, 117.3, 0.033, -0.978, 3, 2305831.105839, 15.0, 117.3, 0.033, -0.978, 3,
-1.13536, 0.98335, 0.26794, -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, -3.09161, -1.92390, -0.82385, 0.02344, 0.87082, 1.97089, 3.13800,
337.8589683, 0.48164, -1.510e-04, 337.8589683, 0.48164, -1.510e-04,
-9.4195702, 0.13945, 3.390e-04 }; -9.4195702, 0.13945, 3.390e-04 };
static double[] LE1701 = new double[] static readonly Double[] LE1701 = new Double[]
{ {
// 1701 2 22 // 1701 2 22
2342390.479120, 23.0, 8.2, 1.428, 0.463, 2, 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, 9.1688605, 0.46956, -7.000e-05,
3.0790301, 0.25315, -2.000e-04 3.0790301, 0.25315, -2.000e-04
}; };
static double[] LE1801 = new double[] static readonly Double[] LE1801 = new Double[]
{ {
// 1801 3 30 // 1801 3 30
2378949.725057, 5.0, 13.0, 2.857, 1.840, 1, 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, 72.2570493, 0.64062, -1.660e-04,
21.3680795, 0.01873, -1.222e-03 21.3680795, 0.01873, -1.222e-03
}; };
static double[] LE1901 = new double[] static readonly Double[] LE1901 = new Double[]
{ {
// 1901 5 3 // 1901 5 3
2415508.271269, 19.0, -0.9, 1.043, -0.033, 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, 296.2552752, 0.52835, -1.150e-04,
-21.2212594, 0.04170, 8.250e-04 -21.2212594, 0.04170, 8.250e-04
}; };
static double[] LE2001 = new double[] static readonly Double[] LE2001 = new Double[]
{ {
// 2001 1 9 // 2001 1 9
2451919.348374, 20.0, 64.1, 2.162, 1.189, 1, 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, 329.8184696, 0.49978, -6.760e-04,
-13.3626205, 0.22960, 3.990e-04 -13.3626205, 0.22960, 3.990e-04
}; };
static double[] LE2101 = new double[] static readonly Double[] LE2101 = new Double[]
{ {
// 2101 2 14 // 2101 2 14
2488478.618055, 3.0, 205.1, 2.218, 1.183, 1, 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, 28.0294400, 0.59158, 9.000e-05,
10.7019400, 0.15900, -6.160e-04 10.7019400, 0.15900, -6.160e-04
}; };
static double[] LE2201 = new double[] static readonly Double[] LE2201 = new Double[]
{ {
// 2201 3 20 // 2201 3 20
2525037.204912, 17.0, 444.3, 0.532, -0.560, 3, 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, 63.0500500, 0.65278, 8.590e-04,
21.0508309, 0.17085, -1.218e-03 21.0508309, 0.17085, -1.218e-03
}; };
static double[] LE2301 = new double[] static readonly Double[] LE2301 = new Double[]
{ {
// 2301 5 23 // 2301 5 23
2561625.186996, 16.0, 720.0, 1.809, 0.754, 2, 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, 101.2753539, 0.59275, -1.730e-04,
23.7726800, -0.09243, -1.170e-03 23.7726800, -0.09243, -1.170e-03
}; };
static double[] LE2401 = new double[] { static readonly Double[] LE2401 = new Double[] {
// 2401 6 26 // 2401 6 26
2598183.958214, 11.0, 1059.4, 2.107, 1.139, 1, 2598183.958214, 11.0, 1059.4, 2.107, 1.139, 1,
5.31800, 0.99489, 0.27108, 5.31800, 0.99489, 0.27108,
@ -13176,7 +13174,7 @@ namespace CoordinateSharp.Eclipse
348.3334732, 0.58130, -3.870e-04, 348.3334732, 0.58130, -3.870e-04,
-5.5431301, 0.18349, 2.190e-04 -5.5431301, 0.18349, 2.190e-04
}; };
static double[] LE2501 = new double[] { static readonly Double[] LE2501 = new Double[] {
// 2501 3 6 // 2501 3 6
2634595.801080, 7.0, 1461.0, 0.491, -0.599, 3, 2634595.801080, 7.0, 1461.0, 0.491, -0.599, 3,
17.93340, 0.90700, 0.24714, 17.93340, 0.90700, 0.24714,
@ -14541,66 +14539,45 @@ namespace CoordinateSharp.Eclipse
8.0835801, 0.28700, -3.300e-04 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. //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, LE1601, LE1701,LE1801, LE1901, LE2001,
LE2101,LE2201, LE2301, LE2401, LE2501 LE2101,LE2201, LE2301, LE2401, LE2501
}; };
double cent = Math.Floor(d.Year * .01) * 100; //Gets turn of century year. Double cent = Math.Floor(d.Year * .01) * 100; //Gets turn of century year.
int index = GetIndex(cent); //Gets index for calling data list. 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 //Determine data to LEnd if year is near beginning or end of databaLE
int halfCent = d.Year - (int)cent; Int32 halfCent = d.Year - (Int32)cent;
if (index == 0 || index == data.Count - 1) 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();
{
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(); }
}
} }
public static double[] LunarDateData_100Year(DateTime d) public static Double[] LunarDateData_100Year(DateTime d) {
{
//Return combined 100 year arrays //Return combined 100 year arrays
List<double[]> data = new List<double[]>() List<Double[]> data = new List<Double[]>()
{ {
LE1601, LE1701,LE1801, LE1901, LE2001, LE1601, LE1701,LE1801, LE1901, LE2001,
LE2101,LE2201, LE2301, LE2401, LE2501 LE2101,LE2201, LE2301, LE2401, LE2501
}; };
double cent = Math.Floor(d.Year * .01) * 100; //Gets turn of century year. Double cent = Math.Floor(d.Year * .01) * 100; //Gets turn of century year.
int index = GetIndex(cent); //Gets index for calling data list. 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 proper 100 year table.
return data[index]; return data[index];
} }
private static int GetIndex(double cent) private static Int32 GetIndex(Double cent) {
{ Int32 dex = 0;
int dex = 0; Int32 c = Convert.ToInt32(cent * .01);
int c = Convert.ToInt32(cent * .01);
//START CENTURY 16 //START CENTURY 16
//END CENTRURY 26 //END CENTRURY 26
//AJDUST AS DATABALE GROWS //AJDUST AS DATABALE GROWS
for (int i = 16; i < 26; i++) for (Int32 i = 16; i < 26; i++) {
{
if (i == c) { return dex; } if (i == c) { return dex; }
dex++; dex++;
} }

View File

@ -2,12 +2,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace CoordinateSharp.Eclipse namespace CoordinateSharp.Eclipse {
{ internal class SolarData {
internal class SolarData
{
//ECLIPSE DATA FROM 1701-2400 //ECLIPSE DATA FROM 1701-2400
static double[] SE1601 = new double[] static readonly Double[] SE1601 = new Double[]
{ {
// 1601 1 4 // 1601 1 4
2305817.017109, 12.0, -4.0, 4.0, 117.4, 117.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.0114460, 0.0000434, -1.270e-05,
0.0046524, 0.0046293 0.0046524, 0.0046293
}; };
static double[] SE1701 = new double[] static readonly Double[] SE1701 = new Double[]
{ {
// 1701 2 7 // 1701 2 7
2342375.461729, 23.0, -4.0, 4.0, 8.2, 8.2, 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.0039760, -0.0000963, -1.230e-05,
0.0046973, 0.0046739 0.0046973, 0.0046739
}; };
static double[] SE1801 = new double[] static readonly Double[] SE1801 = new Double[]
{ {
// 1801 3 14 // 1801 3 14
2378934.156652, 16.0, -4.0, 4.0, 13.0, 13.0, 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.5676560, -0.0000826, -1.030e-05,
0.0214110, -0.0000822, -1.030e-05, 0.0214110, -0.0000822, -1.030e-05,
0.0047365, 0.0047129}; 0.0047365, 0.0047129};
static double[] SE1901 = new double[] static readonly Double[] SE1901 = new Double[]
{ {
// 1901 5 18 // 1901 5 18
2415522.731807, 6.0, -4.0, 4.0, -0.9, -0.9, 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.0268200, 0.0000511, -1.000e-05,
0.0047553, 0.0047316 0.0047553, 0.0047316
}; };
static double[] SE2001 = new double[] static readonly Double[] SE2001 = new Double[]
{ {
// 2001 6 21 // 2001 6 21
2452082.003314, 12.0, -4.0, 4.0, 64.2, 64.2, 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.0062330, -0.0001026, -1.200e-05,
0.0046346, 0.0046116 0.0046346, 0.0046116
}; };
static double[] SE2101 = new double[] static readonly Double[] SE2101 = new Double[]
{ {
// 2101 2 28 // 2101 2 28
2488492.594741, 2.0, -4.0, 4.0, 205.2, 205.2, 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.0190180, -0.0000736, -1.010e-05,
0.0046769, 0.0046536 0.0046769, 0.0046536
}; };
static double[] SE2201 = new double[] static readonly Double[] SE2201 = new Double[]
{ {
// 2201 4 4 // 2201 4 4
2525051.763849, 6.0, -4.0, 4.0, 444.4, 444.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.0284480, 0.0000235, -9.800e-06,
0.0047462, 0.0047226 0.0047462, 0.0047226
}; };
static double[] SE2301 = new double[] static readonly Double[] SE2301 = new Double[]
{ {
// 2301 5 9 // 2301 5 9
2561611.084014, 14.0, -4.0, 4.0, 719.9, 719.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.0071310, -0.0001059, -1.190e-05,
0.0046006, 0.0045776 0.0046006, 0.0045776
}; };
static double[] SE2401 = new double[] { static readonly Double[] SE2401 = new Double[] {
// 2401 1 14 // 2401 1 14
2598021.427310, 22.0, -4.0, 4.0, 1057.8, 1057.8, 2598021.427310, 22.0, -4.0, 4.0, 1057.8, 1057.8,
-0.2870830, 0.5189539, -4.590e-05, -7.000e-06, -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.0163870, -0.0000706, -1.000e-05,
0.0046201, 0.0045971 0.0046201, 0.0045971
}; };
static double[] SE2501 = new double[] { static readonly Double[] SE2501 = new Double[] {
// 2501 2 19 // 2501 2 19
2634580.691215, 5.0, -4.0, 4.0, 1460.8, 1460.8, 2634580.691215, 5.0, -4.0, 4.0, 1460.8, 1460.8,
0.1813720, 0.5619451, -3.330e-05, -9.490e-06, 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.0248230, 0.0000365, -9.800e-06,
0.0046944, 0.0046710 }; 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. //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, SE1601, SE1701, SE1801, SE1901, SE2001,
SE2101, SE2201, SE2301, SE2401, SE2501 SE2101, SE2201, SE2301, SE2401, SE2501
}; };
double cent = Math.Floor(d.Year * .01) * 100; //Gets turn of century year. Double cent = Math.Floor(d.Year * .01) * 100; //Gets turn of century year.
int index = GetIndex(cent); //Gets index for calling data list. 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 //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) 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();
{
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(); }
}
} }
public static double[] SolarDateData_100Year(DateTime d) public static Double[] SolarDateData_100Year(DateTime d) {
{
//Return combined 100 year arrays //Return combined 100 year arrays
List<double[]> data = new List<double[]>() List<Double[]> data = new List<Double[]>()
{ {
SE1601, SE1701, SE1801, SE1901, SE2001, SE1601, SE1701, SE1801, SE1901, SE2001,
SE2101, SE2201, SE2301, SE2401, SE2501 SE2101, SE2201, SE2301, SE2401, SE2501
}; };
double cent = Math.Floor(d.Year * .01) * 100; //Gets turn of century year. Double cent = Math.Floor(d.Year * .01) * 100; //Gets turn of century year.
int index = GetIndex(cent); //Gets index for calling data list. 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 proper 100 year table.
return data[index]; return data[index];
} }
private static int GetIndex(double cent) private static Int32 GetIndex(Double cent) {
{ Int32 dex = 0;
int dex = 0; Int32 c = Convert.ToInt32(cent * .01);
int c = Convert.ToInt32(cent * .01);
//START CENTURY 16 //START CENTURY 16
//END CENTRURY 26 //END CENTRURY 26
//AJDUST AS DATABASE GROWS //AJDUST AS DATABASE GROWS
for(int i = 16; i<26;i++) for (Int32 i = 16; i < 26; i++) {
{ if (i == c) { return dex; }
if(i == c) { return dex; }
dex++; dex++;
} }
return -1; return -1;

View File

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