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