LibreCAD
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
geoarc.cpp
Go to the documentation of this file.
1 #include <cad/math/lcmath.h>
2 #include <stdlib.h>
3 #include "geoarc.h"
4 
5 using namespace lc;
6 using namespace geo;
7 
8 Arc::Arc(const Coordinate &center, double radius, double startAngle, double endAngle)
9  : Base(), _center(center), _radius(radius), _startAngle(Math::correctAngle(startAngle)), _endAngle(Math::correctAngle(endAngle)), _CCW(true) {
10  /*
11  if (startAngle<0.0 || startAngle>PI2 || startAngle<endAngle) {
12  throw "Invalid start angle";
13  }
14  if (endAngle<0.0 || endAngle> PI2) {
15  throw "Invalid end angle";
16  }
17  if (radius<0.0) {
18  throw "Invalid radius";
19  }*/
20 
21 }
22 
23 Arc::Arc(const Coordinate &center, double radius, double startAngle, double endAngle, bool isCCW)
24  : Base(), _center(center), _radius(radius), _startAngle(Math::correctAngle(startAngle)), _endAngle(Math::correctAngle(endAngle)), _CCW(isCCW) {
25 }
26 
27 Arc Arc::createArc3P(const Coordinate &p1, const Coordinate &p2, const Coordinate &p3) {
28 
29  geo::Coordinate vra = p2 - p1;
30  geo::Coordinate vrb = p3 - p1;
31  double ra2 = vra.squared() * 0.5;
32  double rb2 = vrb.squared() * 0.5;
33  double crossp = vra.x() * vrb.y() - vra.y() * vrb.x();
34  if (std::abs(crossp) <= 0.0) {
35  // "Cannot create a arc with radius 0.0.");
36  // TODO add exception handling of some sort
37 // throw;
38  return Arc(geo::Coordinate(0., 0.), 0., 0., 0.);
39  }
40  crossp = 1. / crossp;
41 
42  auto center = geo::Coordinate((ra2 * vrb.y() - rb2 * vra.y()) * crossp, (rb2 * vra.x() - ra2 * vrb.x()) * crossp);
43  auto radius = center.magnitude();
44  center = center + p1;
45  auto angle1 = center.angleTo(p1);
46  auto angle2 = center.angleTo(p3);
47 
48  return Arc(center, radius, angle1, angle2, false);
49 }
50 
51 Arc Arc::createArcBulge(const Coordinate &p1, const Coordinate &p2, const double bulge) {
52  auto isCCW = bulge>0.;
53  auto delta = atan(bulge) * 4.0;
54 
55  auto middle = p1.mid(p2);
56  auto dist = p1.distanceTo(p2)/2.0;
57 
58  auto radius = std::abs(dist / std::sin(delta/2.0));
59 
60  auto wu = std::abs(std::pow(radius, 2.0) - std::pow(dist, 2.0));
61  auto h = std::sqrt(wu);
62  auto angle = p1.angleTo(p2);
63 
64  if (isCCW) {
65  angle-=M_PI/2.0;
66  } else {
67  angle+=M_PI/2.0;
68  }
69 
70  if (std::abs(delta)<M_PI) {
71  h*=-1.0;
72  }
73 
74  auto center = geo::Coordinate(angle) * h + middle;
75 
76  return Arc(center, radius, center.angleTo(p1), center.angleTo(p2), isCCW);
77 }
78 
79 double Arc::radius() const {
80  return _radius;
81 }
82 
83 double Arc::startAngle() const {
84  return _startAngle;
85 }
86 
87 double Arc::endAngle() const {
88  return _endAngle;
89 }
90 
91 const Coordinate Arc::center() const {
92  return _center;
93 }
94 
96  return center() + Coordinate((coord - center()).angle()) * radius();
97 }
99  const auto angle = (coord - center()).angle();
100 
101  // if the angle is between start and stop then calculate the nearest point
102  // on it's entity
103  if (isAngleBetween(angle)) {
104  return center() + angle * radius();
105  }
106 
107  // Find out if angle is closer to start or end and return the appropriate coordinate
108  const auto ad1 = std::abs(angle - _startAngle);
109  const auto ad2 = std::abs(angle - _endAngle);
110 
111  if (ad1<=ad2) {
112  return startP();
113  } else {
114  return endP();
115  }
116 }
117 
118 double Arc::length() const {
119  if (_startAngle > _endAngle) {
120  return std::abs((2. * M_PI + endAngle() - startAngle()) * radius());
121  } else {
122  return std::abs((endAngle() - startAngle()) * radius());
123  }
124 }
125 
126 bool Arc::CCW() const {
127  return _CCW;
128 }
129 
132 }
133 
135  return _center + Coordinate(_endAngle) * _radius;
136 }
137 
139  geo::Area area(startP(), endP());
140 
141  const double startAngle = _startAngle;
142  const double endAngle = _endAngle;
143  const double p0 = 0.0 * M_PI;
144  const double p1 = 0.5 * M_PI;
145  const double p2 = 1.0 * M_PI;
146  const double p3 = 1.5 * M_PI;
147 
148  if ((Math::isAngleBetween(p0, startAngle, endAngle, _CCW))) {
149  area = area.merge(Coordinate(_center.x() + _radius, _center.y()));
150  }
151  if ((Math::isAngleBetween(p1, startAngle, endAngle, _CCW))) {
152  area = area.merge(Coordinate(_center.x(), _center.y() + _radius));
153  }
154  if ((Math::isAngleBetween(p2, startAngle, endAngle, _CCW))) {
155  area = area.merge(Coordinate(_center.x() - _radius, _center.y()));
156  }
157  if ((Math::isAngleBetween(p3, startAngle, endAngle, _CCW))) {
158  area = area.merge(Coordinate(_center.x(), _center.y() - _radius));
159  }
160  return area;
161 }
162 
163 bool Arc::isAngleBetween(double angle) const {
165 }
166 
167 double Arc::angle() const {
168  return Math::correctAngle(std::abs(_endAngle - _startAngle));
169 }
170 
171 double Arc::bulge() const {
172  double bulge = std::tan(angle()/4.0);
173 
174  if(!CCW()) {
175  bulge *= -1;
176  }
177 
178  return bulge;
179 }
double squared() const
double _startAngle
Double startAngle of Arc.
Definition: geoarc.h:142
double angle() const
Definition: geoarc.cpp:167
Coordinate nearestPointOnEntity(const Coordinate &coord) const
Definition: geoarc.cpp:98
Coordinate startP() const
Definition: geoarc.cpp:130
Area boundingBox() const
Definition: geoarc.cpp:138
Coordinate mid(const Coordinate &other) const
double x() const
Returns x of Coordinate.
Definition: geocoordinate.h:26
static Arc createArc3P(const Coordinate &p1, const Coordinate &p2, const Coordinate &p3)
Definition: geoarc.cpp:27
double angleTo(const Coordinate &v) const
Returns angle To the coordinate.
Definition: geocoordinate.h:77
double length() const
Definition: geoarc.cpp:118
double _endAngle
Double endAngle of Arc.
Definition: geoarc.h:143
double y() const
Returns y of Coordinate.
Definition: geocoordinate.h:34
double magnitude() const
Area merge(const Area &other) const
merge two area's and expand if required to largest containing area
Definition: geoarea.h:156
static Arc createArcBulge(const Coordinate &p1, const Coordinate &p2, const double bulge)
Definition: geoarc.cpp:51
bool CCW() const
Returns of the arc is in reversed direction.
Definition: geoarc.cpp:126
double endAngle() const
Returns the EndAngle.
Definition: geoarc.cpp:87
Definition: cadentity.h:12
Coordinate _center
Coordinate center of Arc.
Definition: geoarc.h:140
Definition: lcmath.h:9
Coordinate nearestPointOnPath(const Coordinate &coord) const
Definition: geoarc.cpp:95
bool _CCW
Definition: geoarc.h:144
Arc(const Coordinate &center, double radius, double startAngle, double endAngle)
Definition: geoarc.cpp:8
#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
static bool isAngleBetween(double a, double start, double end, bool CCW)
isAngleBetween, checks if angle is between
Definition: lcmath.cpp:21
Coordinate endP() const
Definition: geoarc.cpp:134
double _radius
Double _Radius of Arc.
Definition: geoarc.h:141
double radius() const
Returns the radius of Arc.
Definition: geoarc.cpp:79
double distanceTo(const geo::Coordinate &c) const
double bulge() const
Definition: geoarc.cpp:171
bool isAngleBetween(double angle) const
Definition: geoarc.cpp:163
double startAngle() const
Returns the startAngle.
Definition: geoarc.cpp:83
const Coordinate center() const
Returns center of Arc.
Definition: geoarc.cpp:91