BarycentricMapping.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_BARYCENTRICMAPPING_INL
00026 #define SOFA_COMPONENT_MAPPING_BARYCENTRICMAPPING_INL
00027 
00028 #include <sofa/helper/system/config.h>
00029 #include <sofa/defaulttype/Mat.h>
00030 #include <sofa/component/mapping/BarycentricMapping.h>
00031 #include <sofa/core/componentmodel/behavior/MechanicalMapping.inl>
00032 #include <sofa/helper/gl/template.h>
00033 #include <algorithm>
00034 #include <iostream>
00035 
00036 #include <sofa/core/componentmodel/topology/BaseMeshTopology.h>
00037 #include <sofa/component/topology/RegularGridTopology.h>
00038 #include <sofa/component/topology/SparseGridTopology.h>
00039 
00040 #include <sofa/component/topology/EdgeSetTopologyContainer.h>
00041 #include <sofa/component/topology/TriangleSetTopologyContainer.h>
00042 #include <sofa/component/topology/QuadSetTopologyContainer.h>
00043 #include <sofa/component/topology/TetrahedronSetTopologyContainer.h>
00044 #include <sofa/component/topology/HexahedronSetTopologyContainer.h>
00045 
00046 #include <sofa/component/topology/PointData.h>
00047 #include <sofa/component/topology/PointData.inl>
00048 
00049 #include <sofa/component/topology/HexahedronData.h>
00050 #include <sofa/component/topology/HexahedronData.inl>
00051 
00052 using std::cerr;
00053 using std::endl;
00054 
00055 namespace sofa
00056 {
00057 
00058 namespace component
00059 {
00060 
00061 namespace mapping
00062 {
00063 
00064 using namespace sofa::defaulttype;
00065 
00066 template <class BasicMapping>
00067 BarycentricMapping<BasicMapping>::BarycentricMapping(In* from, Out* to, BaseMeshTopology * topology )
00068 : Inherit(from, to), mapper(NULL) 
00069 {
00070     createMapperFromTopology(topology);
00071 }
00072 
00073 template <class In, class Out>
00074 void BarycentricMapperRegularGridTopology<In,Out>::clear(int reserve)
00075 {
00076     map.clear();
00077     if (reserve>0) map.reserve(reserve);
00078 }
00079 
00080 template <class In, class Out>
00081     int BarycentricMapperRegularGridTopology<In,Out>::addPointInCube(int cubeIndex, const SReal* baryCoords)
00082 {
00083     map.resize(map.size()+1);
00084     CubeData& data = *map.rbegin();
00085     data.in_index = cubeIndex;
00086     data.baryCoords[0] = (Real)baryCoords[0];
00087     data.baryCoords[1] = (Real)baryCoords[1];
00088     data.baryCoords[2] = (Real)baryCoords[2];
00089     return map.size()-1;
00090 }
00091 
00092 template <class In, class Out>
00093 void BarycentricMapperRegularGridTopology<In,Out>::init(const typename Out::VecCoord& out, const typename In::VecCoord& /*in*/)
00094 {
00095   if (map.size() != 0) return;
00096    int outside = 0;
00097    clear(out.size());
00098    for (unsigned int i=0;i<out.size();i++)
00099    {
00100        Vector3 coefs;
00101        int cube = topology->findCube(Vector3(out[i]), coefs[0], coefs[1], coefs[2]);
00102        if (cube==-1)
00103        {
00104            ++outside;
00105        cube = topology->findNearestCube(Vector3(out[i]), coefs[0], coefs[1], coefs[2]);
00106        }
00107        Vector3 baryCoords = coefs;
00108        addPointInCube(cube, baryCoords.ptr());
00109    }
00110 }
00111 
00112 template <class In, class Out>
00113 void BarycentricMapperSparseGridTopology<In,Out>::clear(int reserve)
00114 {
00115     map.clear();
00116     if (reserve>0) map.reserve(reserve);
00117 }
00118 
00119 template <class In, class Out>
00120     int BarycentricMapperSparseGridTopology<In,Out>::addPointInCube(int cubeIndex, const SReal* baryCoords)
00121 {
00122     map.resize(map.size()+1);
00123     CubeData& data = *map.rbegin();
00124     data.in_index = cubeIndex;
00125     data.baryCoords[0] = (Real)baryCoords[0];
00126     data.baryCoords[1] = (Real)baryCoords[1];
00127     data.baryCoords[2] = (Real)baryCoords[2];
00128     return map.size()-1;
00129 }
00130 
00131 template <class In, class Out>
00132 void BarycentricMapperSparseGridTopology<In,Out>::init(const typename Out::VecCoord& out, const typename In::VecCoord& /*in*/)
00133 {
00134     int outside = 0;
00135 
00136     clear(out.size());
00137     for (unsigned int i=0;i<out.size();i++)
00138     {
00139         Vector3 coefs;
00140         int cube = topology->findCube(Vector3(out[i]), coefs[0], coefs[1], coefs[2]);
00141         if (cube==-1)
00142         {
00143             ++outside;
00144             cube = topology->findNearestCube(Vector3(out[i]), coefs[0], coefs[1], coefs[2]);
00145         }
00146         Vector3 baryCoords = coefs;
00147         addPointInCube(cube, baryCoords.ptr());
00148     }
00149 }
00150 
00151 template <class In, class Out>
00152 void BarycentricMapperMeshTopology<In,Out>::clear1d(int reserve)
00153 {
00154     map1d.clear(); if (reserve>0) map1d.reserve(reserve);
00155 }
00156 
00157 template <class In, class Out>
00158 void BarycentricMapperMeshTopology<In,Out>::clear2d(int reserve)
00159 {
00160     map2d.clear(); if (reserve>0) map2d.reserve(reserve);
00161 }
00162 
00163 template <class In, class Out>
00164 void BarycentricMapperMeshTopology<In,Out>::clear3d(int reserve)
00165 {
00166     map3d.clear(); if (reserve>0) map3d.reserve(reserve);
00167 }
00168 
00169 template <class In, class Out>
00170 void BarycentricMapperMeshTopology<In,Out>::clear(int reserve)
00171 {
00172     map1d.clear(); if (reserve>0) map1d.reserve(reserve);
00173     map2d.clear(); if (reserve>0) map2d.reserve(reserve);
00174     map3d.clear(); if (reserve>0) map3d.reserve(reserve);
00175 }
00176 
00177 template <class In, class Out>
00178     int BarycentricMapperMeshTopology<In,Out>::addPointInLine(int lineIndex, const SReal* baryCoords)
00179 {
00180     map1d.resize(map1d.size()+1);
00181     MappingData1D& data = *map1d.rbegin();
00182     data.in_index = lineIndex;
00183     data.baryCoords[0] = (Real)baryCoords[0];
00184     return map1d.size()-1;
00185 }
00186 
00187 template <class In, class Out>
00188     int BarycentricMapperMeshTopology<In,Out>::addPointInTriangle(int triangleIndex, const SReal* baryCoords)
00189 {
00190     map2d.resize(map2d.size()+1);
00191     MappingData2D& data = *map2d.rbegin();
00192     data.in_index = triangleIndex;
00193     data.baryCoords[0] = (Real)baryCoords[0];
00194     data.baryCoords[1] = (Real)baryCoords[1];
00195     return map2d.size()-1;
00196 }
00197 
00198 template <class In, class Out>
00199 int BarycentricMapperMeshTopology<In,Out>::addPointInQuad(int quadIndex, const SReal* baryCoords)
00200 {
00201     map2d.resize(map2d.size()+1);
00202     MappingData2D& data = *map2d.rbegin();
00203     data.in_index = quadIndex + topology->getNbTriangles();
00204     data.baryCoords[0] = (Real)baryCoords[0];
00205     data.baryCoords[1] = (Real)baryCoords[1];
00206     return map2d.size()-1;
00207 }
00208 
00209 template <class In, class Out>
00210 int BarycentricMapperMeshTopology<In,Out>::addPointInTetra(int tetraIndex, const SReal* baryCoords)
00211 {
00212     map3d.resize(map3d.size()+1);
00213     MappingData3D& data = *map3d.rbegin();
00214     data.in_index = tetraIndex;
00215     data.baryCoords[0] = (Real)baryCoords[0];
00216     data.baryCoords[1] = (Real)baryCoords[1];
00217     data.baryCoords[2] = (Real)baryCoords[2];
00218     return map3d.size()-1;
00219 }
00220 
00221 template <class In, class Out>
00222 int BarycentricMapperMeshTopology<In,Out>::addPointInCube(int cubeIndex, const SReal* baryCoords)
00223 {
00224     map3d.resize(map3d.size()+1);
00225     MappingData3D& data = *map3d.rbegin();
00226     data.in_index = cubeIndex + topology->getNbTetras();
00227     data.baryCoords[0] = (Real)baryCoords[0];
00228     data.baryCoords[1] = (Real)baryCoords[1];
00229     data.baryCoords[2] = (Real)baryCoords[2];
00230     return map3d.size()-1;
00231 }
00232 
00233 template <class In, class Out>
00234 int BarycentricMapperMeshTopology<In,Out>::createPointInLine(const typename Out::Coord& p, int lineIndex, const typename In::VecCoord* points)
00235 {
00236     SReal baryCoords[1];
00237     const sofa::core::componentmodel::topology::BaseMeshTopology::Line& elem = topology->getLine(lineIndex);
00238     const typename In::Coord p0 = (*points)[elem[0]];
00239     const typename In::Coord pA = (*points)[elem[1]] - p0;
00240     typename In::Coord pos = p - p0;
00241     baryCoords[0] = ((pos*pA)/pA.norm2());
00242     return this->addPointInLine(lineIndex, baryCoords);
00243 }
00244 
00245 template <class In, class Out>
00246 int BarycentricMapperMeshTopology<In,Out>::createPointInTriangle(const typename Out::Coord& p, int triangleIndex, const typename In::VecCoord* points)
00247 {
00248     SReal baryCoords[2];
00249     const sofa::core::componentmodel::topology::BaseMeshTopology::Triangle& elem = topology->getTriangle(triangleIndex);
00250     const typename In::Coord p0 = (*points)[elem[0]];
00251     const typename In::Coord pA = (*points)[elem[1]] - p0;
00252     const typename In::Coord pB = (*points)[elem[2]] - p0;
00253     typename In::Coord pos = p - p0;
00254     // First project to plane
00255     typename In::Coord normal = cross(pA, pB);
00256     Real norm2 = normal.norm2();
00257     pos -= normal*((pos*normal)/norm2);
00258     baryCoords[0] = (Real)sqrt(cross(pB, pos).norm2() / norm2);
00259     baryCoords[1] = (Real)sqrt(cross(pA, pos).norm2() / norm2);
00260     return this->addPointInTriangle(triangleIndex, baryCoords);
00261 }
00262 
00263 template <class In, class Out>
00264 int BarycentricMapperMeshTopology<In,Out>::createPointInQuad(const typename Out::Coord& p, int quadIndex, const typename In::VecCoord* points)
00265 {
00266     SReal baryCoords[2];
00267     const sofa::core::componentmodel::topology::BaseMeshTopology::Quad& elem = topology->getQuad(quadIndex);
00268     const typename In::Coord p0 = (*points)[elem[0]];
00269     const typename In::Coord pA = (*points)[elem[1]] - p0;
00270     const typename In::Coord pB = (*points)[elem[3]] - p0;
00271     typename In::Coord pos = p - p0;
00272     Mat<3,3,typename In::Real> m,mt,base;
00273     m[0] = pA;
00274     m[1] = pB;
00275     m[2] = cross(pA, pB);
00276     mt.transpose(m);
00277     base.invert(mt);
00278     const typename In::Coord base0 = base[0];
00279     const typename In::Coord base1 = base[1];
00280     baryCoords[0] = base0 * pos;
00281     baryCoords[1] = base1 * pos;
00282     return this->addPointInQuad(quadIndex, baryCoords);
00283 }
00284 
00285 template <class In, class Out>
00286 void BarycentricMapperMeshTopology<In,Out>::init(const typename Out::VecCoord& out, const typename In::VecCoord& in)
00287 {
00288     int outside = 0;
00289     
00290     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqTetras& tetras = topology->getTetras();
00291 #ifdef SOFA_NEW_HEXA
00292     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqHexas& cubes = topology->getHexas();
00293 #else
00294     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqCubes& cubes = topology->getCubes();
00295 #endif
00296     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqTriangles& triangles = topology->getTriangles();
00297     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqQuads& quads = topology->getQuads();
00298     sofa::helper::vector<Matrix3> bases;
00299     sofa::helper::vector<Vector3> centers;
00300     if (tetras.empty() && cubes.empty())
00301     { // no 3D elements -> map on 2D elements
00302         clear2d(out.size()); // reserve space for 2D mapping
00303         int c0 = triangles.size();
00304         bases.resize(triangles.size()+quads.size());
00305         centers.resize(triangles.size()+quads.size());
00306         for (unsigned int t = 0; t < triangles.size(); t++)
00307         {
00308             Mat3x3d m,mt;
00309             m[0] = in[triangles[t][1]]-in[triangles[t][0]];
00310             m[1] = in[triangles[t][2]]-in[triangles[t][0]];
00311             m[2] = cross(m[0],m[1]);
00312             mt.transpose(m);
00313             bases[t].invert(mt);
00314             centers[t] = (in[triangles[t][0]]+in[triangles[t][1]]+in[triangles[t][2]])/3;
00315         }
00316         for (unsigned int c = 0; c < quads.size(); c++)
00317         {
00318             Mat3x3d m,mt;
00319             m[0] = in[quads[c][1]]-in[quads[c][0]];
00320             m[1] = in[quads[c][3]]-in[quads[c][0]];
00321             m[2] = cross(m[0],m[1]);
00322             mt.transpose(m);
00323             bases[c0+c].invert(mt);
00324             centers[c0+c] = (in[quads[c][0]]+in[quads[c][1]]+in[quads[c][2]]+in[quads[c][3]])*0.25;
00325         }
00326         for (unsigned int i=0;i<out.size();i++)
00327         {
00328             Vector3 pos = out[i];
00329             Vector3 coefs;
00330             int index = -1;
00331             double distance = 1e10;
00332             for (unsigned int t = 0; t < triangles.size(); t++)
00333             {
00334                 Vec3d v = bases[t] * (pos - in[triangles[t][0]]);
00335                 double d = std::max(std::max(-v[0],-v[1]),std::max((v[2]<0?-v[2]:v[2])-0.01,v[0]+v[1]-1));
00336                 if (d>0) d = (pos-centers[t]).norm2();
00337                 if (d<distance) { coefs = v; distance = d; index = t; }
00338             }
00339             for (unsigned int c = 0; c < quads.size(); c++)
00340             {
00341                 Vec3d v = bases[c0+c] * (pos - in[quads[c][0]]);
00342                 double d = std::max(std::max(-v[0],-v[1]),std::max(std::max(v[1]-1,v[0]-1),std::max(v[2]-0.01,-v[2]-0.01)));
00343                 if (d>0) d = (pos-centers[c0+c]).norm2();
00344                 if (d<distance) { coefs = v; distance = d; index = c0+c; }
00345             }
00346             if (distance>0)
00347             {
00348                 ++outside;
00349             }
00350             if (index < c0)
00351                 addPointInTriangle(index, coefs.ptr());
00352             else
00353                 addPointInQuad(index-c0, coefs.ptr());
00354         }
00355     }
00356     else
00357     {
00358         clear3d(out.size()); // reserve space for 3D mapping
00359         int c0 = tetras.size();
00360         bases.resize(tetras.size()+cubes.size());
00361         centers.resize(tetras.size()+cubes.size());
00362         for (unsigned int t = 0; t < tetras.size(); t++)
00363         {
00364             Mat3x3d m,mt;
00365             m[0] = in[tetras[t][1]]-in[tetras[t][0]];
00366             m[1] = in[tetras[t][2]]-in[tetras[t][0]];
00367             m[2] = in[tetras[t][3]]-in[tetras[t][0]];
00368             mt.transpose(m);
00369             bases[t].invert(mt);
00370             centers[t] = (in[tetras[t][0]]+in[tetras[t][1]]+in[tetras[t][2]]+in[tetras[t][3]])*0.25;
00371             //std::cout << "Tetra "<<t<<" center="<<centers[t]<<" base="<<m<<std::endl;
00372         }
00373         for (unsigned int c = 0; c < cubes.size(); c++)
00374         {
00375             Mat3x3d m,mt;
00376             m[0] = in[cubes[c][1]]-in[cubes[c][0]];
00377 #ifdef SOFA_NEW_HEXA            
00378             m[1] = in[cubes[c][3]]-in[cubes[c][0]];
00379 #else
00380             m[1] = in[cubes[c][2]]-in[cubes[c][0]];
00381 #endif            
00382             m[2] = in[cubes[c][4]]-in[cubes[c][0]];
00383             mt.transpose(m);
00384             bases[c0+c].invert(mt);
00385             centers[c0+c] = (in[cubes[c][0]]+in[cubes[c][1]]+in[cubes[c][2]]+in[cubes[c][3]]+in[cubes[c][4]]+in[cubes[c][5]]+in[cubes[c][6]]+in[cubes[c][7]])*0.125;
00386         }
00387         for (unsigned int i=0;i<out.size();i++)
00388         {
00389             Vector3 pos = out[i];
00390             Vector3 coefs;
00391             int index = -1;
00392             double distance = 1e10;
00393             for (unsigned int t = 0; t < tetras.size(); t++)
00394             {
00395                 Vector3 v = bases[t] * (pos - in[tetras[t][0]]);
00396                 double d = std::max(std::max(-v[0],-v[1]),std::max(-v[2],v[0]+v[1]+v[2]-1));
00397                 if (d>0) d = (pos-centers[t]).norm2();
00398                 if (d<distance) { coefs = v; distance = d; index = t; }
00399             }
00400             for (unsigned int c = 0; c < cubes.size(); c++)
00401             {
00402                 Vector3 v = bases[c0+c] * (pos - in[cubes[c][0]]);
00403                 double d = std::max(std::max(-v[0],-v[1]),std::max(std::max(-v[2],v[0]-1),std::max(v[1]-1,v[2]-1)));
00404                 if (d>0) d = (pos-centers[c0+c]).norm2();
00405                 if (d<distance) { coefs = v; distance = d; index = c0+c; }
00406             }
00407             if (distance>0)
00408             {
00409                 ++outside;
00410             }
00411             if (index < c0)
00412                 addPointInTetra(index, coefs.ptr());
00413             else
00414                 addPointInCube(index-c0, coefs.ptr());
00415         }
00416     }
00417 }
00418 
00419 
00420 template <class In, class Out>
00421 void BarycentricMapperEdgeSetTopology<In,Out>::clear(int reserve)
00422 {
00423     map.clear(); if (reserve>0) map.reserve(reserve);
00424 }
00425 
00426 
00427 template <class In, class Out>
00428     int BarycentricMapperEdgeSetTopology<In,Out>::addPointInLine(int edgeIndex, const SReal* baryCoords)
00429 {
00430     map.resize(map.size()+1);
00431     MappingData& data = *map.rbegin();
00432     data.in_index = edgeIndex;
00433     data.baryCoords[0] = (Real)baryCoords[0];
00434     return map.size()-1;
00435 }
00436 
00437 template <class In, class Out>
00438 int BarycentricMapperEdgeSetTopology<In,Out>::createPointInLine(const typename Out::Coord& p, int edgeIndex, const typename In::VecCoord* points)
00439 {
00440   SReal baryCoords[1];
00441     const topology::Edge& elem = this->topology->getEdge(edgeIndex);
00442     const typename In::Coord p0 = (*points)[elem[0]];
00443     const typename In::Coord pA = (*points)[elem[1]] - p0;
00444     typename In::Coord pos = p - p0;
00445     baryCoords[0] = dot(pA,pos)/dot(pA,pA);
00446     return this->addPointInLine(edgeIndex, baryCoords);
00447 }
00448 
00449 template <class In, class Out>
00450 void BarycentricMapperEdgeSetTopology<In,Out>::init(const typename Out::VecCoord& /*out*/, const typename In::VecCoord& /*in*/)
00451 {
00452 //  int outside = 0;
00453 //  const sofa::helper::vector<topology::Edge>& edges = this->topology->getEdges();
00454     //TODO: implementation of BarycentricMapperEdgeSetTopology::init
00455 }
00456 
00457 template <class In, class Out>
00458 void BarycentricMapperTriangleSetTopology<In,Out>::clear(int reserve)
00459 {
00460     map.clear(); if (reserve>0) map.reserve(reserve);
00461 }
00462 
00463 template <class In, class Out>
00464     int BarycentricMapperTriangleSetTopology<In,Out>::addPointInTriangle(int triangleIndex, const SReal* baryCoords)
00465 {
00466     map.resize(map.size()+1);
00467     MappingData& data = *map.rbegin();
00468     data.in_index = triangleIndex;
00469     data.baryCoords[0] = (Real)baryCoords[0];
00470     data.baryCoords[1] = (Real)baryCoords[1];
00471     return map.size()-1;
00472 }
00473 
00474 template <class In, class Out>
00475 int BarycentricMapperTriangleSetTopology<In,Out>::createPointInTriangle(const typename Out::Coord& p, int triangleIndex, const typename In::VecCoord* points)
00476 {
00477   SReal baryCoords[2];
00478     const topology::Triangle& elem = this->topology->getTriangle(triangleIndex);
00479     const typename In::Coord p0 = (*points)[elem[0]];
00480     const typename In::Coord pA = (*points)[elem[1]] - p0;
00481     const typename In::Coord pB = (*points)[elem[2]] - p0;
00482     typename In::Coord pos = p - p0;
00483     // First project to plane
00484     typename In::Coord normal = cross(pA, pB);
00485     Real norm2 = normal.norm2();
00486     pos -= normal*((pos*normal)/norm2);
00487     baryCoords[0] = (Real)sqrt(cross(pB, pos).norm2() / norm2);
00488     baryCoords[1] = (Real)sqrt(cross(pA, pos).norm2() / norm2);
00489     return this->addPointInTriangle(triangleIndex, baryCoords);
00490 }
00491 
00492 template <class In, class Out>
00493 void BarycentricMapperTriangleSetTopology<In,Out>::init(const typename Out::VecCoord& out, const typename In::VecCoord& in)
00494 {
00495     int outside = 0;
00496     
00497     const sofa::helper::vector<topology::Triangle>& triangles = this->topology->getTriangles();
00498     sofa::helper::vector<Mat3x3d> bases;
00499     sofa::helper::vector<Vector3> centers;
00500 
00501     // no 3D elements -> map on 2D elements
00502     clear(out.size()); // reserve space for 2D mapping
00503     bases.resize(triangles.size());
00504     centers.resize(triangles.size());
00505 
00506     for (unsigned int t = 0; t < triangles.size(); t++)
00507     {
00508         Mat3x3d m,mt;
00509         m[0] = in[triangles[t][1]]-in[triangles[t][0]];
00510         m[1] = in[triangles[t][2]]-in[triangles[t][0]];
00511         m[2] = cross(m[0],m[1]);
00512         mt.transpose(m);
00513         bases[t].invert(mt);
00514         centers[t] = (in[triangles[t][0]]+in[triangles[t][1]]+in[triangles[t][2]])/3;
00515     }
00516 
00517     for (unsigned int i=0;i<out.size();i++)
00518     {
00519         Vec3d pos = out[i];
00520         Vector3 coefs;
00521         int index = -1;
00522         double distance = 1e10;
00523         for (unsigned int t = 0; t < triangles.size(); t++)
00524         {
00525             Vec3d v = bases[t] * (pos - in[triangles[t][0]]);
00526             double d = std::max(std::max(-v[0],-v[1]),std::max((v[2]<0?-v[2]:v[2])-0.01,v[0]+v[1]-1));
00527             if (d>0) d = (pos-centers[t]).norm2();
00528             if (d<distance) { coefs = v; distance = d; index = t; }
00529         }
00530         if (distance>0)
00531         {
00532             ++outside;
00533         }
00534         addPointInTriangle(index, coefs.ptr());
00535     }   
00536 }
00537 
00538 template <class In, class Out>
00539 void BarycentricMapperQuadSetTopology<In,Out>::clear(int reserve)
00540 {
00541     map.clear(); if (reserve>0) map.reserve(reserve);
00542 }
00543 
00544 template <class In, class Out>
00545     int BarycentricMapperQuadSetTopology<In,Out>::addPointInQuad(int quadIndex, const SReal* baryCoords)
00546 {
00547     map.resize(map.size()+1);
00548     MappingData& data = *map.rbegin();
00549     data.in_index = quadIndex + topology->getNbTriangles();
00550     data.baryCoords[0] = (Real)baryCoords[0];
00551     data.baryCoords[1] = (Real)baryCoords[1];
00552     return map.size()-1;
00553 }
00554 
00555 template <class In, class Out>
00556 int BarycentricMapperQuadSetTopology<In,Out>::createPointInQuad(const typename Out::Coord& p, int quadIndex, const typename In::VecCoord* points)
00557 {
00558   SReal baryCoords[2];
00559     const topology::Quad& elem = this->topology->getQuad(quadIndex);
00560     const typename In::Coord p0 = (*points)[elem[0]];
00561     const typename In::Coord pA = (*points)[elem[1]] - p0;
00562     const typename In::Coord pB = (*points)[elem[3]] - p0;
00563     typename In::Coord pos = p - p0;
00564     Mat<3,3,typename In::Real> m,mt,base;
00565     m[0] = pA;
00566     m[1] = pB;
00567     m[2] = cross(pA, pB);
00568     mt.transpose(m);
00569     base.invert(mt);
00570     const typename In::Coord base0 = base[0];
00571     const typename In::Coord base1 = base[1];
00572     baryCoords[0] = base0 * pos;
00573     baryCoords[1] = base1 * pos;
00574     return this->addPointInQuad(quadIndex, baryCoords);
00575 }
00576 
00577 template <class In, class Out>
00578 void BarycentricMapperQuadSetTopology<In,Out>::init(const typename Out::VecCoord& out, const typename In::VecCoord& in)
00579 {
00580     int outside = 0;
00581     const sofa::helper::vector<topology::Quad>& quads = this->topology->getQuads();
00582     
00583     sofa::helper::vector<Matrix3> bases;
00584     sofa::helper::vector<Vector3> centers;
00585 
00586     clear(out.size()); 
00587     bases.resize(quads.size());
00588     centers.resize(quads.size());
00589 
00590     for (unsigned int c = 0; c < quads.size(); c++)
00591     {
00592         Mat3x3d m,mt;
00593         m[0] = in[quads[c][1]]-in[quads[c][0]];
00594         m[1] = in[quads[c][3]]-in[quads[c][0]];
00595         m[2] = cross(m[0],m[1]);
00596         mt.transpose(m);
00597         bases[c].invert(mt);
00598         centers[c] = (in[quads[c][0]]+in[quads[c][1]]+in[quads[c][2]]+in[quads[c][3]])*0.25;
00599     }
00600 
00601     for (unsigned int i=0;i<out.size();i++)
00602     {
00603         Vec3d pos = out[i];
00604         Vector3 coefs;
00605         int index = -1;
00606         double distance = 1e10;
00607         for (unsigned int c = 0; c < quads.size(); c++)
00608         {
00609             Vec3d v = bases[c] * (pos - in[quads[c][0]]);
00610             double d = std::max(std::max(-v[0],-v[1]),std::max(std::max(v[1]-1,v[0]-1),std::max(v[2]-0.01,-v[2]-0.01)));
00611             if (d>0) d = (pos-centers[c]).norm2();
00612             if (d<distance) { coefs = v; distance = d; index = c; }
00613         }
00614         if (distance>0)
00615         {
00616             ++outside;
00617         }
00618         addPointInQuad(index, coefs.ptr());
00619     }   
00620 }
00621 
00622 template <class In, class Out>
00623 void BarycentricMapperTetrahedronSetTopology<In,Out>::clear(int reserve)
00624 {
00625     map.clear(); if (reserve>0) map.reserve(reserve);
00626 }
00627 
00628 template <class In, class Out>
00629     int BarycentricMapperTetrahedronSetTopology<In,Out>::addPointInTetra(int tetraIndex, const SReal* baryCoords)
00630 {
00631     map.resize(map.size()+1);
00632     MappingData& data = *map.rbegin();
00633     data.in_index = tetraIndex;
00634     data.baryCoords[0] = (Real)baryCoords[0];
00635     data.baryCoords[1] = (Real)baryCoords[1];
00636     data.baryCoords[2] = (Real)baryCoords[2];
00637     return map.size()-1;
00638 }
00639 
00640 //template <class In, class Out>
00641 //int BarycentricMapperTetrahedronSetTopology<In,Out>::createPointInTetra(const typename Out::Coord& p, int index, const typename In::VecCoord* points)
00642 //{
00643 //  //TODO: add implementation
00644 //}
00645 
00646 template <class In, class Out>
00647 void BarycentricMapperTetrahedronSetTopology<In,Out>::init(const typename Out::VecCoord& out, const typename In::VecCoord& in)
00648 {
00649     int outside = 0;
00650     const sofa::helper::vector<topology::Tetrahedron>& tetras = this->topology->getTetras();
00651 
00652     sofa::helper::vector<Matrix3> bases;
00653     sofa::helper::vector<Vector3> centers;
00654 
00655     clear(out.size());
00656     bases.resize(tetras.size());
00657     centers.resize(tetras.size());
00658     for (unsigned int t = 0; t < tetras.size(); t++)
00659     {
00660         Mat3x3d m,mt;
00661         m[0] = in[tetras[t][1]]-in[tetras[t][0]];
00662         m[1] = in[tetras[t][2]]-in[tetras[t][0]];
00663         m[2] = in[tetras[t][3]]-in[tetras[t][0]];
00664         mt.transpose(m);
00665         bases[t].invert(mt);
00666         centers[t] = (in[tetras[t][0]]+in[tetras[t][1]]+in[tetras[t][2]]+in[tetras[t][3]])*0.25;
00667     }
00668 
00669     for (unsigned int i=0;i<out.size();i++)
00670     {
00671         Vec3d pos = out[i];
00672         Vector3 coefs;
00673         int index = -1;
00674         double distance = 1e10;
00675         for (unsigned int t = 0; t < tetras.size(); t++)
00676         {
00677             Vec3d v = bases[t] * (pos - in[tetras[t][0]]);
00678             double d = std::max(std::max(-v[0],-v[1]),std::max(-v[2],v[0]+v[1]+v[2]-1));
00679             if (d>0) d = (pos-centers[t]).norm2();
00680             if (d<distance) { coefs = v; distance = d; index = t; }
00681         }
00682         if (distance>0)
00683         {
00684             ++outside;
00685         }
00686         addPointInTetra(index, coefs.ptr());
00687     }
00688 }
00689 
00690 template <class In, class Out>
00691 void BarycentricMapperHexahedronSetTopology<In,Out>::clear(int reserve)
00692 {
00693     map.clear(); if (reserve>0) map.reserve(reserve);
00694     hexahedronData.clear();
00695 }
00696 
00697 template <class In, class Out>
00698     int BarycentricMapperHexahedronSetTopology<In,Out>::addPointInCube(int cubeIndex, const SReal* baryCoords)
00699 {
00700     map.resize(map.size()+1);
00701     MappingData& data = *map.rbegin();
00702     data.in_index = cubeIndex + topology->getNbTetras();
00703     data.baryCoords[0] = (Real)baryCoords[0];
00704     data.baryCoords[1] = (Real)baryCoords[1];
00705     data.baryCoords[2] = (Real)baryCoords[2];
00706     return map.size()-1;
00707 }
00708 
00709 template <class In, class Out>
00710 void BarycentricMapperHexahedronSetTopology<In,Out>::init(const typename Out::VecCoord& out, const typename In::VecCoord& in)
00711 {
00712     const sofa::helper::vector<topology::Hexahedron>& cubes = this->topology->getHexas();
00713 
00714     clear(out.size());
00715 
00716     hexahedronData.resize(cubes.size());
00717 
00718     for (unsigned int c = 0; c < cubes.size(); c++)
00719     {
00720         Mat3x3d m,mt;
00721         const Vector3 origin = in[cubes[c][0]];
00722         m[0] = in[cubes[c][1]]-origin;
00723         m[1] = in[cubes[c][3]]-origin;
00724         m[2] = in[cubes[c][4]]-origin;
00725         mt.transpose(m);
00726         hexahedronData[c].origin = origin;
00727         hexahedronData[c].base.invert(mt);
00728         hexahedronData[c].center = (in[cubes[c][0]]+in[cubes[c][1]]+in[cubes[c][2]]+in[cubes[c][3]]
00729                                     +in[cubes[c][4]]+in[cubes[c][5]]+in[cubes[c][6]]+in[cubes[c][7]])*0.125;
00730     }
00731 
00732     for (unsigned int i=0;i<out.size();i++)
00733     {
00734         // find nearest cell
00735         Vector3 coefs;
00736         int index=-1;
00737         double distance = 1e10;
00738         Vector3 pos = out[i];
00739         for (unsigned int c = 0; c < cubes.size(); c++)
00740         {
00741             const Vec3d v = hexahedronData[c].base * (pos - hexahedronData[c].origin);
00742             double d = std::max(std::max(-v[0],-v[1]), std::max(std::max(-v[2],v[0]-1), std::max(v[1]-1,v[2]-1)));
00743             if (d>0) 
00744                 d = (pos-hexahedronData[c].center).norm2();
00745             if (d<distance) 
00746             { 
00747                 coefs = v; 
00748                 distance = d; 
00749                 index = c; 
00750             }
00751         }
00752         if(index != -1)
00753             addPointInCube(index, coefs.ptr());
00754     }
00755 }
00756 
00757 template <class BasicMapping>
00758 void BarycentricMapping<BasicMapping>::createMapperFromTopology(BaseMeshTopology * topology)
00759 {
00760     mapper = NULL;
00761 
00762     core::componentmodel::topology::TopologyContainer* topoCont2;
00763     this->fromModel->getContext()->get(topoCont2);
00764 
00765     if (topoCont2!=NULL)
00766     {
00767 
00768         topology::HexahedronSetTopologyContainer* t1 = dynamic_cast<topology::HexahedronSetTopologyContainer*>(topoCont2);
00769         if(t1 != NULL)
00770         {
00771             typedef BarycentricMapperHexahedronSetTopology<InDataTypes, OutDataTypes> HexahedronSetMapper;
00772             mapper = new HexahedronSetMapper(topology_from);
00773         }
00774         else
00775         {
00776             topology::TetrahedronSetTopologyContainer* t2 = dynamic_cast<topology::TetrahedronSetTopologyContainer*>(topoCont2);
00777             if(t2 != NULL)
00778             {
00779                 typedef BarycentricMapperTetrahedronSetTopology<InDataTypes, OutDataTypes> TetrahedronSetMapper;
00780                 mapper = new TetrahedronSetMapper(topology_from);
00781             }
00782             else
00783             {
00784                 topology::QuadSetTopologyContainer* t3 = dynamic_cast<topology::QuadSetTopologyContainer*>(topoCont2);
00785                 if(t3 != NULL)
00786                 {
00787                     typedef BarycentricMapperQuadSetTopology<InDataTypes, OutDataTypes> QuadSetMapper;
00788                     mapper = new QuadSetMapper(topology_from);
00789                 }
00790                 else
00791                 {
00792                     topology::TriangleSetTopologyContainer* t4 = dynamic_cast<topology::TriangleSetTopologyContainer*>(topoCont2);
00793                     if (t4 != NULL)
00794                     {
00795                         typedef BarycentricMapperTriangleSetTopology<InDataTypes, OutDataTypes> TriangleSetMapper;
00796                         mapper = new TriangleSetMapper(topology_from);
00797                     }
00798                     else
00799                     {
00800                         topology::EdgeSetTopologyContainer* t5 = dynamic_cast<topology::EdgeSetTopologyContainer*>(topoCont2);
00801                         if(t5 != NULL)
00802                         {
00803                             typedef BarycentricMapperEdgeSetTopology<InDataTypes, OutDataTypes> EdgeSetMapper;
00804                             mapper = new EdgeSetMapper(topology_from);
00805                         }
00806                     }
00807                 }
00808             }
00809         }
00810     }
00811     else
00812     {
00813         topology::RegularGridTopology* t2 = dynamic_cast<topology::RegularGridTopology*>(topology);
00814         if (t2!=NULL)
00815         {
00816             typedef BarycentricMapperRegularGridTopology<InDataTypes, OutDataTypes> RegularGridMapper;
00817                 if (f_grid->beginEdit()->isEmpty())
00818             {                        
00819               f_grid->setValue(RegularGridMapper(t2));
00820               mapper = f_grid->beginEdit();
00821             }
00822             else 
00823             {             
00824               f_grid->beginEdit()->setTopology(t2);
00825               this->mapper = f_grid->beginEdit();   
00826             }
00827         }
00828         else
00829         {
00830             topology::SparseGridTopology* t4 = dynamic_cast<topology::SparseGridTopology*>(topology);
00831             if (t4!=NULL)
00832             {
00833                 typedef BarycentricMapperSparseGridTopology<InDataTypes, OutDataTypes> SparseGridMapper;
00834                 mapper = new SparseGridMapper(t4);
00835             }
00836             else // generic MeshTopology
00837             {
00838                 typedef BarycentricMapperMeshTopology<InDataTypes, OutDataTypes> MeshMapper;
00839                 topology::BaseMeshTopology* t3 = dynamic_cast<topology::BaseMeshTopology*>(topology);
00840                 mapper = new MeshMapper(t3);
00841             }
00842         }
00843     }
00844 }
00845 
00846 template <class BasicMapping>
00847 void BarycentricMapping<BasicMapping>::init()
00848 { 
00849     topology_from = this->fromModel->getContext()->getMeshTopology();
00850     topology_to = this->toModel->getContext()->getMeshTopology();
00851 
00852     f_grid->beginEdit();
00853     if(mapper == NULL) // try to create a mapper according to the topology of the In model
00854     {               
00855         if (topology_from!=NULL)
00856         {
00857             createMapperFromTopology(topology_from);
00858         } 
00859     } 
00860 
00861     if (mapper != NULL)
00862     {
00863         mapper->init(*this->toModel->getX(), *this->fromModel->getX());
00864     }
00865     else
00866     {
00867         std::cerr << "ERROR: Barycentric mapping does not understand topology."<<std::endl;
00868     }
00869 
00870     this->BasicMapping::init();
00871     
00872 }
00873 
00874 template <class BasicMapping>
00875 void BarycentricMapping<BasicMapping>::apply( typename Out::VecCoord& out, const typename In::VecCoord& in )
00876 {
00877     if (mapper!=NULL) mapper->apply(out, in);
00878 }
00879 
00880 template <class In, class Out>
00881 void BarycentricMapperRegularGridTopology<In,Out>::apply( typename Out::VecCoord& out, const typename In::VecCoord& in )
00882 {
00883     out.resize(map.size());
00884     for(unsigned int i=0;i<map.size();i++)
00885     {
00886 #ifdef SOFA_NEW_HEXA
00887         const topology::RegularGridTopology::Hexa cube = this->topology->getHexaCopy(this->map[i].in_index);
00888 #else
00889         const topology::RegularGridTopology::Cube cube = this->topology->getCubeCopy(this->map[i].in_index);
00890 #endif
00891         const Real fx = map[i].baryCoords[0];
00892         const Real fy = map[i].baryCoords[1];
00893         const Real fz = map[i].baryCoords[2];
00894         out[i] = in[cube[0]] * ((1-fx) * (1-fy) * (1-fz))
00895                + in[cube[1]] * ((  fx) * (1-fy) * (1-fz))
00896 #ifdef SOFA_NEW_HEXA
00897                + in[cube[3]] * ((1-fx) * (  fy) * (1-fz))
00898                + in[cube[2]] * ((  fx) * (  fy) * (1-fz))
00899 #else
00900                + in[cube[2]] * ((1-fx) * (  fy) * (1-fz))
00901                + in[cube[3]] * ((  fx) * (  fy) * (1-fz))
00902 #endif
00903                + in[cube[4]] * ((1-fx) * (1-fy) * (  fz))
00904                + in[cube[5]] * ((  fx) * (1-fy) * (  fz))
00905 #ifdef SOFA_NEW_HEXA
00906                + in[cube[7]] * ((1-fx) * (  fy) * (  fz))
00907                + in[cube[6]] * ((  fx) * (  fy) * (  fz));
00908 #else
00909                + in[cube[6]] * ((1-fx) * (  fy) * (  fz))
00910                + in[cube[7]] * ((  fx) * (  fy) * (  fz));
00911 #endif
00912     }
00913 }
00914 
00915 template <class In, class Out>
00916 void BarycentricMapperSparseGridTopology<In,Out>::apply( typename Out::VecCoord& out, const typename In::VecCoord& in )
00917 {
00918     out.resize(map.size());
00919     for(unsigned int i=0;i<map.size();i++)
00920     {
00921 #ifdef SOFA_NEW_HEXA        
00922         const topology::SparseGridTopology::Hexa cube = this->topology->getHexa(this->map[i].in_index);
00923 #else
00924         const topology::SparseGridTopology::Cube cube = this->topology->getCube(this->map[i].in_index);
00925 #endif
00926         const Real fx = map[i].baryCoords[0];
00927         const Real fy = map[i].baryCoords[1];
00928         const Real fz = map[i].baryCoords[2];
00929         out[i] = in[cube[0]] * ((1-fx) * (1-fy) * (1-fz))
00930                 + in[cube[1]] * ((  fx) * (1-fy) * (1-fz))
00931 #ifdef SOFA_NEW_HEXA
00932                 + in[cube[3]] * ((1-fx) * (  fy) * (1-fz))
00933                 + in[cube[2]] * ((  fx) * (  fy) * (1-fz))
00934 #else
00935                 + in[cube[2]] * ((1-fx) * (  fy) * (1-fz))
00936                 + in[cube[3]] * ((  fx) * (  fy) * (1-fz))
00937 #endif
00938                 + in[cube[4]] * ((1-fx) * (1-fy) * (  fz))
00939                 + in[cube[5]] * ((  fx) * (1-fy) * (  fz))
00940 #ifdef SOFA_NEW_HEXA
00941                 + in[cube[7]] * ((1-fx) * (  fy) * (  fz))
00942                 + in[cube[6]] * ((  fx) * (  fy) * (  fz));
00943 #else
00944                 + in[cube[6]] * ((1-fx) * (  fy) * (  fz))
00945                 + in[cube[7]] * ((  fx) * (  fy) * (  fz));
00946 #endif
00947     }
00948 }
00949 
00950 template <class In, class Out>
00951 void BarycentricMapperMeshTopology<In,Out>::apply( typename Out::VecCoord& out, const typename In::VecCoord& in )
00952 {
00953     out.resize(map1d.size()+map2d.size()+map3d.size());
00954     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqLines& lines = this->topology->getLines();
00955     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqTriangles& triangles = this->topology->getTriangles();
00956     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqQuads& quads = this->topology->getQuads();
00957     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqTetras& tetras = this->topology->getTetras();
00958 #ifdef SOFA_NEW_HEXA
00959     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqHexas& cubes = this->topology->getHexas();
00960 #else
00961     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqCubes& cubes = this->topology->getCubes();
00962 #endif
00963     // 1D elements
00964     {
00965         for(unsigned int i=0;i<map1d.size();i++)
00966         {
00967             const Real fx = map1d[i].baryCoords[0];
00968             int index = map1d[i].in_index;
00969             {
00970                 const sofa::core::componentmodel::topology::BaseMeshTopology::Line& line = lines[index];
00971                 out[i] = in[line[0]] * (1-fx)
00972                        + in[line[1]] * fx;
00973             }
00974         }
00975     }
00976     // 2D elements
00977     {
00978         const int i0 = map1d.size();
00979         const int c0 = triangles.size();
00980         for(unsigned int i=0;i<map2d.size();i++)
00981         {
00982             const Real fx = map2d[i].baryCoords[0];
00983             const Real fy = map2d[i].baryCoords[1];
00984             int index = map2d[i].in_index;
00985             if (index<c0)
00986             {
00987                 const sofa::core::componentmodel::topology::BaseMeshTopology::Triangle& triangle = triangles[index];
00988                 out[i+i0] = in[triangle[0]] * (1-fx-fy)
00989                           + in[triangle[1]] * fx
00990                           + in[triangle[2]] * fy;
00991             }
00992             else
00993             {
00994                 const sofa::core::componentmodel::topology::BaseMeshTopology::Quad& quad = quads[index-c0];
00995                 out[i+i0] = in[quad[0]] * ((1-fx) * (1-fy))
00996                           + in[quad[1]] * ((  fx) * (1-fy))
00997                           + in[quad[3]] * ((1-fx) * (  fy))
00998                           + in[quad[2]] * ((  fx) * (  fy));
00999             }
01000         }
01001     }
01002     // 3D elements
01003     {
01004         const int i0 = map1d.size() + map2d.size();
01005         const int c0 = tetras.size();
01006         for(unsigned int i=0;i<map3d.size();i++)
01007         {
01008             const Real fx = map3d[i].baryCoords[0];
01009             const Real fy = map3d[i].baryCoords[1];
01010             const Real fz = map3d[i].baryCoords[2];
01011             int index = map3d[i].in_index;
01012             if (index<c0)
01013             {
01014                 const sofa::core::componentmodel::topology::BaseMeshTopology::Tetra& tetra = tetras[index];
01015                 out[i+i0] = in[tetra[0]] * (1-fx-fy-fz)
01016                           + in[tetra[1]] * fx
01017                           + in[tetra[2]] * fy
01018                           + in[tetra[3]] * fz;
01019             }
01020             else
01021             {
01022 #ifdef SOFA_NEW_HEXA                
01023                 const sofa::core::componentmodel::topology::BaseMeshTopology::Hexa& cube = cubes[index-c0];
01024 #else
01025                 const sofa::core::componentmodel::topology::BaseMeshTopology::Cube& cube = cubes[index-c0];
01026 #endif
01027                 out[i+i0] = in[cube[0]] * ((1-fx) * (1-fy) * (1-fz))
01028                           + in[cube[1]] * ((  fx) * (1-fy) * (1-fz))
01029 #ifdef SOFA_NEW_HEXA                
01030                           + in[cube[3]] * ((1-fx) * (  fy) * (1-fz))
01031                           + in[cube[2]] * ((  fx) * (  fy) * (1-fz))
01032 #else
01033                           + in[cube[2]] * ((1-fx) * (  fy) * (1-fz))
01034                           + in[cube[3]] * ((  fx) * (  fy) * (1-fz))
01035 #endif
01036                           + in[cube[4]] * ((1-fx) * (1-fy) * (  fz))
01037                           + in[cube[5]] * ((  fx) * (1-fy) * (  fz))
01038 #ifdef SOFA_NEW_HEXA
01039                           + in[cube[7]] * ((1-fx) * (  fy) * (  fz))
01040                           + in[cube[6]] * ((  fx) * (  fy) * (  fz));
01041 #else
01042                           + in[cube[6]] * ((1-fx) * (  fy) * (  fz))
01043                           + in[cube[7]] * ((  fx) * (  fy) * (  fz));
01044 #endif                          
01045             }
01046         }
01047     }
01048 }
01049 
01050 template <class In, class Out>
01051 void BarycentricMapperEdgeSetTopology<In,Out>::apply( typename Out::VecCoord& out, const typename In::VecCoord& in )
01052 {
01053     out.resize(map.size());
01054     const sofa::helper::vector<topology::Edge>& edges = this->topology->getEdges();
01055     // 2D elements
01056     for(unsigned int i=0;i<map.size();i++)
01057     {
01058         const Real fx = map[i].baryCoords[0];
01059         int index = map[i].in_index;
01060         const topology::Edge& edge = edges[index];
01061         out[i] = in[edge[0]] * (1-fx)
01062                + in[edge[1]] * fx;
01063     }
01064 }
01065 
01066 template <class In, class Out>
01067 void BarycentricMapperTriangleSetTopology<In,Out>::apply( typename Out::VecCoord& out, const typename In::VecCoord& in )
01068 {
01069     out.resize(map.size());
01070     const sofa::helper::vector<topology::Triangle>& triangles = this->topology->getTriangles();
01071     for(unsigned int i=0;i<map.size();i++)
01072     {
01073         const Real fx = map[i].baryCoords[0];
01074         const Real fy = map[i].baryCoords[1];
01075         int index = map[i].in_index;
01076         const topology::Triangle& triangle = triangles[index];
01077         out[i] = in[triangle[0]] * (1-fx-fy)
01078                + in[triangle[1]] * fx
01079                + in[triangle[2]] * fy;
01080     }
01081 }
01082 
01083 template <class In, class Out>
01084 void BarycentricMapperQuadSetTopology<In,Out>::apply( typename Out::VecCoord& out, const typename In::VecCoord& in )
01085 {
01086     out.resize(map.size());
01087     const sofa::helper::vector<topology::Quad>& quads = this->topology->getQuads();
01088     for(unsigned int i=0;i<map.size();i++)
01089     {
01090         const Real fx = map[i].baryCoords[0];
01091         const Real fy = map[i].baryCoords[1];
01092         int index = map[i].in_index;
01093         const topology::Quad& quad = quads[index];
01094         out[i] = in[quad[0]] * ((1-fx) * (1-fy))
01095               + in[quad[1]] * ((  fx) * (1-fy))
01096               + in[quad[3]] * ((1-fx) * (  fy))
01097               + in[quad[2]] * ((  fx) * (  fy));
01098     }
01099 }
01100 
01101 template <class In, class Out>
01102 void BarycentricMapperTetrahedronSetTopology<In,Out>::apply( typename Out::VecCoord& out, const typename In::VecCoord& in )
01103 {
01104     out.resize(map.size());
01105     const sofa::helper::vector<topology::Tetrahedron>& tetras = this->topology->getTetras();
01106     for(unsigned int i=0;i<map.size();i++)
01107     {
01108         const Real fx = map[i].baryCoords[0];
01109         const Real fy = map[i].baryCoords[1];
01110         const Real fz = map[i].baryCoords[2];
01111         int index = map[i].in_index;
01112         const topology::Tetrahedron& tetra = tetras[index];
01113         out[i] = in[tetra[0]] * (1-fx-fy-fz)
01114               + in[tetra[1]] * fx
01115               + in[tetra[2]] * fy
01116               + in[tetra[3]] * fz;
01117     }
01118     //cerr<<"BarycentricMapperTetrahedronSetTopology<In,Out>::apply, in = "<<in<<endl;
01119     //cerr<<"BarycentricMapperTetrahedronSetTopology<In,Out>::apply, out = "<<out<<endl;
01120 }
01121 
01122 template <class In, class Out>
01123 void BarycentricMapperHexahedronSetTopology<In,Out>::apply( typename Out::VecCoord& out, const typename In::VecCoord& in )
01124 {
01125     out.resize(map.size());
01126     const sofa::helper::vector<topology::Hexahedron>& cubes = this->topology->getHexas();
01127     for(unsigned int i=0;i<map.size();i++)
01128     {
01129         const Real fx = map[i].baryCoords[0];
01130         const Real fy = map[i].baryCoords[1];
01131         const Real fz = map[i].baryCoords[2];
01132         int index = map[i].in_index;
01133         const topology::Hexahedron& cube = cubes[index];
01134         out[i] = in[cube[0]] * ((1-fx) * (1-fy) * (1-fz))
01135               + in[cube[1]] * ((  fx) * (1-fy) * (1-fz))
01136               + in[cube[3]] * ((1-fx) * (  fy) * (1-fz))
01137               + in[cube[2]] * ((  fx) * (  fy) * (1-fz))
01138               + in[cube[4]] * ((1-fx) * (1-fy) * (  fz))
01139               + in[cube[5]] * ((  fx) * (1-fy) * (  fz))
01140               + in[cube[7]] * ((1-fx) * (  fy) * (  fz))
01141               + in[cube[6]] * ((  fx) * (  fy) * (  fz));
01142     }
01143 }
01144 
01145 template <class BasicMapping>
01146 void BarycentricMapping<BasicMapping>::applyJ( typename Out::VecDeriv& out, const typename In::VecDeriv& in )
01147 {
01148     out.resize(this->toModel->getX()->size());
01149     if (mapper!=NULL) mapper->applyJ(out, in);
01150 }
01151 
01152 template <class In, class Out>
01153 void BarycentricMapperRegularGridTopology<In,Out>::applyJ( typename Out::VecDeriv& out, const typename In::VecDeriv& in )
01154 {
01155     for(unsigned int i=0;i<map.size();i++)
01156     {
01157 #ifdef SOFA_NEW_HEXA
01158         const topology::RegularGridTopology::Hexa cube = this->topology->getHexaCopy(this->map[i].in_index);
01159 #else
01160         const topology::RegularGridTopology::Cube cube = this->topology->getCubeCopy(this->map[i].in_index);
01161 #endif
01162         const Real fx = map[i].baryCoords[0];
01163         const Real fy = map[i].baryCoords[1];
01164         const Real fz = map[i].baryCoords[2];
01165         out[i] = in[cube[0]] * ((1-fx) * (1-fy) * (1-fz))
01166                + in[cube[1]] * ((  fx) * (1-fy) * (1-fz))
01167 #ifdef SOFA_NEW_HEXA   
01168                + in[cube[3]] * ((1-fx) * (  fy) * (1-fz))
01169                + in[cube[2]] * ((  fx) * (  fy) * (1-fz))
01170 #else
01171                + in[cube[2]] * ((1-fx) * (  fy) * (1-fz))
01172                + in[cube[3]] * ((  fx) * (  fy) * (1-fz))
01173 #endif
01174                + in[cube[4]] * ((1-fx) * (1-fy) * (  fz))
01175                + in[cube[5]] * ((  fx) * (1-fy) * (  fz))
01176 #ifdef SOFA_NEW_HEXA
01177                + in[cube[7]] * ((1-fx) * (  fy) * (  fz))
01178                + in[cube[6]] * ((  fx) * (  fy) * (  fz));
01179 #else
01180                + in[cube[6]] * ((1-fx) * (  fy) * (  fz))
01181                + in[cube[7]] * ((  fx) * (  fy) * (  fz));
01182 #endif               
01183     }
01184 }
01185 
01186 template <class In, class Out>
01187 void BarycentricMapperSparseGridTopology<In,Out>::applyJ( typename Out::VecDeriv& out, const typename In::VecDeriv& in )
01188 {
01189     for(unsigned int i=0;i<map.size();i++)
01190     {
01191 #ifdef SOFA_NEW_HEXA        
01192         const topology::SparseGridTopology::Hexa cube = this->topology->getHexa(this->map[i].in_index);
01193 #else
01194         const topology::SparseGridTopology::Cube cube = this->topology->getCube(this->map[i].in_index);
01195 #endif
01196         const Real fx = map[i].baryCoords[0];
01197         const Real fy = map[i].baryCoords[1];
01198         const Real fz = map[i].baryCoords[2];
01199         out[i] = in[cube[0]] * ((1-fx) * (1-fy) * (1-fz))
01200                 + in[cube[1]] * ((  fx) * (1-fy) * (1-fz))
01201 #ifdef SOFA_NEW_HEXA                
01202                 + in[cube[3]] * ((1-fx) * (  fy) * (1-fz))
01203                 + in[cube[2]] * ((  fx) * (  fy) * (1-fz))
01204 #else
01205                 + in[cube[2]] * ((1-fx) * (  fy) * (1-fz))
01206                 + in[cube[3]] * ((  fx) * (  fy) * (1-fz))
01207 #endif              
01208                 + in[cube[4]] * ((1-fx) * (1-fy) * (  fz))
01209                 + in[cube[5]] * ((  fx) * (1-fy) * (  fz))
01210 #ifdef SOFA_NEW_HEXA
01211                 + in[cube[7]] * ((1-fx) * (  fy) * (  fz))
01212                 + in[cube[6]] * ((  fx) * (  fy) * (  fz));
01213 #else
01214                 + in[cube[6]] * ((1-fx) * (  fy) * (  fz))
01215                 + in[cube[7]] * ((  fx) * (  fy) * (  fz));
01216 #endif              
01217     }
01218 }
01219 
01220 template <class In, class Out>
01221 void BarycentricMapperMeshTopology<In,Out>::applyJ( typename Out::VecDeriv& out, const typename In::VecDeriv& in )
01222 {
01223     //cerr<<"    BarycentricMapping<BasicMapping>::MeshMapper::applyJ"<<endl;
01224     out.resize(map1d.size()+map2d.size()+map3d.size());
01225     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqLines& lines = this->topology->getLines();
01226     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqTriangles& triangles = this->topology->getTriangles();
01227     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqQuads& quads = this->topology->getQuads();
01228     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqTetras& tetras = this->topology->getTetras();
01229 #ifdef SOFA_NEW_HEXA 
01230     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqHexas& cubes = this->topology->getHexas();
01231 #else
01232     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqCubes& cubes = this->topology->getCubes();
01233 #endif
01234     // 1D elements
01235     {
01236         for(unsigned int i=0;i<map1d.size();i++)
01237         {
01238             const Real fx = map1d[i].baryCoords[0];
01239             int index = map1d[i].in_index;
01240             {
01241                 const sofa::core::componentmodel::topology::BaseMeshTopology::Line& line = lines[index];
01242                 out[i] = in[line[0]] * (1-fx)
01243                        + in[line[1]] * fx;
01244             }
01245         }
01246     }
01247     // 2D elements
01248     {
01249         const int i0 = map1d.size();
01250         const int c0 = triangles.size();
01251         for(unsigned int i=0;i<map2d.size();i++)
01252         {
01253             const Real fx = map2d[i].baryCoords[0];
01254             const Real fy = map2d[i].baryCoords[1];
01255             int index = map2d[i].in_index;
01256             if (index<c0)
01257             {
01258                 const sofa::core::componentmodel::topology::BaseMeshTopology::Triangle& triangle = triangles[index];
01259                 out[i+i0] = in[triangle[0]] * (1-fx-fy)
01260                           + in[triangle[1]] * fx
01261                           + in[triangle[2]] * fy;
01262             }
01263             else
01264             {
01265                 const sofa::core::componentmodel::topology::BaseMeshTopology::Quad& quad = quads[index-c0];
01266                 out[i+i0] = in[quad[0]] * ((1-fx) * (1-fy))
01267                           + in[quad[1]] * ((  fx) * (1-fy))
01268                           + in[quad[3]] * ((1-fx) * (  fy))
01269                           + in[quad[2]] * ((  fx) * (  fy));
01270             }
01271         }
01272     }
01273     // 3D elements
01274     {
01275         const int i0 = map1d.size() + map2d.size();
01276         const int c0 = tetras.size();
01277         for(unsigned int i=0;i<map3d.size();i++)
01278         {
01279             const Real fx = map3d[i].baryCoords[0];
01280             const Real fy = map3d[i].baryCoords[1];
01281             const Real fz = map3d[i].baryCoords[2];
01282             int index = map3d[i].in_index;
01283             if (index<c0)
01284             {
01285                           const sofa::core::componentmodel::topology::BaseMeshTopology::Tetra& tetra = tetras[index];
01286                 out[i+i0] = in[tetra[0]] * (1-fx-fy-fz)
01287                           + in[tetra[1]] * fx
01288                           + in[tetra[2]] * fy
01289                           + in[tetra[3]] * fz;
01290             }
01291             else
01292             {
01293 #ifdef SOFA_NEW_HEXA                
01294                 const sofa::core::componentmodel::topology::BaseMeshTopology::Hexa& cube = cubes[index-c0];
01295 #else
01296                 const sofa::core::componentmodel::topology::BaseMeshTopology::Cube& cube = cubes[index-c0];
01297 #endif
01298                 out[i+i0] = in[cube[0]] * ((1-fx) * (1-fy) * (1-fz))
01299                           + in[cube[1]] * ((  fx) * (1-fy) * (1-fz))
01300 #ifdef SOFA_NEW_HEXA                            
01301                           + in[cube[3]] * ((1-fx) * (  fy) * (1-fz))
01302                           + in[cube[2]] * ((  fx) * (  fy) * (1-fz))
01303 #else
01304                           + in[cube[2]] * ((1-fx) * (  fy) * (1-fz))
01305                           + in[cube[3]] * ((  fx) * (  fy) * (1-fz))
01306 #endif
01307                           + in[cube[4]] * ((1-fx) * (1-fy) * (  fz))
01308                           + in[cube[5]] * ((  fx) * (1-fy) * (  fz))
01309 #ifdef SOFA_NEW_HEXA                            
01310                           + in[cube[7]] * ((1-fx) * (  fy) * (  fz))
01311                           + in[cube[6]] * ((  fx) * (  fy) * (  fz));
01312 #else
01313                           + in[cube[6]] * ((1-fx) * (  fy) * (  fz))
01314                           + in[cube[7]] * ((  fx) * (  fy) * (  fz));
01315 #endif
01316             }
01317         }
01318     }
01319 }
01320 
01321 template <class In, class Out>
01322 void BarycentricMapperEdgeSetTopology<In,Out>::applyJ( typename Out::VecDeriv& out, const typename In::VecDeriv& in )
01323 {
01324     out.resize(map.size());
01325     const sofa::helper::vector<topology::Edge>& edges = this->topology->getEdges();
01326     for(unsigned int i=0;i<map.size();i++)
01327     {
01328         const Real fx = map[i].baryCoords[0];
01329         int index = map[i].in_index;
01330         const topology::Edge& edge = edges[index];
01331         out[i] = in[edge[0]] * (1-fx)
01332                + in[edge[1]] * fx;
01333     }
01334 }
01335 
01336 template <class In, class Out>
01337 void BarycentricMapperTriangleSetTopology<In,Out>::applyJ( typename Out::VecDeriv& out, const typename In::VecDeriv& in )
01338 {
01339     out.resize(map.size());
01340     const sofa::helper::vector<topology::Triangle>& triangles = this->topology->getTriangles();
01341     for(unsigned int i=0;i<map.size();i++)
01342     {
01343         const Real fx = map[i].baryCoords[0];
01344         const Real fy = map[i].baryCoords[1];
01345         int index = map[i].in_index;
01346         const topology::Triangle& triangle = triangles[index];
01347         out[i] = in[triangle[0]] * (1-fx-fy)
01348                + in[triangle[1]] * fx
01349                + in[triangle[2]] * fy;
01350     }
01351 }
01352 
01353 template <class In, class Out>
01354 void BarycentricMapperQuadSetTopology<In,Out>::applyJ( typename Out::VecDeriv& out, const typename In::VecDeriv& in )
01355 {
01356     out.resize(map.size());
01357     const sofa::helper::vector<topology::Quad>& quads = this->topology->getQuads();
01358     for(unsigned int i=0;i<map.size();i++)
01359     {
01360         const Real fx = map[i].baryCoords[0];
01361         const Real fy = map[i].baryCoords[1];
01362         int index = map[i].in_index;
01363         const topology::Quad& quad = quads[index];
01364         out[i] = in[quad[0]] * ((1-fx) * (1-fy))
01365               + in[quad[1]] * ((  fx) * (1-fy))
01366               + in[quad[3]] * ((1-fx) * (  fy))
01367               + in[quad[2]] * ((  fx) * (  fy));
01368     }
01369 }
01370 
01371 template <class In, class Out>
01372 void BarycentricMapperTetrahedronSetTopology<In,Out>::applyJ( typename Out::VecDeriv& out, const typename In::VecDeriv& in )
01373 {
01374     out.resize(map.size());
01375     const sofa::helper::vector<topology::Tetrahedron>& tetras = this->topology->getTetras();
01376     for(unsigned int i=0;i<map.size();i++)
01377     {
01378         const Real fx = map[i].baryCoords[0];
01379         const Real fy = map[i].baryCoords[1];
01380         const Real fz = map[i].baryCoords[2];
01381         int index = map[i].in_index;
01382         const topology::Tetrahedron& tetra = tetras[index];
01383         out[i] = in[tetra[0]] * (1-fx-fy-fz)
01384             + in[tetra[1]] * fx
01385             + in[tetra[2]] * fy
01386             + in[tetra[3]] * fz;
01387     }
01388 }
01389 
01390 template <class In, class Out>
01391 void BarycentricMapperHexahedronSetTopology<In,Out>::applyJ( typename Out::VecDeriv& out, const typename In::VecDeriv& in )
01392 {    out.resize(map.size());
01393     const sofa::helper::vector<topology::Hexahedron>& cubes = this->topology->getHexas();
01394     for(unsigned int i=0;i<map.size();i++)
01395     {
01396         const Real fx = map[i].baryCoords[0];
01397         const Real fy = map[i].baryCoords[1];
01398         const Real fz = map[i].baryCoords[2];
01399         int index = map[i].in_index;
01400         const topology::Hexahedron& cube = cubes[index];
01401         out[i] = in[cube[0]] * ((1-fx) * (1-fy) * (1-fz))
01402               + in[cube[1]] * ((  fx) * (1-fy) * (1-fz))
01403               + in[cube[3]] * ((1-fx) * (  fy) * (1-fz))
01404               + in[cube[2]] * ((  fx) * (  fy) * (1-fz))
01405               + in[cube[4]] * ((1-fx) * (1-fy) * (  fz))
01406               + in[cube[5]] * ((  fx) * (1-fy) * (  fz))
01407               + in[cube[7]] * ((1-fx) * (  fy) * (  fz))
01408               + in[cube[6]] * ((  fx) * (  fy) * (  fz));
01409     }
01410 }
01411 
01412 template <class BasicMapping>
01413 void BarycentricMapping<BasicMapping>::applyJT( typename In::VecDeriv& out, const typename Out::VecDeriv& in )
01414 {
01415     if (mapper!=NULL) mapper->applyJT(out, in);
01416 }
01417 
01418 template <class In, class Out>
01419 void BarycentricMapperRegularGridTopology<In,Out>::applyJT( typename In::VecDeriv& out, const typename Out::VecDeriv& in )
01420 {
01421     for(unsigned int i=0;i<map.size();i++)
01422     {
01423         const typename Out::Deriv v = in[i];
01424 #ifdef SOFA_NEW_HEXA
01425         const topology::RegularGridTopology::Hexa cube = this->topology->getHexaCopy(this->map[i].in_index);
01426 #else
01427         const topology::RegularGridTopology::Cube cube = this->topology->getCubeCopy(this->map[i].in_index);
01428 #endif
01429         const OutReal fx = (OutReal)map[i].baryCoords[0];
01430         const OutReal fy = (OutReal)map[i].baryCoords[1];
01431         const OutReal fz = (OutReal)map[i].baryCoords[2];
01432         out[cube[0]] += v * ((1-fx) * (1-fy) * (1-fz));
01433         out[cube[1]] += v * ((  fx) * (1-fy) * (1-fz));
01434 #ifdef SOFA_NEW_HEXA
01435         out[cube[3]] += v * ((1-fx) * (  fy) * (1-fz));
01436         out[cube[2]] += v * ((  fx) * (  fy) * (1-fz));
01437 #else
01438         out[cube[2]] += v * ((1-fx) * (  fy) * (1-fz));
01439         out[cube[3]] += v * ((  fx) * (  fy) * (1-fz));
01440 #endif
01441         out[cube[4]] += v * ((1-fx) * (1-fy) * (  fz));
01442         out[cube[5]] += v * ((  fx) * (1-fy) * (  fz));
01443 #ifdef SOFA_NEW_HEXA
01444         out[cube[7]] += v * ((1-fx) * (  fy) * (  fz));
01445         out[cube[6]] += v * ((  fx) * (  fy) * (  fz));
01446 #else
01447         out[cube[6]] += v * ((1-fx) * (  fy) * (  fz));
01448         out[cube[7]] += v * ((  fx) * (  fy) * (  fz));
01449 #endif        
01450     }
01451 }
01452 
01453 template <class In, class Out>
01454 void BarycentricMapperSparseGridTopology<In,Out>::applyJT( typename In::VecDeriv& out, const typename Out::VecDeriv& in )
01455 {
01456     for(unsigned int i=0;i<map.size();i++)
01457     {
01458         const typename Out::Deriv v = in[i];
01459 #ifdef SOFA_NEW_HEXA
01460         const topology::SparseGridTopology::Hexa cube = this->topology->getHexa(this->map[i].in_index);
01461 #else
01462         const topology::SparseGridTopology::Cube cube = this->topology->getCube(this->map[i].in_index);
01463 #endif
01464         const OutReal fx = (OutReal)map[i].baryCoords[0];
01465         const OutReal fy = (OutReal)map[i].baryCoords[1];
01466         const OutReal fz = (OutReal)map[i].baryCoords[2];
01467         out[cube[0]] += v * ((1-fx) * (1-fy) * (1-fz));
01468         out[cube[1]] += v * ((  fx) * (1-fy) * (1-fz));
01469 #ifdef SOFA_NEW_HEXA
01470         out[cube[3]] += v * ((1-fx) * (  fy) * (1-fz));
01471         out[cube[2]] += v * ((  fx) * (  fy) * (1-fz));
01472 #else
01473         out[cube[2]] += v * ((1-fx) * (  fy) * (1-fz));
01474         out[cube[3]] += v * ((  fx) * (  fy) * (1-fz));
01475 #endif
01476         out[cube[4]] += v * ((1-fx) * (1-fy) * (  fz));
01477         out[cube[5]] += v * ((  fx) * (1-fy) * (  fz));
01478 #ifdef SOFA_NEW_HEXA
01479         out[cube[7]] += v * ((1-fx) * (  fy) * (  fz));
01480         out[cube[6]] += v * ((  fx) * (  fy) * (  fz));
01481 #else
01482         out[cube[6]] += v * ((1-fx) * (  fy) * (  fz));
01483         out[cube[7]] += v * ((  fx) * (  fy) * (  fz));
01484 #endif      
01485     }
01486 }
01487 
01488 template <class In, class Out>
01489 void BarycentricMapperMeshTopology<In,Out>::applyJT( typename In::VecDeriv& out, const typename Out::VecDeriv& in )
01490 {
01491     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqLines& lines = this->topology->getLines();
01492     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqTriangles& triangles = this->topology->getTriangles();
01493     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqQuads& quads = this->topology->getQuads();
01494     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqTetras& tetras = this->topology->getTetras();
01495 #ifdef SOFA_NEW_HEXA
01496     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqHexas& cubes = this->topology->getHexas();
01497 #else
01498     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqCubes& cubes = this->topology->getCubes();
01499 #endif
01500     // 1D elements
01501     {
01502         for(unsigned int i=0;i<map1d.size();i++)
01503         {
01504             const typename Out::Deriv v = in[i];
01505             const OutReal fx = (OutReal)map1d[i].baryCoords[0];
01506             int index = map1d[i].in_index;
01507             {
01508                 const sofa::core::componentmodel::topology::BaseMeshTopology::Line& line = lines[index];
01509                 out[line[0]] += v * (1-fx);
01510                 out[line[1]] += v * fx;
01511             }
01512         }
01513     }
01514     // 2D elements
01515     {
01516         const int i0 = map1d.size();
01517         const int c0 = triangles.size();
01518         for(unsigned int i=0;i<map2d.size();i++)
01519         {
01520             const typename Out::Deriv v = in[i+i0];
01521             const OutReal fx = (OutReal)map2d[i].baryCoords[0];
01522             const OutReal fy = (OutReal)map2d[i].baryCoords[1];
01523             int index = map2d[i].in_index;
01524             if (index<c0)
01525             {
01526                 const sofa::core::componentmodel::topology::BaseMeshTopology::Triangle& triangle = triangles[index];
01527                 out[triangle[0]] += v * (1-fx-fy);
01528                 out[triangle[1]] += v * fx;
01529                 out[triangle[2]] += v * fy;
01530             }
01531             else
01532             {
01533                 const sofa::core::componentmodel::topology::BaseMeshTopology::Quad& quad = quads[index-c0];
01534                 out[quad[0]] += v * ((1-fx) * (1-fy));
01535                 out[quad[1]] += v * ((  fx) * (1-fy));
01536                 out[quad[3]] += v * ((1-fx) * (  fy));
01537                 out[quad[2]] += v * ((  fx) * (  fy));
01538             }
01539         }
01540     }
01541     // 3D elements
01542     {
01543         const int i0 = map1d.size() + map2d.size();
01544         const int c0 = tetras.size();
01545         for(unsigned int i=0;i<map3d.size();i++)
01546         {
01547             const typename Out::Deriv v = in[i+i0];
01548             const OutReal fx = (OutReal)map3d[i].baryCoords[0];
01549             const OutReal fy = (OutReal)map3d[i].baryCoords[1];
01550             const OutReal fz = (OutReal)map3d[i].baryCoords[2];
01551             int index = map3d[i].in_index;
01552             if (index<c0)
01553             {
01554                 const sofa::core::componentmodel::topology::BaseMeshTopology::Tetra& tetra = tetras[index];
01555                 out[tetra[0]] += v * (1-fx-fy-fz);
01556                 out[tetra[1]] += v * fx;
01557                 out[tetra[2]] += v * fy;
01558                 out[tetra[3]] += v * fz;
01559             }
01560             else
01561             {
01562 #ifdef SOFA_NEW_HEXA                
01563                 const sofa::core::componentmodel::topology::BaseMeshTopology::Hexa& cube = cubes[index-c0];
01564 #else
01565                 const sofa::core::componentmodel::topology::BaseMeshTopology::Cube& cube = cubes[index-c0];
01566 #endif
01567                 out[cube[0]] += v * ((1-fx) * (1-fy) * (1-fz));
01568                 out[cube[1]] += v * ((  fx) * (1-fy) * (1-fz));
01569 #ifdef SOFA_NEW_HEXA
01570                 out[cube[3]] += v * ((1-fx) * (  fy) * (1-fz));
01571                 out[cube[2]] += v * ((  fx) * (  fy) * (1-fz));
01572 #else
01573                 out[cube[2]] += v * ((1-fx) * (  fy) * (1-fz));
01574                 out[cube[3]] += v * ((  fx) * (  fy) * (1-fz));
01575 #endif
01576                 out[cube[4]] += v * ((1-fx) * (1-fy) * (  fz));
01577                 out[cube[5]] += v * ((  fx) * (1-fy) * (  fz));
01578 #ifdef SOFA_NEW_HEXA
01579                 out[cube[7]] += v * ((1-fx) * (  fy) * (  fz));
01580                 out[cube[6]] += v * ((  fx) * (  fy) * (  fz));
01581 #else
01582                 out[cube[6]] += v * ((1-fx) * (  fy) * (  fz));
01583                 out[cube[7]] += v * ((  fx) * (  fy) * (  fz));
01584 #endif                
01585             }
01586         }
01587     }
01588 }
01589 
01590 template <class In, class Out>
01591 void BarycentricMapperEdgeSetTopology<In,Out>::applyJT( typename In::VecDeriv& out, const typename Out::VecDeriv& in )
01592 {
01593     const sofa::helper::vector<topology::Edge>& edges = this->topology->getEdges();
01594     for(unsigned int i=0;i<map.size();i++)
01595     {
01596         const typename Out::Deriv v = in[i];
01597         const OutReal fx = (OutReal)map[i].baryCoords[0];
01598         int index = map[i].in_index;
01599         const topology::Edge& edge = edges[index];
01600         out[edge[0]] += v * (1-fx);
01601         out[edge[1]] += v * fx;
01602     }
01603 }
01604 
01605 template <class In, class Out>
01606 void BarycentricMapperTriangleSetTopology<In,Out>::applyJT( typename In::VecDeriv& out, const typename Out::VecDeriv& in )
01607 {
01608     const sofa::helper::vector<topology::Triangle>& triangles = this->topology->getTriangles();
01609     for(unsigned int i=0;i<map.size();i++)
01610     {
01611         const typename Out::Deriv v = in[i];
01612         const OutReal fx = (OutReal)map[i].baryCoords[0];
01613         const OutReal fy = (OutReal)map[i].baryCoords[1];
01614         int index = map[i].in_index;
01615         const topology::Triangle& triangle = triangles[index];
01616         out[triangle[0]] += v * (1-fx-fy);
01617         out[triangle[1]] += v * fx;
01618         out[triangle[2]] += v * fy;
01619     }
01620 }
01621 
01622 template <class In, class Out>
01623 void BarycentricMapperQuadSetTopology<In,Out>::applyJT( typename In::VecDeriv& out, const typename Out::VecDeriv& in )
01624 {
01625     const sofa::helper::vector<topology::Quad>& quads = this->topology->getQuads();
01626     for(unsigned int i=0;i<map.size();i++)
01627     {
01628         const typename Out::Deriv v = in[i];
01629         const OutReal fx = (OutReal)map[i].baryCoords[0];
01630         const OutReal fy = (OutReal)map[i].baryCoords[1];
01631         int index = map[i].in_index;
01632         const topology::Quad& quad = quads[index];
01633         out[quad[0]] += v * ((1-fx) * (1-fy));
01634         out[quad[1]] += v * ((  fx) * (1-fy));
01635         out[quad[3]] += v * ((1-fx) * (  fy));
01636         out[quad[2]] += v * ((  fx) * (  fy));
01637     }
01638 }
01639 
01640 template <class In, class Out>
01641 void BarycentricMapperTetrahedronSetTopology<In,Out>::applyJT( typename In::VecDeriv& out, const typename Out::VecDeriv& in )
01642 {
01643     const sofa::helper::vector<topology::Tetrahedron>& tetras = this->topology->getTetras();
01644     for(unsigned int i=0;i<map.size();i++)
01645     {
01646         const typename Out::Deriv v = in[i];
01647         const OutReal fx = (OutReal)map[i].baryCoords[0];
01648         const OutReal fy = (OutReal)map[i].baryCoords[1];
01649         const OutReal fz = (OutReal)map[i].baryCoords[2];
01650         int index = map[i].in_index;
01651         const topology::Tetrahedron& tetra = tetras[index];
01652         out[tetra[0]] += v * (1-fx-fy-fz);
01653         out[tetra[1]] += v * fx;
01654         out[tetra[2]] += v * fy;
01655         out[tetra[3]] += v * fz;
01656     }
01657 }
01658 
01659 template <class In, class Out>
01660 void BarycentricMapperHexahedronSetTopology<In,Out>::applyJT( typename In::VecDeriv& out, const typename Out::VecDeriv& in )
01661 {
01662     const sofa::helper::vector<topology::Hexahedron>& cubes = this->topology->getHexas();
01663     for(unsigned int i=0;i<map.size();i++)
01664     {
01665         const typename Out::Deriv v = in[i];
01666         const OutReal fx = (OutReal)map[i].baryCoords[0];
01667         const OutReal fy = (OutReal)map[i].baryCoords[1];
01668         const OutReal fz = (OutReal)map[i].baryCoords[2];
01669         int index = map[i].in_index;
01670         const topology::Hexahedron& cube = cubes[index];
01671         out[cube[0]] += v * ((1-fx) * (1-fy) * (1-fz));
01672         out[cube[1]] += v * ((  fx) * (1-fy) * (1-fz));
01673         out[cube[3]] += v * ((1-fx) * (  fy) * (1-fz));
01674         out[cube[2]] += v * ((  fx) * (  fy) * (1-fz));
01675         out[cube[4]] += v * ((1-fx) * (1-fy) * (  fz));
01676         out[cube[5]] += v * ((  fx) * (1-fy) * (  fz));
01677         out[cube[7]] += v * ((1-fx) * (  fy) * (  fz));
01678         out[cube[6]] += v * ((  fx) * (  fy) * (  fz));
01679     }
01680 }
01681 
01682 template <class BasicMapping>
01683 void BarycentricMapping<BasicMapping>::draw()
01684 {
01685     if (!this->getShow()) return;
01686     glDisable (GL_LIGHTING);
01687     glPointSize(7);
01688     glColor4f (1,1,0,1);
01689     const OutVecCoord& out = *this->toModel->getX();
01690     glBegin (GL_POINTS);
01691     for (unsigned int i=0; i<out.size(); i++)
01692     {
01693         helper::gl::glVertexT(out[i]);
01694     }
01695     glEnd();
01696     const InVecCoord& in = *this->fromModel->getX();
01697     if (mapper!=NULL) mapper->draw(out, in);
01698     glPointSize(1);
01699 }
01700 
01701 template <class In, class Out>
01702 void BarycentricMapperRegularGridTopology<In,Out>::draw(const typename Out::VecCoord& out, const typename In::VecCoord& in)
01703 {
01704     glBegin (GL_LINES);
01705     for (unsigned int i=0; i<map.size(); i++)
01706     {
01707 #ifdef SOFA_NEW_HEXA
01708         const topology::RegularGridTopology::Hexa cube = this->topology->getHexaCopy(this->map[i].in_index);
01709 #else
01710         const topology::RegularGridTopology::Cube cube = this->topology->getCubeCopy(this->map[i].in_index);
01711 #endif
01712         const Real fx = map[i].baryCoords[0];
01713         const Real fy = map[i].baryCoords[1];
01714         const Real fz = map[i].baryCoords[2];
01715         Real f[8];
01716         f[0] = (1-fx) * (1-fy) * (1-fz);
01717         f[1] = (  fx) * (1-fy) * (1-fz);
01718 #ifdef SOFA_NEW_HEXA
01719         f[3] = (1-fx) * (  fy) * (1-fz);
01720         f[2] = (  fx) * (  fy) * (1-fz);
01721 #else
01722         f[2] = (1-fx) * (  fy) * (1-fz);
01723         f[3] = (  fx) * (  fy) * (1-fz);
01724 #endif        
01725         f[4] = (1-fx) * (1-fy) * (  fz);
01726         f[5] = (  fx) * (1-fy) * (  fz);
01727 #ifdef SOFA_NEW_HEXA
01728         f[7] = (1-fx) * (  fy) * (  fz);
01729         f[6] = (  fx) * (  fy) * (  fz);
01730 #else
01731         f[6] = (1-fx) * (  fy) * (  fz);
01732         f[7] = (  fx) * (  fy) * (  fz);
01733 #endif
01734         for (int j=0;j<8;j++)
01735         {
01736             if (f[j]<=-0.0001 || f[j]>=0.0001)
01737             {
01738                 glColor3f((float)f[j],(float)f[j],1);
01739                 helper::gl::glVertexT(out[i]);
01740                 helper::gl::glVertexT(in[cube[j]]);
01741             }
01742         }
01743     }
01744     glEnd();
01745 }
01746 
01747 template <class In, class Out>
01748 void BarycentricMapperSparseGridTopology<In,Out>::draw(const typename Out::VecCoord& out, const typename In::VecCoord& in)
01749 {
01750     glBegin (GL_LINES);
01751     for (unsigned int i=0; i<map.size(); i++)
01752     {
01753 #ifdef SOFA_NEW_HEXA
01754         const topology::SparseGridTopology::Hexa cube = this->topology->getHexa(this->map[i].in_index);
01755 #else
01756         const topology::SparseGridTopology::Cube cube = this->topology->getCube(this->map[i].in_index);
01757 #endif
01758         const Real fx = map[i].baryCoords[0];
01759         const Real fy = map[i].baryCoords[1];
01760         const Real fz = map[i].baryCoords[2];
01761         Real f[8];
01762         f[0] = (1-fx) * (1-fy) * (1-fz);
01763         f[1] = (  fx) * (1-fy) * (1-fz);
01764 #ifdef SOFA_NEW_HEXA
01765         f[3] = (1-fx) * (  fy) * (1-fz);
01766         f[2] = (  fx) * (  fy) * (1-fz);
01767 #else
01768         f[2] = (1-fx) * (  fy) * (1-fz);
01769         f[3] = (  fx) * (  fy) * (1-fz);
01770 #endif
01771         f[4] = (1-fx) * (1-fy) * (  fz);
01772         f[5] = (  fx) * (1-fy) * (  fz);
01773 #ifdef SOFA_NEW_HEXA
01774         f[7] = (1-fx) * (  fy) * (  fz);
01775         f[6] = (  fx) * (  fy) * (  fz);
01776 #else
01777         f[6] = (1-fx) * (  fy) * (  fz);
01778         f[7] = (  fx) * (  fy) * (  fz);
01779 #endif
01780         for (int j=0;j<8;j++)
01781         {
01782             if (f[j]<=-0.0001 || f[j]>=0.0001)
01783             {
01784                 glColor3f((float)f[j],(float)f[j],1);
01785                 helper::gl::glVertexT(out[i]);
01786                 helper::gl::glVertexT(in[cube[j]]);
01787             }
01788         }
01789     }
01790     glEnd();
01791 }
01792 
01793 template <class In, class Out>
01794 void BarycentricMapperMeshTopology<In,Out>::draw(const typename Out::VecCoord& out, const typename In::VecCoord& in)
01795 {
01796     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqLines& lines = this->topology->getLines();
01797     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqTriangles& triangles = this->topology->getTriangles();
01798     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqQuads& quads = this->topology->getQuads();
01799     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqTetras& tetras = this->topology->getTetras();
01800 #ifdef SOFA_NEW_HEXA
01801     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqHexas& cubes = this->topology->getHexas();
01802 #else
01803     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqCubes& cubes = this->topology->getCubes();
01804 #endif
01805     glBegin (GL_LINES);
01806     // 1D elements
01807     {
01808         const int i0 = 0;
01809         for(unsigned int i=0;i<map1d.size();i++)
01810         {
01811             const Real fx = map1d[i].baryCoords[0];
01812             int index = map1d[i].in_index;
01813             {
01814                 const sofa::core::componentmodel::topology::BaseMeshTopology::Line& line = lines[index];
01815                 Real f[2];
01816                 f[0] = (1-fx);
01817                 f[1] = fx;
01818                 for (int j=0;j<2;j++)
01819                 {
01820                     if (f[j]<=-0.0001 || f[j]>=0.0001)
01821                     {
01822                         glColor3f((float)f[j],1,(float)f[j]);
01823                         helper::gl::glVertexT(out[i+i0]);
01824                         helper::gl::glVertexT(in[line[j]]);
01825                     }
01826                 }
01827             }
01828         }
01829     }
01830     // 2D elements
01831     {
01832         const int i0 = map1d.size();
01833         const int c0 = triangles.size();
01834         for(unsigned int i=0;i<map2d.size();i++)
01835         {
01836             const Real fx = map2d[i].baryCoords[0];
01837             const Real fy = map2d[i].baryCoords[1];
01838             int index = map2d[i].in_index;
01839             if (index<c0)
01840             {
01841                 const sofa::core::componentmodel::topology::BaseMeshTopology::Triangle& triangle = triangles[index];
01842                 Real f[3];
01843                 f[0] = (1-fx-fy);
01844                 f[1] = fx;
01845                 f[2] = fy;
01846                 for (int j=0;j<3;j++)
01847                 {
01848                     if (f[j]<=-0.0001 || f[j]>=0.0001)
01849                     {
01850                         glColor3f((float)f[j],1,(float)f[j]);
01851                         helper::gl::glVertexT(out[i+i0]);
01852                         helper::gl::glVertexT(in[triangle[j]]);
01853                     }
01854                 }
01855             }
01856             else
01857             {
01858                 const sofa::core::componentmodel::topology::BaseMeshTopology::Quad& quad = quads[index-c0];
01859                 Real f[4];
01860                 f[0] = ((1-fx) * (1-fy));
01861                 f[1] = ((  fx) * (1-fy));
01862                 f[3] = ((1-fx) * (  fy));
01863                 f[2] = ((  fx) * (  fy));
01864                 for (int j=0;j<4;j++)
01865                 {
01866                     if (f[j]<=-0.0001 || f[j]>=0.0001)
01867                     {
01868                         glColor3f((float)f[j],1,(float)f[j]);
01869                         helper::gl::glVertexT(out[i+i0]);
01870                         helper::gl::glVertexT(in[quad[j]]);
01871                     }
01872                 }
01873             }
01874         }
01875     }
01876     // 3D elements
01877     {
01878         const int i0 = map1d.size()+map2d.size();
01879         const int c0 = tetras.size();
01880         for (unsigned int i=0; i<map3d.size(); i++)
01881         {
01882             const Real fx = map3d[i].baryCoords[0];
01883             const Real fy = map3d[i].baryCoords[1];
01884             const Real fz = map3d[i].baryCoords[2];
01885             int index = map3d[i].in_index;
01886             if (index<c0)
01887             {
01888                 const sofa::core::componentmodel::topology::BaseMeshTopology::Tetra& tetra = tetras[index];
01889                 Real f[4];
01890                 f[0] = (1-fx-fy-fz);
01891                 f[1] = fx;
01892                 f[2] = fy;
01893                 f[3] = fz;
01894                 for (int j=0;j<4;j++)
01895                 {
01896                     if (f[j]<=-0.0001 || f[j]>=0.0001)
01897                     {
01898                         glColor3f((float)f[j],1,(float)f[j]);
01899                         helper::gl::glVertexT(out[i+i0]);
01900                         helper::gl::glVertexT(in[tetra[j]]);
01901                     }
01902                 }
01903             }
01904             else
01905             {
01906 #ifdef SOFA_NEW_HEXA
01907                 const sofa::core::componentmodel::topology::BaseMeshTopology::Hexa& cube = cubes[index-c0];
01908 #else
01909                 const sofa::core::componentmodel::topology::BaseMeshTopology::Cube& cube = cubes[index-c0];
01910 #endif 
01911                 Real f[8];
01912                 f[0] = (1-fx) * (1-fy) * (1-fz);
01913                 f[1] = (  fx) * (1-fy) * (1-fz);
01914 #ifdef SOFA_NEW_HEXA
01915                 f[3] = (1-fx) * (  fy) * (1-fz);
01916                 f[2] = (  fx) * (  fy) * (1-fz);
01917 #else
01918                 f[2] = (1-fx) * (  fy) * (1-fz);
01919                 f[3] = (  fx) * (  fy) * (1-fz);
01920 #endif
01921                 f[4] = (1-fx) * (1-fy) * (  fz);
01922                 f[5] = (  fx) * (1-fy) * (  fz);
01923 #ifdef SOFA_NEW_HEXA
01924                 f[7] = (1-fx) * (  fy) * (  fz);
01925                 f[6] = (  fx) * (  fy) * (  fz);
01926 #else
01927                 f[6] = (1-fx) * (  fy) * (  fz);
01928                 f[7] = (  fx) * (  fy) * (  fz);
01929 #endif                
01930                 for (int j=0;j<8;j++)
01931                 {
01932                     if (f[j]<=-0.0001 || f[j]>=0.0001)
01933                     {
01934                         glColor3f((float)f[j],1,1);
01935                         helper::gl::glVertexT(out[i+i0]);
01936                         helper::gl::glVertexT(in[cube[j]]);
01937                     }
01938                 }
01939             }
01940         }
01941     }
01942     glEnd();
01943 }
01944 
01945 
01946 template <class In, class Out>
01947 void BarycentricMapperEdgeSetTopology<In,Out>::draw(const typename Out::VecCoord& out, const typename In::VecCoord& in)
01948 {
01949     const sofa::helper::vector<topology::Edge>& edges = this->topology->getEdges();
01950 
01951     glBegin (GL_LINES);
01952     {
01953         for(unsigned int i=0;i<map.size();i++)
01954         {
01955             const Real fx = map[i].baryCoords[0];
01956             int index = map[i].in_index;
01957             const topology::Edge& edge = edges[index];
01958             {
01959                 const Real f = Real(1.0)-fx;
01960                 if (f<=-0.0001 || f>=0.0001)
01961                 {
01962                     glColor3f((float)f,1,(float)f);
01963                     helper::gl::glVertexT(out[i]);
01964                     helper::gl::glVertexT(in[edge[0]]);
01965                 }
01966             }
01967             {
01968                 const Real f = fx;
01969                 if (f<=-0.0001 || f>=0.0001)
01970                 {
01971                     glColor3f((float)f,1,(float)f);
01972                     helper::gl::glVertexT(out[i]);
01973                     helper::gl::glVertexT(in[edge[1]]);
01974                 }
01975             }
01976         }
01977     }
01978     glEnd();
01979 }
01980 
01981 template <class In, class Out>
01982 void BarycentricMapperTriangleSetTopology<In,Out>::draw(const typename Out::VecCoord& out, const typename In::VecCoord& in)
01983 {
01984     const sofa::helper::vector<topology::Triangle>& triangles = this->topology->getTriangles();
01985 
01986     glBegin (GL_LINES);
01987     {
01988         for(unsigned int i=0;i<map.size();i++)
01989         {
01990             const Real fx = map[i].baryCoords[0];
01991             const Real fy = map[i].baryCoords[1];
01992             int index = map[i].in_index;
01993             const topology::Triangle& triangle = triangles[index];
01994             Real f[3];
01995             f[0] = (1-fx-fy);
01996             f[1] = fx;
01997             f[2] = fy;
01998             for (int j=0;j<3;j++)
01999             {
02000                 if (f[j]<=-0.0001 || f[j]>=0.0001)
02001                 {
02002                     glColor3f((float)f[j],1,(float)f[j]);
02003                     helper::gl::glVertexT(out[i]);
02004                     helper::gl::glVertexT(in[triangle[j]]);
02005                 }
02006             }
02007         }
02008     }
02009     glEnd();
02010 }
02011 
02012 template <class In, class Out>
02013 void BarycentricMapperQuadSetTopology<In,Out>::draw(const typename Out::VecCoord& out, const typename In::VecCoord& in)
02014 {
02015     const sofa::helper::vector<topology::Quad>& quads = this->topology->getQuads();
02016     glBegin (GL_LINES);
02017     {
02018         for(unsigned int i=0;i<map.size();i++)
02019         {
02020             const Real fx = map[i].baryCoords[0];
02021             const Real fy = map[i].baryCoords[1];
02022             int index = map[i].in_index;
02023             const topology::Quad& quad = quads[index];
02024             Real f[4];
02025             f[0] = ((1-fx) * (1-fy));
02026             f[1] = ((  fx) * (1-fy));
02027             f[3] = ((1-fx) * (  fy));
02028             f[2] = ((  fx) * (  fy));
02029             for (int j=0;j<4;j++)
02030             {
02031                 if (f[j]<=-0.0001 || f[j]>=0.0001)
02032                 {
02033                     glColor3f((float)f[j],1,(float)f[j]);
02034                     helper::gl::glVertexT(out[i]);
02035                     helper::gl::glVertexT(in[quad[j]]);
02036                 }
02037             }
02038         }
02039     }
02040     glEnd();
02041 }
02042 
02043 template <class In, class Out>
02044 void BarycentricMapperTetrahedronSetTopology<In,Out>::draw(const typename Out::VecCoord& out, const typename In::VecCoord& in)
02045 {
02046     const sofa::helper::vector<topology::Tetrahedron>& tetras = this->topology->getTetras();
02047     glBegin (GL_LINES);
02048     {
02049         for(unsigned int i=0;i<map.size();i++)
02050         {
02051             const Real fx = map[i].baryCoords[0];
02052             const Real fy = map[i].baryCoords[1];
02053             const Real fz = map[i].baryCoords[2];
02054             int index = map[i].in_index;
02055             const topology::Tetrahedron& tetra = tetras[index];
02056             Real f[4];
02057             f[0] = (1-fx-fy-fz);
02058             f[1] = fx;
02059             f[2] = fy;
02060             f[3] = fz;
02061             for (int j=0;j<4;j++)
02062             {
02063                 if (f[j]<=-0.0001 || f[j]>=0.0001)
02064                 {
02065                     glColor3f((float)f[j],1,(float)f[j]);
02066                     helper::gl::glVertexT(out[i]);
02067                     helper::gl::glVertexT(in[tetra[j]]);
02068                 }
02069             }
02070         }
02071     }
02072     glEnd();
02073 }
02074 
02075 template <class In, class Out>
02076 void BarycentricMapperHexahedronSetTopology<In,Out>::draw(const typename Out::VecCoord& out, const typename In::VecCoord& in)
02077 {
02078     const sofa::helper::vector<topology::Hexahedron>& cubes = this->topology->getHexas();
02079     glBegin (GL_LINES);
02080     {
02081         for(unsigned int i=0;i<map.size();i++)
02082         {
02083             const Real fx = map[i].baryCoords[0];
02084             const Real fy = map[i].baryCoords[1];
02085             const Real fz = map[i].baryCoords[2];
02086             int index = map[i].in_index;
02087             const topology::Hexahedron& cube = cubes[index];
02088             Real f[8];
02089             f[0] = (1-fx) * (1-fy) * (1-fz);
02090             f[1] = (  fx) * (1-fy) * (1-fz);
02091             f[3] = (1-fx) * (  fy) * (1-fz);
02092             f[2] = (  fx) * (  fy) * (1-fz);
02093             f[4] = (1-fx) * (1-fy) * (  fz);
02094             f[5] = (  fx) * (1-fy) * (  fz);
02095             f[7] = (1-fx) * (  fy) * (  fz);
02096             f[6] = (  fx) * (  fy) * (  fz);
02097             for (int j=0;j<8;j++)
02098             {
02099                 if (f[j]<=-0.0001 || f[j]>=0.0001)
02100                 {
02101                     glColor3f((float)f[j],1,1);
02102                     helper::gl::glVertexT(out[i]);
02103                     helper::gl::glVertexT(in[cube[j]]);
02104                 }
02105             }
02106         }
02107     }
02108     glEnd();
02109 }
02110 
02111 /************************************* PropagateConstraint ***********************************/
02112 
02113 
02114 template <class BasicMapping>
02115 void BarycentricMapping<BasicMapping>::applyJT( typename In::VecConst& out, const typename Out::VecConst& in )
02116 {
02117     if (mapper!=NULL)
02118     {
02119         mapper->applyJT(out, in);
02120     }
02121 }
02122 
02123 template <class In, class Out>
02124 void BarycentricMapperRegularGridTopology<In,Out>::applyJT( typename In::VecConst& out, const typename Out::VecConst& in )
02125 {
02126 //    printf("\n applyJT() in BaricentricMapping  [RegularGridMapper] ");
02127     int offset = out.size();
02128     out.resize(offset+in.size());
02129 
02130     for(unsigned int i=0;i<in.size();i++)
02131     {
02132         for(unsigned int j=0;j<in[i].size();j++)
02133         {
02134             const typename Out::SparseDeriv cIn = in[i][j];
02135 #ifdef SOFA_NEW_HEXA
02136             const topology::RegularGridTopology::Hexa cube = this->topology->getHexaCopy(this->map[cIn.index].in_index);
02137 #else
02138             const topology::RegularGridTopology::Cube cube = this->topology->getCubeCopy(this->map[cIn.index].in_index);
02139 #endif
02140             const OutReal fx = (OutReal)map[cIn.index].baryCoords[0];
02141             const OutReal fy = (OutReal)map[cIn.index].baryCoords[1];
02142             const OutReal fz = (OutReal)map[cIn.index].baryCoords[2];
02143             
02144             out[i+offset].push_back(typename In::SparseDeriv(cube[0], (typename In::Deriv) (cIn.data * ((1-fx) * (1-fy) * (1-fz)))));
02145             out[i+offset].push_back(typename In::SparseDeriv(cube[1], (typename In::Deriv) (cIn.data * ((  fx) * (1-fy) * (1-fz)))));
02146 #ifdef SOFA_NEW_HEXA
02147             out[i+offset].push_back(typename In::SparseDeriv(cube[3], (typename In::Deriv) (cIn.data * ((1-fx) * (  fy) * (1-fz)))));
02148             out[i+offset].push_back(typename In::SparseDeriv(cube[2], (typename In::Deriv) (cIn.data * ((  fx) * (  fy) * (1-fz)))));
02149 #else
02150             out[i+offset].push_back(typename In::SparseDeriv(cube[2], (typename In::Deriv) (cIn.data * ((1-fx) * (  fy) * (1-fz)))));
02151             out[i+offset].push_back(typename In::SparseDeriv(cube[3], (typename In::Deriv) (cIn.data * ((  fx) * (  fy) * (1-fz)))));
02152 #endif
02153             out[i+offset].push_back(typename In::SparseDeriv(cube[4], (typename In::Deriv) (cIn.data * ((1-fx) * (1-fy) * (  fz)))));
02154             out[i+offset].push_back(typename In::SparseDeriv(cube[5], (typename In::Deriv) (cIn.data * ((  fx) * (1-fy) * (  fz)))));
02155 #ifdef SOFA_NEW_HEXA
02156             out[i+offset].push_back(typename In::SparseDeriv(cube[7], (typename In::Deriv) (cIn.data * ((1-fx) * (  fy) * (  fz)))));
02157             out[i+offset].push_back(typename In::SparseDeriv(cube[6], (typename In::Deriv) (cIn.data * ((  fx) * (  fy) * (  fz)))));
02158 #else
02159             out[i+offset].push_back(typename In::SparseDeriv(cube[6], (typename In::Deriv) (cIn.data * ((1-fx) * (  fy) * (  fz)))));
02160             out[i+offset].push_back(typename In::SparseDeriv(cube[7], (typename In::Deriv) (cIn.data * ((  fx) * (  fy) * (  fz)))));
02161 #endif            
02162         }
02163     }
02164 }
02165 
02166 template <class In, class Out>
02167 void BarycentricMapperSparseGridTopology<In,Out>::applyJT( typename In::VecConst& out, const typename Out::VecConst& in )
02168 {
02169 //    printf("\n applyJT() in BaricentricMapping  [RegularGridMapper] ");
02170     int offset = out.size();
02171     out.resize(offset+in.size());
02172     for(unsigned int i=0;i<in.size();i++)
02173     {
02174             std::map<int,int> outpos;
02175             int nbout = 0;
02176             for(unsigned int j=0;j<in[i].size();j++)
02177         {
02178             const typename Out::SparseDeriv cIn = in[i][j];
02179 #ifdef SOFA_NEW_HEXA
02180             const topology::SparseGridTopology::Hexa cube = this->topology->getHexa(this->map[cIn.index].in_index);
02181 #else
02182             const topology::SparseGridTopology::Cube cube = this->topology->getCube(this->map[cIn.index].in_index);
02183 #endif
02184             const OutReal fx = (OutReal)map[cIn.index].baryCoords[0];
02185             const OutReal fy = (OutReal)map[cIn.index].baryCoords[1];
02186             const OutReal fz = (OutReal)map[cIn.index].baryCoords[2];
02187                 {   std::pair<std::map<int,int>::iterator,bool> it = outpos.insert(std::make_pair(cube[0],nbout)); OutReal f = ((1-fx) * (1-fy) * (1-fz));
02188                     if (it.second)
02189                     {
02190                         out[i+offset].push_back(typename In::SparseDeriv(cube[0], (typename In::Deriv) (cIn.data * f))); ++nbout;
02191                     }
02192                     else
02193                         out[i+offset][it.first->second].data += (typename In::Deriv) (cIn.data * f);
02194                 }
02195                 {   std::pair<std::map<int,int>::iterator,bool> it = outpos.insert(std::make_pair(cube[1],nbout)); OutReal f = ((  fx) * (1-fy) * (1-fz));
02196                         if (it.second)
02197                         {
02198                             out[i+offset].push_back(typename In::SparseDeriv(cube[1], (typename In::Deriv) (cIn.data * f))); ++nbout;
02199                         }
02200                         else
02201                             out[i+offset][it.first->second].data += (typename In::Deriv) (cIn.data * f);
02202                 }
02203 #ifdef SOFA_NEW_HEXA
02204                 {   std::pair<std::map<int,int>::iterator,bool> it = outpos.insert(std::make_pair(cube[3],nbout)); OutReal f = ((1-fx) * (  fy) * (1-fz));
02205                         if (it.second)
02206                         {
02207                             out[i+offset].push_back(typename In::SparseDeriv(cube[3], (typename In::Deriv) (cIn.data * f))); ++nbout;
02208                         }
02209                         else
02210                             out[i+offset][it.first->second].data += (typename In::Deriv) (cIn.data * f);
02211                 }
02212                 {   std::pair<std::map<int,int>::iterator,bool> it = outpos.insert(std::make_pair(cube[2],nbout)); OutReal f = ((  fx) * (  fy) * (1-fz));
02213                         if (it.second)
02214                         {
02215                             out[i+offset].push_back(typename In::SparseDeriv(cube[2], (typename In::Deriv) (cIn.data * f))); ++nbout;
02216                         }
02217                         else
02218                             out[i+offset][it.first->second].data += (typename In::Deriv) (cIn.data * f);
02219                 }
02220 #else
02221                 {   std::pair<std::map<int,int>::iterator,bool> it = outpos.insert(std::make_pair(cube[2],nbout)); OutReal f = ((1-fx) * (  fy) * (1-fz));
02222                         if (it.second)
02223                         {
02224                             out[i+offset].push_back(typename In::SparseDeriv(cube[2], (typename In::Deriv) (cIn.data * f))); ++nbout;
02225                         }
02226                         else
02227                             out[i+offset][it.first->second].data += (typename In::Deriv) (cIn.data * f);
02228                 }
02229                 {   std::pair<std::map<int,int>::iterator,bool> it = outpos.insert(std::make_pair(cube[3],nbout)); OutReal f = ((  fx) * (  fy) * (1-fz));
02230                         if (it.second)
02231                         {
02232                             out[i+offset].push_back(typename In::SparseDeriv(cube[3], (typename In::Deriv) (cIn.data * f))); ++nbout;
02233                         }
02234                         else
02235                             out[i+offset][it.first->second].data += (typename In::Deriv) (cIn.data * f);
02236                 }
02237 #endif                
02238                 {   std::pair<std::map<int,int>::iterator,bool> it = outpos.insert(std::make_pair(cube[4],nbout)); OutReal f = ((1-fx) * (1-fy) * (  fz));
02239                         if (it.second)
02240                         {
02241                             out[i+offset].push_back(typename In::SparseDeriv(cube[4], (typename In::Deriv) (cIn.data * f))); ++nbout;
02242                         }
02243                         else
02244                             out[i+offset][it.first->second].data += (typename In::Deriv) (cIn.data * f);
02245                 }
02246                 {   std::pair<std::map<int,int>::iterator,bool> it = outpos.insert(std::make_pair(cube[5],nbout)); OutReal f = ((  fx) * (1-fy) * (  fz));
02247                         if (it.second)
02248                         {
02249                             out[i+offset].push_back(typename In::SparseDeriv(cube[5], (typename In::Deriv) (cIn.data * f))); ++nbout;
02250                         }
02251                         else
02252                             out[i+offset][it.first->second].data += (typename In::Deriv) (cIn.data * f);
02253                 }
02254 #ifdef SOFA_NEW_HEXA                
02255                 {   std::pair<std::map<int,int>::iterator,bool> it = outpos.insert(std::make_pair(cube[7],nbout)); OutReal f = ((1-fx) * (  fy) * (  fz));
02256                         if (it.second)
02257                         {
02258                             out[i+offset].push_back(typename In::SparseDeriv(cube[7], (typename In::Deriv) (cIn.data * f))); ++nbout;
02259                         }
02260                         else
02261                             out[i+offset][it.first->second].data += (typename In::Deriv) (cIn.data * f);
02262                 }
02263                 {   std::pair<std::map<int,int>::iterator,bool> it = outpos.insert(std::make_pair(cube[6],nbout)); OutReal f = ((  fx) * (  fy) * (  fz));
02264                         if (it.second)
02265                         {
02266                             out[i+offset].push_back(typename In::SparseDeriv(cube[6], (typename In::Deriv) (cIn.data * f))); ++nbout;
02267                         }
02268                         else
02269                             out[i+offset][it.first->second].data += (typename In::Deriv) (cIn.data * f);
02270                 }
02271 #else
02272                 {   std::pair<std::map<int,int>::iterator,bool> it = outpos.insert(std::make_pair(cube[6],nbout)); OutReal f = ((1-fx) * (  fy) * (  fz));
02273                         if (it.second)
02274                         {
02275                             out[i+offset].push_back(typename In::SparseDeriv(cube[6], (typename In::Deriv) (cIn.data * f))); ++nbout;
02276                         }
02277                         else
02278                             out[i+offset][it.first->second].data += (typename In::Deriv) (cIn.data * f);
02279                 }
02280                 {   std::pair<std::map<int,int>::iterator,bool> it = outpos.insert(std::make_pair(cube[7],nbout)); OutReal f = ((  fx) * (  fy) * (  fz));
02281                         if (it.second)
02282                         {
02283                             out[i+offset].push_back(typename In::SparseDeriv(cube[7], (typename In::Deriv) (cIn.data * f))); ++nbout;
02284                         }
02285                         else
02286                             out[i+offset][it.first->second].data += (typename In::Deriv) (cIn.data * f);
02287                 }
02288 #endif                
02289             //out[i+offset].push_back(typename In::SparseDeriv(cube[0], (typename In::Deriv) (cIn.data * ((1-fx) * (1-fy) * (1-fz)))));
02290             //out[i+offset].push_back(typename In::SparseDeriv(cube[1], (typename In::Deriv) (cIn.data * ((  fx) * (1-fy) * (1-fz)))));
02291             //out[i+offset].push_back(typename In::SparseDeriv(cube[2], (typename In::Deriv) (cIn.data * ((1-fx) * (  fy) * (1-fz)))));
02292             //out[i+offset].push_back(typename In::SparseDeriv(cube[3], (typename In::Deriv) (cIn.data * ((  fx) * (  fy) * (1-fz)))));
02293             //out[i+offset].push_back(typename In::SparseDeriv(cube[4], (typename In::Deriv) (cIn.data * ((1-fx) * (1-fy) * (  fz)))));
02294             //out[i+offset].push_back(typename In::SparseDeriv(cube[5], (typename In::Deriv) (cIn.data * ((  fx) * (1-fy) * (  fz)))));
02295             //out[i+offset].push_back(typename In::SparseDeriv(cube[6], (typename In::Deriv) (cIn.data * ((1-fx) * (  fy) * (  fz)))));
02296             //out[i+offset].push_back(typename In::SparseDeriv(cube[7], (typename In::Deriv) (cIn.data * ((  fx) * (  fy) * (  fz)))));
02297         }
02298     }
02299 }
02300 
02301 template <class In, class Out>
02302 void BarycentricMapperMeshTopology<In,Out>::applyJT( typename In::VecConst& out, const typename Out::VecConst& in )
02303 {
02304 //    printf("\n applyJT() in BaricentricMapping  [MeshMapper] \n");        
02305     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqLines& lines = this->topology->getLines();
02306     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqTriangles& triangles = this->topology->getTriangles();
02307     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqQuads& quads = this->topology->getQuads();
02308     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqTetras& tetras = this->topology->getTetras();
02309 #ifdef SOFA_NEW_HEXA
02310     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqHexas& cubes = this->topology->getHexas();
02311 #else
02312     const sofa::core::componentmodel::topology::BaseMeshTopology::SeqCubes& cubes = this->topology->getCubes();
02313 #endif
02314     //const int iLine = lines.size();
02315     const int iTri = triangles.size();
02316     //const int iQuad = quads.size();
02317     const int iTetra= tetras.size();
02318     //const int iCube = cubes.size();
02319 
02320     const int i1d = map1d.size();
02321     const int i2d = map2d.size();
02322     const int i3d = map3d.size();
02323 
02324     int indexIn;
02325 
02326     int offset = out.size();
02327     out.resize(offset+in.size());
02328 
02329     for(unsigned int i=0;i<in.size();i++)
02330     {
02331         for(unsigned int j=0;j<in[i].size();j++)
02332         {
02333             const typename Out::SparseDeriv cIn = in[i][j];
02334             indexIn = cIn.index;
02335             // 1D elements
02336             if (indexIn < i1d) 
02337             {
02338                 const OutReal fx = (OutReal)map1d[indexIn].baryCoords[0];
02339                 int index = map1d[indexIn].in_index;
02340                 {
02341                     const sofa::core::componentmodel::topology::BaseMeshTopology::Line& line = lines[index];
02342                     out[i+offset].push_back(typename In::SparseDeriv((unsigned) line[0], (typename In::Deriv) cIn.data * (1-fx)));
02343                     out[i+offset].push_back(typename In::SparseDeriv(line[1], (typename In::Deriv) cIn.data * fx));
02344                 }
02345             }
02346             // 2D elements : triangle or quad
02347             else if (indexIn < i2d)
02348             {
02349                 const OutReal fx = (OutReal)map2d[indexIn].baryCoords[0];
02350                 const OutReal fy = (OutReal)map2d[indexIn].baryCoords[1];
02351                 int index = map2d[indexIn].in_index;
02352                 if (index < iTri) // triangle
02353                 {
02354                     const sofa::core::componentmodel::topology::BaseMeshTopology::Triangle& triangle = triangles[index];
02355                     out[i+offset].push_back(typename In::SparseDeriv(triangle[0], (typename In::Deriv) cIn.data * (1-fx-fy)));
02356                     out[i+offset].push_back(typename In::SparseDeriv(triangle[1], (typename In::Deriv) cIn.data * fx));
02357                     out[i+offset].push_back(typename In::SparseDeriv(triangle[2], (typename In::Deriv) cIn.data * fy));
02358                 }
02359                 else // 2D element : Quad
02360                 {
02361                     const sofa::core::componentmodel::topology::BaseMeshTopology::Quad& quad = quads[index - iTri];
02362                     out[i+offset].push_back(typename In::SparseDeriv(quad[0], (typename In::Deriv) cIn.data * ((1-fx) * (1-fy))));
02363                     out[i+offset].push_back(typename In::SparseDeriv(quad[1], (typename In::Deriv) cIn.data * ((  fx) * (1-fy))));
02364                     out[i+offset].push_back(typename In::SparseDeriv(quad[3], (typename In::Deriv) cIn.data * ((1-fx) * (  fy))));
02365                     out[i+offset].push_back(typename In::SparseDeriv(quad[2], (typename In::Deriv) cIn.data * ((  fx) * (  fy))));
02366                 }
02367             }
02368             // 3D elements
02369             else if (indexIn < i3d)
02370             {
02371                 const OutReal fx = (OutReal)map3d[indexIn].baryCoords[0];
02372                 const OutReal fy = (OutReal)map3d[indexIn].baryCoords[1];
02373                 const OutReal fz = (OutReal)map3d[indexIn].baryCoords[2];
02374                 int index = map3d[indexIn].in_index;
02375                 if (index < iTetra) // tetra
02376                 {
02377                     const sofa::core::componentmodel::topology::BaseMeshTopology::Tetra& tetra = tetras[index];
02378                     out[i+offset].push_back(typename In::SparseDeriv(tetra[0], (typename In::Deriv) cIn.data * (1-fx-fy-fz)));
02379                     out[i+offset].push_back(typename In::SparseDeriv(tetra[1], (typename In::Deriv) cIn.data * fx));
02380                     out[i+offset].push_back(typename In::SparseDeriv(tetra[2], (typename In::Deriv) cIn.data * fy));
02381                     out[i+offset].push_back(typename In::SparseDeriv(tetra[3], (typename In::Deriv) cIn.data * fz));
02382                 }
02383                 else // cube
02384                 {
02385 #ifdef SOFA_NEW_HEXA                    
02386                     const sofa::core::componentmodel::topology::BaseMeshTopology::Hexa& cube = cubes[index-iTetra];
02387 #else
02388                     const sofa::core::componentmodel::topology::BaseMeshTopology::Cube& cube = cubes[index-iTetra];
02389 #endif
02390                     out[i+offset].push_back(typename In::SparseDeriv(cube[0], (typename In::Deriv) cIn.data * ((1-fx) * (1-fy) * (1-fz))));
02391                     out[i+offset].push_back(typename In::SparseDeriv(cube[1], (typename In::Deriv) cIn.data * ((  fx) * (1-fy) * (1-fz))));
02392 #ifdef SOFA_NEW_HEXA
02393                     out[i+offset].push_back(typename In::SparseDeriv(cube[3], (typename In::Deriv) cIn.data * ((1-fx) * (  fy) * (1-fz))));
02394                     out[i+offset].push_back(typename In::SparseDeriv(cube[2], (typename In::Deriv) cIn.data * ((  fx) * (  fy) * (1-fz))));
02395 #else
02396                     out[i+offset].push_back(typename In::SparseDeriv(cube[2], (typename In::Deriv) cIn.data * ((1-fx) * (  fy) * (1-fz))));
02397                     out[i+offset].push_back(typename In::SparseDeriv(cube[3], (typename In::Deriv) cIn.data * ((  fx) * (  fy) * (1-fz))));
02398 #endif
02399                     out[i+offset].push_back(typename In::SparseDeriv(cube[4], (typename In::Deriv) cIn.data * ((1-fx) * (1-fy) * (  fz))));
02400                     out[i+offset].push_back(typename In::SparseDeriv(cube[5], (typename In::Deriv) cIn.data * ((  fx) * (1-fy) * (  fz))));
02401 #ifdef SOFA_NEW_HEXA 
02402                     out[i+offset].push_back(typename In::SparseDeriv(cube[7], (typename In::Deriv) cIn.data * ((1-fx) * (  fy) * (  fz))));
02403                     out[i+offset].push_back(typename In::SparseDeriv(cube[6], (typename In::Deriv) cIn.data * ((  fx) * (  fy) * (  fz))));
02404 #else
02405                     out[i+offset].push_back(typename In::SparseDeriv(cube[6], (typename In::Deriv) cIn.data * ((1-fx) * (  fy) * (  fz))));
02406                     out[i+offset].push_back(typename In::SparseDeriv(cube[7], (typename In::Deriv) cIn.data * ((  fx) * (  fy) * (  fz))));
02407 #endif                    
02408                 }
02409             }
02410         }
02411     }
02412 }
02413 
02414 template <class In, class Out>
02415 void BarycentricMapperEdgeSetTopology<In,Out>::applyJT( typename In::VecConst& out, const typename Out::VecConst& in )
02416 {
02417     int offset = out.size();
02418     out.resize(offset+in.size());
02419     const sofa::helper::vector<topology::Edge>& edges = this->topology->getEdges();
02420 
02421     for(unsigned int i=0;i<in.size();i++)
02422     {
02423         for(unsigned int j=0;j<in[i].size();j++)
02424         {
02425             const typename Out::SparseDeriv cIn = in[i][j];
02426             const topology::Edge edge = edges[this->map[cIn.index].in_index];
02427             const OutReal fx = (OutReal)map[cIn.index].baryCoords[0];
02428             
02429             out[i+offset].push_back(typename In::SparseDeriv(edge[0], (typename In::Deriv) (cIn.data * (1-fx))));
02430             out[i+offset].push_back(typename In::SparseDeriv(edge[1], (typename In::Deriv) (cIn.data * (fx))));
02431         }
02432     }
02433 }
02434 
02435 template <class In, class Out>
02436 void BarycentricMapperTriangleSetTopology<In,Out>::applyJT( typename In::VecConst& out, const typename Out::VecConst& in )
02437 {
02438     int offset = out.size();
02439     out.resize(offset+in.size());
02440     const sofa::helper::vector<topology::Triangle>& triangles = this->topology->getTriangles();
02441 
02442     for(unsigned int i=0;i<in.size();i++)
02443     {
02444         for(unsigned int j=0;j<in[i].size();j++)
02445         {
02446             const typename Out::SparseDeriv cIn = in[i][j];
02447             const topology::Triangle triangle = triangles[this->map[cIn.index].in_index];
02448             const OutReal fx = (OutReal)map[cIn.index].baryCoords[0];
02449             const OutReal fy = (OutReal)map[cIn.index].baryCoords[1];
02450             
02451             out[i+offset].push_back(typename In::SparseDeriv(triangle[0], (typename In::Deriv) (cIn.data * (1-fx-fy))));
02452             out[i+offset].push_back(typename In::SparseDeriv(triangle[1], (typename In::Deriv) (cIn.data * (fx))));
02453             out[i+offset].push_back(typename In::SparseDeriv(triangle[2], (typename In::Deriv) (cIn.data * (fy))));
02454         }
02455     }
02456 }
02457 
02458 template <class In, class Out>
02459 void BarycentricMapperQuadSetTopology<In,Out>::applyJT( typename In::VecConst& out, const typename Out::VecConst& in )
02460 {
02461     int offset = out.size();
02462     out.resize(offset+in.size());
02463     const sofa::helper::vector<topology::Quad>& quads = this->topology->getQuads();
02464 
02465     for(unsigned int i=0;i<in.size();i++)
02466     {
02467         for(unsigned int j=0;j<in[i].size();j++)
02468         {
02469             const typename Out::SparseDeriv cIn = in[i][j];
02470             const int indexIn = cIn.index;
02471             const OutReal fx = (OutReal)map[cIn.index].baryCoords[0];
02472             const OutReal fy = (OutReal)map[cIn.index].baryCoords[1];
02473 
02474             const sofa::core::componentmodel::topology::BaseMeshTopology::Quad& quad = quads[map[indexIn].in_index];
02475             out[i+offset].push_back(typename In::SparseDeriv(quad[0], (typename In::Deriv) cIn.data * ((1-fx) * (1-fy))));
02476             out[i+offset].push_back(typename In::SparseDeriv(quad[1], (typename In::Deriv) cIn.data * ((  fx) * (1-fy))));
02477             out[i+offset].push_back(typename In::SparseDeriv(quad[3], (typename In::Deriv) cIn.data * ((1-fx) * (  fy))));
02478             out[i+offset].push_back(typename In::SparseDeriv(quad[2], (typename In::Deriv) cIn.data * ((  fx) * (  fy))));
02479         }
02480     }
02481 }
02482 
02483 template <class In, class Out>
02484 void BarycentricMapperTetrahedronSetTopology<In,Out>::applyJT( typename In::VecConst& out, const typename Out::VecConst& in )
02485 {
02486     int offset = out.size();
02487     out.resize(offset+in.size());
02488     const sofa::helper::vector<topology::Tetrahedron>& tetras = this->topology->getTetras();
02489 
02490     for(unsigned int i=0;i<in.size();i++)
02491     {
02492         for(unsigned int j=0;j<in[i].size();j++)
02493         {
02494             const typename Out::SparseDeriv cIn = in[i][j];
02495             const int indexIn = cIn.index;
02496             const OutReal fx = (OutReal)map[indexIn].baryCoords[0];
02497             const OutReal fy = (OutReal)map[indexIn].baryCoords[1];
02498             const OutReal fz = (OutReal)map[indexIn].baryCoords[2];
02499             int index = map[indexIn].in_index;
02500             const topology::Tetrahedron& tetra = tetras[index];
02501             out[i+offset].push_back(typename In::SparseDeriv(tetra[0], (typename In::Deriv) cIn.data * (1-fx-fy-fz)));
02502             out[i+offset].push_back(typename In::SparseDeriv(tetra[1], (typename In::Deriv) cIn.data * fx));
02503             out[i+offset].push_back(typename In::SparseDeriv(tetra[2], (typename In::Deriv) cIn.data * fy));
02504             out[i+offset].push_back(typename In::SparseDeriv(tetra[3], (typename In::Deriv) cIn.data * fz));
02505         }
02506     }
02507 }
02508 
02509 template <class In, class Out>
02510 void BarycentricMapperHexahedronSetTopology<In,Out>::applyJT( typename In::VecConst& out, const typename Out::VecConst& in )
02511 {
02512     int offset = out.size();
02513     out.resize(offset+in.size());
02514     const sofa::helper::vector<topology::Hexahedron>& cubes = this->topology->getHexas();
02515 
02516     for(unsigned int i=0;i<in.size();i++)
02517     {
02518         for(unsigned int j=0;j<in[i].size();j++)
02519         {
02520             const typename Out::SparseDeriv cIn = in[i][j];
02521             const int indexIn = cIn.index;
02522             const OutReal fx = (OutReal)map[indexIn].baryCoords[0];
02523             const OutReal fy = (OutReal)map[indexIn].baryCoords[1];
02524             const OutReal fz = (OutReal)map[indexIn].baryCoords[2];
02525             int index = map[indexIn].in_index;
02526             const topology::Hexahedron& cube = cubes[index];
02527             out[i+offset].push_back(typename In::SparseDeriv(cube[0], (typename In::Deriv) cIn.data * ((1-fx) * (1-fy) * (1-fz))));
02528             out[i+offset].push_back(typename In::SparseDeriv(cube[1], (typename In::Deriv) cIn.data * ((  fx) * (1-fy) * (1-fz))));
02529             out[i+offset].push_back(typename In::SparseDeriv(cube[3], (typename In::Deriv) cIn.data * ((1-fx) * (  fy) * (1-fz))));
02530             out[i+offset].push_back(typename In::SparseDeriv(cube[2], (typename In::Deriv) cIn.data * ((  fx) * (  fy) * (1-fz))));
02531             out[i+offset].push_back(typename In::SparseDeriv(cube[4], (typename In::Deriv) cIn.data * ((1-fx) * (1-fy) * (  fz))));
02532             out[i+offset].push_back(typename In::SparseDeriv(cube[5], (typename In::Deriv) cIn.data * ((  fx) * (1-fy) * (  fz))));
02533             out[i+offset].push_back(typename In::SparseDeriv(cube[7], (typename In::Deriv) cIn.data * ((1-fx) * (  fy) * (  fz))));
02534             out[i+offset].push_back(typename In::SparseDeriv(cube[6], (typename In::Deriv) cIn.data * ((  fx) * (  fy) * (  fz))));
02535         }
02536     }
02537 }
02538 
02539 template <class In, class Out>
02540 void BarycentricMapperEdgeSetTopology<In,Out>::handleTopologyChange()
02541 {
02542     std::list<const core::componentmodel::topology::TopologyChange *>::const_iterator itBegin = topology->firstChange();
02543     std::list<const core::componentmodel::topology::TopologyChange *>::const_iterator itEnd = topology->lastChange();
02544 
02545     for(std::list<const core::componentmodel::topology::TopologyChange *>::const_iterator changeIt = itBegin;
02546         changeIt != itEnd; ++changeIt)
02547     {
02548         const core::componentmodel::topology::TopologyChangeType changeType = (*changeIt)->getChangeType();
02549         switch(changeType)
02550         {
02551         //TODO: implementation of BarycentricMapperEdgeSetTopology<In,Out>::handleTopologyChange()
02552         case core::componentmodel::topology::ENDING_EVENT:       
02553             break;
02554         case core::componentmodel::topology::POINTSINDICESSWAP:  
02555             break;
02556         case core::componentmodel::topology::POINTSADDED:        
02557             break;
02558         case core::componentmodel::topology::POINTSREMOVED:      
02559             break;
02560         case core::componentmodel::topology::POINTSRENUMBERING:  
02561             break;
02562         case core::componentmodel::topology::EDGESADDED:         
02563             break;
02564         case core::componentmodel::topology::EDGESREMOVED:       
02565             break;
02566         case core::componentmodel::topology::EDGESRENUMBERING:    
02567             break;
02568         default:
02569             break;
02570         }
02571     }
02572 }
02573 
02574 template <class In, class Out>
02575 void BarycentricMapperTriangleSetTopology<In,Out>::handleTopologyChange()
02576 {
02577     std::list<const core::componentmodel::topology::TopologyChange *>::const_iterator itBegin = topology->firstChange();
02578     std::list<const core::componentmodel::topology::TopologyChange *>::const_iterator itEnd = topology->lastChange();
02579 
02580     for(std::list<const core::componentmodel::topology::TopologyChange *>::const_iterator changeIt = itBegin;
02581         changeIt != itEnd; ++changeIt)
02582     {
02583         const core::componentmodel::topology::TopologyChangeType changeType = (*changeIt)->getChangeType();
02584         switch(changeType)
02585         {
02586         //TODO: implementation of BarycentricMapperTriangleSetTopology<In,Out>::handleTopologyChange()
02587         case core::componentmodel::topology::ENDING_EVENT:       
02588             break;
02589         case core::componentmodel::topology::POINTSINDICESSWAP:  
02590             break;
02591         case core::componentmodel::topology::POINTSADDED:        
02592             break;
02593         case core::componentmodel::topology::POINTSREMOVED:      
02594             break;
02595         case core::componentmodel::topology::POINTSRENUMBERING:  
02596             break;
02597         case core::componentmodel::topology::TRIANGLESADDED:     
02598             break;
02599         case core::componentmodel::topology::TRIANGLESREMOVED:   
02600             break;
02601         case core::componentmodel::topology::TRIANGLESRENUMBERING: 
02602             break;
02603         default:
02604             break;
02605         }
02606     }
02607 }
02608 
02609 template <class In, class Out>
02610 void BarycentricMapperQuadSetTopology<In,Out>::handleTopologyChange()
02611 {
02612     std::list<const core::componentmodel::topology::TopologyChange *>::const_iterator itBegin = topology->firstChange();
02613     std::list<const core::componentmodel::topology::TopologyChange *>::const_iterator itEnd = topology->lastChange();
02614 
02615     for(std::list<const core::componentmodel::topology::TopologyChange *>::const_iterator changeIt = itBegin;
02616         changeIt != itEnd; ++changeIt)
02617     {
02618         const core::componentmodel::topology::TopologyChangeType changeType = (*changeIt)->getChangeType();
02619         switch(changeType)
02620         {
02621         //TODO: implementation of BarycentricMapperQuadSetTopology<In,Out>::handleTopologyChange()
02622         case core::componentmodel::topology::ENDING_EVENT:       
02623             break;
02624         case core::componentmodel::topology::POINTSINDICESSWAP:  
02625             break;
02626         case core::componentmodel::topology::POINTSADDED:        
02627             break;
02628         case core::componentmodel::topology::POINTSREMOVED:      
02629             break;
02630         case core::componentmodel::topology::POINTSRENUMBERING:  
02631             break;
02632         case core::componentmodel::topology::QUADSADDED:     
02633             break;
02634         case core::componentmodel::topology::QUADSREMOVED:   
02635             break;
02636         case core::componentmodel::topology::QUADSRENUMBERING: 
02637             break;
02638         default:
02639             break;
02640         }
02641     }
02642 }
02643 
02644 template <class In, class Out>
02645 void BarycentricMapperTetrahedronSetTopology<In,Out>::handleTopologyChange()
02646 {
02647     std::list<const core::componentmodel::topology::TopologyChange *>::const_iterator itBegin = topology->firstChange();
02648     std::list<const core::componentmodel::topology::TopologyChange *>::const_iterator itEnd = topology->lastChange();
02649 
02650     for(std::list<const core::componentmodel::topology::TopologyChange *>::const_iterator changeIt = itBegin;
02651         changeIt != itEnd; ++changeIt)
02652     {
02653         const core::componentmodel::topology::TopologyChangeType changeType = (*changeIt)->getChangeType();
02654         switch(changeType)
02655         {
02656         //TODO: implementation of BarycentricMapperTetrahedronSetTopology<In,Out>::handleTopologyChange()
02657         case core::componentmodel::topology::ENDING_EVENT:       
02658             break;
02659         case core::componentmodel::topology::POINTSINDICESSWAP:  
02660             break;
02661         case core::componentmodel::topology::POINTSADDED:        
02662             break;
02663         case core::componentmodel::topology::POINTSREMOVED:      
02664             break;
02665         case core::componentmodel::topology::POINTSRENUMBERING:  
02666             break;
02667         case core::componentmodel::topology::TETRAHEDRAADDED:     
02668             break;
02669         case core::componentmodel::topology::TETRAHEDRAREMOVED:   
02670             break;
02671         case core::componentmodel::topology::TETRAHEDRARENUMBERING: 
02672             break;
02673         default:
02674             break;
02675         }
02676     }
02677 }
02678 
02679 template <class In, class Out>
02680 void BarycentricMapperHexahedronSetTopology<In,Out>::handleTopologyChange()
02681 {
02682     if(topology->firstChange()==topology->lastChange())
02683         return;
02684 
02685     std::list<const core::componentmodel::topology::TopologyChange *>::const_iterator itBegin = topology->firstChange();
02686     std::list<const core::componentmodel::topology::TopologyChange *>::const_iterator itEnd = topology->lastChange();
02687 
02688     for(std::list<const core::componentmodel::topology::TopologyChange *>::const_iterator changeIt = itBegin;
02689         changeIt != itEnd; ++changeIt)
02690     {
02691         const core::componentmodel::topology::TopologyChangeType changeType = (*changeIt)->getChangeType();
02692         switch(changeType)
02693         {
02694         //TODO: implementation of BarycentricMapperHexahedronSetTopology<In,Out>::handleTopologyChange()
02695         case core::componentmodel::topology::ENDING_EVENT:       
02696             break;
02697         case core::componentmodel::topology::POINTSINDICESSWAP:  
02698             break;
02699         case core::componentmodel::topology::POINTSADDED:        
02700             break;
02701         case core::componentmodel::topology::POINTSREMOVED:      
02702             break;
02703         case core::componentmodel::topology::POINTSRENUMBERING:  
02704             break;
02705         case core::componentmodel::topology::HEXAHEDRAADDED:     
02706             break;
02707         case core::componentmodel::topology::HEXAHEDRAREMOVED:   
02708             {
02709                 const sofa::helper::vector<topology::Hexahedron>& cubes = this->topology->getHexas();
02710 
02711 #ifndef NDEBUG
02712                 if(cubes.size() != hexahedronData.size())
02713                 {
02714                     std::cout << "Error. BarycentricMapperHexahedronSetTopology::handleTopologyChange() : Topology container size does not match the hexahedron data size.";
02715                     return;
02716                 }
02717 #endif
02718 
02719                 const sofa::helper::vector<unsigned int> &tab = (static_cast< const component::topology::HexahedraRemoved *> (*changeIt))->getArray();
02720                 sofa::helper::vector<unsigned int> hexahedra(tab);
02721 
02722                 for(unsigned int i=0; i<hexahedra.size(); ++i)
02723                 {
02724                     // remove all references to the removed cubes from the mapping data
02725                     int cubeId = (int) hexahedra[i];
02726                     for(unsigned int j=0; j<map.size(); ++j)
02727                     {
02728                         if(map[j].in_index == cubeId) // compute new mapping
02729                         {
02730                             Vector3 coefs;
02731                             coefs[0] = map[j].baryCoords[0];
02732                             coefs[1] = map[j].baryCoords[1];
02733                             coefs[2] = map[j].baryCoords[2];
02734 
02735                             // barycentricToWorld
02736                             Matrix3 m;
02737                             m.invert(hexahedronData[cubeId].base);
02738                             Vector3 pos = (m * coefs) + hexahedronData[cubeId].origin;
02739 
02740                             // find nearest cell
02741                             int index=-1;
02742                             double distance = 1e10;
02743                             for (unsigned int c = 0; c < cubes.size(); c++)
02744                             {
02745                                 bool validC = true;
02746                                 // don't search in cubes that are being removed
02747                                 for(unsigned int k=0; k<hexahedra.size(); ++k)
02748                                 {
02749                                     if(c == hexahedra[k])
02750                                     {
02751                                         validC = false;
02752                                         break;
02753                                     }
02754                                 }
02755 
02756                                 if(validC)
02757                                 {
02758                                     const Vec3d v = hexahedronData[c].base * (pos - hexahedronData[c].origin);
02759                                     double d = std::max(std::max(-v[0],-v[1]), std::max(std::max(-v[2],v[0]-1), std::max(v[1]-1,v[2]-1)));
02760                                     if (d>0) 
02761                                         d = (pos-hexahedronData[c].center).norm2();
02762                                     if (d<distance) 
02763                                     { 
02764                                         coefs = v; 
02765                                         distance = d; 
02766                                         index = c; 
02767                                     }
02768                                 }
02769                             }
02770                             
02771                             if(index != -1)
02772                             {
02773                                 map[j].baryCoords[0] = (Real) coefs[0];
02774                                 map[j].baryCoords[1] = (Real) coefs[1];
02775                                 map[j].baryCoords[2] = (Real) coefs[2];
02776                                 map[j].in_index = index;
02777                             }
02778                         }
02779                     }
02780                 }
02781 
02782                 // renumber
02783                 int lastCubeId = (int) cubes.size()-1;
02784                 for(unsigned int i=0; i<hexahedra.size(); ++i)
02785                 {
02786                     unsigned int cubeId = hexahedra[i];
02787                     for(unsigned int j=0; j<map.size(); ++j)
02788                     {
02789                         if(map[j].in_index == lastCubeId) 
02790                             map[j].in_index = cubeId;
02791                     }
02792                     lastCubeId -= 1;
02793                 }
02794             }
02795             break;
02796         case core::componentmodel::topology::HEXAHEDRARENUMBERING: 
02797             break;
02798         default:
02799             break;
02800         }
02801     }
02802 
02803     hexahedronData.handleTopologyEvents(itBegin, itEnd);
02804 }
02805 
02806 template <class In, class Out>
02807 void BarycentricMapperEdgeSetTopology<In,Out>::handlePointEvents(std::list< const core::componentmodel::topology::TopologyChange *>::const_iterator itBegin, 
02808                                                                  std::list< const core::componentmodel::topology::TopologyChange *>::const_iterator itEnd)
02809 {
02810     map.handleTopologyEvents(itBegin, itEnd);
02811 }
02812 
02813 template <class In, class Out>
02814 void BarycentricMapperTriangleSetTopology<In,Out>::handlePointEvents(std::list< const core::componentmodel::topology::TopologyChange *>::const_iterator itBegin, 
02815                                                                  std::list< const core::componentmodel::topology::TopologyChange *>::const_iterator itEnd)
02816 {
02817     map.handleTopologyEvents(itBegin, itEnd);
02818 }
02819 
02820 template <class In, class Out>
02821 void BarycentricMapperQuadSetTopology<In,Out>::handlePointEvents(std::list< const core::componentmodel::topology::TopologyChange *>::const_iterator itBegin, 
02822                                                                  std::list< const core::componentmodel::topology::TopologyChange *>::const_iterator itEnd)
02823 {
02824     map.handleTopologyEvents(itBegin, itEnd);
02825 }
02826 
02827 template <class In, class Out>
02828 void BarycentricMapperTetrahedronSetTopology<In,Out>::handlePointEvents(std::list< const core::componentmodel::topology::TopologyChange *>::const_iterator itBegin, 
02829                                                                  std::list< const core::componentmodel::topology::TopologyChange *>::const_iterator itEnd)
02830 {
02831     map.handleTopologyEvents(itBegin, itEnd);
02832 }
02833 
02834 template <class In, class Out>
02835 void BarycentricMapperHexahedronSetTopology<In,Out>::handlePointEvents(std::list< const core::componentmodel::topology::TopologyChange *>::const_iterator itBegin, 
02836                                                                  std::list< const core::componentmodel::topology::TopologyChange *>::const_iterator itEnd)
02837 {
02838     map.handleTopologyEvents(itBegin, itEnd);
02839 }
02840 
02841 template <class BasicMapping>
02842 void BarycentricMapping<BasicMapping>::handleTopologyChange()
02843 {
02844     BarycentricMapperBaseTopology* topoMapper = dynamic_cast<BarycentricMapperBaseTopology*>(mapper);
02845 
02846     if(topoMapper != NULL)
02847     {
02848         // handle changes in the From topology
02849         topoMapper->handleTopologyChange();
02850 
02851         // handle changes in the To topology
02852         core::componentmodel::topology::BaseMeshTopology* topology_to = this->toModel->getContext()->getMeshTopology();
02853         if (topology_to != NULL)
02854         {
02855             if(topology_to->firstChange() != topology_to->lastChange()) // may not be necessary
02856             {
02857                 const std::list<const core::componentmodel::topology::TopologyChange *>::const_iterator itBegin = topology_to->firstChange();
02858                 const std::list<const core::componentmodel::topology::TopologyChange *>::const_iterator itEnd = topology_to->lastChange();
02859 
02860                 topoMapper->handlePointEvents(itBegin, itEnd);
02861             }
02862         }
02863     }
02864 }
02865 
02866 } // namespace mapping
02867 
02868 } // namespace component
02869 
02870 } // namespace sofa
02871 
02872 #endif

Generated on Sun Nov 23 03:31:48 2008 for Sofa by  doxygen 1.5.7.1