Вопрос

I am working on a countdown project that involves an arc. I've been struggling with the math for a few hours now and hope someone can help me. I have a 150px circle on which I want to draw arc that runs over starting at the top. The circle (ellipse really) is at 160,4

<Ellipse Height="150" HorizontalAlignment="Left" Margin="160,4,0,0"
   Name="minutesClock" Stroke="Gainsboro" StrokeThickness="20" 
   VerticalAlignment="Top" Width="150" />

I have a method that is supposed to calculate the arc from the center top of the circle to whatever number of seconds is left

 private void drawArc(int timevalue, int maxvalue)
 { 
   Ellipse element = (Ellipse)LayoutRoot.FindName("minutesClock");
   double top = element.Margin.Top;
   double left = element.Margin.Left;
   double width = element.Width;
   double height = element.Height;
   double strokeWidth = element.StrokeThickness;

   double startX = left + (width / 2);
   double startY = top + (strokeWidth / 2);
   double radius = (width / 2) - (strokeWidth / 2);

   double percent = (double)timevalue / (double)maxvalue;
   Point center = new Point();
   center.X = top + (height / 2);
   center.Y = left + (width / 2);
   Point newEnd = calculatePoint(radius, percent, center);

   Path arc = (Path)LayoutRoot.FindName(what + "Arc");

   PathFigure path = new PathFigure();
   path.StartPoint = new Point(startX, startY);
   ArcSegment arcSegment = new ArcSegment();
   arcSegment.IsLargeArc = false;
   Size arcSize = new Size(radius,radius);
   arcSegment.Size = arcSize;
   arcSegment.SweepDirection = SweepDirection.Clockwise;

   arcSegment.Point = newEnd;
   arcSegment.RotationAngle = 45;

   path.Segments.Add(arcSegment);

   PathGeometry pg = new PathGeometry();
   pg.Figures = new PathFigureCollection();
   pg.Figures.Add(path);
   arc.Data = pg;
 }

The arc starts at the right place but doesn't end up in the right place (the end point is all over the place). My calculatePoint code has to be where the error is. I figure it has something to do with

private Point calculatePoint(double radius, double percent, Point center)
{
  double degrees = 90 - (360 * percent);
  double radians = (Math.PI * degrees) / 180;
  Point endPoint = new Point();
  endPoint.X = center.X + (radius * Math.Sin(radians));
  endPoint.Y = center.Y + (radius * Math.Cos(radians));

  return endPoint;
}

Where am I going wrong?

Это было полезно?

Решение

You need to subtract the sinus (to go from the center "upwards" on the UI canvas):

endPoint.X = center.X - (radius * Math.Sin(radians));

Origin 0,0 is Top Left corner, not bottom left.

[Edit] Oh and you are confusding x and y: think x is horizontal coordinated and y is vertical, so this is wrong:

center.X = top + (height / 2);
center.Y = left + (width / 2);

and this is wrong:

endPoint.X = center.X + (radius * Math.Sin(radians));
endPoint.Y = center.Y + (radius * Math.Cos(radians));

Corrected:

center.Y = top + (height / 2);
center.X = left + (width / 2);

and (with the subtraction fix I mentioned)

endPoint.Y = center.Y - (radius * Math.Sin(radians));
endPoint.X = center.X + (radius * Math.Cos(radians));
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top