IGL_INLINE void igl::flipped_triangles( const Eigen::PlainObjectBase<DerivedV> & V, const Eigen::PlainObjectBase<DerivedF> & F, Eigen::PlainObjectBase<DerivedX> & X) { assert(V.cols() == 2 && "V should contain 2D positions"); std::vector<typename DerivedX::Scalar> flip_idx; for (int i = 0; i < F.rows(); i++) { // https://www.cs.cmu.edu/~quake/robust.html typedef Eigen::Matrix<typename DerivedV::Scalar,1,2> RowVector2S; RowVector2S v1_n = V.row(F(i,0)); RowVector2S v2_n = V.row(F(i,1)); RowVector2S v3_n = V.row(F(i,2)); Eigen::Matrix<typename DerivedV::Scalar,3,3> T2_Homo; T2_Homo.col(0) << v1_n(0),v1_n(1),1.; T2_Homo.col(1) << v2_n(0),v2_n(1),1.; T2_Homo.col(2) << v3_n(0),v3_n(1),1.; double det = T2_Homo.determinant(); assert(det == det && "det should not be NaN"); if (det < 0) { flip_idx.push_back(i); } } igl::list_to_matrix(flip_idx,X); }
IGL_INLINE void igl::cylinder( const int axis_devisions, const int height_devisions, Eigen::PlainObjectBase<DerivedV> & V, Eigen::PlainObjectBase<DerivedF> & F) { V.resize(axis_devisions*height_devisions,3); F.resize(2*(axis_devisions*(height_devisions-1)),3); int f = 0; typedef typename DerivedV::Scalar Scalar; for(int th = 0;th<axis_devisions;th++) { Scalar x = cos(2.*igl::PI*Scalar(th)/Scalar(axis_devisions)); Scalar y = sin(2.*igl::PI*Scalar(th)/Scalar(axis_devisions)); for(int h = 0;h<height_devisions;h++) { Scalar z = Scalar(h)/Scalar(height_devisions-1); V(th+h*axis_devisions,0) = x; V(th+h*axis_devisions,1) = y; V(th+h*axis_devisions,2) = z; if(h > 0) { F(f,0) = ((th+0)%axis_devisions)+(h-1)*axis_devisions; F(f,1) = ((th+1)%axis_devisions)+(h-1)*axis_devisions; F(f,2) = ((th+0)%axis_devisions)+(h+0)*axis_devisions; f++; F(f,0) = ((th+1)%axis_devisions)+(h-1)*axis_devisions; F(f,1) = ((th+1)%axis_devisions)+(h+0)*axis_devisions; F(f,2) = ((th+0)%axis_devisions)+(h+0)*axis_devisions; f++; } } } assert(f == F.rows()); }
inline void igl::PlanarizerShapeUp<DerivedV, DerivedF>::planarize(Eigen::PlainObjectBase<DerivedV> &Vout) { Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> planarity; Vout = Vin; for (int iter =0; iter<maxIter; ++iter) { igl::quad_planarity(Vout, Fin, planarity); typename DerivedV::Scalar nonPlanarity = planarity.cwiseAbs().maxCoeff(); //std::cerr<<"iter #"<<iter<<": max non-planarity: "<<nonPlanarity<<std::endl; if (nonPlanarity<threshold) break; assembleP(); Vv = solver.solve(Q.transpose()*P); if(solver.info()!=Eigen::Success) { std::cerr << "Linear solve failed - PlanarizerShapeUp.cpp" << std::endl; assert(0); } for (int i =0;i<numV;++i) Vout.row(i) << Vv.segment(3*i,3).transpose(); } // set the mean of Vout to the mean of Vin Eigen::Matrix<typename DerivedV::Scalar, 1, 3> oldMean, newMean; oldMean = Vin.colwise().mean(); newMean = Vout.colwise().mean(); Vout.rowwise() += (oldMean - newMean); };
IGL_INLINE void igl::sort_vectors_ccw( const Eigen::PlainObjectBase<DerivedS>& P, const Eigen::PlainObjectBase<DerivedS>& N, Eigen::PlainObjectBase<DerivedI> &order) { int half_degree = P.cols()/3; //local frame Eigen::Matrix<typename DerivedS::Scalar,1,3> e1 = P.head(3).normalized(); Eigen::Matrix<typename DerivedS::Scalar,1,3> e3 = N.normalized(); Eigen::Matrix<typename DerivedS::Scalar,1,3> e2 = e3.cross(e1); Eigen::Matrix<typename DerivedS::Scalar,3,3> F; F<<e1.transpose(),e2.transpose(),e3.transpose(); Eigen::Matrix<typename DerivedS::Scalar,Eigen::Dynamic,1> angles(half_degree,1); for (int i=0; i<half_degree; ++i) { Eigen::Matrix<typename DerivedS::Scalar,1,3> Pl = F.colPivHouseholderQr().solve(P.segment(i*3,3).transpose()).transpose(); // assert(fabs(Pl(2))/Pl.cwiseAbs().maxCoeff() <1e-5); angles[i] = atan2(Pl(1),Pl(0)); } igl::sort( angles, 1, true, angles, order); //make sure that the first element is always at the top while (order[0] != 0) { //do a circshift int temp = order[0]; for (int i =0; i< half_degree-1; ++i) order[i] = order[i+1]; order(half_degree-1) = temp; } }
bool is_orientable( const Eigen::PlainObjectBase<DerivedF>& F, const Eigen::PlainObjectBase<DeriveduE>& uE, const std::vector<std::vector<uE2EType> >& uE2E) { const size_t num_faces = F.rows(); const size_t num_edges = uE.rows(); auto edge_index_to_face_index = [&](size_t ei) { return ei % num_faces; }; auto is_consistent = [&](size_t fid, size_t s, size_t d) { if ((size_t)F(fid, 0) == s && (size_t)F(fid, 1) == d) return true; if ((size_t)F(fid, 1) == s && (size_t)F(fid, 2) == d) return true; if ((size_t)F(fid, 2) == s && (size_t)F(fid, 0) == d) return true; if ((size_t)F(fid, 0) == d && (size_t)F(fid, 1) == s) return false; if ((size_t)F(fid, 1) == d && (size_t)F(fid, 2) == s) return false; if ((size_t)F(fid, 2) == d && (size_t)F(fid, 0) == s) return false; throw "Invalid face!!"; }; for (size_t i=0; i<num_edges; i++) { const size_t s = uE(i,0); const size_t d = uE(i,1); int count=0; for (const auto& ei : uE2E[i]) { const size_t fid = edge_index_to_face_index(ei); if (is_consistent(fid, s, d)) count++; else count--; } if (count != 0) { return false; } } return true; }
IGL_INLINE bool igl::list_to_matrix(const std::vector<std::vector<T > > & V,Eigen::PlainObjectBase<Derived>& M) { // number of rows int m = V.size(); if(m == 0) { M.resize(0,0); return true; } // number of columns int n = igl::min_size(V); if(n != igl::max_size(V)) { return false; } assert(n != -1); // Resize output M.resize(m,n); // Loop over rows for(int i = 0;i<m;i++) { // Loop over cols for(int j = 0;j<n;j++) { M(i,j) = V[i][j]; } } return true; }
IGL_INLINE void igl::volume( Eigen::PlainObjectBase<DerivedL>& L, Eigen::PlainObjectBase<Derivedvol>& vol) { using namespace Eigen; const int m = L.rows(); typedef typename Derivedvol::Scalar ScalarS; vol.resize(m,1); for(int t = 0;t<m;t++) { const ScalarS u = L(t,0); const ScalarS v = L(t,1); const ScalarS w = L(t,2); const ScalarS U = L(t,3); const ScalarS V = L(t,4); const ScalarS W = L(t,5); const ScalarS X = (w - U + v)*(U + v + w); const ScalarS x = (U - v + w)*(v - w + U); const ScalarS Y = (u - V + w)*(V + w + u); const ScalarS y = (V - w + u)*(w - u + V); const ScalarS Z = (v - W + u)*(W + u + v); const ScalarS z = (W - u + v)*(u - v + W); const ScalarS a = sqrt(x*Y*Z); const ScalarS b = sqrt(y*Z*X); const ScalarS c = sqrt(z*X*Y); const ScalarS d = sqrt(x*y*z); vol(t) = sqrt( (-a + b + c + d)* ( a - b + c + d)* ( a + b - c + d)* ( a + b + c - d))/ (192.*u*v*w); } }
IGL_INLINE void igl::face_areas( const Eigen::MatrixBase<DerivedL>& L, const typename DerivedL::Scalar doublearea_nan_replacement, Eigen::PlainObjectBase<DerivedA>& A) { using namespace Eigen; assert(L.cols() == 6); const int m = L.rows(); // (unsigned) face Areas (opposite vertices: 1 2 3 4) Matrix<typename DerivedA::Scalar,Dynamic,1> A0(m,1), A1(m,1), A2(m,1), A3(m,1); Matrix<typename DerivedA::Scalar,Dynamic,3> L0(m,3), L1(m,3), L2(m,3), L3(m,3); L0<<L.col(1),L.col(2),L.col(3); L1<<L.col(0),L.col(2),L.col(4); L2<<L.col(0),L.col(1),L.col(5); L3<<L.col(3),L.col(4),L.col(5); doublearea(L0,doublearea_nan_replacement,A0); doublearea(L1,doublearea_nan_replacement,A1); doublearea(L2,doublearea_nan_replacement,A2); doublearea(L3,doublearea_nan_replacement,A3); A.resize(m,4); A.col(0) = 0.5*A0; A.col(1) = 0.5*A1; A.col(2) = 0.5*A2; A.col(3) = 0.5*A3; }
IGL_INLINE void igl::internal_angles( const Eigen::PlainObjectBase<DerivedL>& L, Eigen::PlainObjectBase<DerivedK> & K) { typedef typename DerivedL::Index Index; assert(L.cols() == 3 && "Edge-lengths should come from triangles"); const Index m = L.rows(); K.resize(m,3); //for(int d = 0;d<3;d++) //{ // const auto & s1 = L.col(d).array(); // const auto & s2 = L.col((d+1)%3).array(); // const auto & s3 = L.col((d+2)%3).array(); // K.col(d) = ((s3.square() + s2.square() - s1.square())/(2.*s3*s2)).acos(); //} // Minimum number of iterms per openmp thread #ifndef IGL_OMP_MIN_VALUE # define IGL_OMP_MIN_VALUE 1000 #endif #pragma omp parallel for if (m>IGL_OMP_MIN_VALUE) for(Index f = 0;f<m;f++) { for(size_t d = 0;d<3;d++) { const auto & s1 = L(f,d); const auto & s2 = L(f,(d+1)%3); const auto & s3 = L(f,(d+2)%3); K(f,d) = acos((s3*s3 + s2*s2 - s1*s1)/(2.*s3*s2)); } } }
IGL_INLINE void igl::mat_min( const Eigen::DenseBase<DerivedX> & X, const int dim, Eigen::PlainObjectBase<DerivedY> & Y, Eigen::PlainObjectBase<DerivedI> & I) { assert(dim==1||dim==2); // output size int n = (dim==1?X.cols():X.rows()); // resize output Y.resize(n); I.resize(n); // loop over dimension opposite of dim for(int j = 0;j<n;j++) { typename DerivedX::Index PHONY,i; typename DerivedX::Scalar m; if(dim==1) { m = X.col(j).minCoeff(&i,&PHONY); }else { m = X.row(j).minCoeff(&PHONY,&i); } Y(j) = m; I(j) = i; } }
void igl::crouzeix_raviart_massmatrix( const Eigen::PlainObjectBase<DerivedV> & V, const Eigen::PlainObjectBase<DerivedF> & F, const Eigen::PlainObjectBase<DerivedE> & E, const Eigen::PlainObjectBase<DerivedEMAP> & EMAP, Eigen::SparseMatrix<MT> & M) { using namespace Eigen; using namespace std; assert(F.cols() == 3); // Mesh should be edge-manifold assert(is_edge_manifold(F)); // number of elements (triangles) int m = F.rows(); // Get triangle areas VectorXd TA; doublearea(V,F,TA); vector<Triplet<MT> > MIJV(3*m); for(int f = 0;f<m;f++) { for(int c = 0;c<3;c++) { MIJV[f+m*c] = Triplet<MT>(EMAP(f+m*c),EMAP(f+m*c),TA(f)*0.5); } } M.resize(E.rows(),E.rows()); M.setFromTriplets(MIJV.begin(),MIJV.end()); }
IGL_INLINE void igl::project_to_line_segment( const Eigen::PlainObjectBase<DerivedP> & P, const Eigen::PlainObjectBase<DerivedS> & S, const Eigen::PlainObjectBase<DerivedD> & D, Eigen::PlainObjectBase<Derivedt> & t, Eigen::PlainObjectBase<DerivedsqrD> & sqrD) { project_to_line(P,S,D,t,sqrD); const int np = P.rows(); // loop over points and fix those that projected beyond endpoints #pragma omp parallel for if (np>10000) for(int p = 0;p<np;p++) { const Eigen::PlainObjectBase<DerivedS> Pp = P.row(p); if(t(p)<0) { sqrD(p) = (Pp-S).squaredNorm(); t(p) = 0; }else if(t(p)>1) { sqrD(p) = (Pp-D).squaredNorm(); t(p) = 1; } } }
IGL_INLINE void igl::slice_into( const Eigen::PlainObjectBase<DerivedX> & X, const Eigen::Matrix<int,Eigen::Dynamic,1> & R, const Eigen::Matrix<int,Eigen::Dynamic,1> & C, Eigen::PlainObjectBase<DerivedX> & Y) { int xm = X.rows(); int xn = X.cols(); assert(R.size() == xm); assert(C.size() == xn); #ifndef NDEBUG int ym = Y.size(); int yn = Y.size(); assert(R.minCoeff() >= 0); assert(R.maxCoeff() < ym); assert(C.minCoeff() >= 0); assert(C.maxCoeff() < yn); #endif // Build reindexing maps for columns and rows, -1 means not in map Eigen::Matrix<int,Eigen::Dynamic,1> RI; RI.resize(xm); for(int i = 0;i<xm;i++) { for(int j = 0;j<xn;j++) { Y(R(i),C(j)) = X(i,j); } } }
IGL_INLINE void igl::slice( const MatX& X, const Eigen::PlainObjectBase<DerivedR> & R, const int dim, MatY& Y) { Eigen::Matrix<typename DerivedR::Scalar,Eigen::Dynamic,1> C; switch(dim) { case 1: // boring base case if(X.cols() == 0) { Y.resize(R.size(),0); return; } igl::colon(0,X.cols()-1,C); return slice(X,R,C,Y); case 2: // boring base case if(X.rows() == 0) { Y.resize(0,R.size()); return; } igl::colon(0,X.rows()-1,C); return slice(X,C,R,Y); default: assert(false && "Unsupported dimension"); return; } }
IGL_INLINE bool igl::writeOBJ( const std::string str, const Eigen::PlainObjectBase<DerivedV>& V, const Eigen::PlainObjectBase<DerivedF>& F) { std::ofstream s(str.c_str()); if(!s.is_open()) { fprintf(stderr,"IOError: writeOBJ() could not open %s\n",str.c_str()); return false; } for(int i=0;i<(int)V.rows();++i) { s << "v " << V(i,0) << " " << V(i,1) << " " << V(i,2) << std::endl; } for(int i=0;i<(int)F.rows();++i) { s << "f " << F(i,0)+1 << " " << F(i,1)+1 << " " << F(i,2)+1 << std::endl; } s.close(); return true; }
IGL_INLINE void igl::polyvector_field_singularities_from_matchings( const Eigen::PlainObjectBase<DerivedV> &V, const Eigen::PlainObjectBase<DerivedF> &F, const std::vector<bool> &V_border, const std::vector<std::vector<VFType> > &VF, const Eigen::MatrixXi &TT, const Eigen::MatrixXi &E2F, const Eigen::MatrixXi &F2E, const Eigen::PlainObjectBase<DerivedM> &match_ab, const Eigen::PlainObjectBase<DerivedM> &match_ba, Eigen::PlainObjectBase<DerivedS> &singularities, Eigen::PlainObjectBase<DerivedS> &singularity_indices) { igl::polyvector_field_singularities_from_matchings(V, F, V_border, VF, TT, E2F, F2E, match_ab, match_ba, singularities); singularity_indices.setZero(singularities.size(), 1); //get index from first vector only int vector_to_match = 0; for (int i =0; i<singularities.size(); ++i) { int vi = singularities[i]; // Eigen::VectorXi mvi,fi; // igl::polyvector_field_one_ring_matchings(V, F, VF, E2F, F2E, TT, match_ab, match_ba, vi, vector_to_match, mvi, fi); Eigen::VectorXi fi; Eigen::MatrixXi mvi; igl::polyvector_field_one_ring_matchings(V, F, VF, E2F, F2E, TT, match_ab, match_ba, vi, mvi, fi); singularity_indices[i] = (mvi(mvi.rows()-1,vector_to_match) - vector_to_match); } }
void igl::sort_triangles( const Eigen::PlainObjectBase<DerivedV> & V, const Eigen::PlainObjectBase<DerivedF> & F, Eigen::PlainObjectBase<DerivedFF> & FF, Eigen::PlainObjectBase<DerivedI> & I) { using namespace Eigen; using namespace igl; using namespace std; // Put model, projection, and viewport matrices into double arrays Matrix4d MV; Matrix4d P; glGetDoublev(GL_MODELVIEW_MATRIX, MV.data()); glGetDoublev(GL_PROJECTION_MATRIX, P.data()); if(V.cols() == 3) { Matrix<typename DerivedV::Scalar, DerivedV::RowsAtCompileTime,4> hV; hV.resize(V.rows(),4); hV.block(0,0,V.rows(),V.cols()) = V; hV.col(3).setConstant(1); return sort_triangles(hV,F,MV,P,FF,I); }else { return sort_triangles(V,F,MV,P,FF,I); } }
IGL_INLINE void igl::min( const Eigen::SparseMatrix<AType> & A, const int dim, Eigen::PlainObjectBase<DerivedB> & B, Eigen::PlainObjectBase<DerivedI> & I) { const int n = A.cols(); const int m = A.rows(); B.resize(dim==1?n:m); B.setConstant(std::numeric_limits<typename DerivedB::Scalar>::max()); I.resize(dim==1?n:m); for_each(A,[&B,&I,&dim](int i, int j,const typename DerivedB::Scalar v) { if(dim == 2) { std::swap(i,j); } // Coded as if dim == 1, assuming swap for dim == 2 if(v < B(j)) { B(j) = v; I(j) = i; } }); Eigen::VectorXi Z; find_zero(A,dim,Z); for(int j = 0;j<I.size();j++) { if(Z(j) != (dim==1?m:n) && 0 < B(j)) { B(j) = 0; I(j) = Z(j); } } }
IGL_INLINE void igl::per_face_normals( const Eigen::MatrixBase<DerivedV>& V, const Eigen::MatrixBase<DerivedF>& F, const Eigen::MatrixBase<DerivedZ> & Z, Eigen::PlainObjectBase<DerivedN> & N) { N.resize(F.rows(),3); // loop over faces int Frows = F.rows(); #pragma omp parallel for if (Frows>10000) for(int i = 0; i < Frows;i++) { const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v1 = V.row(F(i,1)) - V.row(F(i,0)); const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v2 = V.row(F(i,2)) - V.row(F(i,0)); N.row(i) = v1.cross(v2);//.normalized(); typename DerivedV::Scalar r = N.row(i).norm(); if(r == 0) { N.row(i) = Z; }else { N.row(i) /= r; } } }
IGL_INLINE void igl::in_element( const Eigen::PlainObjectBase<DerivedV> & V, const Eigen::MatrixXi & Ele, const Eigen::PlainObjectBase<DerivedQ> & Q, const AABB<DerivedV,DIM> & aabb, Eigen::SparseMatrix<Scalar> & I) { using namespace std; using namespace Eigen; using namespace igl; const int Qr = Q.rows(); std::vector<Triplet<Scalar> > IJV; IJV.reserve(Qr); #pragma omp parallel for if (Qr>10000) for(int e = 0;e<Qr;e++) { // find all const auto R = aabb.find(V,Ele,Q.row(e),false); for(const auto r : R) { #pragma omp critical IJV.push_back(Triplet<Scalar>(e,r,1)); } } I.resize(Qr,Ele.rows()); I.setFromTriplets(IJV.begin(),IJV.end()); }
IGL_INLINE void igl::find( const Eigen::DenseBase<DerivedX>& X, Eigen::PlainObjectBase<DerivedI> & I, Eigen::PlainObjectBase<DerivedJ> & J, Eigen::PlainObjectBase<DerivedV> & V) { const int nnz = X.count(); I.resize(nnz,1); J.resize(nnz,1); V.resize(nnz,1); { int k = 0; for(int j = 0;j<X.cols();j++) { for(int i = 0;i<X.rows();i++) { if(X(i,j)) { I(k) = i; J(k) = j; V(k) = X(i,j); k++; } } } } }
IGL_INLINE void igl::matlab::parse_rhs_double( const mxArray *prhs[], Eigen::PlainObjectBase<DerivedV> & V) { using namespace std; using namespace Eigen; // set number of mesh vertices const int n = mxGetM(prhs[0]); // set vertex position pointers double * Vp = mxGetPr(prhs[0]); const int dim = mxGetN(prhs[0]); typedef typename DerivedV::Scalar Scalar; Matrix<Scalar, DerivedV::ColsAtCompileTime, DerivedV::RowsAtCompileTime, RowMajor> VT; Scalar * V_data; if(DerivedV::IsRowMajor) { VT.resize(dim,n); V_data = VT.data(); }else { V.resize(n,dim); V_data = V.data(); } copy(Vp,Vp+n*dim,V_data); if(DerivedV::IsRowMajor) { V = VT.transpose(); } }
IGL_INLINE void igl::unique_edge_map( const Eigen::PlainObjectBase<DerivedF> & F, Eigen::PlainObjectBase<DerivedE> & E, Eigen::PlainObjectBase<DeriveduE> & uE, Eigen::PlainObjectBase<DerivedEMAP> & EMAP, std::vector<std::vector<uE2EType> > & uE2E) { using namespace Eigen; using namespace std; // All occurances of directed edges all_edges(F,E); const size_t ne = E.rows(); // This is 2x faster to create than a map from pairs to lists of edges and 5x // faster to access (actually access is probably assympotically faster O(1) // vs. O(log m) Matrix<typename DerivedEMAP::Scalar,Dynamic,1> IA; unique_simplices(E,uE,IA,EMAP); uE2E.resize(uE.rows()); // This does help a little for_each(uE2E.begin(),uE2E.end(),[](vector<uE2EType > & v){v.reserve(2);}); assert((size_t)EMAP.size() == ne); for(uE2EType e = 0;e<(uE2EType)ne;e++) { uE2E[EMAP(e)].push_back(e); } }
IGL_INLINE void igl::randperm( const int n, Eigen::PlainObjectBase<DerivedI> & I) { Eigen::VectorXi II; igl::colon(0,1,n-1,II); I = II; std::random_shuffle(I.data(),I.data()+n); }
IGL_INLINE int igl::unproject_to_zero_plane( const Eigen::PlainObjectBase<Derivedwin> & win, Eigen::PlainObjectBase<Derivedobj> & obj) { return unproject_to_zero_plane(win(0),win(1), &obj.data()[0], &obj.data()[1], &obj.data()[2]); }
IGL_INLINE void igl::jet( const Eigen::PlainObjectBase<DerivedZ> & Z, const bool normalize, Eigen::PlainObjectBase<DerivedC> & C) { const double min_z = (normalize?Z.minCoeff():0); const double max_z = (normalize?Z.maxCoeff():-1); return jet(Z,min_z,max_z,C); }
IGL_INLINE void igl::sort( const Eigen::PlainObjectBase<DerivedX>& X, const int dim, const bool ascending, Eigen::PlainObjectBase<DerivedY>& Y, Eigen::PlainObjectBase<DerivedIX>& IX) { // get number of rows (or columns) int num_inner = (dim == 1 ? X.rows() : X.cols() ); // Special case for swapping if(num_inner == 2) { return igl::sort2(X,dim,ascending,Y,IX); } using namespace Eigen; // get number of columns (or rows) int num_outer = (dim == 1 ? X.cols() : X.rows() ); // dim must be 2 or 1 assert(dim == 1 || dim == 2); // Resize output Y.resize(X.rows(),X.cols()); IX.resize(X.rows(),X.cols()); // idea is to process each column (or row) as a std vector // loop over columns (or rows) for(int i = 0; i<num_outer;i++) { // Unsorted index map for this column (or row) std::vector<size_t> index_map(num_inner); std::vector<double> data(num_inner); for(int j = 0;j<num_inner;j++) { if(dim == 1) { data[j] = (double) X(j,i); }else { data[j] = (double) X(i,j); } } // sort this column (or row) igl::sort( data, ascending, data, index_map); // Copy into Y and IX for(int j = 0;j<num_inner;j++) { if(dim == 1) { Y(j,i) = data[j]; IX(j,i) = index_map[j]; }else { Y(i,j) = data[j]; IX(i,j) = index_map[j]; } } } }
IGL_INLINE void igl::reorient_facets_raycast( const Eigen::PlainObjectBase<DerivedV> & V, const Eigen::PlainObjectBase<DerivedF> & F, Eigen::PlainObjectBase<DerivedFF> & FF, Eigen::PlainObjectBase<DerivedI> & I) { const int rays_total = F.rows()*100; const int rays_minimum = 10; const bool facet_wise = false; const bool use_parity = false; const bool is_verbose = false; Eigen::VectorXi C; reorient_facets_raycast( V,F,rays_total,rays_minimum,facet_wise,use_parity,is_verbose,I,C); // Conservative in case FF = F FF.conservativeResize(F.rows(),F.cols()); for(int i = 0;i<I.rows();i++) { if(I(i)) { FF.row(i) = (F.row(i).reverse()).eval(); }else { FF.row(i) = F.row(i); } } }
IGL_INLINE void igl::components( const Eigen::SparseMatrix<AScalar> & A, Eigen::PlainObjectBase<DerivedC> & C, Eigen::PlainObjectBase<Derivedcounts> & counts) { using namespace Eigen; using namespace std; assert(A.rows() == A.cols() && "A should be square."); const size_t n = A.rows(); Array<bool,Dynamic,1> seen = Array<bool,Dynamic,1>::Zero(n,1); C.resize(n,1); typename DerivedC::Scalar id = 0; vector<typename Derivedcounts::Scalar> vcounts; // breadth first search for(int k=0; k<A.outerSize(); ++k) { if(seen(k)) { continue; } queue<int> Q; Q.push(k); vcounts.push_back(0); while(!Q.empty()) { const int f = Q.front(); Q.pop(); if(seen(f)) { continue; } seen(f) = true; C(f,0) = id; vcounts[id]++; // Iterate over inside for(typename SparseMatrix<AScalar>::InnerIterator it (A,f); it; ++it) { const int g = it.index(); if(!seen(g) && it.value()) { Q.push(g); } } } id++; } assert((size_t) id == vcounts.size()); const size_t ncc = vcounts.size(); assert((size_t)C.maxCoeff()+1 == ncc); counts.resize(ncc,1); for(size_t i = 0;i<ncc;i++) { counts(i) = vcounts[i]; } }
IGL_INLINE int igl::ray_sphere_intersect( const Eigen::PlainObjectBase<Derivedo> & ao, const Eigen::PlainObjectBase<Derivedd> & d, const Eigen::PlainObjectBase<Derivedc> & ac, r_type r, t_type & t0, t_type & t1) { Eigen::Vector3d o = ao-ac; // http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection //Compute A, B and C coefficients double a = d.dot(d); double b = 2 * d.dot(o); double c = o.dot(o) - (r * r); //Find discriminant double disc = b * b - 4 * a * c; // if discriminant is negative there are no real roots, so return // false as ray misses sphere if (disc < 0) { return 0; } // compute q as described above double distSqrt = sqrt(disc); double q; if (b < 0) { q = (-b - distSqrt)/2.0; } else { q = (-b + distSqrt)/2.0; } // compute t0 and t1 t0 = q / a; double _t1 = c/q; if(_t1 == t0) { return 1; } t1 = _t1; // make sure t0 is smaller than t1 if (t0 > t1) { // if t0 is bigger than t1 swap them around double temp = t0; t0 = t1; t1 = temp; } return 2; }