public static void Arc(Cairo.Context context, PointF p, double r, double a1, double a2, bool clockwise, Color color, bool filled, double width = 1.0)
        {
            context.Save();
            context.Translate(p.X, p.Y);

            if (!filled)
            {
                context.LineWidth = width;
                context.LineCap   = Cairo.LineCap.Butt;
                context.LineJoin  = Cairo.LineJoin.Bevel;
            }
            var c = color.ToCairo();

            context.SetSourceRGBA(c.R, c.G, c.B, c.A);

            if (clockwise)
            {
                context.Arc(0, 0, r, a1, a2);
            }
            else
            {
                context.ArcNegative(0, 0, r, a1, a2);
            }

            if (filled)
            {
                context.Fill();
            }
            else
            {
                context.Stroke();
            }

            context.Restore();
        }
Ejemplo n.º 2
0
        private void DrawArcSegment(double xm1, double ym1, double xm2, double ym2, double xr, double yr, double alpha, bool isLargeArc, SweepDirection direction)
        {
            if (xr <= 0.000000001 || yr <= 0.000000001)
            {
                return;
            }

            var x1 = xm1 * Math.Cos(-alpha) - ym1 * Math.Sin(-alpha);
            var y1 = xm1 * Math.Sin(-alpha) + ym1 * Math.Cos(-alpha);

            var x2 = xm2 * Math.Cos(-alpha) - ym2 * Math.Sin(-alpha);
            var y2 = xm2 * Math.Sin(-alpha) + ym2 * Math.Cos(-alpha);

            var r = 0.0;

            if (xr > yr)
            {
                y1 = y1 * xr / yr;
                y2 = y2 * xr / yr;

                r = xr;
            }
            else
            {
                x1 = x1 * yr / xr;
                x2 = x2 * yr / xr;

                r = yr;
            }

            if (4 * r * r < (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
            {
                return;
            }

            var xc1 = 0.0;
            var xc2 = 0.0;
            var yc1 = 0.0;
            var yc2 = 0.0;

            if (Math.Abs(y1 - y2) > 0.000000001)
            {
                var A = (x1 - x2) / (y2 - y1);
                var B = (x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1) / (2 * (y2 - y1));

                var a = A * A + 1;
                var b = -2 * x1 + 2 * A * B - 2 * A * y1;
                var c = x1 * x1 + B * B - 2 * B * y1 + y1 * y1 - r * r;


                xc1 = (-b + Math.Sqrt(b * b - 4 * a * c)) / (2 * a);
                yc1 = A * xc1 + B;

                xc2 = (-b - Math.Sqrt(b * b - 4 * a * c)) / (2 * a);
                yc2 = A * xc2 + B;
            }
            else
            {
                xc1 = (x1 + x2) / 2;
                yc1 = y1 + Math.Sqrt(r * r - (xc1 - x1) * (xc1 - x1));

                xc2 = (x1 + x2) / 2;
                yc2 = y1 - Math.Sqrt(r * r - (xc2 - x1) * (xc2 - x1));
            }

            var angle1 = Math.Abs(y1 - yc1) / r > 1 ? Math.PI / 2 : Math.Asin(Math.Abs(y1 - yc1) / r);

            if ((x1 < xc1) && (y1 >= yc1))
            {
                angle1 = Math.PI - angle1;
            }
            if (y1 < yc1)
            {
                if (x1 < xc1)
                {
                    angle1 = Math.PI + angle1;
                }
                else
                {
                    angle1 = -angle1;
                }
            }

            var angle2 = Math.Abs(y2 - yc1) / r > 1 ? Math.PI / 2 : Math.Asin(Math.Abs(y2 - yc1) / r);

            if ((x2 < xc1) && (y2 >= yc1))
            {
                angle2 = Math.PI - angle2;
            }
            if (y2 < yc1)
            {
                if (x2 < xc1)
                {
                    angle2 = Math.PI + angle2;
                }
                else
                {
                    angle2 = -angle2;
                }
            }

            var alfa1 = Math.Abs(y1 - yc2) / r > 1 ? Math.PI / 2 : Math.Asin(Math.Abs(y1 - yc2) / r);

            if ((x1 < xc2) && (y1 >= yc2))
            {
                alfa1 = Math.PI - alfa1;
            }
            if (y1 < yc2)
            {
                if (x1 < xc2)
                {
                    alfa1 = Math.PI + alfa1;
                }
                else
                {
                    alfa1 = -alfa1;
                }
            }

            var alfa2 = Math.Abs(y2 - yc2) / r > 1 ? Math.PI / 2 : Math.Asin(Math.Abs(y2 - yc2) / r);

            if ((x2 < xc2) && (y2 >= yc2))
            {
                alfa2 = Math.PI - alfa2;
            }
            if (y2 < yc2)
            {
                if (x2 < xc2)
                {
                    alfa2 = Math.PI + alfa2;
                }
                else
                {
                    alfa2 = -alfa2;
                }
            }

            cr.Save();

            cr.Rotate(alpha);

            if (xr > yr)
            {
                cr.Scale(1, yr / xr);
            }
            else
            {
                cr.Scale(xr / yr, 1);
            }

            if (direction == SweepDirection.Clockwise)
            {
                if (isLargeArc)
                {
                    if ((y1 < y2) || ((Math.Abs(y1 - y2) < 0.00000001) && (x1 > x2)))
                    {
                        cr.Arc(xc1, yc1, r, angle1, angle2);
                    }
                    else
                    {
                        cr.Arc(xc2, yc2, r, alfa1, alfa2);
                    }
                }
                else
                {
                    if ((y1 > y2) || ((Math.Abs(y1 - y2) < 0.00000001) && (x1 < x2)))
                    {
                        cr.Arc(xc1, yc1, r, angle1, angle2);
                    }
                    else
                    {
                        cr.Arc(xc2, yc2, r, alfa1, alfa2);
                    }
                }
            }
            else
            {
                if (isLargeArc)
                {
                    if ((y1 > y2) || ((Math.Abs(y1 - y2) < 0.00000001) && (x1 < x2)))
                    {
                        cr.ArcNegative(xc1, yc1, r, angle1, angle2);
                    }
                    else
                    {
                        cr.ArcNegative(xc2, yc2, r, alfa1, alfa2);
                    }
                }
                else
                {
                    if ((y1 < y2) || ((Math.Abs(y1 - y2) < 0.00000001) && (x1 > x2)))
                    {
                        cr.ArcNegative(xc1, yc1, r, angle1, angle2);
                    }
                    else
                    {
                        cr.ArcNegative(xc2, yc2, r, alfa1, alfa2);
                    }
                }
            }

            cr.Restore();
        }