// Compute the derivatives at a point on a NURBS surface // // **params** // + NurbsSurfaceData object representing the surface // + number of derivatives to evaluate // + u parameter at which to evaluate the derivatives // + v parameter at which to evaluate the derivatives // // **returns** // + a point represented by an array of length (dim) func (this *NurbsSurface) Derivatives(uv UV, numDerivs int) [][]vec3.T { ders := this.nonRationalDerivatives(uv, numDerivs) wders := Weight2d(ders) skl := make([][]vec3.T, numDerivs+1) for k := 0; k <= numDerivs; k++ { for l := 0; l <= numDerivs-k; l++ { v := ders[k][l].Vec3 for j := 1; j <= l; j++ { scaled := skl[k][l-j].Scaled(binomial(l, j) * wders[0][j]) v.Sub(&scaled) } for i := 1; i <= k; i++ { scaled := skl[k-i][l].Scaled(binomial(k, i) * wders[i][0]) v.Sub(&scaled) var v2 vec3.T for j := 1; j <= l; j++ { scaled := skl[k-i][l-j].Scaled(binomial(l, j) * wders[i][j]) v2.Add(&scaled) } scaled = v2.Scaled(binomial(k, i)) v.Sub(&scaled) } v.Scale(1 / wders[0][0]) skl[k][l] = v } } return skl }
// // Compute a point in a non-uniform, non-rational B spline volume // // **params** // + VolumeData // + u parameter at which to evaluate the volume point // + v parameter at which to evaluate the volume point // + w parameter at which to evaluate the volume point // // **returns** // + a point represented by an array of length (dim) func (this *volume) PointGivenNML(n, m, l int, uvw UVW) vec3.T { if !areValidRelations(this.DegreeU, len(this.ControlPoints), len(this.KnotsU)) || !areValidRelations(this.DegreeV, len(this.ControlPoints[0]), len(this.KnotsV)) || !areValidRelations(this.DegreeW, len(this.ControlPoints[0][0]), len(this.KnotsW)) { panic("Invalid relations between control points and knot vector") } controlPoints := this.ControlPoints degreeU, degreeV, degreeW := this.DegreeU, this.DegreeV, this.DegreeW knotsU, knotsV, knotsW := this.KnotsU, this.KnotsV, this.KnotsW knotSpanIndexU := knotsU.SpanGivenN(n, degreeU, uvw[0]) knotSpanIndexV := knotsV.SpanGivenN(m, degreeV, uvw[1]) knotSpanIndexW := knotsW.SpanGivenN(l, degreeW, uvw[2]) uBasisVals := BasisFunctionsGivenKnotSpanIndex(knotSpanIndexU, uvw[0], degreeU, knotsU) vBasisVals := BasisFunctionsGivenKnotSpanIndex(knotSpanIndexV, uvw[0], degreeV, knotsV) wBasisVals := BasisFunctionsGivenKnotSpanIndex(knotSpanIndexV, uvw[0], degreeW, knotsW) uind := knotSpanIndexU - degreeU var position, temp, temp2 vec3.T for i := 0; i <= degreeW; i++ { temp2 = vec3.Zero wind := knotSpanIndexW - degreeW + i for j := 0; j <= degreeV; j++ { temp = vec3.Zero vind := knotSpanIndexV - degreeV + j for k := 0; k <= degreeU; k++ { scaled := controlPoints[uind+k][vind][wind].Scaled(uBasisVals[k]) temp.Add(&scaled) } // add weighted contribution of u isoline scaled := temp.Scaled(vBasisVals[j]) temp2.Add(&scaled) } // add weighted contribution from uv isosurfaces scaled := temp2.Scaled(wBasisVals[i]) position.Add(&scaled) } return position }