Subversion Repositories gelsvn

Rev

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