123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- #include "pseudonormal_test.h"
- #include "barycentric_coordinates.h"
- #include "doublearea.h"
- #include "project_to_line_segment.h"
- #include <cassert>
- IGL_INLINE void igl::pseudonormal_test(
- const Eigen::MatrixXd & V,
- const Eigen::MatrixXi & F,
- const Eigen::MatrixXd & FN,
- const Eigen::MatrixXd & VN,
- const Eigen::MatrixXd & EN,
- const Eigen::VectorXi & EMAP,
- const Eigen::RowVector3d & q,
- const int f,
- const Eigen::RowVector3d & c,
- double & s,
- Eigen::RowVector3d & n)
- {
- using namespace Eigen;
- const auto & qc = q-c;
- RowVector3d b;
-
-
-
-
-
- const RowVector3d A = V.row(F(f,0));
- const RowVector3d B = V.row(F(f,1));
- const RowVector3d C = V.row(F(f,2));
- const double area = [&A,&B,&C]()
- {
- Matrix<double,1,1> area;
- doublearea(A,B,C,area);
- return area(0);
- }();
-
-
-
-
- const double MIN_DOUBLE_AREA = 1e-4;
- const double epsilon = 1e-12;
- if(area>MIN_DOUBLE_AREA)
- {
- barycentric_coordinates( c,A,B,C,b);
-
- const int type = (b.array()<=epsilon).cast<int>().sum();
- switch(type)
- {
- case 2:
-
- for(int x = 0;x<3;x++)
- {
- if(b(x)>epsilon)
- {
- n = VN.row(F(f,x));
- break;
- }
- }
- break;
- case 1:
-
- for(int x = 0;x<3;x++)
- {
- if(b(x)<=epsilon)
- {
- n = EN.row(EMAP(F.rows()*x+f));
- break;
- }
- }
- break;
- default:
- assert(false && "all barycentric coords zero.");
- case 0:
- n = FN.row(f);
- break;
- }
- }else
- {
-
- bool found = false;
- for(int v = 0;v<3 && !found;v++)
- {
- if( (c-V.row(F(f,v))).norm() < epsilon)
- {
- found = true;
- n = VN.row(F(f,v));
- }
- }
-
- for(int e = 0;e<3 && !found;e++)
- {
- const RowVector3d s = V.row(F(f,(e+1)%3));
- const RowVector3d d = V.row(F(f,(e+2)%3));
- Matrix<double,1,1> sqr_d_j_x(1,1);
- Matrix<double,1,1> t(1,1);
- project_to_line_segment(c,s,d,t,sqr_d_j_x);
- if(sqrt(sqr_d_j_x(0)) < epsilon)
- {
- n = EN.row(EMAP(F.rows()*e+f));
- found = true;
- }
- }
-
- if(!found)
- {
- n = FN.row(f);
- }
- }
- s = (qc.dot(n) >= 0 ? 1. : -1.);
- }
- IGL_INLINE void igl::pseudonormal_test(
- const Eigen::MatrixXd & V,
- const Eigen::MatrixXi & E,
- const Eigen::MatrixXd & EN,
- const Eigen::MatrixXd & VN,
- const Eigen::RowVector2d & q,
- const int e,
- const Eigen::RowVector2d & c,
- double & s,
- Eigen::RowVector2d & n)
- {
- using namespace Eigen;
- const auto & qc = q-c;
- const double len = (V.row(E(e,1))-V.row(E(e,0))).norm();
-
- RowVector2d b((c-V.row(E(e,1))).norm()/len,(c-V.row(E(e,0))).norm()/len);
-
- const double epsilon = 1e-12;
- const int type = (b.array()<=epsilon).cast<int>().sum();
- switch(type)
- {
- case 1:
-
- for(int x = 0;x<2;x++)
- {
- if(b(x)>epsilon)
- {
- n = VN.row(E(e,x));
- break;
- }
- }
- break;
- default:
- assert(false && "all barycentric coords zero.");
- case 0:
- n = EN.row(e);
- break;
- }
- s = (qc.dot(n) >= 0 ? 1. : -1.);
- }
|