Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/libslic3r/Point.hpp')
-rw-r--r--src/libslic3r/Point.hpp153
1 files changed, 132 insertions, 21 deletions
diff --git a/src/libslic3r/Point.hpp b/src/libslic3r/Point.hpp
index dced5c02a..a6525af4e 100644
--- a/src/libslic3r/Point.hpp
+++ b/src/libslic3r/Point.hpp
@@ -13,6 +13,7 @@
namespace Slic3r {
+class BoundingBox;
class Line;
class MultiPoint;
class Point;
@@ -24,7 +25,9 @@ typedef Eigen::Matrix<coord_t, 2, 1, Eigen::DontAlign> Vec2crd;
typedef Eigen::Matrix<coord_t, 3, 1, Eigen::DontAlign> Vec3crd;
typedef Eigen::Matrix<int, 2, 1, Eigen::DontAlign> Vec2i;
typedef Eigen::Matrix<int, 3, 1, Eigen::DontAlign> Vec3i;
+typedef Eigen::Matrix<int32_t, 2, 1, Eigen::DontAlign> Vec2i32;
typedef Eigen::Matrix<int64_t, 2, 1, Eigen::DontAlign> Vec2i64;
+typedef Eigen::Matrix<int32_t, 3, 1, Eigen::DontAlign> Vec3i32;
typedef Eigen::Matrix<int64_t, 3, 1, Eigen::DontAlign> Vec3i64;
// Vector types with a double coordinate base type.
@@ -53,20 +56,20 @@ typedef Eigen::Transform<double, 3, Eigen::Affine, Eigen::DontAlign> Transform3d
inline bool operator<(const Vec2d &lhs, const Vec2d &rhs) { return lhs(0) < rhs(0) || (lhs(0) == rhs(0) && lhs(1) < rhs(1)); }
+// One likely does not want to perform the cross product with a 32bit accumulator.
+//inline int32_t cross2(const Vec2i32 &v1, const Vec2i32 &v2) { return v1(0) * v2(1) - v1(1) * v2(0); }
inline int64_t cross2(const Vec2i64 &v1, const Vec2i64 &v2) { return v1(0) * v2(1) - v1(1) * v2(0); }
-inline coord_t cross2(const Vec2crd &v1, const Vec2crd &v2) { return v1(0) * v2(1) - v1(1) * v2(0); }
inline float cross2(const Vec2f &v1, const Vec2f &v2) { return v1(0) * v2(1) - v1(1) * v2(0); }
inline double cross2(const Vec2d &v1, const Vec2d &v2) { return v1(0) * v2(1) - v1(1) * v2(0); }
-inline Vec2crd to_2d(const Vec3crd &pt3) { return Vec2crd(pt3(0), pt3(1)); }
-inline Vec2i64 to_2d(const Vec3i64 &pt3) { return Vec2i64(pt3(0), pt3(1)); }
-inline Vec2f to_2d(const Vec3f &pt3) { return Vec2f (pt3(0), pt3(1)); }
-inline Vec2d to_2d(const Vec3d &pt3) { return Vec2d (pt3(0), pt3(1)); }
+template<typename T, int Options>
+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()); }
-inline Vec3d to_3d(const Vec2d &v, double z) { return Vec3d(v(0), v(1), z); }
-inline Vec3f to_3d(const Vec2f &v, float z) { return Vec3f(v(0), v(1), z); }
-inline Vec3i64 to_3d(const Vec2i64 &v, float z) { return Vec3i64(int64_t(v(0)), int64_t(v(1)), int64_t(z)); }
-inline Vec3crd to_3d(const Vec3crd &p, coord_t z) { return Vec3crd(p(0), p(1), z); }
+template<class T, int N, int Options>
+Eigen::Matrix<T, 2, 1, Eigen::DontAlign> to_2d(const Eigen::MatrixBase<Eigen::Matrix<T, N, 1, Options>> &ptN) { return { ptN(0), ptN(1) }; }
+
+template<class T, int Options>
+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 }; }
inline Vec2d unscale(coord_t x, coord_t y) { return Vec2d(unscale<double>(x), unscale<double>(y)); }
inline Vec2d unscale(const Vec2crd &pt) { return Vec2d(unscale<double>(pt(0)), unscale<double>(pt(1))); }
@@ -83,14 +86,16 @@ inline std::string to_string(const Vec3d &pt) { return std::string("[") + std:
std::vector<Vec3f> transform(const std::vector<Vec3f>& points, const Transform3f& t);
Pointf3s transform(const Pointf3s& points, const Transform3d& t);
+template<int N, class T> using Vec = Eigen::Matrix<T, N, 1, Eigen::DontAlign, N, 1>;
+
class Point : public Vec2crd
{
public:
typedef coord_t coord_type;
Point() : Vec2crd(0, 0) {}
- Point(coord_t x, coord_t y) : Vec2crd(x, y) {}
- Point(int64_t x, int64_t y) : Vec2crd(coord_t(x), coord_t(y)) {} // for Clipper
+ Point(int32_t x, int32_t y) : Vec2crd(coord_t(x), coord_t(y)) {}
+ Point(int64_t x, int64_t y) : Vec2crd(coord_t(x), coord_t(y)) {}
Point(double x, double y) : Vec2crd(coord_t(lrint(x)), coord_t(lrint(y))) {}
Point(const Point &rhs) { *this = rhs; }
explicit Point(const Vec2d& rhs) : Vec2crd(coord_t(lrint(rhs.x())), coord_t(lrint(rhs.y()))) {}
@@ -98,6 +103,7 @@ public:
template<typename OtherDerived>
Point(const Eigen::MatrixBase<OtherDerived> &other) : Vec2crd(other) {}
static Point new_scale(coordf_t x, coordf_t y) { return Point(coord_t(scale_(x)), coord_t(scale_(y))); }
+ static Point new_scale(const Vec2d &v) { return Point(coord_t(scale_(v.x())), coord_t(scale_(v.y()))); }
// This method allows you to assign Eigen expressions to MyVectorType
template<typename OtherDerived>
@@ -112,10 +118,19 @@ public:
Point& operator+=(const Point& rhs) { (*this)(0) += rhs(0); (*this)(1) += rhs(1); return *this; }
Point& operator-=(const Point& rhs) { (*this)(0) -= rhs(0); (*this)(1) -= rhs(1); return *this; }
Point& operator*=(const double &rhs) { (*this)(0) = coord_t((*this)(0) * rhs); (*this)(1) = coord_t((*this)(1) * rhs); return *this; }
+ Point operator*(const double &rhs) { return Point((*this)(0) * rhs, (*this)(1) * rhs); }
+
+ void rotate(double angle) { this->rotate(std::cos(angle), std::sin(angle)); }
+ void rotate(double cos_a, double sin_a) {
+ double cur_x = (double)(*this)(0);
+ double cur_y = (double)(*this)(1);
+ (*this)(0) = (coord_t)round(cos_a * cur_x - sin_a * cur_y);
+ (*this)(1) = (coord_t)round(cos_a * cur_y + sin_a * cur_x);
+ }
- void rotate(double angle);
void rotate(double angle, const Point &center);
Point rotated(double angle) const { Point res(*this); res.rotate(angle); return res; }
+ Point rotated(double cos_a, double sin_a) const { Point res(*this); res.rotate(cos_a, sin_a); return res; }
Point rotated(double angle, const Point &center) const { Point res(*this); res.rotate(angle, center); return res; }
int nearest_point_index(const Points &points) const;
int nearest_point_index(const PointConstPtrs &points) const;
@@ -158,6 +173,15 @@ inline bool is_approx(const Vec3d &p1, const Vec3d &p2, double epsilon = EPSILON
return d.x() < epsilon && d.y() < epsilon && d.z() < epsilon;
}
+inline Point lerp(const Point &a, const Point &b, double t)
+{
+ assert((t >= -EPSILON) && (t <= 1. + EPSILON));
+ return ((1. - t) * a.cast<double>() + t * b.cast<double>()).cast<coord_t>();
+}
+
+extern BoundingBox get_extents(const Points &pts);
+extern BoundingBox get_extents(const std::vector<Points> &pts);
+
namespace int128 {
// Exact orientation predicate,
// returns +1: CCW, 0: collinear, -1: CW.
@@ -275,6 +299,33 @@ public:
std::make_pair(nullptr, std::numeric_limits<double>::max());
}
+ // Returns all pairs of values and squared distances.
+ std::vector<std::pair<const ValueType*, double>> find_all(const Vec2crd &pt) {
+ // Iterate over 4 closest grid cells around pt,
+ // Round pt to a closest grid_cell corner.
+ Vec2crd grid_corner((pt(0)+(m_grid_resolution>>1))>>m_grid_log2, (pt(1)+(m_grid_resolution>>1))>>m_grid_log2);
+ // For four neighbors of grid_corner:
+ std::vector<std::pair<const ValueType*, double>> out;
+ const double r2 = double(m_search_radius) * m_search_radius;
+ for (coord_t neighbor_y = -1; neighbor_y < 1; ++ neighbor_y) {
+ for (coord_t neighbor_x = -1; neighbor_x < 1; ++ neighbor_x) {
+ // Range of fragment starts around grid_corner, close to pt.
+ auto range = m_map.equal_range(Vec2crd(grid_corner(0) + neighbor_x, grid_corner(1) + neighbor_y));
+ // Find the map entry closest to pt.
+ for (auto it = range.first; it != range.second; ++it) {
+ const ValueType &value = it->second;
+ const Vec2crd *pt2 = m_point_accessor(value);
+ if (pt2 != nullptr) {
+ const double d2 = (pt - *pt2).cast<double>().squaredNorm();
+ if (d2 <= r2)
+ out.emplace_back(&value, d2);
+ }
+ }
+ }
+ }
+ return out;
+ }
+
private:
typedef typename std::unordered_multimap<Vec2crd, ValueType, PointHash> map_type;
PointAccessor m_point_accessor;
@@ -286,6 +337,72 @@ private:
std::ostream& operator<<(std::ostream &stm, const Vec2d &pointf);
+
+// /////////////////////////////////////////////////////////////////////////////
+// Type safe conversions to and from scaled and unscaled coordinates
+// /////////////////////////////////////////////////////////////////////////////
+
+// Semantics are the following:
+// Upscaling (scaled()): only from floating point types (or Vec) to either
+// floating point or integer 'scaled coord' coordinates.
+// Downscaling (unscaled()): from arithmetic (or Vec) to floating point only
+
+// Conversion definition from unscaled to floating point scaled
+template<class Tout,
+ class Tin,
+ class = FloatingOnly<Tin>>
+inline constexpr FloatingOnly<Tout> scaled(const Tin &v) noexcept
+{
+ return Tout(v / Tin(SCALING_FACTOR));
+}
+
+// Conversion definition from unscaled to integer 'scaled coord'.
+// TODO: is the rounding necessary? Here it is commented out to show that
+// it can be different for integers but it does not have to be. Using
+// std::round means loosing noexcept and constexpr modifiers
+template<class Tout = coord_t, class Tin, class = FloatingOnly<Tin>>
+inline constexpr ScaledCoordOnly<Tout> scaled(const Tin &v) noexcept
+{
+ //return static_cast<Tout>(std::round(v / SCALING_FACTOR));
+ return Tout(v / Tin(SCALING_FACTOR));
+}
+
+// Conversion for Eigen vectors (N dimensional points)
+template<class Tout = coord_t,
+ class Tin,
+ int N,
+ class = FloatingOnly<Tin>,
+ int...EigenArgs>
+inline Eigen::Matrix<ArithmeticOnly<Tout>, N, EigenArgs...>
+scaled(const Eigen::Matrix<Tin, N, EigenArgs...> &v)
+{
+ return (v / SCALING_FACTOR).template cast<Tout>();
+}
+
+// Conversion from arithmetic scaled type to floating point unscaled
+template<class Tout = double,
+ class Tin,
+ class = ArithmeticOnly<Tin>,
+ class = FloatingOnly<Tout>>
+inline constexpr Tout unscaled(const Tin &v) noexcept
+{
+ return Tout(v * Tout(SCALING_FACTOR));
+}
+
+// Unscaling for Eigen vectors. Input base type can be arithmetic, output base
+// type can only be floating point.
+template<class Tout = double,
+ class Tin,
+ int N,
+ class = ArithmeticOnly<Tin>,
+ class = FloatingOnly<Tout>,
+ int...EigenArgs>
+inline constexpr Eigen::Matrix<Tout, N, EigenArgs...>
+unscaled(const Eigen::Matrix<Tin, N, EigenArgs...> &v) noexcept
+{
+ return v.template cast<Tout>() * SCALING_FACTOR;
+}
+
} // namespace Slic3r
// start Boost
@@ -300,7 +417,7 @@ namespace boost { namespace polygon {
typedef coord_t coordinate_type;
static inline coordinate_type get(const Slic3r::Point& point, orientation_2d orient) {
- return (orient == HORIZONTAL) ? (coordinate_type)point(0) : (coordinate_type)point(1);
+ return (coordinate_type)point((orient == HORIZONTAL) ? 0 : 1);
}
};
@@ -308,16 +425,10 @@ namespace boost { namespace polygon {
struct point_mutable_traits<Slic3r::Point> {
typedef coord_t coordinate_type;
static inline void set(Slic3r::Point& point, orientation_2d orient, coord_t value) {
- if (orient == HORIZONTAL)
- point(0) = value;
- else
- point(1) = value;
+ point((orient == HORIZONTAL) ? 0 : 1) = value;
}
static inline Slic3r::Point construct(coord_t x_value, coord_t y_value) {
- Slic3r::Point retval;
- retval(0) = x_value;
- retval(1) = y_value;
- return retval;
+ return Slic3r::Point(x_value, y_value);
}
};
} }