1 // This file is part of libigl, a simple c++ geometry processing library.
2 //
3 // Copyright (C) 2014 Nico Pietroni <nico.pietroni@gmail.com>
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public License
6 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
7 // obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #include "comb_line_field.h"
10 
11 #include <vector>
12 #include <deque>
13 #include "per_face_normals.h"
14 #include "is_border_vertex.h"
15 #include "rotation_matrix_from_directions.h"
16 
17 #include "triangle_triangle_adjacency.h"
18 
19 namespace igl {
20 template <typename DerivedV, typename DerivedF>
21 class CombLine
22 {
23 public:
24 
25     const Eigen::PlainObjectBase<DerivedV> &V;
26     const Eigen::PlainObjectBase<DerivedF> &F;
27     const Eigen::PlainObjectBase<DerivedV> &PD1;
28     DerivedV N;
29 
30 private:
31     // internal
32     DerivedF TT;
33     DerivedF TTi;
34 
35 
36 private:
37 
38 
Sign(double a)39     static inline double Sign(double a){return (double)((a>0)?+1:-1);}
40 
41 
42 private:
43 
44     // returns the 180 deg rotation of a (around n) most similar to target b
45     // a and b should be in the same plane orthogonal to N
K_PI_line(const Eigen::Matrix<typename DerivedV::Scalar,3,1> & a,const Eigen::Matrix<typename DerivedV::Scalar,3,1> & b)46     static inline Eigen::Matrix<typename DerivedV::Scalar, 3, 1> K_PI_line(const Eigen::Matrix<typename DerivedV::Scalar, 3, 1>& a,
47                                                                            const Eigen::Matrix<typename DerivedV::Scalar, 3, 1>& b)
48     {
49         typename DerivedV::Scalar scorea = a.dot(b);
50         if (scorea<0)
51             return -a;
52         else
53             return a;
54     }
55 
56 
57 
58 public:
59 
CombLine(const Eigen::PlainObjectBase<DerivedV> & _V,const Eigen::PlainObjectBase<DerivedF> & _F,const Eigen::PlainObjectBase<DerivedV> & _PD1)60     inline CombLine(const Eigen::PlainObjectBase<DerivedV> &_V,
61                     const Eigen::PlainObjectBase<DerivedF> &_F,
62                     const Eigen::PlainObjectBase<DerivedV> &_PD1):
63         V(_V),
64         F(_F),
65         PD1(_PD1)
66     {
67         igl::per_face_normals(V,F,N);
68         igl::triangle_triangle_adjacency(F,TT,TTi);
69     }
70 
comb(Eigen::PlainObjectBase<DerivedV> & PD1out)71     inline void comb(Eigen::PlainObjectBase<DerivedV> &PD1out)
72     {
73         PD1out.setZero(F.rows(),3);PD1out<<PD1;
74 
75         Eigen::VectorXi mark = Eigen::VectorXi::Constant(F.rows(),false);
76 
77         std::deque<int> d;
78 
79         d.push_back(0);
80         mark(0) = true;
81 
82         while (!d.empty())
83         {
84             int f0 = d.at(0);
85             d.pop_front();
86             for (int k=0; k<3; k++)
87             {
88                 int f1 = TT(f0,k);
89                 if (f1==-1) continue;
90                 if (mark(f1)) continue;
91 
92                 Eigen::Matrix<typename DerivedV::Scalar, 3, 1> dir0  = PD1out.row(f0);
93                 Eigen::Matrix<typename DerivedV::Scalar, 3, 1> dir1  = PD1out.row(f1);
94                 Eigen::Matrix<typename DerivedV::Scalar, 3, 1> n0    = N.row(f0);
95                 Eigen::Matrix<typename DerivedV::Scalar, 3, 1> n1    = N.row(f1);
96 
97                 Eigen::Matrix<typename DerivedV::Scalar, 3, 1> dir0Rot = igl::rotation_matrix_from_directions(n0, n1)*dir0;
98                 dir0Rot.normalize();
99                 Eigen::Matrix<typename DerivedV::Scalar, 3, 1> targD   = K_PI_line(dir1,dir0Rot);
100 
101                 PD1out.row(f1)  = targD;
102                 //PD2out.row(f1)  = n1.cross(targD).normalized();
103 
104                 mark(f1) = true;
105                 d.push_back(f1);
106 
107             }
108         }
109 
110         // everything should be marked
111         for (int i=0; i<F.rows(); i++)
112         {
113             assert(mark(i));
114         }
115     }
116 
117 };
118 }
119 
120 template <typename DerivedV, typename DerivedF>
comb_line_field(const Eigen::PlainObjectBase<DerivedV> & V,const Eigen::PlainObjectBase<DerivedF> & F,const Eigen::PlainObjectBase<DerivedV> & PD1,Eigen::PlainObjectBase<DerivedV> & PD1out)121 IGL_INLINE void igl::comb_line_field(const Eigen::PlainObjectBase<DerivedV> &V,
122                                      const Eigen::PlainObjectBase<DerivedF> &F,
123                                      const Eigen::PlainObjectBase<DerivedV> &PD1,
124                                      Eigen::PlainObjectBase<DerivedV> &PD1out)
125 {
126     igl::CombLine<DerivedV, DerivedF> cmb(V, F, PD1);
127     cmb.comb(PD1out);
128 }
129 
130 #ifdef IGL_STATIC_LIBRARY
131 // Explicit template instantiation
132 #endif
133