LibreCAD
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ellipse.cpp
Go to the documentation of this file.
1 #include <memory>
4 #include "ellipse.h"
5 
6 using namespace lc;
7 using namespace entity;
8 
10  const geo::Coordinate &majorP,
11  double minorRadius,
12  double startAngle,
13  double endAngle,
14  bool reversed,
15  const Layer_CSPtr layer,
16  const MetaInfo_CSPtr metaInfo,
17  const Block_CSPtr block) :
18  CADEntity(layer, metaInfo, block),
19  geo::Ellipse(center, majorP, minorRadius, startAngle, endAngle, reversed) {
20 }
21 
22 Ellipse::Ellipse(const Ellipse_CSPtr other, bool sameID) :
23  CADEntity(other, sameID),
24  geo::Ellipse(other->center(), other->majorP(), other->minorRadius(), other->startAngle(), other->endAngle(),
25  other->isReversed()) {
26 }
27 
28 
29 CADEntity_CSPtr Ellipse::move(const geo::Coordinate &offset) const {
30  auto newellipse = std::make_shared<Ellipse>(this->center() + offset,
31  this->majorP(),
32  this->minorRadius(),
33  this->startAngle(), this->endAngle(),
34  isReversed(),
35  layer(),
36  metaInfo(),
37  block());
38  newellipse->setID(this->id());
39  return newellipse;
40 }
41 
42 CADEntity_CSPtr Ellipse::copy(const geo::Coordinate &offset) const {
43  auto newEllipse = std::make_shared<Ellipse>(this->center() + offset,
44  this->majorP(),
45  this->minorRadius(),
46  this->startAngle(), this->endAngle(),
47  isReversed(),
48  layer(),
49  metaInfo(),
50  block());
51  return newEllipse;
52 }
53 
54 CADEntity_CSPtr Ellipse::rotate(const geo::Coordinate &rotation_center, const double rotation_angle) const {
55  auto rotated = this->georotate(rotation_center, rotation_angle);
56  auto newEllipse = std::make_shared<Ellipse>(rotated.center(),
57  rotated.majorP(),
58  rotated.minorRadius(),
59  rotated.startAngle(),
60  rotated.endAngle(),
61  isReversed(),
62  layer(),
63  metaInfo(),
64  block()
65  );
66  newEllipse->setID(this->id());
67  return newEllipse;
68 }
69 
70 CADEntity_CSPtr Ellipse::scale(const geo::Coordinate &scale_center, const geo::Coordinate &scale_factor) const {
71  auto scaled = this->geoscale(scale_center, scale_factor);
72  auto newEllipse = std::make_shared<Ellipse>(scaled.center(),
73  scaled.majorP(),
74  scaled.minorRadius(),
75  scaled.startAngle(),
76  scaled.endAngle(),
77  isReversed(),
78  layer(),
79  metaInfo(),
80  block()
81  );
82 
83  newEllipse->setID(this->id());
84  return newEllipse;
85 }
86 
87 CADEntity_CSPtr Ellipse::mirror(const geo::Coordinate &axis1, const geo::Coordinate &axis2) const {
88  auto cen = this->center().mirror(axis1, axis2);
89  auto maj = (cen + this->majorP()).mirror(axis1, axis2);
90  auto majP = maj - cen;
91 
92  geo::Coordinate startP, endP;
93  if (isArc()) {
94  startP = startPoint().mirror(axis1, axis2);
95  endP = endPoint().mirror(axis1, axis2);
96  }
97 
98  auto newEllipse = std::make_shared<Ellipse>(cen, majP,
99  minorRadius(),
100  getEllipseAngle(startP),
101  getEllipseAngle(endP),
102  !isReversed(),
103  layer(),
104  metaInfo(),
105  block()
106  );
107  newEllipse->setID(this->id());
108 
109  return newEllipse;
110 }
111 
113  const std::vector<geo::Coordinate> points = findBoxPoints();
114  double minX, minY, maxX, maxY;
115 
116  minX = points[0].x();
117  maxX = points[0].x();
118  minY = points[0].y();
119  maxY = points[0].y();
120 
121  const auto checkPoint = [&](const geo::Coordinate& point) {
122  if (point.x() < minX)
123  minX = point.x();
124  if (point.x() > maxX)
125  maxX = point.x();
126  if (point.y() < minY)
127  minY = point.y();
128  if (point.y() > maxY)
129  maxY = point.y();
130  };
131 
132  for (const auto& point : points)
133  checkPoint(point);
134 
135  return geo::Area(geo::Coordinate(minX, minY),
136  geo::Coordinate(maxX, maxY));
137 }
138 
139 CADEntity_CSPtr Ellipse::modify(Layer_CSPtr layer, const MetaInfo_CSPtr metaInfo, Block_CSPtr block) const {
140  auto newEntity = std::make_shared<Ellipse>(
141  this->center(),
142  this->majorP(),
143  this->minorRadius(),
144  this->startAngle(),
145  this->endAngle(),
146  this->isReversed(),
147  layer,
148  metaInfo,
149  block
150  );
151 
152  newEntity->setID(this->id());
153 
154  return newEntity;
155 }
156 
157 
158 std::vector<lc::geo::Coordinate> Ellipse::findBoxPoints() const {
159  std::vector<lc::geo::Coordinate> resPoints;
160  const double a = majorP().magnitude();
161  const double b = this->minorRadius();
162  const double angle = this->getAngle();
163  geo::Coordinate c1, c2, c3, c4;
164  bool simple = false; // (major axis = ox axis) or (major axis = oy axis)
165 
166  if (sin(angle) == 0) {
167  c1 = geo::Coordinate(this->center().x() + a, this->center().y());
168  c2 = geo::Coordinate(this->center().x(), this->center().y() + b);
169  c3 = geo::Coordinate(this->center().x() - a, this->center().y());
170  c4 = geo::Coordinate(this->center().x(), this->center().y() - b);
171 
172  simple = true;
173  }
174 
175  if (cos(angle) == 0) {
176  c1 = geo::Coordinate(this->center().x() + b, this->center().y());
177  c2 = geo::Coordinate(this->center().x(), this->center().y() + a);
178  c3 = geo::Coordinate(this->center().x() - b, this->center().y());
179  c4 = geo::Coordinate(this->center().x(), this->center().y() - a);
180 
181  simple = true;
182  }
183 
184  if (!simple) {
185  double tanAngle = std::tan(-this->getAngle());
186 
187  auto getY = [&](double x) {
188  return -b * b * x / (a * a * tanAngle);
189  };
190 
191  double x = a * a * tanAngle / (sqrt(a * a * tanAngle * tanAngle + b * b));
192  c1 = geo::Coordinate(x, getY(x));
193  c2 = geo::Coordinate(-x, getY(-x));
194 
195  tanAngle = -1 / tanAngle;
196  x = a * a * tanAngle / (sqrt(a * a * tanAngle * tanAngle + b * b));
197  c3 = geo::Coordinate(x, getY(x));
198  c4 = geo::Coordinate(-x, getY(-x));
199 
200  c1 = c1.rotate(angle) + this->center();
201  c2 = c2.rotate(angle) + this->center();
202  c3 = c3.rotate(angle) + this->center();
203  c4 = c4.rotate(angle) + this->center();
204  }
205 
206  if (this->isArc()) {
207  resPoints.push_back(startPoint());
208  resPoints.push_back(endPoint());
209  }
210 
211  auto checkPoint = [&](geo::Coordinate cord) {
212  if (isAngleBetween(getEllipseAngle(cord)))
213  resPoints.push_back(cord);
214  };
215 
216  checkPoint(c1);
217  checkPoint(c2);
218  checkPoint(c3);
219  checkPoint(c4);
220 
221  return resPoints;
222 }
223 
224 
225 std::vector<EntityCoordinate>
226 Ellipse::snapPoints(const geo::Coordinate &coord, const SimpleSnapConstrain &constrain, double minDistanceToSnap,
227  int maxNumberOfSnapPoints) const {
228 
229  std::vector<EntityCoordinate> resPoints;
230  int ind = 0;
231 
232  if (constrain.constrain() & SimpleSnapConstrain::LOGICAL) {
233  geo::Coordinate tmp;
234 
235  resPoints.emplace_back(this->center(), ind++);
236 
237  auto points = this->findBoxPoints();
238  for (auto p: points)
239  resPoints.emplace_back(p, ind++);
240 
241  geo::Coordinate minorP(this->majorP().angle());
242  minorP = minorP.rotate(M_PI_2);
243  minorP = minorP * this->minorRadius();
244 
245  if (sin(this->getAngle()) != 0 && cos(this->getAngle()) != 0) {
246  //add Ellipse vertices
247  tmp = center() + majorP();
248  if (this->isAngleBetween(0))
249  resPoints.emplace_back(tmp, ind++);
250 
251  tmp = center() - majorP();
252  if (this->isAngleBetween(M_PI))
253  resPoints.emplace_back(tmp, ind++);
254 
255  tmp = center() + minorP;
256  if (this->isAngleBetween(M_PI_2))
257  resPoints.emplace_back(tmp, ind++);
258 
259  tmp = center() - minorP;
260  if (this->isAngleBetween(-M_PI_2))
261  resPoints.emplace_back(tmp, ind++);
262  }
263  }
264 
265  // Any where on entity path
266  if (constrain.constrain() & SimpleSnapConstrain::ON_ENTITYPATH) {
267  geo::Coordinate nearestPoint = this->nearestPointOnPath(coord);
268  resPoints.emplace_back(nearestPoint, ind++);
269  }
270 
271  // Any where on entity
272  if (constrain.constrain() & SimpleSnapConstrain::ON_ENTITY) {
273  geo::Coordinate nearestPoint = nearestPointOnEntity(coord);
274  resPoints.emplace_back(nearestPoint, ind++);
275  }
276 
277  // Cleanup array of snappoints
278  Snapable::snapPointsCleanup(resPoints, coord, maxNumberOfSnapPoints, minDistanceToSnap);
279  return resPoints;
280 }
281 
283  return geo::Ellipse::nearestPointOnPath(coord);
284 }
285 
286 
287 
virtual std::vector< EntityCoordinate > snapPoints(const geo::Coordinate &coord, const SimpleSnapConstrain &constrain, double minDistanceToSnap, int maxNumberOfSnapPoints) const override
see interface Snapable
Definition: ellipse.cpp:226
Coordinate mirror(const Coordinate &axis1, const Coordinate &axis2) const
mirror a coordinate
bool isReversed() const
Definition: geoellipse.cpp:206
virtual CADEntity_CSPtr rotate(const geo::Coordinate &rotation_center, const double rotation_angle) const override
rotate, rotate operation
Definition: ellipse.cpp:54
double startAngle() const
startAngle, Returns Start elliptic!! angle of ellipse
Definition: geoellipse.cpp:32
virtual CADEntity_CSPtr copy(const geo::Coordinate &offset) const override
copy, copies by an offset
Definition: ellipse.cpp:42
virtual geo::Coordinate nearestPointOnPath(const geo::Coordinate &coord) const override
Find the nearest point on the path for this entity for the coordinate coord The path of a entity that...
Definition: ellipse.cpp:282
std::vector< lc::geo::Coordinate > findBoxPoints() const
Definition: ellipse.cpp:158
static const uint16_t LOGICAL
Definition: snapconstrain.h:22
Coordinate startPoint() const
startPoint, start point of ellipse
Definition: geoellipse.cpp:199
virtual CADEntity_CSPtr modify(Layer_CSPtr layer, const MetaInfo_CSPtr metaInfo, Block_CSPtr block) const override
modify Return a new entity with the same ID bit with possible modified metainfo and/pr layer informat...
Definition: ellipse.cpp:139
double getEllipseAngle(const Coordinate &coord) const
getEllipseAngle
Definition: geoellipse.cpp:218
static const uint16_t ON_ENTITYPATH
Definition: snapconstrain.h:19
Ellipse geoscale(const Coordinate &center, const Coordinate &factor) const
scale an ellipse at some center by some factor
Definition: geoellipse.cpp:44
Layer_CSPtr layer() const
layer return the layer this entity is placed on
Definition: cadentity.cpp:29
bool isArc() const
isArc
Definition: geoellipse.cpp:214
virtual CADEntity_CSPtr mirror(const geo::Coordinate &axis1, const geo::Coordinate &axis2) const override
Definition: ellipse.cpp:87
double magnitude() const
MetaInfo_CSPtr metaInfo() const
Definition: cadentity.h:123
static const uint16_t ON_ENTITY
Definition: snapconstrain.h:18
Definition: cadentity.h:12
Coordinate nearestPointOnPath(const Coordinate &coord) const
nearestPointOnPath, (ignore if it arc)
Definition: geoellipse.cpp:149
Coordinate rotate(const Coordinate &angleVector) const
rotate around (0.,0.) with a given angle vector
static void snapPointsCleanup(std::vector< EntityCoordinate > &points, const geo::Coordinate &reference, const unsigned int maxNumberOfSnapPoints, const double minDistanceToSnap)
Definition: snapable.h:53
Ellipse georotate(const Coordinate &center, const double rotation_angle) const
rotate an ellipse at a center by an angle
Definition: geoellipse.cpp:82
A ellipse that can be put in a drawing.
Definition: ellipse.h:27
Block_CSPtr block() const
Return the current entity block.
Definition: cadentity.cpp:33
virtual const geo::Area boundingBox() const override
boundingBox of the entity
Definition: ellipse.cpp:112
virtual CADEntity_CSPtr scale(const geo::Coordinate &scale_center, const geo::Coordinate &scale_factor) const override
scale, scales the entity
Definition: ellipse.cpp:70
#define M_PI
Definition: const.h:16
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
Coordinate endPoint() const
endPoint, end point of ellipse
Definition: geoellipse.cpp:202
const uint16_t constrain() const
Definition: snapconstrain.h:47
virtual CADEntity_CSPtr move(const geo::Coordinate &offset) const override
move, moves by an offset
Definition: ellipse.cpp:29
Ellipse(const geo::Coordinate &center, const geo::Coordinate &majorP, double minorRadius, double startAngle, double endAngle, bool reversed, const Layer_CSPtr layer, const MetaInfo_CSPtr metaInfo=nullptr, const Block_CSPtr block=nullptr)
Create ellipse.
Definition: ellipse.cpp:9
const Coordinate center() const
center, Returns Center point of Ellipse
Definition: geoellipse.cpp:20
double minorRadius() const
minorRadius, Returns the minor radius of ellipse
Definition: geoellipse.cpp:28
Coordinate nearestPointOnEntity(const Coordinate &coord) const
nearestPointOnEntity, ( not ignore arc)
Definition: geoellipse.cpp:167
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