1 #ifndef SLA_INDEXEDMESH_H
2 #define SLA_INDEXEDMESH_H
3 
4 #include <memory>
5 #include <vector>
6 
7 #include <libslic3r/Point.hpp>
8 
9 // There is an implementation of a hole-aware raycaster that was eventually
10 // not used in production version. It is now hidden under following define
11 // for possible future use.
12 // #define SLIC3R_HOLE_RAYCASTER
13 
14 #ifdef SLIC3R_HOLE_RAYCASTER
15   #include "libslic3r/SLA/Hollowing.hpp"
16 #endif
17 
18 namespace Slic3r {
19 
20 class TriangleMesh;
21 
22 namespace sla {
23 
24 using PointSet = Eigen::MatrixXd;
25 
26 /// An index-triangle structure for libIGL functions. Also serves as an
27 /// alternative (raw) input format for the SLASupportTree.
28 //  Implemented in libslic3r/SLA/Common.cpp
29 class IndexedMesh {
30     class AABBImpl;
31 
32     const TriangleMesh* m_tm;
33     double m_ground_level = 0, m_gnd_offset = 0;
34 
35     std::unique_ptr<AABBImpl> m_aabb;
36 
37 #ifdef SLIC3R_HOLE_RAYCASTER
38     // This holds a copy of holes in the mesh. Initialized externally
39     // by load_mesh setter.
40     std::vector<DrainHole> m_holes;
41 #endif
42 
43 public:
44 
45     explicit IndexedMesh(const TriangleMesh&);
46 
47     IndexedMesh(const IndexedMesh& other);
48     IndexedMesh& operator=(const IndexedMesh&);
49 
50     IndexedMesh(IndexedMesh &&other);
51     IndexedMesh& operator=(IndexedMesh &&other);
52 
53     ~IndexedMesh();
54 
ground_level() const55     inline double ground_level() const { return m_ground_level + m_gnd_offset; }
ground_level_offset(double o)56     inline void ground_level_offset(double o) { m_gnd_offset = o; }
ground_level_offset() const57     inline double ground_level_offset() const { return m_gnd_offset; }
58 
59     const std::vector<Vec3f>& vertices() const;
60     const std::vector<Vec3i>& indices()  const;
61     const Vec3f& vertices(size_t idx) const;
62     const Vec3i& indices(size_t idx) const;
63 
64     // Result of a raycast
65     class hit_result {
66         // m_t holds a distance from m_source to the intersection.
67         double m_t = infty();
68         int m_face_id = -1;
69         const IndexedMesh *m_mesh = nullptr;
70         Vec3d m_dir;
71         Vec3d m_source;
72         Vec3d m_normal;
73         friend class IndexedMesh;
74 
75         // A valid object of this class can only be obtained from
76         // IndexedMesh::query_ray_hit method.
hit_result(const IndexedMesh & em)77         explicit inline hit_result(const IndexedMesh& em): m_mesh(&em) {}
78     public:
79         // This denotes no hit on the mesh.
infty()80         static inline constexpr double infty() { return std::numeric_limits<double>::infinity(); }
81 
hit_result(double val=infty ())82         explicit inline hit_result(double val = infty()) : m_t(val) {}
83 
distance() const84         inline double distance() const { return m_t; }
direction() const85         inline const Vec3d& direction() const { return m_dir; }
source() const86         inline const Vec3d& source() const { return m_source; }
position() const87         inline Vec3d position() const { return m_source + m_dir * m_t; }
face() const88         inline int face() const { return m_face_id; }
is_valid() const89         inline bool is_valid() const { return m_mesh != nullptr; }
is_hit() const90         inline bool is_hit() const { return m_face_id >= 0 && !std::isinf(m_t); }
91 
normal() const92         inline const Vec3d& normal() const {
93             assert(is_valid());
94             return m_normal;
95         }
96 
is_inside() const97         inline bool is_inside() const {
98             return is_hit() && normal().dot(m_dir) > 0;
99         }
100     };
101 
102 #ifdef SLIC3R_HOLE_RAYCASTER
103     // Inform the object about location of holes
104     // creates internal copy of the vector
load_holes(const std::vector<DrainHole> & holes)105     void load_holes(const std::vector<DrainHole>& holes) {
106         m_holes = holes;
107     }
108 
109     // Iterates over hits and holes and returns the true hit, possibly
110     // on the inside of a hole.
111     // This function is currently not used anywhere, it was written when the
112     // holes were subtracted on slices, that is, before we started using CGAL
113     // to actually cut the holes into the mesh.
114     hit_result filter_hits(const std::vector<IndexedMesh::hit_result>& obj_hits) const;
115 #endif
116 
117     // Casting a ray on the mesh, returns the distance where the hit occures.
118     hit_result query_ray_hit(const Vec3d &s, const Vec3d &dir) const;
119 
120     // Casts a ray on the mesh and returns all hits
121     std::vector<hit_result> query_ray_hits(const Vec3d &s, const Vec3d &dir) const;
122 
123     double squared_distance(const Vec3d& p, int& i, Vec3d& c) const;
squared_distance(const Vec3d & p) const124     inline double squared_distance(const Vec3d &p) const
125     {
126         int   i;
127         Vec3d c;
128         return squared_distance(p, i, c);
129     }
130 
131     Vec3d normal_by_face_id(int face_id) const;
132 
get_triangle_mesh() const133     const TriangleMesh * get_triangle_mesh() const { return m_tm; }
134 };
135 
136 // Calculate the normals for the selected points (from 'points' set) on the
137 // mesh. This will call squared distance for each point.
138 PointSet normals(const PointSet& points,
139     const IndexedMesh& convert_mesh,
140     double eps = 0.05,  // min distance from edges
__anon4716b31f0102()141     std::function<void()> throw_on_cancel = [](){},
__anon4716b31f0202()142     const std::vector<unsigned>& selected_points = {});
143 
144 }} // namespace Slic3r::sla
145 
146 #endif // INDEXEDMESH_H
147