diff options
Diffstat (limited to 'src/libslic3r/SLA/SupportTreeBuilder.hpp')
-rw-r--r-- | src/libslic3r/SLA/SupportTreeBuilder.hpp | 230 |
1 files changed, 91 insertions, 139 deletions
diff --git a/src/libslic3r/SLA/SupportTreeBuilder.hpp b/src/libslic3r/SLA/SupportTreeBuilder.hpp index 90cf417c8..f29263ca3 100644 --- a/src/libslic3r/SLA/SupportTreeBuilder.hpp +++ b/src/libslic3r/SLA/SupportTreeBuilder.hpp @@ -2,7 +2,6 @@ #define SLA_SUPPORTTREEBUILDER_HPP #include <libslic3r/SLA/Concurrency.hpp> -#include <libslic3r/SLA/Common.hpp> #include <libslic3r/SLA/SupportTree.hpp> #include <libslic3r/SLA/Contour3D.hpp> #include <libslic3r/SLA/Pad.hpp> @@ -50,13 +49,6 @@ namespace sla { * nearby pillar. */ -using Coordf = double; -using Portion = std::tuple<double, double>; - -inline Portion make_portion(double a, double b) { - return std::make_tuple(a, b); -} - template<class Vec> double distance(const Vec& p) { return std::sqrt(p.transpose() * p); } @@ -66,33 +58,25 @@ template<class Vec> double distance(const Vec& pp1, const Vec& pp2) { return distance(p); } -Contour3D sphere(double rho, Portion portion = make_portion(0.0, 2.0*PI), - double fa=(2*PI/360)); +const Vec3d DOWN = {0.0, 0.0, -1.0}; -// Down facing cylinder in Z direction with arguments: -// r: radius -// h: Height -// ssteps: how many edges will create the base circle -// sp: starting point -Contour3D cylinder(double r, double h, size_t ssteps = 45, const Vec3d &sp = {0,0,0}); +struct SupportTreeNode +{ + static const constexpr long ID_UNSET = -1; -const constexpr long ID_UNSET = -1; + long id = ID_UNSET; // For identification withing a tree. +}; -struct Head { - Contour3D mesh; - - size_t steps = 45; - Vec3d dir = {0, 0, -1}; - Vec3d tr = {0, 0, 0}; +// A pinhead originating from a support point +struct Head: public SupportTreeNode { + Vec3d dir = DOWN; + Vec3d pos = {0, 0, 0}; double r_back_mm = 1; double r_pin_mm = 0.5; double width_mm = 2; double penetration_mm = 0.5; - - // For identification purposes. This will be used as the index into the - // container holding the head structures. See SLASupportTree::Impl - long id = ID_UNSET; + // If there is a pillar connecting to this head, then the id will be set. long pillar_id = ID_UNSET; @@ -106,31 +90,23 @@ struct Head { double r_small_mm, double length_mm, double penetration, - const Vec3d &direction = {0, 0, -1}, // direction (normal to the dull end) - const Vec3d &offset = {0, 0, 0}, // displacement - const size_t circlesteps = 45); - - void transform() + const Vec3d &direction = DOWN, // direction (normal to the dull end) + const Vec3d &offset = {0, 0, 0} // displacement + ); + + inline double real_width() const { - using Quaternion = Eigen::Quaternion<double>; - - // We rotate the head to the specified direction The head's pointing - // side is facing upwards so this means that it would hold a support - // point with a normal pointing straight down. This is the reason of - // the -1 z coordinate - auto quatern = Quaternion::FromTwoVectors(Vec3d{0, 0, -1}, dir); - - for(auto& p : mesh.points) p = quatern * p + tr; + return 2 * r_pin_mm + width_mm + 2 * r_back_mm ; } - + inline double fullwidth() const { - return 2 * r_pin_mm + width_mm + 2*r_back_mm - penetration_mm; + return real_width() - penetration_mm; } inline Vec3d junction_point() const { - return tr + ( 2 * r_pin_mm + width_mm + r_back_mm - penetration_mm)*dir; + return pos + (fullwidth() - r_back_mm) * dir; } inline double request_pillar_radius(double radius) const @@ -140,31 +116,17 @@ struct Head { } }; -struct Junction { - Contour3D mesh; +// A junction connecting bridges and pillars +struct Junction: public SupportTreeNode { double r = 1; - size_t steps = 45; Vec3d pos; - - long id = ID_UNSET; - - Junction(const Vec3d& tr, double r_mm, size_t stepnum = 45): - r(r_mm), steps(stepnum), pos(tr) - { - mesh = sphere(r_mm, make_portion(0, PI), 2*PI/steps); - for(auto& p : mesh.points) p += tr; - } + + Junction(const Vec3d &tr, double r_mm) : r(r_mm), pos(tr) {} }; -struct Pillar { - Contour3D mesh; - Contour3D base; - double r = 1; - size_t steps = 0; +struct Pillar: public SupportTreeNode { + double height, r; Vec3d endpt; - double height = 0; - - long id = ID_UNSET; // If the pillar connects to a head, this is the id of that head bool starts_from_head = true; // Could start from a junction as well @@ -175,54 +137,52 @@ struct Pillar { // How many pillars are cascaded with this one unsigned links = 0; - - Pillar(const Vec3d& jp, const Vec3d& endp, - double radius = 1, size_t st = 45); - - Pillar(const Junction &junc, const Vec3d &endp) - : Pillar(junc.pos, endp, junc.r, junc.steps) - {} - - Pillar(const Head &head, const Vec3d &endp, double radius = 1) - : Pillar(head.junction_point(), endp, - head.request_pillar_radius(radius), head.steps) - {} - - inline Vec3d startpoint() const + + Pillar(const Vec3d &endp, double h, double radius = 1.): + height{h}, r(radius), endpt(endp), starts_from_head(false) {} + + Vec3d startpoint() const { - return {endpt(X), endpt(Y), endpt(Z) + height}; + return {endpt.x(), endpt.y(), endpt.z() + height}; } - inline const Vec3d& endpoint() const { return endpt; } - - Pillar& add_base(double baseheight = 3, double radius = 2); + const Vec3d& endpoint() const { return endpt; } +}; + +// A base for pillars or bridges that end on the ground +struct Pedestal: public SupportTreeNode { + Vec3d pos; + double height, r_bottom, r_top; + + Pedestal(const Vec3d &p, double h, double rbottom, double rtop) + : pos{p}, height{h}, r_bottom{rbottom}, r_top{rtop} + {} }; +// This is the thing that anchors a pillar or bridge to the model body. +// It is actually a reverse pinhead. +struct Anchor: public Head { using Head::Head; }; + // A Bridge between two pillars (with junction endpoints) -struct Bridge { - Contour3D mesh; +struct Bridge: public SupportTreeNode { double r = 0.8; - long id = ID_UNSET; Vec3d startp = Vec3d::Zero(), endp = Vec3d::Zero(); Bridge(const Vec3d &j1, const Vec3d &j2, - double r_mm = 0.8, - size_t steps = 45); + double r_mm = 0.8): r{r_mm}, startp{j1}, endp{j2} + {} + + double get_length() const { return (endp - startp).norm(); } + Vec3d get_dir() const { return (endp - startp).normalized(); } }; -// A bridge that spans from model surface to model surface with small connecting -// edges on the endpoints. Used for headless support points. -struct CompactBridge { - Contour3D mesh; - long id = ID_UNSET; - - CompactBridge(const Vec3d& sp, - const Vec3d& ep, - const Vec3d& n, - double r, - bool endball = true, - size_t steps = 45); +struct DiffBridge: public Bridge { + double end_r; + + DiffBridge(const Vec3d &p_s, const Vec3d &p_e, double r_s, double r_e) + : Bridge{p_s, p_e, r_s}, end_r{r_e} + {} }; // A wrapper struct around the pad @@ -258,13 +218,16 @@ struct Pad { // merged mesh. It can be retrieved using a dedicated method (pad()) class SupportTreeBuilder: public SupportTree { // For heads it is beneficial to use the same IDs as for the support points. - std::vector<Head> m_heads; - std::vector<size_t> m_head_indices; - std::vector<Pillar> m_pillars; - std::vector<Junction> m_junctions; - std::vector<Bridge> m_bridges; - std::vector<Bridge> m_crossbridges; - std::vector<CompactBridge> m_compact_bridges; + std::vector<Head> m_heads; + std::vector<size_t> m_head_indices; + std::vector<Pillar> m_pillars; + std::vector<Junction> m_junctions; + std::vector<Bridge> m_bridges; + std::vector<Bridge> m_crossbridges; + std::vector<DiffBridge> m_diffbridges; + std::vector<Pedestal> m_pedestals; + std::vector<Anchor> m_anchors; + Pad m_pad; using Mutex = ccr::SpinningMutex; @@ -274,8 +237,8 @@ class SupportTreeBuilder: public SupportTree { mutable bool m_meshcache_valid = false; mutable double m_model_height = 0; // the full height of the model - template<class...Args> - const Bridge& _add_bridge(std::vector<Bridge> &br, Args&&... args) + template<class BridgeT, class...Args> + const BridgeT& _add_bridge(std::vector<BridgeT> &br, Args&&... args) { std::lock_guard<Mutex> lk(m_mutex); br.emplace_back(std::forward<Args>(args)...); @@ -306,7 +269,7 @@ public: return m_heads.back(); } - template<class...Args> long add_pillar(long headid, Args&&... args) + template<class...Args> long add_pillar(long headid, double length) { std::lock_guard<Mutex> lk(m_mutex); if (m_pillars.capacity() < m_heads.size()) @@ -315,7 +278,9 @@ public: assert(headid >= 0 && size_t(headid) < m_head_indices.size()); Head &head = m_heads[m_head_indices[size_t(headid)]]; - m_pillars.emplace_back(head, std::forward<Args>(args)...); + Vec3d hjp = head.junction_point() - Vec3d{0, 0, length}; + m_pillars.emplace_back(hjp, length, head.r_back_mm); + Pillar& pillar = m_pillars.back(); pillar.id = long(m_pillars.size() - 1); head.pillar_id = pillar.id; @@ -326,11 +291,15 @@ public: return pillar.id; } - void add_pillar_base(long pid, double baseheight = 3, double radius = 2) + void add_pillar_base(long pid, double baseheight = 3, double radius = 2); + + template<class...Args> const Anchor& add_anchor(Args&&...args) { std::lock_guard<Mutex> lk(m_mutex); - assert(pid >= 0 && size_t(pid) < m_pillars.size()); - m_pillars[size_t(pid)].add_base(baseheight, radius); + m_anchors.emplace_back(std::forward<Args>(args)...); + m_anchors.back().id = long(m_junctions.size() - 1); + m_meshcache_valid = false; + return m_anchors.back(); } void increment_bridges(const Pillar& pillar) @@ -371,17 +340,6 @@ public: return pillar.id; } - const Pillar& head_pillar(unsigned headid) const - { - std::lock_guard<Mutex> lk(m_mutex); - assert(headid < m_head_indices.size()); - - const Head& h = m_heads[m_head_indices[headid]]; - assert(h.pillar_id >= 0 && h.pillar_id < long(m_pillars.size())); - - return m_pillars[size_t(h.pillar_id)]; - } - template<class...Args> const Junction& add_junction(Args&&... args) { std::lock_guard<Mutex> lk(m_mutex); @@ -391,18 +349,18 @@ public: return m_junctions.back(); } - const Bridge& add_bridge(const Vec3d &s, const Vec3d &e, double r, size_t n = 45) + const Bridge& add_bridge(const Vec3d &s, const Vec3d &e, double r) { - return _add_bridge(m_bridges, s, e, r, n); + return _add_bridge(m_bridges, s, e, r); } - const Bridge& add_bridge(long headid, const Vec3d &endp, size_t s = 45) + const Bridge& add_bridge(long headid, const Vec3d &endp) { std::lock_guard<Mutex> lk(m_mutex); assert(headid >= 0 && size_t(headid) < m_head_indices.size()); Head &h = m_heads[m_head_indices[size_t(headid)]]; - m_bridges.emplace_back(h.junction_point(), endp, h.r_back_mm, s); + m_bridges.emplace_back(h.junction_point(), endp, h.r_back_mm); m_bridges.back().id = long(m_bridges.size() - 1); h.bridge_id = m_bridges.back().id; @@ -414,14 +372,10 @@ public: { return _add_bridge(m_crossbridges, std::forward<Args>(args)...); } - - template<class...Args> const CompactBridge& add_compact_bridge(Args&&...args) + + template<class...Args> const DiffBridge& add_diffbridge(Args&&... args) { - std::lock_guard<Mutex> lk(m_mutex); - m_compact_bridges.emplace_back(std::forward<Args>(args)...); - m_compact_bridges.back().id = long(m_compact_bridges.size() - 1); - m_meshcache_valid = false; - return m_compact_bridges.back(); + return _add_bridge(m_diffbridges, std::forward<Args>(args)...); } Head &head(unsigned id) @@ -439,7 +393,7 @@ public: } inline const std::vector<Pillar> &pillars() const { return m_pillars; } - inline const std::vector<Head> &heads() const { return m_heads; } + inline const std::vector<Head> &heads() const { return m_heads; } inline const std::vector<Bridge> &bridges() const { return m_bridges; } inline const std::vector<Bridge> &crossbridges() const { return m_crossbridges; } @@ -464,7 +418,7 @@ public: const Pad& pad() const { return m_pad; } // WITHOUT THE PAD!!! - const TriangleMesh &merged_mesh() const; + const TriangleMesh &merged_mesh(size_t steps = 45) const; // WITH THE PAD double full_height() const; @@ -488,8 +442,6 @@ public: virtual const TriangleMesh &retrieve_mesh( MeshType meshtype = MeshType::Support) const override; - - bool build(const SupportableMesh &supportable_mesh); }; }} // namespace Slic3r::sla |