/// <summary> /// Performs a quick benchmark on some sample data. /// </summary> static void QuickBench() { var test = new V3D[] { new V3D(-21298.4, 0.2, 2627.51), new V3D(-11.3359, 0.0, 0.0), new V3D(11.2637, 0.0, -1.28198), new V3D(-21332.3, 0.2, 2629.43) }; var testCurve = new Bezier3(test[0], test[0] + test[1], test[2] + test[3], test[3]); double l0 = 0, l1 = 0, l2 = 0; int s0 = 0, s1 = 0, s2 = 0; TimeSpan t = new TimeSpan(0, 0, 3); s0 = Benchmark(() => { l0 = testCurve.InterpolatedLength; }, t, "line interpolation"); s1 = Benchmark(() => { l1 = testCurve.Length; }, t, "adaptive quadratic interpolation"); s2 = Benchmark(() => { l2 = testCurve.QLength; }, t, "midpoint quadratic interpolation"); Console.WriteLine(String.Format( "\r\n\t\tLine int.:\t| Adaptive:\t| Midpoint:\r\n" + " Result[m]:\t{0}\t| {1}\t| {2}\r\n" + "Speed[op/s]:\t{3}\t\t| {4}\t| {5}", Math.Round(l0, 9), Math.Round(l1, 9), Math.Round(l2, 9), s0, s1, s2 )); Console.ReadKey(true); }
/// <summary> /// Splits the curve at given position (t : 0..1). /// </summary> /// <param name="t">A number from 0 to 1.</param> /// <returns>Two curves.</returns> /// <remarks> /// (De Casteljau's algorithm, see: http://caffeineowl.com/graphics/2d/vectorial/bezierintro.html) /// </remarks> public Bezier3[] SplitAt(double t) { V3D a = V3D.Interpolate(A, B, t); V3D b = V3D.Interpolate(B, C, t); V3D c = V3D.Interpolate(C, D, t); V3D m = V3D.Interpolate(a, b, t); V3D n = V3D.Interpolate(b, c, t); V3D p = P(t); return(new[] { new Bezier3(A, a, m, p), new Bezier3(p, n, c, D) }); }
/// <summary> /// Creates a cubic Bézier curve. /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <param name="c"></param> /// <param name="d"></param> public Bezier3(V3D a, V3D b, V3D c, V3D d) { A = a; B = b; C = c; D = d; }
/// <summary> /// Creates a quadratic Bézier curve. /// </summary> /// <param name="a">Start point.</param> /// <param name="b">Control point.</param> /// <param name="c">End point.</param> public Bezier2(V3D a, V3D b, V3D c) { A = a; B = b; C = c; }
/// <summary> /// Returns the vector between a and b that divides vector (a - b) in t ratio. For zero it's a, for 1 it's b. /// </summary> /// <param name="a">Vector a.</param> /// <param name="b">Vector b.</param> /// <param name="t">A number between 0 and 1.</param> /// <returns>the vector between a and b that divides vector (a - b) in t ratio. For zero it's a, for 1 it's b.</returns> public static V3D Interpolate(V3D a, V3D b, double t) => new V3D(a.X * (1.0 - t) + b.X * t, a.Y * (1.0 - t) + b.Y * t, a.Z * (1.0 - t) + b.Z * t);
/// <summary> /// Returns cross product. /// </summary> /// <param name="a">A vector.</param> /// <returns>Cross product.</returns> public V3D Cross(V3D a) => new V3D(Y * a.Z - Z * a.Y, Z * a.X - X * a.Z, X * a.Y - Y * a.X);
/// <summary> /// Returns dot product. /// </summary> /// <param name="a">A vector.</param> /// <returns>Dot product.</returns> public double Dot(V3D a) => X * a.X + Y * a.Y + Z * a.Z;