CurveMapping.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 //
00026 // C++ Interface: CurveMapping
00027 //
00028 // Description: 
00029 //
00030 //
00031 // Author: The SOFA team </www.sofa-framework.org>, (C) 2008
00032 //
00033 // Copyright: See COPYING file that comes with this distribution
00034 //
00035 //
00036 #ifndef SOFA_COMPONENT_MAPPING_CURVEMAPPING_INL
00037 #define SOFA_COMPONENT_MAPPING_CURVEMAPPING_INL
00038 
00039 #include <sofa/component/mapping/CurveMapping.h>
00040 #include <sofa/core/componentmodel/behavior/MechanicalMapping.inl>
00041 #include <sofa/helper/gl/template.h>
00042 #include <sofa/defaulttype/VecTypes.h>
00043 #include <sofa/defaulttype/Mat.h>
00044 #include <sofa/helper/rmath.h>
00045 #include <sofa/core/objectmodel/KeypressedEvent.h>
00046 #include <sofa/core/objectmodel/MouseEvent.h>
00047 #include <sofa/simulation/common/AnimateBeginEvent.h>
00048 
00049 
00050 namespace sofa
00051 {
00052 
00053 namespace component
00054 {
00055 
00056 namespace mapping
00057 {
00058 
00059 using namespace sofa::defaulttype;
00060 
00061 template <class BasicMapping>
00062 typename CurveMapping<BasicMapping>::Real CurveMapping<BasicMapping>::advanceAbscissa(Real ab, Real dist)
00063 {
00064     int integer = helper::rfloor(ab);
00065     if (integer < 0) integer = 0;
00066     else if (integer > (int)this->lengthElements.size()-1) integer = this->lengthElements.size()-1;
00067     double fraction = ab - integer;
00068     while (integer < (int)this->lengthElements.size()-1 && lengthElements[integer] * (1-fraction) < dist)
00069     {
00070         dist -= (Real) (lengthElements[integer] * (1-fraction));
00071         ++integer;
00072         fraction = 0;
00073     }
00074     fraction += dist / lengthElements[integer];
00075     return (Real) (integer + fraction);
00076 }
00077 
00078 inline Quat computeOrientation(const Vec3d& AB, const Quat& Q)
00079 {
00080     Vec3d PQ = AB;
00081     Quat quat = Q;
00082 
00083     Vec3d x = quat.rotate(Vec3d(1,0,0));
00084     PQ.normalize();
00085     
00086     if (dot(x, PQ) > 0.99)
00087         return Q;
00088 
00089     Vec3d y;
00090     double alpha;
00091 
00092     if (dot(x, PQ) < -0.99)
00093     {
00094         y = quat.rotate(Vec3d(0,0,1));
00095         alpha = M_PI;
00096     }
00097     else
00098     {       
00099         y = cross(x, PQ);
00100         y.normalize();
00101         alpha = acos(dot(x, PQ));
00102     }
00103 
00104     Quat qaux = Quat(y, alpha);
00105     
00106     return (qaux * quat);
00107 }
00108 
00109 template <class BasicMapping>
00110 void CurveMapping<BasicMapping>::init()
00111 {
00112     int nin = this->fromModel->getSize();
00113     int nout = numNodes.getValue();
00114     this->toModel->resize(nout);
00115     
00116     lengthElements.resize(nin-1);
00117 //  const InVecCoord& x0 = *this->fromModel->getX0();
00118     const InVecCoord& x0 = *this->fromModel->getX();
00119     
00120     for (int i=0; i<nin-1; i++)
00121     {
00122         lengthElements[i] = (Real)(x0[i+1]-x0[i]).norm();
00123         //std::cout << "l["<<i<<"] = "<<lengthElements[i]<<std::endl;
00124     }
00125 
00126     helper::vector<Real> &a = *angle.beginEdit();
00127     Real a0 = (a.empty()?(Real)0.0:a[a.size()-1]);
00128     int ai = a.size();
00129     a.resize(nout);
00130     while (ai < nout)
00131         a[ai++] = a0;
00132     angle.endEdit();
00133         quatElements.resize(nin-1);
00134     Quat q(0,0,0,1);
00135     for (int i=0; i<nin-1; i++)
00136     {
00137         quatElements[i] = computeOrientation(x0[i+1]-x0[i], q);
00138         q = quatElements[i];
00139     }
00140         rotateElements();
00141     
00142     helper::vector<Real> ab;
00143     
00144     ab = abscissa.getValue();
00145     ab.resize(nout);
00146     
00147     if (stepNode.getValue() != 0)
00148     {
00149         for (unsigned int i=1; i<ab.size(); i++)
00150             ab[i] = ab[i-1] + stepNode.getValue();
00151     }
00152     else if (distNode.getValue() != 0)
00153     {
00154         for (unsigned int i=1; i<ab.size(); i++)
00155             ab[i] = advanceAbscissa( ab[i-1], distNode.getValue());
00156     }
00157     
00158     abscissa.setValue(ab);
00159     
00160     old_integer.resize(nout);
00161     fill(old_integer.begin(), old_integer.end(), -1);
00162     
00163     old_angle.resize(nout);
00164     fill(old_angle.begin(), old_angle.end(), 0.0);
00165     apply(*this->toModel->getX(), *this->fromModel->getX());
00166     apply(*this->toModel->getXfree(), *this->fromModel->getXfree());
00167 /*
00168 
00169     VecCoord& xto = *this->toModel->getX();
00170     InVecCoord& xfrom = *this->fromModel->getX();
00171 
00172     std::ofstream catheterDataFile("/media/data/sofa-dev/trunk/Sofa/applications/projects/runSofa/rest_position.dat", std::fstream::out | std::fstream::binary);
00173 
00174     apply(xto, xfrom);
00175 
00176     catheterDataFile << "BeamModel_Name toto"
00177             //write the name 
00178              << endl
00179              << "Number_of_Nodes "
00180              << xto.size()
00181              << endl
00182              << "Number_of_Segments "
00183              << xto.size() - 1
00184              << endl
00185              << "List_of_Nodes" << endl;
00186     
00187     for (unsigned int i=0; i<xto.size(); i++)
00188     {
00189         catheterDataFile << i + 1
00190                  << "   "
00191                  << xto[i].getCenter()
00192                  << "   "
00193                  << xto[i].getOrientation().rotate(Vec3d(0, 1, 0))
00194                  << "   "
00195                  << xto[i].getOrientation().rotate(Vec3d(0, 0, 1))
00196                  << endl;
00197     }
00198 
00199     catheterDataFile << "Segments" << endl;
00200 
00201     for (unsigned int i=0; i<xto.size()-1; i++)
00202     {
00203         catheterDataFile << i + 1
00204                  << " "
00205                  << i + 1
00206                  << " "
00207                  << i + 2
00208                  << "   "
00209                  << "2560000.000000" << endl;
00210     }
00211     
00212     this->toModel->resize(1);
00213 */
00214     old_integer.resize(this->toModel->getSize());
00215     fill(old_integer.begin(), old_integer.end(), -1);
00216     this->BasicMapping::init();
00217 }
00218 
00219 template <class BasicMapping>
00220 void CurveMapping<BasicMapping>::reinit()
00221 {
00222     rotateElements();
00223 }
00224 
00225 template <class BasicMapping>
00226 void CurveMapping<BasicMapping>::rotateElements()
00227 {
00228     int nin = this->fromModel->getSize();
00229     rotatedQuatElements.resize(nin-1);
00230     //const InVecCoord& x0 = *this->fromModel->getX0();
00231         Real a = angle.getValue()[0];
00232     for (int i=0; i<nin-1; i++)
00233     {
00234         rotatedQuatElements[i] = quatElements[i]*Quat(Vec3d(1.0,0.0,0.0), a);
00235         rotatedQuatElements[i].normalize();
00236     }
00237 }
00238 
00239 template <class BasicMapping>
00240 void CurveMapping<BasicMapping>::storeResetState()
00241 {
00242     reset_abscissa = abscissa.getValue();
00243 }
00244 
00245 template <class BasicMapping>
00246 void CurveMapping<BasicMapping>::reset()
00247 {
00248     abscissa.setValue(reset_abscissa );
00249     fill(old_integer.begin(), old_integer.end(), -1);
00250     fill(old_angle.begin(), old_angle.end(), 0.0);
00251 }
00252 
00253 template <class BasicMapping>
00254 void CurveMapping<BasicMapping>::apply( typename Out::VecCoord& out, const typename In::VecCoord& in )
00255 {
00256     out.resize(abscissa.getValue().size());
00257     for (unsigned int i=0; i<out.size(); i++)
00258     {
00259             int integer = helper::rfloor(abscissa.getValue()[i]);
00260             if (integer < 0) integer = 0;
00261             else if (integer > (int)in.size()-2) integer = in.size()-2;
00262             double fraction = abscissa.getValue()[i] - integer;
00263             //if (fraction > 1.0) fraction = 1.0;
00264         {
00265             InCoord A, B, AB;
00266             A = in[integer];
00267             B = in[integer+1];
00268             AB = B - A;
00269             out[i].getCenter() = A + (AB * fraction);
00270             //if (integer != old_integer[i]) // rigid position has changed
00271             {
00272                 out[i].getOrientation() = rotatedQuatElements[integer]; //computeOrientation(AB, out[i].getOrientation());
00273                 
00274             }
00275 //          Real Dtheta = angle.getValue()[i] - old_angle[i];
00276 //          if (fabs(Dtheta) > 0.00001)
00277 //          {
00278 //           Quat angularRotation = Quat(Vec3d(0.0,0.0,1.0), Dtheta);
00279 //          out[i].getOrientation() = angularRotation * out[i].getOrientation();
00280 //          out[i].getOrientation().normalize();
00281 //          old_angle[i] = angle.getValue()[i];
00282 //          }
00283             old_integer[i] = integer;
00284         }
00285     }
00286 }
00287 
00288 template <class BasicMapping>
00289 void CurveMapping<BasicMapping>::applyJ( typename Out::VecDeriv& out, const typename In::VecDeriv& in )
00290 {
00291     out.resize(abscissa.getValue().size());
00292     bool isV = false;
00293     const typename In::VecCoord* x = NULL;
00294     if (&in == this->fromModel->getV())
00295     {
00296     isV = true;
00297     x = this->fromModel->getX();
00298     }
00299     else if (&in == this->fromModel->getVfree())
00300     {
00301     isV = true;
00302     x = this->fromModel->getXfree();
00303     }
00304     for (unsigned int i=0; i<out.size(); i++)
00305     {
00306         out[i] = typename Out::Deriv();
00307         int integer = helper::rfloor(abscissa.getValue()[i]);
00308         if (integer < 0) integer = 0;
00309         else if (integer > (int)in.size()-2) integer = in.size()-2;
00310         double fraction = abscissa.getValue()[i] - integer;
00311         //if (fraction > 1.0) fraction = 1.0;
00312         {
00313             typename In::Deriv A, B, AB;
00314             A = in[integer];
00315             B = in[integer+1];
00316             AB = B - A;
00317             out[i].getVCenter() = A + (AB * fraction);
00318         if (isV)
00319         out[i].getVCenter() += ((*x)[integer+1]-(*x)[integer])*(velocity.getValue()/lengthElements[integer]);
00320             out[i].getVOrientation().clear();
00321             //out[i].getOrientation() = computeOrientation(AB, out[i].getOrientation());
00322         }
00323     }
00324 }
00325 
00326 template <class BasicMapping>
00327 void CurveMapping<BasicMapping>::applyJT( typename In::VecDeriv& out, const typename Out::VecDeriv& in )
00328 {
00329     const unsigned int pathsize = this->fromModel->getSize();
00330     out.resize(pathsize);
00331     for (unsigned int i=0; i<in.size(); i++)
00332     {
00333         int integer = helper::rfloor(abscissa.getValue()[i]);
00334         if (integer < 0) integer = 0;
00335         else if (integer > (int)pathsize-2) integer = pathsize-2;
00336         double fraction = abscissa.getValue()[i] - integer;
00337         //if (fraction > 1.0) fraction = 1.0;
00338         {
00339             out[integer] += in[i].getVCenter() * (1-fraction);
00340             out[integer+1] += in[i].getVCenter() * (fraction);
00341         }
00342     }
00343 }
00344 
00345 template <class BaseMapping>
00346 void CurveMapping<BaseMapping>::applyJT( typename In::VecConst& /*out*/, const typename Out::VecConst& /*in*/ )
00347 {
00348 }
00349 
00350 template <class BaseMapping>
00351 void CurveMapping<BaseMapping>::handleEvent(sofa::core::objectmodel::Event* event)
00352 {
00353     if (/*sofa::simulation::AnimateBeginEvent* ev = */dynamic_cast<sofa::simulation::AnimateBeginEvent*>(event))
00354     {
00355         if (fabs(velocity.getValue()) > 0.00001)
00356         {
00357             helper::vector<Real> ab;
00358             ab = abscissa.getValue();
00359             Real s = velocity.getValue() * (Real)this->getContext()->getDt();
00360 //            std::cout << "abscissa += "<<s<<std::endl;
00361             for(unsigned int i=0; i<abscissa.getValue().size(); i++)
00362             {
00363                 //ab[i] += s;
00364             ab[i] = advanceAbscissa(ab[i], s);
00365                 //if (ab[i] > this->fromModel->getSize())
00366                 //    ab[i] = this->fromModel->getSize();
00367 //                std::cout << "abscissa["<<i<<"] = "<<ab[i]<<std::endl;
00368             }
00369         if (distNode.getValue() != 0)
00370         {
00371             for (unsigned int i=1; i<ab.size(); i++)
00372                 ab[i] = advanceAbscissa( ab[i-1], distNode.getValue());
00373         }
00374         abscissa.setValue(ab); 
00375         }
00376     }
00377     else if (sofa::core::objectmodel::MouseEvent* ev = dynamic_cast<sofa::core::objectmodel::MouseEvent*>(event))
00378     {   
00379         switch (ev->getState())
00380         {
00381             case sofa::core::objectmodel::MouseEvent::Wheel :
00382                 {
00383                     helper::vector< Real > ab;
00384                     ab = abscissa.getValue();
00385                     for(unsigned int i=0; i<abscissa.getValue().size(); i++)
00386                     {
00387                         ab[i] = (ev->getWheelDelta() > 0) ? ab[i] + step.getValue() : ab[i] - step.getValue();
00388                     
00389                         if (ab[i] > this->fromModel->getSize())
00390                             ab[i] = (Real)this->fromModel->getSize();
00391 
00392                         if (ab[i] < 0.0)
00393                             ab[i] = 0.0;
00394                     }
00395                     abscissa.setValue(ab);
00396                 }
00397                 break;
00398                 
00399             default:
00400                 break;
00401         }
00402     }
00403     else if (sofa::core::objectmodel::KeypressedEvent* ev = dynamic_cast<sofa::core::objectmodel::KeypressedEvent*>(event))
00404     {
00405         helper::vector<Real> ab;
00406         helper::vector<Real> ang;
00407         switch(ev->getKey())
00408             {
00409                     case 'A':
00410                         velocity.setValue(velocity.getValue()+step.getValue());
00411                         break;
00412                     case 'R':
00413                         velocity.setValue(velocity.getValue()-step.getValue());
00414                         break;
00415         case 'Q':
00416             ab = abscissa.getValue();
00417             for(unsigned int i=0; i<abscissa.getValue().size(); i++)
00418             {
00419                 ab[i] += step.getValue();
00420                 if (ab[i] > this->fromModel->getSize())
00421                     ab[i] = (Real)this->fromModel->getSize();
00422             }
00423             abscissa.setValue(ab); 
00424             break;
00425         case 'W':
00426             ab = abscissa.getValue();
00427             for(unsigned int i=0; i<abscissa.getValue().size(); i++)
00428             {
00429                 ab[i] -= step.getValue();
00430                 if (ab[i] < 0.0)
00431                     ab[i] = 0.0;
00432             }
00433             abscissa.setValue(ab); 
00434             break;
00435         case 'L':
00436             ang = angle.getValue();
00437             for(unsigned int i=0; i<angle.getValue().size(); i++)
00438             {
00439                 ang[i] += angularStep.getValue();
00440             }
00441             angle.setValue(ang);
00442                         rotateElements();
00443             break;
00444         case 'M':
00445             ang = angle.getValue();
00446             for(unsigned int i=0; i<angle.getValue().size(); i++)
00447             {
00448                 ang[i] -= angularStep.getValue();
00449             }
00450             angle.setValue(ang);
00451                         rotateElements();
00452             break;
00453         }
00454 
00455     }
00456 }
00457 
00458 template <class BaseMapping>
00459 void CurveMapping<BaseMapping>::draw()
00460 {
00461     if (!this->getShow()) return;
00462     glPointSize(5);
00463     glColor4f (1,1,0,1);
00464     glBegin (GL_POINTS);
00465     const VecCoord& x = *this->toModel->getX();
00466     for (unsigned int i=0; i<x.size(); i++)
00467     {
00468         helper::gl::glVertexT(x[i]);
00469     }
00470     glEnd();
00471 }
00472 
00473 
00474 
00475 } // namespace mapping
00476 
00477 } // namespace component
00478 
00479 } // namespace sofa
00480 
00481 #endif

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