Hey everyone. I am making an application where a user can draw shapes with their mouse. All the other shapes are implemented, but I am having difficulty with drawing arcs correctly. I got the program to draw arcs, but I am having some bugs in the code. Basically it's supposed to draw the arcs exactly like a 3-point arc in AutoCAD. So I specify the start and middle points, and then use the mouse to position the end point. My problem is that (for some reason) I can't invert the arc when it passes one side of the line made between the start and middle points of the arc. I am horrible at this kind of math so I am wondering if there is anyone out there who can help me out. Any help is appreciated. Thanks! Here is my code:
private void PreviewShape(MouseEventArgs e)
{
if (!line_drawn)
{
linept = new List<Point3D>();
lineTwo = (Point3D)GetPoints(e);
linept.Add(lineOne);
linept.Add(lineTwo);
LinesVisual3D line = new LinesVisual3D();
line.Thickness = 2;
line.Color = Colors.Blue;
line.Points = linept;
if (!skip_remove)
port.Children.RemoveAt(port.Children.Count - 1);
port.Children.Add(line);
}
if (line_drawn)
{
Point3D currentPoint = (Point3D)GetPoints(e);
Point3D center = GetCenterOfCircle(linept.ElementAt(0), linept.ElementAt(1), currentPoint);
PieSliceVisual3D circle = new PieSliceVisual3D();
double RadiusX = Math.Abs(lineOne.X - center.X);
double RadiusY = Math.Abs(lineOne.Y - center.Y);
circle.Center = center;
if (RadiusX >= RadiusY)
circle.OuterRadius = RadiusX;
else
circle.OuterRadius = RadiusY;
circle.InnerRadius = circle.OuterRadius + 3;
if (currentPoint.Y > linept.ElementAt(0).Y)
{
circle.StartAngle = (Math.Atan2(linept.ElementAt(0).Y - center.Y, linept.ElementAt(0).X - center.X) * (180 / Math.PI));
if (circle.StartAngle < 0)
circle.StartAngle += 360;
circle.EndAngle = (Math.Atan2(currentPoint.Y - center.Y, currentPoint.X - center.X) * (180 / Math.PI));
if (circle.EndAngle < 0)
circle.EndAngle += 360;
}
else
{
circle.StartAngle = (Math.Atan2(linept.ElementAt(0).Y - center.Y, linept.ElementAt(0).X - center.X) * (180 / Math.PI));
if (circle.StartAngle < 0)
circle.StartAngle += 360;
circle.EndAngle = (Math.Atan2(currentPoint.Y - center.Y, currentPoint.X - center.X) * (180 / Math.PI));
if (circle.EndAngle < 0)
circle.EndAngle += 360;
}
if (!skip_remove)
port.Children.RemoveAt(port.Children.Count - 1);
port.Children.Add(circle);
}
}
private void Select_Point(object sender, MouseButtonEventArgs e)
{
if (line_drawn)
return;
if (!firstPointSelected && !line_drawn)
{
lineOne = (Point3D)GetPoints(e);
preview = true;
firstPointSelected = true;
}
else if (firstPointSelected)
firstPointSelected = false;
}
private Point3D? GetPoints(MouseEventArgs e)
{
var p = e.GetPosition(port);
var ray = Viewport3DHelper.Point2DtoRay3D(port.Viewport, p);
if (ray != null)
{
var pi = ray.PlaneIntersection(new Point3D(0, 0, .6), new Vector3D(0, 0, 1));
if (pi.HasValue)
return pi;
}
return null;
}
private void Draw_Line(object sender, MouseButtonEventArgs e)
{
if (firstPointSelected)
return;
linept = new List<Point3D>();
if (!line_drawn)
{
lineTwo = (Point3D)GetPoints(e);
linept.Add(lineOne);
linept.Add(lineTwo);
LinesVisual3D line = new LinesVisual3D();
line.Thickness = 2;
line.Color = Colors.Blue;
line.Points = linept;
//port.Children.Add(line);
line_drawn = true;
}
else if (line_drawn)
{
Point3D center = GetCenterOfCircle(linept.ElementAt(0), linept.ElementAt(1), linept.ElementAt(2));
circle = new PieSliceVisual3D();
double RadiusX = Math.Abs(lineOne.X - center.X);
double RadiusY = Math.Abs(lineOne.Y - center.Y);
circle.Center = center;
if (RadiusX >= RadiusY)
circle.OuterRadius = RadiusX;
else
circle.OuterRadius = RadiusY;
circle.InnerRadius = circle.OuterRadius + 3;
if (linept.ElementAt(2).Y > linept.ElementAt(0).Y)
{
circle.StartAngle = (Math.Atan2(linept.ElementAt(0).Y - center.Y, linept.ElementAt(0).X - center.X) * 180 / Math.PI);
if (circle.StartAngle < 0)
circle.StartAngle += 360;
circle.EndAngle = (Math.Atan2(linept.ElementAt(2).Y - center.Y, linept.ElementAt(2).X - center.X) * 180 / Math.PI);
if (circle.EndAngle < 0)
circle.EndAngle += 360;
}
else
{
//the correct one
circle.StartAngle = (Math.Atan2(linept.ElementAt(0).Y - center.Y, linept.ElementAt(0).X - center.X) * 180 / Math.PI);
if (circle.StartAngle < 0)
circle.StartAngle += 360;
circle.EndAngle = (Math.Atan2(linept.ElementAt(2).Y - center.Y, linept.ElementAt(2).X - center.X) * 180 / Math.PI);
if (circle.EndAngle < 0)
circle.EndAngle += 360;
}
port.Children.RemoveAt(port.Children.Count - 1);
port.Children.Add(circle);
line_drawn = false;
preview = false;
skip_remove = true;
}
}
private Point3D GetCenterOfCircle(Point3D startArc, Point3D middleArc, Point3D endArc)
{
double t = middleArc.X * middleArc.X + middleArc.Y * middleArc.Y;
double bc = (startArc.X * startArc.X + startArc.Y * startArc.Y - t) / 2.0;
double cd = (t - endArc.X * endArc.X - endArc.Y * endArc.Y) / 2.0;
double det = (startArc.X - middleArc.X) * (middleArc.Y - endArc.Y) - (middleArc.X - endArc.X) * (startArc.Y - middleArc.Y);
det = 1 / det;
double x = (bc * (middleArc.Y - endArc.Y) - cd * (startArc.Y - middleArc.Y)) * det;
double y = ((startArc.X - middleArc.X) * cd - (middleArc.X - endArc.X) * bc) * det;
double r = Math.Sqrt((x - startArc.X) * (x - startArc.X) + (y - startArc.Y) * (y - startArc.Y));
return new Point3D(x, y, .6);
}