Cubic NURBS by de Boor's Method
Loading the math board and drawing, please wait…
① 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
First({P_{0}, P_{1}, P_{2}, P_{3}, P_{4}, P_{5}, P_{6}, P_{7}, P_{8}, P_{9}}, n + 1) → PFirst({w_{0}, w_{1}, w_{2}, w_{3}, w_{4}, w_{5}, w_{6}, w_{7}, w_{8}, w_{9}}, n + 1) → weightsFirst({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}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}Sequence(Sum[First[Join[{{t_{0}}, Δknots_{tidyends}}], i]], i, 1, 1 + m) → knotsElement(knots, 1) → knot_0Element(knots, 1 + m) → knot_mSequence(Dilate[Element[P, 1 + i], Element[weights, 1 + i], Azathoth], i, 0, n) → P_wSequence(KDpos + KDioffset + (0, (i * KDiystep_i) + ((tri(k) - tri(k - i) - i) * KDiystep_j)), i, 0, k - 1) → KDibasesSequence(KDpos + KDuoffset + (0, KDublossomheight + (i * KDuystep_i) + ((tri(k) - tri(k - i) - i) * KDuystep_j)), i, 0, k - 1) → KDubasesMin(m - k, Length[KeepIf[x ≤ u, knots]] - 1) → Ki_uSequence(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) → KublossomSequence(Sequence[KDirulerbase + ((KDiscale * i), (KDirulerticklength * j)), j, 0, 1], i, k - 1, m + 1 - k) → KDirulerverticesPolyLine(Zip[Element[Element[KDirulervertices, Element[a, 1]], Element[a, 2]], a, {{1, 2}, {1, 1}, {Length[KDirulervertices], 1}, {Length[KDirulervertices], 2}}]) → KDirulermainZip(Segment[Element[a, 1], Element[a, 2]], a, Sequence[Element[KDirulervertices, i], i, 2, Length[KDirulervertices] - 1]) → KDirulerinnerticksSequence(Sequence[Element[KDibases, 1 + i] + ((KDiscale * (Ki_0 + i + j)), (KDiystep_j * j)), j, 0, k - 1 - i], i, 0, k - 1) → KDi_aSequence(Sequence[Element[KDibases, 1 + i] + ((KDiscale * (Ki_0 + j + k)), (KDiystep_j * j)), j, 0, k - 1 - i], i, 0, k - 1) → KDi_bZip(Zip[Segment[aj, bj], aj, ai, bj, bi], ai, KDi_a, bi, KDi_b) → KDis_{ab}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) → KDiufanSequence(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_aSequence(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_bPolyLine(KDpos + KDaoffset + ((-0.5 * KDiscale), 0) + {(0, 0), (0, KDaheight), (((m + 1) * KDiscale), KDaheight), (((m + 1) * KDiscale), 0), (0, 0)}) → KDaboxZip(Segment[a, a + (0, KDaheight)], a, Sequence[KDpos + KDaoffset + ((KDiscale * (i + 0.5)), 0), i, 0, m - 1]) → KDaboxdividersSequence(Text[Element[knots, 1 + i], KDpos + KDaoffset + (-0.15, (0.35 * KDaheight)) + ((KDiscale * i), 0)], i, 0, m) → KDatextTranslate(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) → KDucrankSequence(Segment[Element[P, 1 + i], Element[P_w, 1 + i]], i, 0, n) → wlinesPolyLine(P) → cpPolyLine(P_w) → cp_{w,full}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}Zip(Zip[aj + ((bj - aj) * uj), aj, ai, bj, bi, uj, ui], ai, KDi_a, bi, KDi_b, ui, Kublossom) → KDi_mZip(Zip[aj + ((bj - aj) * uj), aj, ai, bj, bi, uj, ui], ai, KDu_a, bi, KDu_b, ui, Kublossom) → KDu_mZip(Zip[Segment[aj, bj], aj, ai, bj, bi], ai, KDu_a, bi, KDu_m) → KDus_{am}Zip(Zip[Segment[aj, bj], aj, ai, bj, bi], ai, KDu_b, bi, KDu_m) → KDus_{bm}First(KDu_m, k) → KDu_{m,sansfinal}Element(KDu_m, k) → KDu_{m,final}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}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}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}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}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}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}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}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}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_hSequence(PointList[Sequence[First[Element[Element[Blossom_h, 1 + i], 1 + j], 2], j, 0, k - i]], i, 0, k) → Lerp_wFirst(Lerp_w, k) → Lerp_{w,sansfinal}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}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}Element(Element[Blossom_h, 1 + k], 1) → C_hIf(Element[C_h, 3] ≠ 0, Dilate[C_w, 1 / Element[C_h, 3], Azathoth], C_w) → CSegment(Azathoth, If[Element[C_h, 3] ≤ 1, C, C_w]) → CwlineText("Spans", (1.05, -5.38)) → SpansTextText("Degree", (1.05, -4.38)) → DegreeTextText("Weights", (1.05, -6.5 - (0.5 * n_{max}) - 0.38)) → WeightsTextText("First knot and adjustable knot differences", (3.95, -11.38)) → KnotSpansTextText("The curve is discontinuous.", (9.56, -11.38)) → DiscontinuityWarningText("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.