LibreCAD
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
intersectionhandler.cpp
Go to the documentation of this file.
2 using namespace lc;
3 using namespace maths;
4 #include <iostream>
5 std::vector<geo::Coordinate> Intersection::LineLine(const Equation& l1,
6  const Equation& l2) {
7  std::vector<lc::geo::Coordinate> ret;
8  const auto &m1 = l1.Matrix();
9  const auto &m2 = l2.Matrix();
10  Eigen::Matrix2d M;
11  Eigen::Vector2d V;
12 
13  M << m1(2,0) + m1(0,2), m1(2,1) + m1(1,2),
14  m2(2,0) + m2(0,2), m2(2,1) + m2(1,2);
15  V << -m1(2,2), -m2(2,2);
16 
17  Eigen::Vector2d R = M.colPivHouseholderQr().solve(V);
18  ret.emplace_back(R[0], R[1]);
19  return ret;
20 }
21 
22 std::vector<lc::geo::Coordinate> Intersection::LineQuad(const Equation& l1,
23  const Equation& q1) {
24  auto &&tcoords = QuadQuad(l1.flipXY(), q1.flipXY());
25  std::transform(tcoords.begin(), tcoords.end(), tcoords.begin(), [](const lc::geo::Coordinate &c) { return std::move(c.flipXY()); });
26  return tcoords;
27 }
28 
29 std::vector<lc::geo::Coordinate> Intersection::QuadQuad(const Equation& l1,
30  const Equation& l2) {
31  const auto &m1 = l1.Matrix();
32  const auto &m2 = l2.Matrix();
33 
34  if (std::abs(m1(0, 0)) < LCTOLERANCE && std::abs(m1(0, 1)) < LCTOLERANCE
35  &&
36  std::abs(m2(0, 0)) < LCTOLERANCE && std::abs(m2(0, 1)) < LCTOLERANCE
37  ) {
38  if (std::abs(m1(1, 1)) < LCTOLERANCE && std::abs(m2(1, 1)) < LCTOLERANCE) {
39  return LineLine(l1, l2);
40  }
41  return LineQuad(l1,l2);
42  }
43 
44  std::vector<std::vector<double> > ce(0);
45  ce.push_back(l1.Coefficients());
46  ce.push_back(l2.Coefficients());
48 }
49 
50 
51 std::vector<geo::Coordinate> Intersection::bezierLine(
52  geo::BB_CSPtr B, const geo::Vector& V) {
53 
54  std::vector<geo::Coordinate> ret;
55  std::vector<double> roots;
56 
57  auto pts = B->getCP();
58 
59  if(pts.size()==3) {
60  auto ml = geo::Vector(V.start() - V.start(), V.end() - V.start());
61  auto rotate_angle = -ml.Angle1();
62  auto cps = B->move(-V.start())->rotate(ml.start(), rotate_angle)->getCP();
63 
64  auto t2 = cps[0].y() - 2*cps[1].y() + cps[2].y();
65  auto t1 = 2*(cps[1].y() - cps[0].y())/t2;
66  auto coeff = cps[0].y()/t2;
67 
68  roots = lc::Math::quadraticSolver({t1, coeff});
69  } else {
70  auto ml = geo::Vector(V.start() - V.start(), V.end() - V.start());
71  auto rotate_angle = -ml.Angle1();
72  auto cps = B->move(-V.start())->rotate(ml.start(), rotate_angle)->getCP();
73 
74  auto t3 = -cps[0].y() + 3*cps[1].y() - 3*cps[2].y() + cps[3].y();
75  auto t2 = (3*cps[0].y() - 6*cps[1].y() + 3*cps[2].y())/t3;
76  auto t1 = (-3*cps[0].y() +3*cps[1].y())/t3;
77  auto coeff = cps[0].y()/t3;
78 
79  roots = lc::Math::cubicSolver({t2, t1, coeff});
80  }
81  for(const auto &root : roots) {
82  if(root > 0 && root < 1) {
83  ret.push_back(B->DirectValueAt(root));
84  }
85  }
86 
87  return ret;
88 }
89 
90 
91 std::vector<geo::Coordinate> Intersection::bezierCircle(
92  geo::BB_CSPtr B, const geo::Circle& C) {
93 
94  std::vector<geo::Coordinate> ret;
95 
96  // ((x0 (1-t)^2+ x1 (2 t - 2 t^2) + x2 t^2) - xC)^2 + ((y0 (1-t)^2+ y1 (2 t - 2 t^2) + y2 t^2) - yC)^2 = r2
97 
98  // (((a - 2b + c)t^2 + 2t(b-a) + a) - d)^2 + (((e - 2f + g)t^2 + 2t(f-e) + e) - h)^2 - r^2
99 
100  // Solving this for T will get the required intersection
101  std::vector<double>roots;
102 
103  auto points = B->getCP();
104 
105  if(points.size()== 3) {
106 
107  auto r = C.radius();
108  auto d = C.center().x();
109  auto h = C.center().y();
110 
111  auto a = points.at(0).x();
112  auto b = points.at(1).x();
113  auto c = points.at(2).x();
114 
115  auto e = points.at(0).y();
116  auto f = points.at(1).y();
117  auto g = points.at(2).y();
118 
119  auto t4 = (g*g + (2*e - 4*f)*g + 4* f*f - 4* e * f + e*e + c*c + (2*a-4*b)*c + 4*b*b - 4*a*b + a*a);
120  auto t3 = ((4*f - 4*e)*g - 8*f*f + 12*e*f - 4*e*e + (4*b - 4*a)*c - 8*b*b + 12*a*b -4*a*a)/t4;
121  auto t2 = ((-2*g + 4*f -2*e)*h + 2*e*g + 4*f*f - 12*e*f + 6*e*e + (-2*c + 4*b - 2*a)*d + 2*a*c + 4*b*b -12*a*b + 6*a*a)/t4;
122  auto t1 = ((4*e - 4*f)*h + 4*e*f - 4*e*e + (4*a - 4*b)*d + 4*a*b -4*a*a)/t4;
123  auto coeff = (-r*r + h*h -2 *e*h + e*e + d*d - 2*a*d + a*a)/t4;
124 
125  roots = lc::Math::quarticSolver({t3, t2, t1, coeff});
126 
127  for(const auto &root : roots) {
128  if(root > 0 && root < 1) {
129  ret.push_back(B->DirectValueAt(root));
130  }
131  }
132 
133  } else {
134  ret = bezCircleIntersect(B, C.center(), C.radius(), C.radius());
135  }
136  return ret;
137 }
138 
139 
140 std::vector<geo::Coordinate> Intersection::bezierArc(
141  geo::BB_CSPtr B, const geo::Arc& A) {
142 
143  // BezierCircle Intersection
144 
145  // Check intersection points are on Arc.
146 
147  std::vector<geo::Coordinate> ret;
148  const auto &points = bezierCircle(B, geo::Circle(A.center(), A.radius()));
149 
150  for(const auto & pt : points) {
151  if(A.isAngleBetween(pt.angle())) {
152  ret.push_back(pt);
153  }
154  }
155  return ret;
156 }
157 
158 
159 std::vector<geo::Coordinate> Intersection::bezierEllipse(
160  geo::BB_CSPtr B, const geo::Ellipse& E) {
161  std::vector<double> roots;
162  std::vector<geo::Coordinate> arc_ret, ret;
163 
164 
165  auto C = geo::Ellipse(E.center() - E.center(), E.majorP(), E.minorRadius(), E.startAngle(), E.endAngle())
166  .georotate(geo::Coordinate(0,0), -E.getAngle())
167  .geoscale(geo::Coordinate(0,0), geo::Coordinate(1/E.ratio(),1));
168 
169  auto bez = B->move(-E.center())
170  ->rotate(geo::Coordinate(0,0), E.getAngle())
171  ->scale(geo::Coordinate(0,0), geo::Coordinate(1/E.ratio(),1));
172 
173 
174  auto points = B->getCP();
175 
176  if(points.size()== 3) {
177  auto r = C.minorRadius();
178  auto d = C.center().x();
179  auto h = C.center().y();
180 
181  auto a = points.at(0).x();
182  auto b = points.at(1).x();
183  auto c = points.at(2).x();
184 
185  auto e = points.at(0).y();
186  auto f = points.at(1).y();
187  auto g = points.at(2).y();
188 
189  auto t4 = (g*g + (2*e - 4*f)*g + 4* f*f - 4* e * f + e*e + c*c + (2*a-4*b)*c + 4*b*b - 4*a*b + a*a);
190  auto t3 = ((4*f - 4*e)*g - 8*f*f + 12*e*f - 4*e*e + (4*b - 4*a)*c - 8*b*b + 12*a*b -4*a*a)/t4;
191  auto t2 = ((-2*g + 4*f -2*e)*h + 2*e*g + 4*f*f - 12*e*f + 6*e*e + (-2*c + 4*b - 2*a)*d + 2*a*c + 4*b*b -12*a*b + 6*a*a)/t4;
192  auto t1 = ((4*e - 4*f)*h + 4*e*f - 4*e*e + (4*a - 4*b)*d + 4*a*b -4*a*a)/t4;
193  auto coeff = (-r*r + h*h -2 *e*h + e*e + d*d - 2*a*d + a*a)/t4;
194 
195  roots = lc::Math::quarticSolver({t3, t2, t1, coeff});
196 
197  } else {
198  // TODO CUBIC BEZIER/ELLIPSE INTERSECTION
199  }
200 
201  for(const auto &root : roots) {
202  if(root > 0 && root < 1) {
203  ret.push_back(B->DirectValueAt(root));
204  }
205  }
206  if(E.isArc()) {
207  for(const auto &r: ret) {
208  if(E.isAngleBetween(r.angle())) {
209  arc_ret.push_back(r);
210  }
211  }
212  return arc_ret;
213  }
214  return ret;
215 }
216 
217 std::vector<geo::Coordinate> Intersection::bezierBezier(
218  geo::BB_CSPtr B1, geo::BB_CSPtr B2) {
219  std::vector<geo::Coordinate> ret;
220  bezBez(B1,B2, ret);
221  return ret;
222 }
223 
224 void Intersection::bezBez(const geo::BB_CSPtr B1,const geo::BB_CSPtr B2, std::vector<geo::Coordinate>&ret) {
225  auto bb1 = B1->boundingBox();
226  auto bb2 = B2->boundingBox();
227 
228  if(!bb1.overlaps(bb2)) {
229  return;
230  }
231 
232  if(bb1.height() + bb2.height() <= BBHEURISTIC2 && bb1.width() + bb2.width() <= BBHEURISTIC2) {
233  ret.push_back(B1->getCP().at(1));
234  return;
235  }
236 
237  auto b1split = B1->splitHalf();
238  auto b2split = B2->splitHalf();
239  bezBez(b1split[0], b2split[0], ret);
240  bezBez(b1split[1], b2split[0], ret);
241  bezBez(b1split[0], b2split[1], ret);
242  bezBez(b1split[1], b2split[1], ret);
243 }
244 
245 std::vector<geo::Coordinate> Intersection::bezCircleIntersect(lc::geo::BB_CSPtr bez, const geo::Coordinate &ec, double rx, double ry) {
246  std::vector<geo::Coordinate> results;
247  auto coords = bez->getCP();
248  auto p1 = coords.at(0);
249  auto p2 = coords.at(1);
250  auto p3 = coords.at(2);
251  auto p4 = coords.at(3);
252 
253  auto a = p1 * -1;
254  auto b = p2 * 3;
255  auto c = p3 * -3;
256  auto d = a + b + c + p4;
257  auto c3 = geo::Coordinate(d.x(), d.y());
258 
259  a = p1 * 3;
260  b = p2 * -6;
261  c = p3 * 3;
262  d = a + b + c;
263  auto c2 = geo::Coordinate(d.x(), d.y());
264 
265  a = p1 * -3;
266  b = p2 * 3;
267  c = a + b;
268  auto c1 = geo::Coordinate(c.x(), c.y());
269 
270  auto c0 = geo::Coordinate(p1.x(), p1.y());
271 
272  auto rxrx = rx*rx;
273  auto ryry = ry*ry;
274  auto roots = lc::Math::sexticSolver({
275  c3.x()*c3.x()*ryry + c3.y()*c3.y()*rxrx,
276 
277  2*(c3.x()*c2.x()*ryry + c3.y()*c2.y()*rxrx),
278 
279  2*(c3.x()*c1.x()*ryry + c3.y()*c1.y()*rxrx) + c2.x()*c2.x()*ryry + c2.y()*c2.y()*rxrx,
280 
281  2*c3.x()*ryry*(c0.x() - ec.x()) + 2*c3.y()*rxrx*(c0.y() - ec.y()) +
282  2*(c2.x()*c1.x()*ryry + c2.y()*c1.y()*rxrx),
283 
284  2*c2.x()*ryry*(c0.x() - ec.x()) + 2*c2.y()*rxrx*(c0.y() - ec.y()) +
285  c1.x()*c1.x()*ryry + c1.y()*c1.y()*rxrx,
286 
287  2*c1.x()*ryry*(c0.x() - ec.x()) + 2*c1.y()*rxrx*(c0.y() - ec.y()),
288 
289  c0.x()*c0.x()*ryry - 2*c0.y()*ec.y()*rxrx - 2*c0.x()*ec.x()*ryry +
290  c0.y()*c0.y()*rxrx + ec.x()*ec.x()*ryry + ec.y()*ec.y()*rxrx - rxrx*ryry
291  });
292 
293  for(const auto& t : roots) {
294  if(t > 0.000000000 && t < 1.000000000) {
295  results.push_back(c3*t*t*t + c2*t*t + c1*t + c0);
296  }
297  }
298 
299  return results;
300 }
301 
302 std::vector<geo::Coordinate> Intersection::splineLine(geo::Spline B, const geo::Vector& V) {
303  std::vector<geo::Coordinate> ret;
304  auto beziers = B.beziers();
305  for(const auto bezier : beziers) {
306  auto vecret = bezierLine(bezier, V);
307  std::cout << vecret.size() << std::endl;
308  ret.insert(ret.end(), vecret.begin(), vecret.end());
309  }
310  return ret;
311 }
312 
313 std::vector<geo::Coordinate> Intersection::splineCircle(geo::Spline B, const geo::Circle& C) {
314  std::vector<geo::Coordinate> ret;
315  auto beziers = B.beziers();
316  for(const auto & bezier : beziers) {
317  auto vecret = bezierCircle(bezier, C);
318  ret.insert(ret.end(), vecret.begin(), vecret.end());
319  }
320  return ret;
321 }
322 
323 std::vector<geo::Coordinate> Intersection::splineArc(geo::Spline B, const geo::Arc& A) {
324  std::vector<geo::Coordinate> ret;
325  auto beziers = B.beziers();
326  for(const auto & bezier : beziers) {
327  auto vecret = bezierArc(bezier, A);
328  ret.insert(ret.end(), vecret.begin(), vecret.end());
329  }
330  return ret;
331 }
332 
333 std::vector<geo::Coordinate> Intersection::splineEllipse(geo::Spline B, const geo::Ellipse& E) {
334  std::vector<geo::Coordinate> ret;
335  auto beziers = B.beziers();
336  for(const auto & bezier : beziers) {
337  auto vecret = bezierEllipse(bezier, E);
338  ret.insert(ret.end(), vecret.begin(), vecret.end());
339  }
340  return ret;
341 }
342 
343 std::vector<geo::Coordinate> Intersection::splineSpline(geo::Spline B1, geo::Spline B2) {
344  std::vector<geo::Coordinate> ret;
345  auto beziers = B1.beziers();
346  auto beziers2 = B2.beziers();
347  for(const auto & bezier : beziers) {
348  for(const auto & bezier2 : beziers2) {
349  auto vecret = bezierBezier(bezier, bezier2);
350  ret.insert(ret.end(), vecret.begin(), vecret.end());
351  }
352  }
353  return ret;
354 }
355 
356 std::vector<geo::Coordinate> Intersection::splineBezier(geo::Spline B1, geo::BB_CSPtr B2) {
357  std::vector<geo::Coordinate> ret;
358  auto beziers = B1.beziers();
359  for(const auto & bezier : beziers) {
360  auto vecret = bezierBezier(bezier, B2);
361  ret.insert(ret.end(), vecret.begin(), vecret.end());
362  }
363  return ret;
364 }
static std::vector< geo::Coordinate > splineLine(geo::Spline B, const geo::Vector &V)
static std::vector< double > quadraticSolver(const std::vector< double > &ce)
quadraticSolver, Quadratic equations solver
Definition: lcmath.cpp:77
static std::vector< geo::Coordinate > splineEllipse(geo::Spline B, const geo::Ellipse &E)
const Coordinate end() const
Definition: geovector.h:23
static std::vector< double > cubicSolver(const std::vector< double > &ce)
Definition: lcmath.cpp:102
double startAngle() const
startAngle, Returns Start elliptic!! angle of ellipse
Definition: geoellipse.cpp:32
const Eigen::Matrix3d Matrix() const
Matrix Returns matrix of equation.
Definition: equation.cpp:76
double x() const
Returns x of Coordinate.
Definition: geocoordinate.h:26
static std::vector< geo::Coordinate > splineArc(geo::Spline B, const geo::Arc &A)
static std::vector< geo::Coordinate > bezCircleIntersect(lc::geo::BB_CSPtr bez, const geo::Coordinate &ec, double rx, double ry)
static std::vector< double > sexticSolver(const std::vector< double > &ce)
Definition: lcmath.cpp:151
const std::vector< double > Coefficients() const
Coefficients of the equation.
Definition: equation.cpp:40
bool isArc() const
isArc
Definition: geoellipse.cpp:214
static std::vector< lc::geo::Coordinate > LineQuad(const Equation &l1, const Equation &q1)
double Angle1() const
Definition: geovector.h:104
double y() const
Returns y of Coordinate.
Definition: geocoordinate.h:34
const Equation flipXY() const
flipXY Flips the matrix values
Definition: equation.cpp:88
static void bezBez(const geo::BB_CSPtr B1, const geo::BB_CSPtr B2, std::vector< geo::Coordinate > &ret)
static std::vector< geo::Coordinate > bezierCircle(geo::BB_CSPtr B, const geo::Circle &C)
double ratio() const
ratio of major radius to minor radius
Definition: geoellipse.cpp:210
const std::vector< BB_CSPtr > beziers() const
Definition: geospline.cpp:102
double radius() const
returns the radius of the circle.
Definition: geocircle.cpp:17
Definition: cadentity.h:12
static std::vector< lc::geo::Coordinate > LineLine(const Equation &l1, const Equation &l2)
static std::vector< geo::Coordinate > splineCircle(geo::Spline B, const geo::Circle &C)
#define BBHEURISTIC2
Definition: const.h:9
std::shared_ptr< const BezierBase > BB_CSPtr
Definition: geobezierbase.h:15
static std::vector< geo::Coordinate > bezierBezier(geo::BB_CSPtr B1, geo::BB_CSPtr B2)
static std::vector< lc::geo::Coordinate > simultaneousQuadraticSolverFull(const std::vector< std::vector< double > > &m)
simultaneousQuadraticSolverFull
Definition: lcmath.cpp:283
static std::vector< geo::Coordinate > splineBezier(geo::Spline B1, geo::BB_CSPtr B2)
#define LCTOLERANCE
Definition: const.h:6
static std::vector< geo::Coordinate > splineSpline(geo::Spline B1, geo::Spline B2)
double getAngle() const
getAngle of MajorP
Definition: geoellipse.cpp:40
double endAngle() const
endAngle, Return the end elliptic!! angle of ellipse
Definition: geoellipse.cpp:189
static std::vector< geo::Coordinate > bezierEllipse(geo::BB_CSPtr B, const geo::Ellipse &E)
const Coordinate center() const
Returns the Center of circle.
Definition: geocircle.cpp:14
static std::vector< geo::Coordinate > bezierLine(geo::BB_CSPtr B, const geo::Vector &V)
static std::vector< geo::Coordinate > QuadQuad(const Equation &l1, const Equation &l2)
double radius() const
Returns the radius of Arc.
Definition: geoarc.cpp:79
const Coordinate start() const
Definition: geovector.h:20
static std::vector< double > quarticSolver(const std::vector< double > &ce)
Definition: lcmath.cpp:127
const Coordinate center() const
center, Returns Center point of Ellipse
Definition: geoellipse.cpp:20
bool isAngleBetween(double angle) const
Definition: geoarc.cpp:163
static std::vector< geo::Coordinate > bezierArc(geo::BB_CSPtr B, const geo::Arc &A)
double minorRadius() const
minorRadius, Returns the minor radius of ellipse
Definition: geoellipse.cpp:28
const Coordinate center() const
Returns center of Arc.
Definition: geoarc.cpp:91
const Coordinate majorP() const
majorP, Returns major point of the ellipse, relative to center
Definition: geoellipse.cpp:24
bool isAngleBetween(double angle) const
Definition: geoellipse.h:127