Beispiel #1
0
// 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)
}
Beispiel #2
0
func HomoInterpolated(hpt0, hpt1 *HomoPoint, t float64) HomoPoint {
	return HomoPoint{
		vec3.Interpolate(&hpt0.Vec3, &hpt1.Vec3, t),
		(1-t)*hpt0.W + t*hpt1.W,
	}
}
Beispiel #3
0
// 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}
}