libmoldeo (Moldeo 1.0 Core)  1.0
libmoldeo es el conjunto de objetos y funciones, que permiten ejecutar las operaciones básicas de la plataforma Moldeo, y que compone su núcleo.
 Todo Clases Namespaces Archivos Funciones Variables 'typedefs' Enumeraciones Valores de enumeraciones Amigas 'defines' Grupos Páginas
moMathCurve.h
Ir a la documentación de este archivo.
1 /*******************************************************************************
2 
3  moMathCurve.h
4 
5  ****************************************************************************
6  * *
7  * This source is free software; you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation; either version 2 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * This code is distributed in the hope that it will be useful, but *
13  * WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
15  * General Public License for more details. *
16  * *
17  * A copy of the GNU General Public License is available on the World *
18  * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
19  * obtain it by writing to the Free Software Foundation, *
20  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21  * *
22  ****************************************************************************
23 
24  Copyright(C) 2006 Fabricio Costa
25 
26  Authors:
27  Fabricio Costa
28  Andrés Colubri
29 
30  Portions taken from
31  Wild Magic Source Code
32  David Eberly
33  http://www.geometrictools.com
34  Copyright (c) 1998-2007
35 
36 *******************************************************************************/
37 
38 #ifndef __MO_MATH_CURVE_H__
39 #define __MO_MATH_CURVE_H__
40 
41 #include "moMathVector.h"
42 #include "moMathVector3.h"
43 #include "moMathVector4.h"
45 
46 // moCurve2 class ------------------------------------------------------------
47 
48 template <class Real>
50 {
51 public:
52  // abstract base class
53 
54  moCurve2 (Real fTMin, Real fTMax)
55  {
56  m_fTMin = fTMin;
57  m_fTMax = fTMax;
58  }
59 
60 
61  virtual ~moCurve2 ()
62  {
63  }
64 
65 
66  // Interval on which curve parameter is defined. If you are interested
67  // in only a subinterval of the actual domain of the curve, you may set
68  // that subinterval with SetTimeInterval. This function requires that
69  // fTMin < fTMax.
70  Real GetMinTime () const
71  {
72  return m_fTMin;
73  }
74 
75 
76  Real GetMaxTime () const
77  {
78  return m_fTMax;
79  }
80 
81 
82  void SetTimeInterval (Real fTMin, Real fTMax)
83  {
84  m_fTMin = fTMin;
85  m_fTMax = fTMax;
86  }
87 
88 
89  // position and derivatives
90  virtual moVector2<Real> GetPosition (Real fTime) const = 0;
91  virtual moVector2<Real> GetFirstDerivative (Real fTime) const = 0;
92  virtual moVector2<Real> GetSecondDerivative (Real fTime) const = 0;
93  virtual moVector2<Real> GetThirdDerivative (Real fTime) const = 0;
94 
95  // differential geometric quantities
96  virtual Real GetLength (Real fT0, Real fT1) const = 0;
97 
98  Real GetSpeed (Real fTime) const
99  {
100  moVector2<Real> kVelocity = GetFirstDerivative(fTime);
101  Real fSpeed = kVelocity.Length();
102  return fSpeed;
103  }
104 
105 
106  Real GetTotalLength () const
107  {
108  return GetLength(m_fTMin,m_fTMax);
109  }
110 
111 
112  moVector2<Real> GetTangent (Real fTime) const
113  {
114  moVector2<Real> kVelocity = GetFirstDerivative(fTime);
115  kVelocity.Normalize();
116  return kVelocity;
117  }
118 
119 
120  moVector2<Real> GetNormal (Real fTime) const
121  {
122  moVector2<Real> kTangent = GetFirstDerivative(fTime);
123  kTangent.Normalize();
124  moVector2<Real> kNormal = kTangent.Perp();
125  return kNormal;
126  }
127 
128 
129  void GetFrame (Real fTime, moVector2<Real>& rkPosition,
130  moVector2<Real>& rkTangent, moVector2<Real>& rkNormal) const
131  {
132  rkPosition = GetPosition(fTime);
133  rkTangent = GetFirstDerivative(fTime);
134  rkTangent.Normalize();
135  rkNormal = rkTangent.Perp();
136  }
137 
138 
139  Real GetCurvature (Real fTime) const
140  {
141  moVector2<Real> kDer1 = GetFirstDerivative(fTime);
142  moVector2<Real> kDer2 = GetSecondDerivative(fTime);
143  Real fSpeedSqr = kDer1.SquaredLength();
144 
145  if (fSpeedSqr >= moMath<Real>::ZERO_TOLERANCE)
146  {
147  Real fNumer = kDer1.DotPerp(kDer2);
148  Real fDenom = moMath<Real>::Pow(fSpeedSqr,(Real)1.5);
149  return fNumer/fDenom;
150  }
151  else
152  {
153  // curvature is indeterminate, just return 0
154  return (Real)0.0;
155  }
156  }
157 
158 
159  void SubdivideByTime (int iNumPoints,
160  moVector2<Real>*& rakPoint) const
161  {
162  rakPoint = new moVector2<Real>[iNumPoints];
163 
164  Real fDelta = (m_fTMax - m_fTMin)/(iNumPoints-1);
165 
166  for (int i = 0; i < iNumPoints; i++)
167  {
168  Real fTime = m_fTMin + fDelta*i;
169  rakPoint[i] = GetPosition(fTime);
170  }
171  }
172 
173 
174 
175  // inverse mapping of s = Length(t) given by t = Length^{-1}(s)
176  virtual Real GetTime (Real fLength, int iIterations = 32,
177  Real fTolerance = (Real)1e-06) const = 0;
178 
179  // subdivision
180  void SubdivideByLength (int iNumPoints,
181  moVector2<Real>*& rakPoint) const
182  {
183  rakPoint = new moVector2<Real>[iNumPoints];
184 
185  Real fDelta = GetTotalLength()/(iNumPoints-1);
186 
187  for (int i = 0; i < iNumPoints; i++)
188  {
189  Real fLength = fDelta*i;
190  Real fTime = GetTime(fLength);
191  rakPoint[i] = GetPosition(fTime);
192  }
193  }
194 
195 
196 
197 
198 
199  void SubdivideByVariation (Real fMinVariation, int iMaxLevel,
200  int& riNumPoints, moVector2<Real>*& rakPoint) const
201  {
202  // compute end points of curve
203  moVector2<Real> kPMin = GetPosition(m_fTMin);
204  moVector2<Real> kPMax = GetPosition(m_fTMax);
205 
206  // add left end point to list
207  PointList* pkList = new PointList(kPMin,0);
208  riNumPoints = 1;
209 
210  // binary subdivision, leaf nodes add right end point of subinterval
211  SubdivideByVariation(m_fTMin,kPMin,m_fTMax,kPMax,fMinVariation,
212  iMaxLevel,riNumPoints,pkList->m_kNext);
213 
214  // repackage points in an array
215  rakPoint = new moVector2<Real>[riNumPoints];
216  for (int i = 0; i < riNumPoints; i++)
217  {
218  rakPoint[i] = pkList->m_kPoint;
219 
220  PointList* pkSave = pkList;
221  pkList = pkList->m_kNext;
222  delete pkSave;
223  }
224  }
225 
226  // Subdivision by variation. The pointers pkP0 and pkP1 correspond to the
227  // curve points at fT0 and fT1. If the pointer values are not null, the
228  // assumption is that the caller has passed in the curve points.
229  // Otherwise, the function computes the curve points.
230  virtual Real GetVariation (Real fT0, Real fT1,
231  const moVector2<Real>* pkP0 = 0, const moVector2<Real>* pkP1 = 0)
232  const = 0;
233 
234 
235 protected:
236  // curve parameter is t where tmin <= t <= tmax
237  Real m_fTMin, m_fTMax;
238 
239  // subdivision
241  {
242  public:
243  PointList (const moVector2<Real>& rkPoint, PointList* pkNext)
244  {
245  m_kPoint = rkPoint;
246  m_kNext = pkNext;
247  }
248 
251  };
252 
253  void SubdivideByVariation (Real fT0, const moVector2<Real>& rkP0,
254  Real fT1, const moVector2<Real>& rkP1, Real fMinVariation,
255  int iLevel, int& riNumPoints, PointList*& rpkList) const
256  {
257  if (iLevel > 0 && GetVariation(fT0,fT1,&rkP0,&rkP1) > fMinVariation)
258  {
259  // too much variation, subdivide interval
260  iLevel--;
261  Real fTMid = ((Real)0.5)*(fT0+fT1);
262  moVector2<Real> kPMid = GetPosition(fTMid);
263 
264  SubdivideByVariation(fT0,rkP0,fTMid,kPMid,fMinVariation,iLevel,
265  riNumPoints,rpkList);
266 
267  SubdivideByVariation(fTMid,kPMid,fT1,rkP1,fMinVariation,iLevel,
268  riNumPoints,rpkList);
269  }
270  else
271  {
272  // add right end point, left end point was added by neighbor
273  rpkList = new PointList(rkP1,rpkList);
274  riNumPoints++;
275  }
276  }
277 };
278 
280 typedef moCurve2<MOfloat> moCurve2f;
281 
283 typedef moCurve2<MOdouble> moCurve2d;
284 
285 // moSingleCurve2 class ------------------------------------------------------------
286 
287 template <class Real>
289 {
290 public:
291  // abstract base class
292 
293 
294  moSingleCurve2 (Real fTMin, Real fTMax) : moCurve2<Real>(fTMin,fTMax)
295  {
296  }
297 
298  // length-from-time and time-from-length
299  virtual Real GetLength (Real fT0, Real fT1) const {
303  return moIntegrate1<Real>::RombergIntegral(8,fT0,fT1,GetSpeedWithData,
304  (void*)this);
305  }
306  virtual Real GetTime (Real fLength, int iIterations = 32,
307  Real fTolerance = (Real)1e-06) const
308  {
309  if (fLength <= (Real)0.0)
310  {
311  return m_fTMin;
312  }
313 
314  if (fLength >= GetTotalLength())
315  {
316  return m_fTMax;
317  }
318 
319  // initial guess for Newton's method
320  Real fRatio = fLength/GetTotalLength();
321  Real fOmRatio = ((Real)1.0) - fRatio;
322  Real fTime = fOmRatio*m_fTMin + fRatio*m_fTMax;
323 
324  for (int i = 0; i < iIterations; i++)
325  {
326  Real fDifference = GetLength(m_fTMin,fTime) - fLength;
327  if (moMath<Real>::FAbs(fDifference) < fTolerance)
328  {
329  return fTime;
330  }
331 
332  fTime -= fDifference/this->GetSpeed(fTime);
333  }
334 
335  // Newton's method failed. You might want to increase iterations or
336  // tolerance or integration accuracy. However, in this application it
337  // is likely that the time values are oscillating, due to the limited
338  // numerical precision of 32-bit floats. It is safe to use the last
339  // computed time.
340  return fTime;
341  }
342 
343 protected:
347 
348  static Real GetSpeedWithData (Real fTime, void* pvData)
349  {
350  return ((moCurve2<Real>*)pvData)->GetSpeed(fTime);
351  }
352 };
353 
355 typedef moSingleCurve2<MOfloat> moSingleCurve2f;
356 
358 typedef moSingleCurve2<MOdouble> moSingleCurve2d;
359 
360 // moMultipleCurve2 class ------------------------------------------------------------
361 
362 template <class Real>
364 {
365 public:
366  // Construction and destruction for abstract base class. moMultipleCurve2
367  // accepts responsibility for deleting the input array.
368  moMultipleCurve2 (int iSegments, Real* afTime) : moCurve2<Real>(afTime[0],afTime[iSegments])
369  {
370  m_iSegments = iSegments;
371  m_afTime = afTime;
372  m_afLength = 0;
373  m_afAccumLength = 0;
374  }
375  virtual~moMultipleCurve2 () {
376  delete[] m_afTime;
377  delete[] m_afLength;
378  delete[] m_afAccumLength;
379  }
380 
381  // member access
382  int GetSegments () const {
383  return m_iSegments;
384  }
385  const Real* GetTimes () const {
386  return m_afTime;
387  }
388 
389  // length-from-time and time-from-length
390  virtual Real GetLength (Real fT0, Real fT1) const {
391  //assert(m_fTMin <= fT0 && fT0 <= m_fTMax);
392  //assert(m_fTMin <= fT1 && fT1 <= m_fTMax);
393  //assert(fT0 <= fT1);
394 
395  if (!m_afLength)
396  {
397  InitializeLength();
398  }
399 
400  int iKey0, iKey1;
401  Real fDt0, fDt1;
402  GetKeyInfo(fT0,iKey0,fDt0);
403  GetKeyInfo(fT1,iKey1,fDt1);
404 
405  Real fLength;
406  if (iKey0 < iKey1)
407  {
408  // accumulate full-segment lengths
409  fLength = (Real)0.0;
410  for (int i = iKey0+1; i < iKey1; i++)
411  {
412  fLength += m_afLength[i];
413  }
414 
415  // add on partial first segment
416  fLength += GetLengthKey(iKey0,fDt0,m_afTime[iKey0+1]-m_afTime[iKey0]);
417 
418  // add on partial last segment
419  fLength += GetLengthKey(iKey1,(Real)0.0,fDt1);
420  }
421  else
422  {
423  fLength = GetLengthKey(iKey0,fDt0,fDt1);
424  }
425 
426  return fLength;
427  }
428 
429  virtual Real GetTime (Real fLength, int iIterations = 32,
430  Real fTolerance = (Real)1e-06) const {
431  if (!m_afLength)
432  {
433  InitializeLength();
434  }
435 
436  if (fLength <= (Real)0.0)
437  {
438  return m_fTMin;
439  }
440 
441  if (fLength >= m_afAccumLength[m_iSegments-1])
442  {
443  return m_fTMax;
444  }
445 
446  int iKey;
447  for (iKey = 0; iKey < m_iSegments; iKey++)
448  {
449  if (fLength < m_afAccumLength[iKey])
450  {
451  break;
452  }
453  }
454  if (iKey >= m_iSegments)
455  {
456  return m_afTime[m_iSegments];
457  }
458 
459  // try Newton's method first for rapid convergence
460  Real fL0, fL1;
461  if (iKey == 0)
462  {
463  fL0 = fLength;
464  fL1 = m_afAccumLength[0];
465  }
466  else
467  {
468  fL0 = fLength - m_afAccumLength[iKey-1];
469  fL1 = m_afAccumLength[iKey] - m_afAccumLength[iKey-1];
470  }
471 
472  // use Newton's method to invert the arc length integral
473  Real fDt1 = m_afTime[iKey+1] - m_afTime[iKey];
474  Real fDt0 = fDt1*fL0/fL1;
475  for (int i = 0; i < iIterations; i++)
476  {
477  Real fDifference = GetLengthKey(iKey,(Real)0.0,fDt0) - fL0;
478  if (moMath<Real>::FAbs(fDifference) <= fTolerance)
479  {
480  return m_afTime[iKey] + fDt0;
481  }
482 
483  fDt0 -= fDifference/GetSpeedKey(iKey,fDt0);
484  }
485 
486  // Newton's method failed. You might want to increase iterations or
487  // tolerance or integration accuracy. However, in this application it
488  // is likely that the time values are oscillating, due to the limited
489  // numerical precision of 32-bit floats. It is safe to use the last
490  // computed time.
491  return m_afTime[iKey] + fDt0;
492  }
493 
494  // support for subdivision
495  virtual Real GetVariation (Real fT0, Real fT1,
496  const moVector2<Real>* pkP0 = 0, const moVector2<Real>* pkP1 = 0) const {
497  //assert(m_fTMin <= fT0 && fT0 <= m_fTMax);
498  //assert(m_fTMin <= fT1 && fT1 <= m_fTMax);
499  //assert(fT0 <= fT1);
500 
501  // construct line segment, A + (t-t0)*B
502  moVector2<Real> kP0, kP1;
503  if (!pkP0)
504  {
505  kP0 = this->GetPosition(fT0);
506  pkP0 = &kP0;
507  }
508  if (!pkP1)
509  {
510  kP1 = this->GetPosition(fT1);
511  pkP1 = &kP1;
512  }
513  Real fInvDT = ((Real)1.0)/(fT1 - fT0);
514  moVector2<Real> kA, kB = fInvDT*(*pkP1 - *pkP0);
515 
516  int iKey0, iKey1;
517  Real fDt0, fDt1;
518  GetKeyInfo(fT0,iKey0,fDt0);
519  GetKeyInfo(fT1,iKey1,fDt1);
520 
521  Real fVariation;
522  if (iKey0 < iKey1)
523  {
524  // accumulate full-segment variations
525  fVariation = (Real)0.0;
526  for (int i = iKey0+1; i < iKey1; i++)
527  {
528  kA = *pkP0 + (m_afTime[i] - fT0)*kB;
529  fVariation += GetVariationKey(i,(Real)0.0,
530  m_afTime[i+1]-m_afTime[i],kA,kB);
531  }
532 
533  // add on partial first segment
534  kA = *pkP0 + (m_afTime[iKey0] - fT0)*kB;
535  fVariation += GetVariationKey(iKey0,fDt0,
536  m_afTime[iKey0+1]-m_afTime[iKey0],kA,kB);
537 
538  // add on partial last segment
539  kA = *pkP0 + (m_afTime[iKey1] - fT0)*kB;
540  fVariation += GetVariationKey(iKey1,(Real)0.0,fDt1,kA,kB);
541  }
542  else
543  {
544  kA = *pkP0 + (m_afTime[iKey0] - fT0)*kB;
545  fVariation = GetVariationKey(iKey0,fDt0,fDt1,kA,kB);
546  }
547 
548  return fVariation;
549  }
550 
551 protected:
554 
556  Real* m_afTime;
557 
558  // These quantities are allocated by GetLength when they are needed the
559  // first time. The allocations occur in InitializeLength (called by
560  // GetLength), so this member function must be 'const'. In order to
561  // allocate the arrays in a 'const' function, they must be declared as
562  // 'mutable'.
563  mutable Real* m_afLength;
564  mutable Real* m_afAccumLength;
565 
566  void GetKeyInfo (Real fTime, int& riKey, Real& rfDt) const {
567  if (fTime <= m_afTime[0])
568  {
569  riKey = 0;
570  rfDt = (Real)0.0;
571  }
572  else if (fTime >= m_afTime[m_iSegments])
573  {
574  riKey = m_iSegments-1;
575  rfDt = m_afTime[m_iSegments] - m_afTime[m_iSegments-1];
576  }
577  else
578  {
579  for (int i = 0; i < m_iSegments; i++)
580  {
581  if (fTime < m_afTime[i+1])
582  {
583  riKey = i;
584  rfDt = fTime - m_afTime[i];
585  break;
586  }
587  }
588  }
589  }
590 
591  void InitializeLength () const {
592  m_afLength = new Real[m_iSegments];
593  m_afAccumLength = new Real[m_iSegments];
594 
595  // arc lengths of the segments
596  int iKey;
597  for (iKey = 0; iKey < m_iSegments; iKey++)
598  {
599  m_afLength[iKey] = GetLengthKey(iKey,(Real)0.0,
600  m_afTime[iKey+1]-m_afTime[iKey]);
601  }
602 
603  // accumulative arc length
604  m_afAccumLength[0] = m_afLength[0];
605  for (iKey = 1; iKey < m_iSegments; iKey++)
606  {
607  m_afAccumLength[iKey] = m_afAccumLength[iKey-1] + m_afLength[iKey];
608  }
609  }
610  virtual Real GetSpeedKey (int iKey, Real fTime) const = 0;
611  virtual Real GetLengthKey (int iKey, Real fT0, Real fT1) const = 0;
612  virtual Real GetVariationKey (int iKey, Real fT0, Real fT1,
613  const moVector2<Real>& rkA, const moVector2<Real>& rkB) const = 0;
614 
615  static Real GetSpeedWithData (Real fTime, void* pvData) {
616  moMultipleCurve2* pvThis = *(moMultipleCurve2**) pvData;
617  int iKey = *(int*)((char*)pvData + sizeof(pvThis));
618  return pvThis->GetSpeedKey(iKey,fTime);
619  }
620 };
621 
623 typedef moMultipleCurve2<MOfloat> moMultipleCurve2f;
624 
626 typedef moMultipleCurve2<MOdouble> moMultipleCurve2d;
627 
628 // moCurve3 class ------------------------------------------------------------
629 
630 template <class Real>
632 {
633 public:
634  // abstract base class
635  moCurve3 (Real fTMin, Real fTMax) {
636  m_fTMin = fTMin;
637  m_fTMax = fTMax;
638  }
639  virtual ~moCurve3 () {
640 
641  }
642 
643 
644  // Interval on which curve parameter is defined. If you are interested
645  // in only a subinterval of the actual domain of the curve, you may set
646  // that subinterval with SetTimeInterval. This function requires that
647  // fTMin < fTMax.
648  Real GetMinTime () const {
649  return m_fTMin;
650  }
651  Real GetMaxTime () const {
652  return m_fTMax;
653  }
654  void SetTimeInterval (Real fTMin, Real fTMax) {
655  //assert(fTMin < fTMax);
656  m_fTMin = fTMin;
657  m_fTMax = fTMax;
658  }
659 
660  // position and derivatives
661  virtual moVector3<Real> GetPosition (Real fTime) const = 0;
662  virtual moVector3<Real> GetFirstDerivative (Real fTime) const = 0;
663  virtual moVector3<Real> GetSecondDerivative (Real fTime) const = 0;
664  virtual moVector3<Real> GetThirdDerivative (Real fTime) const = 0;
665 
666  virtual Real GetTime (Real fLength, int iIterations = 32,
667  Real fTolerance = (Real)1e-06) const = 0;
668  virtual Real GetVariation (Real fT0, Real fT1,
669  const moVector3<Real>* pkP0, const moVector3<Real>* pkP1) const = 0;
670 
671  // differential geometric quantities
672 
673  virtual Real GetLength (Real fT0, Real fT1) const = 0;
674  Real GetSpeed (Real fTime) const
675  {
676  moVector3<Real> kVelocity = GetFirstDerivative(fTime);
677  Real fSpeed = kVelocity.Length();
678  return fSpeed;
679  }
680  Real GetTotalLength () const
681  {
682  return GetLength(m_fTMin,m_fTMax);
683  }
684  moVector3<Real> GetTangent (Real fTime) const
685  {
686  moVector3<Real> kVelocity = GetFirstDerivative(fTime);
687  kVelocity.Normalize();
688  return kVelocity;
689  }
690  moVector3<Real> GetNormal (Real fTime) const {
691  moVector3<Real> kVelocity = GetFirstDerivative(fTime);
692  moVector3<Real> kAcceleration = GetSecondDerivative(fTime);
693  Real fVDotV = kVelocity.Dot(kVelocity);
694  Real fVDotA = kVelocity.Dot(kAcceleration);
695  moVector3<Real> kNormal = fVDotV*kAcceleration - fVDotA*kVelocity;
696  kNormal.Normalize();
697  return kNormal;
698  }
699 
700  moVector3<Real> GetBinormal (Real fTime) const
701  {
702  moVector3<Real> kVelocity = GetFirstDerivative(fTime);
703  moVector3<Real> kAcceleration = GetSecondDerivative(fTime);
704  Real fVDotV = kVelocity.Dot(kVelocity);
705  Real fVDotA = kVelocity.Dot(kAcceleration);
706  moVector3<Real> kNormal = fVDotV*kAcceleration - fVDotA*kVelocity;
707  kNormal.Normalize();
708  kVelocity.Normalize();
709  moVector3<Real> kBinormal = kVelocity.Cross(kNormal);
710  return kBinormal;
711  }
712 
713 
714  void GetFrame (Real fTime, moVector3<Real>& rkPosition,
715  moVector3<Real>& rkTangent, moVector3<Real>& rkNormal,
716  moVector3<Real>& rkBinormal) const
717  {
718  rkPosition = GetPosition(fTime);
719  moVector3<Real> kVelocity = GetFirstDerivative(fTime);
720  moVector3<Real> kAcceleration = GetSecondDerivative(fTime);
721  Real fVDotV = kVelocity.Dot(kVelocity);
722  Real fVDotA = kVelocity.Dot(kAcceleration);
723  rkNormal = fVDotV*kAcceleration - fVDotA*kVelocity;
724  rkNormal.Normalize();
725  rkTangent = kVelocity;
726  rkTangent.Normalize();
727  rkBinormal = rkTangent.Cross(rkNormal);
728  }
729 
730 
731  Real GetCurvature (Real fTime) const
732  {
733  moVector3<Real> kVelocity = GetFirstDerivative(fTime);
734  Real fSpeedSqr = kVelocity.SquaredLength();
735 
736  if (fSpeedSqr >= moMath<Real>::ZERO_TOLERANCE)
737  {
738  moVector3<Real> kAcceleration = GetSecondDerivative(fTime);
739  moVector3<Real> kCross = kVelocity.Cross(kAcceleration);
740  Real fNumer = kCross.Length();
741  Real fDenom = moMath<Real>::Pow(fSpeedSqr,(Real)1.5);
742  return fNumer/fDenom;
743  }
744  else
745  {
746  // curvature is indeterminate, just return 0
747  return (Real)0.0;
748  }
749  }
750 
751 
752  Real GetTorsion (Real fTime) const
753  {
754  moVector3<Real> kVelocity = GetFirstDerivative(fTime);
755  moVector3<Real> kAcceleration = GetSecondDerivative(fTime);
756  moVector3<Real> kCross = kVelocity.Cross(kAcceleration);
757  Real fDenom = kCross.SquaredLength();
758 
759  if (fDenom >= moMath<Real>::ZERO_TOLERANCE)
760  {
761  moVector3<Real> kJerk = GetThirdDerivative(fTime);
762  Real fNumer = kCross.Dot(kJerk);
763  return fNumer/fDenom;
764  }
765  else
766  {
767  // torsion is indeterminate, just return 0
768  return (Real)0.0;
769  }
770  }
771 
772 
773  void SubdivideByTime (int iNumPoints,
774  moVector3<Real>*& rakPoint) const
775  {
776  //assert( iNumPoints >= 2 );
777  rakPoint = new moVector3<Real>[iNumPoints];
778 
779  Real fDelta = (m_fTMax - m_fTMin)/(iNumPoints-1);
780 
781  for (int i = 0; i < iNumPoints; i++)
782  {
783  Real fTime = m_fTMin + fDelta*i;
784  rakPoint[i] = GetPosition(fTime);
785  }
786  }
787 
788 
789  void SubdivideByLength (int iNumPoints,
790  moVector3<Real>*& rakPoint) const
791  {
792  //assert(iNumPoints >= 2);
793  rakPoint = new moVector3<Real>[iNumPoints];
794 
795  Real fDelta = GetTotalLength()/(iNumPoints-1);
796 
797  for (int i = 0; i < iNumPoints; i++)
798  {
799  Real fLength = fDelta*i;
800  Real fTime = GetTime(fLength);
801  rakPoint[i] = GetPosition(fTime);
802  }
803  }
804 
805 
806 protected:
807  // curve parameter is t where tmin <= t <= tmax
808  Real m_fTMin, m_fTMax;
809 
810  // subdivision
812  {
813  public:
814  PointList (const moVector3<Real>& rkPoint, PointList* pkNext)
815  {
816  m_kPoint = rkPoint;
817  m_kNext = pkNext;
818  }
819 
822  };
823 
824  void SubdivideByVariation (Real fT0, const moVector3<Real>& rkP0,
825  Real fT1, const moVector3<Real>& rkP1, Real fMinVariation, int iLevel,
826  int& riNumPoints, PointList*& rpkList) const
827  {
828  if (iLevel > 0 && GetVariation(fT0,fT1,&rkP0,&rkP1) > fMinVariation)
829  {
830  // too much variation, subdivide interval
831  iLevel--;
832  Real fTMid = ((Real)0.5)*(fT0+fT1);
833  moVector3<Real> kPMid = GetPosition(fTMid);
834 
835  SubdivideByVariation(fT0,rkP0,fTMid,kPMid,fMinVariation,iLevel,
836  riNumPoints,rpkList);
837 
838  SubdivideByVariation(fTMid,kPMid,fT1,rkP1,fMinVariation,iLevel,
839  riNumPoints,rpkList);
840  }
841  else
842  {
843  // add right end point, left end point was added by neighbor
844  rpkList = new PointList(rkP1,rpkList);
845  riNumPoints++;
846  }
847  }
848 };
849 
851 typedef moCurve3<MOfloat> moCurve3f;
852 
854 typedef moCurve3<MOdouble> moCurve3d;
855 
856 // moSingleCurve3 ------------------------------------------------------------
857 
858 template <class Real>
860 {
861 public:
862  // abstract base class
863  moSingleCurve3 (Real fTMin, Real fTMax) :
864  moCurve3<Real>(fTMin,fTMax) {
865  }
866 
867  // length-from-time and time-from-length
868  virtual Real GetLength (Real fT0, Real fT1) const {
869  return moIntegrate1<Real>::RombergIntegral(8,fT0,fT1,GetSpeedWithData,
870  (void*)this);
871  }
872 
873  Real GetTime (Real fLength, int iIterations,
874  Real fTolerance) const
875  {
876  if (fLength <= (Real)0.0)
877  {
878  return m_fTMin;
879  }
880 
881  if (fLength >= GetTotalLength())
882  {
883  return m_fTMax;
884  }
885 
886  // initial guess for Newton's method
887  Real fRatio = fLength/GetTotalLength();
888  Real fOmRatio = (Real)1.0 - fRatio;
889  Real fTime = fOmRatio*m_fTMin + fRatio*m_fTMax;
890 
891  for (int i = 0; i < iIterations; i++)
892  {
893  Real fDifference = GetLength(m_fTMin,fTime) - fLength;
894  if (moMath<Real>::FAbs(fDifference) < fTolerance)
895  {
896  return fTime;
897  }
898 
899  fTime -= fDifference/this->GetSpeed(fTime);
900  }
901 
902  // Newton's method failed. You might want to increase iterations or
903  // tolerance or integration accuracy. However, in this application it
904  // is likely that the time values are oscillating, due to the limited
905  // numerical precision of 32-bit floats. It is safe to use the last
906  // computed time.
907  return fTime;
908  }
909 
910 
911 protected:
915 
916  static Real GetSpeedWithData (Real fTime, void* pvData) {
917  return ((moCurve3<Real>*)pvData)->GetSpeed(fTime);
918  }
919 };
920 
922 typedef moSingleCurve3<MOfloat> moSingleCurve3f;
923 
925 typedef moSingleCurve3<MOdouble> moSingleCurve3d;
926 
927 // moMultipleCurve3 ------------------------------------------------------------
928 
929 template <class Real>
931 {
932 public:
933  // Construction and destruction for abstract base class. moMultipleCurve3
934  // accepts responsibility for deleting the input array.
935  moMultipleCurve3 (int iSegments, Real* afTime)
936  :
937  moCurve3<Real>(afTime[0],afTime[iSegments])
938  {
939  m_iSegments = iSegments;
940  m_afTime = afTime;
941  m_afLength = 0;
942  m_afAccumLength = 0;
943  }
944  virtual ~moMultipleCurve3 () {
945  delete[] m_afTime;
946  delete[] m_afLength;
947  delete[] m_afAccumLength;
948  }
949 
950  // member access
951  int GetSegments () const {
952  return m_iSegments;
953  }
954  const Real* GetTimes () const {
955  return m_afTime;
956  }
957 
958  // length-from-time and time-from-length
959  virtual Real GetLength (Real fT0, Real fT1) const {
960  if (!m_afLength)
961  {
962  InitializeLength();
963  }
964 
965  int iKey0, iKey1;
966  Real fDt0, fDt1;
967  GetKeyInfo(fT0,iKey0,fDt0);
968  GetKeyInfo(fT1,iKey1,fDt1);
969 
970  Real fLength;
971  if (iKey0 < iKey1)
972  {
973  // accumulate full-segment lengths
974  fLength = (Real)0.0;
975  for (int i = iKey0+1; i < iKey1; i++)
976  fLength += m_afLength[i];
977 
978  // add on partial first segment
979  fLength += GetLengthKey(iKey0,fDt0,m_afTime[iKey0+1]-m_afTime[iKey0]);
980 
981  // add on partial last segment
982  fLength += GetLengthKey(iKey1,(Real)0.0,fDt1);
983  }
984  else
985  {
986  fLength = GetLengthKey(iKey0,fDt0,fDt1);
987  }
988 
989  return fLength;
990 
991  }
992  virtual Real GetTime (Real fLength, int iIterations = 32,
993  Real fTolerance = (Real)1e-06) const {
994  if (!m_afLength)
995  {
996  InitializeLength();
997  }
998 
999  if (fLength <= (Real)0.0)
1000  {
1001  return m_fTMin;
1002  }
1003 
1004  if (fLength >= m_afAccumLength[m_iSegments-1])
1005  {
1006  return m_fTMax;
1007  }
1008 
1009  int iKey;
1010  for (iKey = 0; iKey < m_iSegments; iKey++)
1011  {
1012  if (fLength < m_afAccumLength[iKey])
1013  {
1014  break;
1015  }
1016  }
1017  if (iKey >= m_iSegments)
1018  {
1019  return m_afTime[m_iSegments];
1020  }
1021 
1022  // try Newton's method first for rapid convergence
1023  Real fL0, fL1;
1024  if (iKey == 0)
1025  {
1026  fL0 = fLength;
1027  fL1 = m_afAccumLength[0];
1028  }
1029  else
1030  {
1031  fL0 = fLength - m_afAccumLength[iKey-1];
1032  fL1 = m_afAccumLength[iKey] - m_afAccumLength[iKey-1];
1033  }
1034 
1035  // use Newton's method to invert the arc length integral
1036  Real fDt1 = m_afTime[iKey+1] - m_afTime[iKey];
1037  Real fDt0 = fDt1*fL0/fL1;
1038  for (int i = 0; i < iIterations; i++)
1039  {
1040  Real fDifference = GetLengthKey(iKey,(Real)0.0,fDt0) - fL0;
1041  if (moMath<Real>::FAbs(fDifference) <= fTolerance)
1042  {
1043  return m_afTime[iKey] + fDt0;
1044  }
1045 
1046  fDt0 -= fDifference/GetSpeedKey(iKey,fDt0);
1047  }
1048 
1049  // Newton's method failed. You might want to increase iterations or
1050  // tolerance or integration accuracy. However, in this application it
1051  // is likely that the time values are oscillating, due to the limited
1052  // numerical precision of 32-bit floats. It is safe to use the last
1053  // computed time.
1054  return m_afTime[iKey] + fDt0;
1055 
1056  }
1057 
1058  // support for subdivision
1059  virtual Real GetVariation (Real fT0, Real fT1,
1060  const moVector3<Real>* pkP0 = 0, const moVector3<Real>* pkP1 = 0) const {
1061  //assert(m_fTMin <= fT0 && fT0 <= m_fTMax);
1062  //assert(m_fTMin <= fT1 && fT1 <= m_fTMax);
1063  //assert(fT0 <= fT1);
1064 
1065  // construct line segment, A + (t-t0)*B
1066  moVector3<Real> kP0, kP1;
1067  if (!pkP0)
1068  {
1069  kP0 = this->GetPosition(fT0);
1070  pkP0 = &kP0;
1071  }
1072  if (!pkP1)
1073  {
1074  kP1 = this->GetPosition(fT1);
1075  pkP1 = &kP1;
1076  }
1077  Real fInvDT = ((Real)1.0)/(fT1 - fT0);
1078  moVector3<Real> kA, kB = fInvDT*(*pkP1 - *pkP0);
1079 
1080  int iKey0, iKey1;
1081  Real fDt0, fDt1;
1082  GetKeyInfo(fT0,iKey0,fDt0);
1083  GetKeyInfo(fT1,iKey1,fDt1);
1084 
1085  Real fVariation;
1086  if (iKey0 < iKey1)
1087  {
1088  // accumulate full-segment variations
1089  fVariation = (Real)0.0;
1090  for (int i = iKey0+1; i < iKey1; i++)
1091  {
1092  kA = *pkP0 + (m_afTime[i] - fT0)*kB;
1093  fVariation += GetVariationKey(i,(Real)0.0,
1094  m_afTime[i+1]-m_afTime[i],kA,kB);
1095  }
1096 
1097  // add on partial first segment
1098  kA = *pkP0 + (m_afTime[iKey0] - fT0)*kB;
1099  fVariation += GetVariationKey(iKey0,fDt0,
1100  m_afTime[iKey0+1]-m_afTime[iKey0],kA,kB);
1101 
1102  // add on partial last segment
1103  kA = *pkP0 + (m_afTime[iKey1] - fT0)*kB;
1104  fVariation += GetVariationKey(iKey1,0.0f,fDt1,kA,kB);
1105  }
1106  else
1107  {
1108  kA = *pkP0 + (m_afTime[iKey0] - fT0)*kB;
1109  fVariation = GetVariationKey(iKey0,fDt0,fDt1,kA,kB);
1110  }
1111 
1112  return fVariation; }
1113 
1114 protected:
1117 
1119  Real* m_afTime;
1120 
1121  // These quantities are allocated by GetLength when they are needed the
1122  // first time. The allocations occur in InitializeLength (called by
1123  // GetLength), so this member function must be 'const'. In order to
1124  // allocate the arrays in a 'const' function, they must be declared as
1125  // 'mutable'.
1126  mutable Real* m_afLength;
1127  mutable Real* m_afAccumLength;
1128 
1129  void GetKeyInfo (Real fTime, int& riKey, Real& rfDt) const {
1130  if (fTime <= m_afTime[0])
1131  {
1132  riKey = 0;
1133  rfDt = (Real)0.0;
1134  }
1135  else if (fTime >= m_afTime[m_iSegments])
1136  {
1137  riKey = m_iSegments-1;
1138  rfDt = m_afTime[m_iSegments] - m_afTime[m_iSegments-1];
1139  }
1140  else
1141  {
1142  for (int i = 0; i < m_iSegments; i++)
1143  {
1144  if (fTime < m_afTime[i+1])
1145  {
1146  riKey = i;
1147  rfDt = fTime - m_afTime[i];
1148  break;
1149  }
1150  }
1151  }
1152  }
1153 
1154  void InitializeLength () const {
1155  m_afLength = new Real[m_iSegments];
1156  m_afAccumLength = new Real[m_iSegments];
1157 
1158  // arc lengths of the segments
1159  int iKey;
1160  for (iKey = 0; iKey < m_iSegments; iKey++)
1161  {
1162  m_afLength[iKey] = GetLengthKey(iKey,(Real)0.0,
1163  m_afTime[iKey+1]-m_afTime[iKey]);
1164  }
1165 
1166  // accumulative arc length
1167  m_afAccumLength[0] = m_afLength[0];
1168  for (iKey = 1; iKey < m_iSegments; iKey++)
1169  {
1170  m_afAccumLength[iKey] = m_afAccumLength[iKey-1] + m_afLength[iKey];
1171  }
1172  }
1173  virtual Real GetSpeedKey (int iKey, Real fTime) const = 0;
1174  virtual Real GetLengthKey (int iKey, Real fT0, Real fT1) const = 0;
1175  virtual Real GetVariationKey (int iKey, Real fT0, Real fT1,
1176  const moVector3<Real>& rkA, const moVector3<Real>& rkB) const = 0;
1177 
1178  static Real GetSpeedWithData (Real fTime, void* pvData) {
1179  moMultipleCurve3* pvThis = *(moMultipleCurve3**) pvData;
1180  int iKey = *(int*)((char*)pvData + sizeof(pvThis));
1181  return pvThis->GetSpeedKey(iKey,fTime);
1182  }
1183 };
1184 
1186 typedef moMultipleCurve3<MOfloat> moMultipleCurve3f;
1187 
1189 typedef moMultipleCurve3<MOdouble> moMultipleCurve3d;
1190 
1191 #endif
1192 
Real Length() const
moVector3< Real > GetTangent(Real fTime) const
Definition: moMathCurve.h:684
Real GetSpeed(Real fTime) const
Definition: moMathCurve.h:98
void GetKeyInfo(Real fTime, int &riKey, Real &rfDt) const
Definition: moMathCurve.h:1129
PointList * m_kNext
Definition: moMathCurve.h:250
moSingleCurve3< MOfloat > moSingleCurve3f
Definition: moMathCurve.h:922
virtual ~moCurve3()
Definition: moMathCurve.h:639
Real GetTotalLength() const
Definition: moMathCurve.h:106
moMultipleCurve2< MOfloat > moMultipleCurve2f
Definition: moMathCurve.h:623
Real * m_afAccumLength
Definition: moMathCurve.h:1127
virtual Real GetVariation(Real fT0, Real fT1, const moVector2< Real > *pkP0=0, const moVector2< Real > *pkP1=0) const
Definition: moMathCurve.h:495
Real SquaredLength() const
Real GetTime(Real fLength, int iIterations, Real fTolerance) const
Definition: moMathCurve.h:873
void SetTimeInterval(Real fTMin, Real fTMax)
Definition: moMathCurve.h:654
static Real GetSpeedWithData(Real fTime, void *pvData)
Definition: moMathCurve.h:916
moCurve3< MOfloat > moCurve3f
Definition: moMathCurve.h:851
void SubdivideByTime(int iNumPoints, moVector3< Real > *&rakPoint) const
Definition: moMathCurve.h:773
moMultipleCurve2(int iSegments, Real *afTime)
Definition: moMathCurve.h:368
static Real RombergIntegral(int iOrder, Real fA, Real fB, Function oF, void *pvUserData=0)
virtual Real GetLength(Real fT0, Real fT1) const
Definition: moMathCurve.h:868
f
Definition: jquery.js:71
moSingleCurve2< MOdouble > moSingleCurve2d
Definition: moMathCurve.h:358
void InitializeLength() const
Definition: moMathCurve.h:591
moMultipleCurve3< MOfloat > moMultipleCurve3f
Definition: moMathCurve.h:1186
Real GetTotalLength() const
Definition: moMathCurve.h:680
const Real * GetTimes() const
Definition: moMathCurve.h:385
Clase base abstracta de donde deben derivar los objetos [virtual pura].
Definition: moAbstract.h:191
void InitializeLength() const
Definition: moMathCurve.h:1154
virtual Real GetSpeedKey(int iKey, Real fTime) const =0
virtual ~moMultipleCurve3()
Definition: moMathCurve.h:944
virtual ~moMultipleCurve2()
Definition: moMathCurve.h:375
int GetSegments() const
Definition: moMathCurve.h:382
moVector2< Real > GetTangent(Real fTime) const
Definition: moMathCurve.h:112
Real GetMinTime() const
Definition: moMathCurve.h:648
moSingleCurve3(Real fTMin, Real fTMax)
Definition: moMathCurve.h:863
#define LIBMOLDEO_API
Definition: moTypes.h:180
moCurve2< MOdouble > moCurve2d
Definition: moMathCurve.h:283
virtual Real GetLength(Real fT0, Real fT1) const
Definition: moMathCurve.h:959
Real m_fTMin
Definition: moMathCurve.h:808
virtual Real GetVariation(Real fT0, Real fT1, const moVector3< Real > *pkP0=0, const moVector3< Real > *pkP1=0) const
Definition: moMathCurve.h:1059
void SetTimeInterval(Real fTMin, Real fTMax)
Definition: moMathCurve.h:82
virtual ~moCurve2()
Definition: moMathCurve.h:61
void GetFrame(Real fTime, moVector2< Real > &rkPosition, moVector2< Real > &rkTangent, moVector2< Real > &rkNormal) const
Definition: moMathCurve.h:129
void SubdivideByLength(int iNumPoints, moVector2< Real > *&rakPoint) const
Definition: moMathCurve.h:180
PointList(const moVector2< Real > &rkPoint, PointList *pkNext)
Definition: moMathCurve.h:243
moTypes MOint moText moParamIndex moParamReference int iRow int int i int i
Definition: all_f.js:18
Real Normalize()
Definition: moMathVector.h:179
Real GetSpeed(Real fTime) const
Definition: moMathCurve.h:674
Real m_fTMin
Definition: moMathCurve.h:237
Real GetMinTime() const
Definition: moMathCurve.h:70
void SubdivideByVariation(Real fT0, const moVector2< Real > &rkP0, Real fT1, const moVector2< Real > &rkP1, Real fMinVariation, int iLevel, int &riNumPoints, PointList *&rpkList) const
Definition: moMathCurve.h:253
moVector2< Real > GetNormal(Real fTime) const
Definition: moMathCurve.h:120
virtual Real GetTime(Real fLength, int iIterations=32, Real fTolerance=(Real) 1e-06) const
Definition: moMathCurve.h:992
Real GetTorsion(Real fTime) const
Definition: moMathCurve.h:752
void GetKeyInfo(Real fTime, int &riKey, Real &rfDt) const
Definition: moMathCurve.h:566
moMultipleCurve3(int iSegments, Real *afTime)
Definition: moMathCurve.h:935
Real * m_afAccumLength
Definition: moMathCurve.h:564
void SubdivideByVariation(Real fMinVariation, int iMaxLevel, int &riNumPoints, moVector2< Real > *&rakPoint) const
Definition: moMathCurve.h:199
virtual Real GetSpeedKey(int iKey, Real fTime) const =0
Real Dot(const moVector3 &rkV) const
void SubdivideByTime(int iNumPoints, moVector2< Real > *&rakPoint) const
Definition: moMathCurve.h:159
moCurve2< MOfloat > moCurve2f
Definition: moMathCurve.h:280
void SubdivideByLength(int iNumPoints, moVector3< Real > *&rakPoint) const
Definition: moMathCurve.h:789
static Real GetSpeedWithData(Real fTime, void *pvData)
Definition: moMathCurve.h:348
Real GetMaxTime() const
Definition: moMathCurve.h:76
Real Normalize()
moMultipleCurve3< MOdouble > moMultipleCurve3d
Definition: moMathCurve.h:1189
Real GetCurvature(Real fTime) const
Definition: moMathCurve.h:139
function e
Definition: jquery.js:71
moSingleCurve2< MOfloat > moSingleCurve2f
Definition: moMathCurve.h:355
moVector3< Real > GetBinormal(Real fTime) const
Definition: moMathCurve.h:700
void SubdivideByVariation(Real fT0, const moVector3< Real > &rkP0, Real fT1, const moVector3< Real > &rkP1, Real fMinVariation, int iLevel, int &riNumPoints, PointList *&rpkList) const
Definition: moMathCurve.h:824
virtual Real GetLength(Real fT0, Real fT1) const
Definition: moMathCurve.h:299
virtual Real GetLength(Real fT0, Real fT1) const
Definition: moMathCurve.h:390
virtual Real GetTime(Real fLength, int iIterations=32, Real fTolerance=(Real) 1e-06) const
Definition: moMathCurve.h:429
moCurve3< MOdouble > moCurve3d
Definition: moMathCurve.h:854
PointList(const moVector3< Real > &rkPoint, PointList *pkNext)
Definition: moMathCurve.h:814
moVector3 Cross(const moVector3 &rkV) const
PointList * m_kNext
Definition: moMathCurve.h:821
Real SquaredLength() const
Definition: moMathVector.h:173
static Real GetSpeedWithData(Real fTime, void *pvData)
Definition: moMathCurve.h:615
Definition: moMath.h:64
const Real * GetTimes() const
Definition: moMathCurve.h:954
moCurve2(Real fTMin, Real fTMax)
Definition: moMathCurve.h:54
Real DotPerp(const moVector2 &rkV) const
returns DotPerp((x,y),(V.x,V.y)) = x*V.y - y*V.x
Definition: moMathVector.h:212
moVector2< Real > m_kPoint
Definition: moMathCurve.h:249
static Real Pow(Real fBase, Real fExponent)
Definition: moMath.h:250
int GetSegments() const
Definition: moMathCurve.h:951
moVector2 Perp() const
returns (y,-x)
Definition: moMathVector.h:199
moSingleCurve3< MOdouble > moSingleCurve3d
Definition: moMathCurve.h:925
moVector3< Real > GetNormal(Real fTime) const
Definition: moMathCurve.h:690
void GetFrame(Real fTime, moVector3< Real > &rkPosition, moVector3< Real > &rkTangent, moVector3< Real > &rkNormal, moVector3< Real > &rkBinormal) const
Definition: moMathCurve.h:714
Real Length() const
Definition: moMathVector.h:170
moVector3< Real > m_kPoint
Definition: moMathCurve.h:820
moMultipleCurve2< MOdouble > moMultipleCurve2d
Definition: moMathCurve.h:626
Real GetCurvature(Real fTime) const
Definition: moMathCurve.h:731
moSingleCurve2(Real fTMin, Real fTMax)
Definition: moMathCurve.h:294
Real GetMaxTime() const
Definition: moMathCurve.h:651
static Real GetSpeedWithData(Real fTime, void *pvData)
Definition: moMathCurve.h:1178
virtual Real GetTime(Real fLength, int iIterations=32, Real fTolerance=(Real) 1e-06) const
Definition: moMathCurve.h:306
moCurve3(Real fTMin, Real fTMax)
Definition: moMathCurve.h:635