1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Drawing;
5 using System.Data;
6 using System.Linq;
7 using System.Text;
8 using System.Windows.Forms;
9 using NETGeographicLib;
10 
11 namespace Projections
12 {
13     public partial class RhumbPanel : UserControl
14     {
15         Rhumb m_rhumb;
RhumbPanel()16         public RhumbPanel()
17         {
18             InitializeComponent();
19             m_rhumb = Rhumb.WGS84();
20             m_Lat1TextBox.Text = "32";
21             m_lon1TextBox.Text = "-86";
22             m_lat2TextBox.Text = "33";
23             m_lon2TextBox.Text = "-87";
24             OnIndirect(this, null);
25         }
26 
OnDirect(object sender, EventArgs e)27         private void OnDirect(object sender, EventArgs e)
28         {
29             try
30             {
31                 double lat1 = Double.Parse( m_Lat1TextBox.Text );
32                 double lon1 = Double.Parse( m_lon1TextBox.Text );
33                 double s12 = Double.Parse( m_s12TextBox.Text );
34                 double azimuth = Double.Parse( m_azimuthTextBox.Text );
35                 double lat2, lon2;
36                 m_rhumb.Direct(lat1, lon1, azimuth, s12, out lat2, out lon2);
37                 m_lat2TextBox.Text = lat2.ToString();
38                 m_lon2TextBox.Text = lon2.ToString();
39                 GeneratePoints(lat1, lon1, azimuth, 0.25 * s12);
40             }
41             catch (Exception xcpt )
42             {
43                 MessageBox.Show( xcpt.Message, "Invalid input", MessageBoxButtons.OK, MessageBoxIcon.Error );
44             }
45         }
46 
OnIndirect(object sender, EventArgs e)47         private void OnIndirect(object sender, EventArgs e)
48         {
49             try
50             {
51                 double lat1 = Double.Parse(m_Lat1TextBox.Text);
52                 double lon1 = Double.Parse(m_lon1TextBox.Text);
53                 double lat2 = Double.Parse(m_lat2TextBox.Text);
54                 double lon2 = Double.Parse(m_lon2TextBox.Text);
55                 double s12, azimuth;
56                 m_rhumb.Inverse(lat1, lon1, lat2, lon2, out s12, out azimuth);
57                 m_s12TextBox.Text = s12.ToString();
58                 m_azimuthTextBox.Text = azimuth.ToString();
59                 GeneratePoints(lat1, lon1, azimuth, 0.25 * s12);
60             }
61             catch (Exception xcpt)
62             {
63                 MessageBox.Show(xcpt.Message, "Invalid input", MessageBoxButtons.OK, MessageBoxIcon.Error);
64             }
65         }
66 
GeneratePoints( double lat1, double lon1, double azimuth, double space )67         private void GeneratePoints( double lat1, double lon1, double azimuth, double space )
68         {
69             RhumbLine line = m_rhumb.Line(lat1, lon1, azimuth);
70             m_pointsView.Items.Clear();
71             for (int i = 0; i < 5; i++)
72             {
73                 double lat2, lon2;
74                 line.Position(i * space, out lat2, out lon2);
75                 string[] items = new string[2] { lat2.ToString(), lon2.ToString() };
76                 ListViewItem item = new ListViewItem(items);
77                 m_pointsView.Items.Add(item);
78             }
79         }
80 
OnValidate(object sender, EventArgs e)81         private void OnValidate(object sender, EventArgs e)
82         {
83             try
84             {
85                 Rhumb r = new Rhumb(NETGeographicLib.Constants.WGS84.EquatorialRadius, NETGeographicLib.Constants.WGS84.Flattening, true);
86                 double lat1 = 32.0, lon1 = -86.0, azi12 = 45.0, s12 = 5000.0;
87                 double lat2, lon2, _s12, _azi12, Area, _Area;
88                 r.Direct(lat1, lon1, azi12, s12, out lat2, out lon2);
89                 r.Inverse(lat1, lon1, lat2, lon2, out _s12, out _azi12);
90                 if ( Test(s12,_s12) || Test(azi12,_azi12))
91                     throw new Exception(String.Format("Inverse != Direct: S12 -> {0}, {1}, azi12 -> {2}, {3}", s12, _s12, azi12, _azi12));
92                 r.Direct(lat1, lon1, azi12, s12, out lat2, out lon2, out Area);
93                 r.Inverse(lat1, lon1, lat2, lon2, out _s12, out _azi12, out _Area);
94                 if (Test(s12, _s12) || Test(azi12, _azi12) || Test(Area,_Area))
95                     throw new Exception(String.Format("Inverse != Direct: S12 -> {0}, {1}, azi12 -> {2}, {3}, Area -> {4}, {5}", s12, _s12, azi12, _azi12, Area, _Area));
96 
97                 double _lat2, _lon2;
98                 RhumbLine l = r.Line(lat1, lon1, azi12);
99                 l.Position(s12, out _lat2, out _lon2);
100                 if (Test(lat2,_lat2) || Test(lon2, _lon2))
101                     throw new Exception(String.Format("Latitude -> {0}, {1}, Longitude -> {2}, {3}", lat2, _lat2, lon2, _lon2));
102                 l.Position(s12, out _lat2, out _lon2, out _Area);
103                 if (Test(lat2, _lat2) || Test(lon2, _lon2) || Test(Area, _Area))
104                     throw new Exception(String.Format("Latitude -> {0}, {1}, Longitude -> {2}, {3}, Area -> {4}, {5}", lat2, _lat2, lon2, _lon2, Area, _Area));
105 
106                 MessageBox.Show("No exceptions detected", "OK", MessageBoxButtons.OK, MessageBoxIcon.Information);
107             }
108             catch ( Exception xcpt )
109             {
110                 MessageBox.Show( xcpt.Message, "Exception thrown", MessageBoxButtons.OK, MessageBoxIcon.Error );
111             }
112         }
113 
Test(double a, double b)114         bool Test(double a, double b)
115         {
116             double delta = a != 0.0 ? Math.Abs((a - b) / a) : Math.Abs(a - b);
117             return delta > 1.0e-12;
118         }
119     }
120 }
121