1 // This is brl/bbas/bmsh3d/bmsh3d_edge.h
2 #ifndef bmsh3d_edge_h_
3 #define bmsh3d_edge_h_
4 //---------------------------------------------------------------------
5 //:
6 // \file
7 // \brief Basic 3d edge on a mesh
8 //
9 // \author
10 //  MingChing Chang  June 13, 2005
11 //
12 // \verbatim
13 //  Modifications
14 //   <none>
15 // \endverbatim
16 //
17 //-------------------------------------------------------------------------
18 
19 #include <vector>
20 #include <iostream>
21 #include <sstream>
22 #include "bmsh3d_halfedge.h"
23 #include "bmsh3d_utils.h"
24 
25 #ifdef _MSC_VER
26 #  include <vcl_msvc_warnings.h>
27 #endif
28 #include <vgl/vgl_fwd.h>
29 
30 //#######################################################
31 //     The Mesh Library Data Structure
32 //     (Combined IndexedFaceSet and Half-Edge.
33 //      Use depend on what you need.)
34 //     The actual edge element that's under both-way pointer to the half-edges.
35 //     For a manifold mesh:
36 //          - two pointers to both half-edges.
37 //     For a non-manifold mesh:
38 //          - a vector of pointers the other half-edges.
39 //#######################################################
40 
41 class bmsh3d_face;
42 
43 //: A manifold edge element (or link) has pointer to one of the half edges
44 class bmsh3d_edge : public vispt_elm
45 {
46  protected:
47   //: pointer to one of the halfedges associated with it.
48   //  The halfedges form a circular list.
49   //  Note that we don't need to use type 'he_halfedge' here!
50   bmsh3d_halfedge* halfedge_;
51 
52   //: the starting and ending vertices
53   bmsh3d_vertex*   vertices_[2];
54 
55   //: all bmsh3d_vertex, bmsh3d_edge, bmsh3d_face have an id
56   int               id_;
57 
58   //: The visited flag for mesh hypergraph traversal.
59   //    - b_visited_:
60   mutable int      i_visited_;
61 
62  public:
63   //###### Constructor/Destructor ######
bmsh3d_edge(bmsh3d_vertex * sv,bmsh3d_vertex * ev,int id)64   bmsh3d_edge(bmsh3d_vertex* sv, bmsh3d_vertex* ev, int id)
65   {
66     id_           = id;
67     halfedge_     = nullptr;
68     vertices_[0]  = sv;
69     vertices_[1]  = ev;
70     i_visited_    = 0;
71   }
72   ~bmsh3d_edge() override;
73   bmsh3d_edge* clone();
74 
75   //###### Data access functions ######
76 
id()77   int id() const { return id_; }
set_id(int id)78   void set_id(int id) { id_ = id; }
halfedge()79   bmsh3d_halfedge* halfedge() const { return halfedge_; }
set_halfedge(bmsh3d_halfedge * halfedge)80   void set_halfedge(bmsh3d_halfedge*  halfedge) { halfedge_ = halfedge; }
b_visited()81   bool b_visited() const { return i_visited_ != 0; }
set_visited(bool b)82   void set_visited(bool b) const { i_visited_ = b ? 1 : 0; } /* mutable */
83 
84   //: if i_visited_ less than i_traverse_flag, it's not visited
is_visited(int traverse_value)85   bool is_visited(int traverse_value) const { return i_visited_ >= traverse_value; }
set_i_visited(int traverse_value)86   void set_i_visited(int traverse_value) const { i_visited_ = traverse_value; }
87 
is_valid()88   bool is_valid() const { return i_visited_ != 0; }
set_valid(bool v)89   void set_valid(bool v) const {  i_visited_ = v ? 1 : 0; } /* mutable */
90 
91   //###### Connectivity query functions ######
sV()92   bmsh3d_vertex* sV() const { return vertices_[0]; }
eV()93   bmsh3d_vertex* eV() const { return vertices_[1]; }
vertices(unsigned int i)94   bmsh3d_vertex* vertices(unsigned int i) const { return vertices_[i]; }
set_vertex(unsigned int i,bmsh3d_vertex * V)95   void set_vertex(unsigned int i, bmsh3d_vertex* V) { vertices_[i] = V; }
other_V(const bmsh3d_vertex * V)96   bmsh3d_vertex* other_V(const bmsh3d_vertex* V) const {
97     if (vertices_[0] == V)
98       return vertices_[1];
99 
100     if (vertices_[1] == V)
101       return vertices_[0];
102 
103     return nullptr;
104   }
is_V_incident(const bmsh3d_vertex * V)105   bool is_V_incident(const bmsh3d_vertex* V) const {
106     return vertices_[0] == V || vertices_[1] == V;
107   }
both_Vs_incident(const bmsh3d_vertex * V0,const bmsh3d_vertex * V1)108   bool both_Vs_incident(const bmsh3d_vertex* V0, const bmsh3d_vertex* V1) const {
109     return (vertices_[0] == V0 && vertices_[1] == V1)
110         || (vertices_[0] == V1 && vertices_[1] == V0);
111   }
is_self_loop()112   bool is_self_loop() const { return vertices_[0] == vertices_[1]; }
113 
114   unsigned int n_incident_Fs() const;
115   bool is_F_incident(const bmsh3d_face* F) const;
116   bool is_F_incident(bmsh3d_face* F) const;
117   bmsh3d_halfedge* get_HE_of_F(bmsh3d_face* F) const;
118 
119   void get_incident_Fs(std::vector<bmsh3d_face*>& incident_faces) const;
120 
121   bmsh3d_face* incident_F_given_E(bmsh3d_edge* other_incident_E) const;
122   bmsh3d_face* incident_F_given_V(bmsh3d_vertex* incident_vertex) const;
123 
124   //: Check if E is 2-incident to one sheet.
125   bmsh3d_face* is_2_incident_to_one_S() const;
126   //: Check if E is 3-incident to one sheet.
127   bmsh3d_face* is_3_incident_to_one_S() const;
128 
129   bmsh3d_face* other_2_manifold_F(bmsh3d_face* inputF) const;
130 
131   //: given a tau, return the extrinsic coordinate
132   vgl_point_3d<double> _point_from_tau(const double tau) const;
133 
134   //: mid-point of this link
135   vgl_point_3d<double> mid_pt() const;
136 
137   //: length of this link.
138   double length() const;
139 
140   //###### Connectivity Modification Functions ######
switch_s_e_vertex()141   void switch_s_e_vertex() {
142     bmsh3d_vertex* temp = vertices_[0];
143     vertices_[0] = vertices_[1];
144     vertices_[1] = temp;
145   }
146 
147   void _connect_HE_to_end(bmsh3d_halfedge* inputHE);
148 
149   //: Disconnect one of the halfedge of this edge and fix the circular list of halfedge pairs.
150   void _disconnect_HE(bmsh3d_halfedge* inputHE);
151 
152   //: disconnect all incident faces and return the vector of all such faces.
153   void disconnect_all_Fs(std::vector<bmsh3d_face*>& disconn_faces);
154 
155   //###### For the edge of a 2-manifold triangular mesh only ######
156   bmsh3d_halfedge* m2_other_HE(bmsh3d_halfedge* inputHE);
157   bmsh3d_face* m2_other_face(bmsh3d_face* input_face);
158 
159   //###### Other functions ######
160   void getInfo(std::ostringstream& ostrm) override;
161 };
162 
163 //: Given two consecutive edges, find the common incident vertex.
incident_V_of_Es(const bmsh3d_edge * E0,const bmsh3d_edge * E1)164 inline bmsh3d_vertex* incident_V_of_Es(const bmsh3d_edge* E0, const bmsh3d_edge* E1)
165 {
166   bmsh3d_vertex* V = E0->eV();
167   if (E1->is_V_incident(V))
168     return V;
169   V = E0->sV();
170   if (E1->is_V_incident(V))
171     return V;
172   return nullptr;
173 }
174 
175 //: Return the first found vertex that is incident to both E1 and E2.
Es_sharing_V(const bmsh3d_edge * E1,const bmsh3d_edge * E2)176 inline bmsh3d_vertex* Es_sharing_V(const bmsh3d_edge* E1, const bmsh3d_edge* E2)
177 {
178   if (E1->is_V_incident(E2->sV()))
179     return E2->sV();
180   if (E1->is_V_incident(E2->eV()))
181     return E2->eV();
182   return nullptr;
183 }
184 
185 //: Return the first found vertex that is incident to both E1 and E2.
186 //  Also determine if E1 and E2 are in a loop of two edges.
Es_sharing_V_check(const bmsh3d_edge * E1,const bmsh3d_edge * E2,bool & loop)187 inline bmsh3d_vertex* Es_sharing_V_check(const bmsh3d_edge* E1, const bmsh3d_edge* E2,
188                                          bool& loop)
189 {
190   bmsh3d_vertex* V1 = nullptr;
191   bmsh3d_vertex* V2 = nullptr;
192   loop = false;
193   if (E1->is_V_incident(E2->sV()))
194     V1 = E2->sV();
195   if (E1->is_V_incident(E2->eV()))
196     V2 = E2->eV();
197   if (V1 && V2)
198     loop = true;
199 
200   if (V1)
201     return V1;
202   else if (V2)
203     return V2;
204   else
205     return nullptr;
206 }
207 
same_incident_Vs(const bmsh3d_edge * E1,const bmsh3d_edge * E2)208 inline bool same_incident_Vs(const bmsh3d_edge* E1, const bmsh3d_edge* E2)
209 {
210   if (E1->sV() == E2->sV() && E1->eV() == E2->eV())
211     return true;
212   if (E1->sV() == E2->eV() && E1->eV() == E2->sV())
213     return true;
214   return false;
215 }
216 
217 #endif
218