def evaluate_rational(self): """ Evaluates the NURBS curve. .. note:: The evaluated surface points are stored in :py:attr:`~curvepts`. :return: None """ # Check all parameters are set before the curve evaluation self._check_variables() # Clean up the curve points, if necessary self._reset_curve() # Algorithm A4.1 for u in utils.frange(0, 1, self._mDelta): span = utils.find_span(self._mDegree, tuple(self._mKnotVector), len(self._mCtrlPts), u) basis = utils.basis_functions(self._mDegree, tuple(self._mKnotVector), span, u) curveptw = [0.0, 0.0, 0.0] for i in range(0, self._mDegree + 1): curveptw[0] += (basis[i] * (self._mCtrlPts[span - self._mDegree + i][0] * self._mWeights[span - self._mDegree + i])) curveptw[1] += (basis[i] * (self._mCtrlPts[span - self._mDegree + i][1] * self._mWeights[span - self._mDegree + i])) curveptw[2] += (basis[i] * self._mWeights[span - self._mDegree + i]) # Divide by weight curvept = [ float(curveptw[0] / curveptw[2]), float(curveptw[1] / curveptw[2]) ] self._mCurvePts.append(curvept)
def evaluate(self): """ Evaluates the B-Spline curve. .. note:: The evaluated surface points are stored in :py:attr:`~curvepts`. :return: None """ # Check all parameters are set before the curve evaluation self._check_variables() # Clean up the curve points, if necessary self._reset_curve() # Algorithm A3.1 for u in utils.frange(0, 1, self._mDelta): span = utils.find_span(self._mDegree, tuple(self._mKnotVector), len(self._mCtrlPts), u) basis = utils.basis_functions(self._mDegree, tuple(self._mKnotVector), span, u) curvept = [0.0, 0.0] for i in range(0, self._mDegree + 1): curvept[0] += (basis[i] * self._mCtrlPts[span - self._mDegree + i][0]) curvept[1] += (basis[i] * self._mCtrlPts[span - self._mDegree + i][1]) self._mCurvePts.append(curvept)
def evaluate(self): """ Evaluates the B-Spline surface. .. note:: The evaluated surface points are stored in :py:attr:`~surfpts`. :return: None """ # Check all parameters are set before the surface evaluation self._check_variables() # Clean up the surface points lists, if necessary self._reset_surface() # Algorithm A3.5 for v in utils.frange(0, 1, self._mDelta): span_v = utils.find_span(self._mDegreeV, tuple(self._mKnotVectorV), self._mCtrlPts_sizeV, v) basis_v = utils.basis_functions(self._mDegreeV, tuple(self._mKnotVectorV), span_v, v) for u in utils.frange(0, 1, self._mDelta): span_u = utils.find_span(self._mDegreeU, tuple(self._mKnotVectorU), self._mCtrlPts_sizeU, u) basis_u = utils.basis_functions(self._mDegreeU, tuple(self._mKnotVectorU), span_u, u) idx_u = span_u - self._mDegreeU surfpt = [0.0, 0.0, 0.0] for l in range(0, self._mDegreeV + 1): temp = [0.0, 0.0, 0.0] idx_v = span_v - self._mDegreeV + l for k in range(0, self._mDegreeU + 1): temp[0] += (basis_u[k] * self._mCtrlPts2D[idx_u + k][idx_v][0]) temp[1] += (basis_u[k] * self._mCtrlPts2D[idx_u + k][idx_v][1]) temp[2] += (basis_u[k] * self._mCtrlPts2D[idx_u + k][idx_v][2]) surfpt[0] += (basis_v[l] * temp[0]) surfpt[1] += (basis_v[l] * temp[1]) surfpt[2] += (basis_v[l] * temp[2]) self._mSurfPts.append(surfpt)
def derivatives2(self, u=-1, order=0): """ Evaluates n-th order curve derivatives at the given u using Algorithm A3.2 :param u: knot value :type u: float :param order: derivative order :type order: integer :return: A list containing up to {order}-th derivative of the curve :rtype: list """ # Check all parameters are set before the curve evaluation self._check_variables() # Check u parameters are correct if u < 0.0 or u > 1.0: raise ValueError('"u" value should be between 0 and 1.') # Algorithm A3.2: CurveDerivsAlg1 du = min(self._mDegree, order) CK = [[None for x in range(2)] for y in range(order + 1)] for k in range(self._mDegree + 1, order + 1): CK[k] = [0.0 for x in range(2)] span = utils.find_span(self._mDegree, tuple(self._mKnotVector), len(self._mCtrlPts), u) bfunsders = utils.basis_functions_ders(self._mDegree, tuple(self._mKnotVector), span, u, du) for k in range(0, du + 1): CK[k] = [0.0 for x in range(2)] for j in range(0, self._mDegree + 1): CK[k][0] += (bfunsders[k][j] * self._mCtrlPts[span - self._mDegree + j][0]) CK[k][1] += (bfunsders[k][j] * self._mCtrlPts[span - self._mDegree + j][1]) # Return the derivatives return CK
def derivatives(self, u=-1, v=-1, order=0): """ Evaluates n-th order surface derivatives at the given (u,v) parameter. * SKL[0][0] will be the surface point itself * SKL[0][1] will be the 1st derivative w.r.t. v * SKL[2][1] will be the 2nd derivative w.r.t. u and 1st derivative w.r.t. v :param u: parameter in the U direction :type u: float :param v: parameter in the V direction :type v: float :param order: derivative order :type order: integer :return: A list SKL, where SKL[k][l] is the derivative of the surface S(u,v) w.r.t. u k times and v l times :rtype: list """ # Check all parameters are set before the surface evaluation self._check_variables() # Check u and v parameters are correct utils.check_uv(u, v) # Algorithm A3.6 du = min(self._mDegreeU, order) dv = min(self._mDegreeV, order) SKL = [[[0.0 for x in range(3)] for y in range(dv + 1)] for z in range(du + 1)] span_u = utils.find_span(self._mDegreeU, tuple(self._mKnotVectorU), self._mCtrlPts_sizeU, u) bfunsders_u = utils.basis_functions_ders(self._mDegreeU, self._mKnotVectorU, span_u, u, du) span_v = utils.find_span(self._mDegreeV, tuple(self._mKnotVectorV), self._mCtrlPts_sizeV, v) bfunsders_v = utils.basis_functions_ders(self._mDegreeV, self._mKnotVectorV, span_v, v, dv) for k in range(0, du + 1): temp = [[] for y in range(self._mDegreeV + 1)] for s in range(0, self._mDegreeV + 1): temp[s] = [0.0 for x in range(3)] for r in range(0, self._mDegreeU + 1): cu = span_u - self._mDegreeU + r cv = span_v - self._mDegreeV + s temp[s][0] += (bfunsders_u[k][r] * self._mCtrlPts2D[cu][cv][0]) temp[s][1] += (bfunsders_u[k][r] * self._mCtrlPts2D[cu][cv][1]) temp[s][2] += (bfunsders_u[k][r] * self._mCtrlPts2D[cu][cv][2]) dd = min(order - k, dv) for l in range(0, dd + 1): for s in range(0, self._mDegreeV + 1): SKL[k][l][0] += (bfunsders_v[l][s] * temp[s][0]) SKL[k][l][1] += (bfunsders_v[l][s] * temp[s][1]) SKL[k][l][2] += (bfunsders_v[l][s] * temp[s][2]) # Return the derivatives return SKL
def evaluate_rational(self): """ Evaluates the NURBS surface. .. note:: The evaluated surface points are stored in :py:attr:`~surfpts`. :return: None """ # Check all parameters are set before the surface evaluation self._check_variables() # Clean up the surface points lists, if necessary self._reset_surface() # Prepare a 2D weighted control points array ctrlptsw = [] c_u = 0 while c_u < self._mCtrlPts_sizeU: ctrlptsw_v = [] c_v = 0 while c_v < self._mCtrlPts_sizeV: temp = [ self._mCtrlPts2D[c_u][c_v][0] * self._mWeights[c_u + (c_v * self._mCtrlPts_sizeU)], self._mCtrlPts2D[c_u][c_v][1] * self._mWeights[c_u + (c_v * self._mCtrlPts_sizeU)], self._mCtrlPts2D[c_u][c_v][2] * self._mWeights[c_u + (c_v * self._mCtrlPts_sizeU)], self._mWeights[c_u + (c_v * self._mCtrlPts_sizeU)] ] ctrlptsw_v.append(temp) c_v += 1 ctrlptsw.append(ctrlptsw_v) c_u += 1 # Algorithm A4.3 for v in utils.frange(0, 1, self._mDelta): span_v = utils.find_span(self._mDegreeV, tuple(self._mKnotVectorV), self._mCtrlPts_sizeV, v) basis_v = utils.basis_functions(self._mDegreeV, tuple(self._mKnotVectorV), span_v, v) for u in utils.frange(0, 1, self._mDelta): span_u = utils.find_span(self._mDegreeU, tuple(self._mKnotVectorU), self._mCtrlPts_sizeU, u) basis_u = utils.basis_functions(self._mDegreeU, tuple(self._mKnotVectorU), span_u, u) idx_u = span_u - self._mDegreeU surfptw = [0.0, 0.0, 0.0, 0.0] for l in range(0, self._mDegreeV + 1): temp = [0.0, 0.0, 0.0, 0.0] idx_v = span_v - self._mDegreeV + l for k in range(0, self._mDegreeU + 1): temp[0] += (basis_u[k] * ctrlptsw[idx_u + k][idx_v][0]) temp[1] += (basis_u[k] * ctrlptsw[idx_u + k][idx_v][1]) temp[2] += (basis_u[k] * ctrlptsw[idx_u + k][idx_v][2]) temp[3] += (basis_u[k] * ctrlptsw[idx_u + k][idx_v][3]) surfptw[0] += (basis_v[l] * temp[0]) surfptw[1] += (basis_v[l] * temp[1]) surfptw[2] += (basis_v[l] * temp[2]) surfptw[3] += (basis_v[l] * temp[3]) # Divide by weight to obtain 3D surface points surfpt = [ surfptw[0] / surfptw[3], surfptw[1] / surfptw[3], surfptw[2] / surfptw[3] ] self._mSurfPts.append(surfpt)