Sfoglia il codice sorgente

ramer douglas peucker line simplification

Former-commit-id: 0b6214100d7ee42cc1b953cdeb56575591454060
Alec Jacobson 8 anni fa
parent
commit
cd47c51ffa

+ 67 - 0
include/igl/ramer_douglas_peucker.cpp

@@ -0,0 +1,67 @@
+#include "ramer_douglas_peucker.h"
+
+#include "find.h"
+#include "project_to_line.h"
+#include "EPS.h"
+#include "slice_mask.h"
+template <typename DerivedP, typename DerivedS, typename DerivedJ>
+IGL_INLINE void igl::ramer_douglas_peucker(
+  const Eigen::MatrixBase<DerivedP> & P,
+  const typename DerivedP::Scalar tol,
+  Eigen::PlainObjectBase<DerivedS> & S,
+  Eigen::PlainObjectBase<DerivedJ> & J)
+{
+  typedef typename DerivedP::Scalar Scalar;
+  // number of vertices
+  const int n = P.rows();
+  // Trivial base case
+  if(n <= 1)
+  {
+    J = DerivedJ::Zero(n);
+    S = P;
+    return;
+  }
+  // number of dimensions
+  const int m = P.cols();
+  Eigen::Array<bool,Eigen::Dynamic,1> I =
+    Eigen::Array<bool,Eigen::Dynamic,1>::Constant(n,1,true);
+  const auto stol = tol*tol;
+  std::function<void(const int,const int)> simplify;
+  simplify = [&I,&P,&stol,&simplify](const int ixs, const int ixe)->void
+  {
+    assert(ixe>ixs);
+    Scalar sdmax = 0;
+    typename Eigen::Matrix<Scalar,Eigen::Dynamic,1>::Index ixc = -1;
+    if((ixe-ixs)>1)
+    {
+      Scalar sdes = (P.row(ixe)-P.row(ixs)).squaredNorm();
+      Eigen::Matrix<Scalar,Eigen::Dynamic,1> sD;
+      const auto & Pblock = P.block(ixs+1,0,((ixe+1)-ixs)-2,P.cols());
+      if(sdes<=EPS<Scalar>())
+      {
+        sD = (Pblock.rowwise()-P.row(ixs)).rowwise().squaredNorm();
+      }else
+      {
+        Eigen::Matrix<Scalar,Eigen::Dynamic,1> T;
+        project_to_line(Pblock,P.row(ixs).eval(),P.row(ixe).eval(),T,sD);
+      }
+      sdmax = sD.maxCoeff(&ixc);
+      // Index full P
+      ixc = ixc+(ixs+1);
+    }
+    if(sdmax <= stol)
+    {
+      if(ixs != ixe-1)
+      {
+        I.block(ixs+1,0,((ixe+1)-ixs)-2,1).setConstant(false);
+      }
+    }else
+    {
+      simplify(ixs,ixc);
+      simplify(ixc,ixe);
+    }
+  };
+  simplify(0,n-1);
+  slice_mask(P,I,1,S);
+  find(I,J);
+}

+ 26 - 0
include/igl/ramer_douglas_peucker.h

@@ -0,0 +1,26 @@
+#ifndef IGL_RAMER_DOUGLAS_PEUCKER_H
+#define IGL_RAMER_DOUGLAS_PEUCKER_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+namespace igl
+{
+  // Ramer-Douglas-Peucker piecewise-linear curve simplification.
+  //
+  // Inputs:
+  //   P  #P by dim ordered list of vertices along the curve
+  //   tol  tolerance (maximal euclidean distance allowed between the new line
+  //     and a vertex)
+  // Outputs:
+  //   S  #S by dim ordered list of points along the curve
+  //   J  #S list of indices into P so that S = P(J,:)
+  template <typename DerivedP, typename DerivedS, typename DerivedJ>
+  IGL_INLINE void ramer_douglas_peucker(
+    const Eigen::MatrixBase<DerivedP> & P,
+    const typename DerivedP::Scalar tol,
+    Eigen::PlainObjectBase<DerivedS> & S,
+    Eigen::PlainObjectBase<DerivedJ> & J);
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "ramer_douglas_peucker.cpp"
+#endif
+#endif