Browse Source

decimation example

Former-commit-id: 33140c7652706daa84877c2c49557ee5d19f01dd
Alec Jacobson 10 years ago
parent
commit
51a2586e3a
2 changed files with 144 additions and 0 deletions
  1. 11 0
      tutorial/703_Decimation/CMakeLists.txt
  2. 133 0
      tutorial/703_Decimation/main.cpp

+ 11 - 0
tutorial/703_Decimation/CMakeLists.txt

@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 2.6)
+project(703_Decimation)
+
+include("../CMakeLists.shared")
+
+set(SOURCES
+${PROJECT_SOURCE_DIR}/main.cpp
+)
+
+add_executable(${PROJECT_NAME}_bin ${SOURCES} ${SHARED_SOURCES})
+target_link_libraries(${PROJECT_NAME}_bin ${SHARED_LIBRARIES})

+ 133 - 0
tutorial/703_Decimation/main.cpp

@@ -0,0 +1,133 @@
+#include <igl/collapse_edge.h>
+#include <igl/edge_flaps.h>
+#include <igl/read_triangle_mesh.h>
+#include <igl/circulation.h>
+#include <igl/Viewer/viewer.h>
+#include <Eigen/Core>
+#include <iostream>
+#include <set>
+
+int main(int argc, char * argv[])
+{
+  using namespace std;
+  using namespace Eigen;
+  using namespace igl;
+  cout<<"Usage: ./progressive_hulls [filename.(off|obj|ply)]"<<endl;
+  cout<<"  [space]  toggle animation."<<endl;
+  cout<<"  'r'  reset."<<endl;
+  // Load a closed manifold mesh
+  string filename("../shared/fertility.off");
+  if(argc>=2)
+  {
+    filename = argv[1];
+  }
+  MatrixXd V,OV;
+  MatrixXi F,OF;
+  read_triangle_mesh(filename,OV,OF);
+
+  igl::Viewer viewer;
+
+  // Prepare array-based edge data structures and priority queue
+  VectorXi EMAP;
+  MatrixXi E,EF,EI;
+  typedef std::set<std::pair<double,int> > PriorityQueue;
+  PriorityQueue Q;
+  std::vector<PriorityQueue::iterator > Qit;
+  // If an edge were collapsed, we'd collapse it to these points:
+  MatrixXd C;
+  int num_collapsed;
+
+  // Function for computing cost of collapsing edge (lenght) and placement
+  // (midpoint)
+  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,
+    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)));
+  };
+
+
+  // Function to reset original mesh and data structures
+  const auto & reset = [&]()
+  {
+    F = OF;
+    V = OV;
+    edge_flaps(F,E,EMAP,EF,EI);
+    Qit.resize(E.rows());
+
+    C.resize(E.rows(),V.cols());
+    VectorXd costs(E.rows());
+    for(int e = 0;e<E.rows();e++)
+    {
+      double cost = e;
+      RowVectorXd p(1,3);
+      shortest_edge_and_midpoint(e,V,F,E,EMAP,EF,EI,cost,p);
+      C.row(e) = p;
+      Qit[e] = Q.insert(std::pair<double,int>(cost,e)).first;
+    }
+    num_collapsed = 0;
+    viewer.data.clear();
+    viewer.data.set_mesh(V,F);
+    viewer.data.set_face_based(true);
+  };
+
+  const auto &pre_draw = [&](igl::Viewer & viewer)->bool
+  {
+    // If animating then collapse 10% of edges
+    if(viewer.core.is_animating && !Q.empty())
+    {
+      bool something_collapsed = false;
+      // collapse edge 
+      const int max_iter = std::ceil(0.01*Q.size());
+      for(int j = 0;j<max_iter;j++)
+      {
+        if(!collapse_edge(shortest_edge_and_midpoint,V,F,E,EMAP,EF,EI,Q,Qit,C))
+        {
+          break;
+        }
+        something_collapsed = true;
+        num_collapsed++;
+      }
+
+      if(something_collapsed)
+      {
+        viewer.data.clear();
+        viewer.data.set_mesh(V,F);
+        viewer.data.set_face_based(true);
+      }
+    }
+    return false;
+  };
+
+  const auto &key_down = 
+    [&](igl::Viewer &viewer,unsigned char key,int mod)->bool
+  {
+    switch(key)
+    {
+      case ' ':
+        viewer.core.is_animating ^= 1;
+        break;
+      case 'R':
+      case 'r':
+        reset();
+        break;
+      default:
+        return false;
+    }
+    return true;
+  };
+
+  reset();
+  viewer.core.is_animating = true;
+  viewer.callback_key_down = key_down;
+  viewer.callback_pre_draw = pre_draw;
+  return viewer.launch();
+}