Implements a least-squares bezier curve fitting routine based on http://tog.acm.org/resources/GraphicsGems/gems/FitCurves.c with a few optimizations made by me. You can read the article here: http://read.pudn.com/downloads141/ebook/610086/Graphics_Gems_I.pdf page 626. To use, call the Fit static function and wait for magic to happen.
Inheritance: CurveFitBase
Exemple #1
0
        public static CubicBezier[] Fit(List <VECTOR> points, FLOAT maxError, ref List <VECTOR> pts, ref List <FLOAT> arclen)
        {
            if (maxError < EPSILON)
            {
                throw new InvalidOperationException("maxError cannot be negative/zero/less than epsilon value");
            }
            if (points == null)
            {
                throw new ArgumentNullException("points");
            }
            if (points.Count < 2)
            {
                pts    = new List <VECTOR>();
                arclen = new List <FLOAT>();
                return(NO_CURVES); // need at least 2 points to do anything
            }

            CurveFit instance = GetInstance();

            try
            {
                // should be cleared after each run
                Debug.Assert(instance._pts.Count == 0 && instance._result.Count == 0 &&
                             instance._u.Count == 0 && instance._arclen.Count == 0);

                // initialize arrays
                instance._pts.AddRange(points);
                instance.InitializeArcLengths(ref pts, ref arclen);
                instance._squaredError = maxError * maxError;

                // Find tangents at ends
                int    last = points.Count - 1;
                VECTOR tanL = instance.GetLeftTangent(last);
                VECTOR tanR = instance.GetRightTangent(0);

                // do the actual fit
                instance.FitRecursive(0, last, tanL, tanR);
                return(instance._result.ToArray());
            }
            finally
            {
                instance._pts.Clear();
                instance._result.Clear();
                instance._arclen.Clear();
                instance._u.Clear();
            }
        }
Exemple #2
0
        // Update is called once per frame
        void Update()
        {
            Transform[] trans = GetComponentsInChildren <Transform>();
            cubes.Clear();
            for (int i = 0; i < trans.Length; i++)
            {
                if (trans[i].gameObject.GetComponent <MeshRenderer>() != null)
                {
                    cubes.Add(trans[i].transform.position);
                }
            }
            // List<Vector3> reduced =  CurvePreprocess.RdpReduce(cubes, 30f);   // use the Ramer-Douglas-Pueker algorithm to remove unnecessary points
            List <float>   arcL = new List <float>();
            List <Vector3> pts  = new List <Vector3>();

            curves.Clear();
            curves.AddRange(CurveFit.Fit(cubes, error, ref pts, ref arcL));
            Debug.Log(curves.Count);
            if (cpt.Count < curves.Count)
            {
                for (int i = cpt.Count; i < curves.Count; i++)
                {
                    cpt.Add(Instantiate(controlPointObj));
                }
            }
            else if (cpt.Count > curves.Count)
            {
                for (int i = cpt.Count - 1; i >= curves.Count; i--)
                {
                    Destroy(cpt[i]);
                    cpt.RemoveAt(i);
                }
            }
            for (int i = 0; i < curves.Count; i++)
            {
                DrawCurve(100, curves[i], i);
            }
        }
Exemple #3
0
 private static CurveFit GetInstance()
 {
     return(_instance ?? (_instance = new CurveFit()));
 }
Exemple #4
0
 private static CurveFit GetInstance()
 {
     return _instance ?? (_instance = new CurveFit());
 }