CubeTopology.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
00024 ******************************************************************************/
00025 #include <sofa/component/topology/CubeTopology.h>
00026 #include <sofa/core/ObjectFactory.h>
00027 
00028 namespace sofa
00029 {
00030 
00031 namespace component
00032 {
00033 
00034 namespace topology
00035 {
00036 
00037 using namespace sofa::defaulttype;
00038 using std::cout;
00039 using std::endl;
00040 
00041 void CubeTopology::parse(core::objectmodel::BaseObjectDescription* arg)
00042 {
00043     this->MeshTopology::parse(arg);
00044     float scale=1.0f;
00045     if (arg->getAttribute("scale")!=NULL) {
00046         scale = (float)atof(arg->getAttribute("scale"));
00047     }
00048     this->setSize();
00049     if (arg->getAttribute("xmin") != NULL && 
00050     arg->getAttribute("ymin") != NULL && 
00051     arg->getAttribute("zmin") != NULL && 
00052     arg->getAttribute("xmax") != NULL && 
00053     arg->getAttribute("ymax") != NULL && 
00054     arg->getAttribute("zmax") != NULL )
00055     {
00056     const char* xmin = arg->getAttribute("xmin");
00057     const char* ymin = arg->getAttribute("ymin");
00058     const char* zmin = arg->getAttribute("zmin");
00059     const char* xmax = arg->getAttribute("xmax");
00060     const char* ymax = arg->getAttribute("ymax");
00061     const char* zmax = arg->getAttribute("zmax");
00062     min.setValue(Vector3((SReal)(atof(xmin)*scale), (SReal)(atof(ymin)*scale), (SReal)(atof(zmin)*scale)));
00063     max.setValue(Vector3((SReal)(atof(xmax)*scale), (SReal)(atof(ymax)*scale), (SReal)(atof(zmax)*scale)));
00064     }
00065     this->setPos(min.getValue()[0],max.getValue()[0],min.getValue()[1],max.getValue()[1],min.getValue()[2],max.getValue()[2]);
00066 }
00067 
00068 SOFA_DECL_CLASS(CubeTopology)
00069 
00070 int CubeTopologyClass = core::RegisterObject("Surface of a cube in 3D")
00071 .add< CubeTopology >()
00072 ;
00073 
00074 CubeTopology::CubeTopology(int _nx, int _ny, int _nz)
00075 : nx(initData(&nx,_nx,"nx","x grid resolution")), ny(initData(&ny,_ny,"ny","y grid resolution")), nz(initData(&nz,_nz,"nz","z grid resolution"))
00076 , internalPoints(initData(&internalPoints, false, "internalPoints", "include internal points (allow a one-to-one mapping between points from RegularGridTopology and CubeTopology)"))
00077 , splitNormals(initData(&splitNormals, false, "splitNormals", "split corner points to have planar normals"))
00078 , min(initData(&min,Vector3(0.0f,0.0f,0.0f),"min", "Min"))
00079 , max(initData(&max,Vector3(1.0f,1.0f,1.0f),"max", "Max"))
00080 {
00081     setSize();
00082 }
00083 
00084 CubeTopology::CubeTopology()
00085 : nx(initData(&nx,0,"nx","x grid resolution")), ny(initData(&ny,0,"ny","y grid resolution")), nz(initData(&nz,0,"nz","z grid resolution"))
00086 , internalPoints(initData(&internalPoints, false, "internalPoints", "include internal points (allow a one-to-one mapping between points from RegularGridTopology and CubeTopology)"))
00087 , splitNormals(initData(&splitNormals, false, "splitNormals", "split corner points to have planar normals"))
00088 , min(initData(&min,Vector3(0.0f,0.0f,0.0f),"min", "Min"))
00089 , max(initData(&max,Vector3(1.0f,1.0f,1.0f),"max", "Max"))
00090 {
00091 }
00092 
00093 void CubeTopology::setSize(int nx, int ny, int nz)
00094 {
00095     if (nx == this->nx.getValue() && ny == this->ny.getValue() && nz == this->nz.getValue())
00096     return;
00097     this->nx.setValue(nx);
00098     this->ny.setValue(ny);
00099     this->nz.setValue(nz);
00100     setSize();
00101 }
00102 
00103 void CubeTopology::init()
00104 {
00105     this->MeshTopology::init();
00106     setSize();
00107 }
00108 
00109 void CubeTopology::reinit()
00110 {
00111     this->MeshTopology::reinit();
00112     setSize();
00113 }
00114 
00115 
00116 void CubeTopology::setSize()
00117 {
00118     const int nx = this->nx.getValue();
00119     const int ny = this->ny.getValue();
00120     const int nz = this->nz.getValue();
00121     if (splitNormals.getValue())
00122     this->nbPoints = nx*ny*(nz>1?2:1) + ny*nz*(nx>1?2:1) + nz*nx*(ny>1?2:1);
00123     else if (!internalPoints.getValue() && (nx>1 && ny>1 && nz>1))
00124     this->nbPoints = nx*ny*2 + (nz-2)*(2*nx+2*ny-4);
00125     else
00126     this->nbPoints = nx*ny*nz;
00127 
00128     invalidate();
00129 }
00130 
00131 int CubeTopology::point(int x, int y, int z, Plane p) const
00132 {
00133     const int nx = this->nx.getValue();
00134     const int ny = this->ny.getValue();
00135     const int nz = this->nz.getValue();
00136     if (splitNormals.getValue())
00137     {
00138     if (p == PLANE_UNKNOWN)
00139     {
00140         if (x==0) p = PLANE_X0;
00141         else if (x==nx-1) p = PLANE_X1;
00142         else if (y==0) p = PLANE_Y0;
00143         else if (y==ny-1) p = PLANE_Y1;
00144         else if (z==0) p = PLANE_Z0;
00145         else if (z==nz-1) p = PLANE_Z1;
00146     }
00147     int i = 0;
00148     switch (p)
00149     {
00150     case PLANE_X0: i =                               y+ny*z; break;
00151     case PLANE_X1: i =   ny*nz +   nx*nz +   nx*ny + y+ny*z; break;
00152     case PLANE_Y0: i =   ny*nz                     + x+nx*z; break;
00153     case PLANE_Y1: i = 2*ny*nz +   nx*nz +   nx*ny + x+nx*z; break;
00154     case PLANE_Z0: i =   ny*nz +   nx*nz           + x+nx*y; break;
00155     case PLANE_Z1: i = 2*ny*nz + 2*nx*nz +   nx*ny + x+nx*y; break;
00156     case PLANE_UNKNOWN: break;
00157     }
00158     return i;
00159     }
00160     else if (!internalPoints.getValue() && (nx>1 && ny>1 && nz>1))
00161     {
00162     if (z==0)
00163         return (x+nx*y);
00164     else if (z==nz-1)
00165         return (x+nx*(y+ny));
00166     else
00167     {
00168         int base = nx*ny*2 + (2*nx+2*ny-4)*(z-1);
00169         if (y==0)
00170         return base + x;
00171         else if (y==ny-1)
00172         return base + x + nx;
00173         else if (x==0)
00174         return base + 2*nx + (y-1);
00175         else
00176         return base + 2*nx + (ny-2) + (y-1);
00177     }
00178     }
00179     else
00180     return x+nx*(y+ny*z);
00181 }
00182 
00183 void CubeTopology::updateEdges()
00184 {
00185     SeqEdges& edges = *seqEdges.beginEdit();
00186     const int nx = this->nx.getValue();
00187     const int ny = this->ny.getValue();
00188     const int nz = this->nz.getValue();
00189     edges.clear();
00190     edges.reserve((nx-1)*(2*ny+2*nz-4) + (ny-1)*(2*nx+2*nz-4) + (nz-1)*(2*nx+2*ny-4));
00191     for (int z=0; z<nz; z++)
00192     for (int y=0; y<ny; y++)
00193         for (int x=0; x<nx; x++)
00194         {
00195         // lines along X
00196         if (x<nx-1 && (y==0 || y==ny-1 || z==0 || z==nz-1))
00197             edges.push_back(Edge(point(x,y,z),point(x+1,y,z)));
00198         // lines along Y
00199         if (y<ny-1 && (x==0 || x==nx-1 || z==0 || z==nz-1))
00200             edges.push_back(Edge(point(x,y,z),point(x,y+1,z)));
00201         // lines along Z
00202         if (z<nz-1 && (x==0 || x==nx-1 || y==0 || y==ny-1))
00203             edges.push_back(Edge(point(x,y,z),point(x,y,z+1)));
00204         }
00205     seqEdges.endEdit();
00206 }
00207 
00208 void CubeTopology::updateQuads()
00209 {
00210     seqQuads.beginEdit()->clear();
00211     const int nx = this->nx.getValue();
00212     const int ny = this->ny.getValue();
00213     const int nz = this->nz.getValue();
00214     seqQuads.beginEdit()->reserve((nx-1)*(ny-1)*(nz>1?2:1)+(nx-1)*(nz-1)*(ny>1?2:1)+(ny-1)*(nz-1)*(nx>1?2:1));
00215     // quads along Z=0 plane
00216     for (int z=0, y=0; y<ny-1; y++)
00217     for (int x=0; x<nx-1; x++)
00218         seqQuads.beginEdit()->push_back(Quad(point(x,y,z,PLANE_Z0),point(x,y+1,z,PLANE_Z0),point(x+1,y+1,z,PLANE_Z0),point(x+1,y,z,PLANE_Z0)));
00219     // quads along Z=NZ-1 plane
00220     if (nz > 1)
00221     for (int z=nz-1, y=0; y<ny-1; y++)
00222     for (int x=0; x<nx-1; x++)
00223         seqQuads.beginEdit()->push_back(Quad(point(x,y,z,PLANE_Z1),point(x+1,y,z,PLANE_Z1),point(x+1,y+1,z,PLANE_Z1),point(x,y+1,z,PLANE_Z1)));
00224     // quads along Y=0 plane
00225     for (int y=0, z=0; z<nz-1; z++)
00226     for (int x=0; x<nx-1; x++)
00227         seqQuads.beginEdit()->push_back(Quad(point(x,y,z,PLANE_Y0),point(x+1,y,z,PLANE_Y0),point(x+1,y,z+1,PLANE_Y0),point(x,y,z+1,PLANE_Y0)));
00228     // quads along Y=NY-1 plane
00229     if (ny > 1)
00230     for (int y=ny-1, z=0; z<nz-1; z++)
00231     for (int x=0; x<nx-1; x++)
00232         seqQuads.beginEdit()->push_back(Quad(point(x,y,z,PLANE_Y1),point(x,y,z+1,PLANE_Y1),point(x+1,y,z+1,PLANE_Y1),point(x+1,y,z,PLANE_Y1)));
00233     // quads along X=0 plane
00234     for (int x=0, z=0; z<nz-1; z++)
00235     for (int y=0; y<ny-1; y++)
00236         seqQuads.beginEdit()->push_back(Quad(point(x,y,z,PLANE_X0),point(x,y,z+1,PLANE_X0),point(x,y+1,z+1,PLANE_X0),point(x,y+1,z,PLANE_X0)));
00237     // quads along X=NX-1 plane
00238     if (nx > 1)
00239     for (int x=nx-1, z=0; z<nz-1; z++)
00240     for (int y=0; y<ny-1; y++)
00241         seqQuads.beginEdit()->push_back(Quad(point(x,y,z,PLANE_X1),point(x,y+1,z,PLANE_X1),point(x,y+1,z+1,PLANE_X1),point(x,y,z+1,PLANE_X1)));
00242     
00243     seqQuads.endEdit();
00244 }
00245 
00246 void CubeTopology::setPos(SReal xmin, SReal xmax, SReal ymin, SReal ymax, SReal zmin, SReal zmax)
00247 {
00248     setP0(Vector3(xmin,ymin,zmin));
00249     if (nx.getValue()>1)
00250     setDx(Vector3((xmax-xmin)/(nx.getValue()-1),0,0));
00251     else
00252     setDx(Vector3(0,0,0));
00253     if (ny.getValue()>1)
00254     setDy(Vector3(0,(ymax-ymin)/(ny.getValue()-1),0));
00255     else
00256     setDy(Vector3(0,0,0));
00257     if (nz.getValue()>1)
00258     setDz(Vector3(0,0,(zmax-zmin)/(nz.getValue()-1)));
00259     else
00260     setDz(Vector3(0,0,0));
00261 }
00262 
00263 Vector3 CubeTopology::getPoint(int i) const
00264 {
00265     const int nx = this->nx.getValue();
00266     const int ny = this->ny.getValue();
00267     const int nz = this->nz.getValue();
00268     int x,y,z;
00269     if (splitNormals.getValue())
00270     {
00271     if (i < ny*nz+nx*nz+nx*ny)
00272     {
00273         x = 0;
00274         y = 0;
00275         z = 0;
00276     }
00277     else
00278     {
00279         i -= ny*nz+nx*nz+nx*ny;
00280         x = nx-1;
00281         y = ny-1;
00282         z = nz-1;
00283     }
00284     if (i < ny*nz)
00285     {
00286         y = i % ny;
00287         z = i / ny;
00288     }
00289     else
00290     {
00291         i -= ny*nz;
00292         if (i < nx*nz)
00293         {
00294         x = i % nx;
00295         z = i / nx;
00296         }
00297         else
00298         {
00299         i -= nx*nz;
00300         x = i % nx;
00301         y = i / nx;
00302         }
00303     }
00304     }
00305     else if (!internalPoints.getValue() && (nx>1 && ny>1 && nz>1))
00306     {
00307     const int nxny = nx*ny;
00308     if (i<nxny)
00309     {
00310         x = i%nx; i/=nx;
00311         y = i;
00312         z = 0;
00313     }
00314     else if (i<2*nxny)
00315     {
00316         i -= nxny;
00317         x = i%nx; i/=nx;
00318         y = i;
00319         z = nz-1;
00320     }
00321     else
00322     {
00323         i -= 2*nxny;
00324         const int psize = (2*nx+2*(ny-2));
00325         z = i/psize; i-=z*psize;
00326         z+=1;
00327         if (i < nx)
00328         {
00329         x = i;
00330         y = 0;
00331         }
00332         else if (i < 2*nx)
00333         {
00334         x = i-nx;
00335         y = ny-1;
00336         }
00337         else if (i < 2*nx + (ny-2))
00338         {
00339         x = 0;
00340         y = 1+i-2*nx;
00341         }
00342         else
00343         {
00344         x = nx-1;
00345         y = 1+i-2*nx-(ny-2);
00346         }
00347     }
00348     }
00349     else
00350     {
00351     x = i%nx; i/=nx;
00352     y = i%ny; i/=ny;
00353     z = i;
00354     }
00355     return getPoint(x,y,z);
00356 }
00357 
00358 Vector3 CubeTopology::getPoint(int x, int y, int z) const
00359 {
00360     return p0+dx*x+dy*y+dz*z;
00361 }
00362 
00363 } // namespace topology
00364 
00365 } // namespace component
00366 
00367 } // namespace sofa

Generated on Sun Nov 23 03:42:46 2008 for Sofa by  doxygen 1.5.7.1