예제 #1
0
        internal CalculatedArcValues GetCalculatedArcValues()
        {
            CalculatedArcValues calcVal = new CalculatedArcValues();

            /*
             *	This algorithm is taken from the Batik source. All cudos to the Batik crew.
             */

            PointF startPoint = PreviousSeg.AbsXY;
            PointF endPoint = AbsXY;

            float x0 = startPoint.X;
            float y0 = startPoint.Y;

            float x = endPoint.X;
            float y = endPoint.Y;

            // Compute the half distance between the current and the final point
            double dx2 = (x0 - x) / 2.0;
            double dy2 = (y0 - y) / 2.0;

            // Convert angle from degrees to radians
            double radAngle = Angle * Math.PI / 180;
            double cosAngle = Math.Cos(radAngle);
            double sinAngle = Math.Sin(radAngle);

            //
            // Step 1 : Compute (x1, y1)
            //
            double x1 = (cosAngle * dx2 + sinAngle * dy2);
            double y1 = (-sinAngle * dx2 + cosAngle * dy2);
            // Ensure radii are large enough

            double rx = Math.Abs(R1);
            double ry = Math.Abs(R2);

            double Prx = rx * rx;
            double Pry = ry * ry;
            double Px1 = x1 * x1;
            double Py1 = y1 * y1;

            // check that radii are large enough
            double radiiCheck = Px1/Prx + Py1/Pry;
            if (radiiCheck > 1)
            {
                rx = Math.Sqrt(radiiCheck) * rx;
                ry = Math.Sqrt(radiiCheck) * ry;
                Prx = rx * rx;
                Pry = ry * ry;
            }

            //
            // Step 2 : Compute (cx1, cy1)
            //
            double sign = (LargeArcFlag == SweepFlag) ? -1 : 1;
            double sq = ((Prx*Pry)-(Prx*Py1)-(Pry*Px1)) / ((Prx*Py1)+(Pry*Px1));
            sq = (sq < 0) ? 0 : sq;
            double coef = (sign * Math.Sqrt(sq));
            double cx1 = coef * ((rx * y1) / ry);
            double cy1 = coef * -((ry * x1) / rx);

            //
            // Step 3 : Compute (cx, cy) from (cx1, cy1)
            //
            double sx2 = (x0 + x) / 2.0;
            double sy2 = (y0 + y) / 2.0;
            double cx = sx2 + (cosAngle * cx1 - sinAngle * cy1);
            double cy = sy2 + (sinAngle * cx1 + cosAngle * cy1);

            //
            // Step 4 : Compute the angleStart (angle1) and the angleExtent (dangle)
            //
            double ux = (x1 - cx1); // rx;
            double uy = (y1 - cy1); // ry;
            double vx = (-x1 - cx1); // rx;
            double vy = (-y1 - cy1); // ry;
            double p, n;
            // Compute the angle start
            n = Math.Sqrt((ux * ux) + (uy * uy));
            p = ux; // (1 * ux) + (0 * uy)
            sign = (uy < 0) ? -1d : 1d;
            double angleStart = sign * Math.Acos(p / n);
            angleStart = angleStart * 180 / Math.PI;

            // Compute the angle extent
            n = Math.Sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy));
            p = ux * vx + uy * vy;
            sign = (ux * vy - uy * vx < 0) ? -1d : 1d;
            double angleExtent = sign * Math.Acos(p / n);
            angleExtent = angleExtent * 180 / Math.PI;

            if(!sweepFlag && angleExtent > 0)
            {
                angleExtent -= 360f;
            }
            else if (sweepFlag && angleExtent < 0)
            {
                angleExtent += 360f;
            }
            angleExtent %= 360f;
            angleStart %= 360f;

            calcVal.CorrRx = (float)rx;
            calcVal.CorrRy = (float)ry;
            calcVal.Cx = (float)cx;
            calcVal.Cy = (float)cy;
            calcVal.AngleStart = (float)angleStart;
            calcVal.AngleExtent = (float)angleExtent;

            return calcVal;
        }
예제 #2
0
        internal CalculatedArcValues GetCalculatedArcValues()
        {
            CalculatedArcValues calcVal = new CalculatedArcValues();

            /*
             *	This algorithm is taken from the Batik source. All cudos to the Batik crew.
             */

            PointF startPoint = PreviousSeg.AbsXY;
            PointF endPoint   = AbsXY;

            float x0 = startPoint.X;
            float y0 = startPoint.Y;

            float x = endPoint.X;
            float y = endPoint.Y;

            // Compute the half distance between the current and the final point
            double dx2 = (x0 - x) / 2.0;
            double dy2 = (y0 - y) / 2.0;

            // Convert angle from degrees to radians
            double radAngle = Angle * Math.PI / 180;
            double cosAngle = Math.Cos(radAngle);
            double sinAngle = Math.Sin(radAngle);

            //
            // Step 1 : Compute (x1, y1)
            //
            double x1 = (cosAngle * dx2 + sinAngle * dy2);
            double y1 = (-sinAngle * dx2 + cosAngle * dy2);
            // Ensure radii are large enough

            double rx = Math.Abs(R1);
            double ry = Math.Abs(R2);

            double Prx = rx * rx;
            double Pry = ry * ry;
            double Px1 = x1 * x1;
            double Py1 = y1 * y1;

            // check that radii are large enough
            double radiiCheck = Px1 / Prx + Py1 / Pry;

            if (radiiCheck > 1)
            {
                rx  = Math.Sqrt(radiiCheck) * rx;
                ry  = Math.Sqrt(radiiCheck) * ry;
                Prx = rx * rx;
                Pry = ry * ry;
            }

            //
            // Step 2 : Compute (cx1, cy1)
            //
            double sign = (LargeArcFlag == SweepFlag) ? -1 : 1;
            double sq   = ((Prx * Pry) - (Prx * Py1) - (Pry * Px1)) / ((Prx * Py1) + (Pry * Px1));

            sq = (sq < 0) ? 0 : sq;
            double coef = (sign * Math.Sqrt(sq));
            double cx1  = coef * ((rx * y1) / ry);
            double cy1  = coef * -((ry * x1) / rx);

            //
            // Step 3 : Compute (cx, cy) from (cx1, cy1)
            //
            double sx2 = (x0 + x) / 2.0;
            double sy2 = (y0 + y) / 2.0;
            double cx  = sx2 + (cosAngle * cx1 - sinAngle * cy1);
            double cy  = sy2 + (sinAngle * cx1 + cosAngle * cy1);

            //
            // Step 4 : Compute the angleStart (angle1) and the angleExtent (dangle)
            //
            double ux = (x1 - cx1);             // rx;
            double uy = (y1 - cy1);             // ry;
            double vx = (-x1 - cx1);            // rx;
            double vy = (-y1 - cy1);            // ry;
            double p, n;

            // Compute the angle start
            n    = Math.Sqrt((ux * ux) + (uy * uy));
            p    = ux;          // (1 * ux) + (0 * uy)
            sign = (uy < 0) ? -1d : 1d;
            double angleStart = sign * Math.Acos(p / n);

            angleStart = angleStart * 180 / Math.PI;

            // Compute the angle extent
            n    = Math.Sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy));
            p    = ux * vx + uy * vy;
            sign = (ux * vy - uy * vx < 0) ? -1d : 1d;
            double angleExtent = sign * Math.Acos(p / n);

            angleExtent = angleExtent * 180 / Math.PI;

            if (!sweepFlag && angleExtent > 0)
            {
                angleExtent -= 360f;
            }
            else if (sweepFlag && angleExtent < 0)
            {
                angleExtent += 360f;
            }
            angleExtent %= 360f;
            angleStart  %= 360f;

            calcVal.CorrRx      = (float)rx;
            calcVal.CorrRy      = (float)ry;
            calcVal.Cx          = (float)cx;
            calcVal.Cy          = (float)cy;
            calcVal.AngleStart  = (float)angleStart;
            calcVal.AngleExtent = (float)angleExtent;


            return(calcVal);
        }
예제 #3
0
        public GraphicsPath GetGraphicsPath()
        {
            if (gp == null)
            {
                gp = new GraphicsPath();

                PointF initPoint = new PointF(0, 0);
                PointF lastPoint = new PointF(0, 0);

                SvgPathSegList segments = (SvgPathSegList)PathSegList;
                SvgPathSeg     segment;

                int nElems = segments.NumberOfItems;

                for (int i = 0; i < nElems; i++)
                {
                    segment = (SvgPathSeg)segments.GetItem(i);

                    if (segment is SvgPathSegMoveto)
                    {
                        SvgPathSegMoveto seg = (SvgPathSegMoveto)segment;
                        gp.StartFigure();
                        lastPoint = initPoint = seg.AbsXY;
                    }
                    else if (segment is SvgPathSegLineto)
                    {
                        SvgPathSegLineto seg = (SvgPathSegLineto)segment;
                        PointF           p   = seg.AbsXY;
                        gp.AddLine(lastPoint.X, lastPoint.Y, p.X, p.Y);

                        lastPoint = p;
                    }
                    else if (segment is SvgPathSegCurveto)
                    {
                        SvgPathSegCurveto seg  = (SvgPathSegCurveto)segment;
                        PointF            xy   = seg.AbsXY;
                        PointF            x1y1 = seg.CubicX1Y1;
                        PointF            x2y2 = seg.CubicX2Y2;
                        gp.AddBezier(lastPoint.X, lastPoint.Y, x1y1.X, x1y1.Y, x2y2.X, x2y2.Y, xy.X, xy.Y);

                        lastPoint = xy;
                    }
                    else if (segment is SvgPathSegArc)
                    {
                        SvgPathSegArc seg = (SvgPathSegArc)segment;
                        PointF        p   = seg.AbsXY;
                        if (lastPoint.Equals(p))
                        {
                            // If the endpoints (x, y) and (x0, y0) are identical, then this
                            // is equivalent to omitting the elliptical arc segment entirely.
                        }
                        else if (seg.R1 == 0 || seg.R2 == 0)
                        {
                            // Ensure radii are valid
                            gp.AddLine(lastPoint, p);
                        }
                        else
                        {
                            CalculatedArcValues calcValues = seg.GetCalculatedArcValues();

                            GraphicsPath gp2 = new GraphicsPath();
                            gp2.StartFigure();
                            gp2.AddArc(
                                calcValues.Cx - calcValues.CorrRx,
                                calcValues.Cy - calcValues.CorrRy,
                                calcValues.CorrRx * 2,
                                calcValues.CorrRy * 2,
                                calcValues.AngleStart,
                                calcValues.AngleExtent
                                );

                            Matrix matrix = new Matrix();
                            matrix.Translate(
                                -calcValues.Cx,
                                -calcValues.Cy
                                );
                            gp2.Transform(matrix);

                            matrix = new Matrix();
                            matrix.Rotate(seg.Angle);
                            gp2.Transform(matrix);

                            matrix = new Matrix();
                            matrix.Translate(calcValues.Cx, calcValues.Cy);
                            gp2.Transform(matrix);

                            gp.AddPath(gp2, true);
                        }

                        lastPoint = p;
                    }
                    else if (segment is SvgPathSegClosePath)
                    {
                        gp.CloseFigure();
                        lastPoint = initPoint;
                    }
                }

                string fillRule = GetPropertyValue("fill-rule");
                if (fillRule == "evenodd")
                {
                    gp.FillMode = FillMode.Alternate;
                }
                else
                {
                    gp.FillMode = FillMode.Winding;
                }
            }

            return(gp);
        }