libmoldeo (Moldeo 1.0 Core)  1.0
libmoldeo is the group of objects and functions that executes the basic operations of Moldeo 1.0 Platform.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
moMathVector.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2 
3  moMathVector.cpp
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 #include "moMathVector.h"
39 
40 #include "moArray.h"
41 moDefineDynamicArray(moVector2iArray)
42 moDefineDynamicArray(moVector2fArray)
43 moDefineDynamicArray(moVector2fpArray)
44 moDefineDynamicArray(moVector2dArray)
45 
46 // moVector2 class ------------------------------------------------------------
47 /*
48 template <class Real>
49 moVector2<Real>::moVector2 ()
50 {
51  // uninitialized for performance in array construction
52 }
53 
54 
55 template <class Real>
56 moVector2<Real>::moVector2 (Real fX, Real fY)
57 {
58  m_afTuple[0] = fX;
59  m_afTuple[1] = fY;
60 }
61 
62 template <class Real>
63 moVector2<Real>::moVector2 (const Real* afTuple)
64 {
65  m_afTuple[0] = afTuple[0];
66  m_afTuple[1] = afTuple[1];
67 }
68 
69 template <class Real>
70 moVector2<Real>::moVector2 (const moVector2& rkV) : moAbstract(rkV)
71 {
72  m_afTuple[0] = rkV.m_afTuple[0];
73  m_afTuple[1] = rkV.m_afTuple[1];
74 }
75 
76 template <class Real>
77 int moVector2<Real>::CompareArrays (const moVector2& rkV) const
78 {
79  return memcmp(m_afTuple,rkV.m_afTuple,2*sizeof(Real));
80 }
81 
82 template <class Real>
83 bool moVector2<Real>::operator== (const moVector2& rkV) const
84 {
85  return CompareArrays(rkV) == 0;
86 }
87 
88 template <class Real>
89 bool moVector2<Real>::operator!= (const moVector2& rkV) const
90 {
91  return CompareArrays(rkV) != 0;
92 }
93 
94 template <class Real>
95 bool moVector2<Real>::operator< (const moVector2& rkV) const
96 {
97  return CompareArrays(rkV) < 0;
98 }
99 
100 template <class Real>
101 bool moVector2<Real>::operator<= (const moVector2& rkV) const
102 {
103  return CompareArrays(rkV) <= 0;
104 }
105 
106 template <class Real>
107 bool moVector2<Real>::operator> (const moVector2& rkV) const
108 {
109  return CompareArrays(rkV) > 0;
110 }
111 
112 template <class Real>
113 bool moVector2<Real>::operator>= (const moVector2& rkV) const
114 {
115  return CompareArrays(rkV) >= 0;
116 }
117 
118 template <class Real>
119 moVector2<Real> moVector2<Real>::operator+ (const moVector2& rkV) const
120 {
121  moVector2<Real> ret(m_afTuple[0]+rkV.m_afTuple[0], m_afTuple[1]+rkV.m_afTuple[1]);
122  return ret;
123 }
124 
125 template <class Real>
126 moVector2<Real> moVector2<Real>::operator- (const moVector2& rkV) const
127 {
128  moVector2<Real> ret(m_afTuple[0]-rkV.m_afTuple[0], m_afTuple[1]-rkV.m_afTuple[1]);
129  return ret;
130 }
131 */
132 /*
133 template <class Real>
134 moVector2<Real> moVector2<Real>::operator* (Real fScalar) const
135 {
136  moVector2<Real> ret(fScalar*m_afTuple[0], fScalar*m_afTuple[1]);
137  return ret;
138 }
139 
140 template <class Real>
141 moVector2<Real> moVector2<Real>::operator/ (Real fScalar) const
142 {
143  moVector2 kQuot;
144 
145  if (fScalar != (Real)0.0)
146  {
147  Real fInvScalar = ((Real)1.0)/fScalar;
148  kQuot.m_afTuple[0] = fInvScalar*m_afTuple[0];
149  kQuot.m_afTuple[1] = fInvScalar*m_afTuple[1];
150  }
151  else
152  {
153  kQuot.m_afTuple[0] = moMath<Real>::MAX_REAL;
154  kQuot.m_afTuple[1] = moMath<Real>::MAX_REAL;
155  }
156 
157  return kQuot;
158 }
159 
160 template <class Real>
161 moVector2<Real> moVector2<Real>::operator- () const
162 {
163  moVector2<Real> ret(-m_afTuple[0], -m_afTuple[1]);
164  return ret;
165 }
166 
167 template <class Real>
168 moVector2<Real>& moVector2<Real>::operator/= (Real fScalar)
169 {
170  if (fScalar != (Real)0.0)
171  {
172  Real fInvScalar = ((Real)1.0)/fScalar;
173  m_afTuple[0] *= fInvScalar;
174  m_afTuple[1] *= fInvScalar;
175  }
176  else
177  {
178  m_afTuple[0] = moMath<Real>::MAX_REAL;
179  m_afTuple[1] = moMath<Real>::MAX_REAL;
180  }
181 
182  return *this;
183 }
184 */
185 /*
186 // vector operations
187 template <class Real>
188 Real moVector2<Real>::Length () const
189 {
190  return moMath<Real>::Sqrt(m_afTuple[0]*m_afTuple[0] + m_afTuple[1]*m_afTuple[1]);
191 }
192 
193 template <class Real>
194 Real moVector2<Real>::SquaredLength () const
195 {
196  return m_afTuple[0]*m_afTuple[0] + m_afTuple[1]*m_afTuple[1];
197 }
198 
199 template <class Real>
200 Real moVector2<Real>::Dot (const moVector2& rkV) const
201 {
202  return m_afTuple[0]*rkV.m_afTuple[0] + m_afTuple[1]*rkV.m_afTuple[1];
203 }
204 */
205 /*
206 template <class Real>
207 Real moVector2<Real>::Normalize ()
208 {
209  Real fLength = Length();
210 
211  if (fLength > moMath<Real>::ZERO_TOLERANCE)
212  {
213  Real fInvLength = ((Real)1.0)/fLength;
214  m_afTuple[0] *= fInvLength;
215  m_afTuple[1] *= fInvLength;
216  }
217  else
218  {
219  fLength = (Real)0.0;
220  m_afTuple[0] = (Real)0.0;
221  m_afTuple[1] = (Real)0.0;
222  }
223 
224  return fLength;
225 }
226 
227  // returns (y,-x)
228 template <class Real>
229 moVector2<Real> moVector2<Real>::Perp () const
230 {
231  moVector2<Real> ret(m_afTuple[1],-m_afTuple[0]);
232  return ret;
233 }
234 
235 // returns (y,-x)/sqrt(x*x+y*y)
236 template <class Real>
237 moVector2<Real> moVector2<Real>::UnitPerp () const
238 {
239  moVector2 kPerp(m_afTuple[1],-m_afTuple[0]);
240  kPerp.Normalize();
241  return kPerp;
242 }
243 
244 // returns DotPerp((x,y),(V.x,V.y)) = x*V.y - y*V.x
245 template <class Real>
246 Real moVector2<Real>::DotPerp (const moVector2& rkV) const
247 {
248  return m_afTuple[0]*rkV.m_afTuple[1] - m_afTuple[1]*rkV.m_afTuple[0];
249 }
250 
251 template <class Real>
252 void moVector2<Real>::GetBarycentrics (const moVector2& rkV0, const moVector2& rkV1,
253  const moVector2& rkV2, Real afBary[3]) const
254 {
255  // compute the vectors relative to V2 of the triangle
256  moVector2 akDiff[3] =
257  {
258  rkV0 - rkV2,
259  rkV1 - rkV2,
260  *this - rkV2
261  };
262 
263  // If the vertices have large magnitude, the linear system of equations
264  // for computing barycentric coordinates can be ill-conditioned. To avoid
265  // this, uniformly scale the triangle edges to be of order 1. The scaling
266  // of all differences does not change the barycentric coordinates.
267  Real fMax = (Real)0.0;
268  int i;
269  for (i = 0; i < 2; i++)
270  {
271  for (int j = 0; j < 2; j++)
272  {
273  Real fValue = moMath<Real>::FAbs(akDiff[i][j]);
274  if (fValue > fMax)
275  {
276  fMax = fValue;
277  }
278  }
279  }
280 
281  // scale down only large data
282  if (fMax > (Real)1.0)
283  {
284  Real fInvMax = ((Real)1.0)/fMax;
285  for (i = 0; i < 3; i++)
286  {
287  akDiff[i] *= fInvMax;
288  }
289  }
290 
291  Real fDet = akDiff[0].DotPerp(akDiff[1]);
292  if (moMath<Real>::FAbs(fDet) > moMath<Real>::ZERO_TOLERANCE)
293  {
294  Real fInvDet = ((Real)1.0)/fDet;
295  afBary[0] = akDiff[2].DotPerp(akDiff[1])*fInvDet;
296  afBary[1] = akDiff[0].DotPerp(akDiff[2])*fInvDet;
297  afBary[2] = (Real)1.0 - afBary[0] - afBary[1];
298  }
299  else
300  {
301  // The triangle is a sliver. Determine the longest edge and
302  // compute barycentric coordinates with respect to that edge.
303  moVector2 kE2 = rkV0 - rkV1;
304  Real fMaxSqrLength = kE2.SquaredLength();
305  int iMaxIndex = 2;
306  Real fSqrLength = akDiff[1].SquaredLength();
307  if (fSqrLength > fMaxSqrLength)
308  {
309  iMaxIndex = 1;
310  fMaxSqrLength = fSqrLength;
311  }
312  fSqrLength = akDiff[0].SquaredLength();
313  if (fSqrLength > fMaxSqrLength)
314  {
315  iMaxIndex = 0;
316  fMaxSqrLength = fSqrLength;
317  }
318 
319  if (fMaxSqrLength > moMath<Real>::ZERO_TOLERANCE)
320  {
321  Real fInvSqrLength = ((Real)1.0)/fMaxSqrLength;
322  if (iMaxIndex == 0)
323  {
324  // P-V2 = t(V0-V2)
325  afBary[0] = akDiff[2].Dot(akDiff[0])*fInvSqrLength;
326  afBary[1] = (Real)0.0;
327  afBary[2] = (Real)1.0 - afBary[0];
328  }
329  else if (iMaxIndex == 1)
330  {
331  // P-V2 = t(V1-V2)
332  afBary[0] = (Real)0.0;
333  afBary[1] = akDiff[2].Dot(akDiff[1])*fInvSqrLength;
334  afBary[2] = (Real)1.0 - afBary[1];
335  }
336  else
337  {
338  // P-V1 = t(V0-V1)
339  akDiff[2] = *this - rkV1;
340  afBary[0] = akDiff[2].Dot(kE2)*fInvSqrLength;
341  afBary[1] = (Real)1.0 - afBary[0];
342  afBary[2] = (Real)0.0;
343  }
344  }
345  else
346  {
347  // triangle is a nearly a point, just return equal weights
348  afBary[0] = ((Real)1.0)/(Real)3.0;
349  afBary[1] = afBary[0];
350  afBary[2] = afBary[0];
351  }
352  }
353 }
354 
355 template <class Real>
356 void moVector2<Real>::Orthonormalize (moVector2& rkU, moVector2& rkV)
357 {
358  // If the input vectors are v0 and v1, then the Gram-Schmidt
359  // orthonormalization produces vectors u0 and u1 as follows,
360  //
361  // u0 = v0/|v0|
362  // u1 = (v1-(u0*v1)u0)/|v1-(u0*v1)u0|
363  //
364  // where |A| indicates length of vector A and A*B indicates dot
365  // product of vectors A and B.
366 
367  // compute u0
368  rkU.Normalize();
369 
370  // compute u1
371  Real fDot0 = rkU.Dot(rkV);
372  rkV -= rkU*fDot0;
373  rkV.Normalize();
374 }
375 
376 template <class Real>
377 void moVector2<Real>::GenerateOrthonormalBasis (moVector2& rkU, moVector2& rkV)
378 {
379  rkV.Normalize();
380  rkU = rkV.Perp();
381 }
382 
383 template <class Real>
384 void moVector2<Real>::ComputeExtremes (int iVQuantity, const moVector2* akPoint,
385  moVector2& rkMin, moVector2& rkMax)
386 {
387  if (!(iVQuantity > 0 && akPoint)) return;
388 
389  rkMin = akPoint[0];
390  rkMax = rkMin;
391  for (int i = 1; i < iVQuantity; i++)
392  {
393  const moVector2<Real>& rkPoint = akPoint[i];
394  for (int j = 0; j < 2; j++)
395  {
396  if (rkPoint[j] < rkMin[j])
397  {
398  rkMin[j] = rkPoint[j];
399  }
400  else if (rkPoint[j] > rkMax[j])
401  {
402  rkMax[j] = rkPoint[j];
403  }
404  }
405  }
406 }
407 
408 // Cosine between 'this' vector and rkV.
409 template <class Real>
410 Real moVector2<Real>::Cosine (const moVector2<Real>& rkV)
411 {
412  Real l = Length();
413  Real lv = rkV.Length();
414  if ((0 < l) && (0 < lv)) return Dot(rkV) / (l * lv);
415  else return 0;
416 }
417 // Angle between 'this' vector and rkV.
418 template <class Real>
419 Real moVector2<Real>::Angle (const moVector2<Real>& rkV) {
420  return moMath<Real>::ACos(Cosine(rkV));
421 }
422 */
423 template<> const moVector2<MOlong> moVector2<MOlong>::ZERO(0,0);
424 template<> const moVector2<MOlong> moVector2<MOlong>::UNIT_X(1,0);
425 template<> const moVector2<MOlong> moVector2<MOlong>::UNIT_Y(0,1);
426 template<> const moVector2<MOlong> moVector2<MOlong>::ONE(1,1);
427 
428 template<> const moVector2<MOfloat> moVector2<MOfloat>::ZERO(0.0f,0.0f);
429 template<> const moVector2<MOfloat> moVector2<MOfloat>::UNIT_X(1.0f,0.0f);
430 template<> const moVector2<MOfloat> moVector2<MOfloat>::UNIT_Y(0.0f,1.0f);
431 template<> const moVector2<MOfloat> moVector2<MOfloat>::ONE(1.0f,1.0f);
432 
433 template<> const moVector2<MOdouble> moVector2<MOdouble>::ZERO(0.0,0.0);
434 template<> const moVector2<MOdouble> moVector2<MOdouble>::UNIT_X(1.0,0.0);
435 template<> const moVector2<MOdouble> moVector2<MOdouble>::UNIT_Y(0.0,1.0);
436 template<> const moVector2<MOdouble> moVector2<MOdouble>::ONE(1.0,1.0);
437 
438 
#define MOfloat
Definition: moTypes.h:403
#define MOlong
Definition: moTypes.h:391
#define moDefineDynamicArray(name)
Definition: moArray.cpp:222
#define MOdouble
Definition: moTypes.h:404