1 #ifndef slic3r_Point_hpp_
2 #define slic3r_Point_hpp_
3
4 #include "libslic3r.h"
5 #include <cstddef>
6 #include <vector>
7 #include <cmath>
8 #include <string>
9 #include <sstream>
10 #include <unordered_map>
11
12 #include <Eigen/Geometry>
13
14 namespace Slic3r {
15
16 class BoundingBox;
17 class Line;
18 class MultiPoint;
19 class Point;
20 typedef Point Vector;
21
22 // Eigen types, to replace the Slic3r's own types in the future.
23 // Vector types with a fixed point coordinate base type.
24 typedef Eigen::Matrix<coord_t, 2, 1, Eigen::DontAlign> Vec2crd;
25 typedef Eigen::Matrix<coord_t, 3, 1, Eigen::DontAlign> Vec3crd;
26 typedef Eigen::Matrix<int, 2, 1, Eigen::DontAlign> Vec2i;
27 typedef Eigen::Matrix<int, 3, 1, Eigen::DontAlign> Vec3i;
28 typedef Eigen::Matrix<int32_t, 2, 1, Eigen::DontAlign> Vec2i32;
29 typedef Eigen::Matrix<int64_t, 2, 1, Eigen::DontAlign> Vec2i64;
30 typedef Eigen::Matrix<int32_t, 3, 1, Eigen::DontAlign> Vec3i32;
31 typedef Eigen::Matrix<int64_t, 3, 1, Eigen::DontAlign> Vec3i64;
32
33 // Vector types with a double coordinate base type.
34 typedef Eigen::Matrix<float, 2, 1, Eigen::DontAlign> Vec2f;
35 typedef Eigen::Matrix<float, 3, 1, Eigen::DontAlign> Vec3f;
36 typedef Eigen::Matrix<double, 2, 1, Eigen::DontAlign> Vec2d;
37 typedef Eigen::Matrix<double, 3, 1, Eigen::DontAlign> Vec3d;
38
39 typedef std::vector<Point> Points;
40 typedef std::vector<Point*> PointPtrs;
41 typedef std::vector<const Point*> PointConstPtrs;
42 typedef std::vector<Vec3crd> Points3;
43 typedef std::vector<Vec2d> Pointfs;
44 typedef std::vector<Vec2d> Vec2ds;
45 typedef std::vector<Vec3d> Pointf3s;
46
47 typedef Eigen::Matrix<float, 2, 2, Eigen::DontAlign> Matrix2f;
48 typedef Eigen::Matrix<double, 2, 2, Eigen::DontAlign> Matrix2d;
49 typedef Eigen::Matrix<float, 3, 3, Eigen::DontAlign> Matrix3f;
50 typedef Eigen::Matrix<double, 3, 3, Eigen::DontAlign> Matrix3d;
51
52 typedef Eigen::Transform<float, 2, Eigen::Affine, Eigen::DontAlign> Transform2f;
53 typedef Eigen::Transform<double, 2, Eigen::Affine, Eigen::DontAlign> Transform2d;
54 typedef Eigen::Transform<float, 3, Eigen::Affine, Eigen::DontAlign> Transform3f;
55 typedef Eigen::Transform<double, 3, Eigen::Affine, Eigen::DontAlign> Transform3d;
56
operator <(const Vec2d & lhs,const Vec2d & rhs)57 inline bool operator<(const Vec2d &lhs, const Vec2d &rhs) { return lhs(0) < rhs(0) || (lhs(0) == rhs(0) && lhs(1) < rhs(1)); }
58
59 // One likely does not want to perform the cross product with a 32bit accumulator.
60 //inline int32_t cross2(const Vec2i32 &v1, const Vec2i32 &v2) { return v1(0) * v2(1) - v1(1) * v2(0); }
cross2(const Vec2i64 & v1,const Vec2i64 & v2)61 inline int64_t cross2(const Vec2i64 &v1, const Vec2i64 &v2) { return v1(0) * v2(1) - v1(1) * v2(0); }
cross2(const Vec2f & v1,const Vec2f & v2)62 inline float cross2(const Vec2f &v1, const Vec2f &v2) { return v1(0) * v2(1) - v1(1) * v2(0); }
cross2(const Vec2d & v1,const Vec2d & v2)63 inline double cross2(const Vec2d &v1, const Vec2d &v2) { return v1(0) * v2(1) - v1(1) * v2(0); }
64
65 template<typename T, int Options>
perp(const Eigen::MatrixBase<Eigen::Matrix<T,2,1,Options>> & v)66 inline Eigen::Matrix<T, 2, 1, Eigen::DontAlign> perp(const Eigen::MatrixBase<Eigen::Matrix<T, 2, 1, Options>> &v) { return Eigen::Matrix<T, 2, 1, Eigen::DontAlign>(- v.y(), v.x()); }
67
68 template<class T, int N, int Options>
to_2d(const Eigen::MatrixBase<Eigen::Matrix<T,N,1,Options>> & ptN)69 Eigen::Matrix<T, 2, 1, Eigen::DontAlign> to_2d(const Eigen::MatrixBase<Eigen::Matrix<T, N, 1, Options>> &ptN) { return { ptN(0), ptN(1) }; }
70
71 template<class T, int Options>
to_3d(const Eigen::MatrixBase<Eigen::Matrix<T,2,1,Options>> & pt,const T z)72 Eigen::Matrix<T, 3, 1, Eigen::DontAlign> to_3d(const Eigen::MatrixBase<Eigen::Matrix<T, 2, 1, Options>> & pt, const T z) { return { pt(0), pt(1), z }; }
73
unscale(coord_t x,coord_t y)74 inline Vec2d unscale(coord_t x, coord_t y) { return Vec2d(unscale<double>(x), unscale<double>(y)); }
unscale(const Vec2crd & pt)75 inline Vec2d unscale(const Vec2crd &pt) { return Vec2d(unscale<double>(pt(0)), unscale<double>(pt(1))); }
unscale(const Vec2d & pt)76 inline Vec2d unscale(const Vec2d &pt) { return Vec2d(unscale<double>(pt(0)), unscale<double>(pt(1))); }
unscale(coord_t x,coord_t y,coord_t z)77 inline Vec3d unscale(coord_t x, coord_t y, coord_t z) { return Vec3d(unscale<double>(x), unscale<double>(y), unscale<double>(z)); }
unscale(const Vec3crd & pt)78 inline Vec3d unscale(const Vec3crd &pt) { return Vec3d(unscale<double>(pt(0)), unscale<double>(pt(1)), unscale<double>(pt(2))); }
unscale(const Vec3d & pt)79 inline Vec3d unscale(const Vec3d &pt) { return Vec3d(unscale<double>(pt(0)), unscale<double>(pt(1)), unscale<double>(pt(2))); }
80
to_string(const Vec2crd & pt)81 inline std::string to_string(const Vec2crd &pt) { return std::string("[") + std::to_string(pt(0)) + ", " + std::to_string(pt(1)) + "]"; }
to_string(const Vec2d & pt)82 inline std::string to_string(const Vec2d &pt) { return std::string("[") + std::to_string(pt(0)) + ", " + std::to_string(pt(1)) + "]"; }
to_string(const Vec3crd & pt)83 inline std::string to_string(const Vec3crd &pt) { return std::string("[") + std::to_string(pt(0)) + ", " + std::to_string(pt(1)) + ", " + std::to_string(pt(2)) + "]"; }
to_string(const Vec3d & pt)84 inline std::string to_string(const Vec3d &pt) { return std::string("[") + std::to_string(pt(0)) + ", " + std::to_string(pt(1)) + ", " + std::to_string(pt(2)) + "]"; }
85
86 std::vector<Vec3f> transform(const std::vector<Vec3f>& points, const Transform3f& t);
87 Pointf3s transform(const Pointf3s& points, const Transform3d& t);
88
89 template<int N, class T> using Vec = Eigen::Matrix<T, N, 1, Eigen::DontAlign, N, 1>;
90
91 class Point : public Vec2crd
92 {
93 public:
94 typedef coord_t coord_type;
95
Point()96 Point() : Vec2crd(0, 0) {}
Point(int32_t x,int32_t y)97 Point(int32_t x, int32_t y) : Vec2crd(coord_t(x), coord_t(y)) {}
Point(int64_t x,int64_t y)98 Point(int64_t x, int64_t y) : Vec2crd(coord_t(x), coord_t(y)) {}
Point(double x,double y)99 Point(double x, double y) : Vec2crd(coord_t(lrint(x)), coord_t(lrint(y))) {}
Point(const Point & rhs)100 Point(const Point &rhs) { *this = rhs; }
Point(const Vec2d & rhs)101 explicit Point(const Vec2d& rhs) : Vec2crd(coord_t(lrint(rhs.x())), coord_t(lrint(rhs.y()))) {}
102 // This constructor allows you to construct Point from Eigen expressions
103 template<typename OtherDerived>
Point(const Eigen::MatrixBase<OtherDerived> & other)104 Point(const Eigen::MatrixBase<OtherDerived> &other) : Vec2crd(other) {}
new_scale(coordf_t x,coordf_t y)105 static Point new_scale(coordf_t x, coordf_t y) { return Point(coord_t(scale_(x)), coord_t(scale_(y))); }
new_scale(const Vec2d & v)106 static Point new_scale(const Vec2d &v) { return Point(coord_t(scale_(v.x())), coord_t(scale_(v.y()))); }
107
108 // This method allows you to assign Eigen expressions to MyVectorType
109 template<typename OtherDerived>
operator =(const Eigen::MatrixBase<OtherDerived> & other)110 Point& operator=(const Eigen::MatrixBase<OtherDerived> &other)
111 {
112 this->Vec2crd::operator=(other);
113 return *this;
114 }
115
operator <(const Point & rhs) const116 bool operator< (const Point& rhs) const { return (*this)(0) < rhs(0) || ((*this)(0) == rhs(0) && (*this)(1) < rhs(1)); }
117
operator +=(const Point & rhs)118 Point& operator+=(const Point& rhs) { (*this)(0) += rhs(0); (*this)(1) += rhs(1); return *this; }
operator -=(const Point & rhs)119 Point& operator-=(const Point& rhs) { (*this)(0) -= rhs(0); (*this)(1) -= rhs(1); return *this; }
operator *=(const double & rhs)120 Point& operator*=(const double &rhs) { (*this)(0) = coord_t((*this)(0) * rhs); (*this)(1) = coord_t((*this)(1) * rhs); return *this; }
operator *(const double & rhs)121 Point operator*(const double &rhs) { return Point((*this)(0) * rhs, (*this)(1) * rhs); }
122
rotate(double angle)123 void rotate(double angle) { this->rotate(std::cos(angle), std::sin(angle)); }
rotate(double cos_a,double sin_a)124 void rotate(double cos_a, double sin_a) {
125 double cur_x = (double)(*this)(0);
126 double cur_y = (double)(*this)(1);
127 (*this)(0) = (coord_t)round(cos_a * cur_x - sin_a * cur_y);
128 (*this)(1) = (coord_t)round(cos_a * cur_y + sin_a * cur_x);
129 }
130
131 void rotate(double angle, const Point ¢er);
rotated(double angle) const132 Point rotated(double angle) const { Point res(*this); res.rotate(angle); return res; }
rotated(double cos_a,double sin_a) const133 Point rotated(double cos_a, double sin_a) const { Point res(*this); res.rotate(cos_a, sin_a); return res; }
rotated(double angle,const Point & center) const134 Point rotated(double angle, const Point ¢er) const { Point res(*this); res.rotate(angle, center); return res; }
135 int nearest_point_index(const Points &points) const;
136 int nearest_point_index(const PointConstPtrs &points) const;
137 int nearest_point_index(const PointPtrs &points) const;
138 bool nearest_point(const Points &points, Point* point) const;
139 double ccw(const Point &p1, const Point &p2) const;
140 double ccw(const Line &line) const;
141 double ccw_angle(const Point &p1, const Point &p2) const;
142 Point projection_onto(const MultiPoint &poly) const;
143 Point projection_onto(const Line &line) const;
144 };
145
is_approx(const Point & p1,const Point & p2,coord_t epsilon=coord_t (SCALED_EPSILON))146 inline bool is_approx(const Point &p1, const Point &p2, coord_t epsilon = coord_t(SCALED_EPSILON))
147 {
148 Point d = (p2 - p1).cwiseAbs();
149 return d.x() < epsilon && d.y() < epsilon;
150 }
151
is_approx(const Vec2f & p1,const Vec2f & p2,float epsilon=float (EPSILON))152 inline bool is_approx(const Vec2f &p1, const Vec2f &p2, float epsilon = float(EPSILON))
153 {
154 Vec2f d = (p2 - p1).cwiseAbs();
155 return d.x() < epsilon && d.y() < epsilon;
156 }
157
is_approx(const Vec2d & p1,const Vec2d & p2,double epsilon=EPSILON)158 inline bool is_approx(const Vec2d &p1, const Vec2d &p2, double epsilon = EPSILON)
159 {
160 Vec2d d = (p2 - p1).cwiseAbs();
161 return d.x() < epsilon && d.y() < epsilon;
162 }
163
is_approx(const Vec3f & p1,const Vec3f & p2,float epsilon=float (EPSILON))164 inline bool is_approx(const Vec3f &p1, const Vec3f &p2, float epsilon = float(EPSILON))
165 {
166 Vec3f d = (p2 - p1).cwiseAbs();
167 return d.x() < epsilon && d.y() < epsilon && d.z() < epsilon;
168 }
169
is_approx(const Vec3d & p1,const Vec3d & p2,double epsilon=EPSILON)170 inline bool is_approx(const Vec3d &p1, const Vec3d &p2, double epsilon = EPSILON)
171 {
172 Vec3d d = (p2 - p1).cwiseAbs();
173 return d.x() < epsilon && d.y() < epsilon && d.z() < epsilon;
174 }
175
lerp(const Point & a,const Point & b,double t)176 inline Point lerp(const Point &a, const Point &b, double t)
177 {
178 assert((t >= -EPSILON) && (t <= 1. + EPSILON));
179 return ((1. - t) * a.cast<double>() + t * b.cast<double>()).cast<coord_t>();
180 }
181
182 extern BoundingBox get_extents(const Points &pts);
183 extern BoundingBox get_extents(const std::vector<Points> &pts);
184
185 namespace int128 {
186 // Exact orientation predicate,
187 // returns +1: CCW, 0: collinear, -1: CW.
188 int orient(const Vec2crd &p1, const Vec2crd &p2, const Vec2crd &p3);
189 // Exact orientation predicate,
190 // returns +1: CCW, 0: collinear, -1: CW.
191 int cross(const Vec2crd &v1, const Vec2crd &v2);
192 }
193
194 // To be used by std::unordered_map, std::unordered_multimap and friends.
195 struct PointHash {
operator ()Slic3r::PointHash196 size_t operator()(const Vec2crd &pt) const {
197 return std::hash<coord_t>()(pt(0)) ^ std::hash<coord_t>()(pt(1));
198 }
199 };
200
201 // A generic class to search for a closest Point in a given radius.
202 // It uses std::unordered_multimap to implement an efficient 2D spatial hashing.
203 // The PointAccessor has to return const Point*.
204 // If a nullptr is returned, it is ignored by the query.
205 template<typename ValueType, typename PointAccessor> class ClosestPointInRadiusLookup
206 {
207 public:
ClosestPointInRadiusLookup(coord_t search_radius,PointAccessor point_accessor=PointAccessor ())208 ClosestPointInRadiusLookup(coord_t search_radius, PointAccessor point_accessor = PointAccessor()) :
209 m_search_radius(search_radius), m_point_accessor(point_accessor), m_grid_log2(0)
210 {
211 // Resolution of a grid, twice the search radius + some epsilon.
212 coord_t gridres = 2 * m_search_radius + 4;
213 m_grid_resolution = gridres;
214 assert(m_grid_resolution > 0);
215 assert(m_grid_resolution < (coord_t(1) << 30));
216 // Compute m_grid_log2 = log2(m_grid_resolution)
217 if (m_grid_resolution > 32767) {
218 m_grid_resolution >>= 16;
219 m_grid_log2 += 16;
220 }
221 if (m_grid_resolution > 127) {
222 m_grid_resolution >>= 8;
223 m_grid_log2 += 8;
224 }
225 if (m_grid_resolution > 7) {
226 m_grid_resolution >>= 4;
227 m_grid_log2 += 4;
228 }
229 if (m_grid_resolution > 1) {
230 m_grid_resolution >>= 2;
231 m_grid_log2 += 2;
232 }
233 if (m_grid_resolution > 0)
234 ++ m_grid_log2;
235 m_grid_resolution = 1 << m_grid_log2;
236 assert(m_grid_resolution >= gridres);
237 assert(gridres > m_grid_resolution / 2);
238 }
239
insert(const ValueType & value)240 void insert(const ValueType &value) {
241 const Vec2crd *pt = m_point_accessor(value);
242 if (pt != nullptr)
243 m_map.emplace(std::make_pair(Vec2crd(pt->x()>>m_grid_log2, pt->y()>>m_grid_log2), value));
244 }
245
insert(ValueType && value)246 void insert(ValueType &&value) {
247 const Vec2crd *pt = m_point_accessor(value);
248 if (pt != nullptr)
249 m_map.emplace(std::make_pair(Vec2crd(pt->x()>>m_grid_log2, pt->y()>>m_grid_log2), std::move(value)));
250 }
251
252 // Erase a data point equal to value. (ValueType has to declare the operator==).
253 // Returns true if the data point equal to value was found and removed.
erase(const ValueType & value)254 bool erase(const ValueType &value) {
255 const Point *pt = m_point_accessor(value);
256 if (pt != nullptr) {
257 // Range of fragment starts around grid_corner, close to pt.
258 auto range = m_map.equal_range(Point((*pt)(0)>>m_grid_log2, (*pt)(1)>>m_grid_log2));
259 // Remove the first item.
260 for (auto it = range.first; it != range.second; ++ it) {
261 if (it->second == value) {
262 m_map.erase(it);
263 return true;
264 }
265 }
266 }
267 return false;
268 }
269
270 // Return a pair of <ValueType*, distance_squared>
find(const Vec2crd & pt)271 std::pair<const ValueType*, double> find(const Vec2crd &pt) {
272 // Iterate over 4 closest grid cells around pt,
273 // find the closest start point inside these cells to pt.
274 const ValueType *value_min = nullptr;
275 double dist_min = std::numeric_limits<double>::max();
276 // Round pt to a closest grid_cell corner.
277 Vec2crd grid_corner((pt(0)+(m_grid_resolution>>1))>>m_grid_log2, (pt(1)+(m_grid_resolution>>1))>>m_grid_log2);
278 // For four neighbors of grid_corner:
279 for (coord_t neighbor_y = -1; neighbor_y < 1; ++ neighbor_y) {
280 for (coord_t neighbor_x = -1; neighbor_x < 1; ++ neighbor_x) {
281 // Range of fragment starts around grid_corner, close to pt.
282 auto range = m_map.equal_range(Vec2crd(grid_corner(0) + neighbor_x, grid_corner(1) + neighbor_y));
283 // Find the map entry closest to pt.
284 for (auto it = range.first; it != range.second; ++it) {
285 const ValueType &value = it->second;
286 const Vec2crd *pt2 = m_point_accessor(value);
287 if (pt2 != nullptr) {
288 const double d2 = (pt - *pt2).cast<double>().squaredNorm();
289 if (d2 < dist_min) {
290 dist_min = d2;
291 value_min = &value;
292 }
293 }
294 }
295 }
296 }
297 return (value_min != nullptr && dist_min < coordf_t(m_search_radius) * coordf_t(m_search_radius)) ?
298 std::make_pair(value_min, dist_min) :
299 std::make_pair(nullptr, std::numeric_limits<double>::max());
300 }
301
302 // Returns all pairs of values and squared distances.
find_all(const Vec2crd & pt)303 std::vector<std::pair<const ValueType*, double>> find_all(const Vec2crd &pt) {
304 // Iterate over 4 closest grid cells around pt,
305 // Round pt to a closest grid_cell corner.
306 Vec2crd grid_corner((pt(0)+(m_grid_resolution>>1))>>m_grid_log2, (pt(1)+(m_grid_resolution>>1))>>m_grid_log2);
307 // For four neighbors of grid_corner:
308 std::vector<std::pair<const ValueType*, double>> out;
309 const double r2 = double(m_search_radius) * m_search_radius;
310 for (coord_t neighbor_y = -1; neighbor_y < 1; ++ neighbor_y) {
311 for (coord_t neighbor_x = -1; neighbor_x < 1; ++ neighbor_x) {
312 // Range of fragment starts around grid_corner, close to pt.
313 auto range = m_map.equal_range(Vec2crd(grid_corner(0) + neighbor_x, grid_corner(1) + neighbor_y));
314 // Find the map entry closest to pt.
315 for (auto it = range.first; it != range.second; ++it) {
316 const ValueType &value = it->second;
317 const Vec2crd *pt2 = m_point_accessor(value);
318 if (pt2 != nullptr) {
319 const double d2 = (pt - *pt2).cast<double>().squaredNorm();
320 if (d2 <= r2)
321 out.emplace_back(&value, d2);
322 }
323 }
324 }
325 }
326 return out;
327 }
328
329 private:
330 typedef typename std::unordered_multimap<Vec2crd, ValueType, PointHash> map_type;
331 PointAccessor m_point_accessor;
332 map_type m_map;
333 coord_t m_search_radius;
334 coord_t m_grid_resolution;
335 coord_t m_grid_log2;
336 };
337
338 std::ostream& operator<<(std::ostream &stm, const Vec2d &pointf);
339
340
341 // /////////////////////////////////////////////////////////////////////////////
342 // Type safe conversions to and from scaled and unscaled coordinates
343 // /////////////////////////////////////////////////////////////////////////////
344
345 // Semantics are the following:
346 // Upscaling (scaled()): only from floating point types (or Vec) to either
347 // floating point or integer 'scaled coord' coordinates.
348 // Downscaling (unscaled()): from arithmetic (or Vec) to floating point only
349
350 // Conversion definition from unscaled to floating point scaled
351 template<class Tout,
352 class Tin,
353 class = FloatingOnly<Tin>>
scaled(const Tin & v)354 inline constexpr FloatingOnly<Tout> scaled(const Tin &v) noexcept
355 {
356 return Tout(v / Tin(SCALING_FACTOR));
357 }
358
359 // Conversion definition from unscaled to integer 'scaled coord'.
360 // TODO: is the rounding necessary? Here it is commented out to show that
361 // it can be different for integers but it does not have to be. Using
362 // std::round means loosing noexcept and constexpr modifiers
363 template<class Tout = coord_t, class Tin, class = FloatingOnly<Tin>>
scaled(const Tin & v)364 inline constexpr ScaledCoordOnly<Tout> scaled(const Tin &v) noexcept
365 {
366 //return static_cast<Tout>(std::round(v / SCALING_FACTOR));
367 return Tout(v / Tin(SCALING_FACTOR));
368 }
369
370 // Conversion for Eigen vectors (N dimensional points)
371 template<class Tout = coord_t,
372 class Tin,
373 int N,
374 class = FloatingOnly<Tin>,
375 int...EigenArgs>
376 inline Eigen::Matrix<ArithmeticOnly<Tout>, N, EigenArgs...>
scaled(const Eigen::Matrix<Tin,N,EigenArgs...> & v)377 scaled(const Eigen::Matrix<Tin, N, EigenArgs...> &v)
378 {
379 return (v / SCALING_FACTOR).template cast<Tout>();
380 }
381
382 // Conversion from arithmetic scaled type to floating point unscaled
383 template<class Tout = double,
384 class Tin,
385 class = ArithmeticOnly<Tin>,
386 class = FloatingOnly<Tout>>
unscaled(const Tin & v)387 inline constexpr Tout unscaled(const Tin &v) noexcept
388 {
389 return Tout(v * Tout(SCALING_FACTOR));
390 }
391
392 // Unscaling for Eigen vectors. Input base type can be arithmetic, output base
393 // type can only be floating point.
394 template<class Tout = double,
395 class Tin,
396 int N,
397 class = ArithmeticOnly<Tin>,
398 class = FloatingOnly<Tout>,
399 int...EigenArgs>
400 inline constexpr Eigen::Matrix<Tout, N, EigenArgs...>
unscaled(const Eigen::Matrix<Tin,N,EigenArgs...> & v)401 unscaled(const Eigen::Matrix<Tin, N, EigenArgs...> &v) noexcept
402 {
403 return v.template cast<Tout>() * SCALING_FACTOR;
404 }
405
406 } // namespace Slic3r
407
408 // start Boost
409 #include <boost/version.hpp>
410 #include <boost/polygon/polygon.hpp>
411 namespace boost { namespace polygon {
412 template <>
413 struct geometry_concept<Slic3r::Point> { typedef point_concept type; };
414
415 template <>
416 struct point_traits<Slic3r::Point> {
417 typedef coord_t coordinate_type;
418
getboost::polygon::point_traits419 static inline coordinate_type get(const Slic3r::Point& point, orientation_2d orient) {
420 return (coordinate_type)point((orient == HORIZONTAL) ? 0 : 1);
421 }
422 };
423
424 template <>
425 struct point_mutable_traits<Slic3r::Point> {
426 typedef coord_t coordinate_type;
setboost::polygon::point_mutable_traits427 static inline void set(Slic3r::Point& point, orientation_2d orient, coord_t value) {
428 point((orient == HORIZONTAL) ? 0 : 1) = value;
429 }
constructboost::polygon::point_mutable_traits430 static inline Slic3r::Point construct(coord_t x_value, coord_t y_value) {
431 return Slic3r::Point(x_value, y_value);
432 }
433 };
434 } }
435 // end Boost
436
437 // Serialization through the Cereal library
438 namespace cereal {
439 // template<class Archive> void serialize(Archive& archive, Slic3r::Vec2crd &v) { archive(v.x(), v.y()); }
440 // template<class Archive> void serialize(Archive& archive, Slic3r::Vec3crd &v) { archive(v.x(), v.y(), v.z()); }
serialize(Archive & archive,Slic3r::Vec2i & v)441 template<class Archive> void serialize(Archive& archive, Slic3r::Vec2i &v) { archive(v.x(), v.y()); }
serialize(Archive & archive,Slic3r::Vec3i & v)442 template<class Archive> void serialize(Archive& archive, Slic3r::Vec3i &v) { archive(v.x(), v.y(), v.z()); }
443 // template<class Archive> void serialize(Archive& archive, Slic3r::Vec2i64 &v) { archive(v.x(), v.y()); }
444 // template<class Archive> void serialize(Archive& archive, Slic3r::Vec3i64 &v) { archive(v.x(), v.y(), v.z()); }
serialize(Archive & archive,Slic3r::Vec2f & v)445 template<class Archive> void serialize(Archive& archive, Slic3r::Vec2f &v) { archive(v.x(), v.y()); }
serialize(Archive & archive,Slic3r::Vec3f & v)446 template<class Archive> void serialize(Archive& archive, Slic3r::Vec3f &v) { archive(v.x(), v.y(), v.z()); }
serialize(Archive & archive,Slic3r::Vec2d & v)447 template<class Archive> void serialize(Archive& archive, Slic3r::Vec2d &v) { archive(v.x(), v.y()); }
serialize(Archive & archive,Slic3r::Vec3d & v)448 template<class Archive> void serialize(Archive& archive, Slic3r::Vec3d &v) { archive(v.x(), v.y(), v.z()); }
449
load(Archive & archive,Slic3r::Matrix2f & m)450 template<class Archive> void load(Archive& archive, Slic3r::Matrix2f &m) { archive.loadBinary((char*)m.data(), sizeof(float) * 4); }
save(Archive & archive,Slic3r::Matrix2f & m)451 template<class Archive> void save(Archive& archive, Slic3r::Matrix2f &m) { archive.saveBinary((char*)m.data(), sizeof(float) * 4); }
452 }
453
454 #endif
455