LibreCAD
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
geobeziercubic.cpp
Go to the documentation of this file.
1 #include "geobeziercubic.h"
2 
3 using namespace lc;
4 using namespace geo;
5 
6 CubicBezier::CubicBezier(const Coordinate& point_a, const Coordinate& point_b, const Coordinate& point_c, const Coordinate& point_d)
7  : _pointA(point_a), _pointB(point_b), _pointC(point_c), _pointD(point_d) {
8 }
9 
11  _pointA(bez._pointA), _pointB(bez._pointB),
12  _pointC(bez._pointC), _pointD(bez._pointD) {
13 }
14 
16 
17  auto v1 =(_pointB - _pointA)*3;
18  auto v2 = (_pointC - _pointB)*3;
19  auto v3 = (_pointD - _pointC)*3;
20 
21  auto a = v1 - (v2*2) + v3;
22  auto b = (v2 - v1)*2;
23  auto c = v1;
24 
25  std::vector<double> x_roots = lc::Math::quadraticSolver({b.x()/a.x(), c.x()/a.x()});
26  std::vector<double> y_roots = lc::Math::quadraticSolver({b.y()/a.y(), b.y()/a.y()});
27 
28  std::vector<double> x_{_pointA.x(), _pointB.x(),_pointC.x(), _pointD.x() };
29  std::vector<double> y_{_pointA.y(), _pointB.y(),_pointC.y(), _pointD.y() };
30 
31 
32  for(const double tx_ : x_roots) {
33  if(tx_ > 0. && tx_ < 1.0) {
34  auto bez1 = DirectValueAt(tx_);
35  x_.push_back(bez1.x());
36  y_.push_back(bez1.y());
37  }
38  }
39  for(const double ty_ : y_roots) {
40  if(ty_ > 0. && ty_ < 1.0) {
41  auto bez2 = DirectValueAt(ty_);
42  x_.push_back(bez2.x());
43  y_.push_back(bez2.y());
44  }
45  }
46  std::sort(x_.begin(), x_.end());
47  std::sort(y_.begin(), y_.end());
48 
49  return Area(geo::Coordinate(x_.front(), y_.front()), geo::Coordinate (x_.back() ,y_.back()));
50 }
51 
53 
54  /*
55  * Difference between nearest point on path and
56  * nearest point on entity for a bezier curve is that
57  * for calculating the nearest point on entity you check
58  * that if the value of "t" is between 0 and 1
59  * whereas for nearest point on path, you don't check that
60  */
61 
62  auto min_distance = std::numeric_limits<double>::max();
63  Coordinate ret;
64 
65  auto tValues = nearestPointTValue(coord);
66 
67  for (auto val : tValues) {
68  geo::Coordinate point_on_path = DirectValueAt(val);
69  auto raw_distance = coord.distanceTo(point_on_path);
70  if(raw_distance < min_distance) {
71  ret = point_on_path;
72  min_distance = raw_distance;
73  }
74  }
75 
76  return returnCasesForNearestPoint(min_distance, coord, ret);
77 }
78 
80  auto min_distance = std::numeric_limits<double>::max();
81 
82  Coordinate ret;
83 
84  auto tValues = nearestPointTValue(coord);
85 
86  for (auto val : tValues) {
87  if(val > 0 && val < 1) {
88  geo::Coordinate point_on_path = DirectValueAt(val);
89  auto raw_distance = coord.distanceTo(point_on_path);
90  if(raw_distance < min_distance) {
91  ret = point_on_path;
92  min_distance = raw_distance;
93  }
94  }
95  }
96 
97  return returnCasesForNearestPoint(min_distance, coord, ret);
98 }
99 
105 std::vector<double> CubicBezier::nearestPointTValue(const lc::geo::Coordinate &coord) const {
106  // auto pos = _pointA - coord;
107 
108  // auto Ax = _pointB.x() - _pointA.x();
109  // auto Ay = _pointB.y() - _pointA.y();
110  // auto Bx = _pointA.x() - (_pointB.x()*2.0) + _pointC.x();
111  // auto By = _pointA.y() - (_pointB.y()*2.0) + _pointC.y();
112 
113  // auto a = Bx * Bx + By * By;
114  // auto b = (3 * (Ax * Bx + Ay * By)) / a;
115  // auto c = (2 * (Ax * Ax + Ay * Ay) + pos.x() * Bx + pos.y() * By) / a;
116  // auto d = (pos.x() * Ax + pos.y() * Ay) / a;
117 
118  // return lc::Math::cubicSolver({b, c, d});
119  std::vector<double> empty(0, 0.);
120  return empty; // TODO: no return statement
121 }
122 
123 const std::vector<geo::Coordinate> CubicBezier::getCP() const {
124  std::vector<Coordinate> ret{_pointA, _pointB, _pointC, _pointD};
125  return ret;
126 }
127 
128 
138  double min_distance, const lc::geo::Coordinate &coord,
139  const lc::geo::Coordinate &ret) const {
140  // auto distance_to_A = coord.distanceTo(_pointA);
141  // auto distance_to_C = coord.distanceTo(_pointC);
142 
143  // // Point is on curve
144  // if(min_distance < distance_to_A && min_distance < distance_to_C) {
145  // return ret;
146  // }
147  // // Point is on starting of Curve
148  // if (distance_to_A < distance_to_C) {
149  // return _pointA;
150  // }
151  // // Point is end of curve
152  // return _pointC;
153  return ret; // TODO: no return statement
154 }
155 
156 Coordinate CubicBezier::CasteljauAt(std::vector<Coordinate> points, double t) const {
157  if(points.size() == 1) return points.front();
158  else {
159  int size_ = points.size();
160  std::vector<Coordinate> new_vec;
161  for(int i = 1; i < size_; i++) {
162  new_vec.push_back(points[i-1] * (1.0-t) + points[i] * t);
163  }
164  return CasteljauAt(new_vec, t);
165  }
166 }
167 
169  auto t_square = t*t;
170  auto t_cube = t_square*t;
171  auto one_minus_t = 1 - t;
172  auto one_minus_square = one_minus_t*one_minus_t;
173  auto one_minus_cube = one_minus_square * one_minus_t;
174 
175  return (_pointA*one_minus_cube) + (_pointB*3*one_minus_square*t) + (_pointC*3*one_minus_t*t_square) + (_pointD*t_cube);
176 }
177 
178 const std::vector<Coordinate> CubicBezier::Curve(double precession) {
179  std::vector<Coordinate> v = { _pointA, _pointB, _pointC, _pointD };
180  std::vector<Coordinate> ret;
181  for(auto i = 0.; i < 1.0; i+=precession) {
182  ret.push_back(CasteljauAt(v, i));
183  }
184  return ret;
185 }
186 
187 const double CubicBezier::length() const {
188  return 0; // TODO: no return statement
189 }
190 
191 BB_CSPtr CubicBezier::rotate(const geo::Coordinate& center, double angle) const {
192  auto z = std::make_shared<const lc::geo::CubicBezier>(_pointA.rotate(center, angle),
193  _pointB.rotate(center, angle),
194  _pointC.rotate(center, angle),
195  _pointD.rotate(center, angle));
196  return z;
197 }
198 
199 BB_CSPtr CubicBezier::scale(const geo::Coordinate& center, const geo::Coordinate& factor) const {
200  auto z = std::make_shared<const lc::geo::CubicBezier>( _pointA.scale(center, factor),
201  _pointB.scale(center, factor),
202  _pointC.scale(center, factor),
203  _pointD.scale(center, factor)
204  );
205  return z;
206 }
207 
209  auto z = std::make_shared<const lc::geo::CubicBezier>(_pointA + offset,
210  _pointB + offset,
211  _pointC + offset,
212  _pointD + offset
213  );
214  return z;
215 }
216 
217 const Coordinate CubicBezier::tangent(double t) const {
218  const Coordinate empty;
219  return empty; // TODO: no return statement
220 }
221 
222 const Coordinate CubicBezier::normal(double t) const {
223  const Coordinate empty;
224  return empty; // TODO: no return statement
225 }
226 
227 BB_CSPtr CubicBezier::mirror(const geo::Coordinate& axis1, const geo::Coordinate& axis2) const {
228  auto z = std::make_shared<const lc::geo::CubicBezier>(_pointA.mirror(axis1, axis2),
229  _pointB.mirror(axis1, axis2),
230  _pointC.mirror(axis1, axis2),
231  _pointD.mirror(axis1, axis2)
232  );
233  return z;
234 }
235 
236 std::vector<BB_CSPtr> CubicBezier::splitHalf() const {
237  auto E = (_pointA+_pointB)/2;
238  auto F = (_pointB+_pointC)/2;
239  auto G = (_pointC+_pointD)/2;
240  auto H = (E+F)/2;
241  auto J = (F+G)/2;
242  auto K = (H+J)/2;
243 
244  BB_CSPtr b1 = std::make_shared<CubicBezier>(CubicBezier(_pointA,E,H,K));
245  BB_CSPtr b2 = std::make_shared<CubicBezier>(CubicBezier(K,J,G,_pointD));
246 
247  return {b1, b2};
248 }
249 
251  return NULL; // TODO: no return statement
252 }
253 
255  auto x1 = _pointA.x();
256  auto y1 = _pointA.y();
257 
258  auto x2 = _pointB.x();
259  auto y2 = _pointB.y();
260 
261  auto x3 = _pointC.x();
262  auto y3 = _pointC.y();
263 
264  auto x4 = _pointD.x();
265  auto y4 = _pointD.y();
266 
267  auto x12 = (x2-x1)*t+x1;
268  auto y12 = (y2-y1)*t+y1;
269 
270  auto x23 = (x3-x2)*t+x2;
271  auto y23 = (y3-y2)*t+y2;
272 
273  auto x34 = (x4-x3)*t+x3;
274  auto y34 = (y4-y3)*t+y3;
275 
276  auto x123 = (x23-x12)*t+x12;
277  auto y123 = (y23-y12)*t+y12;
278 
279  auto x234 = (x34-x23)*t+x23;
280  auto y234 = (y34-y23)*t+y23;
281 
282  auto x1234 = (x234-x123)*t+x123;
283  auto y1234 = (y234-y123)*t+y123;
284 
285  return std::make_shared<CubicBezier>(CubicBezier({x1, y1}, {x12, y12}, {x123, y123}, {x1234, y1234}));
286 }
Coordinate mirror(const Coordinate &axis1, const Coordinate &axis2) const
mirror a coordinate
virtual BB_CSPtr rotate(const geo::Coordinate &center, double angle) const override
rotate the bezier at specific center and some angle
static std::vector< double > quadraticSolver(const std::vector< double > &ce)
quadraticSolver, Quadratic equations solver
Definition: lcmath.cpp:77
virtual BB_CSPtr splitAtT(double t) const override
splitAtT Splits bezier at specific time.
virtual const lc::geo::Coordinate returnCasesForNearestPoint(double min_distance, const lc::geo::Coordinate &coord, const Coordinate &ret) const override
Bezier::returnCasesForNearestPoint.
double x() const
Returns x of Coordinate.
Definition: geocoordinate.h:26
virtual BB_CSPtr scale(const geo::Coordinate &center, const geo::Coordinate &factor) const override
scale the bezier at specific center by some factor
double y() const
Returns y of Coordinate.
Definition: geocoordinate.h:34
Coordinate scale(const double &scale_factor) const
virtual const std::vector< Coordinate > Curve(double precession) override
Curve Creates a bezier curve for drawing with some precession value.
virtual BB_CSPtr mirror(const geo::Coordinate &axis1, const geo::Coordinate &axis2) const override
mirror a bezier around a line
virtual Coordinate nearestPointOnEntity(const Coordinate &coord) const override
nearestPointOnEntity of the bezier
virtual std::vector< double > nearestPointTValue(const Coordinate &coord) const override
Bezier::nearestPointTValue.
Definition: cadentity.h:12
virtual const std::vector< Coordinate > getCP() const override
getCP Returns the control points of the bezier
Coordinate rotate(const Coordinate &angleVector) const
rotate around (0.,0.) with a given angle vector
virtual BB_CSPtr move(const geo::Coordinate &offset) const override
move the bezeir by some offset
virtual const Coordinate tangent(double t) const override
tangent of the bezeir
std::shared_ptr< const BezierBase > BB_CSPtr
Definition: geobezierbase.h:15
virtual BB_CSPtr offset(const geo::Coordinate &offset) const override
offset offsets the bezier.
virtual Coordinate DirectValueAt(double t) const override
DirectValueAt Coordinate of bezier at time t calculated numerically.
virtual std::vector< BB_CSPtr > splitHalf() const override
splitHalf Splits the bezier into two halves.
virtual Coordinate nearestPointOnPath(const Coordinate &coord) const override
nearestPointOnPath of the bezier
virtual Coordinate CasteljauAt(std::vector< Coordinate > points, double t) const override
CasteljauAt Coordinate of bezier at time t.
double distanceTo(const geo::Coordinate &c) const
CubicBezier(const Coordinate &point_a, const Coordinate &point_b, const Coordinate &point_c, const Coordinate &point_d)
virtual const Coordinate normal(double t) const override
normal of the bezier at time t
virtual const double length() const override
length of the Bezier
virtual const Area boundingBox() const override
boundingBox of the bezier