Cubic NURBS by de Boor's Method

Cubic NURBS by de Boor's Method
Loading the math board and drawing, please wait…
2020-01-01 22:24
① This example demonstrates the construction of a cubic Non-Uniform Rational B-Spline (NURBS) curve using de Boor's recursive algorithm, showing the curve along with its control points and weights. ② Core mathematical concepts include NURBS curves, B-spline basis functions, de Boor's algorithm, control points and weights, and parametric curves. ③ Construction highlights: from the summary, GeoGebra commands such as Join, Sequence, Element, Min, PolyLine, Zip, Translate, If, Segment, and Text are used; multiple control points P0 to P9 and corresponding weights w0 to w9 are defined, along with parameter t0 and intermediate points d1 to d10, to recursively generate points on the curve and finally draw the cubic NURBS. ④ Suitable for university-level courses in computer-aided geometric design, numerical analysis, or mathematical modeling, and also for advanced high school students exploring parametric curves and spline concepts.

GeoGebra Commands & Parameters

  1. First({P_{0}, P_{1}, P_{2}, P_{3}, P_{4}, P_{5}, P_{6}, P_{7}, P_{8}, P_{9}}, n + 1) → P
  2. First({w_{0}, w_{1}, w_{2}, w_{3}, w_{4}, w_{5}, w_{6}, w_{7}, w_{8}, w_{9}}, n + 1) → weights
  3. First({d_{1}, d_{2}, d_{3}, d_{4}, d_{5}, d_{6}, d_{7}, d_{8}, d_{9}, d_{10}, d_{11}, d_{12}, d_{13}, d_{14}, d_{15}}, m) → Δknots_{input}
  4. Join({Sequence[0, j, 1, k - 1], If[Sum[Take[Δknots_{input}, k, m + 1 - k]] > 0, Take[Δknots_{input}, k, m + 1 - k], Join[{If[m - k ≥ k, Take[Δknots_{input}, k, m - k], {}], {1}}]], Sequence[0, j, 1, k - 1]}) → Δknots_{tidyends}
  5. Sequence(Sum[First[Join[{{t_{0}}, Δknots_{tidyends}}], i]], i, 1, 1 + m) → knots
  6. Element(knots, 1) → knot_0
  7. Element(knots, 1 + m) → knot_m
  8. Sequence(Dilate[Element[P, 1 + i], Element[weights, 1 + i], Azathoth], i, 0, n) → P_w
  9. Sequence(KDpos + KDioffset + (0, (i * KDiystep_i) + ((tri(k) - tri(k - i) - i) * KDiystep_j)), i, 0, k - 1) → KDibases
  10. Sequence(KDpos + KDuoffset + (0, KDublossomheight + (i * KDuystep_i) + ((tri(k) - tri(k - i) - i) * KDuystep_j)), i, 0, k - 1) → KDubases
  11. Min(m - k, Length[KeepIf[x ≤ u, knots]] - 1) → Ki_u
  12. Sequence(Sequence[(u - Element[knots, 1 + Ki_0 + i + j]) / (Element[knots, 1 + Ki_0 + j + k] - Element[knots, 1 + Ki_0 + i + j]), j, 0, k - 1 - i], i, 0, k - 1) → Kublossom
  13. Sequence(Sequence[KDirulerbase + ((KDiscale * i), (KDirulerticklength * j)), j, 0, 1], i, k - 1, m + 1 - k) → KDirulervertices
  14. PolyLine(Zip[Element[Element[KDirulervertices, Element[a, 1]], Element[a, 2]], a, {{1, 2}, {1, 1}, {Length[KDirulervertices], 1}, {Length[KDirulervertices], 2}}]) → KDirulermain
  15. Zip(Segment[Element[a, 1], Element[a, 2]], a, Sequence[Element[KDirulervertices, i], i, 2, Length[KDirulervertices] - 1]) → KDirulerinnerticks
  16. Sequence(Sequence[Element[KDibases, 1 + i] + ((KDiscale * (Ki_0 + i + j)), (KDiystep_j * j)), j, 0, k - 1 - i], i, 0, k - 1) → KDi_a
  17. Sequence(Sequence[Element[KDibases, 1 + i] + ((KDiscale * (Ki_0 + j + k)), (KDiystep_j * j)), j, 0, k - 1 - i], i, 0, k - 1) → KDi_b
  18. Zip(Zip[Segment[aj, bj], aj, ai, bj, bi], ai, KDi_a, bi, KDi_b) → KDis_{ab}
  19. Sequence(Translate[PolyLine[KDuoffset + ((KDiuscale * (Element[knots, 1 + i] - knot_0)), KDublossomheight + KDtticklength), KDuoffset + ((KDiuscale * (Element[knots, 1 + i] - knot_0)), (-KDtticklength)), KDaoffset + ((KDiscale * i), KDaheight + (KDiufantickheight * KDiufanheight)), KDaoffset + ((KDiscale * i), KDaheight)], KDpos], i, 0, m) → KDiufan
  20. Sequence(Sequence[Element[KDubases, 1 + i] + ((KDiuscale * (Element[knots, 1 + Ki_0 + i + j] - knot_0)), (KDuystep_j * j)), j, 0, k - 1 - i], i, 0, k - 1) → KDu_a
  21. Sequence(Sequence[Element[KDubases, 1 + i] + ((KDiuscale * (Element[knots, 1 + Ki_0 + j + k] - knot_0)), (KDuystep_j * j)), j, 0, k - 1 - i], i, 0, k - 1) → KDu_b
  22. PolyLine(KDpos + KDaoffset + ((-0.5 * KDiscale), 0) + {(0, 0), (0, KDaheight), (((m + 1) * KDiscale), KDaheight), (((m + 1) * KDiscale), 0), (0, 0)}) → KDabox
  23. Zip(Segment[a, a + (0, KDaheight)], a, Sequence[KDpos + KDaoffset + ((KDiscale * (i + 0.5)), 0), i, 0, m - 1]) → KDaboxdividers
  24. Sequence(Text[Element[knots, 1 + i], KDpos + KDaoffset + (-0.15, (0.35 * KDaheight)) + ((KDiscale * i), 0)], i, 0, m) → KDatext
  25. Translate(PolyLine[KDuoffset + ((KDiuscale * (u - knot_0)), KDublossomheight + KDuticklength), KDuoffset + ((KDiuscale * (u - knot_0)), (-KDtticklength)), KDaoffset + ((KDiscale * (Ki_u + Element[Element[Kublossom, Length[Kublossom]], 1])), KDaheight + (KDiufantickheight * KDiufanheight)), KDaoffset + ((KDiscale * (Ki_u + Element[Element[Kublossom, Length[Kublossom]], 1])), KDaheight + ((0.1 * KDiufantickheight) * KDiufanheight))], KDpos) → KDucrank
  26. Sequence(Segment[Element[P, 1 + i], Element[P_w, 1 + i]], i, 0, n) → wlines
  27. PolyLine(P) → cp
  28. PolyLine(P_w) → cp_{w,full}
  29. Zip(Segment[Element[P_w, 1 + a], Element[P_w, 1 + a + 1]], a, KeepIf[x ≥ 0, Sequence[If[Sum[abs(Take[weights - 1, 1 + i, 1 + i + 1])] > 0, i, -1], i, 0, n - 1]]) → cp_{w,selective}
  30. Zip(Zip[aj + ((bj - aj) * uj), aj, ai, bj, bi, uj, ui], ai, KDi_a, bi, KDi_b, ui, Kublossom) → KDi_m
  31. Zip(Zip[aj + ((bj - aj) * uj), aj, ai, bj, bi, uj, ui], ai, KDu_a, bi, KDu_b, ui, Kublossom) → KDu_m
  32. Zip(Zip[Segment[aj, bj], aj, ai, bj, bi], ai, KDu_a, bi, KDu_m) → KDus_{am}
  33. Zip(Zip[Segment[aj, bj], aj, ai, bj, bi], ai, KDu_b, bi, KDu_m) → KDus_{bm}
  34. First(KDu_m, k) → KDu_{m,sansfinal}
  35. Element(KDu_m, k) → KDu_{m,final}
  36. Sequence({x(Element[P_w, 1 + Ki_0 + j]), y(Element[P_w, 1 + Ki_0 + j]), Element[weights, 1 + Ki_0 + j]}, j, 0, k) → Lerp_{h,0}
  37. Sequence(Element[Lerp_{h,0}, 1 + j] + ((Element[Lerp_{h,0}, 1 + j + 1] - Element[Lerp_{h,0}, 1 + j]) * Element[Element[Kublossom, 1], 1 + j]), j, 0, k - 1) → Lerp_{h,1}
  38. Sequence(Element[Lerp_{h,1}, 1 + j] + ((Element[Lerp_{h,1}, 1 + j + 1] - Element[Lerp_{h,1}, 1 + j]) * Element[Element[Kublossom, 2], 1 + j]), j, 0, k - 2) → Lerp_{h,2}
  39. Sequence(Element[Lerp_{h,2}, 1 + j] + ((Element[Lerp_{h,2}, 1 + j + 1] - Element[Lerp_{h,2}, 1 + j]) * Element[Element[Kublossom, 3], 1 + j]), j, 0, k - 3) → Lerp_{h,3}
  40. Sequence(Element[Lerp_{h,3}, 1 + j] + ((Element[Lerp_{h,3}, 1 + j + 1] - Element[Lerp_{h,3}, 1 + j]) * Element[Element[Kublossom, 4], 1 + j]), j, 0, k - 4) → Lerp_{h,4}
  41. Sequence(Element[Lerp_{h,4}, 1 + j] + ((Element[Lerp_{h,4}, 1 + j + 1] - Element[Lerp_{h,4}, 1 + j]) * Element[Element[Kublossom, 5], 1 + j]), j, 0, k - 5) → Lerp_{h,5}
  42. Sequence(Element[Lerp_{h,5}, 1 + j] + ((Element[Lerp_{h,5}, 1 + j + 1] - Element[Lerp_{h,5}, 1 + j]) * Element[Element[Kublossom, 6], 1 + j]), j, 0, k - 6) → Lerp_{h,6}
  43. Sequence(Element[Lerp_{h,6}, 1 + j] + ((Element[Lerp_{h,6}, 1 + j + 1] - Element[Lerp_{h,6}, 1 + j]) * Element[Element[Kublossom, 7], 1 + j]), j, 0, k - 7) → Lerp_{h,7}
  44. First({Lerp_{h,0}, Lerp_{h,1}, Lerp_{h,2}, Lerp_{h,3}, Lerp_{h,4}, Lerp_{h,5}, Lerp_{h,6}, Lerp_{h,7}}, k + 1) → Blossom_h
  45. Sequence(PointList[Sequence[First[Element[Element[Blossom_h, 1 + i], 1 + j], 2], j, 0, k - i]], i, 0, k) → Lerp_w
  46. First(Lerp_w, k) → Lerp_{w,sansfinal}
  47. Sequence(Sequence[Segment[Element[Element[Lerp_w, 1 + i], 1 + j], Element[Element[Lerp_w, 1 + i + 1], 1 + j]], j, 0, k - 1 - i], i, 0, k - 1) → Lerpspan_{am}
  48. Sequence(Sequence[Segment[Element[Element[Lerp_w, 1 + i], 1 + j + 1], Element[Element[Lerp_w, 1 + i + 1], 1 + j]], j, 0, k - 1 - i], i, 0, k - 1) → Lerpspan_{bm}
  49. Element(Element[Blossom_h, 1 + k], 1) → C_h
  50. If(Element[C_h, 3] ≠ 0, Dilate[C_w, 1 / Element[C_h, 3], Azathoth], C_w) → C
  51. Segment(Azathoth, If[Element[C_h, 3] ≤ 1, C, C_w]) → Cwline
  52. Text("Spans", (1.05, -5.38)) → SpansText
  53. Text("Degree", (1.05, -4.38)) → DegreeText
  54. Text("Weights", (1.05, -6.5 - (0.5 * n_{max}) - 0.38)) → WeightsText
  55. Text("First knot and adjustable knot differences", (3.95, -11.38)) → KnotSpansText
  56. Text("The curve is discontinuous.", (9.56, -11.38)) → DiscontinuityWarning
  57. Text("A non-monotonic knot vector is invalid.", (13.25, -11.38)) → NonmonotonicityWarning

AI Drawing Prompt Reference

Draw a cubic non-uniform rational B-spline curve defined by 10 control points, each with a corresponding weight. First, define 10 control points P0 to P9 and their weights w0 to w9, then use de Boor's recursive algorithm to generate points on the curve, and finally draw the curve along with its control points and weights.
The prompt above was compiled from the original drawing commands and is for reference only.