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