// Generate the control points, weights, and knots of a surface defined by 4 points // // **params** // + first point in counter-clockwise form // + second point in counter-clockwise form // + third point in counter-clockwise form // + forth point in counter-clockwise form // // **returns** // + NurbsSurfaceData object func FourPointSurface(p1, p2, p3, p4 *vec3.T, _degree *int) *verb.NurbsSurface { var degree int if _degree == nil { degree = 3 } else { degree = *_degree } degreeFloat := float64(degree) pts := make([][]vec3.T, degree+1) for i := range pts { iFloat := float64(i) row := make([]vec3.T, degree+1) for j := range row { l := 1 - iFloat/degreeFloat p1p2 := vec3.Interpolate(p1, p2, l) p4p3 := vec3.Interpolate(p4, p3, l) row[j] = vec3.Interpolate(&p1p2, &p4p3, 1-float64(j)/degreeFloat) } pts[i] = row } // build uniform weights weightRow := make([]float64, degree+1) for i := range weightRow { weightRow[i] = 1 } weights := make([][]float64, degree+1) for i := range weights { weights[i] = weightRow } knots := make([]float64, 2*(degree+1)) for i := degree + 1; i < len(knots); i++ { knots[i] = 1 } return verb.NewNurbsSurfaceUnchecked(degree, degree, pts, weights, knots, knots) }
func HomoInterpolated(hpt0, hpt1 *HomoPoint, t float64) HomoPoint { return HomoPoint{ vec3.Interpolate(&hpt0.Vec3, &hpt1.Vec3, t), (1-t)*hpt0.W + t*hpt1.W, } }
// Insert a collection of knots on a curve // // Corresponds to Algorithm A5.4 (Piegl & Tiller) // // **params** // + NurbsCurveData object representing the curve // + array of knots to insert // // **returns** // + NurbsCurveData object representing the curve // func (this *NurbsCurve) knotRefine(knotsToInsert KnotVec) *NurbsCurve { if len(knotsToInsert) == 0 { return this.clone() } degree := this.degree controlPoints := this.controlPoints knots := this.knots n := len(controlPoints) - 1 m := n + degree + 1 r := len(knotsToInsert) - 1 a := knots.Span(degree, knotsToInsert[0]) b := knots.Span(degree, knotsToInsert[r]) // TODO can we use slices instead of maps? controlPointsPost := make(map[int]HomoPoint) knotsPost := make(map[int]float64) // new control pts for i := 0; i <= a-degree; i++ { controlPointsPost[i] = controlPoints[i] } for i := b - 1; i <= n; i++ { controlPointsPost[i+r+1] = controlPoints[i] } // new knot vector for i := 0; i <= a; i++ { knotsPost[i] = knots[i] } for i := b + degree; i <= m; i++ { knotsPost[i+r+1] = knots[i] } i := b + degree - 1 k := b + degree + r j := r for j >= 0 { for knotsToInsert[j] <= knots[i] && i > a { controlPointsPost[k-degree-1] = controlPoints[i-degree-1] knotsPost[k] = knots[i] k = k - 1 i = i - 1 } controlPointsPost[k-degree-1] = controlPointsPost[k-degree] for l := 1; l <= degree; l++ { ind := k - degree + l alfa := knotsPost[k+l] - knotsToInsert[j] if math.Abs(alfa) < Epsilon { controlPointsPost[ind-1] = controlPointsPost[ind] } else { alfa /= knotsPost[k+l] - knots[i-degree+l] oldP, newP := controlPointsPost[ind], controlPointsPost[ind-1] controlPointsPost[ind-1] = HomoPoint{ vec3.Interpolate(&oldP.Vec3, &newP.Vec3, alfa), controlPointsPost[ind-1].W, } } } knotsPost[k] = knotsToInsert[j] k = k - 1 j-- } var maxCptsI int for i := range controlPointsPost { if i > maxCptsI { maxCptsI = i } } finalCpts := make([]HomoPoint, maxCptsI+1) for i, cpt := range controlPointsPost { finalCpts[i] = cpt } var maxKnotsI int for i := range knotsPost { if i > maxKnotsI { maxKnotsI = i } } finalKnots := make(KnotVec, maxKnotsI+1) for i, knot := range knotsPost { finalKnots[i] = knot } return &NurbsCurve{degree, finalCpts, finalKnots} }