1 #ifndef SLA_SUPPORTTREE_HPP 2 #define SLA_SUPPORTTREE_HPP 3 4 #include <vector> 5 #include <memory> 6 #include <Eigen/Geometry> 7 8 #include <libslic3r/SLA/Pad.hpp> 9 #include <libslic3r/SLA/IndexedMesh.hpp> 10 #include <libslic3r/SLA/SupportPoint.hpp> 11 #include <libslic3r/SLA/JobController.hpp> 12 13 namespace Slic3r { 14 15 class TriangleMesh; 16 class Model; 17 class ModelInstance; 18 class ModelObject; 19 class Polygon; 20 class ExPolygon; 21 22 using Polygons = std::vector<Polygon>; 23 using ExPolygons = std::vector<ExPolygon>; 24 25 namespace sla { 26 27 enum class PillarConnectionMode 28 { 29 zigzag, 30 cross, 31 dynamic 32 }; 33 34 struct SupportTreeConfig 35 { 36 bool enabled = true; 37 38 // Radius in mm of the pointing side of the head. 39 double head_front_radius_mm = 0.2; 40 41 // How much the pinhead has to penetrate the model surface 42 double head_penetration_mm = 0.5; 43 44 // Radius of the back side of the 3d arrow. 45 double head_back_radius_mm = 0.5; 46 47 double head_fallback_radius_mm = 0.25; 48 49 // Width in mm from the back sphere center to the front sphere center. 50 double head_width_mm = 1.0; 51 52 // How to connect pillars 53 PillarConnectionMode pillar_connection_mode = PillarConnectionMode::dynamic; 54 55 // Only generate pillars that can be routed to ground 56 bool ground_facing_only = false; 57 58 // TODO: unimplemented at the moment. This coefficient will have an impact 59 // when bridges and pillars are merged. The resulting pillar should be a bit 60 // thicker than the ones merging into it. How much thicker? I don't know 61 // but it will be derived from this value. 62 double pillar_widening_factor = 0.5; 63 64 // Radius in mm of the pillar base. 65 double base_radius_mm = 2.0; 66 67 // The height of the pillar base cone in mm. 68 double base_height_mm = 1.0; 69 70 // The default angle for connecting support sticks and junctions. 71 double bridge_slope = M_PI/4; 72 73 // The max length of a bridge in mm 74 double max_bridge_length_mm = 10.0; 75 76 // The max distance of a pillar to pillar link. 77 double max_pillar_link_distance_mm = 10.0; 78 79 // The elevation in Z direction upwards. This is the space between the pad 80 // and the model object's bounding box bottom. 81 double object_elevation_mm = 10; 82 83 // The shortest distance between a pillar base perimeter from the model 84 // body. This is only useful when elevation is set to zero. 85 double pillar_base_safety_distance_mm = 0.5; 86 87 unsigned max_bridges_on_pillar = 3; 88 head_fullwidthSlic3r::sla::SupportTreeConfig89 double head_fullwidth() const { 90 return 2 * head_front_radius_mm + head_width_mm + 91 2 * head_back_radius_mm - head_penetration_mm; 92 } 93 94 // ///////////////////////////////////////////////////////////////////////// 95 // Compile time configuration values (candidates for runtime) 96 // ///////////////////////////////////////////////////////////////////////// 97 98 // The max Z angle for a normal at which it will get completely ignored. 99 static const double constexpr normal_cutoff_angle = 150.0 * M_PI / 180.0; 100 101 // The shortest distance of any support structure from the model surface 102 static const double constexpr safety_distance_mm = 0.5; 103 104 static const double constexpr max_solo_pillar_height_mm = 15.0; 105 static const double constexpr max_dual_pillar_height_mm = 35.0; 106 static const double constexpr optimizer_rel_score_diff = 1e-6; 107 static const unsigned constexpr optimizer_max_iterations = 1000; 108 static const unsigned constexpr pillar_cascade_neighbors = 3; 109 110 }; 111 112 // TODO: Part of future refactor 113 //class SupportConfig { 114 // std::optional<SupportTreeConfig> tree_cfg {std::in_place_t{}}; // fill up 115 // std::optional<PadConfig> pad_cfg; 116 //}; 117 118 enum class MeshType { Support, Pad }; 119 120 struct SupportableMesh 121 { 122 IndexedMesh emesh; 123 SupportPoints pts; 124 SupportTreeConfig cfg; 125 PadConfig pad_cfg; 126 SupportableMeshSlic3r::sla::SupportableMesh127 explicit SupportableMesh(const TriangleMesh & trmsh, 128 const SupportPoints &sp, 129 const SupportTreeConfig &c) 130 : emesh{trmsh}, pts{sp}, cfg{c} 131 {} 132 SupportableMeshSlic3r::sla::SupportableMesh133 explicit SupportableMesh(const IndexedMesh &em, 134 const SupportPoints &sp, 135 const SupportTreeConfig &c) 136 : emesh{em}, pts{sp}, cfg{c} 137 {} 138 }; 139 140 /// The class containing mesh data for the generated supports. 141 class SupportTree 142 { 143 JobController m_ctl; 144 public: 145 using UPtr = std::unique_ptr<SupportTree>; 146 147 static UPtr create(const SupportableMesh &input, 148 const JobController &ctl = {}); 149 150 virtual ~SupportTree() = default; 151 152 virtual const TriangleMesh &retrieve_mesh(MeshType meshtype) const = 0; 153 154 /// Adding the "pad" under the supports. 155 /// modelbase will be used according to the embed_object flag in PoolConfig. 156 /// If set, the plate will be interpreted as the model's intrinsic pad. 157 /// Otherwise, the modelbase will be unified with the base plate calculated 158 /// from the supports. 159 virtual const TriangleMesh &add_pad(const ExPolygons &modelbase, 160 const PadConfig & pcfg) = 0; 161 162 virtual void remove_pad() = 0; 163 164 std::vector<ExPolygons> slice(const std::vector<float> &, 165 float closing_radius) const; 166 167 void retrieve_full_mesh(TriangleMesh &outmesh) const; 168 ctl() const169 const JobController &ctl() const { return m_ctl; } 170 }; 171 172 } 173 174 } 175 176 #endif // SLASUPPORTTREE_HPP 177