Saturday, January 31, 2015

Plotting Points On A Circle

I once developed a small countdown timer application that used a pie-chart to display the remaining time.  This involved some high school math to be able to plot a line from the center of the circle and plot a radius to specified point on the line.  The same code would also be helpful for developing an application with a compass.

w = width of the space where the circle is bounded
h = height of the space where the circle is bounded
d = diameter (the shorter of w or h)
r = radius = d/2 = SQRT((x2-x1)^2 + (y2-y1)^2)
x1,y1 = circle center
x2,y2 = a point on the circumference
a = angle (from 12:00)
b = modified angle to convert from degrees to radians, reverse direction of unit circle, and start at 12:00 instead of 3:00.
t = total number of segments
s = segment number
a = (360/t) * s = 360 * (s/t)
b = (270 - a) * (Pi / 180)
x2 = x1 + (r * cos(b))
y2 = y1 + (r * sin(b))
x1 = w/2
y1 = h/2

For a space that  has a height of 400 and a width of 648
h = 400, w = 648
d = 400
r = 400/2 = 200
x1 = 648/2 = 324
y1 = 400/2 = 200

In the case of a clock, there are 60 seconds and thus 60 total segments
t = 60

Each second is 1 segment and thus 20 seconds is segment number 20
s = 20
a = (360/60) * 20 = 120
b =  (270 - 120) * (Pi / 180) = 149.9825

x2 = 324 + (200 * cos(149.9825)) = 324 + (200 * -0.5) = 324 + (-100) = 224
y2 = 200 + (200 * sin(149.9825)) = 200 + (200 * 0.866) = 200 + 173.21 = 373.21

In C#.NET, it looks like this:

  int radius = 0;
  double angle = 0;
  lineShape1.X1 = ClientSize.Width / 2;
  lineShape1.Y1 = ClientSize.Height / 2;
  if (lineShape1.X1 < lineShape1.Y1 ) {
      radius = lineShape1.X1;
  }
  else {
      radius = lineShape1.Y1;
  }
  angle =  Convert.ToDouble(360 *
              (Convert.ToDouble(TotalRemaining)
             / Convert.ToDouble(TotalStart)));
  angle = (270 - angle) * (Math.PI / 180);
  lineShape1.X2 = Convert.ToInt32(lineShape1.X1 
                   + (radius * Math.Cos(angle)));
  lineShape1.Y2 = Convert.ToInt32(lineShape1.Y1 
                   + (radius * Math.Sin(angle)));

download exe

download source code



No comments:

Post a Comment