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); }
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); }