Point.hpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. ///|/ Copyright (c) Prusa Research 2016 - 2023 Vojtěch Bubník @bubnikv, Pavel Mikuš @Godrak, Enrico Turri @enricoturri1966, Lukáš Matěna @lukasmatena, Lukáš Hejl @hejllukas, Filip Sykala @Jony01, Tomáš Mészáros @tamasmeszaros, Vojtěch Král @vojtechkral
  2. ///|/ Copyright (c) SuperSlicer 2019 Remi Durand @supermerill
  3. ///|/ Copyright (c) Slic3r 2013 - 2016 Alessandro Ranellucci @alranel
  4. ///|/ Copyright (c) 2016 Mark Walker
  5. ///|/
  6. ///|/ ported from lib/Slic3r/Point.pm:
  7. ///|/ Copyright (c) Prusa Research 2018 Vojtěch Bubník @bubnikv
  8. ///|/ Copyright (c) Slic3r 2011 - 2015 Alessandro Ranellucci @alranel
  9. ///|/
  10. ///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
  11. ///|/
  12. #ifndef slic3r_Point_hpp_
  13. #define slic3r_Point_hpp_
  14. #include "libslic3r.h"
  15. #include <cstddef>
  16. #include <vector>
  17. #include <cmath>
  18. #include <string>
  19. #include <sstream>
  20. #include <unordered_map>
  21. #include <oneapi/tbb/scalable_allocator.h>
  22. #include <Eigen/Geometry>
  23. #include "LocalesUtils.hpp"
  24. namespace Slic3r {
  25. class BoundingBox;
  26. class BoundingBoxf;
  27. class Point;
  28. using Vector = Point;
  29. // Base template for eigen derived vectors
  30. template<int N, int M, class T>
  31. using Mat = Eigen::Matrix<T, N, M, Eigen::DontAlign, N, M>;
  32. template<int N, class T> using Vec = Mat<N, 1, T>;
  33. template<typename NumberType>
  34. using DynVec = Eigen::Matrix<NumberType, Eigen::Dynamic, 1>;
  35. // Eigen types, to replace the Slic3r's own types in the future.
  36. // Vector types with a fixed point coordinate base type.
  37. using Vec2crd = Eigen::Matrix<coord_t, 2, 1, Eigen::DontAlign>;
  38. using Vec3crd = Eigen::Matrix<coord_t, 3, 1, Eigen::DontAlign>;
  39. //using Vec2i32 = Eigen::Matrix<int, 2, 1, Eigen::DontAlign>;
  40. //using Vec3i = Eigen::Matrix<int, 3, 1, Eigen::DontAlign>;
  41. //using Vec4i = Eigen::Matrix<int, 4, 1, Eigen::DontAlign>;
  42. using Vec2i32 = Eigen::Matrix<int32_t, 2, 1, Eigen::DontAlign>;
  43. using Vec2i64 = Eigen::Matrix<int64_t, 2, 1, Eigen::DontAlign>;
  44. using Vec3i32 = Eigen::Matrix<int32_t, 3, 1, Eigen::DontAlign>;
  45. using Vec3i64 = Eigen::Matrix<int64_t, 3, 1, Eigen::DontAlign>;
  46. using Vec4i32 = Eigen::Matrix<int32_t, 4, 1, Eigen::DontAlign>;
  47. // Vector types with a double coordinate base type.
  48. using Vec2f = Eigen::Matrix<float, 2, 1, Eigen::DontAlign>;
  49. using Vec3f = Eigen::Matrix<float, 3, 1, Eigen::DontAlign>;
  50. using Vec4f = Eigen::Matrix<float, 4, 1, Eigen::DontAlign>;
  51. using Vec2d = Eigen::Matrix<double, 2, 1, Eigen::DontAlign>;
  52. using Vec3d = Eigen::Matrix<double, 3, 1, Eigen::DontAlign>;
  53. using Vec4d = Eigen::Matrix<double, 4, 1, Eigen::DontAlign>;
  54. template<typename BaseType>
  55. using PointsAllocator = tbb::scalable_allocator<BaseType>;
  56. //using PointsAllocator = std::allocator<BaseType>;
  57. using Points = std::vector<Point, PointsAllocator<Point>>;
  58. using PointPtrs = std::vector<Point*>;
  59. using PointConstPtrs = std::vector<const Point*>;
  60. using Points3 = std::vector<Vec3crd>;
  61. using Pointfs = std::vector<Vec2d>;
  62. using Vec2ds = std::vector<Vec2d>;
  63. using Pointf3s = std::vector<Vec3d>;
  64. // for storing product
  65. using P2 = Eigen::Matrix<Coord2, 2, 1, Eigen::DontAlign>;
  66. using VecOfPoints = std::vector<Points, PointsAllocator<Points>>;
  67. using Matrix2f = Eigen::Matrix<float, 2, 2, Eigen::DontAlign>;
  68. using Matrix2d = Eigen::Matrix<double, 2, 2, Eigen::DontAlign>;
  69. using Matrix3f = Eigen::Matrix<float, 3, 3, Eigen::DontAlign>;
  70. using Matrix3d = Eigen::Matrix<double, 3, 3, Eigen::DontAlign>;
  71. using Matrix4f = Eigen::Matrix<float, 4, 4, Eigen::DontAlign>;
  72. using Matrix4d = Eigen::Matrix<double, 4, 4, Eigen::DontAlign>;
  73. template<int N, class T>
  74. using Transform = Eigen::Transform<float, N, Eigen::Affine, Eigen::DontAlign>;
  75. using Transform2f = Eigen::Transform<float, 2, Eigen::Affine, Eigen::DontAlign>;
  76. using Transform2d = Eigen::Transform<double, 2, Eigen::Affine, Eigen::DontAlign>;
  77. using Transform3f = Eigen::Transform<float, 3, Eigen::Affine, Eigen::DontAlign>;
  78. using Transform3d = Eigen::Transform<double, 3, Eigen::Affine, Eigen::DontAlign>;
  79. // I don't know why Eigen::Transform::Identity() return a const object...
  80. template<int N, class T> Transform<N, T> identity() { return Transform<N, T>::Identity(); }
  81. inline const auto &identity3f = identity<3, float>;
  82. inline const auto &identity3d = identity<3, double>;
  83. inline coordf_t dot(const Vec2d &v1, const Vec2d &v2) { return v1.x() * v2.x() + v1.y() * v2.y(); }
  84. inline coordf_t dot(const Vec2d &v) { return v.x() * v.x() + v.y() * v.y(); }
  85. inline bool operator<(const Vec2d &lhs, const Vec2d &rhs) { return lhs.x() < rhs.x() || (lhs.x() == rhs.x() && lhs.y() < rhs.y()); }
  86. // Cross product of two 2D vectors.
  87. // None of the vectors may be of int32_t type as the result would overflow.
  88. template<typename Derived, typename Derived2>
  89. inline typename Derived::Scalar cross2(const Eigen::MatrixBase<Derived> &v1, const Eigen::MatrixBase<Derived2> &v2)
  90. {
  91. static_assert(Derived::IsVectorAtCompileTime && int(Derived::SizeAtCompileTime) == 2, "cross2(): first parameter is not a 2D vector");
  92. static_assert(Derived2::IsVectorAtCompileTime && int(Derived2::SizeAtCompileTime) == 2, "cross2(): first parameter is not a 2D vector");
  93. static_assert(! std::is_same<typename Derived::Scalar, int32_t>::value, "cross2(): Scalar type must not be int32_t, otherwise the cross product would overflow.");
  94. static_assert(std::is_same<typename Derived::Scalar, typename Derived2::Scalar>::value, "cross2(): Scalar types of 1st and 2nd operand must be equal.");
  95. return v1.x() * v2.y() - v1.y() * v2.x();
  96. }
  97. // cross2 that use double as intermediate values, to avoid overflow of int types.
  98. template<typename Derived, typename Derived2>
  99. inline typename Derived::Scalar cross2_double(const Eigen::MatrixBase<Derived> &v1, const Eigen::MatrixBase<Derived2> &v2)
  100. {
  101. static_assert(Derived::IsVectorAtCompileTime && int(Derived::SizeAtCompileTime) == 2, "cross2(): first parameter is not a 2D vector");
  102. static_assert(Derived2::IsVectorAtCompileTime && int(Derived2::SizeAtCompileTime) == 2, "cross2(): first parameter is not a 2D vector");
  103. static_assert(! std::is_same<typename Derived::Scalar, int32_t>::value, "cross2(): Scalar type must not be int32_t, otherwise the cross product would overflow.");
  104. static_assert(std::is_same<typename Derived::Scalar, typename Derived2::Scalar>::value, "cross2(): Scalar types of 1st and 2nd operand must be equal.");
  105. return Derived::Scalar(double(v1.x()) * double(v2.y()) - double(v1.y()) * double(v2.x()));
  106. }
  107. // 2D vector perpendicular to the argument.
  108. template<typename Derived>
  109. inline Eigen::Matrix<typename Derived::Scalar, 2, 1, Eigen::DontAlign> perp(const Eigen::MatrixBase<Derived> &v)
  110. {
  111. static_assert(Derived::IsVectorAtCompileTime && int(Derived::SizeAtCompileTime) == 2, "perp(): parameter is not a 2D vector");
  112. return { - v.y(), v.x() };
  113. }
  114. #if _DEBUG
  115. inline double ccw_angle_old_test(const Vec2crd &me, const Vec2crd &p1, const Vec2crd &p2)
  116. {
  117. //FIXME this calculates an atan2 twice! Project one vector into the other!
  118. double angle = atan2(p1.x() - (me).x(), p1.y() - (me).y())
  119. - atan2(p2.x() - (me).x(), p2.y() - (me).y());
  120. // we only want to return only positive angles
  121. return angle <= 0 ? angle + 2*PI : angle;
  122. }
  123. #endif
  124. inline double abs_angle(double rad) {
  125. return rad <= 0 ? rad + 2 * PI : rad;
  126. }
  127. // Angle from v1 to v2, returning double atan2(y, x) normalized to <-PI, PI>.
  128. // By rotating v1 by this angle in the CCW direction, you get the direction of v2
  129. // This rotation is CCW if the angle is >0.
  130. template<typename Derived, typename Derived2>
  131. inline double angle_ccw(const Eigen::MatrixBase<Derived> &v1, const Eigen::MatrixBase<Derived2> &v2) {
  132. static_assert(Derived::IsVectorAtCompileTime && int(Derived::SizeAtCompileTime) == 2, "angle(): first parameter is not a 2D vector");
  133. static_assert(Derived2::IsVectorAtCompileTime && int(Derived2::SizeAtCompileTime) == 2, "angle(): second parameter is not a 2D vector");
  134. auto v1d = v1.template cast<double>();
  135. auto v2d = v2.template cast<double>();
  136. return atan2(cross2(v1d, v2d), v1d.dot(v2d));
  137. }
  138. template<typename Derived>
  139. Eigen::Matrix<typename Derived::Scalar, 2, 1, Eigen::DontAlign> to_2d(const Eigen::MatrixBase<Derived> &ptN) {
  140. static_assert(Derived::IsVectorAtCompileTime && int(Derived::SizeAtCompileTime) >= 3, "to_2d(): first parameter is not a 3D or higher dimensional vector");
  141. return ptN.template head<2>();
  142. }
  143. template<typename Derived>
  144. inline Eigen::Matrix<typename Derived::Scalar, 3, 1, Eigen::DontAlign> to_3d(const Eigen::MatrixBase<Derived> &pt, const typename Derived::Scalar z) {
  145. static_assert(Derived::IsVectorAtCompileTime && int(Derived::SizeAtCompileTime) == 2, "to_3d(): first parameter is not a 2D vector");
  146. return { pt.x(), pt.y(), z };
  147. }
  148. inline Vec2d unscale(coord_t x, coord_t y) { return Vec2d(unscaled(x), unscaled(y)); }
  149. inline Vec2d unscale(const Vec2crd &pt) { return Vec2d(unscaled(pt.x()), unscaled(pt.y())); }
  150. inline Vec2d unscale(const Vec2d &pt) { return Vec2d(unscaled(pt.x()), unscaled(pt.y())); }
  151. inline Vec3d unscale(coord_t x, coord_t y, coord_t z) { return Vec3d(unscaled(x), unscaled(y), unscaled(z)); }
  152. inline Vec3d unscale(const Vec3crd &pt) { return Vec3d(unscaled(pt.x()), unscaled(pt.y()), unscaled(pt.z())); }
  153. inline Vec3d unscale(const Vec3d &pt) { return Vec3d(unscaled(pt.x()), unscaled(pt.y()), unscaled(pt.z())); }
  154. inline std::string to_string(const Vec2crd &pt) { return std::string("[") + float_to_string_decimal_point(pt.x()) + ", " + float_to_string_decimal_point(pt.y()) + "]"; }
  155. inline std::string to_string(const Vec2d &pt) { return std::string("[") + float_to_string_decimal_point(pt.x()) + ", " + float_to_string_decimal_point(pt.y()) + "]"; }
  156. inline std::string to_string(const Vec3crd &pt) { return std::string("[") + float_to_string_decimal_point(pt.x()) + ", " + float_to_string_decimal_point(pt.y()) + ", " + float_to_string_decimal_point(pt.z()) + "]"; }
  157. inline std::string to_string(const Vec3d &pt) { return std::string("[") + float_to_string_decimal_point(pt.x()) + ", " + float_to_string_decimal_point(pt.y()) + ", " + float_to_string_decimal_point(pt.z()) + "]"; }
  158. std::vector<Vec3f> transform(const std::vector<Vec3f>& points, const Transform3f& t);
  159. Pointf3s transform(const Pointf3s& points, const Transform3d& t);
  160. /// <summary>
  161. /// Check whether transformation matrix contains odd number of mirroring.
  162. /// NOTE: In code is sometime function named is_left_handed
  163. /// </summary>
  164. /// <param name="transform">Transformation to check</param>
  165. /// <returns>Is positive determinant</returns>
  166. inline bool has_reflection(const Transform3d &transform) { return transform.matrix().determinant() < 0; }
  167. /// <summary>
  168. /// Getter on base of transformation matrix
  169. /// </summary>
  170. /// <param name="index">column index</param>
  171. /// <param name="transform">source transformation</param>
  172. /// <returns>Base of transformation matrix</returns>
  173. inline const Vec3d get_base(unsigned index, const Transform3d &transform) { return transform.linear().col(index); }
  174. inline const Vec3d get_x_base(const Transform3d &transform) { return get_base(0, transform); }
  175. inline const Vec3d get_y_base(const Transform3d &transform) { return get_base(1, transform); }
  176. inline const Vec3d get_z_base(const Transform3d &transform) { return get_base(2, transform); }
  177. inline const Vec3d get_base(unsigned index, const Transform3d::LinearPart &transform) { return transform.col(index); }
  178. inline const Vec3d get_x_base(const Transform3d::LinearPart &transform) { return get_base(0, transform); }
  179. inline const Vec3d get_y_base(const Transform3d::LinearPart &transform) { return get_base(1, transform); }
  180. inline const Vec3d get_z_base(const Transform3d::LinearPart &transform) { return get_base(2, transform); }
  181. template<int N, class T> using Vec = Eigen::Matrix<T, N, 1, Eigen::DontAlign, N, 1>;
  182. class Point : public Vec2crd
  183. {
  184. public:
  185. using coord_type = coord_t;
  186. Point() : Vec2crd(0, 0) {}
  187. Point(int32_t x, int32_t y) : Vec2crd(coord_t(x), coord_t(y)) {}
  188. Point(int64_t x, int32_t y) : Vec2crd(coord_t(x), coord_t(y)) {}
  189. Point(int32_t x, int64_t y) : Vec2crd(coord_t(x), coord_t(y)) {}
  190. Point(int64_t x, int64_t y) : Vec2crd(coord_t(x), coord_t(y)) {}
  191. Point(double x, double y) : Vec2crd(coord_t(std::round(x)), coord_t(std::round(y))) {}
  192. Point(const Point &rhs) { *this = rhs; }
  193. explicit Point(const Vec2d& rhs) : Vec2crd(coord_t(std::round(rhs.x())), coord_t(std::round(rhs.y()))) {}
  194. // This constructor allows you to construct Point from Eigen expressions
  195. // This constructor has to be implicit (non-explicit) to allow implicit conversion from Eigen expressions.
  196. template<typename OtherDerived>
  197. Point(const Eigen::MatrixBase<OtherDerived> &other) : Vec2crd(other) {}
  198. static Point new_scale(coordf_t x, coordf_t y) { return Point(coord_t(scale_(x)), coord_t(scale_(y))); }
  199. static Point new_scale(const Point &p) { return Point(scale_t(p.x()), scale_t(p.y())); }
  200. template<typename OtherDerived>
  201. static Point new_scale(const Eigen::MatrixBase<OtherDerived> &v) { return Point(scale_t(v.x()), scale_t(v.y())); }
  202. // This method allows you to assign Eigen expressions to MyVectorType
  203. template<typename OtherDerived>
  204. Point& operator=(const Eigen::MatrixBase<OtherDerived> &other)
  205. {
  206. this->Vec2crd::operator=(other);
  207. return *this;
  208. }
  209. Point& operator+=(const Point& rhs) { this->x() += rhs.x(); this->y() += rhs.y(); return *this; }
  210. Point& operator-=(const Point& rhs) { this->x() -= rhs.x(); this->y() -= rhs.y(); return *this; }
  211. Point& operator*=(const double &rhs) { this->x() = coord_t(this->x() * rhs); this->y() = coord_t(this->y() * rhs); return *this; }
  212. //Point operator*(const double &rhs) const { return Point(this->x() * rhs, this->y() * rhs); } //already exist outside
  213. void rotate(double angle) { this->rotate(std::cos(angle), std::sin(angle)); }
  214. void rotate(double cos_a, double sin_a) {
  215. double cur_x = (double)this->x();
  216. double cur_y = (double)this->y();
  217. this->x() = (coord_t)round(cos_a * cur_x - sin_a * cur_y);
  218. this->y() = (coord_t)round(cos_a * cur_y + sin_a * cur_x);
  219. }
  220. void rotate(double angle, const Point &center);
  221. Point rotated(double angle) const { Point res(*this); res.rotate(angle); return res; }
  222. Point rotated(double cos_a, double sin_a) const { Point res(*this); res.rotate(cos_a, sin_a); return res; }
  223. Point rotated(double angle, const Point &center) const { Point res(*this); res.rotate(angle, center); return res; }
  224. Point projection_onto(const Point &line_pa, const Point &line_pb) const;
  225. Point interpolate(const double percent, const Point &p) const;
  226. coordf_t distance_to(const Point &point) const { return (point - *this).cast<coordf_t>().norm(); }
  227. coordf_t distance_to_square(const Point &point) const {
  228. coordf_t dx = double(point.x() - this->x());
  229. coordf_t dy = double(point.y() - this->y());
  230. return dx*dx + dy*dy;
  231. }
  232. bool coincides_with(const Point &point) const { return this->x() == point.x() && this->y() == point.y(); }
  233. bool coincides_with_epsilon(const Point &point) const {
  234. return std::abs(this->x() - point.x()) < SCALED_EPSILON/2 && std::abs(this->y() - point.y()) < SCALED_EPSILON/2;
  235. }
  236. };
  237. inline bool operator<(const Point &l, const Point &r)
  238. {
  239. return l.x() < r.x() || (l.x() == r.x() && l.y() < r.y());
  240. }
  241. inline Point operator* (const Point& l, const double &r)
  242. {
  243. return {coord_t(l.x() * r), coord_t(l.y() * r)};
  244. }
  245. inline bool is_approx(const Point &p1, const Point &p2, coord_t epsilon = coord_t(SCALED_EPSILON))
  246. {
  247. Point d = (p2 - p1).cwiseAbs();
  248. return d.x() < epsilon && d.y() < epsilon;
  249. }
  250. inline bool is_approx(const Vec2f &p1, const Vec2f &p2, float epsilon = float(EPSILON))
  251. {
  252. Vec2f d = (p2 - p1).cwiseAbs();
  253. return d.x() < epsilon && d.y() < epsilon;
  254. }
  255. inline bool is_approx(const Vec2d &p1, const Vec2d &p2, double epsilon = EPSILON)
  256. {
  257. Vec2d d = (p2 - p1).cwiseAbs();
  258. return d.x() < epsilon && d.y() < epsilon;
  259. }
  260. inline bool is_approx(const Vec3f &p1, const Vec3f &p2, float epsilon = float(EPSILON))
  261. {
  262. Vec3f d = (p2 - p1).cwiseAbs();
  263. return d.x() < epsilon && d.y() < epsilon && d.z() < epsilon;
  264. }
  265. inline bool is_approx(const Vec3d &p1, const Vec3d &p2, double epsilon = EPSILON)
  266. {
  267. Vec3d d = (p2 - p1).cwiseAbs();
  268. return d.x() < epsilon && d.y() < epsilon && d.z() < epsilon;
  269. }
  270. inline Point lerp(const Point &a, const Point &b, double t)
  271. {
  272. assert((t >= -EPSILON) && (t <= 1. + EPSILON));
  273. return ((1. - t) * a.cast<double>() + t * b.cast<double>()).cast<coord_t>();
  274. }
  275. // if IncludeBoundary, then a bounding box is defined even for a single point.
  276. // otherwise a bounding box is only defined if it has a positive area.
  277. template<bool IncludeBoundary = false>
  278. BoundingBox get_extents(const Points &pts);
  279. extern template BoundingBox get_extents<false>(const Points &pts);
  280. extern template BoundingBox get_extents<true>(const Points &pts);
  281. // if IncludeBoundary, then a bounding box is defined even for a single point.
  282. // otherwise a bounding box is only defined if it has a positive area.
  283. template<bool IncludeBoundary = false>
  284. BoundingBox get_extents(const VecOfPoints &pts);
  285. extern template BoundingBox get_extents<false>(const VecOfPoints &pts);
  286. extern template BoundingBox get_extents<true>(const VecOfPoints &pts);
  287. BoundingBoxf get_extents(const std::vector<Vec2d> &pts);
  288. int nearest_point_index(const Points &points, const Point &pt);
  289. inline std::pair<Point, bool> nearest_point(const Points &points, const Point &pt)
  290. {
  291. int idx = nearest_point_index(points, pt);
  292. return idx == -1 ? std::make_pair(Point(), false) : std::make_pair(points[idx], true);
  293. }
  294. // Test for duplicate points in a vector of points.
  295. // The points are copied, sorted and checked for duplicates globally.
  296. bool has_duplicate_points(Points &&pts);
  297. inline bool has_duplicate_points(const Points &pts)
  298. {
  299. Points cpy = pts;
  300. return has_duplicate_points(std::move(cpy));
  301. }
  302. // Test for duplicate points in a vector of points.
  303. // Only successive points are checked for equality.
  304. inline bool has_duplicate_successive_points(const Points &pts)
  305. {
  306. for (size_t i = 1; i < pts.size(); ++ i)
  307. if (pts[i - 1] == pts[i])
  308. return true;
  309. return false;
  310. }
  311. // Test for duplicate points in a vector of points.
  312. // Only successive points are checked for equality. Additionally, first and last points are compared for equality.
  313. inline bool has_duplicate_successive_points_closed(const Points &pts)
  314. {
  315. return has_duplicate_successive_points(pts) || (pts.size() >= 2 && pts.front() == pts.back());
  316. }
  317. // Collect adjecent(duplicit points)
  318. Points collect_duplicates(Points pts /* Copy */);
  319. inline bool shorter_then(const Point& p0, const coord_t len)
  320. {
  321. if (p0.x() > len || p0.x() < -len)
  322. return false;
  323. if (p0.y() > len || p0.y() < -len)
  324. return false;
  325. return p0.cast<int64_t>().squaredNorm() <= Slic3r::sqr(int64_t(len));
  326. }
  327. namespace int128 {
  328. // Exact orientation predicate,
  329. // returns +1: CCW, 0: collinear, -1: CW.
  330. int orient(const Vec2crd &p1, const Vec2crd &p2, const Vec2crd &p3);
  331. // Exact orientation predicate,
  332. // returns +1: CCW, 0: collinear, -1: CW.
  333. int cross(const Vec2crd &v1, const Vec2crd &v2);
  334. }
  335. // To be used by std::unordered_map, std::unordered_multimap and friends.
  336. struct PointHash {
  337. size_t operator()(const Vec2crd &pt) const noexcept {
  338. return coord_t((89 * 31 + int64_t(pt.x())) * 31 + pt.y());
  339. }
  340. };
  341. // A generic class to search for a closest Point in a given radius.
  342. // It uses std::unordered_multimap to implement an efficient 2D spatial hashing.
  343. // The PointAccessor has to return const Point*.
  344. // If a nullptr is returned, it is ignored by the query.
  345. template<typename ValueType, typename PointAccessor> class ClosestPointInRadiusLookup
  346. {
  347. public:
  348. ClosestPointInRadiusLookup(coord_t search_radius, PointAccessor point_accessor = PointAccessor()) :
  349. m_search_radius(search_radius), m_point_accessor(point_accessor), m_grid_log2(0)
  350. {
  351. // Resolution of a grid, twice the search radius + some epsilon.
  352. coord_t gridres = 2 * m_search_radius + 4;
  353. m_grid_resolution = gridres;
  354. assert(m_grid_resolution > 0);
  355. assert(m_grid_resolution < (coord_t(1) << 30));
  356. // Compute m_grid_log2 = log2(m_grid_resolution)
  357. if (m_grid_resolution > 32767) {
  358. m_grid_resolution >>= 16;
  359. m_grid_log2 += 16;
  360. }
  361. if (m_grid_resolution > 127) {
  362. m_grid_resolution >>= 8;
  363. m_grid_log2 += 8;
  364. }
  365. if (m_grid_resolution > 7) {
  366. m_grid_resolution >>= 4;
  367. m_grid_log2 += 4;
  368. }
  369. if (m_grid_resolution > 1) {
  370. m_grid_resolution >>= 2;
  371. m_grid_log2 += 2;
  372. }
  373. if (m_grid_resolution > 0)
  374. ++ m_grid_log2;
  375. m_grid_resolution = ((coord_t)1) << m_grid_log2;
  376. assert(m_grid_resolution >= gridres);
  377. assert(gridres > m_grid_resolution / 2);
  378. }
  379. void insert(const ValueType &value) {
  380. const Vec2crd *pt = m_point_accessor(value);
  381. if (pt != nullptr)
  382. m_map.emplace(std::make_pair(Vec2crd(pt->x()>>m_grid_log2, pt->y()>>m_grid_log2), value));
  383. }
  384. void insert(ValueType &&value) {
  385. const Vec2crd *pt = m_point_accessor(value);
  386. if (pt != nullptr)
  387. m_map.emplace(std::make_pair(Vec2crd(pt->x()>>m_grid_log2, pt->y()>>m_grid_log2), std::move(value)));
  388. }
  389. // Erase a data point equal to value. (ValueType has to declare the operator==).
  390. // Returns true if the data point equal to value was found and removed.
  391. bool erase(const ValueType &value) {
  392. const Point *pt = m_point_accessor(value);
  393. if (pt != nullptr) {
  394. // Range of fragment starts around grid_corner, close to pt.
  395. auto range = m_map.equal_range(Point((*pt).x()>>m_grid_log2, (*pt).y()>>m_grid_log2));
  396. // Remove the first item.
  397. for (auto it = range.first; it != range.second; ++ it) {
  398. if (it->second == value) {
  399. m_map.erase(it);
  400. return true;
  401. }
  402. }
  403. }
  404. return false;
  405. }
  406. // Return a pair of <ValueType*, distance_squared>
  407. std::pair<const ValueType*, double> find(const Vec2crd &pt) {
  408. // Iterate over 4 closest grid cells around pt,
  409. // find the closest start point inside these cells to pt.
  410. const ValueType *value_min = nullptr;
  411. double dist_min = std::numeric_limits<double>::max();
  412. // Round pt to a closest grid_cell corner.
  413. Vec2crd grid_corner((pt.x()+(m_grid_resolution>>1))>>m_grid_log2, (pt.y()+(m_grid_resolution>>1))>>m_grid_log2);
  414. // For four neighbors of grid_corner:
  415. for (coord_t neighbor_y = -1; neighbor_y < 1; ++ neighbor_y) {
  416. for (coord_t neighbor_x = -1; neighbor_x < 1; ++ neighbor_x) {
  417. // Range of fragment starts around grid_corner, close to pt.
  418. auto range = m_map.equal_range(Vec2crd(grid_corner.x() + neighbor_x, grid_corner.y() + neighbor_y));
  419. // Find the map entry closest to pt.
  420. for (auto it = range.first; it != range.second; ++it) {
  421. const ValueType &value = it->second;
  422. const Vec2crd *pt2 = m_point_accessor(value);
  423. if (pt2 != nullptr) {
  424. const double d2 = (pt - *pt2).cast<double>().squaredNorm();
  425. if (d2 < dist_min) {
  426. dist_min = d2;
  427. value_min = &value;
  428. }
  429. }
  430. }
  431. }
  432. }
  433. return (value_min != nullptr && dist_min < coordf_t(m_search_radius) * coordf_t(m_search_radius)) ?
  434. std::make_pair(value_min, dist_min) :
  435. std::make_pair(nullptr, std::numeric_limits<double>::max());
  436. }
  437. // Returns all pairs of values and squared distances.
  438. std::vector<std::pair<const ValueType*, double>> find_all(const Vec2crd &pt) {
  439. // Iterate over 4 closest grid cells around pt,
  440. // Round pt to a closest grid_cell corner.
  441. Vec2crd grid_corner((pt.x()+(m_grid_resolution>>1))>>m_grid_log2, (pt.y()+(m_grid_resolution>>1))>>m_grid_log2);
  442. // For four neighbors of grid_corner:
  443. std::vector<std::pair<const ValueType*, double>> out;
  444. const double r2 = double(m_search_radius) * m_search_radius;
  445. for (coord_t neighbor_y = -1; neighbor_y < 1; ++ neighbor_y) {
  446. for (coord_t neighbor_x = -1; neighbor_x < 1; ++ neighbor_x) {
  447. // Range of fragment starts around grid_corner, close to pt.
  448. auto range = m_map.equal_range(Vec2crd(grid_corner.x() + neighbor_x, grid_corner.y() + neighbor_y));
  449. // Find the map entry closest to pt.
  450. for (auto it = range.first; it != range.second; ++it) {
  451. const ValueType &value = it->second;
  452. const Vec2crd *pt2 = m_point_accessor(value);
  453. if (pt2 != nullptr) {
  454. const double d2 = (pt - *pt2).cast<double>().squaredNorm();
  455. if (d2 <= r2)
  456. out.emplace_back(&value, d2);
  457. }
  458. }
  459. }
  460. }
  461. return out;
  462. }
  463. private:
  464. using map_type = typename std::unordered_multimap<Vec2crd, ValueType, PointHash>;
  465. PointAccessor m_point_accessor;
  466. map_type m_map;
  467. coord_t m_search_radius;
  468. coord_t m_grid_resolution;
  469. coord_t m_grid_log2;
  470. };
  471. std::ostream& operator<<(std::ostream &stm, const Vec2d &pointf);
  472. // /////////////////////////////////////////////////////////////////////////////
  473. // Type safe conversions to and from scaled and unscaled coordinates
  474. // /////////////////////////////////////////////////////////////////////////////
  475. // Semantics are the following:
  476. // Upscaling (scaled()): only from floating point types (or Vec) to either
  477. // floating point or integer 'scaled coord' coordinates.
  478. // Downscaling (unscaled()): from arithmetic (or Vec) to floating point only
  479. // Conversion definition from unscaled to floating point scaled
  480. template<class Tout,
  481. class Tin,
  482. class = FloatingOnly<Tin>>
  483. inline constexpr FloatingOnly<Tout> scaled(const Tin &v) noexcept
  484. {
  485. return Tout(v / Tin(SCALING_FACTOR));
  486. }
  487. // Conversion definition from unscaled to integer 'scaled coord'.
  488. // TODO: is the rounding necessary? Here it is commented out to show that
  489. // it can be different for integers but it does not have to be. Using
  490. // std::round means loosing noexcept and constexpr modifiers
  491. template<class Tout = coord_t, class Tin, class = FloatingOnly<Tin>>
  492. inline constexpr ScaledCoordOnly<Tout> scaled(const Tin &v) noexcept
  493. {
  494. //return static_cast<Tout>(std::round(v / SCALING_FACTOR));
  495. return Tout(v / Tin(SCALING_FACTOR));
  496. }
  497. // Conversion for Eigen vectors (N dimensional points)
  498. template<class Tout = coord_t,
  499. class Tin,
  500. int N,
  501. class = FloatingOnly<Tin>,
  502. int...EigenArgs>
  503. inline Eigen::Matrix<ArithmeticOnly<Tout>, N, EigenArgs...>
  504. scaled(const Eigen::Matrix<Tin, N, EigenArgs...> &v)
  505. {
  506. return (v / SCALING_FACTOR).template cast<Tout>();
  507. }
  508. // Conversion from arithmetic scaled type to floating point unscaled
  509. template<class Tout = double,
  510. class Tin,
  511. class = ArithmeticOnly<Tin>,
  512. class = FloatingOnly<Tout>>
  513. inline constexpr Tout unscaled(const Tin &v) noexcept
  514. {
  515. return Tout(v) * Tout(SCALING_FACTOR);
  516. }
  517. // Unscaling for Eigen vectors. Input base type can be arithmetic, output base
  518. // type can only be floating point.
  519. template<class Tout = double,
  520. class Tin,
  521. int N,
  522. class = ArithmeticOnly<Tin>,
  523. class = FloatingOnly<Tout>,
  524. int...EigenArgs>
  525. inline constexpr Eigen::Matrix<Tout, N, EigenArgs...>
  526. unscaled(const Eigen::Matrix<Tin, N, EigenArgs...> &v) noexcept
  527. {
  528. return v.template cast<Tout>() * Tout(SCALING_FACTOR);
  529. }
  530. // Align a coordinate to a grid. The coordinate may be negative,
  531. // the aligned value will never be bigger than the original one.
  532. inline coord_t align_to_grid(const coord_t coord, const coord_t spacing) {
  533. // Current C++ standard defines the result of integer division to be rounded to zero,
  534. // for both positive and negative numbers. Here we want to round down for negative
  535. // numbers as well.
  536. coord_t aligned = (coord < 0) ?
  537. ((coord - spacing + 1) / spacing) * spacing :
  538. (coord / spacing) * spacing;
  539. assert(aligned <= coord);
  540. return aligned;
  541. }
  542. inline Point align_to_grid(Point coord, Point spacing)
  543. { return Point(align_to_grid(coord.x(), spacing.x()), align_to_grid(coord.y(), spacing.y())); }
  544. inline coord_t align_to_grid(coord_t coord, coord_t spacing, coord_t base)
  545. { return base + align_to_grid(coord - base, spacing); }
  546. inline Point align_to_grid(Point coord, Point spacing, Point base)
  547. { return Point(align_to_grid(coord.x(), spacing.x(), base.x()), align_to_grid(coord.y(), spacing.y(), base.y())); }
  548. // MinMaxLimits
  549. template<typename T> struct MinMax { T min; T max;};
  550. template<typename T>
  551. static bool apply(std::optional<T> &val, const MinMax<T> &limit) {
  552. if (!val.has_value()) return false;
  553. return apply<T>(*val, limit);
  554. }
  555. template<typename T>
  556. static bool apply(T &val, const MinMax<T> &limit)
  557. {
  558. if (val > limit.max) {
  559. val = limit.max;
  560. return true;
  561. }
  562. if (val < limit.min) {
  563. val = limit.min;
  564. return true;
  565. }
  566. return false;
  567. }
  568. } // namespace Slic3r
  569. // start Boost
  570. #include <boost/version.hpp>
  571. #include <boost/polygon/polygon.hpp>
  572. namespace boost { namespace polygon {
  573. template <>
  574. struct geometry_concept<Slic3r::Point> { using type = point_concept; };
  575. template <>
  576. struct point_traits<Slic3r::Point> {
  577. using coordinate_type = coord_t;
  578. static inline coordinate_type get(const Slic3r::Point& point, orientation_2d orient) {
  579. return static_cast<coordinate_type>(point((orient == HORIZONTAL) ? 0 : 1));
  580. }
  581. };
  582. template <>
  583. struct point_mutable_traits<Slic3r::Point> {
  584. using coordinate_type = coord_t;
  585. static inline void set(Slic3r::Point& point, orientation_2d orient, coord_t value) {
  586. point((orient == HORIZONTAL) ? 0 : 1) = value;
  587. }
  588. static inline Slic3r::Point construct(coord_t x_value, coord_t y_value) {
  589. return Slic3r::Point(x_value, y_value);
  590. }
  591. };
  592. } }
  593. // end Boost
  594. #include <cereal/cereal.hpp>
  595. // Serialization through the Cereal library
  596. namespace cereal {
  597. // template<class Archive> void serialize(Archive& archive, Slic3r::Vec2crd &v) { archive(v.x(), v.y()); }
  598. // template<class Archive> void serialize(Archive& archive, Slic3r::Vec3crd &v) { archive(v.x(), v.y(), v.z()); }
  599. template<class Archive> void serialize(Archive& archive, Slic3r::Vec2i32 &v) { archive(v.x(), v.y()); }
  600. template<class Archive> void serialize(Archive& archive, Slic3r::Vec3i32 &v) { archive(v.x(), v.y(), v.z()); }
  601. template<class Archive> void serialize(Archive& archive, Slic3r::Vec2i64 &v) { archive(v.x(), v.y()); }
  602. template<class Archive> void serialize(Archive& archive, Slic3r::Vec3i64 &v) { archive(v.x(), v.y(), v.z()); }
  603. template<class Archive> void serialize(Archive& archive, Slic3r::Vec2f &v) { archive(v.x(), v.y()); }
  604. template<class Archive> void serialize(Archive& archive, Slic3r::Vec3f &v) { archive(v.x(), v.y(), v.z()); }
  605. template<class Archive> void serialize(Archive& archive, Slic3r::Vec2d &v) { archive(v.x(), v.y()); }
  606. template<class Archive> void serialize(Archive& archive, Slic3r::Vec3d &v) { archive(v.x(), v.y(), v.z()); }
  607. template<class Archive> void serialize(Archive& archive, Slic3r::Matrix4d &m){ archive(binary_data(m.data(), 4*4*sizeof(double))); }
  608. template<class Archive> void serialize(Archive& archive, Slic3r::Matrix2f &m){ archive(binary_data(m.data(), 2*2*sizeof(float))); }
  609. // Eigen Transformation serialization
  610. template<class Archive, class T, int N> inline void serialize(Archive& archive, Eigen::Transform<T, N, Eigen::Affine, Eigen::DontAlign>& t){ archive(t.matrix()); }
  611. }
  612. // To be able to use Vec<> and Mat<> in range based for loops:
  613. namespace Eigen {
  614. template<class T, int N, int M>
  615. T* begin(Slic3r::Mat<N, M, T> &mat) { return mat.data(); }
  616. template<class T, int N, int M>
  617. T* end(Slic3r::Mat<N, M, T> &mat) { return mat.data() + N * M; }
  618. template<class T, int N, int M>
  619. const T* begin(const Slic3r::Mat<N, M, T> &mat) { return mat.data(); }
  620. template<class T, int N, int M>
  621. const T* end(const Slic3r::Mat<N, M, T> &mat) { return mat.data() + N * M; }
  622. } // namespace Eigen
  623. #endif