colorPerVertexApproximator.hpp 5.81 KB
Newer Older
1 2 3 4 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 31 32 33 34
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* version 0.1                                                                  *
* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg           *
*                                                                              *
* 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
{

namespace Decimation
{

/************************************************************************************
35
 *                      NAIVE COLOR METRIC                                          *
36 37 38
 ************************************************************************************/

template <typename PFP>
39
void Approximator_ColorNaive<PFP>::approximate(Dart d)
40 41 42
{
	Dart dd = this->m_map.phi1(d) ;

43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
	const VEC3& p1 = m_position.operator[](d) ;
	const VEC3& p2 = m_position.operator[](dd) ;
	const VEC3& p = m_approxposition.operator[](d) ;

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

	this->m_approx[0][d] = m_color->operator[](d)*ratio + m_color->operator[](dd)*(1-ratio) ;
}

/************************************************************************************
 *                            EXTENDED QUADRIC ERROR METRIC                         *
 ************************************************************************************/
template <typename PFP>
bool Approximator_ColorQEMext<PFP>::init()
{
	m_quadric = this->m_map.template getAttribute<QuadricNd<REAL,6>, VERTEX>("QEMext-quadric") ;
60
	// Does not require to be valid (if it is not, altenatives will be used).
61 62 63 64 65

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

	return m_position->isValid() && m_color->isValid() ;
68 69 70 71 72 73 74 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 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
}

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

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

	QuadricNd<REAL,6> 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
		{
			VEC6 p0,p1,p2 ;
			for (unsigned int i = 0 ; i < 3 ; ++i)
			{
				p0[i] = this->m_attrV[0]->operator[](it)[i] ;
				p0[i+3] = this->m_attrV[1]->operator[](it)[i] ;
				p1[i] = this->m_attrV[0]->operator[](m.phi1(it))[i] ;
				p1[i+3] = this->m_attrV[1]->operator[](m.phi1(it))[i] ;
				p2[i] = this->m_attrV[0]->operator[](m.phi_1(it))[i] ;
				p2[i+3] = this->m_attrV[1]->operator[](m.phi_1(it))[i] ;
			}

			QuadricNd<REAL,6> q(p0,p1,p2) ;
			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)
			{
				p0[i] = this->m_attrV[0]->operator[](it)[i] ;
				p0[i+3] = this->m_attrV[1]->operator[](it)[i] ;
				p1[i] = this->m_attrV[0]->operator[](m.phi1(it))[i] ;
				p1[i+3] = this->m_attrV[1]->operator[](m.phi1(it))[i] ;
				p2[i] = this->m_attrV[0]->operator[](m.phi_1(it))[i] ;
				p2[i+3] = this->m_attrV[1]->operator[](m.phi_1(it))[i] ;
			}

			QuadricNd<REAL,6> q(p0,p1,p2) ;
			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] ;
	}

	QuadricNd<REAL,6> quad ;
	quad += q1 ;	// compute the sum of the
	quad += q2 ;	// two vertices quadrics

	VEC6 res ;
132
	bool opt = quad.findOptimizedVec(res) ;	// try to compute an optimized position for the contraction of this edge
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
	if(!opt)
	{
		VEC6 p1, p2 ;
		for (unsigned int i = 0 ; i < 3; ++i)
		{
			p1[i] = this->m_attrV[0]->operator[](d)[i] ;	// let the new vertex lie
			p1[i+3] = this->m_attrV[1]->operator[](d)[i] ; // on either one
			p2[i] = this->m_attrV[0]->operator[](dd)[i] ;	// of the two
			p2[i+3] = this->m_attrV[1]->operator[](dd)[i] ; // endpoints
		}
		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)
	{
160 161
		this->m_approx[0][d][i] = res[i] ;
		this->m_approx[1][d][i] = res[i+3] ;
162
	}
163 164 165 166 167 168 169
}

} //namespace Decimation

} //namespace Algo

} //namespace CGoGN