// This file is part of libigl, a simple c++ geometry processing library. // // Copyright (C) 2016 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 "circumradius.h" #include "edge_lengths.h" #include "doublearea.h" #include "placeholders.h" #include template < typename DerivedV, typename DerivedF, typename DerivedR> IGL_INLINE void igl::circumradius( const Eigen::MatrixBase & V, const Eigen::MatrixBase & F, Eigen::PlainObjectBase & R) { // cols at compiletime should be Dynamic or 3 static_assert(DerivedF::ColsAtCompileTime == Eigen::Dynamic || DerivedF::ColsAtCompileTime == 3,"F should contain triangles"); assert(F.cols() == 3 && "F should contain triangles"); Eigen::Matrix l; igl::edge_lengths(V,F,l); DerivedR A; igl::doublearea(l,0.,A); // use formula: R=abc/(4*area) to compute the circum radius R = l.col(0).array() * l.col(1).array() * l.col(2).array() / (2.0*A.array()); } template < typename DerivedV, typename DerivedT, typename DerivedR, typename DerivedC, typename DerivedB> IGL_INLINE void igl::circumradius( const Eigen::MatrixBase & V, const Eigen::MatrixBase & T, Eigen::PlainObjectBase & R, Eigen::PlainObjectBase & C, Eigen::PlainObjectBase & B) { using Scalar = typename DerivedV::Scalar; const int TCOLS = DerivedT::ColsAtCompileTime; const int VCOLS = DerivedV::ColsAtCompileTime; const int ACOLS = TCOLS==Eigen::Dynamic?Eigen::Dynamic:TCOLS+1; const int ss = T.cols(); R.resize(T.rows(),1); C.resize(T.rows(),V.cols()); B.resize(T.rows(),T.cols()); for(int i = 0;i A(T.cols()+1,T.cols()+1); // Not sure if this .eval() is a good idea const auto Vi = V(T.row(i),igl::placeholders::all).eval(); A.topLeftCorner(T.cols(),T.cols()) = 2*(Vi*Vi.transpose()); A.block(0,T.cols(),T.cols(),1).setConstant(1); A.block(T.cols(),0,1,T.cols()).setConstant(1); A(T.cols(),T.cols()) = 0; Eigen::Matrix b(T.cols()+1,1); b.head(T.cols()) = (Vi.array().square().rowwise().sum()).eval(); b(T.cols()) = 1; // [B;λ] = A\b const auto x = (A.colPivHouseholderQr().solve(b)).eval(); B.row(i) = x.head(T.cols()); C.row(i) = B.row(i) * Vi; const Scalar lambda = x(T.cols()); R(i) = std::sqrt(lambda + C.row(i).squaredNorm()); } } #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh template void igl::circumradius, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::circumradius, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); template void igl::circumradius, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::circumradius, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::circumradius, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::circumradius, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::circumradius, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::circumradius, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::circumradius, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::circumradius, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); #endif