Main Page   Class Hierarchy   Compound List   File List   Compound Members  

hnurbsS_sp.cpp

00001 /*=====================================================================
00002         File: hnurbsS_sp.cpp
00003      Purpose:       
00004     Revision: $Id: hnurbsS_sp.cpp,v 1.2 2002/05/13 21:07:46 philosophil Exp $
00005   Created by: Philippe Lavoie          (14 May, 1998)
00006  Modified by: 
00007 
00008  Copyright notice:
00009           Copyright (C) 1996-1997 Philippe Lavoie
00010  
00011           This library is free software; you can redistribute it and/or
00012           modify it under the terms of the GNU Library General Public
00013           License as published by the Free Software Foundation; either
00014           version 2 of the License, or (at your option) any later version.
00015  
00016           This library is distributed in the hope that it will be useful,
00017           but WITHOUT ANY WARRANTY; without even the implied warranty of
00018           MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019           Library General Public License for more details.
00020  
00021           You should have received a copy of the GNU Library General Public
00022           License along with this library; if not, write to the Free
00023           Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00024 =====================================================================*/
00025 #include <hnurbsS_sp.h>
00026 #include <string.h>
00027 
00030 namespace PLib {
00031 
00044 template <class T, int N>
00045 void HNurbsSurfaceSP<T,N>::updateMaxU() {
00046   if(degU>3){
00047 #ifdef USE_EXCEPTION
00048     throw NurbsError();
00049 #else
00050     Error error("HNurbsSurfaceSP<T,N>::updateMaxU()") ;
00051     error << "This class doesn't support surfaces having a degree of 4 and higher.\n" ;
00052     error.fatal() ;
00053 #endif
00054   }
00055   else{
00056     maxU.resize(P.rows()) ;
00057     maxAtU_.resize(P.rows()) ;
00058     for(int i=0;i<P.rows();++i){
00059       if(!maxInfluence(i,U,degU,maxAtU_[i]))
00060         cerr << "Problem in maxInfluence U!\n" ;
00061       maxU[i] = nurbsBasisFun(maxAtU_[i],i,degU,U) ;
00062     }
00063     
00064   }
00065 }
00066 
00079 template <class T, int N>
00080 void HNurbsSurfaceSP<T,N>::updateMaxV() {
00081   if(degV>3){
00082 #ifdef USE_EXCEPTION
00083     throw NurbsError();
00084 #else
00085     Error error("HNurbsSurfaceSP<T,N>::updateMaxV()") ;
00086     error << "This class doesn't support surfaces having a degree of 4 and higher.\n" ;
00087     error.fatal() ;
00088 #endif
00089   }
00090   else{
00091     maxV.resize(P.cols()) ;
00092     maxAtV_.resize(P.cols()) ;
00093     for(int i=0;i<P.cols();++i){
00094       if(!maxInfluence(i,V,degV,maxAtV_[i]))
00095         cerr << "Problem in maxInfluence V!\n" ;
00096       maxV[i] = nurbsBasisFun(maxAtV_[i],i,degV,V) ;
00097     }
00098     
00099   }
00100 }
00101 
00114 template <class T, int N>
00115 void HNurbsSurfaceSP<T,N>::modSurfCPby(int i, int j, const HPoint_nD<T,N>& a) {
00116   offset(i,j) +=  a / (maxU[i]*maxV[j]) ; 
00117   if(baseLevel_){
00118     Point_nD<T,N> vecOffset ; 
00119     vecOffset = offset(i,j).x()*ivec(i,j) +
00120       offset(i,j).y()*jvec(i,j) +
00121       offset(i,j).z()*kvec(i,j) ;
00122     P(i,j).x() = baseSurf.ctrlPnts()(i,j).x()+vecOffset.x() ;
00123     P(i,j).y() = baseSurf.ctrlPnts()(i,j).y()+vecOffset.y() ;
00124     P(i,j).z() = baseSurf.ctrlPnts()(i,j).z()+vecOffset.z() ;
00125   }
00126   else
00127     P(i,j) = offset(i,j) ; 
00128 }
00129 
00150 template <class T, int N>
00151 void HNurbsSurfaceSP<T,N>::modOnlySurfCPby(int i, int j, const HPoint_nD<T,N>& a){
00152   int k ; 
00153 
00154   P = offset ; 
00155 
00156   // by definition the offset has w = 0 , but this isn't valid for
00157   // the control points, increasing the w by 1, will generate a valid surface
00158   if(baseLevel_)
00159     for(k=0;k<P.rows();++k)
00160       for(int l=0;l<P.cols();++l)
00161         P(k,l).w() += T(1) ; 
00162 
00163   int sizeU, sizeV ;
00164 
00165   sizeU = 2*degU+3 ; 
00166   if(i-degU-1<0) sizeU += i-degU-1 ; 
00167   if(i+degU+1>=P.rows()) sizeU -= i+degU+1-P.rows() ;
00168 
00169   sizeV = 2*degV+3 ;
00170   if(j-degV-1<0) sizeV += j-degV-1 ; 
00171   if(j+degV+1>=P.cols()) sizeV -= j+degV+1-P.cols() ;
00172   
00173   Vector<T> u(sizeU) ;
00174   Vector<T> v(sizeV) ;
00175   Vector<Point_nD<T,N> > pts(sizeU*sizeV) ; 
00176   Vector<int> pu(sizeU*sizeV) ;
00177   Vector<int> pv(sizeU*sizeV) ;
00178 
00179   int n=0;
00180   int nu = 0 ;
00181   int nv = 0 ; 
00182   for(k=i-degU-1;k<=i+degU+1;++k){
00183     if(k<0)
00184       continue ;
00185     if(k>=P.rows())
00186       break ; 
00187     nv = 0 ;
00188     for(int l=j-degV-1;l<=j+degV+1;++l){
00189       if(l<0)
00190         continue ;
00191       if(l>=P.cols())
00192         break ; 
00193       if( k == i && j==l){
00194         pts[n].x() = a.x() ; 
00195         pts[n].y() = a.y() ; 
00196         pts[n].z() = a.z() ; 
00197       }
00198       //else
00199       //pts[n] = Point_nD<T,N>(0,0,0) ;
00200       pu[n] = nu ; 
00201       pv[n] = nv ; 
00202       if(k==i){
00203         v[nv] = maxAtV_[l] ; // only need to initialise this once
00204       }
00205       ++n ;
00206       ++nv ; 
00207     }  
00208     u[nu] = maxAtU_[k] ;
00209     ++nu ; 
00210   }
00211 
00212   u.resize(nu) ;
00213   v.resize(nv) ; 
00214   pts.resize(n) ;
00215   pu.resize(n) ; 
00216   pv.resize(n) ; 
00217 
00218   if(NurbsSurface<T,N>::movePoint(u,v,pts,pu,pv)){
00219     offset = P ; 
00220     // an offset shouldn't have a weight value.
00221     if(baseLevel_)
00222       for(k=0;k<P.rows();++k)
00223         for(int l=0;l<P.cols();++l)
00224           offset(k,l).w() -= T(1) ; 
00225   }
00226   updateSurface(); 
00227 }
00228 
00229 /*
00230   not defined for now. I'm not sure we need it/want it.
00231 
00232  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00233   Modifies the surface point to a certain value.
00234   \param i  the row of the surface point
00235                j  the column of the surface point
00236                a  modify the surface point to this value
00237   \return
00238   \warning The degree in U and V of the surface must be of 3 or less.
00239 
00240   \author Philippe Lavoie
00241   \date 14 May, 1998
00242  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00243 /*void HNurbsSurfaceSP<T,N>::modSurfCP(int i, int j, const HPoint_nD<T,N>& a) {
00244   modSurfCPby(i,j,a-surfP(i,j)) ;
00245 }
00246 */
00247 
00261 template <class T, int N>
00262 HNurbsSurfaceSP<T,N>* HNurbsSurfaceSP<T,N>::addLevel(int n, int s) {
00263   HNurbsSurfaceSP<T,N> *newLevel ;
00264 
00265   if(nextLevel_)
00266     return 0 ;
00267 
00268   Vector<T> newU,newV ;
00269   
00270   splitUV(n,s,n,s,newU,newV) ;
00271 
00272   newLevel = new HNurbsSurfaceSP<T,N>(this,newU,newV) ;
00273 
00274   return newLevel ;
00275 }
00276 
00288 template <class T, int N>
00289 HNurbsSurfaceSP<T,N>* HNurbsSurfaceSP<T,N>::addLevel() {
00290   HNurbsSurfaceSP<T,N> *newLevel ;
00291 
00292   if(nextLevel_)
00293     return 0 ;
00294 
00295   newLevel = new HNurbsSurfaceSP<T,N>(this) ;
00296 
00297   return newLevel ;
00298 }
00299 
00308 template <class T, int N>
00309 void HNurbsSurfaceSP<T,N>::copy(const HNurbsSurface<T,N>& nS){
00310   HNurbsSurface<T,N> *levelP ;
00311   levelP = nS.nextLevel() ;
00312 
00313   NurbsSurface<T,N>::operator=(nS) ;
00314   rU = nS.rU ;
00315   rV = nS.rV ;
00316   offset = nS.offset ;
00317 
00318   updateMaxUV() ; 
00319 
00320   firstLevel_ = this ;
00321 
00322   if(levelP){
00323     HNurbsSurfaceSP<T,N> *newLevel ;
00324     newLevel =  new HNurbsSurfaceSP<T,N>(this) ; 
00325     newLevel->copy(*levelP) ;
00326     nextLevel_ = newLevel ;
00327     lastLevel_ = nextLevel_->lastLevel() ;
00328   }
00329   else{
00330     lastLevel_ = this ;
00331   }
00332 
00333 }
00334 
00349 template <class T, int N>
00350 void HNurbsSurfaceSP<T,N>::updateSurface(int i0, int j0){
00351   if(i0>=0 && j0>=0){
00352     if(offset(i0,j0).x()==0.0 && offset(i0,j0).y()==0.0 && offset(i0,j0).z()==0.0)
00353       return ;
00354   }
00355   if(baseLevel_){
00356     if(initBase()){
00357       P = baseSurf.ctrlPnts() ;
00358       U = baseSurf.knotU() ;
00359       V = baseSurf.knotV() ;
00360       degU = baseSurf.degreeU() ;
00361       degV = baseSurf.degreeV() ;
00362       updateMaxUV() ; 
00363     }
00364     if(i0>=0 && j0>=0){
00365       Point_nD<T,N> vecOffset ;
00366       vecOffset = offset(i0,j0).x()*ivec(i0,j0) +
00367         offset(i0,j0).y()*jvec(i0,j0) +
00368         offset(i0,j0).z()*kvec(i0,j0) ;
00369       P(i0,j0).x() = baseSurf.ctrlPnts()(i0,j0).x()+vecOffset.x() ;
00370       P(i0,j0).y() = baseSurf.ctrlPnts()(i0,j0).y()+vecOffset.y() ;
00371       P(i0,j0).z() = baseSurf.ctrlPnts()(i0,j0).z()+vecOffset.z() ;
00372     }
00373     else{
00374       for(int i=0;i<P.rows();++i)
00375         for(int j=0;j<P.cols();++j){
00376           if(offset(i,j).x() != 0 || 
00377              offset(i,j).y() != 0 || offset(i,j).z() || 0){
00378             Point_nD<T,N> vecOffset ;
00379             vecOffset = offset(i,j).x()*ivec(i,j) +
00380               offset(i,j).y()*jvec(i,j) +
00381               offset(i,j).z()*kvec(i,j) ;
00382             P(i,j).x() = baseSurf.ctrlPnts()(i,j).x()+vecOffset.x() ;
00383             P(i,j).y() = baseSurf.ctrlPnts()(i,j).y()+vecOffset.y() ;
00384             P(i,j).z() = baseSurf.ctrlPnts()(i,j).z()+vecOffset.z() ;
00385           }
00386         }
00387     }
00388   }
00389   else{
00390     if(i0>=0 && j0>=0)
00391       P(i0,j0) = offset(i0,j0) ;
00392     else{
00393       for(int i=0;i<P.rows();++i)
00394         for(int j=0;j<P.cols();++j){
00395           P(i,j) = offset(i,j) ;
00396         }
00397     }
00398   }
00399 
00400   ++updateN ;
00401 }
00402 
00411 template <class T, int N>
00412 void HNurbsSurfaceSP<T,N>::updateLevels(int upLevel){
00413   if(!okMax())
00414     updateMaxUV() ; 
00415   if(upLevel>=0){
00416     if(level()<=upLevel){
00417       this->updateSurface() ;
00418     }
00419   }
00420   else{
00421     this->updateSurface() ;
00422   }
00423 
00424   if(upLevel>level() || upLevel<0){
00425     if(nextLevel_)
00426       ((HNurbsSurfaceSP<T,N>*)nextLevel_)->updateLevels(upLevel) ;
00427   }
00428 }
00429 
00440 template <class T, int N>
00441 int HNurbsSurfaceSP<T,N>::read(ifstream &fin){
00442   if(!fin) {
00443     return 0 ;
00444   }
00445   int nu,nv,du,dv;
00446   char *type ;
00447   type = new char[4] ;
00448   if(!fin.read(type,sizeof(char)*4)) { delete []type ; return 0 ;}
00449   int r1 = strncmp(type,"hns3",4) ;
00450   int r2 = strncmp(type,"hns4",4) ;
00451   int r3 = strncmp(type,"hnso",4) ;
00452   if(!(r1 || r2 || r3)) 
00453     return 0 ;
00454   T *p,*p2 ;
00455   if(!r1 || !r2){
00456     if(!fin.read((char*)&nu,sizeof(int))) { delete []type ; return 0 ;}
00457     if(!fin.read((char*)&nv,sizeof(int))) { delete []type ; return 0 ;}
00458     if(!fin.read((char*)&du,sizeof(int))) { delete []type ; return 0 ;}
00459     if(!fin.read((char*)&dv,sizeof(int))) { delete []type ; return 0 ;}
00460     
00461     resize(nu,nv,du,dv) ;
00462     
00463     if(!fin.read((char*)U.memory(),sizeof(T)*U.n())) { delete []type ; return 0 ;}
00464     if(!fin.read((char*)V.memory(),sizeof(T)*V.n())) { delete []type ; return 0 ;}
00465     
00466     if(!r1){
00467       p = new T[3*nu*nv] ;
00468       if(!fin.read((char*)p,sizeof(T)*3*nu*nv)) { delete []type ; return 0 ;}
00469       p2 = p ;
00470       for(int i=0;i<nu;i++)
00471         for(int j=0;j<nv;j++){
00472           P(i,j).x() = *(p++) ;
00473           P(i,j).y() = *(p++) ;
00474           P(i,j).z() = *(p++) ;
00475           P(i,j).w() = 1.0 ;
00476         }
00477       delete []p2 ;
00478     }
00479     else{
00480       p = new T[4*nu*nv] ;
00481       if(!fin.read((char*)p,sizeof(T)*4*nu*nv)) { delete []type ; return 0 ;}
00482       p2 = p ;
00483       for(int i=0;i<nu;i++)
00484         for(int j=0;j<nv;j++){
00485           P(i,j).x() = *(p++) ;
00486           P(i,j).y() = *(p++) ;
00487           P(i,j).z() = *(p++) ;
00488           P(i,j).w() = *(p++) ;
00489         }
00490       delete []p2 ;
00491     }
00492     offset = P ;
00493     this->updateSurface() ;
00494   }
00495   else { // reading the offset information
00496     int ru,rv ;
00497     if(!fin.read((char*)&ru,sizeof(int))) { delete []type ; return 0 ;}
00498     if(!fin.read((char*)&rv,sizeof(int))) { delete []type ; return 0 ;}
00499     rU.resize(ru) ;
00500     rV.resize(rv) ;
00501     if(rU.n()>0)
00502       if(!fin.read((char*)rU.memory(),sizeof(T)*rU.n())) { delete []type ; return 0 ;}
00503     if(rV.n()>0)
00504       if(!fin.read((char*)rV.memory(),sizeof(T)*rV.n())) { delete []type ; return 0 ;}
00505     
00506     if(!fin.read((char*)&nu,sizeof(int))) { delete []type ; return 0 ;}
00507     if(!fin.read((char*)&nv,sizeof(int))) { delete []type ; return 0 ;}
00508 
00509     p = new T[4*nu*nv] ;
00510     if(!fin.read((char*)p,sizeof(T)*4*nu*nv)) { delete []type ; return 0 ;}
00511     p2 = p ;
00512     offset.resize(nu,nv) ;
00513     for(int i=0;i<nu;i++)
00514       for(int j=0;j<nv;j++){
00515         offset(i,j).x() = *(p++) ;
00516         offset(i,j).y() = *(p++) ;
00517         offset(i,j).z() = *(p++) ;
00518         offset(i,j).w() = *(p++) ;
00519       }
00520     delete []p2 ;    
00521     --baseUpdateN ;
00522     this->updateSurface() ;
00523   }
00524 
00525   // now we must read all the level information (if any)
00526   char *ptxt ;
00527   ptxt = new char[7] ;
00528   // the following line is used so that purify doesn't give a warning
00529   ptxt[0] = ptxt[1] = ptxt[2] = ptxt[3] = ptxt[4] = ptxt[5] = ptxt[6] = 0 ;
00530   int mark  = fin.tellg() ;
00531   if(!fin.read(ptxt,sizeof(char)*5))
00532     { delete []ptxt ; delete []type ; return 1 ; }
00533   char *pat ;
00534   pat = strstr(ptxt,"level") ;
00535   if(pat){
00536     // insert a new level
00537     HNurbsSurfaceSP<T,N> *newPatch = new HNurbsSurfaceSP<T,N>(this) ; 
00538     if(newPatch){
00539       if(!newPatch->read(fin)) 
00540         return 0 ;      
00541     }
00542     else
00543       return 0 ;
00544   }
00545   else{ 
00546     // something else is after the HNurbs
00547     // restore were the file was before the read
00548     fin.seekg(mark);
00549   }
00550 
00551   delete []ptxt ;
00552   delete []type ;
00553   return 1 ;
00554 }
00555 
00556 } // end namespace

Generated on Tue Jun 24 13:26:55 2003 for NURBS++ by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002