38 #ifndef METRICTENSOR_H
39 #define METRICTENSOR_H
44 #include <Eigen/Dense>
49 template<
typename treal_t,
int dim>
50 std::ostream& operator<<(std::ostream& out, const MetricTensor<treal_t,dim>& in);
103 for(
size_t i=0; i<(dim==2?3:6); i++)
104 _metric[i] = metric._metric[i];
112 for(
size_t i=0; i<(dim==2?3:6); i++)
113 metric[i] = _metric[i];
136 for(
size_t i=0; i<(dim==2?3:6); i++)
137 _metric[i] = metric[i];
144 Eigen::Matrix<treal_t, dim, dim>
M;
147 M << metric[0]+DBL_EPSILON, metric[1],
148 metric[1], metric[2]+DBL_EPSILON;
150 M << metric[0]+DBL_EPSILON, metric[1], metric[2],
151 metric[1], metric[3]+DBL_EPSILON, metric[4],
152 metric[2], metric[4], metric[5]+DBL_EPSILON;
158 Eigen::EigenSolver< Eigen::Matrix<treal_t, dim, dim> > solver(M);
160 Eigen::Matrix<treal_t, dim, 1> evalues = solver.eigenvalues().real().cwise().abs();
161 Eigen::Matrix<treal_t, dim, dim> evectors = solver.eigenvectors().real();
162 Eigen::Matrix<treal_t, dim, dim> Mp = evectors*evalues.asDiagonal()*evectors.transpose();
186 void constrain(
const treal_t* M_in,
bool perserved_small_edges=
true){
187 for(
size_t i=0; i<(dim==2?3:6); i++){
189 std::cerr<<
"WARNING: encountered NAN in "<<__FILE__<<
", "<<__LINE__<<std::endl;
197 const treal_t *Mr=_metric, *
Mi=metric._metric;
198 Eigen::Matrix<treal_t, dim, dim> M1;
200 M1 << _metric[0], _metric[1],
201 _metric[1], _metric[2];
203 M1[0] = _metric[0]; M1[1] = _metric[1]; M1[2] = _metric[2];
204 M1[3] = _metric[1]; M1[4] = _metric[3]; M1[5] = _metric[4];
205 M1[6] = _metric[2]; M1[7] = _metric[4]; M1[8] = _metric[5];
208 Eigen::EigenSolver< Eigen::Matrix<treal_t, dim, dim> > solver1(M1);
209 Eigen::Matrix<treal_t, dim, 1> evalues1 = solver1.eigenvalues().real().cwise().abs();
213 aspect_r = std::min(evalues1[0], evalues1[1])/
214 std::max(evalues1[0], evalues1[1]);
217 if(!std::isnormal(aspect_r)){
219 _metric[i] = M_in[i];
224 aspect_r = std::min(std::min(evalues1[0], evalues1[1]), evalues1[2])/
225 std::max(std::max(evalues1[0], evalues1[1]), evalues1[2]);
227 Eigen::Matrix<treal_t, dim, dim> M2;
229 M2 << metric._metric[0], metric._metric[1],
230 metric._metric[1], metric._metric[2];
232 M2[0] = metric._metric[0]; M2[1] = metric._metric[1]; M2[2] = metric._metric[2];
233 M2[3] = metric._metric[1]; M2[4] = metric._metric[3]; M2[5] = metric._metric[4];
234 M2[6] = metric._metric[2]; M2[7] = metric._metric[4]; M2[8] = metric._metric[5];
241 Eigen::EigenSolver< Eigen::Matrix<treal_t, dim, dim> > solver2(M2);
242 Eigen::Matrix<treal_t, dim, 1> evalues2 = solver2.eigenvalues().real().cwise().abs();
246 aspect_i = std::min(evalues2[0], evalues2[1])/
247 std::max(evalues2[0], evalues2[1]);
249 aspect_i = std::min(std::min(evalues2[0], evalues2[1]), evalues2[2])/
250 std::max(std::max(evalues2[0], evalues2[1]), evalues2[2]);
252 if(aspect_i>aspect_r){
262 M1 << Mr[0], Mr[1], Mr[2],
266 Eigen::EigenSolver< Eigen::Matrix<treal_t, dim, dim> > solver(M1);
267 Eigen::Matrix<treal_t, dim, dim> F =
268 solver.eigenvalues().real().cwise().abs().cwise().sqrt().asDiagonal()*
269 solver.eigenvectors().real();
275 M2 << Mi[0], Mi[1], Mi[2],
279 Eigen::Matrix<treal_t, dim, dim>
M = F.inverse().transpose()*M2*F.inverse();
281 Eigen::EigenSolver< Eigen::Matrix<treal_t, dim, dim> > solver3(M);
282 Eigen::Matrix<treal_t, dim, 1> evalues = solver3.eigenvalues().real().cwise().abs();
283 Eigen::Matrix<treal_t, dim, dim> evectors = solver3.eigenvectors().real();
285 if(perserved_small_edges)
286 for(
size_t i=0; i<dim; i++)
287 evalues[i] = std::max((treal_t) 1.0, evalues[i]);
289 for(
size_t i=0; i<dim; i++)
290 evalues[i] = std::min((treal_t) 1.0, evalues[i]);
292 Eigen::Matrix<treal_t, dim, dim> Mc = F.transpose()*evectors*evalues.asDiagonal()*evectors.transpose()*F;
314 Eigen::Matrix<treal_t, dim, dim> M1;
316 M1 << _metric[0], _metric[1],
317 _metric[1], _metric[2];
319 M1[0] = _metric[0]; M1[1] = _metric[1]; M1[2] = _metric[2];
320 M1[3] = _metric[1]; M1[4] = _metric[3]; M1[5] = _metric[4];
321 M1[6] = _metric[2]; M1[7] = _metric[4]; M1[8] = _metric[5];
324 Eigen::EigenSolver< Eigen::Matrix<treal_t, dim, dim> > solver1(M1);
326 Eigen::Matrix<treal_t, dim, 1> evalues = solver1.eigenvalues().real().cwise().abs();
327 Eigen::Matrix<treal_t, dim, dim> evectors = solver1.eigenvectors().real();
330 if(evalues[0]<evalues[1]){
331 evalues[0] = std::max(evalues[0], evalues[1]/(max_ratio*max_ratio));
333 evalues[1] = std::max(evalues[1], evalues[0]/(max_ratio*max_ratio));
336 treal_t max_eigenvalue = std::max(evalues[0], std::max(evalues[1], evalues[2]));
337 treal_t min_eigenvalue = max_eigenvalue/(max_ratio*max_ratio);
339 for(
int i=0;i<dim;i++)
340 evalues[i] = std::max(evalues[i], min_eigenvalue);
343 Eigen::Matrix<treal_t, dim, dim> Mc = evectors*evalues.asDiagonal()*evectors.transpose();
366 for(
size_t i=0; i<(dim==2?3:6); i++)
367 _metric[i] *= scale_factor;
379 treal_t l0 = sqrt(1.0/D[0]);
380 treal_t l1 = sqrt(1.0/D[1]);
381 result = (l0+l1)*0.5;
383 treal_t l0 = sqrt(1.0/D[0]);
384 treal_t l1 = sqrt(1.0/D[1]);
385 treal_t l2 = sqrt(1.0/D[2]);
386 result = (l0+l1+l2)/3.0;
401 min_d = std::min(D[0], D[1]);
403 min_d = std::min(std::min(D[0], D[1]), D[2]);
405 return sqrt(1.0/min_d);
417 max_d = std::max(D[0], D[1]);
419 max_d = std::max(std::max(D[0], D[1]), D[2]);
421 return sqrt(1.0/max_d);
425 Eigen::Matrix<treal_t, dim, dim>
M;
427 M << _metric[0], _metric[1],
428 _metric[1], _metric[2];
430 M << _metric[0], _metric[1], _metric[2],
431 _metric[1], _metric[3], _metric[4],
432 _metric[2], _metric[4], _metric[5];
435 for(
size_t i=0; i<dim; i++)
436 eigenvalues[i] = 0.0;
438 for(
size_t i=0; i<dim*dim; i++)
439 eigenvectors[i] = 0.0;
441 Eigen::EigenSolver< Eigen::Matrix<treal_t, dim, dim> > solver(M);
443 Eigen::Matrix<treal_t, dim, 1> evalues = solver.eigenvalues().real().cwise().abs();
444 Eigen::Matrix<treal_t, dim, dim> evectors = solver.eigenvectors().real();
446 for(
size_t i=0; i<dim; i++)
447 eigenvalues[i] = evalues[i];
449 Eigen::Matrix<treal_t, dim, dim> Mp = evectors.transpose();
450 for(
size_t i=0; i<dim*dim; i++)
451 eigenvectors[i] = Mp[i];
457 treal_t eigenvalues[dim];
458 for(
size_t i=0; i<dim; i++)
459 eigenvalues[i] = fabs(D[i]);
462 for(
size_t i=0; i<dim; i++){
463 for(
size_t j=0; j<dim; j++){
464 int ii = (i*dim) + j;
466 for(
size_t k=0; k<dim; k++)
467 M[ii]+=eigenvalues[k]*V[k*dim+i]*V[k*dim+j];
486 treal_t _metric[dim==2?3:(dim==3?6:-1)];
489 template<
typename treal_t,
int dim>
490 std::ostream& operator<<(std::ostream& out, const MetricTensor<treal_t,dim>& in){
492 out << in._metric[0] <<
" " << in._metric[1] << std::endl
493 << in._metric[1] <<
" " << in._metric[2] << std::endl;
495 out << in._metric[0] <<
" " << in._metric[1] <<
" " << in._metric[2] << std::endl
496 << in._metric[1] <<
" " << in._metric[3] <<
" " << in._metric[4] << std::endl
497 << in._metric[2] <<
" " << in._metric[4] <<
" " << in._metric[5] << std::endl;
symmetric metric tensor class.
void limit_aspect_ratio(treal_t max_ratio)
treal_t max_length() const
MetricTensor()
Default constructor.
void eigen_undecomp(const treal_t *D, const treal_t *V)
const MetricTensor & operator=(const MetricTensor< treal_t, dim > &metric)
MetricTensor(const MetricTensor< treal_t, dim > &metric)
treal_t average_length() const
static void positive_definiteness(treal_t *metric)
void eigen_decomp(treal_t *eigenvalues, treal_t *eigenvectors) const
void get_metric(treal_t *metric)
~MetricTensor()
Default destructor.
void set_metric(const treal_t *metric)
double min_length() const
MetricTensor(const treal_t *metric)
const treal_t * get_metric() const
Give const pointer to metric tensor.
void scale(treal_t scale_factor)
void constrain(const treal_t *M_in, bool perserved_small_edges=true)