IGL_INLINE bool igl::copyleft::boolean::mesh_boolean( const Eigen::PlainObjectBase<DerivedVA> & VA, const Eigen::PlainObjectBase<DerivedFA> & FA, const Eigen::PlainObjectBase<DerivedVB> & VB, const Eigen::PlainObjectBase<DerivedFB> & FB, const WindingNumberOp& wind_num_op, const KeepFunc& keep, const ResolveFunc& resolve_fun, Eigen::PlainObjectBase<DerivedVC > & VC, Eigen::PlainObjectBase<DerivedFC > & FC, Eigen::PlainObjectBase<DerivedJ > & J) { #ifdef MESH_BOOLEAN_TIMING const auto & tictoc = []() -> double { static double t_start = igl::get_seconds(); double diff = igl::get_seconds()-t_start; t_start += diff; return diff; }; const auto log_time = [&](const std::string& label) -> void { std::cout << "mesh_boolean." << label << ": " << tictoc() << std::endl; }; tictoc(); #endif typedef typename DerivedVC::Scalar Scalar; //typedef typename DerivedFC::Scalar Index; typedef CGAL::Epeck Kernel; typedef Kernel::FT ExactScalar; typedef Eigen::Matrix<Scalar,Eigen::Dynamic,3> MatrixX3S; //typedef Eigen::Matrix<Index,Eigen::Dynamic,Eigen::Dynamic> MatrixXI; typedef Eigen::Matrix<typename DerivedJ::Scalar,Eigen::Dynamic,1> VectorXJ; // Generate combined mesh. typedef Eigen::Matrix< ExactScalar, Eigen::Dynamic, Eigen::Dynamic, DerivedVC::IsRowMajor> MatrixXES; MatrixXES V; DerivedFC F; VectorXJ CJ; { DerivedVA VV(VA.rows() + VB.rows(), 3); DerivedFC FF(FA.rows() + FB.rows(), 3); VV << VA, VB; FF << FA, FB.array() + VA.rows(); //// Handle annoying empty cases //if(VA.size()>0) //{ // VV<<VA; //} //if(VB.size()>0) //{ // VV<<VB; //} //if(FA.size()>0) //{ // FF<<FA; //} //if(FB.size()>0) //{ // FF<<FB.array()+VA.rows(); //} resolve_fun(VV, FF, V, F, CJ); } #ifdef MESH_BOOLEAN_TIMING log_time("resolve_self_intersection"); #endif // Compute winding numbers on each side of each facet. const size_t num_faces = F.rows(); Eigen::MatrixXi W; Eigen::VectorXi labels(num_faces); std::transform(CJ.data(), CJ.data()+CJ.size(), labels.data(), [&](int i) { return i<FA.rows() ? 0:1; }); bool valid = true; if (num_faces > 0) { valid = valid & igl::copyleft::cgal::propagate_winding_numbers(V, F, labels, W); } else { W.resize(0, 4); } assert((size_t)W.rows() == num_faces); if (W.cols() == 2) { assert(FB.rows() == 0); Eigen::MatrixXi W_tmp(num_faces, 4); W_tmp << W, Eigen::MatrixXi::Zero(num_faces, 2); W = W_tmp; } else { assert(W.cols() == 4); } #ifdef MESH_BOOLEAN_TIMING log_time("propagate_input_winding_number"); #endif // Compute resulting winding number. Eigen::MatrixXi Wr(num_faces, 2); for (size_t i=0; i<num_faces; i++) { Eigen::MatrixXi w_out(1,2), w_in(1,2); w_out << W(i,0), W(i,2); w_in << W(i,1), W(i,3); Wr(i,0) = wind_num_op(w_out); Wr(i,1) = wind_num_op(w_in); } #ifdef MESH_BOOLEAN_TIMING log_time("compute_output_winding_number"); #endif // Extract boundary separating inside from outside. auto index_to_signed_index = [&](size_t i, bool ori) -> int { return (i+1)*(ori?1:-1); }; //auto signed_index_to_index = [&](int i) -> size_t { // return abs(i) - 1; //}; std::vector<int> selected; for(size_t i=0; i<num_faces; i++) { auto should_keep = keep(Wr(i,0), Wr(i,1)); if (should_keep > 0) { selected.push_back(index_to_signed_index(i, true)); } else if (should_keep < 0) { selected.push_back(index_to_signed_index(i, false)); } } const size_t num_selected = selected.size(); DerivedFC kept_faces(num_selected, 3); DerivedJ kept_face_indices(num_selected, 1); for (size_t i=0; i<num_selected; i++) { size_t idx = abs(selected[i]) - 1; if (selected[i] > 0) { kept_faces.row(i) = F.row(idx); } else { kept_faces.row(i) = F.row(idx).reverse(); } kept_face_indices(i, 0) = CJ[idx]; } #ifdef MESH_BOOLEAN_TIMING log_time("extract_output"); #endif // Finally, remove duplicated faces and unreferenced vertices. { DerivedFC G; DerivedJ JJ; igl::resolve_duplicated_faces(kept_faces, G, JJ); igl::slice(kept_face_indices, JJ, 1, J); #ifdef DOUBLE_CHECK_EXACT_OUTPUT { // Sanity check on exact output. igl::copyleft::cgal::RemeshSelfIntersectionsParam params; params.detect_only = true; params.first_only = true; MatrixXES dummy_VV; DerivedFC dummy_FF, dummy_IF; Eigen::VectorXi dummy_J, dummy_IM; igl::copyleft::cgal::SelfIntersectMesh< Kernel, MatrixXES, DerivedFC, MatrixXES, DerivedFC, DerivedFC, Eigen::VectorXi, Eigen::VectorXi > checker(V, G, params, dummy_VV, dummy_FF, dummy_IF, dummy_J, dummy_IM); if (checker.count != 0) { throw "Self-intersection not fully resolved."; } } #endif MatrixX3S Vs(V.rows(), V.cols()); for (size_t i=0; i<(size_t)V.rows(); i++) { for (size_t j=0; j<(size_t)V.cols(); j++) { igl::copyleft::cgal::assign_scalar(V(i,j), Vs(i,j)); } } Eigen::VectorXi newIM; igl::remove_unreferenced(Vs,G,VC,FC,newIM); } #ifdef MESH_BOOLEAN_TIMING log_time("clean_up"); #endif return valid; }
void CKLDualInferenceMethod::update_alpha() { float64_t nlml_new=0; float64_t nlml_def=0; Map<MatrixXd> eigen_K(m_ktrtr.matrix, m_ktrtr.num_rows, m_ktrtr.num_cols); CDualVariationalGaussianLikelihood *lik= get_dual_variational_likelihood(); if (m_alpha.vlen == m_labels->get_num_labels()) { nlml_new=get_negative_log_marginal_likelihood_helper(); index_t len=m_labels->get_num_labels(); SGVector<float64_t> W_tmp(len); Map<VectorXd> eigen_W(W_tmp.vector, W_tmp.vlen); eigen_W.fill(0.5); SGVector<float64_t> sW_tmp(len); Map<VectorXd> eigen_sW(sW_tmp.vector, sW_tmp.vlen); eigen_sW=eigen_W.array().sqrt().matrix(); SGMatrix<float64_t> L_tmp=CMatrixOperations::get_choleksy(W_tmp, sW_tmp, m_ktrtr, CMath::exp(m_log_scale*2.0)); Map<MatrixXd> eigen_L(L_tmp.matrix, L_tmp.num_rows, L_tmp.num_cols); lik->set_dual_parameters(W_tmp, m_labels); //construct alpha SGVector<float64_t> alpha_tmp=lik->get_mu_dual_parameter(); Map<VectorXd> eigen_alpha(alpha_tmp.vector, alpha_tmp.vlen); eigen_alpha=-eigen_alpha; //construct mu SGVector<float64_t> mean=m_mean->get_mean_vector(m_features); Map<VectorXd> eigen_mean(mean.vector, mean.vlen); SGVector<float64_t> mu_tmp(len); Map<VectorXd> eigen_mu(mu_tmp.vector, mu_tmp.vlen); //mu=K*alpha+m eigen_mu=eigen_K*CMath::exp(m_log_scale*2.0)*eigen_alpha+eigen_mean; //construct s2 MatrixXd eigen_V=eigen_L.triangularView<Upper>().adjoint().solve(eigen_sW.asDiagonal()*eigen_K*CMath::exp(m_log_scale*2.0)); SGVector<float64_t> s2_tmp(len); Map<VectorXd> eigen_s2(s2_tmp.vector, s2_tmp.vlen); eigen_s2=(eigen_K.diagonal().array()*CMath::exp(m_log_scale*2.0)-(eigen_V.array().pow(2).colwise().sum().transpose())).abs().matrix(); lik->set_variational_distribution(mu_tmp, s2_tmp, m_labels); nlml_def=get_nlml_wrapper(alpha_tmp, mu_tmp, L_tmp); if (nlml_new<=nlml_def) { lik->set_dual_parameters(m_W, m_labels); lik->set_variational_distribution(m_mu, m_s2, m_labels); } } if (m_alpha.vlen != m_labels->get_num_labels() || nlml_def<nlml_new) { if(m_alpha.vlen != m_labels->get_num_labels()) m_alpha = SGVector<float64_t>(m_labels->get_num_labels()); index_t len=m_alpha.vlen; m_W=SGVector<float64_t>(len); for (index_t i=0; i<m_W.vlen; i++) m_W[i]=0.5; lik->set_dual_parameters(m_W, m_labels); m_sW=SGVector<float64_t>(len); m_mu=SGVector<float64_t>(len); m_s2=SGVector<float64_t>(len); m_Sigma=SGMatrix<float64_t>(len, len); m_Sigma.zero(); m_V=SGMatrix<float64_t>(len, len); } nlml_new=optimization(); lik->set_variational_distribution(m_mu, m_s2, m_labels); TParameter* s2_param=lik->m_parameters->get_parameter("sigma2"); m_dv=lik->get_variational_first_derivative(s2_param); TParameter* mu_param=lik->m_parameters->get_parameter("mu"); m_df=lik->get_variational_first_derivative(mu_param); }
IGL_INLINE void igl::copyleft::boolean::mesh_boolean( const Eigen::PlainObjectBase<DerivedVA> & VA, const Eigen::PlainObjectBase<DerivedFA> & FA, const Eigen::PlainObjectBase<DerivedVB> & VB, const Eigen::PlainObjectBase<DerivedFB> & FB, const WindingNumberOp& wind_num_op, const KeepFunc& keep, const ResolveFunc& resolve_fun, Eigen::PlainObjectBase<DerivedVC > & VC, Eigen::PlainObjectBase<DerivedFC > & FC, Eigen::PlainObjectBase<DerivedJ > & J) { typedef typename DerivedVC::Scalar Scalar; //typedef typename DerivedFC::Scalar Index; typedef CGAL::Epeck Kernel; typedef Kernel::FT ExactScalar; typedef Eigen::Matrix<Scalar,Eigen::Dynamic,3> MatrixX3S; //typedef Eigen::Matrix<Index,Eigen::Dynamic,Eigen::Dynamic> MatrixXI; typedef Eigen::Matrix<typename DerivedJ::Scalar,Eigen::Dynamic,1> VectorXJ; // Generate combined mesh. typedef Eigen::Matrix< ExactScalar, Eigen::Dynamic, Eigen::Dynamic, DerivedVC::IsRowMajor> MatrixXES; MatrixXES V; DerivedFC F; VectorXJ CJ; { DerivedVA VV(VA.rows() + VB.rows(), 3); DerivedFC FF(FA.rows() + FB.rows(), 3); VV << VA, VB; FF << FA, FB.array() + VA.rows(); //// Handle annoying empty cases //if(VA.size()>0) //{ // VV<<VA; //} //if(VB.size()>0) //{ // VV<<VB; //} //if(FA.size()>0) //{ // FF<<FA; //} //if(FB.size()>0) //{ // FF<<FB.array()+VA.rows(); //} resolve_fun(VV, FF, V, F, CJ); } // Compute winding numbers on each side of each facet. const size_t num_faces = F.rows(); Eigen::MatrixXi W; Eigen::VectorXi labels(num_faces); std::transform(CJ.data(), CJ.data()+CJ.size(), labels.data(), [&](int i) { return i<FA.rows() ? 0:1; }); igl::copyleft::cgal::propagate_winding_numbers(V, F, labels, W); assert((size_t)W.rows() == num_faces); if (W.cols() == 2) { assert(FB.rows() == 0); Eigen::MatrixXi W_tmp(num_faces, 4); W_tmp << W, Eigen::MatrixXi::Zero(num_faces, 2); W = W_tmp; } else { assert(W.cols() == 4); } // Compute resulting winding number. Eigen::MatrixXi Wr(num_faces, 2); for (size_t i=0; i<num_faces; i++) { Eigen::MatrixXi w_out(1,2), w_in(1,2); w_out << W(i,0), W(i,2); w_in << W(i,1), W(i,3); Wr(i,0) = wind_num_op(w_out); Wr(i,1) = wind_num_op(w_in); } // Extract boundary separating inside from outside. auto index_to_signed_index = [&](size_t i, bool ori) -> int{ return (i+1)*(ori?1:-1); }; //auto signed_index_to_index = [&](int i) -> size_t { // return abs(i) - 1; //}; std::vector<int> selected; for(size_t i=0; i<num_faces; i++) { auto should_keep = keep(Wr(i,0), Wr(i,1)); if (should_keep > 0) { selected.push_back(index_to_signed_index(i, true)); } else if (should_keep < 0) { selected.push_back(index_to_signed_index(i, false)); } } const size_t num_selected = selected.size(); DerivedFC kept_faces(num_selected, 3); DerivedJ kept_face_indices(num_selected, 1); for (size_t i=0; i<num_selected; i++) { size_t idx = abs(selected[i]) - 1; if (selected[i] > 0) { kept_faces.row(i) = F.row(idx); } else { kept_faces.row(i) = F.row(idx).reverse(); } kept_face_indices(i, 0) = CJ[idx]; } // Finally, remove duplicated faces and unreferenced vertices. { DerivedFC G; DerivedJ JJ; igl::resolve_duplicated_faces(kept_faces, G, JJ); igl::slice(kept_face_indices, JJ, 1, J); MatrixX3S Vs(V.rows(), V.cols()); for (size_t i=0; i<(size_t)V.rows(); i++) { for (size_t j=0; j<(size_t)V.cols(); j++) { igl::copyleft::cgal::assign_scalar(V(i,j), Vs(i,j)); } } Eigen::VectorXi newIM; igl::remove_unreferenced(Vs,G,VC,FC,newIM); } }