diff --git a/src/libslic3r/BoundingBox.hpp b/src/libslic3r/BoundingBox.hpp index 4fbe72163c..2216d78882 100644 --- a/src/libslic3r/BoundingBox.hpp +++ b/src/libslic3r/BoundingBox.hpp @@ -186,6 +186,11 @@ inline bool empty(const BoundingBox3Base &bb) return ! bb.defined || bb.min(0) >= bb.max(0) || bb.min(1) >= bb.max(1) || bb.min(2) >= bb.max(2); } +inline BoundingBox scaled(const BoundingBoxf &bb) { return {scaled(bb.min), scaled(bb.max)}; } +inline BoundingBox3 scaled(const BoundingBoxf3 &bb) { return {scaled(bb.min), scaled(bb.max)}; } +inline BoundingBoxf unscaled(const BoundingBox &bb) { return {unscaled(bb.min), unscaled(bb.max)}; } +inline BoundingBoxf3 unscaled(const BoundingBox3 &bb) { return {unscaled(bb.min), unscaled(bb.max)}; } + } // namespace Slic3r // Serialization through the Cereal library diff --git a/src/libslic3r/MTUtils.hpp b/src/libslic3r/MTUtils.hpp index 3402d2c856..170a6599c6 100644 --- a/src/libslic3r/MTUtils.hpp +++ b/src/libslic3r/MTUtils.hpp @@ -11,6 +11,7 @@ #include "libslic3r.h" #include "Point.hpp" +#include "BoundingBox.hpp" namespace Slic3r { @@ -75,143 +76,6 @@ public: } }; -/// An std compatible random access iterator which uses indices to the -/// source vector thus resistant to invalidation caused by relocations. It -/// also "knows" its container. No comparison is neccesary to the container -/// "end()" iterator. The template can be instantiated with a different -/// value type than that of the container's but the types must be -/// compatible. E.g. a base class of the contained objects is compatible. -/// -/// For a constant iterator, one can instantiate this template with a value -/// type preceded with 'const'. -template -class IndexBasedIterator -{ - static const size_t NONE = size_t(-1); - - std::reference_wrapper m_index_ref; - size_t m_idx = NONE; - -public: - using value_type = Value; - using pointer = Value *; - using reference = Value &; - using difference_type = long; - using iterator_category = std::random_access_iterator_tag; - - inline explicit IndexBasedIterator(Vector &index, size_t idx) - : m_index_ref(index), m_idx(idx) - {} - - // Post increment - inline IndexBasedIterator operator++(int) - { - IndexBasedIterator cpy(*this); - ++m_idx; - return cpy; - } - - inline IndexBasedIterator operator--(int) - { - IndexBasedIterator cpy(*this); - --m_idx; - return cpy; - } - - inline IndexBasedIterator &operator++() - { - ++m_idx; - return *this; - } - - inline IndexBasedIterator &operator--() - { - --m_idx; - return *this; - } - - inline IndexBasedIterator &operator+=(difference_type l) - { - m_idx += size_t(l); - return *this; - } - - inline IndexBasedIterator operator+(difference_type l) - { - auto cpy = *this; - cpy += l; - return cpy; - } - - inline IndexBasedIterator &operator-=(difference_type l) - { - m_idx -= size_t(l); - return *this; - } - - inline IndexBasedIterator operator-(difference_type l) - { - auto cpy = *this; - cpy -= l; - return cpy; - } - - operator difference_type() { return difference_type(m_idx); } - - /// Tesing the end of the container... this is not possible with std - /// iterators. - inline bool is_end() const - { - return m_idx >= m_index_ref.get().size(); - } - - inline Value &operator*() const - { - assert(m_idx < m_index_ref.get().size()); - return m_index_ref.get().operator[](m_idx); - } - - inline Value *operator->() const - { - assert(m_idx < m_index_ref.get().size()); - return &m_index_ref.get().operator[](m_idx); - } - - /// If both iterators point past the container, they are equal... - inline bool operator==(const IndexBasedIterator &other) - { - size_t e = m_index_ref.get().size(); - return m_idx == other.m_idx || (m_idx >= e && other.m_idx >= e); - } - - inline bool operator!=(const IndexBasedIterator &other) - { - return !(*this == other); - } - - inline bool operator<=(const IndexBasedIterator &other) - { - return (m_idx < other.m_idx) || (*this == other); - } - - inline bool operator<(const IndexBasedIterator &other) - { - return m_idx < other.m_idx && (*this != other); - } - - inline bool operator>=(const IndexBasedIterator &other) - { - return m_idx > other.m_idx || *this == other; - } - - inline bool operator>(const IndexBasedIterator &other) - { - return m_idx > other.m_idx && *this != other; - } -}; - /// A very simple range concept implementation with iterator-like objects. template class Range { @@ -252,97 +116,6 @@ template struct remove_cvref template using remove_cvref_t = typename remove_cvref::type; -// A shorter C++14 style form of the enable_if metafunction -template -using enable_if_t = typename std::enable_if::type; - -// ///////////////////////////////////////////////////////////////////////////// -// Type safe conversions to and from scaled and unscaled coordinates -// ///////////////////////////////////////////////////////////////////////////// - -// A meta-predicate which is true for integers wider than or equal to coord_t -template struct is_scaled_coord -{ - static const SLIC3R_CONSTEXPR bool value = - std::is_integral::value && - std::numeric_limits::digits >= - std::numeric_limits::digits; -}; - -// Meta predicates for floating, 'scaled coord' and generic arithmetic types -template -using FloatingOnly = enable_if_t::value, O>; - -template -using ScaledCoordOnly = enable_if_t::value, O>; - -template -using IntegerOnly = enable_if_t::value, O>; - -template -using ArithmeticOnly = enable_if_t::value, O>; - -// 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> -inline constexpr FloatingOnly 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> -inline constexpr ScaledCoordOnly scaled(const Tin &v) noexcept -{ - //return static_cast(std::round(v / SCALING_FACTOR)); - return Tout(v / Tin(SCALING_FACTOR)); -} - -// Conversion for Eigen vectors (N dimensional points) -template, - int...EigenArgs> -inline Eigen::Matrix, N, EigenArgs...> -scaled(const Eigen::Matrix &v) -{ - return (v / SCALING_FACTOR).template cast(); -} - -// Conversion from arithmetic scaled type to floating point unscaled -template, - class = FloatingOnly> -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 = FloatingOnly, - int...EigenArgs> -inline constexpr Eigen::Matrix -unscaled(const Eigen::Matrix &v) noexcept -{ - return v.template cast() * SCALING_FACTOR; -} - template // Arbitrary allocator can be used inline IntegerOnly> reserve_vector(I capacity) { diff --git a/src/libslic3r/Point.hpp b/src/libslic3r/Point.hpp index e095f1c757..7a6b31395f 100644 --- a/src/libslic3r/Point.hpp +++ b/src/libslic3r/Point.hpp @@ -288,6 +288,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> +inline constexpr FloatingOnly 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> +inline constexpr ScaledCoordOnly scaled(const Tin &v) noexcept +{ + //return static_cast(std::round(v / SCALING_FACTOR)); + return Tout(v / Tin(SCALING_FACTOR)); +} + +// Conversion for Eigen vectors (N dimensional points) +template, + int...EigenArgs> +inline Eigen::Matrix, N, EigenArgs...> +scaled(const Eigen::Matrix &v) +{ + return (v / SCALING_FACTOR).template cast(); +} + +// Conversion from arithmetic scaled type to floating point unscaled +template, + class = FloatingOnly> +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 = FloatingOnly, + int...EigenArgs> +inline constexpr Eigen::Matrix +unscaled(const Eigen::Matrix &v) noexcept +{ + return v.template cast() * SCALING_FACTOR; +} + } // namespace Slic3r // start Boost diff --git a/src/libslic3r/libslic3r.h b/src/libslic3r/libslic3r.h index 1cf946f8b8..5012762a9c 100644 --- a/src/libslic3r/libslic3r.h +++ b/src/libslic3r/libslic3r.h @@ -17,6 +17,7 @@ #include #include #include +#include #include "Technologies.hpp" #include "Semver.hpp" @@ -247,6 +248,37 @@ static inline bool is_approx(Number value, Number test_value) return std::fabs(double(value) - double(test_value)) < double(EPSILON); } +// A meta-predicate which is true for integers wider than or equal to coord_t +template struct is_scaled_coord +{ + static const constexpr bool value = + std::is_integral::value && + std::numeric_limits::digits >= + std::numeric_limits::digits; +}; + +// Meta predicates for floating, 'scaled coord' and generic arithmetic types +// Can be used to restrict templates to work for only the specified set of types. +// parameter T is the type we want to restrict +// parameter O (Optional defaults to T) is the type that the whole expression +// will be evaluated to. +// e.g. template FloatingOnly is_nan(T val); +// The whole template will be defined only for floating point types and the +// return type will be bool. +// For more info how to use, see docs for std::enable_if +// +template +using FloatingOnly = std::enable_if_t::value, O>; + +template +using ScaledCoordOnly = std::enable_if_t::value, O>; + +template +using IntegerOnly = std::enable_if_t::value, O>; + +template +using ArithmeticOnly = std::enable_if_t::value, O>; + } // namespace Slic3r #endif