// This is brl/bbas/bmsh3d/bmsh3d_face.h //--------------------------------------------------------------------- #ifndef bmsh3d_face_h_ #define bmsh3d_face_h_ //: // \file // \brief Basic 3d face on a mesh // // \author // MingChing Chang April 22, 2005 // // \verbatim // Modifications // // \endverbatim // //------------------------------------------------------------------------- #include #include #include #ifdef _MSC_VER # include #endif #include #include #include #include #include #include "bmsh3d_utils.h" #include "bmsh3d_vertex.h" class bmsh3d_edge; //Color code to visualize several mesh objects. typedef enum { BOGUS_TRIFACE = 0, TRIFACE_111 = 1, TRIFACE_112 = 2, TRIFACE_113P = 3, TRIFACE_122 = 4, TRIFACE_123P = 5, TRIFACE_13P3P = 6, TRIFACE_222 = 7, TRIFACE_223P = 8, TRIFACE_23P3P = 9, TRIFACE_3P3P3P = 10, TRIFACE_E4P = 11, } TRIFACE_TYPE; class bmsh3d_mesh; class bmsh3d_face : public vispt_elm { protected: //: Pointer to the IFS vertices of this face. std::vector vertices_; bmsh3d_halfedge* halfedge_; int id_; //: // This variable is used for // - i_visited_ flag for mesh traversal. // - a flag in gdt propagation. // - storing the sheet id. int i_value_; public: //###### Constructor/Destructor ###### bmsh3d_face() { halfedge_ = nullptr; i_value_ = 0; id_ = -1; } bmsh3d_face(bmsh3d_halfedge* he) { halfedge_ = he; i_value_ = 0; id_ = -1; } bmsh3d_face(const int id) { halfedge_ = nullptr; id_ = id; i_value_ = 0; } ~bmsh3d_face() override { vertices_.clear(); // make sure that all halfedges are deleted before the destructor. // You should use bmsh3d_mesh::delete_face to delete a face. assert (halfedge_ == nullptr); } //###### Data access functions ###### const bmsh3d_vertex* vertices(unsigned int i) const { return vertices_[i]; } bmsh3d_vertex* vertices(unsigned int i) { return vertices_[i]; } const std::vector& vertices() const { return vertices_; } std::vector& vertices() { return vertices_; } bmsh3d_halfedge* halfedge() const { return halfedge_; } bmsh3d_halfedge* & halfedge() { return halfedge_; } void set_halfedge(bmsh3d_halfedge* he) { halfedge_ = he; } int id() const { return id_; } void set_id(int id) { id_ = id; } //: if i_value_ less than i_traverse_flag, it's not visited bool is_visited(int traverse_value) const { return i_value_ >= traverse_value; } void set_i_visited(int traverse_value) { i_value_ = traverse_value; } //: just use the i_value_ as a boolean flag bool b_visited() const { return i_value_ != 0; } void set_visited(bool b) { i_value_ = b ? 1 : 0; } int sid() const { return i_value_; } void set_sid(int sid) { i_value_ = sid; } //###### Connectivity Query via Halfedges ###### void get_incident_HEs(std::vector& incident_HEs) const; void get_incident_Es(std::vector& incident_Es) const; unsigned int n_incident_Es() const; bool is_E_incident(const bmsh3d_edge* inputE) const; bmsh3d_halfedge* find_bnd_HE() const; bool is_V_incident_via_HE(const bmsh3d_vertex* inputV) const; bmsh3d_vertex* get_next_V_via_HE(const bmsh3d_vertex* inputV) const; //: Given a vertex V and an edge of this face incident to V, find the other edge of this face incident to V. bmsh3d_edge* find_other_E(const bmsh3d_vertex* inputV, const bmsh3d_edge* inputE) const; //: Given a vertex V and a halfedge of this face incident to V, find the other halfedge of this face incident to V. bmsh3d_halfedge* find_other_HE(const bmsh3d_vertex* inputV, const bmsh3d_halfedge* inputHE) const; //: Given a vertex V and an edge of this face incident to V, find the next edge (following the circular halfedge list) of this face incident to V. bmsh3d_edge* find_next_E(const bmsh3d_vertex* inputV, const bmsh3d_edge* inputE) const; //: Given a vertex V and a halfedge of this face incident to V, find the next halfedge (following the circular halfedge list) of this face incident to V. bmsh3d_halfedge* find_next_HE(const bmsh3d_vertex* inputV, const bmsh3d_halfedge* inputHE) const; double angle_at_V(const bmsh3d_vertex* inputV) const; int n_incident_Vs_in_set(std::set& vertices) const; bool all_Vs_incident(std::vector& vertices) const; void get_ordered_Vs(std::vector& vertices) const; void _get_ordered_Vs_MHE(std::vector& vertices) const; void _get_ordered_Vs_IFS(std::vector& vertices) const; void get_ordered_V_ids(std::vector& vids) const; void _get_ordered_V_ids_MHE(std::vector& vids) const; void _get_ordered_V_ids_IFS(std::vector& vids) const; //###### Handle local list of incident vertices ###### void _ifs_add_vertex(bmsh3d_vertex* V) { vertices_.push_back(V); } void _ifs_clear_vertices() { vertices_.clear(); } bmsh3d_vertex* _ifs_prev_V(bmsh3d_vertex* inputV) const { if (vertices_[0] == inputV) return vertices_[vertices_.size()-1]; for (unsigned int i=1; iset_vid(V->id()); } } //Test if the face's IFS structure is correct (repeated or wrong Vids). bool _is_ifs_valid(bmsh3d_mesh* M); bool _ifs_inside_box(const vgl_box_3d& box) const; bool _ifs_outside_box(const vgl_box_3d& box) const; //###### Geometry Query Functions ###### bool is_inside_box(const vgl_box_3d& box) const; bool is_outside_box(const vgl_box_3d& box) const; vgl_point_3d compute_center_pt() const; vgl_point_3d compute_center_pt(const std::vector& vertices) const; vgl_vector_3d compute_normal(); //###### Connectivity Modification Functions ###### //: Connect a halfedge to this mesh face. void _connect_HE_to_end(bmsh3d_halfedge* inputHE); //: Remove the input halfedge from the face's halfedge list. bool _remove_HE(bmsh3d_halfedge* inputHE); //: Create a halfedge and connect a mesh face and an edge. void connect_E_to_end(bmsh3d_edge* E); //: Disconnect a face and an edge(delete the halfedge). void disconnect_E(bmsh3d_halfedge* HE); //: Sort the incident halfedges to form a circular list bool _sort_HEs_circular(); //: disconnect all associated halfedges from their edges and delete them. virtual void _discon_all_incident_Es(); //: reverse the orientation of chain of halfedges of this face. void _reverse_HE_chain(); void set_orientation(bmsh3d_halfedge* new_start_he, bmsh3d_vertex* new_next_v); //###### Other functions ###### void getInfo(std::ostringstream& ostrm) override; //###### For triangular face only ###### TRIFACE_TYPE tri_get_topo_type() const; std::string tri_get_topo_string() const; //###### For the face of a 2-manifold triangular mesh only ###### // these functions start with tag m2t (manifold-2-triangle) bmsh3d_edge* m2t_edge_against_vertex(bmsh3d_vertex* input_vertex); bmsh3d_halfedge* m2t_halfedge_against_vertex(bmsh3d_vertex* input_vertex); //: given input_face, find the neighboring face against the input_vertex bmsh3d_face* m2t_nbr_face_against_vertex(bmsh3d_vertex* input_vertex); bmsh3d_face* m2t_nbr_face_sharing_edge(bmsh3d_vertex* v1, bmsh3d_vertex* v2); //: given v1, v2, find v3 bmsh3d_vertex* t_3rd_vertex(const bmsh3d_vertex* V1, const bmsh3d_vertex* V2) const; bmsh3d_vertex* t_vertex_against_edge(const bmsh3d_edge* inputE) const; }; //###### Additional Functions ###### bmsh3d_halfedge* _find_prev_in_HE_chain(const bmsh3d_halfedge* inputHE); //: disconnect all associated halfedges from their edges from the given he_head. void _delete_HE_chain(bmsh3d_halfedge* & he_head); // Return: the set of incident edges that get disconnected. // Also set the he_head to be NULL after calling it. void _delete_HE_chain(bmsh3d_halfedge* & he_head, std::vector& incident_edge_list); //: Given the face, current halfedge, and current eV, find the next halfedge given in the vector<>. bmsh3d_halfedge* _find_next_halfedge(bmsh3d_halfedge* HE, bmsh3d_vertex* eV, std::vector& inc_hes); //: Assume the mesh face is planar and compute a 2D planar coordinate for it. void get_2d_coord(const std::vector& vertices, vgl_vector_3d& N, vgl_vector_3d& AX, vgl_vector_3d& AY); //: Return ordered set of vertices in 2D (x,y) coord. void get_2d_polygon(const std::vector& vertices, std::vector& xs, std::vector& ys); //: Return the projected point in the local 2D (x,y) coord. vgl_point_2d get_2d_proj_pt(vgl_point_3d P, const vgl_point_3d& A, const vgl_vector_3d& AX, const vgl_vector_3d& AY); vgl_point_3d compute_cen(const std::vector& vertices); vgl_vector_3d compute_normal_ifs(const std::vector& vertices); //: Compute face normal using the given edge and starting node. vgl_vector_3d compute_normal(const vgl_point_3d& C, const bmsh3d_edge* E, const bmsh3d_vertex* Es); //: Return true if vertices is a polygon or obtuse triangle. bool is_tri_non_acute(const std::vector& vertices); bool is_F_extraneous(bmsh3d_face* F); bmsh3d_face* get_F_sharing_Es(bmsh3d_edge* E1, bmsh3d_edge* E2); //###### For the face of a 2-manifold triangular mesh only ###### inline void m2t_compute_tri_angles(const double& c, const double& l, const double& r, double& angle_cl, double& angle_cr, double& angle_lr) { angle_cl = std::acos( (c*c + l*l - r*r)/(c*l*2) ); angle_cr = std::acos( (c*c + r*r - l*l)/(c*r*2) ); angle_lr = std::acos( (l*l + r*r - c*c)/(l*r*2) ); } inline void m2t_compute_angles_cl_cr(const double& c, const double& l, const double& r, double& angle_cl, double& angle_cr) { angle_cl = std::acos( (c*c + l*l - r*r)/(c*l*2) ); angle_cr = std::acos( (c*c + r*r - l*l)/(c*r*2) ); } inline double m2t_compute_angle_cl(const double& c, const double& l, const double& r) { return std::acos( (c*c + l*l - r*r)/(c*l*2) ); } inline double m2t_compute_angle_cr(const double& c, const double& l, const double& r) { return std::acos( (c*c + r*r - l*l)/(c*r*2) ); } inline double m2t_compute_angle_lr(const double& c, const double& l, const double& r) { return std::acos( (l*l + r*r - c*c)/(l*r*2) ); } #endif