MathTools.cpp
Go to the documentation of this file.
1 // *****************************************************************
2 // Filename: AspectGraphProcessor.cpp
3 // Copyright: Kai Welke, Chair Prof. Dillmann (IAIM),
4 // Institute for Computer Science and Engineering (CSE),
5 // University of Karlsruhe. All rights reserved.
6 // Author: Kai Welke
7 // Date: 12.06.2007
8 // *****************************************************************
9 
10 // *****************************************************************
11 // includes
12 // *****************************************************************
13 #include "MathTools.h"
14 
15 #include <cmath>
16 
17 //#include "Base/Tools/DebugMemory.h"
18 
19 
20 // **********************************************************
21 // transformation on sphere coordinates and paths
22 // **********************************************************
23 // returns transformation from p1 -> p2
26 {
27  TSphereCoord start1, start2, end1, end2;
28  start1 = p1->at(0).Position;
29  end1 = p1->at(p1->size() - 1).Position;
30  start2 = p2->at(0).Position;
31  end2 = p2->at(p2->size() - 1).Position;
32 
33  return determineTransformation(start1, start2, end1, end2);
34 }
35 
36 TPath*
38 {
39  TPath* pResulting = new TPath();
40 
41  if (pPath->size() < 2)
42  {
43  printf("ERROR: path is too short\n");
44  delete pResulting;
45  return nullptr;
46  }
47 
48  // copy path and transform
49  for (auto element : *pPath)
50  {
51  TSphereCoord res = MathTools::transform(element.Position, transform);
52  element.Position = res;
53 
54  pResulting->push_back(element);
55  }
56 
57  return pResulting;
58 }
59 
60 TPath*
62 {
63  TPath* pResulting = new TPath();
64 
65  if (pPath->size() < 2)
66  {
67  printf("ERROR: path is too short\n");
68  delete pResulting;
69  return nullptr;
70  }
71 
72  // copy path and transform
73  for (auto element : *pPath)
74  {
75  TSphereCoord res = MathTools::inverseTransform(element.Position, transform);
76  element.Position = res;
77 
78  pResulting->push_back(element);
79  }
80 
81  return pResulting;
82 }
83 
86  TSphereCoord start2,
87  TSphereCoord end1,
88  TSphereCoord end2)
89 {
90  TTransform result;
91 
92  // first determine alpha and beta and beta axis
93  float fAlpha, fBeta;
94  Eigen::Vector3d betaAxis;
95  determineTransformationAlphaBeta(start1, start2, fAlpha, fBeta, betaAxis);
96  result.fAlpha = fAlpha;
97  result.fBeta = fBeta;
98  result.betaAxis = betaAxis;
99 
100  // calculate angular for psi rotation
101 
102  // apply transform to first path end
103  TSphereCoord end1_transformed = transformAlphaBeta(end1, fAlpha, fBeta, betaAxis);
104 
105  Eigen::Vector3d end1_transformed_v, start2_v, end2_v;
106  convert(end1_transformed, end1_transformed_v);
107  convert(start2, start2_v);
108  convert(end2, end2_v);
109 
110  // calculate angle between start2 <-> end1_tranformed ; start2 <-> end2
111  Eigen::Vector3d zero = Eigen::Vector3d::Zero();
112 
113  Eigen::Vector3d line1 = MathTools::dropAPerpendicular(end1_transformed_v, zero, start2_v);
114  Eigen::Vector3d line2 = MathTools::dropAPerpendicular(end2_v, zero, start2_v);
115  line1 -= end1_transformed_v;
116  line2 -= end2_v;
117 
118  float fPsi = MathTools::AngleAndDirection(line1, line2, start2_v) * 180.0 / M_PI;
119 
120  result.fPsi = fPsi;
121  result.psiAxis = start2_v;
122 
123  return result;
124 }
125 
128 {
129  // first apply alpha , beta
130  TSphereCoord rotated_ab =
131  transformAlphaBeta(sc, transform.fAlpha, transform.fBeta, transform.betaAxis);
132 
133  Eigen::Vector3d rotated_ab_v;
134 
135  convert(rotated_ab, rotated_ab_v);
136 
137  // now apply final rotation
138  Eigen::AngleAxisd rot(-transform.fPsi * M_PI / 180.0, transform.psiAxis);
139  rotated_ab_v = rot.matrix() * rotated_ab_v;
140 
141  TSphereCoord rotated;
142  convert(rotated_ab_v, rotated);
143 
144  return rotated;
145 }
146 
149 {
150  Eigen::Vector3d sc_v;
151  convert(sc, sc_v);
152 
153  // first rotate
154  Eigen::AngleAxisd rot(transform.fPsi * M_PI / 180.0, transform.psiAxis);
155  sc_v = rot.matrix() * sc_v;
156 
157  TSphereCoord rotated;
158  convert(sc_v, rotated);
159 
161  rotated, transform.fAlpha, transform.fBeta, transform.betaAxis);
162 }
163 
164 // determine alpha and beta of a transform
165 // fAlpha: rotation around the z axis in counterclockwise direction considering the positive z-axis
166 // fBeta: rotation around the rotated y axis in counterclockwise direction considering the positive y-axis
167 void
169  TSphereCoord sc2,
170  float& fAlpha,
171  float& fBeta,
172  Eigen::Vector3d& betaAxis)
173 {
174  Eigen::Vector3d vector1, vector2;
175  convert(sc1, vector1);
176  convert(sc2, vector2);
177 
178  // project both vectors to xy plane
179  Eigen::Vector3d vector1_xy, vector2_xy;
180 
181  vector1_xy = vector1;
182  vector2_xy = vector2;
183 
184  vector1_xy(2) = 0.0;
185  vector2_xy(2) = 0.0;
186 
187  // calculate first angle from vec1_projected to vec2_projected with normale z
188  Eigen::Vector3d normal = Eigen::Vector3d::UnitZ();
189 
190  if (vector1_xy.norm() == 0.0 || vector2_xy.norm() == 0)
191  {
192  fAlpha = ((sc2.fTheta - sc1.fTheta) / 180.0 * M_PI);
193  }
194  else
195  {
196  fAlpha = MathTools::AngleAndDirection(vector1_xy, vector2_xy, normal);
197  }
198 
199  // now rotate first vector with alpha
200  Eigen::Vector3d rotated1, rotated_y;
201 
202  // the vector to rotate
203 
204  rotated1 = vector1;
205  // set rotation: alpha around z-axis to transform v1 in same plane as v2
206 
207  Eigen::AngleAxisd rotation(fAlpha, Eigen::Vector3d::UnitZ());
208  ;
209  Eigen::AngleAxisd rotation_yaxis(sc2.fTheta, Eigen::Vector3d::UnitZ());
210 
211  // we need normal for angle calculateion, so also rotate x-axis
212  rotated_y << 0.0, 1.0, 0.0;
213 
214  // rotate vector and x-axis
215 
216 
217  rotated1 = rotation.matrix() * rotated1;
218 
219  rotated_y = rotation_yaxis.matrix() * rotated_y;
220 
221  betaAxis = rotated_y;
222 
223  // calculate angle between both vectors
224  fBeta = MathTools::AngleAndDirection(rotated1, vector2, rotated_y);
225 
226  fAlpha *= 180.0 / M_PI;
227  fBeta *= 180.0 / M_PI;
228 }
229 
231 MathTools::transformAlphaBeta(TSphereCoord sc, float fAlpha, float fBeta, Eigen::Vector3d betaAxis)
232 {
233  TSphereCoord result;
234  Eigen::Vector3d vector1, vector1_rotated;
235  convert(sc, vector1);
236 
237  // rotate around positive z-axis
238  Eigen::AngleAxisd rotation_alpha(fAlpha / 180.0 * M_PI, Eigen::Vector3d::UnitZ());
239 
240  // rotate vector aroun z axis
241  vector1_rotated = rotation_alpha.matrix() * vector1;
242  // rotate vector with beta around betaAxis
243  Eigen::AngleAxisd rot(-fBeta / 180.0 * M_PI, betaAxis);
244 
245  vector1_rotated = rot.matrix() * vector1_rotated;
246 
247  convert(vector1_rotated, result);
248 
249  return result;
250 }
251 
254  float fAlpha,
255  float fBeta,
256  Eigen::Vector3d betaAxis)
257 {
258  Eigen::Vector3d vector1;
259  convert(sc, vector1);
260 
261  // do inverse of beta axis rotation
262  Eigen::AngleAxisd rot(fBeta / 180.0 * M_PI, betaAxis);
263  vector1 = rot.matrix() * vector1;
264 
265  // do inverse of zaxis rotation
266  Eigen::AngleAxisd rotation_alpha(-fAlpha / 180.0 * M_PI, Eigen::Vector3d::UnitZ());
267 
268  // rotate vector aroun z axis
269  vector1 = rotation_alpha * vector1;
270 
271  TSphereCoord result;
272  convert(vector1, result);
273 
274  return result;
275 }
276 
277 // **********************************************************
278 // calculations on sphere coordinates
279 // **********************************************************
280 float
282 {
283  float u1, v1, u2, v2;
284 
285  u1 = p2.fPhi - p1.fPhi;
286  v1 = p2.fTheta - p1.fTheta;
287  u2 = p3.fPhi - p1.fPhi;
288  v2 = p3.fTheta - p1.fTheta;
289 
290  return u1 * v2 - v1 * u2;
291 }
292 
293 double
294 MathTools::Angle(Eigen::Vector3d vec1, Eigen::Vector3d vec2)
295 {
296  double r = vec1.dot(vec2) / (vec1.norm() * vec2.norm());
297  r = std::min(1.0, std::max(-1.0, r));
298  return std::acos(r);
299 }
300 
301 float
303 {
304  Eigen::Vector3d vec1, vec2;
305  p1.fDistance = 1.0f;
306  p2.fDistance = 1.0f;
307 
308  convert(p1, vec1);
309  convert(p2, vec2);
310 
311  float fAngle = (float)MathTools::Angle(vec1, vec2);
312 
313  // length of circular arc
314  // not necessary because Math3d::Angle returns a value in radians
315  //float fDist = float( (2 * M_PI * fAngle ) / 360.0f);
316 
317  return fAngle;
318 }
319 
320 float
322 {
323  // never use this!!!!
324  TSphereCoord diff;
325  diff.fPhi = p1.fPhi - p2.fPhi;
326  diff.fTheta = p1.fTheta - p2.fTheta;
327 
328  float fAngle = sqrt(diff.fPhi * diff.fPhi + diff.fTheta * diff.fTheta);
329 
330  return fAngle;
331 }
332 
333 // **********************************************************
334 // extended 2d Math
335 // **********************************************************
336 bool
337 MathTools::IntersectLines(Eigen::Vector2d p1,
338  Eigen::Vector2d m1,
339  Eigen::Vector2d p2,
340  Eigen::Vector2d m2,
341  Eigen::Vector2d& res)
342 {
343  // calculate perpendicular bisector of sides
344  float dx = float(p1(0) - p2(0));
345  float dy = float(p1(1) - p2(1));
346 
347  // now from
348  // g1: g1(x,y) = (p1x,p1y) + (m1x,m1y) * c1
349  // g2: g2(x,y) = (p2x,p2y) + (m2x,m2y) * c2
350  // -->
351  // g1(x,y) = g2(x,y)
352  // -->
353  // (p1x,p1y) + (m1x,m1y) * c1 = (p2x,p2y) + (m2x,m2y) * c2
354  // (p1x,p1y) - (p2x,p2y) = (dx,dy) = (m2x,m2y) * c2 - (m1x,m1y) * c1
355  // -->
356  // dx = m2x * c2 - m1x * c1, dy = m2y * c2 - m1y * c1
357  // c1 = (m2y * c2 - dy) / m1y
358  // dx = m2x * c2 - m1x * (m2y * c2 - dy) / m1y
359 
360  float z = float(dx - (m1(0) * dy) / m1(1));
361  float n = float(m2(0) - (m1(0) * m2(1)) / m1(1));
362 
363  float c2;
364 
365  if (n == 0)
366  {
367  return false;
368  }
369  else
370  {
371  c2 = z / n;
372  }
373 
374  res(0) = p2(0) + c2 * m2(0);
375  res(1) = p2(1) + c2 * m2(1);
376 
377  return true;
378 }
379 
380 // **********************************************************
381 // extended 3d Math
382 // **********************************************************
383 // checked and working
384 float
385 MathTools::AngleAndDirection(Eigen::Vector3d vector1,
386  Eigen::Vector3d vector2,
387  Eigen::Vector3d normal)
388 {
389  double fAngle = MathTools::Angle(vector1, vector2);
390 
391  Eigen::Vector3d axis = vector1.cross(vector2);
392 
393  // compare axis and normal
394  normal.normalize();
395 
396  double c = normal.dot(vector1);
397 
398  axis += vector1;
399  double d = normal.dot(axis) - c;
400 
401 
402  if (d < 0)
403  {
404  return 2 * M_PI - fAngle;
405  }
406 
407  return (float)fAngle;
408 }
409 
410 // checked and working
411 Eigen::Vector3d
412 MathTools::dropAPerpendicular(Eigen::Vector3d point,
413  Eigen::Vector3d linepoint,
414  Eigen::Vector3d linevector)
415 {
416  // helping plane normal (ax + by + cz + d = 0)
417  Eigen::Vector3d plane_normal = linevector; // (a,b,c)
418  float d = (float)-plane_normal.dot(point);
419 
420  // calculate k from plane and line intersection
421  float z = float(-plane_normal(0) * linepoint(0) - plane_normal(1) * linepoint(1) -
422  plane_normal(2) * linepoint(2) - d);
423  float n = float(plane_normal(0) * linevector(0) + plane_normal(1) * linevector(1) +
424  plane_normal(2) * linevector(2));
425 
426  float k = z / n;
427 
428  // calculate line from line equation
429  linevector = k * linevector;
430  linevector += linepoint;
431 
432  return linevector;
433 }
434 
435 // **********************************************************
436 // conversions
437 // **********************************************************
438 // checked and working
439 void
440 MathTools::convert(TSphereCoord in, Eigen::Vector3d& out)
441 {
442  // alpha is azimuth, beta is polar angle
443  in.fPhi *= M_PI / 180.0f;
444  in.fTheta *= M_PI / 180.0f;
445 
446  // OLD and wrong??
447  // out.x = in.fDistance * sin(in.fPhi) * cos(in.fTheta);
448  // out.y = in.fDistance * sin(in.fPhi) * sin(in.fTheta);
449  // out.z = in.fDistance * cos(in.fPhi);
450 
451  Eigen::Vector3d vector = Eigen::Vector3d::UnitZ();
452  Eigen::AngleAxisd rotation_y(in.fPhi, Eigen::Vector3d::UnitY());
453  Eigen::AngleAxisd rotation_z(in.fTheta, Eigen::Vector3d::UnitZ());
454 
455 
456  // first rotate around y axis with phi
457  vector = rotation_y.matrix() * vector;
458 
459  // second rotate around z with theta
460  vector = rotation_z.matrix() * vector;
461 
462  out = vector;
463 }
464 
465 void
467 {
468  convert(in, out);
469  out *= in.fDistance;
470 }
471 
472 void
473 MathTools::convert(TSphereCoord in, Eigen::Vector3f& out)
474 {
475  Eigen::Vector3d vec;
476  convert(in, vec);
477  out = vec.cast<float>();
478 }
479 
480 // checked and working
481 void
482 MathTools::convert(Eigen::Vector3d in, TSphereCoord& out)
483 {
484  // alpha is azimuth, beta is polar angle
485  out.fDistance = in.norm();
486 
487  float fAngle = in(2) / out.fDistance;
488 
489  if (fAngle < -1.0f)
490  {
491  fAngle = -1.0f;
492  }
493 
494  if (fAngle > 1.0f)
495  {
496  fAngle = 1.0f;
497  }
498 
499  out.fPhi = (float)acos(fAngle);
500 
501  out.fTheta = (float)atan2(in(1), in(0));
502 
503  // convert to angles and correct interval
504  out.fPhi /= M_PI / 180.0f;
505  out.fTheta /= M_PI / 180.0f;
506 
507  // only positive rotations
508  if (out.fTheta < 0.0)
509  {
510  out.fTheta = 360.0f + out.fTheta;
511  }
512 
513  // be aware of limit
514  if (out.fPhi > 180.0)
515  {
516  out.fPhi = out.fPhi - 180.0f;
517  }
518 }
519 
520 void
521 MathTools::convert(Eigen::Vector3f in, TSphereCoord& out)
522 {
523  Eigen::Vector3d vec(in(0), in(1), in(2));
524  convert(vec, out);
525 }
MathTools::transformAlphaBeta
static TSphereCoord transformAlphaBeta(TSphereCoord sc, float fAlpha, float fBeta, Eigen::Vector3d betaAxis)
Definition: MathTools.cpp:231
MathTools::determineTransformationAlphaBeta
static void determineTransformationAlphaBeta(TSphereCoord sc1, TSphereCoord sc2, float &fAlpha, float &fBeta, Eigen::Vector3d &betaAxis)
Definition: MathTools.cpp:168
GfxTL::vec2
VectorXD< 2, float > vec2
Definition: VectorXD.h:724
TSphereCoord::fTheta
float fTheta
Definition: Structs.h:27
TTransform::fBeta
float fBeta
Definition: Structs.h:46
TTransform::fAlpha
float fAlpha
Definition: Structs.h:45
MathTools::inverseTransformAlphaBeta
static TSphereCoord inverseTransformAlphaBeta(TSphereCoord sc, float fAlpha, float fBeta, Eigen::Vector3d betaAxis)
Definition: MathTools.cpp:253
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:46
MathTools::AngleAndDirection
static float AngleAndDirection(Eigen::Vector3d vector1, Eigen::Vector3d vector2, Eigen::Vector3d normal)
Definition: MathTools.cpp:385
TTransform::betaAxis
Eigen::Vector3d betaAxis
Definition: Structs.h:47
MathTools::convertWithDistance
static void convertWithDistance(TSphereCoord in, Eigen::Vector3d &out)
Definition: MathTools.cpp:466
TTransform
Definition: Structs.h:43
MathTools::determineTransformation
static TTransform determineTransformation(TSphereCoord start1, TSphereCoord start2, TSphereCoord end1, TSphereCoord end2)
Definition: MathTools.cpp:85
TSphereCoord::fPhi
float fPhi
Definition: Structs.h:26
MathTools::inverseTransform
static TSphereCoord inverseTransform(TSphereCoord sc, TTransform transform)
Definition: MathTools.cpp:148
TTransform::fPsi
float fPsi
Definition: Structs.h:48
M_PI
#define M_PI
Definition: MathTools.h:17
MathTools.h
MathTools::determinePathTransformation
static TTransform determinePathTransformation(TPath *p1, TPath *p2)
Definition: MathTools.cpp:25
MathTools::CalculateCrossProductFromDifference
static float CalculateCrossProductFromDifference(TSphereCoord p1, TSphereCoord p2, TSphereCoord p3)
Definition: MathTools.cpp:281
MathTools::getDistance
static float getDistance(TSphereCoord p1, TSphereCoord p2, float fRadius)
Definition: MathTools.cpp:321
max
T max(T t1, T t2)
Definition: gdiam.h:51
MathTools::transform
static TSphereCoord transform(TSphereCoord sc, TTransform transform)
Definition: MathTools.cpp:127
TTransform::psiAxis
Eigen::Vector3d psiAxis
Definition: Structs.h:49
MathTools::transformPath
static TPath * transformPath(TTransform transform, TPath *pPath)
Definition: MathTools.cpp:37
armarx::transform
auto transform(const Container< InputT, Alloc > &in, OutputT(*func)(InputT const &)) -> Container< OutputT, typename std::allocator_traits< Alloc >::template rebind_alloc< OutputT >>
Convenience function (with less typing) to transform a container of type InputT into the same contain...
Definition: algorithm.h:351
GfxTL::vec1
VectorXD< 1, float > vec1
Definition: VectorXD.h:723
GfxTL::sqrt
VectorXD< D, T > sqrt(const VectorXD< D, T > &a)
Definition: VectorXD.h:704
float
#define float
Definition: 16_Level.h:22
MathTools::IntersectLines
static bool IntersectLines(Eigen::Vector2d p1, Eigen::Vector2d m1, Eigen::Vector2d p2, Eigen::Vector2d m2, Eigen::Vector2d &res)
Definition: MathTools.cpp:337
MathTools::Angle
static double Angle(Eigen::Vector3d vec1, Eigen::Vector3d vec2)
Definition: MathTools.cpp:294
TSphereCoord::fDistance
float fDistance
Definition: Structs.h:25
MathTools::inverseTransformPath
static TPath * inverseTransformPath(TTransform transform, TPath *pPath)
Definition: MathTools.cpp:61
min
T min(T t1, T t2)
Definition: gdiam.h:44
MathTools::getDistanceOnArc
static float getDistanceOnArc(TSphereCoord p1, TSphereCoord p2)
Definition: MathTools.cpp:302
TSphereCoord
Definition: Structs.h:23
MathTools::convert
static void convert(TSphereCoord in, Eigen::Vector3d &out)
Definition: MathTools.cpp:440
MathTools::dropAPerpendicular
static Eigen::Vector3d dropAPerpendicular(Eigen::Vector3d point, Eigen::Vector3d linepoint, Eigen::Vector3d linevector)
Definition: MathTools.cpp:412
TPath
std::vector< TPathElement > TPath
Definition: Structs.h:63