CurveMapping.inl
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
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
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
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
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
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
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
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
00271 {
00272 out[i].getOrientation() = rotatedQuatElements[integer];
00273
00274 }
00275
00276
00277
00278
00279
00280
00281
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
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
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
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& , const typename Out::VecConst& )
00347 {
00348 }
00349
00350 template <class BaseMapping>
00351 void CurveMapping<BaseMapping>::handleEvent(sofa::core::objectmodel::Event* event)
00352 {
00353 if (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
00361 for(unsigned int i=0; i<abscissa.getValue().size(); i++)
00362 {
00363
00364 ab[i] = advanceAbscissa(ab[i], s);
00365
00366
00367
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 }
00476
00477 }
00478
00479 }
00480
00481 #endif