colorPerVertexApproximator.hpp 8.46 KB
Newer Older
1
2
3
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* version 0.1                                                                  *
4
* Copyright (C) 2009-2013, IGG Team, ICube, University of Strasbourg           *
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
*                                                                              *
* This library is free software; you can redistribute it and/or modify it      *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your     *
* option) any later version.                                                   *
*                                                                              *
* This library is distributed in the hope that it will be useful, but WITHOUT  *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or        *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License  *
* for more details.                                                            *
*                                                                              *
* You should have received a copy of the GNU Lesser General Public License     *
* along with this library; if not, write to the Free Software Foundation,      *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.           *
*                                                                              *
* Web site: http://cgogn.unistra.fr/                                           *
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/

namespace CGoGN
{

namespace Algo
{

31
32
33
namespace Surface
{

34
35
36
37
namespace Decimation
{

/************************************************************************************
38
 *                      NAIVE COLOR METRIC                                          *
39
40
 ************************************************************************************/

41
42
43
44
45
46
template <typename PFP>
bool Approximator_ColorNaive<PFP>::init()
{
	return this->m_approx.isValid() && m_position.isValid() && m_approximatedPosition.isValid() ;
}

47
template <typename PFP>
48
void Approximator_ColorNaive<PFP>::approximate(Dart d)
49
50
51
{
	Dart dd = this->m_map.phi1(d) ;

52
53
54
	const VEC3& p1 = m_position[d] ;
	const VEC3& p2 = m_position[dd] ;
	const VEC3& p = m_approximatedPosition[d] ;
55

56
57
	VEC3 edge = p2 - p1 ;
	REAL ratio = std::max(std::min(((p - p1) * edge) / edge.norm2(), REAL(1)), REAL(0)) ;
58

59
	this->m_approx[d] = this->m_attr[d] * ratio + this->m_attr[dd] * (REAL(1) - ratio) ;
60
61
62
63
64
}

/************************************************************************************
 *                            EXTENDED QUADRIC ERROR METRIC                         *
 ************************************************************************************/
65
/*
66
67
68
template <typename PFP>
bool Approximator_ColorQEMext<PFP>::init()
{
Sylvain Thery's avatar
Sylvain Thery committed
69
	m_quadric = this->m_map.template getAttribute<Utils::QuadricNd<REAL,6>, VERTEX, MAP>("QEMext-quadric") ;
70
	// Does not require to be valid (if it is not, altenatives will be used).
71

72
	return m_position.isValid() && m_color.isValid() ;
73
74
75
76
77
78
79
80
81
82
}

template <typename PFP>
void Approximator_ColorQEMext<PFP>::approximate(Dart d)
{
	MAP& m = this->m_map ;

	// get some darts
	Dart dd = m.phi2(d) ;

83
	Utils::QuadricNd<REAL,6> q1, q2 ;
84
85
86
87
88
89
90
91
92
	if(!m_quadric.isValid()) // if the selector is not QEM, compute local error quadrics
	{
		// compute the error quadric associated to v1
		Dart it = d ;
		do
		{
			VEC6 p0,p1,p2 ;
			for (unsigned int i = 0 ; i < 3 ; ++i)
			{
93
94
95
96
97
98
				p0[i] = (*m_position)[it][i] ;
				p0[i+3] = (*m_color)[it][i] ;
				p1[i] = (*m_position)[m.phi1(it)][i] ;
				p1[i+3] = (*m_color)[m.phi1(it)][i] ;
				p2[i] = (*m_position)[m.phi_1(it)][i] ;
				p2[i+3] = (*m_color)[m.phi_1(it)][i] ;
99
100
			}

101
			Utils::QuadricNd<REAL,6> q(p0,p1,p2) ;
102
103
104
105
106
107
108
109
110
111
112
			q1 += q ;
			it = m.phi2_1(it) ;
		} while(it != d) ;

		// compute the error quadric associated to v2
		it = dd ;
		do
		{
			VEC6 p0,p1,p2 ;
			for (unsigned int i = 0 ; i < 3 ; ++i)
			{
113
114
115
116
117
118
				p0[i] = (*m_position)[it][i] ;
				p0[i+3] = (*m_color)[it][i] ;
				p1[i] = (*m_position)[m.phi1(it)][i] ;
				p1[i+3] = (*m_color)[m.phi1(it)][i] ;
				p2[i] = (*m_position)[m.phi_1(it)][i] ;
				p2[i+3] = (*m_color)[m.phi_1(it)][i] ;
119
120
			}

121
			Utils::QuadricNd<REAL,6> q(p0,p1,p2) ;
122
123
124
125
126
127
128
129
130
131
			q2 += q ;
			it = m.phi2_1(it) ;
		} while(it != dd) ;
	}
	else // if the selector is QEM, use the error quadrics computed by the selector
	{
		q1 = m_quadric[d] ;
		q2 = m_quadric[dd] ;
	}

132
	Utils::QuadricNd<REAL,6> quad ;
133
134
135
136
	quad += q1 ;	// compute the sum of the
	quad += q2 ;	// two vertices quadrics

	VEC6 res ;
137
	bool opt = quad.findOptimizedVec(res) ;	// try to compute an optimized position for the contraction of this edge
138
139
140
141
142
	if(!opt)
	{
		VEC6 p1, p2 ;
		for (unsigned int i = 0 ; i < 3; ++i)
		{
143
144
145
146
			p1[i] = (*m_position)[d][i] ;	// let the new vertex lie
			p1[i+3] = (*m_color)[d][i] ; // on either one
			p2[i] = (*m_position)[dd][i] ;	// of the two
			p2[i+3] = (*m_color)[dd][i] ; // endpoints
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
		}
		VEC6 p12 = (p1 + p2) / 2.0f ;	// or the middle of the edge

		REAL e1 = quad(p1) ;
		REAL e2 = quad(p2) ;
		REAL e12 = quad(p12) ;
		REAL minerr = std::min(std::min(e1, e2), e12) ;	// consider only the one for
		if(minerr == e12)
			res = p12 ;		// which the error is minimal
		else if(minerr == e1)
			res = p1 ;
		else
			res = p2 ;
	}

	// copy res into m_approx
	for (unsigned int i = 0 ; i < 3 ; ++i)
	{
165
166
		this->m_approx[0][d][i] = res[i] ;
		this->m_approx[1][d][i] = res[i+3] ;
167
	}
168
}
169
*/
170
171
172
/************************************************************************************
 *                    GEOM + COLOR OPTIMIZED ERROR METRIC                           *
 ************************************************************************************/
173
/*
174
175
176
template <typename PFP>
bool Approximator_GeomColOpt<PFP>::init()
{
Sylvain Thery's avatar
Sylvain Thery committed
177
	m_quadric = this->m_map.template getAttribute<Utils::Quadric<REAL>, VERTEX, MAP>("QEMquadric") ;
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
	// Does not require to be valid (if it is not, altenatives will be used).

	if(this->m_predictor)
	{
		return false ;
	}

	return m_position->isValid() && m_color->isValid() ;
}

template <typename PFP>
void Approximator_GeomColOpt<PFP>::approximate(Dart d)
{
	MAP& m = this->m_map ;

	// get some darts
	Dart dd = m.phi2(d) ;

	// POSITION
	Utils::Quadric<REAL> q1, q2 ;
	if(!m_quadric.isValid()) // if the selector is not QEM, compute local error quadrics
	{
		// compute the error quadric associated to v1
		Dart it = d ;
		do
		{
204
			Utils::Quadric<REAL> q((*m_position)[it], (*m_position)[m.phi1(it)], (*m_position)[m.phi_1(it)]) ;
205
206
207
208
209
210
211
212
			q1 += q ;
			it = m.phi2_1(it) ;
		} while(it != d) ;

		// compute the error quadric associated to v2
		it = dd ;
		do
		{
213
			Utils::Quadric<REAL> q((*m_position)[it], (*m_position)[m.phi1(it)], (*m_position)[m.phi_1(it)]) ;
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
			q2 += q ;
			it = m.phi2_1(it) ;
		} while(it != dd) ;
	}
	else // if the selector is QEM, use the error quadrics computed by the selector
	{
		q1 = m_quadric[d] ;
		q2 = m_quadric[dd] ;
	}

	Utils::Quadric<REAL> quad ;
	quad += q1 ;	// compute the sum of the
	quad += q2 ;	// two vertices quadrics

	VEC3 res ;
	bool opt = quad.findOptimizedPos(res) ;	// try to compute an optimized position for the contraction of this edge

231
232
	const VEC3& p0 = (*m_position)[d] ;    // let the new vertex lie
	const VEC3& p1 = (*m_position)[dd] ;   // on either one of the two endpoints
233

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
234
	if(false && !opt)
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
	{
		VEC3 p12 = (p0 + p1) / 2.0f ;   // or the middle of the edge
		REAL e1 = quad(p0) ;
		REAL e2 = quad(p1) ;
		REAL e12 = quad(p12) ;
		REAL minerr = std::min(std::min(e1, e2), e12) ; // consider only the one for
		if(minerr == e12)		this->m_approx[0][d] = p12 ;             // which the error is minimal
		else if(minerr == e1)	this->m_approx[0][d] = p0 ;
		else					this->m_approx[0][d] = p1 ;
	}
	// copy res into m_approx
	else
	{
		this->m_approx[0][d] = res ;
	}
	const VEC3& p = this->m_approx[0][d] ;

	// COLOR
253
254
	const VEC3& c1 = (*m_color)[d] ;    // let the new vertex lie
	const VEC3& c2 = (*m_color)[dd] ;   // on either one of the two endpoints
255
256
257
258
259
260
261
262
263
264

	VEC3 e = p1 - p0 ;
	VEC3 e1 = p - p0 ;
	const REAL normE1 = e1.normalize() ;
	const REAL normE = e.normalize() ;
	REAL ratio = (e * e1)*normE1/normE ;
	ratio = std::max(REAL(0),std::min(REAL(1),ratio)) ;

	this->m_approx[1][d] = ratio*c1 + (1-ratio)*c2 ;
}
265
266
*/
} // namespace Decimation
267

268
} // namespace Surface
269

270
} // namespace Algo
271

272
} // namespace CGoGN