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