# Extracting control points from BezierFunction

given a Bézier surface, is there a simple way to express $g_{12}$ (from the First fundamental form) again in Bézier form?

More precisely, I have control points and a Bézier function $f$:

cps = {{{0, 0}, {.5, .36}, {1, 0}},
{{.4, .37}, {.6, .3}, {.6, .42}},
{{0, 1}, {.45, .46}, {1, 1}}};
f = BezierFunction[cps];


I can compute $g_{12}$

g12 = D[f[u, v], u].D[f[u, v], v];


Since $g_{12}$ is a polynomial in $u$ and $v$, there is surely a way to express it as a Bézier function. Can I get the corresponding control points in some easy way from this representation? Or do I have to teach Mathematica what are the control points of $\frac{\partial f}{\partial u}$, of $\frac{\partial f}{\partial v}$, and what to do with them to get my result?

The operation is surprisingly nontrivial, so I'm putting it out here for reference.

The idea is to work with explicit BernsteinBasis[] expansions and then do a few algebraic manipulations. To wit:

expr = Fold[Dot, #, {Table[BernsteinBasis[2, k, v], {k, 0, 2}],
Table[BernsteinBasis[2, k, u], {k, 0, 2}]}] & /@
Transpose[cps, {2, 3, 1}]


yields the explicit basis expansion. Now, compute the required derivative:

dd = D[expr, u].D[expr, v] // Expand;


A look at the (long!) explicit expression reveals that the function does not yet have the compatible basis functions being combined. We thus need to do a few replacements:

ddn = Chop[dd //.
Times[a_., BernsteinBasis[n1_, k1_, u_], c_., BernsteinBasis[n2_, k2_, u_]] :>
Times[a, c, Binomial[n1, k1], Binomial[n2, k2],
BernsteinBasis[n1 + n2, k1 + k2, u]]/Binomial[n1 + n2, k1 + k2]];


Now, the (messy!) control point extraction:

ccp = (Function[b, Coefficient[#, b]] /@ Table[BernsteinBasis[3, k, v], {k, 0, 3}]) & /@
(Coefficient[ddn, #] & /@ Table[BernsteinBasis[3, k, u], {k, 0, 3}])
{{1.3328, 0.1648, 0.125867, -1.4048},
{0.18, -0.122667, -0.0462222, 0.122667},
{-0.357333, 0.249333, -0.0915556, 0.194667},
{-2.0808, -0.250133, -0.1672, 2.1328}}


This can now be fed to BezierFunction[]:

nbf = BezierFunction[Map[List, ccp, {2}]];


Compare this with the usual derivative expression:

Plot3D[First[nbf[u, v]] - Derivative[1, 0][f][u, v].Derivative[0, 1][f][u, v],
{u, 0, 1}, {v, 0, 1}, PlotRange -> All]


and we see that the difference is on the order of roundoff.

• It's been over two weeks and I am still flabbergasted that someone took the effort of thoroughly answering such an old question. Thank you! However, I cannot accept it before trying it out and that will take some time, as I don't possess any Mathematica license at the moment. – Dominik Mokriš Oct 12 '18 at 19:53
• That is fine. ;) This seems to have been asked during one of my hiatuses, so I had missed it. – J. M.'s technical difficulties Oct 12 '18 at 20:35
• On Thursday I checked it on my friend's computer and it seems that you are right. Thanks again for the answer! – Dominik Mokriš Dec 12 '18 at 21:03