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 #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
00128
00129 int x,y,z,i,mk;
00130 const int *tri;
00131
00132 OutReal r2 = (OutReal)sqr(r);
00133
00134 z = 0;
00135 newPlane();
00136 for (z=1;z<nz;z++)
00137 {
00138 newPlane();
00139
00140
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
00163
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
00192 {
00193 y=0;
00194 x=0;
00195 i+=nx;
00196 }
00197 for(y=1;y<ny;y++)
00198 {
00199
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
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
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
00265
00266 }
00267
00268
00269 template <class In, class Out>
00270 void ImplicitSurfaceMapping<In,Out>::applyJ( OutVecDeriv& , const InVecDeriv& )
00271 {
00272 }
00273
00274 }
00275
00276 }
00277
00278 }
00279
00280 #endif