def shape_functions(self,xi1,xi2,number_of_derivatives=0): if number_of_derivatives > 1: raise "Only coded for first derivative" # Make sure values are floating point xi1=np.asarray(xi1,np.float).reshape(-1,) xi2=np.asarray(xi2,np.float).reshape(-1,) num = np.size(xi1) Bi = NURBSinC.multiAllBernsteinDers(self.n,xi1,number_of_derivatives) Bj = NURBSinC.multiAllBernsteinDers(self.m,xi2,number_of_derivatives) N = Bi[:,0].reshape(num,-1,1) * Bj[:,0].reshape(num,1,-1) * self.wmat W = np.sum(np.sum(N,1),1).reshape(-1,1,1) if number_of_derivatives==1: R = np.zeros((num,(self.n+1)*(self.m+1),3)) Nu = Bi[:,1].reshape(num,-1,1) * Bj[:,0].reshape(num,1,-1) * self.wmat Wu = np.sum(np.sum(Nu,1),1).reshape(-1,1,1) Nv = Bi[:,0].reshape(num,-1,1) * Bj[:,1].reshape(num,1,-1) * self.wmat Wv = np.sum(np.sum(Nv,1),1).reshape(-1,1,1) R[:,:,0] = (N/W).reshape(num,-1) # From formula S_alpha(u,v) in NURBS books pg 136 R[:,:,1] = ((Nu*W-N*Wu)/(W**2)).reshape(num,-1) R[:,:,2] = ((Nv*W-N*Wv)/(W**2)).reshape(num,-1) else: R = np.zeros((num,(self.n+1)*(self.m+1),1)) R[:,:,0] = (N/W).reshape(num,-1) return R
def NURBS_basis_functions(self,xi,num_derivatives=0): xi = np.asarray(xi,np.float).reshape(-1,) spans = NURBSinC.multiFindSpan(self.n,self.p,xi,self.U) if num_derivatives==1: N = NURBSinC.multidersNURBSbasis(spans,xi,self.p,1,self.U,self.w) else: N = np.zeros((xi.size,1,self.n+1)) N[:,0,:] = NURBSinC.multiNURBSbasis(spans,xi,self.p,self.U,self.w) return N
def NURBS_basis_functions(self, xi, num_derivatives=0): xi = np.asarray(xi, np.float).reshape(-1, ) spans = NURBSinC.multiFindSpan(self.n, self.p, xi, self.U) if num_derivatives == 1: N = NURBSinC.multidersNURBSbasis(spans, xi, self.p, 1, self.U, self.w) else: N = np.zeros((xi.size, 1, self.n + 1)) N[:, 0, :] = NURBSinC.multiNURBSbasis(spans, xi, self.p, self.U, self.w) return N
def shape_functions(self,xi,number_of_derivatives=0): """Returns the basis functions on the element in the form [i,j,d] where: i: xi coordinate index j: Bezier function index d: derivative""" if number_of_derivatives > 1: raise "Only coded for first derivative" xi=np.asarray(xi,np.float).reshape(-1,) if number_of_derivatives==1: B = NURBSinC.multiRationalBernsteinDers(self.n,self.Pw.T,xi,1) else: B = np.zeros((xi.size,self.n+1,1)) B[:,:,0] = NURBSinC.multiRationalBernstein(self.n,self.Pw.T,xi) return B
def shape_functions(self, xi, number_of_derivatives=0): """Returns the basis functions on the element in the form [i,j,d] where: i: xi coordinate index j: Bezier function index d: derivative""" if number_of_derivatives > 1: raise "Only coded for first derivative" xi = np.asarray(xi, np.float).reshape(-1, ) if number_of_derivatives == 1: B = NURBSinC.multiRationalBernsteinDers(self.n, self.Pw.T, xi, 1) else: B = np.zeros((xi.size, self.n + 1, 1)) B[:, :, 0] = NURBSinC.multiRationalBernstein(self.n, self.Pw.T, xi) return B
def NURBSbasis(self,uv,i=None,j=None): """Evaluate one basis function given uv, a (2,-1) matrix""" if uv.shape[1]>1: if i!=None and j!=None: uspan = NURBSinC.multiFindSpan(self.n,self.p,uv[0],self.U) Nu = NURBSinC.multiBasisFuns(uspan,uv[0],self.p,self.U) vspan = NURBSinC.multiFindSpan(self.m,self.q,uv[1],self.V) Nv = NURBSinC.multiBasisFuns(vspan,uv[1],self.q,self.V) denominator = np.zeros(uv.shape[1],) for k in xrange(self.n+1): for l in xrange(self.m+1): denominator += Nu[:,k]*Nv[:,l]*self.w[k,l] return Nu[:,i]*Nv[:,j]*self.w[i,j] / denominator else: return NURBSinC.multiSurfaceBasis(uv,self.p,self.n,self.U,self.q,self.m,self.V,self.w) else: print "Need to 'NURBSbasis' for single point"
def NURBSbasis(self, uv, i=None, j=None): """Evaluate one basis function given uv, a (2,-1) matrix""" if uv.shape[1] > 1: if i != None and j != None: uspan = NURBSinC.multiFindSpan(self.n, self.p, uv[0], self.U) Nu = NURBSinC.multiBasisFuns(uspan, uv[0], self.p, self.U) vspan = NURBSinC.multiFindSpan(self.m, self.q, uv[1], self.V) Nv = NURBSinC.multiBasisFuns(vspan, uv[1], self.q, self.V) denominator = np.zeros(uv.shape[1], ) for k in xrange(self.n + 1): for l in xrange(self.m + 1): denominator += Nu[:, k] * Nv[:, l] * self.w[k, l] return Nu[:, i] * Nv[:, j] * self.w[i, j] / denominator else: return NURBSinC.multiSurfaceBasis(uv, self.p, self.n, self.U, self.q, self.m, self.V, self.w) else: print "Need to 'NURBSbasis' for single point"
def refineknotvector(self, XI, knotvec_choice): """Insert the knots contained in XI into U or V""" XI = np.asarray(XI, np.float).reshape(-1, ) if knotvec_choice == 'U': if np.min(XI) <= np.min(self.U): raise "Knots cannot be inserted: some elements too small" if np.max(XI) >= np.max(self.U): raise "Knots cannot be inserted: some elements too large" if np.any([ np.equal(xi, self.U).sum() + np.equal(xi, XI).sum() > self.p for xi in np.unique(XI) ]): raise "Knots cannot be inserted: some multiplicities too large" self.U, self.V, self.Pw = NURBSinC.RefineKnotVectSurface( self.n, self.p, self.U, self.m, self.q, self.V, self.Pw, XI, 0) self.r = self.U.shape[0] - 1 self.n = self.r - self.p - 1 self.pspans = np.unique(self.U) if knotvec_choice == 'V': if np.min(XI) <= np.min(self.V): raise "Knots cannot be inserted: some elements too small" if np.max(XI) >= np.max(self.V): raise "Knots cannot be inserted: some elements too large" if np.any([ np.equal(xi, self.V).sum() + np.equal(xi, XI).sum() > self.q for xi in np.unique(XI) ]): raise "Knots cannot be inserted: some multiplicities too large" self.V, self.U, self.Pw = NURBSinC.RefineKnotVectSurface( self.m, self.q, self.V, self.n, self.p, self.U, np.transpose(self.Pw, (1, 0, 2)), XI, 0) self.Pw = np.transpose(self.Pw, (1, 0, 2)) self.s = self.V.shape[0] - 1 self.m = self.s - self.q - 1 self.qspans = np.unique(self.V) self.P = (self.Pw[:, :, :3].T / self.Pw[:, :, 3].T).T self.w = self.Pw[:, :, 3]
def shape_functions(self, xi1, xi2, number_of_derivatives=0): if number_of_derivatives > 1: raise "Only coded for first derivative" # Make sure values are floating point xi1 = np.asarray(xi1, np.float).reshape(-1, ) xi2 = np.asarray(xi2, np.float).reshape(-1, ) num = np.size(xi1) Bi = NURBSinC.multiAllBernsteinDers(self.n, xi1, number_of_derivatives) Bj = NURBSinC.multiAllBernsteinDers(self.m, xi2, number_of_derivatives) N = Bi[:, 0].reshape(num, -1, 1) * Bj[:, 0].reshape(num, 1, -1) * self.wmat W = np.sum(np.sum(N, 1), 1).reshape(-1, 1, 1) if number_of_derivatives == 1: R = np.zeros((num, (self.n + 1) * (self.m + 1), 3)) Nu = Bi[:, 1].reshape(num, -1, 1) * Bj[:, 0].reshape( num, 1, -1) * self.wmat Wu = np.sum(np.sum(Nu, 1), 1).reshape(-1, 1, 1) Nv = Bi[:, 0].reshape(num, -1, 1) * Bj[:, 1].reshape( num, 1, -1) * self.wmat Wv = np.sum(np.sum(Nv, 1), 1).reshape(-1, 1, 1) R[:, :, 0] = (N / W).reshape(num, -1) # From formula S_alpha(u,v) in NURBS books pg 136 R[:, :, 1] = ((Nu * W - N * Wu) / (W**2)).reshape(num, -1) R[:, :, 2] = ((Nv * W - N * Wv) / (W**2)).reshape(num, -1) else: R = np.zeros((num, (self.n + 1) * (self.m + 1), 1)) R[:, :, 0] = (N / W).reshape(num, -1) return R
def refineknotvector(self, XI): XI = np.asarray(XI, np.float).reshape(-1, ) """Refine the curve knot vector""" if np.min(XI) <= np.min(self.U): raise "Knots cannot be inserted: some values too small" if np.max(XI) >= np.max(self.U): raise "Knots cannot be inserted: some values too large" if np.any([ np.equal(xi, self.U).sum() + np.equal(xi, XI).sum() > self.p for xi in np.unique(XI) ]): raise "Knots cannot be inserted: some multiplicities too high" self.n, self.U, self.Pw = NURBSinC.RefineKnotVectCurve( self.n, self.p, self.U, self.Pw, XI) self.P, self.w = (self.Pw[:, :2].T / self.Pw[:, 2].T).T, self.Pw[:, 2]
def decompose(self): """Decompose NURBS surface into rational Bezier patches""" return NURBSinC.DecomposeSurface(self.n, self.p, self.U, self.m, self.q, self.V, self.Pw)
def vals(self, u, v): """Return coordinates of NURBS surface at (u,v)""" u = np.asarray(u, np.float).reshape(-1, ) v = np.asarray(v, np.float).reshape(-1, ) return NURBSinC.multiSurfacePoint(self.n, self.p, self.U, self.m, self.q, self.V, self.Pw, u, v)
def vals(self,u,v): """Return coordinates of NURBS surface at (u,v)""" u=np.asarray(u,np.float).reshape(-1,) v=np.asarray(v,np.float).reshape(-1,) return NURBSinC.multiSurfacePoint(self.n,self.p,self.U,self.m,self.q,self.V,self.Pw,u,v)
def decompose_into_Bezier_segments(self): nb, Qw = NURBSinC.DecomposeCurve(self.n, self.p, self.U, self.Pw) return nb, Qw