コード例 #1
0
        public override VectorPoint Copy()
        {
            EllipseLinePoint point = new EllipseLinePoint(X, Y);

            point.Length     = Length;
            point.SweepAngle = SweepAngle;
            point.StartAngle = StartAngle;
            point.SinXAxis   = SinXAxis;
            point.CosXAxis   = CosXAxis;
            point.CenterX    = CenterX;
            point.CenterY    = CenterY;
            point.RadiusX    = RadiusX;
            point.RadiusY    = RadiusY;

            return(point);
        }
コード例 #2
0
        /// <summary>Handles SVG arcs.</summary>
        public void EllipseArc(float rx, float ry, float xAxisRotation, float p1x, float p1y, bool largeArcFlag, bool sweepFlag)
        {
            // In accordance to: http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters
            rx = Math.Abs(rx);
            ry = Math.Abs(ry);

            // If the endpoints are identical, do nothing.
            if (LatestPathNode.X == p1x && LatestPathNode.Y == p1y)
            {
                return;
            }

            // If rx = 0 or ry = 0 then this arc is treated as a straight line segment joining the endpoints.
            if (rx == 0f || ry == 0f)
            {
                LineTo(p1x, p1y);
                return;
            }

            // Normalize rotation from deg to radians:
            xAxisRotation = (xAxisRotation % 360f) * UnityEngine.Mathf.Deg2Rad;


            float cosXAxis = (float)Math.Cos(xAxisRotation);
            float sinXAxis = (float)Math.Sin(xAxisRotation);

            // Conversion from endpoint to center parameterization
            // http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter

            // #1: Compute transformed point
            float dx = (LatestPathNode.X - p1x) / 2f;
            float dy = (LatestPathNode.Y - p1y) / 2f;

            float transformedX = (float)(cosXAxis * dx + sinXAxis * dy);
            float transformedY = (float)(-sinXAxis * dx + cosXAxis * dy);

            // Ensure radii are large enough
            float radiiCheck = (float)(
                Math.Pow(transformedX, 2f) / Math.Pow(rx, 2f) +
                Math.Pow(transformedY, 2f) / Math.Pow(ry, 2f)
                );

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

            // #2: Compute transformed center
            float cSquareNumerator = (float)(
                Math.Pow(rx, 2f) * Math.Pow(ry, 2f) -
                Math.Pow(rx, 2f) * Math.Pow(transformedY, 2f) -
                Math.Pow(ry, 2f) * Math.Pow(transformedX, 2f)
                );

            float cSquareRootDenom = (float)(
                Math.Pow(rx, 2f) * Math.Pow(transformedY, 2f) +
                Math.Pow(ry, 2f) * Math.Pow(transformedX, 2f)
                );

            float cRadicand = cSquareNumerator / cSquareRootDenom;

            // Make sure this never drops below zero because of precision
            cRadicand = cRadicand < 0f ? 0f : cRadicand;

            float cCoef = (largeArcFlag != sweepFlag ? 1f : -1f) * (float)Math.Sqrt(cRadicand);

            float transformedCenterX = cCoef * ((rx * transformedY) / ry);
            float transformedCenterY = cCoef * (-(ry * transformedX) / rx);

            // #3: Compute center

            float centerX = (float)(
                cosXAxis * transformedCenterX -
                sinXAxis * transformedCenterY + ((LatestPathNode.X + p1x) / 2f)
                );

            float centerY = (float)(
                sinXAxis * transformedCenterX +
                cosXAxis * transformedCenterY + ((LatestPathNode.Y + p1y) / 2f)
                );

            // #4: Compute start/sweep angles
            // Start angle of the elliptical arc prior to the stretch and rotate operations.
            // Difference between the start and end angles
            UnityEngine.Vector2 startVector = new UnityEngine.Vector2(
                (transformedX - transformedCenterX) / rx,
                (transformedY - transformedCenterY) / ry
                );

            float startAngle = AngleBetween(new UnityEngine.Vector2(1f, 0f), startVector);

            UnityEngine.Vector2 endVector = new UnityEngine.Vector2(
                (-transformedX - transformedCenterX) / rx,
                (-transformedY - transformedCenterY) / ry
                );

            float sweepAngle = AngleBetween(startVector, endVector);

            if (!sweepFlag && sweepAngle > 0)
            {
                sweepAngle -= 2f * (float)Math.PI;
            }
            else if (sweepFlag && sweepAngle < 0)
            {
                sweepAngle += 2f * (float)Math.PI;
            }

            // We use % instead of `mod(..)` because we want it to be -360deg to 360deg(but actually in radians)
            sweepAngle %= 2f * (float)Math.PI;

            // Ellipse point:
            EllipseLinePoint elp = new EllipseLinePoint(p1x, p1y);

            // Apply values:
            elp.SweepAngle = sweepAngle;
            elp.StartAngle = startAngle;
            elp.SinXAxis   = sinXAxis;
            elp.CosXAxis   = cosXAxis;
            elp.CenterX    = centerX;
            elp.CenterY    = centerY;
            elp.RadiusX    = rx;
            elp.RadiusY    = ry;

            // Add it:
            AddPathNode(elp);
        }