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
36TPath*
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
60TPath*
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
167void
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
231MathTools::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// **********************************************************
280float
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
293double
294MathTools::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
301float
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
320float
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// **********************************************************
336bool
337MathTools::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
384float
385MathTools::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
411Eigen::Vector3d
412MathTools::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
439void
440MathTools::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
465void
467{
468 convert(in, out);
469 out *= in.fDistance;
470}
471
472void
473MathTools::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
481void
482MathTools::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
520void
521MathTools::convert(Eigen::Vector3f in, TSphereCoord& out)
522{
523 Eigen::Vector3d vec(in(0), in(1), in(2));
524 convert(vec, out);
525}
#define float
Definition 16_Level.h:22
#define M_PI
Definition MathTools.h:17
std::vector< TPathElement > TPath
Definition Structs.h:63
constexpr T c
static bool IntersectLines(Eigen::Vector2d p1, Eigen::Vector2d m1, Eigen::Vector2d p2, Eigen::Vector2d m2, Eigen::Vector2d &res)
static double Angle(Eigen::Vector3d vec1, Eigen::Vector3d vec2)
static void determineTransformationAlphaBeta(TSphereCoord sc1, TSphereCoord sc2, float &fAlpha, float &fBeta, Eigen::Vector3d &betaAxis)
static TSphereCoord inverseTransform(TSphereCoord sc, TTransform transform)
static TSphereCoord inverseTransformAlphaBeta(TSphereCoord sc, float fAlpha, float fBeta, Eigen::Vector3d betaAxis)
static TSphereCoord transformAlphaBeta(TSphereCoord sc, float fAlpha, float fBeta, Eigen::Vector3d betaAxis)
static TPath * inverseTransformPath(TTransform transform, TPath *pPath)
Definition MathTools.cpp:61
static float getDistanceOnArc(TSphereCoord p1, TSphereCoord p2)
static TPath * transformPath(TTransform transform, TPath *pPath)
Definition MathTools.cpp:37
static void convertWithDistance(TSphereCoord in, Eigen::Vector3d &out)
static float AngleAndDirection(Eigen::Vector3d vector1, Eigen::Vector3d vector2, Eigen::Vector3d normal)
static Eigen::Vector3d dropAPerpendicular(Eigen::Vector3d point, Eigen::Vector3d linepoint, Eigen::Vector3d linevector)
static TTransform determineTransformation(TSphereCoord start1, TSphereCoord start2, TSphereCoord end1, TSphereCoord end2)
Definition MathTools.cpp:85
static float CalculateCrossProductFromDifference(TSphereCoord p1, TSphereCoord p2, TSphereCoord p3)
static TSphereCoord transform(TSphereCoord sc, TTransform transform)
static float getDistance(TSphereCoord p1, TSphereCoord p2, float fRadius)
static void convert(TSphereCoord in, Eigen::Vector3d &out)
static TTransform determinePathTransformation(TPath *p1, TPath *p2)
Definition MathTools.cpp:25
float fDistance
Definition Structs.h:25
float fTheta
Definition Structs.h:27
float fPhi
Definition Structs.h:26
float fBeta
Definition Structs.h:46
Eigen::Vector3d psiAxis
Definition Structs.h:49
float fAlpha
Definition Structs.h:45
float fPsi
Definition Structs.h:48
Eigen::Vector3d betaAxis
Definition Structs.h:47