Subversion Repositories gelsvn

Rev

Rev 26 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
24 jab 1
#include <queue>
2
#include <vector>
3
 
4
#include "triangulate.h"
5
#include "HMesh/VertexCirculator.h"
6
#include "HMesh/FaceCirculator.h"
7
 
8
using namespace std;
9
using namespace CGLA;
10
using namespace HMesh;
11
 
12
namespace HMeshUtil
13
{
14
  void get_candidates(const VertexIter& v,
15
											vector<HalfEdgeIter>& candidates)
16
 
17
 
18
  {
19
    vector<VertexIter> vertices;
20
    vector<HalfEdgeIter> hedges;
21
 
22
    VertexCirculator vc(v);
23
    for(;!vc.end();++vc)
24
      {
25
				vertices.push_back(vc.get_vertex());
26
				hedges.push_back(vc.get_halfedge());
27
      }
28
    int N = vc.no_steps();
29
    vector<VertexIter> vertices_check(vertices);
30
    assert(N==vertices.size());
31
 
32
    for(int i=N-1;i>=0;--i)
33
      {
34
				HalfEdgeIter h = hedges[i]->next;
35
				while(h->vert != vertices[(i+N-1)%N])
36
					{
37
						if(find(vertices_check.begin(),vertices_check.end(), 
38
										h->vert) == vertices_check.end())
39
							candidates.push_back(h);
40
						h = h->next;
41
						assert(h!=v);
42
					}
43
      }
44
  }
45
 
46
  float curv(const Vec3f& p, std::vector<Vec3f>& vec)
47
  {
48
    int N = vec.size();
49
    std::vector<Vec3f> normals;
50
    for(int i=0;i<N;++i)
51
      {
52
 
53
				Vec3f norm = normalize(cross(vec[i]-p, vec[(i+1)%N]-p));
54
				normals.push_back(norm);
55
      }
56
    float alpha = 0;
57
    for(int i=0;i<N;++i)
58
      {
59
				alpha += (vec[i]-p).length()*acos(dot(normals[i],normals[(i+1)%N]));
60
      }
61
    return alpha;
62
  }
63
 
64
  float get_badness(const VertexIter& v, const VertexIter& n)
65
  {
66
    vector<HalfEdgeIter> hedges;
67
 
68
    VertexCirculator vc(v);
69
    for(;!vc.end();++vc)
70
      hedges.push_back(vc.get_halfedge());
71
 
72
    vector<Vec3f> one_ring;
73
    vector<Vec3f> one_ring_n;
74
    int N = vc.no_steps();
75
    for(int i=N-1;i>=0;--i)
76
      {
77
				HalfEdgeIter h = hedges[i];
78
				h = h->next;
79
				while(h->vert != v)
80
					{
81
						one_ring.push_back(h->vert->get_pos());
82
						if(h->vert != n)
83
							one_ring_n.push_back(h->vert->get_pos());
84
						h = h->next;
85
					}
86
      }
87
    return curv(v->get_pos(),one_ring)-curv(v->get_pos(),one_ring_n);
88
  }
89
 
90
 
91
  const CGLA::Vec3f get_normal(const VertexIter& v)
92
  {
93
 
94
    vector<HalfEdgeIter> hedges;
95
 
96
    VertexCirculator vc(v);
97
    for(;!vc.end();++vc)
98
      hedges.push_back(vc.get_halfedge());
99
 
100
    vector<Vec3f> one_ring;
101
    int N = vc.no_steps();
102
    for(int i=N-1;i>=0;--i)
103
      {
104
				HalfEdgeIter h = hedges[i];
105
				h = h->next;
106
				while(h->vert != v)
107
					{
108
						one_ring.push_back(h->vert->get_pos());
109
						h = h->next;
110
					}
111
      }
112
    Vec3f norm(0);
113
    N= one_ring.size();
114
    Vec3f p0 = v->get_pos();
115
    for(int i=0;i<N;++i)
116
      {
117
				Vec3f p1 = one_ring[i];
118
				Vec3f p2 = one_ring[(i+1)%N];
119
				Vec3f e0 = normalize(p1-p0);
120
				Vec3f e1 = normalize(p2-p0);
121
				norm += cross(e0,e1)*acos(dot(e0,e1));
122
      }
123
    return normalize(norm);
124
  }
125
 
126
  void safe_triangulate(Manifold& m)
127
  {
128
    vector<FaceIter> fv;
129
    for(FaceIter  fi=m.faces_begin(); fi != m.faces_end(); ++fi)
130
      fv.push_back(fi);
131
    for(int i=0;i<fv.size();++i)
132
      m.safe_triangulate(fv[i]);
133
  }
134
 
135
  void triangulate(Manifold& m)
136
  {
137
    vector<FaceIter> fv;
138
    for(FaceIter  fi=m.faces_begin(); fi != m.faces_end(); ++fi)
139
      fv.push_back(fi);
140
    for(int i=0;i<fv.size();++i)
141
      m.triangulate(fv[i]);
142
  }
143
 
144
  struct PotentialEdge
145
  {
146
    int time_tag;
147
    float badness;
148
    FaceIter f;
149
    VertexIter v0, v1;
150
  };
151
 
152
  bool operator>(const PotentialEdge& e0, const PotentialEdge& e1)
153
  {
154
    return e0.badness>e1.badness;
155
  }
156
 
157
  typedef std::priority_queue<PotentialEdge,
158
															std::vector<PotentialEdge>,
159
															std::greater<PotentialEdge> > 
160
  PotentialEdgeQueue;
161
 
162
  void insert_potential_edges(const VertexIter& v,
163
															PotentialEdgeQueue& pot_edges)
164
  {
165
    vector<Vec3f> one_ring;
166
    vector<HalfEdgeIter> candidates;
167
    get_candidates(v, candidates);
168
 
169
    Vec3f p0 = v->get_pos();
170
    Vec3f norm = get_normal(v);
171
    int n = candidates.size();
172
    for(int i=0;i<n;++i)
173
      {
174
				VertexIter v_n = candidates[i]->vert;
175
				Vec3f edir = normalize(v_n->get_pos()-p0);
176
				Vec3f norm_n = get_normal(v_n);
177
				float bad = sqr(dot(edir, norm));
178
				float bad_n = sqr(dot(edir, norm_n));
179
 
180
				PotentialEdge pot;
181
 
182
				/* So if the edge between two vertices is not orthogonal to 
183
					 their normals, the badness is increased. Badness is also
184
					 increased if the normals are very different. */
185
 
186
				pot.badness = bad+bad_n - dot(norm_n,norm);
187
				pot.time_tag = v->touched;
188
				pot.v0 = v;
189
				pot.v1 = candidates[i]->vert;
190
				pot.f = candidates[i]->face;
191
 
192
				pot_edges.push(pot);
193
      }
194
  }
195
 
196
 
197
  void create_candidates(Manifold& m, PotentialEdgeQueue& pot_edges)
198
  {
199
    for(VertexIter v= m.vertices_begin(); v!= m.vertices_end();++v)
200
      {
201
				v->touched = 0;
202
				insert_potential_edges(v, pot_edges);
203
      }
204
  }
205
 
206
 
207
 
208
 
209
  void curvature_triangulate(Manifold& m)
210
  {
211
    PotentialEdgeQueue pot_edges;
212
 
213
    // Create candidates
214
    create_candidates(m,pot_edges);
215
 
216
    while(!pot_edges.empty())
217
      {
218
				const PotentialEdge& pot_edge = pot_edges.top();
219
 
220
				// Record all the vertices of the face. We need to 
221
				// recompute the candidates.
222
				std::vector<VertexIter> reeval_vec;
223
				FaceCirculator fc(pot_edge.f);
224
				while(!fc.end())
225
					{
226
						reeval_vec.push_back(fc.get_vertex());
227
						++fc;
228
					}
229
 
230
				VertexIter v0 = pot_edge.v0;
231
 
232
				// Make sure that the vertex has not been touched since 
233
				// we created the potential edge. If the vertex has been
234
				// touched the candidate edge has either (a) been processed,
235
				// (b) received a lower priority or (c) become invalid.
236
				if(pot_edge.time_tag == v0->touched)
237
					{
238
						VertexIter v1 = pot_edge.v1;
239
 
240
						vector<Vec3f> one_ring;
241
						vector<HalfEdgeIter> candidates;
242
 
243
						m.split_face(pot_edge.f, v0, v1);
244
 
245
						// Recompute priorities.
246
						for(int i=0;i<reeval_vec.size();++i)
247
							{
248
								VertexIter& v = reeval_vec[i];
249
								v->touched++;
250
								insert_potential_edges(v, pot_edges);
251
							}
252
 
253
					}
254
				pot_edges.pop();
255
      }
256
 
257
  }
258
 
259
}