2#ifndef GYM_PCB_GEOMETRY_H
3#define GYM_PCB_GEOMETRY_H
5#define CGAL_DISABLE_ROUNDING_MATH_CHECK
13#include <CGAL/Bbox_2.h>
14#include <CGAL/Polygon_2.h>
15#include <CGAL/Simple_cartesian.h>
16typedef CGAL::Simple_cartesian<Real> Kernel;
18#if CGAL_VERSION_MAJOR >= 6
19#define std_get_for_cgal std::get_if
21#define std_get_for_cgal boost::get
24using Vector_2 = Kernel::Vector_2;
25using Vector_3 = Kernel::Vector_3;
26using Point_2 = Kernel::Point_2;
27using Point_3 = Kernel::Point_3;
28using Direction_2 = Kernel::Direction_2;
29using Ray_2 = Kernel::Ray_2;
30using Ray_3 = Kernel::Ray_3;
31using Line_2 = Kernel::Line_2;
32using Segment_2 = Kernel::Segment_2;
33using Segment_3 = Kernel::Segment_3;
34using Triangle_2 = Kernel::Triangle_2;
35using Triangle_3 = Kernel::Triangle_3;
36using Circle_2 = Kernel::Circle_2;
38using Bbox_2 = CGAL::Bbox_2;
39using Iso_rectangle_2 = CGAL::Iso_rectangle_2<Kernel>;
40using Polygon_2 = CGAL::Polygon_2<Kernel>;
42using Aff_transformation_2 = CGAL::Aff_transformation_2<Kernel>;
44#include "Math/IPoint2.hpp"
45#include "Math/IPoint3.hpp"
53inline Real cosine(
const Vector_2 &v1,
const Vector_2 &v2)
55 return CGAL::scalar_product(v1, v2) / std::sqrt(v1.squared_length() *
63inline float distance45(
const Point_2 &A,
const Point_2 &B)
65 const Real dx = std::abs(A.x() - B.x());
66 const Real dy = std::abs(A.y() - B.y());
67 return dx + dy - std::min(dx, dy) * (2.0 - std::sqrt(2.0));
75inline Bbox_2 bbox_expanded_abs(
const Bbox_2 &box, Real m)
77 return Bbox_2(box.xmin() - m, box.ymin() - m, box.xmax() + m, box.ymax() + m);
82inline Bbox_2 bbox_expanded_rel(
const Bbox_2 &box, Real r)
84 return bbox_expanded_abs(box, std::max(box.xmax() - box.xmin(), box.ymax() - box.ymin()) * r);
87inline Bbox_2 bbox_intersection(
const Bbox_2 &box1,
const Bbox_2 &box2)
89 return Bbox_2(std::max(box1.xmin(), box2.xmin()),
90 std::max(box1.ymin(), box2.ymin()),
91 std::min(box1.xmax(), box2.xmax()),
92 std::min(box1.ymax(), box2.ymax()));
95inline Real bbox_area(
const Bbox_2 &box)
97 return (box.xmax() - box.xmin()) * (box.ymax() - box.ymin());
100inline Real bbox_diameter(
const Bbox_2 &box)
102 auto dx = box.xmax() - box.xmin();
103 auto dy = box.ymax() - box.ymin();
104 return std::sqrt(dx * dx + dy * dy);
107inline std::string to_string(
const Bbox_2 &box)
109 return fmt::format(
"{:f} {:f} {:f} {:f}", box.xmin(), box.ymin(), box.xmax(), box.ymax());
115inline Point_2 closest_on(
const Segment_2 &s,
const Point_2 &o)
117 auto x = s.supporting_line().projection(o);
120 return (CGAL::squared_distance(o, s.source()) <
121 CGAL::squared_distance(o, s.target())) ? s.source() : s.target();
134 Point_25(
const Point_2 &x,
int z) : _xy(x), _z(z) { }
135 Point_25(Real x, Real y,
int z) : _xy(x,y), _z(z) { }
136 const Point_2& xy()
const {
return _xy; }
137 Real x()
const {
return _xy.x(); }
138 Real y()
const {
return _xy.y(); }
139 int z()
const {
return _z; }
140 Point_25 withZ(
int z)
const {
return Point_25(_xy, z); }
141 Bbox_2 bbox()
const {
return _xy.bbox(); }
142 Point_25& operator=(
const Point_25 &v) { _xy = v._xy; _z = v._z;
return *
this; }
143 bool operator<(
const Point_25 &v)
const {
return (_z < v._z) || (_z == v._z && _xy < v._xy); }
144 bool operator==(
const Point_25 &v)
const {
return _xy == v._xy && _z == v._z; }
145 Point_25 operator+(
const Vector_2 &v)
const {
return Point_25(_xy + v, _z); }
158 Segment_25(
const Segment_2 &s,
int layer = 0) : mS2(s), mLayer(layer) {
160 Segment_25(const ::Point_2 &p, const ::Point_2 &q,
int layer = 0) : mS2(p, q), mLayer(layer) {
162 const Segment_2& s2()
const {
return mS2; }
163 int z()
const {
return mLayer; }
164 void setLayer(
int z) { mLayer = z; }
167 const Point_2& source_2()
const {
return mS2.source(); }
168 const Point_2& target_2()
const {
return mS2.target(); }
169 Real squared_length()
const {
return mS2.squared_length(); }
170 Real length()
const {
return std::sqrt(squared_length()); }
171 bool is_horizontal()
const {
return mS2.is_horizontal(); }
172 bool is_vertical()
const {
return mS2.is_vertical(); }
174 ::Vector_2 getPerpendicularCCW(Real s = 1.0)
const;
176 Real anglePi2()
const {
const auto v = mS2.to_vector();
return std::atan(v.y() / v.x()); }
177 Segment_25& rectify(Real angleTolerance);
178 int majorAxis()
const {
const auto v = mS2.to_vector();
return std::abs(v.y()) > std::abs(v.x()) ? 1 : 0; }
179 Segment_25 opposite()
const {
return Segment_25(mS2.opposite(), z()); }
180 bool isXOrdered()
const {
return mS2.source().x() <= mS2.target().x(); }
181 bool isYOrdered()
const {
return mS2.source().y() <= mS2.target().y(); }
182 Segment_25 orderedX()
const {
return isXOrdered() ? *this : opposite(); }
183 Segment_25 orderedY()
const {
return isYOrdered() ? *this : opposite(); }
184 bool operator<(
const Segment_25 &s)
const {
return (source() < s.source()) || (source() == s.source() && target() < s.target()); }
185 bool operator==(
const Segment_25 &s)
const {
return mLayer == s.mLayer && mS2 == s.mS2; }
186 int equals(
const Segment_25 &s)
const;
187 Real maxNorm()
const {
return std::max(std::abs(mS2.to_vector().x()), std::abs(mS2.to_vector().y())); }
188 Real angleWith(
const Segment_25&)
const;
199 if (mLayer != s.mLayer)
203 return (mS2 == s.mS2.opposite()) ? -1 : 0;
210 const auto v = mS2.to_vector();
211 auto s0 = std::sqrt(v.squared_length());
214inline ::Vector_2 Segment_25::getPerpendicularCCW(Real s)
const
216 auto vd =
getDirection(s); return ::Vector_2(-vd.y(), vd.x());
218inline Segment_25& Segment_25::rectify(Real angleTolerance)
220 const auto v0 = mS2.source();
221 const auto v1 = mS2.target();
222 const auto A = std::abs(anglePi2());
223 if (std::abs(A) < angleTolerance)
224 mS2 = Segment_2(v0, Point_2(v1.x(), v0.y()));
225 else if (std::abs(A - M_PI_2) < angleTolerance)
226 mS2 = Segment_2(v0, Point_2(v0.x(), v1.y()));
229inline int Segment_25::angle45()
const
231 const auto dx = std::abs(source_2().x() - target_2().x());
232 const auto dy = std::abs(source_2().y() - target_2().y());
233 const auto t225 = std::sqrt(2.0) - 1.0;
234 const auto t675 = std::sqrt(2.0) + 1.0;
241inline Real Segment_25::angleWith(
const Segment_25 &s)
const
243 const auto u = s2().to_vector();
244 const auto v = s.s2().to_vector();
245 const auto d = u.x() * v.x() + u.y() * v.y();
246 const auto x = u.x() * v.y() - u.y() * v.x();
247 return std::atan2(x, d);
255inline std::ostream& operator<<(std::ostream &os,
const Point_2 &v)
257 return os <<
'(' << v.x() <<
',' << v.y() <<
')';
260inline std::ostream& operator<<(std::ostream &os,
const Point_25 &v)
262 return os <<
'(' << v.x() <<
',' << v.y() <<
',' << v.z() <<
')';
265inline std::ostream& operator<<(std::ostream &os,
const Vector_2 &v)
267 return os <<
'(' << v.x() <<
',' << v.y() <<
')';
270inline std::ostream& operator<<(std::ostream &os,
const Triangle_2 &A)
272 return os <<
'<' << A.vertex(0) <<
' ' << A.vertex(1) <<
' ' << A.vertex(2) <<
'>';
275inline std::ostream& operator<<(std::ostream &os,
const Segment_2 &s)
277 return os <<
'[' << s.source() <<
'_' << s.target() <<
']';
280inline std::ostream& operator<<(std::ostream &os,
const Segment_25 &s)
282 return os <<
'[' << s.source() <<
'_' << s.target() <<
"|z=" << s.z() <<
']';
Definition Geometry.hpp:131
Definition Geometry.hpp:155
::Vector_2 getDirection(Real s=1.0) const
Definition Geometry.hpp:208
int equals(const Segment_25 &s) const
Definition Geometry.hpp:197