/*===================================================================== File: nurbsArray.h Purpose: Revision: $Id: nurbsArray.cpp,v 1.2 2002/05/13 21:07:46 philosophil Exp $ Created by: Philippe Lavoie (7 Oct, 1997) Copyright notice: Copyright (C) 1996-1997 Philippe Lavoie This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. =====================================================================*/ #include #include #include /*! */ namespace PLib { /*! \brief Constructor from a pointer to an array of curves \author Philippe Lavoie \date 24 January 1997 */ template NurbsCurveArray::NurbsCurveArray(NurbsCurve* Ca, int s){ sze = rsize = 0 ; resize(s) ; for(int i=0;i void NurbsCurveArray::init(NurbsCurve* ca,int size){ resize(size) ; for(int i=0;i void NurbsCurveArray::resize(int size) { int i ; if(size<=rsize){ sze = size ; return ; } NurbsCurve** t; t = new NurbsCurve* [size] ; if(C){ for(i=0;i ; C = t ; sze = size ; rsize = size ; } /*! \brief Reads a NurbsCurveArray from a file \param filename the filename to read the curve array from \return 0 if an error occurs, 1 otherwise \author Philippe Lavoie \date 24 January 1997 */ template int NurbsCurveArray::read(const char* filename){ ifstream fin(filename) ; if(!fin) { return 0 ; } int np,d; int na ; char *type ; type = new char[3] ; if(!fin.read(type,sizeof(char)*3)) return 0 ; int r1 = strncmp(type,"nca",3) ; if(!(r1==0)) return 0 ; if(!fin.read((char*)&na,sizeof(int))) return 0 ; resize(na) ; int nread = 0 ; while(nread < na){ if(!fin.read((char*)&np,sizeof(int))) return 0 ; if(!fin.read((char*)&d,sizeof(int))) return 0 ; operator[](nread).resize(np,d) ; if(!fin.read((char*)operator[](nread).knot().memory(),sizeof(T)*operator[](nread).knot().n())) return 0 ; T *p,*p2 ; p = new T[4*np] ; if(!fin.read((char*)p,sizeof(T)*4*np)) return 0 ; p2 = p ; for(int i=0;i t ; t.x() = *(p++) ; t.y() = *(p++) ; t.z() = *(p++) ; t.w() = *(p++) ; operator[](nread).modCP(i,t) ; } delete []p2 ; ++nread ; } delete []type ; return 1 ; } /*! \brief Writes a NurbsCurveArray from a file \param filename --> the filename to read the curve array from \return 0 if an error occurs, 1 otherwise \author Philippe Lavoie \date 24 January 1997 */ template int NurbsCurveArray::write(const char* filename){ ofstream fout(filename) ; if(!fout) { return 0 ; } if(!fout.write((char*)&"nca",sizeof(char)*3)) return 0 ; if(!fout.write((char*)&sze,sizeof(int))) return 0 ; int nwrote = 0 ; while(nwrote < sze){ int nn = operator[](nwrote).ctrlPnts().n() ; int nd = operator[](nwrote).degree() ; if(!fout.write((char*)&nn,sizeof(int))) return 0 ; if(!fout.write((char*)&nd,sizeof(int))) return 0 ; if(!fout.write((char*)operator[](nwrote).knot().memory(),sizeof(T)*operator[](nwrote).knot().n())) return 0 ; T *p,*p2 ; p = new T[4*operator[](nwrote).ctrlPnts().n()] ; p2 = p ; for(int i=0;i NurbsSurfaceArray::NurbsSurfaceArray(NurbsSurface* Sa, int s){ sze = rsize = 0 ; resize(s) ; for(int i=0;i void NurbsSurfaceArray::init(NurbsSurface* Sa,int size){ resize(size) ; for(int i=0;i void NurbsSurfaceArray::resize(int size) { int i ; if(size<=rsize){ sze = size ; return ; } NurbsSurface** t; t = new NurbsSurface* [size] ; if(S){ for(i=0;i ; S = t ; sze = size ; rsize = size ; } /*! \brief Copy one surface array to another \param S the array to copy \return a reference to itself \author Philippe Lavoie \date 24 January 1997 */ template NurbsSurfaceArray& NurbsSurfaceArray::operator=(const NurbsSurfaceArray& Sa){ resize(Sa.n()) ; for(int i=0;i inline Point_nD project2D(const HPoint_nD& p){ Point_nD pnt ; if(absolute(p.z()+T(1))>0.0001){ pnt.x() = p.x()/p.w() ; pnt.y() = p.y()/p.w() ; //pnt.x() /= p.z()+1 ; //pnt.y() /= p.z()+1 ; } else{ pnt.x() = p.x()/p.w(); pnt.y() = p.y()/p.w(); } return pnt ; } const float offX = 50 ; const float offY = 70 ; template inline void movePsP(Point_nD &p, T magFact){ p *= magFact ; p += Point_nD(offX,offY,0) ; //p = p*magFact+Point_nD(offX,offY,0) ; } template inline void movePsP(Point_nD &p, T magFact){ p *= magFact ; p += Point_nD(offX,offY) ; //p = p*magFact+Point_nD(offX,offY,0) ; } #endif // !INCLUDE_TEMPLATE_SOURCE /*! \brief Writes a post-script file representing an array of curves \param filename the file to write the postscript file to \param cp a flag indicating if the control points should be drawn, 0 = no and 1 = yes \param magFact a magnification factor, the 2D point of the control points will be magnified by this value. The size is measured in postscript points. If the magFact is set to a value smaller or equal to 0, than the program will try to guess a magnification factor such that the curve is large enough to fill the page. \param dash the size of the dash in postscript points . A size smaller or equal to 0 indicates that the line joining the control points is plain. \return 0 if an error occurs, 1 otherwise \warning If the weights of the curve are not all at 1, the result might not be representative of the true NURBS curve. \author Philippe Lavoie \date 7 October 1998 */ template int NurbsCurveArray::writePS(const char* filename,int cp,T magFact, T dash, bool ) const { ofstream fout(filename) ; if(!fout) return 0 ; if(curve(0).degree()<3){ NurbsCurveArray a3 ; a3.resize(n()) ; for(int i=0;i3){ return 0 ; } // find bounding box parameters T mx,my,Mx,My ; mx = Mx = 0 ; my = My = 0 ; for(int i=0;i p ; int step ; step = curve(i).ctrlPnts().n() + 5 ; for(int j=0;j<=step;++j){ T u ; u = (T)j/(T)step ; p = project2D(curve(i)(u)) ; if(i==0){ mx = Mx = p.x() ; my = My = p.y() ; } if(p.x() < mx) mx = p.x() ; if(p.x() > Mx) Mx = p.x() ; if(p.y() < my) my = p.y() ; if(p.y() > My) My = p.y() ; } } int guess =0 ; if(magFact<= T() ){ magFact = T(1) ; guess = 1 ; } if(guess){ //magFact = minimum((T)500/(T)(Mx-mx),(T)700/(T)(My-my)) ; } mx = mx*magFact+offX; my = my*magFact+offY; Mx = Mx*magFact+offX; My = My*magFact+offY; fout << "%!PS-Adobe-2.1\n%%Title: " << filename << endl ; fout << "%%Creator: NurbsCurve::writePS\n" ; fout << "%%BoundingBox: " << mx << ' ' << my << ' ' << Mx << ' ' << My << endl ; fout << "%%Pages: 0" << endl ; fout << "%%EndComments" << endl ; fout << "0 setlinewidth\n" ; fout << "0 setgray\n" ; fout << endl ; for(int k=0;k Ca ; curve(k).decompose(Ca) ; int deg = curve(k).degree() ; Matrix< Point_nD > pnts(Ca.n(),deg+1) ; int i,j ; for(i=0;i0){ // draw the control points of the original curve Vector< Point_nD > pts(curve(k).ctrlPnts().n()) ; for(i=0;i0) fout << "[" << dash << "] " << dash << " setdash\n" ; fout << "newpath\n" ; fout << pts[0].x() << ' ' << pts[0].y() << " moveto\n" ; for(i=1;i > pts(curve(k).ctrlPnts().n()*Ca.n()) ; int l=0 ; for(i=0;i0) fout << "[" << dash << "] " << dash << " setdash\n" ; fout << "newpath\n" ; fout << pts[0].x() << ' ' << pts[0].y() << " moveto\n" ; for(i=1;i int NurbsCurveArray::writePSp(const char* filename,const Vector< Point_nD >& points, const Vector< Point_nD >& vectors, int cp, T magFact, T dash, bool ) const { ofstream fout(filename) ; if(!fout) return 0 ; if(curve(0).degree()<3){ NurbsCurveArray a3 ; a3.resize(n()) ; for(int i=0;i3){ return 0 ; } // find bounding box parameters T mx,my,Mx,My ; mx = Mx = 0 ; my = My = 0 ; for(int i=0;i p ; int step ; step = curve(i).ctrlPnts().n() + 5 ; for(int j=0;j<=step;++j){ T u ; u = (T)j/(T)step ; p = project2D(curve(i)(u)) ; if(i==0){ mx = Mx = p.x() ; my = My = p.y() ; } if(p.x() < mx) mx = p.x() ; if(p.x() > Mx) Mx = p.x() ; if(p.y() < my) my = p.y() ; if(p.y() > My) My = p.y() ; } } int guess =0 ; if(magFact<= T() ){ magFact = T(1) ; guess = 1 ; } if(guess){ //magFact = minimum((T)500/(T)(Mx-mx),(T)700/(T)(My-my)) ; } mx = mx*magFact+offX; my = my*magFact+offY; Mx = Mx*magFact+offX; My = My*magFact+offY; fout << "%!PS-Adobe-2.1\n%%Title: " << filename << endl ; fout << "%%Creator: NurbsCurve::writePS\n" ; fout << "%%BoundingBox: " << mx << ' ' << my << ' ' << Mx << ' ' << My << endl ; fout << "%%Pages: 0" << endl ; fout << "%%EndComments" << endl ; fout << "0 setlinewidth\n" ; fout << "0 setgray\n" ; fout << endl ; for(int k=0;k Ca ; curve(k).decompose(Ca) ; int deg = curve(k).degree() ; Matrix< Point_nD > pnts(Ca.n(),deg+1) ; int i,j ; for(i=0;i0){ // draw the control points of the original curve Vector< Point_nD > pts(curve(k).ctrlPnts().n()) ; for(i=0;i0) fout << "[" << dash << "] " << dash << " setdash\n" ; fout << "newpath\n" ; fout << pts[0].x() << ' ' << pts[0].y() << " moveto\n" ; for(i=1;i > pts(curve(k).ctrlPnts().n()*Ca.n()) ; int l=0 ; for(i=0;i0) fout << "[" << dash << "] " << dash << " setdash\n" ; fout << "newpath\n" ; fout << pts[0].x() << ' ' << pts[0].y() << " moveto\n" ; for(i=1;i p ; p = points[i] ; movePsP(p,magFact) ; fout << "newpath\n" ; fout << p.x() << ' ' << p.y() << " 3 0 360 arc\nfill\n" ; } if(vectors.n()==points.n()){ for(int i=0;i p,p2 ; p = points[i] ; p2 = points[i] + vectors[i] ; movePsP(p,magFact) ; movePsP(p2,magFact) ; fout << "newpath\n" ; fout << p.x() << ' ' << p.y() << " moveto\n" ; if(dash>0) fout << "[" << dash/2.0 << "] " << dash/2.0 << " setdash\n" ; fout << p2.x() << ' ' << p2.y() << " lineto\n" ; fout << "stroke\n" ; } } fout << "showpage\n%%EOF\n" ; return 1 ; } } // end namespace