decimation.hpp 11.6 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-2012, IGG Team, LSIIT, 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 31 32 33 34 35 36
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/

namespace CGoGN
{

namespace Algo
{

namespace Decimation
{

template <typename PFP>
void decimate(
	typename PFP::MAP& map, SelectorType s, ApproximatorType a,
37 38
	VertexAttribute<typename PFP::VEC3>& position, unsigned int nbWantedVertices, const FunctorSelect& selected,
	void (*callback_wrapper)(void*, const void*), void* callback_object
Pierre Kraemer's avatar
Pierre Kraemer committed
39 40 41 42 43
)
{
	std::vector<ApproximatorGen<PFP>*> approximators ;
	EdgeSelector<PFP>* selector = NULL ;

44 45
	std::vector<VertexAttribute<typename PFP::VEC3>* > v_pos ;
	v_pos.push_back(&position) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
46 47 48
	switch(a)
	{
		case A_QEM :
49
			approximators.push_back(new Approximator_QEM<PFP>(map, v_pos)) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
50 51
			break ;
		case A_MidEdge :
52
			approximators.push_back(new Approximator_MidEdge<PFP>(map, v_pos)) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
53 54
			break ;
		case A_CornerCutting :
55
			approximators.push_back(new Approximator_CornerCutting<PFP>(map, v_pos)) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
56 57
			break ;
		case A_TangentPredict1 :
58
			approximators.push_back(new Approximator_MidEdge<PFP>(map, v_pos)) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
59 60
			break ;
		case A_TangentPredict2 :
61
			approximators.push_back(new Approximator_MidEdge<PFP>(map, v_pos)) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
62
			break ;
63
		case A_hHalfCollapse :
64 65
			approximators.push_back(new Approximator_HalfCollapse<PFP>(map, v_pos)) ;
			break ;
66 67
		case A_ColorNaive :
		{
68
			// pos
69
			approximators.push_back(new Approximator_QEM<PFP>(map, v_pos)) ;
70 71 72 73 74

			// col
			std::vector<VertexAttribute<typename PFP::VEC3>* > v_col ;
			VertexAttribute<typename PFP::VEC3> colors = map.template getAttribute<typename PFP::VEC3, VERTEX>("color") ;
			v_col.push_back(&colors) ;
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
			approximators.push_back(new Approximator_ColorNaive<PFP>(map, v_col)) ;
		}
		break ;
		case A_ColorQEMext :
		{
			// pos+col
			std::vector<VertexAttribute<typename PFP::VEC3>* > v_poscol ;
			v_poscol.push_back(&position) ; // pos
			VertexAttribute<typename PFP::VEC3> colors = map.template getAttribute<typename PFP::VEC3, VERTEX>("color") ;
			v_poscol.push_back(&colors) ; // col
			approximators.push_back(new Approximator_ColorQEMext<PFP>(map, v_poscol)) ;
		}
		break;
		case A_hQEM :
			approximators.push_back(new Approximator_QEMhalfEdge<PFP>(map, v_pos)) ;
		break ;
		case A_hLightfieldHalf :
		{
			// pos
			approximators.push_back(new Approximator_HalfCollapse<PFP>(map, v_pos)) ;

			// frame
			std::vector<VertexAttribute<typename PFP::VEC3>* > v_frame ;
			VertexAttribute<typename PFP::VEC3> FT = map.template getAttribute<typename PFP::VEC3, VERTEX>("frameT") ;
			VertexAttribute<typename PFP::VEC3> FB = map.template getAttribute<typename PFP::VEC3, VERTEX>("frameB") ;
			VertexAttribute<typename PFP::VEC3> FN = map.template getAttribute<typename PFP::VEC3, VERTEX>("frameN") ;
			v_frame.push_back(&FT) ;
			v_frame.push_back(&FB) ;
			v_frame.push_back(&FN) ;
			approximators.push_back(new Approximator_FrameHalf<PFP>(map, v_frame)) ;

//			TODO
//			// function coefs
//			std::vector<VertexAttribute<typename PFP::VEC3>* > v_coefs ;
//			VertexAttribute<typename PFP::VEC3> coefs = map.template getAttribute<typename PFP::VEC3, VERTEX>("SLFcoefs_0") ;
//			v_frame.push_back(&coefs) ;
//			approximators.push_back(new Approximator_LFcoefs<PFP>(map, v_coefs)) ;
		}
		break ;
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
		/*case A_LightfieldHalf:
			approximators.push_back(new Approximator_HalfCollapse<PFP>(map, position)) ;

			// Get all frame embeddings
			std::vector<VertexAttribute<PFP::VEC3>* > vertexAttributesFrame ;
			VertexAttribute<PFP::VEC3> frame0 = myMap.getAttribute<PFP::VEC3, VERTEX>("frameT") ; 	vertexAttributesFrame.push_back(&frame0) ;
			VertexAttribute<PFP::VEC3> frame1 = myMap.getAttribute<PFP::VEC3, VERTEX>("frameB") ; 	vertexAttributesFrame.push_back(&frame1) ;
			VertexAttribute<PFP::VEC3> frame2 = myMap.getAttribute<PFP::VEC3, VERTEX>("frameN") ;	vertexAttributesFrame.push_back(&frame2) ;
			approximators.push_back(new Approximator_FrameHalf<PFP>(map, vertexAttributesFrame)) ; // TODO

			// Get all coefficient embeddings
			const unsigned int K = 200 ;
			std::vector<VertexAttribute<PFP::VEC3>* > vertexAttributesCoefs ;
			VertexAttribute<PFP::VEC3> *PBcoefs = new VertexAttribute<PFP::VEC3>[K] ;
			for (unsigned int k = 0 ; k < K ; ++k)
			{
				std::stringstream s ;
				s << "PBcoefs" << k ;
				PBcoefs[k] = myMap.getAttribute<PFP::VEC3, VERTEX>(s.str()) ;
				if (!PBcoefs[k].isValid())
					break ;
				vertexAttributesCoefs.push_back(&PBcoefs[k]) ;
			}
			const bool& sh = vertexAttributesCoefs.empty() ; // sh or pb
			VertexAttribute<PFP::VEC3> *SHcoefs = new VertexAttribute<PFP::VEC3>[K] ;
			for (unsigned int k = 0 ; k < K ; ++k)
			{
				std::stringstream s ;
				s << "SHcoefs" << k ;
				SHcoefs[k] = myMap.getAttribute<PFP::VEC3, VERTEX>(s.str()) ;
				if (!SHcoefs[k].isValid())
					break ;
				vertexAttributesCoefs.push_back(&SHcoefs[k]) ;
			}
			approximators.push_back(new Approximator_LightfieldCoefsHalf<PFP>(map, vertexAttributesCoefs, sh)) ; // TODO
			break ;
		case A_LightfieldFull_deprecated :
Pierre Kraemer's avatar
Pierre Kraemer committed
151
		{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
152
			approximators.push_back(new Approximator_QEMhalfEdge<PFP>(map, position)) ;
153
			/ *
154
			PFP::TVEC3 frame[3] ;
155 156 157
			frame[0] = map.template getAttribute<typename PFP::VEC3, VERTEX>("frame_T") ; // Tangent
			frame[1] = map.template getAttribute<typename PFP::VEC3, VERTEX>("frame_B") ; // Bitangent
			frame[2] = map.template getAttribute<typename PFP::VEC3, VERTEX>("frame_N") ; // Normal
158 159 160 161
			for (unsigned int i = 0 ; i < 3 ; ++i)
				if (!frame[i].isValid()) {
					CGoGNerr << "In function decimate : frame[" << i << "] is not valid" << CGoGNendl ;
				}
162

163 164 165 166 167 168 169
			VertexAttribute<typename PFP::VEC3> colorPTM[6] ;
			colorPTM[0] = map.template getAttribute<typename PFP::VEC3, VERTEX>("colorPTM_a") ;
			colorPTM[1] = map.template getAttribute<typename PFP::VEC3, VERTEX>("colorPTM_b") ;
			colorPTM[2] = map.template getAttribute<typename PFP::VEC3, VERTEX>("colorPTM_c") ;
			colorPTM[3] = map.template getAttribute<typename PFP::VEC3, VERTEX>("colorPTM_d") ;
			colorPTM[4] = map.template getAttribute<typename PFP::VEC3, VERTEX>("colorPTM_e") ;
			colorPTM[5] = map.template getAttribute<typename PFP::VEC3, VERTEX>("colorPTM_f") ;
170 171 172 173
			for (unsigned int i = 0 ; i < 6 ; ++i)
				if (!colorPTM[i].isValid()) {
					CGoGNerr << "In function decimate : colorPTM[" << i << "] is not valid" << CGoGNendl ;
				}
174
			*
175 176
			VertexAttribute<Geom::Matrix<3,3,typename PFP::REAL> > frame = map.template getAttribute<Geom::Matrix<3,3,typename PFP::REAL>, VERTEX>("frame") ;
			VertexAttribute<Geom::Matrix<3,6,typename PFP::REAL> > RGBfunctions = map.template getAttribute<Geom::Matrix<3,6,typename PFP::REAL>, VERTEX>("colorPTM") ;
177 178
			approximators.push_back(new Approximator_Frame_deprecated<PFP>(map, frame)) ;
			approximators.push_back(new Approximator_RGBfunctions_deprecated<PFP>(map, RGBfunctions)) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
179 180
			break ;
		}
181
		case A_LightfieldHalf_deprecated :
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
182
		{
183
			approximators.push_back(new Approximator_HalfCollapse<PFP>(map, position)) ;
184 185
			VertexAttribute<Geom::Matrix<3,3,typename PFP::REAL> > frame = map.template getAttribute<Geom::Matrix<3,3,typename PFP::REAL>, VERTEX>("frame") ;
			VertexAttribute<Geom::Matrix<3,6,typename PFP::REAL> > RGBfunctions = map.template getAttribute<Geom::Matrix<3,6,typename PFP::REAL>, VERTEX>("colorPTM") ;
186 187
			approximators.push_back(new Approximator_FrameHalf_deprecated<PFP>(map, frame)) ;
			approximators.push_back(new Approximator_RGBfunctionsHalf_deprecated<PFP>(map, RGBfunctions)) ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
188
			break ;
189
		}*/
Pierre Kraemer's avatar
Pierre Kraemer committed
190 191 192 193 194
	}

	switch(s)
	{
		case S_MapOrder :
195
			selector = new EdgeSelector_MapOrder<PFP>(map, position, approximators, selected) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
196 197
			break ;
		case S_Random :
198
			selector = new EdgeSelector_Random<PFP>(map, position, approximators, selected) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
199 200
			break ;
		case S_EdgeLength :
201
			selector = new EdgeSelector_Length<PFP>(map, position, approximators, selected) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
202
			break ;
203
		case S_QEMml :
204
			selector = new EdgeSelector_QEMml<PFP>(map, position, approximators, selected) ;
205
			break ;
Pierre Kraemer's avatar
Pierre Kraemer committed
206
		case S_QEM :
207
			selector = new EdgeSelector_QEM<PFP>(map, position, approximators, selected) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
208 209
			break ;
		case S_Curvature :
210
			selector = new EdgeSelector_Curvature<PFP>(map, position, approximators, selected) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
211 212
			break ;
		case S_MinDetail :
213
			selector = new EdgeSelector_MinDetail<PFP>(map, position, approximators, selected) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
214
			break ;
215 216 217
		case S_ColorNaive :
			selector = new EdgeSelector_ColorNaive<PFP>(map, position, approximators, selected) ;
			break ;
218
		case S_hQEMml :
219
			selector = new HalfEdgeSelector_QEMml<PFP>(map, position, approximators, selected) ;
220
			break ;
221 222
		case S_hLightfield :
			selector = new HalfEdgeSelector_Lightfield<PFP>(map, position, approximators, selected) ;
223
			break ;
Pierre Kraemer's avatar
Pierre Kraemer committed
224 225 226 227 228 229 230 231
	}

	for(typename std::vector<ApproximatorGen<PFP>*>::iterator it = approximators.begin(); it != approximators.end(); ++it)
		(*it)->init() ;

	if(!selector->init())
		return ;

232
	unsigned int nbVertices = map.template getNbOrbits<VERTEX>() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
233 234
	bool finished = false ;
	Dart d ;
235

Pierre Kraemer's avatar
Pierre Kraemer committed
236 237
	while(!finished)
	{
238 239
		if(!selector->nextEdge(d))
		{
Pierre Kraemer's avatar
Pierre Kraemer committed
240
			break ;
241
		}
Pierre Kraemer's avatar
Pierre Kraemer committed
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262

		--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

263 264
		if(nbVertices <= nbWantedVertices)
		{
Pierre Kraemer's avatar
Pierre Kraemer committed
265
			finished = true ;
266
		}
267 268 269 270

		// Progress bar support
		if (callback_wrapper != NULL && callback_object != NULL)
			callback_wrapper(callback_object, &nbVertices) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
271 272 273 274 275 276 277 278 279 280 281 282
	}

	delete selector ;
	for(typename std::vector<ApproximatorGen<PFP>*>::iterator it = approximators.begin(); it != approximators.end(); ++it)
		delete (*it) ;
}

} //namespace Decimation

} //namespace Algo

} //namespace CGoGN