00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
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
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
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
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
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
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
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
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
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 }
00364
00365 }
00366
00367 }