decimation.hpp 8.26 KB
Newer Older
Pierre Kraemer's avatar
Pierre Kraemer committed
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           *
Pierre Kraemer's avatar
Pierre Kraemer committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
*                                                                              *
* 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.           *
*                                                                              *
20
* Web site: http://cgogn.unistra.fr/                                           *
Pierre Kraemer's avatar
Pierre Kraemer committed
21 22 23 24 25 26 27 28 29 30
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/

namespace CGoGN
{

namespace Algo
{

31 32 33
namespace Surface
{

Pierre Kraemer's avatar
Pierre Kraemer committed
34 35 36 37
namespace Decimation
{

template <typename PFP>
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
38
int decimate(
Pierre Kraemer's avatar
Pierre Kraemer committed
39
	typename PFP::MAP& map, SelectorType s, ApproximatorType a,
40
	std::vector<VertexAttribute<typename PFP::VEC3>* >& attribs, unsigned int nbWantedVertices,
41
	EdgeAttribute<typename PFP::REAL> *edgeErrors,
42
	void (*callback_wrapper)(void*, const void*), void* callback_object
Pierre Kraemer's avatar
Pierre Kraemer committed
43 44
)
{
45
	assert(attribs.size() >= 1 || !"Decimate: not enough attribs provided") ;
46
	assert(attribs[0]->name() == "position" || !"Decimate: first attribute should always be the position") ;
47 48
	VertexAttribute<typename PFP::VEC3> position = *(attribs[0]) ;

Pierre Kraemer's avatar
Pierre Kraemer committed
49
	std::vector<ApproximatorGen<PFP>*> approximators ;
50
	Selector<PFP>* selector = NULL ;
Pierre Kraemer's avatar
Pierre Kraemer committed
51

52 53
	std::vector<VertexAttribute<typename PFP::VEC3>* > *v_approx = NULL ;

Pierre Kraemer's avatar
Pierre Kraemer committed
54 55 56
	switch(a)
	{
		case A_QEM :
57
			approximators.push_back(new Approximator_QEM<PFP>(map, attribs)) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
58 59
			break ;
		case A_MidEdge :
60
			approximators.push_back(new Approximator_MidEdge<PFP>(map, attribs)) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
61 62
			break ;
		case A_CornerCutting :
63
			approximators.push_back(new Approximator_CornerCutting<PFP>(map, attribs)) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
64 65
			break ;
		case A_TangentPredict1 :
66
			approximators.push_back(new Approximator_MidEdge<PFP>(map, attribs)) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
67 68
			break ;
		case A_TangentPredict2 :
69
			approximators.push_back(new Approximator_MidEdge<PFP>(map, attribs)) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
70
			break ;
Sauvage's avatar
Sauvage committed
71 72 73
		case A_NormalArea :
			approximators.push_back(new Approximator_NormalArea<PFP>(map, attribs)) ;
			break ;
74
		case A_hHalfCollapse :
75
			approximators.push_back(new Approximator_HalfCollapse<PFP>(map, attribs)) ;
76
			break ;
77 78
		case A_ColorNaive :
		{
79 80
			v_approx = new std::vector<VertexAttribute<typename PFP::VEC3>* >[2] ;

81
			// pos
82
			v_approx[0].push_back(attribs[0]) ;
83
			approximators.push_back(new Approximator_QEM<PFP>(map, v_approx[0])) ;
84 85

			// col
86 87
			assert(attribs.size() >= 2 || !"Decimate: A_ColorNaive --> not enough attribs provided") ;
			v_approx[1].push_back(attribs[1]) ;
88
			approximators.push_back(new Approximator_ColorNaive<PFP>(map, v_approx[1])) ;
89 90 91 92
		}
		break ;
		case A_ColorQEMext :
		{
93
			// pos + col
94 95
			assert(attribs.size() >= 2 || !"Decimate: A_ColorQEMext --> not enough attribs provided") ;
			approximators.push_back(new Approximator_ColorQEMext<PFP>(map, attribs)) ;
96 97
		}
		break;
98 99 100 101 102 103 104
		case A_GeomColorOpt :
		{
			// pos + col
			assert(attribs.size() >= 2 || !"Decimate: A_GeomColorOpt --> not enough attribs provided") ;
			approximators.push_back(new Approximator_GeomColOpt<PFP>(map, attribs)) ;
		}
		break ;
105
		case A_hQEM :
106
			// pos
107
			approximators.push_back(new Approximator_QEMhalfEdge<PFP>(map, attribs)) ;
Sylvain Thery's avatar
Sylvain Thery committed
108 109 110 111
			break ;

		case A_OTHER:
			break;
Pierre Kraemer's avatar
Pierre Kraemer committed
112 113 114 115 116
	}

	switch(s)
	{
		case S_MapOrder :
117
			selector = new EdgeSelector_MapOrder<PFP>(map, position, approximators) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
118 119
			break ;
		case S_Random :
120
			selector = new EdgeSelector_Random<PFP>(map, position, approximators) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
121 122
			break ;
		case S_EdgeLength :
123
			selector = new EdgeSelector_Length<PFP>(map, position, approximators) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
124
			break ;
125
		case S_QEMml :
126
			selector = new EdgeSelector_QEMml<PFP>(map, position, approximators) ;
127
			break ;
Pierre Kraemer's avatar
Pierre Kraemer committed
128
		case S_QEM :
129
			selector = new EdgeSelector_QEM<PFP>(map, position, approximators) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
130 131
			break ;
		case S_Curvature :
132
			selector = new EdgeSelector_Curvature<PFP>(map, position, approximators) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
133
			break ;
134
		case S_NormalArea :
135
			selector = new EdgeSelector_NormalArea<PFP>(map, position, approximators) ;
136
			break ;
137
		case S_CurvatureTensor :
138
			selector = new EdgeSelector_CurvatureTensor<PFP>(map, position, approximators) ;
139
			break ;
Pierre Kraemer's avatar
Pierre Kraemer committed
140
		case S_MinDetail :
141
			selector = new EdgeSelector_MinDetail<PFP>(map, position, approximators) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
142
			break ;
143
		case S_ColorNaive :
144
			selector = new EdgeSelector_ColorNaive<PFP>(map, position, approximators) ;
145
			break ;
146
		case S_QEMextColor :
147
			selector = new EdgeSelector_QEMextColor<PFP>(map, position, approximators) ;
148
			break ;
149
		case S_hQEMextColor :
150
			selector = new HalfEdgeSelector_QEMextColor<PFP>(map, position, approximators) ;
151
			break ;
152
		case S_hQEMml :
153
			selector = new HalfEdgeSelector_QEMml<PFP>(map, position, approximators) ;
154
			break ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
155 156 157 158 159 160
		case S_hColorGradient:
			selector = new HalfEdgeSelector_ColorGradient<PFP>(map, position, approximators) ;
			break ;
		case S_GeomColOptGrad:
			selector = new EdgeSelector_GeomColOptGradient<PFP>(map, position, approximators) ;
			break ;
Sylvain Thery's avatar
Sylvain Thery committed
161 162
		case S_OTHER:
			break;
Pierre Kraemer's avatar
Pierre Kraemer committed
163 164
	}

Sylvain Thery's avatar
Sylvain Thery committed
165
	int status = decimate<PFP>(map, selector, approximators, nbWantedVertices, true, edgeErrors, callback_wrapper, callback_object) ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
166 167 168

	delete selector ;

Pierre Kraemer's avatar
Pierre Kraemer committed
169
	for(typename std::vector<ApproximatorGen<PFP>*>::iterator it = approximators.begin(); it != approximators.end(); ++it)
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
170
		delete (*it) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
171

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
172
	delete[] v_approx ;
173

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
174 175
	return status ;
}
176

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
177 178 179
template <typename PFP>
int decimate(
		typename PFP::MAP& map,
180
		Selector<PFP>* selector, std::vector<ApproximatorGen<PFP>*>& approximators,
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
181
		unsigned int nbWantedVertices,
182 183 184
		bool recomputePriorityList,
		EdgeAttribute<typename PFP::REAL> *edgeErrors,
		void (*callback_wrapper)(void*, const void*), void *callback_object
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
185 186 187 188
)
{
	for(typename std::vector<ApproximatorGen<PFP>*>::iterator it = approximators.begin(); it != approximators.end(); ++it)
		(*it)->init() ;
189

190 191 192 193 194 195
	Dart d ;
	if (recomputePriorityList || !selector->nextEdge(d))
	{
		if(!selector->init())
			return -1 ; // init failed
	}
196

197
	unsigned int nbVertices = map.template getNbOrbits<VERTEX>() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
198
	bool finished = false ;
199

Pierre Kraemer's avatar
Pierre Kraemer committed
200 201
	while(!finished)
	{
202
		if(!selector->nextEdge(d))
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
203
			break ; // finished before achieving amount of required vertices
Pierre Kraemer's avatar
Pierre Kraemer committed
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224

		--nbVertices ;

		Dart d2 = map.phi2(map.phi_1(d)) ;
		Dart dd2 = map.phi2(map.phi_1(map.phi2(d))) ;

		for(typename std::vector<ApproximatorGen<PFP>*>::iterator it = approximators.begin(); it != approximators.end(); ++it)
		{
			(*it)->approximate(d) ;				// compute approximated attributes
			(*it)->saveApprox(d) ;
		}

		selector->updateBeforeCollapse(d) ;		// update selector

		map.collapseEdge(d) ;					// collapse edge

		for(typename std::vector<ApproximatorGen<PFP>*>::iterator it = approximators.begin(); it != approximators.end(); ++it)
			(*it)->affectApprox(d2);			// affect data to the resulting vertex

		selector->updateAfterCollapse(d2, dd2) ;// update selector

225
		if(nbVertices <= nbWantedVertices)
Pierre Kraemer's avatar
Pierre Kraemer committed
226
			finished = true ;
227 228 229 230

		// Progress bar support
		if (callback_wrapper != NULL && callback_object != NULL)
			callback_wrapper(callback_object, &nbVertices) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
231 232
	}

233 234 235
	if (edgeErrors != NULL)
		selector->getEdgeErrors(edgeErrors) ;

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
236
	return finished == true ? 0 : 1 ; // finished correctly
Pierre Kraemer's avatar
Pierre Kraemer committed
237 238
}

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
239
} // namespace Decimation
Pierre Kraemer's avatar
Pierre Kraemer committed
240

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
241
} // namespace Surface
242

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
243
} // namespace Algo
Pierre Kraemer's avatar
Pierre Kraemer committed
244

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
245
} // namespace CGoGN