Subversion Repositories gelsvn

Rev

Rev 149 | Rev 182 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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