123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- // This file is part of libigl, a simple c++ geometry processing library.
- //
- // Copyright (C) 2015 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 "decimate.h"
- #include "collapse_edge.h"
- #include "edge_flaps.h"
- #include "remove_unreferenced.h"
- #include "max_faces_stopping_condition.h"
- #include <iostream>
- IGL_INLINE bool igl::decimate(
- const Eigen::MatrixXd & V,
- const Eigen::MatrixXi & F,
- const size_t max_m,
- Eigen::MatrixXd & U,
- Eigen::MatrixXi & G,
- Eigen::VectorXi & J)
- {
- int m = F.rows();
- const auto & shortest_edge_and_midpoint = [](
- const int e,
- const Eigen::MatrixXd & V,
- const Eigen::MatrixXi & /*F*/,
- const Eigen::MatrixXi & E,
- const Eigen::VectorXi & /*EMAP*/,
- const Eigen::MatrixXi & /*EF*/,
- const Eigen::MatrixXi & /*EI*/,
- double & cost,
- Eigen::RowVectorXd & p)
- {
- cost = (V.row(E(e,0))-V.row(E(e,1))).norm();
- p = 0.5*(V.row(E(e,0))+V.row(E(e,1)));
- };
- return decimate(
- V,
- F,
- shortest_edge_and_midpoint,
- max_faces_stopping_condition(m,max_m),
- U,
- G,
- J);
- }
- IGL_INLINE bool igl::decimate(
- const Eigen::MatrixXd & OV,
- const Eigen::MatrixXi & OF,
- const std::function<void(
- const int,
- const Eigen::MatrixXd &,
- const Eigen::MatrixXi &,
- const Eigen::MatrixXi &,
- const Eigen::VectorXi &,
- const Eigen::MatrixXi &,
- const Eigen::MatrixXi &,
- double &,
- Eigen::RowVectorXd &)> & cost_and_placement,
- const std::function<bool(
- const Eigen::MatrixXd &,
- const Eigen::MatrixXi &,
- const Eigen::MatrixXi &,
- const Eigen::VectorXi &,
- const Eigen::MatrixXi &,
- const Eigen::MatrixXi &,
- const std::set<std::pair<double,int> > &,
- const std::vector<std::set<std::pair<double,int> >::iterator > &,
- const Eigen::MatrixXd &,
- const int,
- const int,
- const int,
- const int,
- const int)> & stopping_condition,
- Eigen::MatrixXd & U,
- Eigen::MatrixXi & G,
- Eigen::VectorXi & J)
- {
- using namespace Eigen;
- using namespace std;
- // Working copies
- Eigen::MatrixXd V = OV;
- Eigen::MatrixXi F = OF;
- VectorXi EMAP;
- MatrixXi E,EF,EI;
- typedef std::set<std::pair<double,int> > PriorityQueue;
- PriorityQueue Q;
- std::vector<PriorityQueue::iterator > Qit;
- edge_flaps(F,E,EMAP,EF,EI);
- Qit.resize(E.rows());
- // If an edge were collapsed, we'd collapse it to these points:
- MatrixXd C(E.rows(),V.cols());
- for(int e = 0;e<E.rows();e++)
- {
- double cost = e;
- RowVectorXd p(1,3);
- cost_and_placement(e,V,F,E,EMAP,EF,EI,cost,p);
- C.row(e) = p;
- Qit[e] = Q.insert(std::pair<double,int>(cost,e)).first;
- }
- int prev_e = -1;
- bool clean_finish = false;
- while(true)
- {
- if(Q.empty())
- {
- break;
- }
- if(Q.begin()->first == std::numeric_limits<double>::infinity())
- {
- // min cost edge is infinite cost
- break;
- }
- int e,e1,e2,f1,f2;
- if(collapse_edge(cost_and_placement,V,F,E,EMAP,EF,EI,Q,Qit,C,e,e1,e2,f1,f2))
- {
- if(stopping_condition(V,F,E,EMAP,EF,EI,Q,Qit,C,e,e1,e2,f1,f2))
- {
- clean_finish = true;
- break;
- }
- }else
- {
- if(prev_e == e)
- {
- assert(false && "Edge collapse no progress... bad stopping condition?");
- break;
- }
- // Edge was not collapsed... must have been invalid. collapse_edge should
- // have updated its cost to inf... continue
- }
- prev_e = e;
- }
- // remove all IGL_COLLAPSE_EDGE_NULL faces
- MatrixXi F2(F.rows(),3);
- J.resize(F.rows());
- int m = 0;
- for(int f = 0;f<F.rows();f++)
- {
- if(
- F(f,0) != IGL_COLLAPSE_EDGE_NULL ||
- F(f,1) != IGL_COLLAPSE_EDGE_NULL ||
- F(f,2) != IGL_COLLAPSE_EDGE_NULL)
- {
- F2.row(m) = F.row(f);
- J(m) = f;
- m++;
- }
- }
- F2.conservativeResize(m,F2.cols());
- J.conservativeResize(m);
- VectorXi _1;
- remove_unreferenced(V,F2,U,G,_1);
- return clean_finish;
- }
|