Subversion Repositories gelsvn

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
39 bj 1
#include <queue>
2
#include "mesh_optimization.h"
3
#include "HMesh/FaceCirculator.h"
4
#include "HMesh/VertexCirculator.h"
5
#include "caps_and_needles.h"
6
#include "Geometry/QEM.h"
7
 
8
using namespace std;
9
using namespace CGLA;
10
using namespace GEO;
11
using namespace HMesh;
12
 
13
 
14
namespace HMeshUtil
15
{
16
	namespace
17
	{
18
		float min_angle(const Vec3f& v0,const Vec3f& v1,const Vec3f& v2)
19
		{
20
			Vec3f a = normalize(v1-v0);
21
			Vec3f b = normalize(v2-v1);
22
			Vec3f c = normalize(v0-v2);
23
 
24
			return min(dot(a,-c), min(dot(b,-a), dot(c,-b)));
25
		}
26
 
27
		float edge_error(HalfEdgeIter h, 
28
										 const Vec3f& pa,
29
										 const Vec3f& pb)
30
		{
31
			QEM q;
32
			if(h->face != NULL_FACE_ITER)
33
				q += QEM(Vec3d(0), Vec3d(get_normal(h->face)));
34
			if(h->opp->face != NULL_FACE_ITER)
35
				q += QEM(Vec3d(0), Vec3d(get_normal(h->opp->face)));
36
			return q.error(pb-pa);
37
		}
38
 
39
 
40
		float vertex_error(VertexIter va, const Vec3f& pb)
41
		{
42
			QEM q;
43
			Vec3f pa = va->get_pos();
44
			for(VertexCirculator vc(va); !vc.end(); ++vc)
45
				{
46
					FaceIter f = vc.get_face();
47
					if(f != NULL_FACE_ITER)
48
						{
49
							Vec3f n = get_normal(f);
50
							q += QEM(Vec3d(0), Vec3d(n));
51
						}
52
				}
53
			return q.error(pb-pa);
54
		}
55
 
56
	}
57
 
58
	void remove_caps_from_trimesh(Manifold& mani, float ang_thresh)
59
	{
60
		for(FaceIter fi=mani.faces_begin(); fi != mani.faces_end(); ++fi)
61
			{
62
				Vec3f p[3];
63
				HalfEdgeIter he[3];
64
				VertexIter vi[3];
65
 
66
				int n=0;
67
				for(FaceCirculator fc(fi); !fc.end(); ++fc,++n)
68
					{
69
						vi[n] = fc.get_vertex();
70
						p[n]  = fc.get_vertex()->get_pos();
71
						he[n]= fc.get_halfedge();
72
					}
73
				assert(n=3);
74
 
75
				bool is_collapsed = false;
76
				Vec3f edges[3];
77
				for(int i=0;i<3;++i)
78
					{
79
						edges[i] = p[(i+1)%3]-p[i];
80
						float l = length(edges[i]);
81
						if(l<1e-20)
82
							is_collapsed = true;
83
						else
84
							edges[i] /= l;
85
					}
86
				if(is_collapsed) continue;
87
 
88
				for(int i=0;i<3;++i)
89
					{
90
						float d = max(-1.0f,min(1.0f,dot(-edges[(i+2)%3],edges[i])));
91
						float ang = acos(d);
92
						if(ang > ang_thresh)
93
							{
94
								int iplus1 = (i+1)%3;
95
								Vec3f edge_dir = edges[iplus1];
96
								Vec3f pprj =  
97
									edge_dir * dot(edge_dir,p[i]-p[iplus1])+p[iplus1];
98
 
99
								HalfEdgeIter h = he[iplus1];
100
								Vec3f v0 = h->vert->get_pos();
101
								Vec3f v1 = h->next->vert->get_pos();
102
								Vec3f v2 = h->opp->vert->get_pos();
103
								Vec3f v3 = h->opp->next->vert->get_pos();
104
 
105
								float m1 = min(min_angle(v0,v1,v2), min_angle(v0,v2,v3));
106
								float m2 = min(min_angle(v0,pprj,v3), min_angle(pprj,v2,v3));
107
								if(m1 < m2)
108
									{
109
										if(edge_error(he[iplus1], pprj, vi[i]->get_pos()) >
110
											 vertex_error(vi[i], pprj))
111
											vi[i]->set_pos(pprj);
112
 
113
										mani.flip(he[iplus1]);
114
										break;
115
									}
116
							}
117
					}
118
 
119
			}
120
	}
121
 
122
 
123
 
124
	void remove_needles_from_trimesh(Manifold& mani, 
125
																	 float thresh)
126
	{
127
		bool did_work;
128
		do
129
			{
130
				did_work = false;
131
				for(VertexIter vi=mani.vertices_begin(); 
132
						vi != mani.vertices_end(); ++vi)
133
					{
134
						if(vi->is_boundary()) continue;
135
						for(VertexCirculator vc(vi);!vc.end();++vc)
136
							{
137
								if(vc.get_halfedge()->vert->is_boundary()) continue;
138
								HalfEdgeIter he = vc.get_halfedge()->opp;
139
 
140
								VertexIter n = vc.get_vertex();
141
								float dist = length(he);
142
								if((dist<thresh) && mani.collapse_precond(n,he))
143
									{
144
										if(vertex_error(vi,n->get_pos()) < 
145
											 vertex_error(n,vi->get_pos()))
146
											vi->set_pos(n->get_pos());
147
 
148
										mani.collapse_halfedge(n,he);
149
										did_work = true;
150
										break;
151
									}
152
							}
153
					}
154
			}
155
		while(did_work);
156
	}
157
}