Пример #1
0
        public BezierSubdivision Prev() // Previous index at current level
        {
            var next = new BezierSubdivision(new List <Vector2>(Points), Level, Index - 1);

            next.ScaleRight(-1);
            next.Reverse();
            return(next);
        }
Пример #2
0
        public BezierSubdivision Parent() // Parent subdivision (inverse of BezierSubdivide)
        {
            var parent = new BezierSubdivision(new List <Vector2>(Points), Level - 1, Index >> 1);

            if ((Index & 1) == 0)
            {
                parent.ScaleRight(2);
            }
            else
            {
                parent.ScaleLeft(-1);
            }
            return(parent);
        }
Пример #3
0
        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);
        }