示例#1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="EllipseGeometry"/> class.
        /// </summary>
        /// <param name="rect">The rectangle that the ellipse should fill.</param>
        public EllipseGeometry(Rect rect)
        {
            IPlatformRenderInterface factory = PerspexLocator.Current.GetService <IPlatformRenderInterface>();
            IStreamGeometryImpl      impl    = factory.CreateStreamGeometry();

            using (IStreamGeometryContextImpl ctx = impl.Open())
            {
                double controlPointRatio = (Math.Sqrt(2) - 1) * 4 / 3;
                var    center            = rect.Center;
                var    radius            = new Vector(rect.Width / 2, rect.Height / 2);

                var x0 = center.X - radius.X;
                var x1 = center.X - (radius.X * controlPointRatio);
                var x2 = center.X;
                var x3 = center.X + (radius.X * controlPointRatio);
                var x4 = center.X + radius.X;

                var y0 = center.Y - radius.Y;
                var y1 = center.Y - (radius.Y * controlPointRatio);
                var y2 = center.Y;
                var y3 = center.Y + (radius.Y * controlPointRatio);
                var y4 = center.Y + radius.Y;

                ctx.BeginFigure(new Point(x2, y0), true);
                ctx.CubicBezierTo(new Point(x3, y0), new Point(x4, y1), new Point(x4, y2));
                ctx.CubicBezierTo(new Point(x4, y3), new Point(x3, y4), new Point(x2, y4));
                ctx.CubicBezierTo(new Point(x1, y4), new Point(x0, y3), new Point(x0, y2));
                ctx.CubicBezierTo(new Point(x0, y1), new Point(x1, y0), new Point(x2, y0));
                ctx.EndFigure(true);
            }

            PlatformImpl = impl;
        }
示例#2
0
 /// <summary>
 /// Draws a Bezier curve to the specified point.
 /// </summary>
 /// <param name="point1">The first control point used to specify the shape of the curve.</param>
 /// <param name="point2">The second control point used to specify the shape of the curve.</param>
 /// <param name="point3">The destination point for the end of the curve.</param>
 public void CubicBezierTo(Point point1, Point point2, Point point3)
 {
     _impl.CubicBezierTo(point1, point2, point3);
 }
示例#3
0
 /// <summary>
 /// Draws a Bezier curve to the specified point.
 /// </summary>
 /// <param name="point1">The first control point used to specify the shape of the curve.</param>
 /// <param name="point2">The second control point used to specify the shape of the curve.</param>
 /// <param name="point3">The destination point for the end of the curve.</param>
 public void CubicBezierTo(Point point1, Point point2, Point point3)
 {
     _impl.CubicBezierTo(point1, point2, point3);
     _currentPoint = point3;
 }
示例#4
0
 public static void QuadraticBezierTo(IStreamGeometryContextImpl context, Point current, Point controlPoint, Point endPoint)
 {
     //(s, (s + 2c)/ 3, (e + 2c)/ 3, e)
     context.CubicBezierTo((current + 2*controlPoint)/3, (endPoint + 2*controlPoint)/3, endPoint);
 }
示例#5
0
 public static void QuadraticBezierTo(IStreamGeometryContextImpl context, Point current, Point controlPoint, Point endPoint)
 {
     //(s, (s + 2c)/ 3, (e + 2c)/ 3, e)
     context.CubicBezierTo((current + 2 * controlPoint) / 3, (endPoint + 2 * controlPoint) / 3, endPoint);
 }
示例#6
0
            /// <summary>
            /// Builds the arc outline using given StreamGeometryContext
            /// </summary>
            /// <param name="path">A StreamGeometryContext to output the path commands to</param>
            /// <param name="degree">degree of the Bezier curve to use</param>
            /// <param name="threshold">acceptable error</param>
            /// <param name="openNewFigure">if true, a new figure will be started in the specified StreamGeometryContext</param>
            public void BuildArc(IStreamGeometryContextImpl path, int degree, double threshold, bool openNewFigure)
            {
                if (degree < 1 || degree > _maxDegree)
                    throw new ArgumentException($"degree should be between {1} and {_maxDegree}", nameof(degree));

                // find the number of Bezier curves needed
                bool found = false;
                int n = 1;
                double dEta;
                double etaB;
                while (!found && n < 1024)
                {
                    dEta = (Eta2 - Eta1) / n;
                    if (dEta <= 0.5 * Math.PI)
                    {
                        etaB = Eta1;
                        found = true;
                        for (int i = 0; found && i < n; ++i)
                        {
                            double etaA = etaB;
                            etaB += dEta;
                            found = EstimateError(degree, etaA, etaB) <= threshold;
                        }
                    }
                    n = n << 1;
                }
                dEta = (Eta2 - Eta1) / n;
                etaB = Eta1;
                double cosEtaB = Math.Cos(etaB);
                double sinEtaB = Math.Sin(etaB);
                double aCosEtaB = A * cosEtaB;
                double bSinEtaB = B * sinEtaB;
                double aSinEtaB = A * sinEtaB;
                double bCosEtaB = B * cosEtaB;
                double xB = Cx + aCosEtaB * _cosTheta - bSinEtaB * _sinTheta;
                double yB = Cy + aCosEtaB * _sinTheta + bSinEtaB * _cosTheta;
                double xBDot = -aSinEtaB * _cosTheta - bCosEtaB * _sinTheta;
                double yBDot = -aSinEtaB * _sinTheta + bCosEtaB * _cosTheta;

                /*
                  This controls the drawing in case of pies
                if (openNewFigure)
                {
                    if (IsPieSlice)
                    {
                        path.BeginFigure(new Point(Cx, Cy), false, false);
                        path.LineTo(new Point(xB, yB), true, true);
                    }
                    else
                    {
                        path.BeginFigure(new Point(xB, yB), false, false);
                    }
                }
                else
                {
                    //path.LineTo(new Point(xB, yB), true, true);
                }
                */

                //otherwise we're supposed to be already at the (xB,yB)

                double t = Math.Tan(0.5 * dEta);
                double alpha = Math.Sin(dEta) * (Math.Sqrt(4 + 3 * t * t) - 1) / 3;
                for (int i = 0; i < n; ++i)
                {
                    //double etaA = etaB;
                    double xA = xB;
                    double yA = yB;
                    double xADot = xBDot;
                    double yADot = yBDot;
                    etaB += dEta;
                    cosEtaB = Math.Cos(etaB);
                    sinEtaB = Math.Sin(etaB);
                    aCosEtaB = A * cosEtaB;
                    bSinEtaB = B * sinEtaB;
                    aSinEtaB = A * sinEtaB;
                    bCosEtaB = B * cosEtaB;
                    xB = Cx + aCosEtaB * _cosTheta - bSinEtaB * _sinTheta;
                    yB = Cy + aCosEtaB * _sinTheta + bSinEtaB * _cosTheta;
                    xBDot = -aSinEtaB * _cosTheta - bCosEtaB * _sinTheta;
                    yBDot = -aSinEtaB * _sinTheta + bCosEtaB * _cosTheta;
                    if (degree == 1)
                    {
                        path.LineTo(new Point(xB, yB));
                    }
                    else if (degree == 2)
                    {
                        double k = (yBDot * (xB - xA) - xBDot * (yB - yA)) / (xADot * yBDot - yADot * xBDot);
                        path.QuadraticBezierTo(new Point(xA + k * xADot, yA + k * yADot), new Point(xB, yB));
                    }
                    else
                    {
                        path.CubicBezierTo(
                            new Point(xA + alpha * xADot, yA + alpha * yADot),
                            new Point(xB - alpha * xBDot, yB - alpha * yBDot),
                            new Point(xB, yB)
                            );
                    }
                }
                if (IsPieSlice)
                {
                    path.LineTo(new Point(Cx, Cy));
                }
            }