Sfoglia il codice sorgente

Added dedicated isolines function

Former-commit-id: 64b4e40a4b929b75b90cb31fec6d20cad4fbec52
Oded Stein 7 anni fa
parent
commit
c03f412f8a

+ 117 - 0
include/igl/isolines.cpp

@@ -0,0 +1,117 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2017 Oded Stein <oded.stein@columbia.edu>
+//
+// 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 "isolines.h"
+
+#include <vector>
+#include <array>
+#include <iostream>
+
+#include "sort.h"
+#include "remove_duplicate_vertices.h"
+
+
+template <typename DerivedV,
+typename DerivedF,
+typename DerivedZ,
+typename DerivedIsoV,
+typename DerivedIsoE>
+IGL_INLINE void igl::isolines(
+                              const Eigen::MatrixBase<DerivedV>& V,
+                              const Eigen::MatrixBase<DerivedF>& F,
+                              const Eigen::MatrixBase<DerivedZ>& z,
+                              const int n,
+                              Eigen::PlainObjectBase<DerivedIsoV>& isoV,
+                              Eigen::PlainObjectBase<DerivedIsoE>& isoE)
+{
+    //Constants
+    const int dim = V.cols();
+    assert(dim==2 || dim==3);
+    const int nVerts = V.rows();
+    assert(z.rows() == nVerts &&
+           "There must be as many function entries as vertices");
+    const int nFaces = F.rows();
+    const int np1 = n+1;
+    const double min = z.minCoeff(), max = z.maxCoeff();
+    
+    
+    //Following http://www.alecjacobson.com/weblog/?p=2529
+    typedef typename DerivedZ::Scalar Scalar;
+    typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1> Vec;
+    Vec iso(np1);
+    for(int i=0; i<np1; ++i)
+        iso(i) = Scalar(i)/Scalar(n)*(max-min) + min;
+    
+    typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> Matrix;
+    std::array<Matrix,3> t{{Matrix(nFaces, np1),
+        Matrix(nFaces, np1), Matrix(nFaces, np1)}};
+    for(int i=0; i<nFaces; ++i) {
+        for(int k=0; k<3; ++k) {
+            const Scalar z1=z(F(i,k)), z2=z(F(i,(k+1)%3));
+            for(int j=0; j<np1; ++j) {
+                t[k](i,j) = (iso(j)-z1) / (z2-z1);
+                if(t[k](i,j)<0 || t[k](i,j)>1)
+                    t[k](i,j) = std::numeric_limits<Scalar>::quiet_NaN();
+            }
+        }
+    }
+    
+    std::array<std::vector<int>,3> Fij, Iij;
+    for(int i=0; i<nFaces; ++i) {
+        for(int j=0; j<np1; ++j) {
+            for(int k=0; k<3; ++k) {
+                const int kp1=(k+1)%3, kp2=(k+2)%3;
+                if(std::isfinite(t[kp1](i,j)) && std::isfinite(t[kp2](i,j))) {
+                    Fij[k].push_back(i);
+                    Iij[k].push_back(j);
+                }
+            }
+        }
+    }
+    
+    const int K = Fij[0].size()+Fij[1].size()+Fij[2].size();
+    isoV.resize(2*K, dim);
+    int b = 0;
+    for(int k=0; k<3; ++k) {
+        const int kp1=(k+1)%3, kp2=(k+2)%3;
+        for(int i=0; i<Fij[k].size(); ++i) {
+            isoV.row(b+i) = (1.-t[kp1](Fij[k][i],Iij[k][i]))*
+            V.row(F(Fij[k][i],kp1)) +
+            t[kp1](Fij[k][i],Iij[k][i])*V.row(F(Fij[k][i],kp2));
+            isoV.row(K+b+i) = (1.-t[kp2](Fij[k][i],Iij[k][i]))*
+            V.row(F(Fij[k][i],kp2)) +
+            t[kp2](Fij[k][i],Iij[k][i])*V.row(F(Fij[k][i],k));
+        }
+        b += Fij[k].size();
+    }
+    
+    isoE.resize(K,2);
+    for(int i=0; i<K; ++i)
+        isoE.row(i) << i, K+i;
+    
+    
+    //Remove double entries
+    typedef typename DerivedIsoV::Scalar LScalar;
+    typedef typename DerivedIsoE::Scalar LInt;
+    typedef Eigen::Matrix<LInt, Eigen::Dynamic, 1> LIVec;
+    typedef Eigen::Matrix<LScalar, Eigen::Dynamic, Eigen::Dynamic> LMat;
+    typedef Eigen::Matrix<LInt, Eigen::Dynamic, Eigen::Dynamic> LIMat;
+    LIVec dummy1, dummy2;
+    igl::remove_duplicate_vertices(LMat(isoV), LIMat(isoE),
+                                   1e-12, isoV, dummy1, dummy2, isoE);
+    
+}
+
+
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template instantiation
+template void igl::isolines<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, int const, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > &, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > &);
+#endif
+

+ 52 - 0
include/igl/isolines.h

@@ -0,0 +1,52 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2017 Oded Stein <oded.stein@columbia.edu>
+//
+// 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_ISOLINES_H
+#define IGL_ISOLINES_H
+#include "igl_inline.h"
+
+#include <Eigen/Dense>
+#include <Eigen/Sparse>
+
+
+namespace igl
+{
+    // Constructs isolines for a function z given on a mesh (V,F)
+    //
+    //
+    // Inputs:
+    //   V  #V by dim list of mesh vertex positions
+    //   F  #F by 3 list of mesh faces (must be triangles)
+    //   z  #V by 1 list of function values ecaluated at vertices
+    //   n  the number of desired isolines
+    // Outputs:
+    //   isoV  #isoV by dim list of isoline vertex positions
+    //   isoE  #isoE by dim list of isoline edge positions
+    //
+    //
+    
+    template <typename DerivedV,
+    typename DerivedF,
+    typename DerivedZ,
+    typename DerivedIsoV,
+    typename DerivedIsoE>
+    IGL_INLINE void isolines(
+                             const Eigen::MatrixBase<DerivedV>& V,
+                             const Eigen::MatrixBase<DerivedF>& F,
+                             const Eigen::MatrixBase<DerivedZ>& z,
+                             const int n,
+                             Eigen::PlainObjectBase<DerivedIsoV>& isoV,
+                             Eigen::PlainObjectBase<DerivedIsoE>& isoE);
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "isolines.cpp"
+#endif
+
+#endif

+ 0 - 90
tutorial/712_DataSmoothing/isolines.h

@@ -1,90 +0,0 @@
-
-#include <vector>
-#include <limits>
-#include <stdlib.h>
-
-#include <igl/remove_unreferenced.h>
-
-
-static void isolines(const Eigen::MatrixXd& V,
-    const Eigen::MatrixXi& F,
-    const Eigen::VectorXd& z,
-    const int grads,
-    Eigen::MatrixXd& isoV,
-    Eigen::MatrixXi& isoE)
-{
-    const double min = z.minCoeff(), max = z.maxCoeff();
-
-    //Following http://www.alecjacobson.com/weblog/?p=2529
-    Eigen::VectorXd iso(grads+1);
-    for(int i=0; i<iso.size(); ++i)
-        iso(i) = double(i)/double(grads)*(max-min) + min;
-
-    Eigen::MatrixXd t12(F.rows(), iso.size()), t23(F.rows(), iso.size()),
-        t31(F.rows(), iso.size());
-    for(int i=0; i<t12.rows(); ++i) {
-        const double z1=z(F(i,0)), z2=z(F(i,1)), z3=z(F(i,2));
-        const double s12 = z2-z1;
-        const double s23 = z3-z2;
-        const double s31 = z1-z3;
-        for(int j=0; j<t12.cols(); ++j) {
-            t12(i,j) = (iso(j)-z1) / s12;
-            t23(i,j) = (iso(j)-z2) / s23;
-            t31(i,j) = (iso(j)-z3) / s31;
-            if(t12(i,j)<0 || t12(i,j)>1)
-                t12(i,j) = std::numeric_limits<double>::quiet_NaN();
-            if(t23(i,j)<0 || t23(i,j)>1)
-                t23(i,j) = std::numeric_limits<double>::quiet_NaN();
-            if(t31(i,j)<0 || t31(i,j)>1)
-                t31(i,j) = std::numeric_limits<double>::quiet_NaN();
-        }
-    }
-
-    std::vector<int> F12, F23, F31, I12, I23, I31;
-    for(int i=0; i<t12.rows(); ++i) {
-        for(int j=0; j<t12.cols(); ++j) {
-            if(std::isfinite(t23(i,j)) && std::isfinite(t31(i,j))) {
-                F12.push_back(i);
-                I12.push_back(j);
-            }
-            if(std::isfinite(t31(i,j)) && std::isfinite(t12(i,j))) {
-                F23.push_back(i);
-                I23.push_back(j);
-            }
-            if(std::isfinite(t12(i,j)) && std::isfinite(t23(i,j))) {
-                F31.push_back(i);
-                I31.push_back(j);
-            }
-        }
-    }
-
-    const int K = F12.size()+F23.size()+F31.size();
-    isoV.resize(2*K, 3);
-    int b = 0;
-    for(int i=0; i<F12.size(); ++i) {
-        isoV.row(b+i) = (1.-t23(F12[i],I12[i]))*V.row(F(F12[i],1))
-            + t23(F12[i],I12[i])*V.row(F(F12[i],2));
-        isoV.row(K+b+i) = (1.-t31(F12[i],I12[i]))*V.row(F(F12[i],2))
-            + t31(F12[i],I12[i])*V.row(F(F12[i],0));
-    }
-    b += F12.size();
-    for(int i=0; i<F23.size(); ++i) {
-        isoV.row(b+i) = (1.-t31(F23[i],I23[i]))*V.row(F(F23[i],2))
-            + t31(F23[i],I23[i])*V.row(F(F23[i],0));
-        isoV.row(K+b+i) = (1.-t12(F23[i],I23[i]))*V.row(F(F23[i],0))
-            + t12(F23[i],I23[i])*V.row(F(F23[i],1));
-    }
-    b += F23.size();
-    for(int i=0; i<F31.size(); ++i) {
-        isoV.row(b+i) = (1.-t12(F31[i],I31[i]))*V.row(F(F31[i],0))
-            + t12(F31[i],I31[i])*V.row(F(F31[i],1));
-        isoV.row(K+b+i) = (1.-t23(F31[i],I31[i]))*V.row(F(F31[i],1))
-            + t23(F31[i],I31[i])*V.row(F(F31[i],2));
-    }
-
-    isoE.resize(K,2);
-    for(int i=0; i<K; ++i)
-        isoE.row(i) << i, K+i;
-
-}
-

+ 2 - 2
tutorial/712_DataSmoothing/main.cpp

@@ -18,7 +18,7 @@
 
 #include "tutorial_shared_path.h"
 
-#include "isolines.h"
+#include <igl/isolines.h>
 
 
 int main(int argc, char * argv[])
@@ -90,7 +90,7 @@ int main(int argc, char * argv[])
         Eigen::MatrixXd isoV;
         Eigen::MatrixXi isoE;
         if(key!='2')
-            isolines(V, F, *z, 30, isoV, isoE);
+            igl::isolines(V, F, *z, 30, isoV, isoE);
         viewer.data.set_edges(isoV,isoE,Eigen::RowVector3d(0,0,0));
         Eigen::MatrixXd colors;
         igl::jet(*z, true, colors);