LMat619 0 Newbie Poster

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);
        }