title: Find point on ellipse given the angle, then reverse the process
body: <p>My first task is simple: find the points of the ellipse to be drawn on screen.  I made an Ellipse class below with a method that takes in an angle between 0 to 2*PI and returns the point.  </p>
  
  <pre><code>public class Ellipse
  {
      public PointF Center { get; set; }
      public float A { get; set; }  /* horizontal semiaxis */
      public float B { get; set; }  /* vertical semiaxis */
  
      public Ellipse(PointF center, float a, float b)
      {
          this.Center = center;
          this.A = a;
          this.B = b;
      }        
  
      public PointF GetXYWhenT(float t_rad)
      {
          float x = this.Center.X + (this.A * (float)Math.Cos(t_rad));
          float y = this.Center.Y + (this.B * (float)Math.Sin(t_rad));
          return new PointF(x, y);
      }
  }
  </code></pre>
  
  <p>I use the parametric equation of the ellipse as it is convenient for this task.  Parameter t is the angle.  X and Y values are calculated and put together as a point on the ellipse.  By increasing parameter t, I can obtain the points in the order that makes drawing the ellipse as simple as connecting the dots.</p>
  
  <pre><code>private void RunTest1()
  {
      PointF center = new PointF(0, 0);
      float a = 3;  /* horizontal semiaxis */
      float b = 4;  /* vertical semiaxis */
      Ellipse ellipse = new Ellipse(center, a, b);
  
      List&lt;PointF&gt; curve = new List&lt;PointF&gt;();   /* collects all points needed to draw the ellipse */
  
      float start = 0;
      float end = (float)(2 * Math.PI);  /* 360 degrees */
      float step = 0.0174533f;  /* 1 degree */
  
      for (float t_rad = start; t_rad &lt;= end; t_rad += step)
      {
          PointF point = ellipse.GetXYWhenT(t_rad);
          curve.Add(point);
      }
  }
  </code></pre>
  
  <p>RunTest<em>X</em> are methods I run in Main.  The first will give me the points I need to draw this ellipse.  The points are correct.  <em>I have visual confirmation of the ellipse being drawn to specification</em> using a draw method that I will not be including here.  <strong>Drawing it is NOT the issue.</strong>  The takeaway here is that for every value of t_rad, I have a corresponding point on the curve. </p>
  
  <p>Now I need to perform a different task after I draw the ellipse.  To do this, I need to reverse the process in that I take an arbitrary point on the ellipse and convert it back to the t_rad.  Math.Atan2 should do the trick. The method is called GetTWhenPoint.  It's an extension method in MyMath class.  </p>
  
  <pre><code>public static class MyMath
  {
      public static float GetTWhenPoint(this PointF center, PointF point)
      {
          float x = point.X - center.X;
          float y = point.Y - center.Y;
  
          float retval = (float)Math.Atan2(y, x);
          if (retval &lt; 0)
          {
              retval += (float)(2 * Math.PI);
          }
  
          return retval;
      }
  }
  </code></pre>
  
  <p>Simple trigonometry, right?  However... </p>
  
  <pre><code>private void RunTest2()
  {
      PointF center = new PointF(0, 0);
      float a = 3;  /* horizontal semiaxis */
      float b = 4;  /* vertical semiaxis */
      Ellipse ellipse = new Ellipse(center, a, b);
  
      string debug = "TEST 2\r\n";
  
      float start = 0;
      float end = (float)(2 * Math.PI);  
      float step = 0.0174533f;      
  
      for (float t_rad = start; t_rad &lt;= end; t_rad += step)
      {
          PointF point = ellipse.GetXYWhenT(t_rad);
          double t_rad2 = center.GetTWhenPoint(point);
          debug += t_rad.ToString() + "\t" + t_rad2.ToString() + "\r\n";
      }
  
      Clipboard.SetText(debug);
  }
  </code></pre>
  
  <p>When I use it to convert the point back to t_rad2, I expect it to be equal to or pretty darn close to the original t_rad.  </p>
  
  <pre><code>TEST 2
  0   0
  0.0174533   0.0232692267745733
  0.0349066   0.0465274415910244
  0.0523599   0.0697636753320694
  0.0698132   0.0929670184850693
  0.0872665   0.116126760840416
  ...
  6.178444    6.14392471313477
  6.195897    6.1670298576355
  6.21335 6.19018936157227
  6.230803    6.21339273452759
  6.248257    6.23662853240967
  6.26571 6.25988674163818
  6.283163    6.28315591812134
  </code></pre>
  
  <p>What am I missing here? All my numbers so far have been in radians (as far as I can tell).  Now here's where it gets weirder... </p>
  
  <pre><code>private void RunTest3()
  {
      PointF center = new PointF(0, 0);
      float a = 4;  /* horizontal semiaxis */
      float b = 4;  /* vertical semiaxis */
      Ellipse ellipse = new Ellipse(center, a, b);
  
      string debug = "TEST 3\r\n";
  
      float start = 0;
      float end = (float)(2 * Math.PI);
      float step = 0.0174533f;  
  
      for (float t_rad = start; t_rad &lt;= end; t_rad += step)
      {
          PointF point = ellipse.GetXYWhenT(t_rad);
          double t_rad2 = center.GetTWhenPoint(point);
          debug += t_rad.ToString() + "\t" + t_rad2.ToString() + "\r\n";
      }
  
      Clipboard.SetText(debug);    
  }
  </code></pre>
  
  <p>If I set a and b equal to make the ellipse a perfect circle then everything looks normal!  </p>
  
  <pre><code>TEST 3
  0   0
  0.0174533   0.0174532998353243
  0.0349066   0.0349065996706486
  0.0523599   0.0523599050939083
  0.0698132   0.0698131918907166
  0.0872665   0.0872664898633957
  ...    
  6.178444    6.17844390869141
  6.195897    6.19589710235596
  6.21335 6.21335029602051
  6.230803    6.23080348968506
  6.248257    6.24825668334961
  6.26571 6.26570987701416
  6.283163    6.28316307067871
  </code></pre>
  
  <p>What this tells me is that when I convert the point back to t_rad2 it is somehow affected by the dimensions of the ellipse.  But how?  Apart from the center adjustment of the ellipse with respect to the Cartesian origin (0,0), GetTWhenPoint method does not make use of any other information from the Ellipse class specifically the semi-axes.  Math.Atan2 only needs the x and y values of the point to find the angle it makes with the 0-degree vector.  That's basic trigonometry.  </p>
  
  <p>It shouldn't even care that it's a point on the ellipse.  From the  context of the method, it's just a point just like infinitely any other.  How is my extension method somehow being affected by the dimensions of my ellipse? </p>
  
  <p>Is it my math that's wrong? I mean it's been a while since I used trig but I think I remember the simple ones correctly.  </p>
  
  <p>Thanks in advance!</p>