/// <summary> /// Computes the maximum squared distance from a point to the curve using the current parameterization. /// </summary> protected FLOAT FindMaxSquaredError(int first, int last, CubicBezier curve, out int split) { List <VECTOR> pts = _pts; List <FLOAT> u = _u; int s = (last - first + 1) / 2; int nPts = last - first + 1; FLOAT max = 0; for (int i = 1; i < nPts; i++) { VECTOR v0 = pts[first + i]; VECTOR v1 = curve.Sample(u[i]); FLOAT d = VectorHelper.DistanceSquared(v0, v1); if (d > max) { max = d; s = i; } } // split at point of maximum error split = s + first; if (split <= first) { split = first + 1; } if (split >= last) { split = last - 1; } return(max); }
/// <summary> /// Attempts to find a slightly better parameterization for u on the given curve. /// </summary> protected void Reparameterize(int first, int last, CubicBezier curve) { List <VECTOR> pts = _pts; List <FLOAT> u = _u; int nPts = last - first; for (int i = 1; i < nPts; i++) { VECTOR p = pts[first + i]; FLOAT t = u[i]; FLOAT ti = 1 - t; // Control vertices for Q' VECTOR qp0 = (curve.p1 - curve.p0) * 3; VECTOR qp1 = (curve.p2 - curve.p1) * 3; VECTOR qp2 = (curve.p3 - curve.p2) * 3; // Control vertices for Q'' VECTOR qpp0 = (qp1 - qp0) * 2; VECTOR qpp1 = (qp2 - qp1) * 2; // Evaluate Q(t), Q'(t), and Q''(t) VECTOR p0 = curve.Sample(t); VECTOR p1 = ((ti * ti) * qp0) + ((2 * ti * t) * qp1) + ((t * t) * qp2); VECTOR p2 = (ti * qpp0) + (t * qpp1); // these are the actual fitting calculations using http://en.wikipedia.org/wiki/Newton%27s_method // We can't just use .X and .Y because Unity uses lower-case "x" and "y". FLOAT num = ((VectorHelper.GetX(p0) - VectorHelper.GetX(p)) * VectorHelper.GetX(p1)) + ((VectorHelper.GetY(p0) - VectorHelper.GetY(p)) * VectorHelper.GetY(p1)); FLOAT den = (VectorHelper.GetX(p1) * VectorHelper.GetX(p1)) + (VectorHelper.GetY(p1) * VectorHelper.GetY(p1)) + ((VectorHelper.GetX(p0) - VectorHelper.GetX(p)) * VectorHelper.GetX(p2)) + ((VectorHelper.GetY(p0) - VectorHelper.GetY(p)) * VectorHelper.GetY(p2)); FLOAT newU = t - num / den; if (Math.Abs(den) > EPSILON && newU >= 0 && newU <= 1) { u[i] = newU; } } }
void DrawCurve(int c_numSamples, burningmime.curves.CubicBezier bezier, int index) { List <Vector3> drawpoint = new List <Vector3>(); for (int i = 0; i < c_numSamples; ++i) { float percent = ((float)i) / (c_numSamples - 1); Vector3 drawpts = new Vector3(); //drawpts = Hermitefunc(A, B, C, D, t); drawpts = bezier.Sample(percent); drawpoint.Add(drawpts); pts.Add(drawpts); dpts.Add(bezier.Tangent(percent)); if (arcLen.Count == 0) { arcLen.Add(0); } else { arcLen.Add(arcLen[arcLen.Count - 1] + Vector3.Distance(pts[pts.Count - 1], pts[pts.Count - 2])); } } LineRenderer lineRenderer; if (line[index].GetComponent <LineRenderer>() == null) { line[index].AddComponent <LineRenderer>(); } lineRenderer = line[index].GetComponent <LineRenderer>(); lineRenderer.material = new Material(Shader.Find("Standard")); lineRenderer.sharedMaterial.SetColor("_Color", Color.red); lineRenderer.positionCount = drawpoint.Count; lineRenderer.SetPositions(drawpoint.ToArray()); }
void DrawCurve(int c_numSamples, CubicBezier bezier, int index) { List <Vector3> drawpoint = new List <Vector3>(); for (int i = 0; i < c_numSamples; ++i) { float percent = ((float)i) / (c_numSamples - 1); Vector3 drawpts = new Vector3(); //drawpts = Hermitefunc(A, B, C, D, t); drawpts = bezier.Sample(percent); drawpoint.Add(drawpts); } LineRenderer lineRenderer; if (cpt[index].GetComponent <LineRenderer>() == null) { cpt[index].AddComponent <LineRenderer>(); } lineRenderer = cpt[index].GetComponent <LineRenderer>(); lineRenderer.material = new Material(Shader.Find("Standard")); lineRenderer.sharedMaterial.SetColor("_Color", Color.red); lineRenderer.positionCount = drawpoint.Count; lineRenderer.SetPositions(drawpoint.ToArray()); }
/// <summary> /// Updates the internal arc length array for a curve. Expects the list to contain enough elements. /// </summary> private void UpdateArcLengths(int iCurve) { CubicBezier curve = _curves[iCurve]; int nSamples = _samplesPerCurve; List <FLOAT> arclen = _arclen; FLOAT clen = iCurve > 0 ? arclen[iCurve * nSamples - 1] : 0; VECTOR pp = curve.p0; Debug.Assert(arclen.Count >= ((iCurve + 1) * nSamples)); for (int iPoint = 0; iPoint < nSamples; iPoint++) { int idx = (iCurve * nSamples) + iPoint; FLOAT t = (iPoint + 1) / (FLOAT)nSamples; VECTOR np = curve.Sample(t); FLOAT d = VectorHelper.Distance(np, pp); clen += d; arclen[idx] = clen; pp = np; } }