public static IEnumerable <double> GetRedAnchorCompletions(SliderPath sliderPath)
        {
            int    start       = 0;
            int    end         = 0;
            double totalLength = 0;
            var    anchors     = sliderPath.ControlPoints;

            for (int i = 0; i < anchors.Count; i++)
            {
                end++;

                if (i == anchors.Count - 1 || anchors[i] != anchors[i + 1])
                {
                    continue;
                }

                var cpSpan      = anchors.GetRange(start, end - start);
                var subdivision = new BezierSubdivision(cpSpan);
                totalLength += subdivision.SubdividedApproximationLength();

                yield return(totalLength / sliderPath.Distance);

                start = end;
            }
        }
        public static IEnumerable <BezierSubdivision> ChopAnchors(SliderPath sliderPath)
        {
            switch (sliderPath.Type)
            {
            case PathType.Catmull:
            case PathType.Linear:
                return(ChopAnchorsLinear(sliderPath.ControlPoints));

            default:
                return(ChopAnchors(sliderPath.ControlPoints));
            }
        }
        public static List <Vector2> MoveAnchorsToLength(List <Vector2> anchors, PathType pathType, double newLength, out PathType newPathType)
        {
            var newAnchors    = new List <Vector2>();
            var sliderPath    = new SliderPath(pathType, anchors.ToArray(), newLength);
            var maxSliderPath = new SliderPath(pathType, anchors.ToArray());

            if (newLength > maxSliderPath.Distance)
            {
                // Extend linearly
                switch (pathType)
                {
                case PathType.Bezier:
                    newPathType = PathType.Bezier;
                    newAnchors.AddRange(anchors);
                    newAnchors.Add(anchors.Last());
                    newAnchors.Add(sliderPath.PositionAt(1));
                    break;

                case PathType.Catmull:
                case PathType.PerfectCurve:
                    // Convert to bezier and then extend
                    newPathType = PathType.Bezier;
                    newAnchors  = BezierConverter.ConvertToBezier(sliderPath).ControlPoints;
                    newAnchors.Add(anchors.Last());
                    newAnchors.Add(sliderPath.PositionAt(1));
                    break;

                default:
                    newPathType = pathType;
                    newAnchors.AddRange(anchors);
                    newAnchors[newAnchors.Count - 1] = sliderPath.PositionAt(1);
                    break;
                }
            }
            else
            {
                switch (sliderPath.Type)
                {
                case PathType.Catmull:
                case PathType.Bezier:
                    newPathType = PathType.Bezier;

                    // Convert in case the path type is catmull
                    var convert = BezierConverter.ConvertToBezier(sliderPath).ControlPoints;

                    // Find the last bezier segment and the pixel length at that part
                    BezierSubdivision subdivision = null;
                    double            totalLength = 0;

                    foreach (var bezierSubdivision in ChopAnchors(convert))
                    {
                        subdivision = bezierSubdivision;
                        var length = bezierSubdivision.SubdividedApproximationLength();

                        if (totalLength + length > newLength)
                        {
                            break;
                        }

                        totalLength += length;
                        newAnchors.AddRange(bezierSubdivision.Points);
                    }

                    if (subdivision == null)
                    {
                        break;
                    }

                    // Find T for the remaining pixel length
                    var t = subdivision.LengthToT(newLength - totalLength);

                    // ScaleRight the BezierSubdivision so the anchors end at T
                    subdivision.ScaleRight(t);

                    // Add the scaled anchors
                    newAnchors.AddRange(subdivision.Points);
                    break;

                case PathType.PerfectCurve:
                    newPathType = PathType.PerfectCurve;
                    newAnchors.AddRange(anchors);
                    newAnchors[1] = sliderPath.PositionAt(0.5);
                    newAnchors[2] = sliderPath.PositionAt(1);
                    break;

                default:
                    newPathType = pathType;
                    if (anchors.Count > 2)
                    {
                        // Find the section of the linear slider which contains the slider end
                        totalLength = 0;
                        foreach (var bezierSubdivision in ChopAnchorsLinear(anchors))
                        {
                            newAnchors.Add(bezierSubdivision.Points[0]);
                            var length = bezierSubdivision.Length();

                            if (totalLength + length > newLength)
                            {
                                break;
                            }

                            totalLength += length;
                        }
                        newAnchors.Add(sliderPath.PositionAt(1));
                    }
                    else
                    {
                        newAnchors.AddRange(anchors);
                        newAnchors[newAnchors.Count - 1] = sliderPath.PositionAt(1);
                    }
                    break;
                }
            }

            return(newAnchors);
        }