BranchingTree.hpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. #ifndef SUPPORTTREEBRANCHING_HPP
  2. #define SUPPORTTREEBRANCHING_HPP
  3. // For indexed_triangle_set
  4. #include <admesh/stl.h>
  5. #include "libslic3r/ExPolygon.hpp"
  6. namespace Slic3r { namespace branchingtree {
  7. // Branching tree input parameters. This is an in-line fillable structure with
  8. // setters returning self references.
  9. class Properties
  10. {
  11. double m_max_slope = PI / 4.;
  12. double m_ground_level = 0.;
  13. double m_sampling_radius = .5;
  14. double m_max_branch_len = 10.;
  15. ExPolygons m_bed_shape;
  16. public:
  17. // Maximum slope for bridges of the tree
  18. Properties &max_slope(double val) noexcept
  19. {
  20. m_max_slope = val;
  21. return *this;
  22. }
  23. // Z level of the ground
  24. Properties &ground_level(double val) noexcept
  25. {
  26. m_ground_level = val;
  27. return *this;
  28. }
  29. // How far should sample points be in the mesh and the ground
  30. Properties &sampling_radius(double val) noexcept
  31. {
  32. m_sampling_radius = val;
  33. return *this;
  34. }
  35. // Shape of the print bed (ground)
  36. Properties &bed_shape(ExPolygons bed) noexcept
  37. {
  38. m_bed_shape = std::move(bed);
  39. return *this;
  40. }
  41. Properties &max_branch_length(double val) noexcept
  42. {
  43. m_max_branch_len = val;
  44. return *this;
  45. }
  46. double max_slope() const noexcept { return m_max_slope; }
  47. double ground_level() const noexcept { return m_ground_level; }
  48. double sampling_radius() const noexcept { return m_sampling_radius; }
  49. double max_branch_length() const noexcept { return m_max_branch_len; }
  50. const ExPolygons &bed_shape() const noexcept { return m_bed_shape; }
  51. };
  52. // A junction of the branching tree with position and radius.
  53. struct Node
  54. {
  55. static constexpr int ID_NONE = -1;
  56. int id = ID_NONE, left = ID_NONE, right = ID_NONE;
  57. Vec3f pos;
  58. float Rmin = 0.f;
  59. // Tracking the weight of each junction, which is essentially the sum of
  60. // the lenghts of all branches emanating from this junction.
  61. float weight = 0.f;
  62. Node(const Vec3f &p, float r_min = .0f) : pos{p}, Rmin{r_min}, weight{0.f}
  63. {}
  64. };
  65. inline bool is_occupied(const Node &n)
  66. {
  67. return n.left != Node::ID_NONE && n.right != Node::ID_NONE;
  68. }
  69. // An output interface for the branching tree generator function. Consider each
  70. // method as a callback and implement the actions that need to be done.
  71. class Builder
  72. {
  73. public:
  74. virtual ~Builder() = default;
  75. // A simple bridge from junction to junction.
  76. virtual bool add_bridge(const Node &from, const Node &to) = 0;
  77. // An Y shaped structure with two starting points and a merge point below
  78. // them. The angles will respect the max_slope setting.
  79. virtual bool add_merger(const Node &node,
  80. const Node &closest,
  81. const Node &merge_node) = 0;
  82. // Add an anchor bridge to the ground (print bed)
  83. virtual bool add_ground_bridge(const Node &from,
  84. const Node &to) = 0;
  85. // Add an anchor bridge to the model body
  86. virtual bool add_mesh_bridge(const Node &from, const Node &to) = 0;
  87. virtual std::optional<Vec3f> suggest_avoidance(const Node &from,
  88. float max_bridge_len) const
  89. {
  90. return {};
  91. }
  92. // Report nodes that can not be routed to an endpoint (model or ground)
  93. virtual void report_unroutable(const Node &j) = 0;
  94. // If returns false, the tree building process shall stop
  95. virtual bool is_valid() const { return true; }
  96. };
  97. // Build the actual tree.
  98. // its: The input mesh
  99. // support_leafs: The input support points
  100. // builder: The output interface, describes how to build the tree
  101. // properties: Parameters of the tree
  102. //
  103. // Notes:
  104. // The original algorithm implicitly ensures that the generated tree avoids
  105. // the model body. This implementation uses point sampling of the mesh thus an
  106. // explicit check is needed if the part of the tree being inserted properly
  107. // avoids the model. This can be done in the builder implementation. Each
  108. // method can return a boolean indicating whether the given branch can or
  109. // cannot be inserted. If a particular path is unavailable, the algorithm
  110. // will try a few other paths as well. If all of them fail, one of the
  111. // report_unroutable_* methods will be called as a last resort.
  112. void build_tree(const indexed_triangle_set &its,
  113. const std::vector<Node> &support_leafs,
  114. Builder &builder,
  115. const Properties &properties = {});
  116. inline void build_tree(const indexed_triangle_set &its,
  117. const std::vector<Node> &support_leafs,
  118. Builder &&builder,
  119. const Properties &properties = {})
  120. {
  121. build_tree(its, support_leafs, builder, properties);
  122. }
  123. // Helper function to derive a bed polygon only from the model bounding box.
  124. ExPolygon make_bed_poly(const indexed_triangle_set &its);
  125. }} // namespace Slic3r::branchingtree
  126. #endif // SUPPORTTREEBRANCHING_HPP