LibreCAD
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
lc::Math Class Reference

#include <lcmath.h>

Static Public Member Functions

static bool isAngleBetween (double a, double start, double end, bool CCW)
 isAngleBetween, checks if angle is between More...
 
static double correctAngle (double a)
 correctAngle, Corrects angle to be in -PI to PI More...
 
static double getAngleDifferenceShort (double a1, double a2, bool CCW)
 getAngleDifference, Angle difference between 2 angles More...
 
static double getAngleDifference (double a1, double a2, bool CCW)
 getAngleDifference, Angle difference between 2 angles More...
 
static std::vector< double > quadraticSolver (const std::vector< double > &ce)
 quadraticSolver, Quadratic equations solver More...
 
static std::vector< double > cubicSolver (const std::vector< double > &ce)
 
static std::vector< double > quarticSolver (const std::vector< double > &ce)
 
static std::vector< double > sexticSolver (const std::vector< double > &ce)
 
static std::vector< double > quarticSolverFull (const std::vector< double > &ce)
 
static std::vector
< lc::geo::Coordinate
simultaneousQuadraticSolver (const std::vector< double > &m)
 
static bool simultaneousQuadraticVerify (const std::vector< std::vector< double > > &m, const geo::Coordinate &v)
 
static std::vector
< lc::geo::Coordinate
simultaneousQuadraticSolverFull (const std::vector< std::vector< double > > &m)
 simultaneousQuadraticSolverFull More...
 
static std::vector
< lc::geo::Coordinate
simultaneousQuadraticSolverMixed (const std::vector< std::vector< double > > &m)
 

Detailed Description

Definition at line 9 of file lcmath.h.

Member Function Documentation

double Math::correctAngle ( double  a)
static

correctAngle, Corrects angle to be in -PI to PI

Parameters
doublea, angle
Returns
double corrected angle

Corrects the given angle to the range of -PI to PI

Definition at line 33 of file lcmath.cpp.

33  {
34  return std::remainder(a, 2. * M_PI);
35 }
#define M_PI
Definition: const.h:16
std::vector< double > Math::cubicSolver ( const std::vector< double > &  ce)
static

cubic solver x^3 + ce[0] x^2 + ce[1] x + ce[2] = 0 , a vector of size 3 contains the coefficient in order

Returns
, a vector contains real roots

Definition at line 102 of file lcmath.cpp.

102  {
103  std::vector<double> ans(0, 0.);
104  if (ce.size() != 3) {
105  return ans;
106  }
107 
108  Eigen::PolynomialSolver<double, Eigen::Dynamic> solver;
109  Eigen::VectorXd coeff(4);
110 
111  coeff[0] = ce[2];
112  coeff[1] = ce[1];
113  coeff[2] = ce[0];
114  coeff[3] = 1;
115 
116  solver.compute(coeff);
117 
118  solver.realRoots(ans);
119  return ans;
120 }
double Math::getAngleDifference ( double  a1,
double  a2,
bool  CCW 
)
static

getAngleDifference, Angle difference between 2 angles

Parameters
doublea1, angle 1
doublea2, angle 2
bool,CCWCounter Clickwise Check
Returns
double angle difference

Definition at line 54 of file lcmath.cpp.

54  {
55  double difference;
56 
57  if(CCW) {
58  difference = end - start;
59  }
60  else {
61  difference = start - end;
62  }
63 
64  if (difference < 0.) {
65  difference = 2.0 * M_PI - std::abs(difference);
66  }
67 
68  return difference;
69 }
#define M_PI
Definition: const.h:16
double Math::getAngleDifferenceShort ( double  a1,
double  a2,
bool  CCW 
)
static

getAngleDifference, Angle difference between 2 angles

Parameters
doublea1, angle 1
doublea2, angle 2
bool,CCWCounter Clickwise Check
Returns
double angle difference
The angle that needs to be added to a1 to reach a2. Always positive and less than 2*pi.

Definition at line 41 of file lcmath.cpp.

41  {
42  if (!CCW) {
43  std::swap(a1, a2);
44  }
45 
46  auto angle = correctAngle(a2 - a1);
47  if(angle < 0) {
48  angle += 2*M_PI;
49  }
50 
51  return angle;
52 }
#define M_PI
Definition: const.h:16
static double correctAngle(double a)
correctAngle, Corrects angle to be in -PI to PI
Definition: lcmath.cpp:33
bool Math::isAngleBetween ( double  angle,
double  start,
double  end,
bool  CCW 
)
static

isAngleBetween, checks if angle is between

Parameters
a,angle
a1,angle1
a2,angle2
bool,CCWCounter Clickwise Check
Returns
bool

Tests if angle a is between a1 and a2. a, a1 and a2 must be in the range between -PI and PI. All angles in rad.

Parameters
reversedtrue for clockwise testing. false for ccw testing.
Returns
true if the angle a is between a1 and a2.

Definition at line 21 of file lcmath.cpp.

23  {
24  double diffA = getAngleDifference(start, end, CCW);
25  double diffB = getAngleDifference(start, angle, CCW);
26  return diffB <= diffA;
27 }
static double getAngleDifference(double a1, double a2, bool CCW)
getAngleDifference, Angle difference between 2 angles
Definition: lcmath.cpp:54
std::vector< double > Math::quadraticSolver ( const std::vector< double > &  ce)
static

quadraticSolver, Quadratic equations solver

Parameters
vector<double>ce, equation
Returns
vector<double> roots

quadratic solver x^2 + ce[0] x + ce[1] = 0 , a vector of size 2 contains the coefficient in order

Returns
, a vector contains real roots

Definition at line 77 of file lcmath.cpp.

77  {
78  std::vector<double> ans(0, 0.);
79 
80  if (ce.size() != 2) {
81  return ans;
82  }
83 
84  Eigen::PolynomialSolver<double, Eigen::Dynamic> solver;
85  Eigen::VectorXd coeff(3);
86 
87  coeff[0] = ce[1];
88  coeff[1] = ce[0];
89  coeff[2] = 1;
90 
91  solver.compute(coeff);
92 
93  solver.realRoots(ans);
94  return ans;
95 }
std::vector< double > Math::quarticSolver ( const std::vector< double > &  ce)
static

quartic solver x^4 + ce[0] x^3 + ce[1] x^2 + ce[2] x + ce[3] = 0 , a vector of size 4 contains the coefficient in order

Returns
, a vector contains real roots

Definition at line 127 of file lcmath.cpp.

127  {
128  // std::cout<<"x^4+("<<ce[0]<<")*x^3+("<<ce[1]<<")*x^2+("<<ce[2]<<")*x+("<<ce[3]<<")==0"<<std::endl;
129 
130  std::vector<double> ans(0, 0.);
131  Eigen::PolynomialSolver<double, Eigen::Dynamic> solver;
132  Eigen::VectorXd coeff(5);
133 
134  if (ce.size() != 4) {
135  return ans;
136  }
137 
138  coeff[0] = ce[3];
139  coeff[1] = ce[2];
140  coeff[2] = ce[1];
141  coeff[3] = ce[0];
142  coeff[4] = 1;
143 
144  solver.compute(coeff);
145 
146  solver.realRoots(ans);
147  return ans;
148 
149 }
std::vector< double > Math::quarticSolverFull ( const std::vector< double > &  ce)
static

quartic solver ce[4] x^4 + ce[3] x^3 + ce[2] x^2 + ce[1] x + ce[0] = 0 , a vector of size 5 contains the coefficient in order

Returns
, a vector contains real roots ToDo, need a robust algorithm to locate zero terms, better handling of tolerances

Definition at line 183 of file lcmath.cpp.

183  {
184  // std::cout<<ce[4]<<"*y^4+("<<ce[3]<<")*y^3+("<<ce[2]<<"*y^2+("<<ce[1]<<")*y+("<<ce[0]<<")==0"<<std::endl;
185 
186  std::vector<double> roots(0, 0.);
187 
188  if (ce.size() != 5) {
189  return roots;
190  }
191 
192  std::vector<double> ce2(4, 0.);
193 
194  if (std::abs(ce[4]) < 1.0e-14) { // this should not happen
195  if (std::abs(ce[3]) < 1.0e-14) { // this should not happen
196  if (std::abs(ce[2]) < 1.0e-14) { // this should not happen
197  if (std::abs(ce[1]) > 1.0e-14) {
198  roots.push_back(-ce[0] / ce[1]);
199  } else {
200  // can not determine y. this means overlapped, but overlap should have been detected before, therefore return empty set
201  return roots;
202  }
203  } else {
204  ce2.resize(2);
205  ce2[0] = ce[1] / ce[2];
206  ce2[1] = ce[0] / ce[2];
207  roots = Math::quadraticSolver(ce2);
208  }
209  } else {
210  ce2.resize(3);
211  ce2[0] = ce[2] / ce[3];
212  ce2[1] = ce[1] / ce[3];
213  ce2[2] = ce[0] / ce[3];
214  roots = Math::cubicSolver(ce2);
215  }
216  } else {
217  ce2[0] = ce[3] / ce[4];
218  ce2[1] = ce[2] / ce[4];
219  ce2[2] = ce[1] / ce[4];
220  ce2[3] = ce[0] / ce[4];
221 
222  if (std::abs(ce2[3]) <= TOLERANCE15) {
223  //constant term is zero, factor 0 out, solve a cubic equation
224  ce2.resize(3);
225  roots = Math::cubicSolver(ce2);
226  roots.push_back(0.);
227  } else {
228  roots = Math::quarticSolver(ce2);
229  }
230  }
231 
232  return roots;
233 }
static std::vector< double > quadraticSolver(const std::vector< double > &ce)
quadraticSolver, Quadratic equations solver
Definition: lcmath.cpp:77
static std::vector< double > cubicSolver(const std::vector< double > &ce)
Definition: lcmath.cpp:102
#define TOLERANCE15
Definition: const.h:11
static std::vector< double > quarticSolver(const std::vector< double > &ce)
Definition: lcmath.cpp:127
std::vector< double > Math::sexticSolver ( const std::vector< double > &  ce)
static

quartic solver ce[4] x^4 + ce[3] x^3 + ce[2] x^2 + ce[1] x + ce[0] = 0 , a vector of size 5 contains the coefficient in order

Returns
, a vector contains real roots

Definition at line 151 of file lcmath.cpp.

151  {
152 
153  std::vector<double> ans(0, 0.);
154  Eigen::PolynomialSolver<double, Eigen::Dynamic> solver;
155  Eigen::VectorXd coeff(7);
156 
157  if (ce.size() != 7) {
158  return ans;
159  }
160 
161  coeff[0] = ce[6];
162  coeff[1] = ce[5];
163  coeff[2] = ce[4];
164  coeff[3] = ce[3];
165  coeff[4] = ce[2];
166  coeff[5] = ce[1];
167  coeff[6] = ce[0];
168 
169  solver.compute(coeff);
170 
171  solver.realRoots(ans);
172 
173  return ans;
174 }
std::vector< lc::geo::Coordinate > Math::simultaneousQuadraticSolver ( const std::vector< double > &  m)
static

solver quadratic simultaneous equations of a set of two

solver quadratic simultaneous equations of set two

Definition at line 245 of file lcmath.cpp.

245  {
246  std::vector<lc::geo::Coordinate> ret(0);
247 
248  if (m.size() != 8) {
249  return ret; // valid m should contain exact 8 elements
250  }
251 
252  std::vector< double> c1(0, 0.);
253  std::vector< std::vector<double> > m1(0, c1);
254  c1.resize(6);
255  c1[0] = m[0];
256  c1[1] = 0.;
257  c1[2] = m[1];
258  c1[3] = 0.;
259  c1[4] = 0.;
260  c1[5] = -1.;
261  m1.push_back(c1);
262  c1[0] = m[2];
263  c1[1] = 2.*m[3];
264  c1[2] = m[4];
265  c1[3] = m[5];
266  c1[4] = m[6];
267  c1[5] = m[7];
268  m1.push_back(c1);
269 
271 }
static std::vector< lc::geo::Coordinate > simultaneousQuadraticSolverFull(const std::vector< std::vector< double > > &m)
simultaneousQuadraticSolverFull
Definition: lcmath.cpp:283
std::vector< lc::geo::Coordinate > Math::simultaneousQuadraticSolverFull ( const std::vector< std::vector< double > > &  m)
static

simultaneousQuadraticSolverFull

Parameters
vector<vector<double> > m
Returns
std::vector<lc::geo::Coordinate> Coordinates

solver quadratic simultaneous equations of a set of two

eliminate x, quartic equation of y

Collect[Eliminate[{ a*x^2 + b*x*y+c*y^2+d*x+e*y+f==0,g*x^2+h*x*y+i*y^2+j*x+k*y+l==0},x],y]

Definition at line 283 of file lcmath.cpp.

283  {
284  std::vector<lc::geo::Coordinate> ret;
285 
286  if (m.size() != 2) {
287  return ret;
288  }
289 
290  if (m[0].size() == 3 || m[1].size() == 3) {
292  }
293 
294  if (m[0].size() != 6 || m[1].size() != 6) {
295  return ret;
296  }
297 
299  auto& a = m[0][0];
300  auto& b = m[0][1];
301  auto& c = m[0][2];
302  auto& d = m[0][3];
303  auto& e = m[0][4];
304  auto& f = m[0][5];
305 
306  auto& g = m[1][0];
307  auto& h = m[1][1];
308  auto& i = m[1][2];
309  auto& j = m[1][3];
310  auto& k = m[1][4];
311  auto& l = m[1][5];
315  /*
316  f^2 g^2 - d f g j + a f j^2 - 2 a f g l + (2 e f g^2 - d f g h - b f g j + 2 a f h j - 2 a f g k) y + (2 c f g^2 - b f g h + a f h^2 - 2 a f g i) y^2
317  ==
318  -(d^2 g l) + a d j l - a^2 l^2
319  +
320  (d e g j - a e j^2 - d^2 g k + a d j k - 2 b d g l + 2 a e g l + a d h l + a b j l - 2 a^2 k l) y
321  +
322  (-(e^2 g^2) + d e g h - d^2 g i + c d g j + b e g j - 2 a e h j + a d i j - a c j^2 - 2 b d g k + 2 a e g k + a d h k + a b j k - a^2 k^2 - b^2 g l + 2 a c g l + a b h l - 2 a^2 i l) y^2
323  +
324  (-2 c e g^2 + c d g h + b e g h - a e h^2 - 2 b d g i + 2 a e g i + a d h i + b c g j - 2 a c h j + a b i j - b^2 g k + 2 a c g k + a b h k - 2 a^2 i k) y^3
325  +
326  (-(c^2 g^2) + b c g h - a c h^2 - b^2 g i + 2 a c g i + a b h i - a^2 i^2) y^4
327 
328 
329  */
330  double a2 = a * a;
331  double b2 = b * b;
332  double c2 = c * c;
333  double d2 = d * d;
334  double e2 = e * e;
335  double f2 = f * f;
336 
337  double g2 = g * g;
338  double h2 = h * h;
339  double i2 = i * i;
340  double j2 = j * j;
341  double k2 = k * k;
342  double l2 = l * l;
343  std::vector<double> qy(5, 0.);
344  //y^4
345  qy[4] = -c2 * g2 + b * c * g * h - a * c * h2 - b2 * g * i + 2.*a * c * g * i + a * b * h * i - a2 * i2;
346  //y^3
347  qy[3] = -2.*c * e * g2 + c * d * g * h + b * e * g * h - a * e * h2 - 2.*b * d * g * i + 2.*a * e * g * i + a * d * h * i +
348  b * c * g * j - 2.*a * c * h * j + a * b * i * j - b2 * g * k + 2.*a * c * g * k + a * b * h * k - 2.*a2 * i * k;
349  //y^2
350  qy[2] = (-e2 * g2 + d * e * g * h - d2 * g * i + c * d * g * j + b * e * g * j - 2.*a * e * h * j + a * d * i * j - a * c * j2 -
351  2.*b * d * g * k + 2.*a * e * g * k + a * d * h * k + a * b * j * k - a2 * k2 - b2 * g * l + 2.*a * c * g * l + a * b * h * l - 2.*a2 * i * l)
352  - (2.*c * f * g2 - b * f * g * h + a * f * h2 - 2.*a * f * g * i);
353  //y
354  qy[1] = (d * e * g * j - a * e * j2 - d2 * g * k + a * d * j * k - 2.*b * d * g * l + 2.*a * e * g * l + a * d * h * l + a * b * j * l - 2.*a2 * k * l)
355  - (2.*e * f * g2 - d * f * g * h - b * f * g * j + 2.*a * f * h * j - 2.*a * f * g * k);
356  //y^0
357  qy[0] = -d2 * g * l + a * d * j * l - a2 * l2
358  - (f2 * g2 - d * f * g * j + a * f * j2 - 2.*a * f * g * l);
359  //quarticSolver
360  auto&& roots = quarticSolverFull(qy);
361 
362  if (roots.size() == 0) { // no intersection found
363  return ret;
364  }
365 
366  std::vector<double> ce(0, 0.);
367 
368  for (size_t i0 = 0; i0 < roots.size(); i0++) {
369  /*
370  Collect[Eliminate[{ a*x^2 + b*x*y+c*y^2+d*x+e*y+f==0,g*x^2+h*x*y+i*y^2+j*x+k*y+l==0},x],y]
371  */
372  ce.resize(3);
373  ce[0] = a;
374  ce[1] = b * roots[i0] + d;
375  ce[2] = c * roots[i0] * roots[i0] + e * roots[i0] + f;
376 
377  if (std::abs(ce[0]) < 1e-75 && std::abs(ce[1]) < 1e-75) {
378  ce[0] = g;
379  ce[1] = h * roots[i0] + j;
380  ce[2] = i * roots[i0] * roots[i0] + k * roots[i0] + f;
381  }
382 
383  if (std::abs(ce[0]) < 1e-75 && std::abs(ce[1]) < 1e-75) {
384  continue;
385  }
386 
387  if (std::abs(a) > 1e-75) {
388  std::vector<double> ce2(2, 0.);
389  ce2[0] = ce[1] / ce[0];
390  ce2[1] = ce[2] / ce[0];
391  auto&& xRoots = quadraticSolver(ce2);
392 
393  for (size_t j0 = 0; j0 < xRoots.size(); j0++) {
394  geo::Coordinate vp(xRoots[j0], roots[i0]);
395 
396  if (simultaneousQuadraticVerify(m, vp)) {
397  ret.push_back(vp);
398  }
399  }
400 
401  continue;
402  }
403 
404  geo::Coordinate vp(-ce[2] / ce[1], roots[i0]);
405 
406  if (simultaneousQuadraticVerify(m, vp)) {
407  ret.push_back(vp);
408  }
409  }
410 
411  return ret;
412 }
static std::vector< double > quadraticSolver(const std::vector< double > &ce)
quadraticSolver, Quadratic equations solver
Definition: lcmath.cpp:77
static std::vector< lc::geo::Coordinate > simultaneousQuadraticSolverMixed(const std::vector< std::vector< double > > &m)
Definition: lcmath.cpp:414
static bool simultaneousQuadraticVerify(const std::vector< std::vector< double > > &m, const geo::Coordinate &v)
Definition: lcmath.cpp:484
static std::vector< double > quarticSolverFull(const std::vector< double > &ce)
Definition: lcmath.cpp:183
std::vector< lc::geo::Coordinate > Math::simultaneousQuadraticSolverMixed ( const std::vector< std::vector< double > > &  m)
static

y (2 b c d-a c e)-a c g+c^2 d = y^2 (a^2 (-f)+a b e-b^2 d)+y (a b g-a^2 h)+a^2 (-i)

Definition at line 414 of file lcmath.cpp.

414  {
415  std::vector<lc::geo::Coordinate> ret;
416  auto p0 = & (m[0]);
417  auto p1 = & (m[1]);
418 
419  if (p1->size() == 3) {
420  std::swap(p0, p1);
421  }
422 
423  if (p1->size() == 3) {
424  //linear
425  Eigen::Matrix2d M;
426  Eigen::Vector2d V;
427  M << m[0][0], m[0][1],
428  m[1][0], m[1][1];
429  V << -m[0][2], -m[1][2];
430  Eigen::Vector2d sn = M.colPivHouseholderQr().solve(V);
431  ret.push_back(geo::Coordinate(sn[0], sn[1]));
432  return ret;
433  }
434 
435  const double& a = p0->at(0);
436  const double& b = p0->at(1);
437  const double& c = p0->at(2);
438  const double& d = p1->at(0);
439  const double& e = p1->at(1);
440  const double& f = p1->at(2);
441  const double& g = p1->at(3);
442  const double& h = p1->at(4);
443  const double& i = p1->at(5);
447  std::vector<double> ce(3, 0.);
448  const double&& a2 = a * a;
449  const double&& b2 = b * b;
450  const double&& c2 = c * c;
451  ce[0] = -f * a2 + a * b * e - b2 * d;
452  ce[1] = a * b * g - a2 * h - (2 * b * c * d - a * c * e);
453  ce[2] = a * c * g - c2 * d - a2 * i;
454  std::vector<double> roots(0, 0.);
455 
456  if (std::abs(ce[0]) < 1e-75) {
457  if (std::abs(ce[1]) > 1e-75) {
458  roots.push_back(- ce[2] / ce[1]);
459  }
460  } else {
461  std::vector<double> ce2(2, 0.);
462  ce2[0] = ce[1] / ce[0];
463  ce2[1] = ce[2] / ce[0];
464  roots = quadraticSolver(ce2);
465  }
466 
467  if (roots.size() == 0) {
468  return ret;
469  }
470 
471  for (size_t i = 0; i < roots.size(); i++) {
472  ret.push_back(geo::Coordinate(-(b * roots.at(i) + c) / a, roots.at(i)));
473  }
474 
475  return ret;
476 
477 }
static std::vector< double > quadraticSolver(const std::vector< double > &ce)
quadraticSolver, Quadratic equations solver
Definition: lcmath.cpp:77
bool Math::simultaneousQuadraticVerify ( const std::vector< std::vector< double > > &  m,
const geo::Coordinate v 
)
static

solver quadratic simultaneous equations of a set of two

verify a solution for simultaneousQuadratic the coefficient matrix , a candidate to verify

Returns
true, for a valid solution

tolerance test for bug#3606099 verifying the equations to floating point tolerance by terms

Definition at line 484 of file lcmath.cpp.

484  {
485  const double& x = v.x();
486  const double& y = v.y();
487  const double x2 = x * x;
488  const double y2 = y * y;
489  auto& a = m[0][0];
490  auto& b = m[0][1];
491  auto& c = m[0][2];
492  auto& d = m[0][3];
493  auto& e = m[0][4];
494  auto& f = m[0][5];
495 
496  auto& g = m[1][0];
497  auto& h = m[1][1];
498  auto& i = m[1][2];
499  auto& j = m[1][3];
500  auto& k = m[1][4];
501  auto& l = m[1][5];
506  double terms0[12] = { a * x2, b* x * y, c * y2, d * x, e * y, f, g * x2, h* x * y, i * y2, j * x, k * y, l};
507  double amax0 = std::abs(terms0[0]), amax1 = std::abs(terms0[6]);
508  double sum0 = 0., sum1 = 0.;
509 
510  for (int i = 0; i < 6; i++) {
511  if (amax0 < std::abs(terms0[i])) {
512  amax0 = std::abs(terms0[i]);
513  }
514 
515  sum0 += terms0[i];
516  }
517 
518  for (int i = 6; i < 12; i++) {
519  if (amax1 < std::abs(terms0[i])) {
520  amax1 = std::abs(terms0[i]);
521  }
522 
523  sum1 += terms0[i];
524  }
525 
526  const double tols = 2.*sqrt(6.) * sqrt(DBL_EPSILON); //experimental tolerances to verify simultaneous quadratic
527 
528  return (amax0 <= tols || std::abs(sum0) / amax0 < tols) && (amax1 <= tols || std::abs(sum1) / amax1 < tols);
529 }
double x() const
Returns x of Coordinate.
Definition: geocoordinate.h:26
double y() const
Returns y of Coordinate.
Definition: geocoordinate.h:34

The documentation for this class was generated from the following files: