/// <summary>
        /// Creates a list of equally spaced points that lie on the path described by straight line segments between
        /// adjacent points in the source list.
        /// </summary>
        /// <param name="src">Source list of points.</param>
        /// <param name="md">Distance between points on the new path.</param>
        /// <returns>List of equally-spaced points on the path.</returns>
        public static List <VECTOR> Linearize(List <VECTOR> src, FLOAT md)
        {
            if (src == null)
            {
                throw new ArgumentNullException("src");
            }
            if (md <= VectorHelper.EPSILON)
            {
                throw new InvalidOperationException("md " + md + " is be less than epislon " + EPSILON);
            }
            List <VECTOR> dst = new List <VECTOR>();

            if (src.Count > 0)
            {
                VECTOR pp = src[0];
                dst.Add(pp);
                FLOAT cd = 0;
                for (int ip = 1; ip < src.Count; ip++)
                {
                    VECTOR p0 = src[ip - 1];
                    VECTOR p1 = src[ip];
                    FLOAT  td = VectorHelper.Distance(p0, p1);
                    if (cd + td > md)
                    {
                        FLOAT pd = md - cd;
                        dst.Add(VectorHelper.Lerp(p0, p1, pd / td));
                        FLOAT rd = td - pd;
                        while (rd > md)
                        {
                            rd -= md;
                            VECTOR np = VectorHelper.Lerp(p0, p1, (td - rd) / td);
                            if (!VectorHelper.EqualsOrClose(np, pp))
                            {
                                dst.Add(np);
                                pp = np;
                            }
                        }
                        cd = rd;
                    }
                    else
                    {
                        cd += td;
                    }
                }
                // last point
                VECTOR lp = src[src.Count - 1];
                if (!VectorHelper.EqualsOrClose(pp, lp))
                {
                    dst.Add(lp);
                }
            }
            return(dst);
        }
Esempio n. 2
0
 /// <summary>
 /// Adds a curve to the end of the spline.
 /// </summary>
 public void Add(CubicBezier curve)
 {
     if (_curves.Count > 0 && !VectorHelper.EqualsOrClose(_curves[_curves.Count - 1].p3, curve.p0))
     {
         throw new InvalidOperationException("The new curve does at index " + _curves.Count + " does not connect with the previous curve at index " + (_curves.Count - 1));
     }
     _curves.Add(curve);
     for (int i = 0; i < _samplesPerCurve; i++) // expand the array since updateArcLengths expects these values to be there
     {
         _arclen.Add(0);
     }
     UpdateArcLengths(_curves.Count - 1);
 }
        /// <summary>
        /// Removes any repeated points (that is, one point extremely close to the previous one). The same point can
        /// appear multiple times just not right after one another. This does not modify the input list. If no repeats
        /// were found, it returns the input list; otherwise it creates a new list with the repeats removed.
        /// </summary>
        /// <param name="pts">Initial list of points.</param>
        /// <returns>Either pts (if no duplicates were found), or a new list containing pts with duplicates removed.</returns>
        public static List <VECTOR> RemoveDuplicates(List <VECTOR> pts)
        {
            if (pts.Count < 2)
            {
                return(pts);
            }

            // Common case -- no duplicates, so just return the source list
            VECTOR prev = pts[0];
            int    len  = pts.Count;
            int    nDup = 0;

            for (int i = 1; i < len; i++)
            {
                VECTOR cur = pts[i];
                if (VectorHelper.EqualsOrClose(prev, cur))
                {
                    nDup++;
                }
                else
                {
                    prev = cur;
                }
            }

            if (nDup == 0)
            {
                return(pts);
            }
            else
            {
                // Create a copy without them
                List <VECTOR> dst = new List <VECTOR>(len - nDup);
                prev = pts[0];
                dst.Add(prev);
                for (int i = 1; i < len; i++)
                {
                    VECTOR cur = pts[i];
                    if (!VectorHelper.EqualsOrClose(prev, cur))
                    {
                        dst.Add(cur);
                        prev = cur;
                    }
                }
                return(dst);
            }
        }
Esempio n. 4
0
 /// <summary>
 /// Modifies a curve in the spline. It must connect with the previous and next curves (if applicable). This requires that the
 /// arc length table be recalculated for that curve and all curves after it -- for example, if you update the first curve in the
 /// spline, each curve after that would need to be recalculated (could avoid this by caching the lengths on a per-curve basis if you're
 /// doing this often, but since the typical case is only updating the last curve, and the entire array needs to be visited anyway, it
 /// wouldn't save much).
 /// </summary>
 /// <param name="index">Index of the curve to update in <see cref="Curves"/>.</param>
 /// <param name="curve">The new curve with which to replace it.</param>
 public void Update(int index, CubicBezier curve)
 {
     if (index < 0)
     {
         throw new IndexOutOfRangeException("Negative index");
     }
     if (index >= _curves.Count)
     {
         throw new IndexOutOfRangeException("Curve index " + index + " is out of range (there are " + _curves.Count + " curves in the spline)");
     }
     if (index > 0 && !VectorHelper.EqualsOrClose(_curves[index - 1].p3, curve.p0))
     {
         throw new InvalidOperationException("The updated curve at index " + index + " does not connect with the previous curve at index " + (index - 1));
     }
     if (index < _curves.Count - 1 && !VectorHelper.EqualsOrClose(_curves[index + 1].p0, curve.p3))
     {
         throw new InvalidOperationException("The updated curve at index " + index + " does not connect with the next curve at index " + (index + 1));
     }
     _curves[index] = curve;
     for (int i = index; i < _curves.Count; i++)
     {
         UpdateArcLengths(i);
     }
 }