Пример #1
0
        public float[] Approximate(float precision)
        {
            var pathIteratorFactory = new CachedPathIteratorFactory(new FullPathIterator(this));
            var pathIterator        = pathIteratorFactory.Iterator();

            float[] points        = new float[8];
            var     segmentPoints = new List <Vector2>();
            var     lengths       = new List <float>();
            float   errorSquared  = precision * precision;

            while (!pathIterator.Done)
            {
                var type = pathIterator.CurrentSegment(points);
                switch (type)
                {
                case PathIterator.ContourType.MoveTo:
                    AddMove(segmentPoints, lengths, points);
                    break;

                case PathIterator.ContourType.Close:
                    AddLine(segmentPoints, lengths, points);
                    break;

                case PathIterator.ContourType.Line:
                    AddLine(segmentPoints, lengths, points.Skip(2).ToArray());
                    break;

                case PathIterator.ContourType.Arc:
                    AddBezier(points, QuadraticBezierCalculation, segmentPoints, lengths, errorSquared, false);
                    break;

                case PathIterator.ContourType.Bezier:
                    AddBezier(points, CubicBezierCalculation, segmentPoints, lengths, errorSquared, true);
                    break;
                }

                pathIterator.Next();
            }

            if (!segmentPoints.Any())
            {
                int numVerbs = Contours.Count;
                if (numVerbs == 1)
                {
                    AddMove(segmentPoints, lengths, Contours[0].Points);
                }
                else
                {
                    // Invalid or empty path. Fall back to point(0,0)
                    AddMove(segmentPoints, lengths, new[] { 0.0f, 0.0f });
                }
            }

            float totalLength = lengths.Last();

            if (totalLength == 0)
            {
                // Lone Move instructions should still be able to animate at the same value.
                segmentPoints.Add(segmentPoints.Last());
                lengths.Add(1);
                totalLength = 1;
            }

            var numPoints = segmentPoints.Count;
            var approximationArraySize = numPoints * 3;

            var approximation = new float[approximationArraySize];

            int approximationIndex = 0;

            for (var i = 0; i < numPoints; i++)
            {
                var point = segmentPoints[i];
                approximation[approximationIndex++] = lengths[i] / totalLength;
                approximation[approximationIndex++] = point.X;
                approximation[approximationIndex++] = point.Y;
            }

            return(approximation);
        }
Пример #2
0
        public bool GetSegment(float startD, float stopD, ref Path dst, bool startWithMoveTo)
        {
            var length = Length;

            if (startD < 0)
            {
                startD = 0;
            }

            if (stopD > length)
            {
                stopD = length;
            }

            if (startD >= stopD)
            {
                return(false);
            }

            var iterator = _originalPathIterator.Iterator();

            var accLength    = startD;
            var isZeroLength = true;

            var points = new float[6];

            iterator.JumpToSegment(accLength);

            while (!iterator.Done && stopD - accLength > 0.1f)
            {
                var type = iterator.CurrentSegment(points, stopD - accLength);

                if (accLength - iterator.CurrentSegmentLength <= stopD)
                {
                    if (startWithMoveTo)
                    {
                        startWithMoveTo = false;

                        if (type != PathIterator.ContourType.MoveTo == false)
                        {
                            var lastPoint = new float[2];
                            iterator.GetCurrentSegmentEnd(lastPoint);
                            dst.MoveTo(lastPoint[0], lastPoint[1]);
                        }
                    }

                    isZeroLength = isZeroLength && iterator.CurrentSegmentLength > 0;
                    switch (type)
                    {
                    case PathIterator.ContourType.MoveTo:
                        dst.MoveTo(points[0], points[1]);
                        break;

                    case PathIterator.ContourType.Line:
                        dst.LineTo(points[0], points[1]);
                        break;

                    case PathIterator.ContourType.Close:
                        dst.Close();
                        break;

                    case PathIterator.ContourType.Bezier:
                    case PathIterator.ContourType.Arc:
                        dst.CubicTo(points[0], points[1],
                                    points[2], points[3],
                                    points[4], points[5]);
                        break;
                    }
                }

                accLength += iterator.CurrentSegmentLength;
                iterator.Next();
            }

            return(!isZeroLength);
        }