123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- // This file is part of libigl, a simple c++ geometry processing library.
- //
- // Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
- //
- // 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 "qslim.h"
- #include "collapse_edge.h"
- #include "connect_boundary_to_infinity.h"
- #include "decimate.h"
- #include "edge_flaps.h"
- #include "is_edge_manifold.h"
- #include "max_faces_stopping_condition.h"
- #include "per_vertex_point_to_plane_quadrics.h"
- #include "qslim_optimal_collapse_edge_callbacks.h"
- #include "quadric_binary_plus_operator.h"
- #include "remove_unreferenced.h"
- #include "slice.h"
- #include "slice_mask.h"
- IGL_INLINE bool igl::qslim(
- const Eigen::MatrixXd & V,
- const Eigen::MatrixXi & F,
- const size_t max_m,
- Eigen::MatrixXd & U,
- Eigen::MatrixXi & G,
- Eigen::VectorXi & J,
- Eigen::VectorXi & I)
- {
- using namespace igl;
- // Original number of faces
- const int orig_m = F.rows();
- // Tracking number of faces
- int m = F.rows();
- typedef Eigen::MatrixXd DerivedV;
- typedef Eigen::MatrixXi DerivedF;
- DerivedV VO;
- DerivedF FO;
- igl::connect_boundary_to_infinity(V,F,VO,FO);
- // decimate will not work correctly on non-edge-manifold meshes. By extension
- // this includes meshes with non-manifold vertices on the boundary since these
- // will create a non-manifold edge when connected to infinity.
- if(!is_edge_manifold(FO))
- {
- return false;
- }
- Eigen::VectorXi EMAP;
- Eigen::MatrixXi E,EF,EI;
- edge_flaps(FO,E,EMAP,EF,EI);
- // Quadrics per vertex
- typedef std::tuple<Eigen::MatrixXd,Eigen::RowVectorXd,double> Quadric;
- std::vector<Quadric> quadrics;
- per_vertex_point_to_plane_quadrics(VO,FO,EMAP,EF,EI,quadrics);
- // State variables keeping track of edge we just collapsed
- int v1 = -1;
- int v2 = -1;
- // Callbacks for computing and updating metric
- std::function<void(
- const int e,
- const Eigen::MatrixXd &,
- const Eigen::MatrixXi &,
- const Eigen::MatrixXi &,
- const Eigen::VectorXi &,
- const Eigen::MatrixXi &,
- const Eigen::MatrixXi &,
- double &,
- Eigen::RowVectorXd &)> cost_and_placement;
- std::function<bool(
- const Eigen::MatrixXd & ,/*V*/
- const Eigen::MatrixXi & ,/*F*/
- const Eigen::MatrixXi & ,/*E*/
- const Eigen::VectorXi & ,/*EMAP*/
- const Eigen::MatrixXi & ,/*EF*/
- const Eigen::MatrixXi & ,/*EI*/
- const std::set<std::pair<double,int> > & ,/*Q*/
- const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
- const Eigen::MatrixXd & ,/*C*/
- const int /*e*/
- )> pre_collapse;
- std::function<void(
- const Eigen::MatrixXd & , /*V*/
- const Eigen::MatrixXi & , /*F*/
- const Eigen::MatrixXi & , /*E*/
- const Eigen::VectorXi & ,/*EMAP*/
- const Eigen::MatrixXi & , /*EF*/
- const Eigen::MatrixXi & , /*EI*/
- const std::set<std::pair<double,int> > & , /*Q*/
- const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/
- const Eigen::MatrixXd & , /*C*/
- const int , /*e*/
- const int , /*e1*/
- const int , /*e2*/
- const int , /*f1*/
- const int , /*f2*/
- const bool /*collapsed*/
- )> post_collapse;
- qslim_optimal_collapse_edge_callbacks(
- E,quadrics,v1,v2, cost_and_placement, pre_collapse,post_collapse);
- // Call to greedy decimator
- bool ret = decimate(
- VO, FO,
- cost_and_placement,
- max_faces_stopping_condition(m,orig_m,max_m),
- pre_collapse,
- post_collapse,
- E, EMAP, EF, EI,
- U, G, J, I);
- // Remove phony boundary faces and clean up
- const Eigen::Array<bool,Eigen::Dynamic,1> keep = (J.array()<orig_m);
- igl::slice_mask(Eigen::MatrixXi(G),keep,1,G);
- igl::slice_mask(Eigen::VectorXi(J),keep,1,J);
- Eigen::VectorXi _1,I2;
- igl::remove_unreferenced(Eigen::MatrixXd(U),Eigen::MatrixXi(G),U,G,_1,I2);
- igl::slice(Eigen::VectorXi(I),I2,1,I);
- return ret;
- }
|