1 // This file is part of libigl, a simple c++ geometry processing library.
2 //
3 // Copyright (C) 2013 Alec Jacobson <alecjacobson@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 #include "on_boundary.h"
9 
10 // IGL includes
11 #include "sort.h"
12 #include "face_occurrences.h"
13 
14 // STL includes
15 
16 template <typename IntegerT>
on_boundary(const std::vector<std::vector<IntegerT>> & T,std::vector<bool> & I,std::vector<std::vector<bool>> & C)17 IGL_INLINE void igl::on_boundary(
18   const std::vector<std::vector<IntegerT> > & T,
19   std::vector<bool> & I,
20   std::vector<std::vector<bool> > & C)
21 {
22   using namespace std;
23   if(T.empty())
24   {
25     I.clear();
26     C.clear();
27     return;
28   }
29 
30   switch(T[0].size())
31   {
32     case 3:
33     {
34       // Get a list of all faces
35       vector<vector<IntegerT> > F(T.size()*3,vector<IntegerT>(2));
36       // Gather faces, loop over tets
37       for(int i = 0; i< (int)T.size();i++)
38       {
39         assert(T[i].size() == 3);
40         // get face in correct order
41         F[i*3+0][0] = T[i][1];
42         F[i*3+0][1] = T[i][2];
43         F[i*3+1][0] = T[i][2];
44         F[i*3+1][1] = T[i][0];
45         F[i*3+2][0] = T[i][0];
46         F[i*3+2][1] = T[i][1];
47       }
48       // Counts
49       vector<int> FC;
50       face_occurrences(F,FC);
51       C.resize(T.size(),vector<bool>(3));
52       I.resize(T.size(),false);
53       for(int i = 0; i< (int)T.size();i++)
54       {
55         for(int j = 0;j<3;j++)
56         {
57           assert(FC[i*3+j] == 2 || FC[i*3+j] == 1);
58           C[i][j] = FC[i*3+j]==1;
59           // if any are on boundary set to true
60           I[i] = I[i] || C[i][j];
61         }
62       }
63       return;
64     }
65     case 4:
66     {
67       // Get a list of all faces
68       vector<vector<IntegerT> > F(T.size()*4,vector<IntegerT>(3));
69       // Gather faces, loop over tets
70       for(int i = 0; i< (int)T.size();i++)
71       {
72         assert(T[i].size() == 4);
73         // get face in correct order
74         F[i*4+0][0] = T[i][1];
75         F[i*4+0][1] = T[i][3];
76         F[i*4+0][2] = T[i][2];
77         // get face in correct order
78         F[i*4+1][0] = T[i][0];
79         F[i*4+1][1] = T[i][2];
80         F[i*4+1][2] = T[i][3];
81         // get face in correct order
82         F[i*4+2][0] = T[i][0];
83         F[i*4+2][1] = T[i][3];
84         F[i*4+2][2] = T[i][1];
85         // get face in correct order
86         F[i*4+3][0] = T[i][0];
87         F[i*4+3][1] = T[i][1];
88         F[i*4+3][2] = T[i][2];
89       }
90       // Counts
91       vector<int> FC;
92       face_occurrences(F,FC);
93       C.resize(T.size(),vector<bool>(4));
94       I.resize(T.size(),false);
95       for(int i = 0; i< (int)T.size();i++)
96       {
97         for(int j = 0;j<4;j++)
98         {
99           assert(FC[i*4+j] == 2 || FC[i*4+j] == 1);
100           C[i][j] = FC[i*4+j]==1;
101           // if any are on boundary set to true
102           I[i] = I[i] || C[i][j];
103         }
104       }
105       return;
106     }
107   }
108 
109 
110 }
111 
112 #include "list_to_matrix.h"
113 #include "matrix_to_list.h"
114 
115 template <typename DerivedT, typename DerivedI, typename DerivedC>
on_boundary(const Eigen::MatrixBase<DerivedT> & T,Eigen::PlainObjectBase<DerivedI> & I,Eigen::PlainObjectBase<DerivedC> & C)116 IGL_INLINE void igl::on_boundary(
117   const Eigen::MatrixBase<DerivedT>& T,
118   Eigen::PlainObjectBase<DerivedI>& I,
119   Eigen::PlainObjectBase<DerivedC>& C)
120 {
121   assert(T.cols() == 0 || T.cols() == 4 || T.cols() == 3);
122   using namespace std;
123   using namespace Eigen;
124   // Cop out: use vector of vectors version
125   vector<vector<typename DerivedT::Scalar> > vT;
126   matrix_to_list(T,vT);
127   vector<bool> vI;
128   vector<vector<bool> > vC;
129   on_boundary(vT,vI,vC);
130   list_to_matrix(vI,I);
131   list_to_matrix(vC,C);
132 }
133 
134 
135 #ifdef IGL_STATIC_LIBRARY
136 // Explicit template instantiation
137 // generated by autoexplicit.sh
138 template void igl::on_boundary<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Array<bool, -1, 1, 0, -1, 1>, Eigen::Array<bool, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Array<bool, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Array<bool, -1, 3, 0, -1, 3> >&);
139 template void igl::on_boundary<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
140 template void igl::on_boundary<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Array<bool, -1, 1, 0, -1, 1>, Eigen::Array<bool, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Array<bool, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Array<bool, -1, -1, 0, -1, -1> >&);
141 #endif
142