ImplicitSurfaceMapping.inl

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 #ifndef SOFA_COMPONENT_MAPPING_IMPLICITSURFACEMAPPING_INL
00026 #define SOFA_COMPONENT_MAPPING_IMPLICITSURFACEMAPPING_INL
00027 
00028 #include <sofa/component/mapping/ImplicitSurfaceMapping.h>
00029 #include <sofa/core/Mapping.inl>
00030 #include <sofa/helper/rmath.h>
00031 #include <map>
00032 #include <list>
00033 
00034 
00035 
00036 namespace sofa
00037 {
00038 
00039 namespace component
00040 {
00041 
00042 namespace mapping
00043 {
00044 
00045 using namespace sofa::defaulttype;
00046 using namespace sofa::helper;
00047 
00048 template <class In, class Out>
00049 void ImplicitSurfaceMapping<In,Out>::init()
00050 {
00051     core::Mapping<In,Out>::init();
00052     topology::MeshTopology::init();
00053 }
00054 
00055 template <class In, class Out>
00056 void ImplicitSurfaceMapping<In,Out>::parse(core::objectmodel::BaseObjectDescription* arg)
00057 {
00058     this->Inherit::parse(arg);
00059      if ( arg->getAttribute("minx") || arg->getAttribute("miny") || arg->getAttribute("minz"))
00060        this->setGridMin(atof(arg->getAttribute("minx","-100.0")),
00061             atof(arg->getAttribute("miny","-100.0")),
00062             atof(arg->getAttribute("minz","-100.0")));
00063      if (arg->getAttribute("maxx") || arg->getAttribute("maxy") || arg->getAttribute("maxz"))
00064        this->setGridMax(atof(arg->getAttribute("maxx","100.0")),
00065             atof(arg->getAttribute("maxy","100.0")),
00066             atof(arg->getAttribute("maxz","100.0")));
00067 }
00068 
00069 template<class Real>
00070 Real sqr(Real r)
00071 {
00072     return r*r;
00073 }
00074 
00075 template <class In, class Out>
00076 void ImplicitSurfaceMapping<In,Out>::apply( OutVecCoord& out, const InVecCoord& in )
00077 {
00078     InReal invStep = (InReal)(1/mStep.getValue());
00079     out.resize(0);
00080     clear();
00081     if (in.size()==0) return;
00082     InReal xmin, xmax;
00083     InReal ymin, ymax;
00084     xmin = xmax = in[0][0]*invStep;
00085     ymin = ymax = in[0][1]*invStep;
00086     const InReal r = (InReal)(getRadius() / mStep.getValue());
00087     std::map<int, std::list< InCoord > > sortParticles;
00088     for (unsigned int ip=0; ip<in.size(); ip++)
00089     {
00090         InCoord c0 = in[ip];
00091         if (c0[0] < (*mGridMin.beginEdit())[0] || c0[0] > (*mGridMax.beginEdit())[0] ||
00092             c0[1] < (*mGridMin.beginEdit())[1] || c0[1] > (*mGridMax.beginEdit())[1] ||
00093             c0[2] < (*mGridMin.beginEdit())[2] || c0[2] > (*mGridMax.beginEdit())[2])
00094             continue;
00095         InCoord c = c0 * invStep;
00096         if (c[0] < xmin)
00097             xmin = c[0];
00098         else if (c[0] > xmax)
00099             xmax = c[0];
00100         if (c[1] < ymin)
00101             ymin = c[1];
00102         else if (c[1] > ymax)
00103             ymax = c[1];
00104         int z0 = rceil(c[2]-r);
00105         int z1 = rfloor(c[2]+r);
00106         for (int z = z0; z < z1; ++z)
00107             sortParticles[z].push_back(c);
00108     }
00109 
00110     const int z0 = sortParticles.begin()->first - 1;
00111     const int nz = sortParticles.rbegin()->first - z0 + 2;
00112     const int y0 = rceil(ymin-r) - 1;
00113     const int ny = rfloor(ymax+r) - y0 + 2;
00114     const int x0 = rceil(xmin-r) - 1;
00115     const int nx = rfloor(xmax+r) - x0 + 2;
00116 
00117     (*planes.beginEdit()).resize(2*nx*ny);
00118     P0 = (*planes.beginEdit()).begin()+0;
00119     P1 = (*planes.beginEdit()).begin()+nx*ny;
00120 
00122     
00123     const OutReal isoval = (OutReal) getIsoValue();
00124 
00125     const int dx = 1;
00126     const int dy = nx;
00127     //const int dz = nx*ny;
00128 
00129     int x,y,z,i,mk;
00130     const int *tri;
00131 
00132     OutReal r2 = (OutReal)sqr(r);
00133     // First plane is all zero
00134     z = 0;
00135     newPlane();
00136     for (z=1;z<nz;z++)
00137     {
00138         newPlane();
00139         
00140         // Compute the data
00141         const std::list<InCoord>& particles = sortParticles[z0+z];
00142         for (typename std::list<InCoord>::const_iterator it = particles.begin(); it != particles.end(); ++it)
00143         {
00144             InCoord c = *it;
00145             int cx0 = rceil(c[0]-r);
00146             int cx1 = rfloor(c[0]+r);
00147             int cy0 = rceil(c[1]-r);
00148             int cy1 = rfloor(c[1]+r);
00149             OutCoord dp2;
00150             dp2[2] = (OutReal)sqr(z0+z-c[2]);
00151             i = (cx0-x0)+(cy0-y0)*nx;
00152             for (int y = cy0 ; y <= cy1 ; y++)
00153             {
00154                 dp2[1] = (OutReal)sqr(y-c[1]);
00155                 int ix = i;
00156                 for (int x = cx0 ; x <= cx1 ; x++, ix++)
00157                 {
00158                     dp2[0] = (OutReal)sqr(x-c[0]);
00159                     OutReal d2 = dp2[0]+dp2[1]+dp2[2];
00160                     if (d2 < r2)
00161                     {
00162                         // Soft object field function from the Wyvill brothers
00163                         // See http://astronomy.swin.edu.au/~pbourke/modelling/implicitsurf/
00164                         d2 /= r2;
00165                         (P1+ix)->data += (1 + (-4*d2*d2*d2 + 17*d2*d2 - 22*d2)/9);
00166                     }
00167                 }
00168                 i += nx;
00169             }
00170         }
00171         
00172         i=0;
00173         int edgecube[12];
00174         const int edgepts[12] = {0,1,0,1,0,1,0,1,2,2,2,2};
00175         typename std::vector<CubeData>::iterator base = (*planes.beginEdit()).begin();
00176         int ip0 = P0-base;
00177         int ip1 = P1-base;
00178         edgecube[0]  = (ip0   -dy);
00179         edgecube[1]  = (ip0      );
00180         edgecube[2]  = (ip0      );
00181         edgecube[3]  = (ip0-dx   );
00182         edgecube[4]  = (ip1   -dy);
00183         edgecube[5]  = (ip1      );
00184         edgecube[6]  = (ip1      );
00185         edgecube[7]  = (ip1-dx   );
00186         edgecube[8]  = (ip1-dx-dy);
00187         edgecube[9]  = (ip1-dy   );
00188         edgecube[10] = (ip1      );
00189         edgecube[11] = (ip1-dx   );
00190 
00191         // First line is all zero
00192         {
00193             y=0;
00194             x=0;
00195             i+=nx;
00196         }
00197         for(y=1;y<ny;y++)
00198         {
00199             // First column is all zero
00200             x=0;
00201             ++i;
00202 
00203             for(x=1;x<nx;x++)
00204             {
00205                 if (((P1+i)->data>isoval)^((P1+i-dx)->data>isoval))
00206                 {
00207                     (P1+i)->p[0] = addPoint<0>(out, x0+x,y0+y,z0+z,(P1+i)->data,(P1+i-dx)->data,isoval);
00208                 }
00209                 if (((P1+i)->data>isoval)^((P1+i-dy)->data>isoval))
00210                 {
00211                     (P1+i)->p[1] = addPoint<1>(out, x0+x,y0+y,z0+z,(P1+i)->data,(P1+i-dy)->data,isoval);
00212                 }
00213                 if (((P1+i)->data>isoval)^((P0+i)->data>isoval))
00214                 {
00215                     (P1+i)->p[2] = addPoint<2>(out, x0+x,y0+y,z0+z,(P1+i)->data,(P0+i)->data,isoval);
00216                 }
00217 
00218                 // All points should now be created
00219 
00220                 if ((P0+i-dx-dy)->data > isoval) mk = 1; else mk=0;
00221                 if ((P0+i   -dy)->data > isoval) mk|= 2;
00222                 if ((P0+i      )->data > isoval) mk|= 4;
00223                 if ((P0+i-dx   )->data > isoval) mk|= 8;
00224                 if ((P1+i-dx-dy)->data > isoval) mk|= 16;
00225                 if ((P1+i   -dy)->data > isoval) mk|= 32;
00226                 if ((P1+i      )->data > isoval) mk|= 64;
00227                 if ((P1+i-dx   )->data > isoval) mk|= 128;
00228 
00229                 tri=sofa::helper::MarchingCubeTriTable[mk];
00230                 while (*tri>=0)
00231                 {
00232                     typename std::vector<CubeData>::iterator b = base+i;
00233                     if (addFace((b+edgecube[tri[0]])->p[edgepts[tri[0]]],
00234                                 (b+edgecube[tri[1]])->p[edgepts[tri[1]]],
00235                                 (b+edgecube[tri[2]])->p[edgepts[tri[2]]], out.size())<0)
00236                     {
00237                         std::cerr << "  mk=0x"<<std::hex<<mk<<std::dec<<" p1="<<tri[0]<<" p2="<<tri[1]<<" p3="<<tri[2]<<std::endl;
00238                         for (int e=0;e<12;e++) std::cerr << "  e"<<e<<"="<<(b+edgecube[e])->p[edgepts[e]];
00239                         std::cerr<<std::endl;
00240                     }
00241                     tri+=3;
00242                 }
00243                 ++i;
00244             }
00245         }
00246     }
00247     //        std::cout << out.size() << " points, "<<seqTriangles.getValue().size()<<" faces."<<std::endl;
00248 }
00249 
00250 template <class In, class Out>
00251 void ImplicitSurfaceMapping<In,Out>::newPlane()
00252 {
00253     CubeData c;
00254     c.p[0] = -1;
00255     c.p[1] = -1;
00256     c.p[2] = -1;
00257     c.data = 0;
00258     typename std::vector<CubeData>::iterator P = P0;
00259     P0 = P1;
00260     P1 = P;
00261     int n = planes.getValue().size()/2;
00262     for (int i=0;i<n;++i,++P)
00263         *P = c;
00264     //plane0.swap(plane1);
00265     //plane1.fill(c);
00266 }
00267 
00268 
00269 template <class In, class Out>
00270 void ImplicitSurfaceMapping<In,Out>::applyJ( OutVecDeriv& /*out*/, const InVecDeriv& /*in*/ )
00271 {
00272 }
00273 
00274 } // namespace mapping
00275 
00276 } // namespace component
00277 
00278 } // namespace sofa
00279 
00280 #endif

Generated on Sun Nov 23 03:32:30 2008 for Sofa by  doxygen 1.5.7.1