// This file is part of libigl, a simple c++ geometry processing library. // // Copyright (C) 2015 Alec Jacobson // // This Source Code Form is subject to the terms of the Mozilla Public License // v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "slice_tets.h" #include "LinSpaced.h" #include "sort.h" #include "edges.h" #include "slice.h" #include "cat.h" #include "ismember.h" #include "unique_rows.h" #include #include #include template < typename DerivedV, typename DerivedT, typename DerivedS, typename DerivedSV, typename DerivedSF, typename DerivedJ, typename BCType> IGL_INLINE void igl::slice_tets( const Eigen::MatrixBase& V, const Eigen::MatrixBase& T, const Eigen::MatrixBase & S, Eigen::PlainObjectBase& SV, Eigen::PlainObjectBase& SF, Eigen::PlainObjectBase& J, Eigen::SparseMatrix & BC) { Eigen::MatrixXi sE; Eigen::Matrix lambda; igl::slice_tets(V,T,S,SV,SF,J,sE,lambda); const int ns = SV.rows(); std::vector > BCIJV(ns*2); for(int i = 0;i(i,sE(i,0), lambda(i)); BCIJV[2*i+1] = Eigen::Triplet(i,sE(i,1),1.0-lambda(i)); } BC.resize(SV.rows(),V.rows()); BC.setFromTriplets(BCIJV.begin(),BCIJV.end()); } template < typename DerivedV, typename DerivedT, typename DerivedS, typename DerivedSV, typename DerivedSF, typename DerivedJ> IGL_INLINE void igl::slice_tets( const Eigen::MatrixBase& V, const Eigen::MatrixBase& T, const Eigen::MatrixBase & S, Eigen::PlainObjectBase& SV, Eigen::PlainObjectBase& SF, Eigen::PlainObjectBase& J) { Eigen::MatrixXi sE; Eigen::Matrix lambda; igl::slice_tets(V,T,S,SV,SF,J,sE,lambda); } template < typename DerivedV, typename DerivedT, typename DerivedS, typename DerivedSV, typename DerivedSF, typename DerivedJ, typename DerivedsE, typename Derivedlambda> IGL_INLINE void igl::slice_tets( const Eigen::MatrixBase& V, const Eigen::MatrixBase& T, const Eigen::MatrixBase & S, Eigen::PlainObjectBase& SV, Eigen::PlainObjectBase& SF, Eigen::PlainObjectBase& J, Eigen::PlainObjectBase& sE, Eigen::PlainObjectBase& lambda) { using namespace Eigen; using namespace std; assert(V.cols() == 3 && "V should be #V by 3"); assert(T.cols() == 4 && "T should be #T by 4"); static const Eigen::Matrix flipped_order = (Eigen::Matrix(12,4)<< 3,2,0,1, 3,1,2,0, 3,0,1,2, 2,3,1,0, 2,1,0,3, 2,0,3,1, 1,3,0,2, 1,2,3,0, 1,0,2,3, 0,3,2,1, 0,2,1,3, 0,1,3,2 ).finished(); // number of tets const size_t m = T.rows(); typedef typename DerivedS::Scalar Scalar; typedef typename DerivedT::Scalar Index; typedef Matrix VectorXS; typedef Matrix MatrixX4S; typedef Matrix MatrixX3S; typedef Matrix MatrixX2S; typedef Matrix MatrixX4I; typedef Matrix MatrixX3I; typedef Matrix MatrixX2I; typedef Matrix VectorXI; typedef Array ArrayXb; MatrixX4S IT(m,4); for(size_t t = 0;t & T, const MatrixX4S & IT, const ArrayXb & I, MatrixX4I & TI, MatrixX4S & ITI, VectorXI & JI) { const Index num_I = std::count(I.data(),I.data()+I.size(),true); TI.resize(num_I,4); ITI.resize(num_I,4); JI.resize(num_I,1); { size_t k = 0; for(size_t t = 0;t<(size_t)T.rows();t++) { if(I(t)) { TI.row(k) = T.row(t); ITI.row(k) = IT.row(t); JI(k) = t; k++; } } assert(k == num_I); } }; ArrayXb I13 = (IT.array()<0).rowwise().count()==1; ArrayXb I31 = (IT.array()>0).rowwise().count()==1; ArrayXb I22 = (IT.array()<0).rowwise().count()==2; MatrixX4I T13,T31,T22; MatrixX4S IT13,IT31,IT22; VectorXI J13,J31,J22; extract_rows(T,IT,I13,T13,IT13,J13); extract_rows(T,IT,I31,T31,IT31,J31); extract_rows(T,IT,I22,T22,IT22,J22); const auto & apply_sort4 = [] ( const MatrixX4I & T, const MatrixX4I & sJ, MatrixX4I & sT) { sT.resize(T.rows(),4); for(size_t t = 0;t<(size_t)T.rows();t++) { for(size_t c = 0;c<4;c++) { sT(t,c) = T(t,sJ(t,c)); } } }; const auto & apply_sort2 = [] ( const MatrixX2I & E, const MatrixX2I & sJ, Eigen::PlainObjectBase& sE) { sE.resize(E.rows(),2); for(size_t t = 0;t<(size_t)E.rows();t++) { for(size_t c = 0;c<2;c++) { sE(t,c) = E(t,sJ(t,c)); } } }; const auto & one_below = [&apply_sort4]( const MatrixX4I & T, const MatrixX4S & IT, MatrixX2I & U, MatrixX3I & SF) { // Number of tets const size_t m = T.rows(); if(m == 0) { U.resize(0,2); SF.resize(0,3); return; } MatrixX4S sIT; MatrixX4I sJ; sort(IT,2,true,sIT,sJ); MatrixX4I sT; apply_sort4(T,sJ,sT); U.resize(3*m,2); U<< sT.col(0),sT.col(1), sT.col(0),sT.col(2), sT.col(0),sT.col(3); SF.resize(m,3); for(size_t c = 0;c<3;c++) { SF.col(c) = igl::LinSpaced< Eigen::Matrix > (m,0+c*m,(m-1)+c*m); } ArrayXb flip; { VectorXi _; ismember_rows(sJ,flipped_order,flip,_); } for(int i = 0;i(m,0+0*m,(m-1)+0*m); SF.block(0,1,m,1) = igl::LinSpaced(m,0+1*m,(m-1)+1*m); SF.block(0,2,m,1) = igl::LinSpaced(m,0+3*m,(m-1)+3*m); SF.block(m,0,m,1) = igl::LinSpaced(m,0+0*m,(m-1)+0*m); SF.block(m,1,m,1) = igl::LinSpaced(m,0+3*m,(m-1)+3*m); SF.block(m,2,m,1) = igl::LinSpaced(m,0+2*m,(m-1)+2*m); ArrayXb flip; { VectorXi _; ismember_rows(sJ,flipped_order,flip,_); } for(int i = 0;i()*lambda(e) + V.row(sE(e,1)).template cast()*(1.0-lambda(e)); } SF.resize( SF13.rows()+SF31.rows()+SF22.rows(),3); SF<< SF13, U13.rows()+ SF31.rowwise().reverse().array(), U13.rows()+U31.rows()+SF22.array(); std::for_each( SF.data(), SF.data()+SF.size(), [&uJ](typename DerivedSF::Scalar & i){i=uJ(i);}); J.resize(SF.rows()); J<, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, double>(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::SparseMatrix&); #endif