Browse Source

simplify polyhedron

Former-commit-id: 02a3acc726d746b21e45eff74c9189686b5d98a3
Alec Jacobson 9 years ago
parent
commit
4123794f61
2 changed files with 138 additions and 0 deletions
  1. 101 0
      include/igl/simplify_polyhedron.cpp
  2. 37 0
      include/igl/simplify_polyhedron.h

+ 101 - 0
include/igl/simplify_polyhedron.cpp

@@ -0,0 +1,101 @@
+// 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 "simplify_polyhedron.h"
+#include "decimate.h"
+#include "circulation.h"
+#include "per_face_normals.h"
+#include "infinite_cost_stopping_condition.h"
+#include <functional>
+
+IGL_INLINE void igl::simplify_polyhedron(
+  const Eigen::MatrixXd & OV,
+  const Eigen::MatrixXi & OF,
+  Eigen::MatrixXd & V,
+  Eigen::MatrixXi & F,
+  Eigen::VectorXi & J)
+{
+  assert(false && "This is incorrect. In all but simple cases, this could introduce self-intersections");
+  // TODO: to generalize to non-manifold and open meshes, the cost should be 0
+  // if moving the vertex kept all incident faces in their original planes and
+  // kept all incident boundary edges on their original lines.
+
+  Eigen::MatrixXd N;
+  // Function for computing cost of collapsing edge (0 if at least one
+  // direction doesn't change pointset, inf otherwise) and placement (in lowest
+  // cost direction).
+  const auto & perfect= [&N](
+    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)
+  {
+    // Function for ocmputing cost (0 or inf) of collapsing edge by placing
+    // vertex at `positive` end of edge.
+    const auto & perfect_directed = [&N](
+      const int e,
+      const bool positive,
+      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)
+    {
+      const auto vi = E(e,positive);
+      const auto vj = E(e,!positive);
+      p = V.row(vj);
+      std::vector<int> faces = igl::circulation(e,positive,F,E,EMAP,EF,EI);
+      assert(faces.size() >= 2);
+      const Eigen::RowVectorXd nfront = N.row(faces.front());
+      const Eigen::RowVectorXd nback = N.row(faces.back());
+      // loop around faces incident on vi, beginning by matching normals to
+      // front, then allow one switch to back normal
+      bool matching_front = true;
+      cost = 0;
+      for(auto f : faces)
+      {
+        const Eigen::RowVectorXd nf = N.row(f);
+        const double epsilon = 1e-10;
+        if(matching_front && (nf-nfront).norm()>epsilon)
+        {
+          matching_front = false;
+        }
+        if(!matching_front && (nf-nback).norm()>epsilon)
+        {
+          cost = std::numeric_limits<double>::infinity();
+          break;
+        }
+      }
+    }; 
+    p.resize(3);
+    double cost0, cost1;
+    Eigen::RowVectorXd p0, p1;
+    perfect_directed(e,false,V,F,E,EMAP,EF,EI,cost0,p0);
+    perfect_directed(e,true,V,F,E,EMAP,EF,EI,cost1,p1);
+    if(cost0 < cost1)
+    {
+      cost = cost0;
+      p = p0;
+    }else
+    {
+      cost = cost1;
+      p = p1;
+    }
+  };
+  igl::per_face_normals(OV,OF,N);
+  igl::decimate(
+    OV,OF,perfect,igl::infinite_cost_stopping_condition(perfect),V,F,J);
+}
+

+ 37 - 0
include/igl/simplify_polyhedron.h

@@ -0,0 +1,37 @@
+// 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/.
+#ifndef IGL_SIMPLIFY_POLYHEDRON_H
+#define IGL_SIMPLIFY_POLYHEDRON_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+namespace igl
+{
+  // Simplify a polyhedron represented as a triangle mesh (OV,OF) by collapsing
+  // any edge that doesn't contribute to defining surface's pointset. This
+  // _would_ also make sense for open and non-manifold meshes, but the current
+  // implementation only works with closed manifold surfaces with well defined
+  // triangle normals.
+  //
+  // Inputs:
+  //   OV  #OV by 3 list of input mesh vertex positions
+  //   OF  #OF by 3 list of input mesh triangle indices into OV
+  // Outputs:
+  //   V  #V by 3 list of output mesh vertex positions
+  //   F  #F by 3 list of input mesh triangle indices into V
+  //   J  #F list of indices into OF of birth parents
+  IGL_INLINE void simplify_polyhedron(
+    const Eigen::MatrixXd & OV,
+    const Eigen::MatrixXi & OF,
+    Eigen::MatrixXd & V,
+    Eigen::MatrixXi & F,
+    Eigen::VectorXi & J);
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "simplify_polyhedron.cpp"
+#endif
+#endif