Browse Source

initial import igl_lib

dpanozzo 13 years ago
commit
6a75c9f30c
12 changed files with 566 additions and 0 deletions
  1. 79 0
      cotmatrix.h
  2. 92 0
      edgetopology.h
  3. 49 0
      ismanifold.h
  4. 41 0
      main.cpp
  5. 40 0
      read.h
  6. 54 0
      readOBJ.h
  7. 38 0
      readOFF.h
  8. 28 0
      readme.txt
  9. 47 0
      tt.h
  10. 34 0
      write.h
  11. 30 0
      writeOBJ.h
  12. 34 0
      writeOFF.h

+ 79 - 0
cotmatrix.h

@@ -0,0 +1,79 @@
+//
+//  IGL Lib - Simple C++ mesh library 
+//
+//  Copyright 2011, Daniele Panozzo. All rights reserved.
+
+#ifndef COTMATRIX_H
+#define COTMATRIX_H
+
+#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
+#include <Eigen/Dense>
+#include <Eigen/Sparse>
+
+
+namespace igl 
+{
+    void computeCotWeights(Eigen::Vector3d& v1, Eigen::Vector3d& v2, Eigen::Vector3d& v3, double& cotAlpha, double& cotBeta, double& cotGamma)
+    {
+        Eigen::Vector3d v12 = v2-v1;
+        Eigen::Vector3d v13 = v3-v1;
+        Eigen::Vector3d v23 = v3-v2;
+        
+        double halfArea = (v12.cross(v13)).norm();//squaredNorm();
+        
+        //improve numerical stability
+        const double cotTolerance = 1e-10;
+        if(halfArea < cotTolerance)
+        {
+            std::cout << "Cot weights are close to singular!" << std::endl;
+            halfArea = cotTolerance;
+        }
+        
+        cotAlpha = (v12.dot(v13)) / halfArea;
+        cotBeta =  (v23.dot(-v12)) / halfArea;
+        cotGamma = (-v23.dot(-v13)) / halfArea;
+    }
+    
+    void cotmatrix (Eigen::MatrixXd V, Eigen::MatrixXi F, Eigen::SparseMatrix<double>& L, bool cotan = true)
+    {
+        Eigen::DynamicSparseMatrix<double, Eigen::RowMajor> dyn_L (V.rows(), V.rows());
+        
+        for (unsigned i = 0; i < F.rows(); i++)
+        {
+            int vi1 = F(i,0);
+            int vi2 = F(i,1);
+            int vi3 = F(i,2);
+            
+            if (cotan)
+            {
+                Eigen::Vector3d v1 (V(vi1,0), V(vi1,1), V(vi1,2));
+                Eigen::Vector3d v2 (V(vi2,0), V(vi2,1), V(vi2,2));
+                Eigen::Vector3d v3 (V(vi3,0), V(vi3,1), V(vi3,2));
+                double cot_a, cot_b, cot_g;
+                computeCotWeights (v1, v2, v3, cot_a, cot_b, cot_g);
+                
+                dyn_L.coeffRef (vi1, vi2) += cot_g;
+                dyn_L.coeffRef (vi2, vi3) += cot_a;
+                dyn_L.coeffRef (vi3, vi1) += cot_b;
+            }
+            else
+            {
+                dyn_L.coeffRef (vi1, vi2) += 1.0;
+                dyn_L.coeffRef (vi2, vi3) += 1.0;
+                dyn_L.coeffRef (vi3, vi1) += 1.0;
+            }
+        }
+        
+        for (int k=0; k < dyn_L.outerSize(); ++k)
+        {
+            double tmp = 0.0f;
+            for (Eigen::DynamicSparseMatrix<double, Eigen::RowMajor>::InnerIterator it (dyn_L, k); it; ++it)
+                tmp += it.value ();
+            dyn_L.coeffRef (k,k) = -tmp;
+        }
+        
+        L = Eigen::SparseMatrix<double> (dyn_L);
+    }
+}
+
+#endif

+ 92 - 0
edgetopology.h

@@ -0,0 +1,92 @@
+//
+//  IGL Lib - Simple C++ mesh library 
+//
+//  Copyright 2011, Daniele Panozzo. All rights reserved.
+
+#ifndef EDGETOPOLOGY_H
+#define EDGETOPOLOGY_H
+
+#include <Eigen/Core>
+#include <string>
+
+namespace igl 
+{
+    // Initialize Edges and their topological relations
+    
+    // Output:
+    // E  : #Ex2, Stores the edge description as pair of indices to vertices
+    // FE : #Fx3, Stores the Triangle-Edge relation
+    // EF : #Ex2: Stores the Edge-Triangle relation (unsorted)
+
+    void edgetopology(Eigen::MatrixXd& V, Eigen::MatrixXi& F, 
+                      Eigen::MatrixXi& E, Eigen::MatrixXi& FE, Eigen::MatrixXi& EF)
+    {
+        assert(isManifold());
+        vector<vector<int> > ETT;
+        for(int f=0;f<F.rows();++f)
+            for (int i=0;i<3;++i)
+            {
+                // v1 v2 f vi 
+                int v1 = F(f,i);
+                int v2 = F(f,(i+1)%3);
+                if (v1 > v2) std::swap(v1,v2);
+                vector<int> r(4);
+                r[0] = v1; r[1] = v2;
+                r[2] = f;  r[3] = i;
+                ETT.push_back(r);
+            }
+        std::sort(ETT.begin(),ETT.end());
+        
+        // count the number of edges (assume manifoldness)
+        int En = 1; // the last is always counted
+        for(int i=0;i<ETT.size()-1;++i)
+            if (!((ETT[i][0] == ETT[i+1][0]) && (ETT[i][1] == ETT[i+1][1])))
+                ++En;
+        
+        E  = MatrixXi::Constant((int)(En),2,-1);
+        FE = MatrixXi::Constant((int)(F.rows()),3,-1);
+        EF = MatrixXi::Constant((int)(En),2,-1);
+        En = 0;
+        
+        for(int i=0;i<ETT.size();++i)
+        {
+            
+            for(int j=0;j<ETT[i].size();++j)
+            {
+                cerr << ETT[i][j] << "\t\t";
+            }
+            cerr << endl;
+        }
+        
+        
+        for(int i=0;i<ETT.size();++i)
+        {
+            if (i == ETT.size()-1 ||
+                !((ETT[i][0] == ETT[i+1][0]) && (ETT[i][1] == ETT[i+1][1]))
+                )
+            {
+                // Border edge
+                vector<int>& r1 = ETT[i];
+                E(En,0)         = r1[0];
+                E(En,1)         = r1[1];
+                EF(En,0)        = r1[2];
+                FE(r1[2],r1[3]) = En;
+            } 
+            else
+            {
+                vector<int>& r1 = ETT[i];
+                vector<int>& r2 = ETT[i+1];
+                E(En,0)         = r1[0];
+                E(En,1)         = r1[1];
+                EF(En,0)        = r1[2];
+                EF(En,1)        = r2[2];
+                FE(r1[2],r1[3]) = En;
+                FE(r2[2],r2[3]) = En;
+                ++i; // skip the next one
+            }
+            ++En;
+        }        
+    }
+}
+
+#endif

+ 49 - 0
ismanifold.h

@@ -0,0 +1,49 @@
+//
+//  IGL Lib - Simple C++ mesh library 
+//
+//  Copyright 2011, Daniele Panozzo. All rights reserved.
+
+#ifndef ISMANIFOLD_H
+#define ISMANIFOLD_H
+
+#include <Eigen/Core>
+#include <string>
+
+namespace igl 
+{
+    // check if the mesh is edge-manifold
+    bool isManifold(Eigen::MatrixXd& V, Eigen::MatrixXd& F)
+    {
+        vector<vector<int> > TTT;
+        for(int f=0;f<F.rows();++f)
+            for (int i=0;i<3;++i)
+            {
+                // v1 v2 f ei 
+                int v1 = F(f,i);
+                int v2 = F(f,(i+1)%3);
+                if (v1 > v2) std::swap(v1,v2);
+                vector<int> r(4);
+                r[0] = v1; r[1] = v2;
+                r[2] = f;  r[3] = i;
+                TTT.push_back(r);
+            }
+        std::sort(TTT.begin(),TTT.end());
+        TT = MatrixXi::Constant((int)(F.rows()),3,-1);
+        
+        for(int i=2;i<TTT.size();++i)
+        {
+            vector<int>& r1 = TTT[i-2];
+            vector<int>& r2 = TTT[i-1];
+            vector<int>& r3 = TTT[i];
+            if ( (r1[0] == r2[0] && r2[0] == r3[0]) 
+                && 
+                (r1[1] == r2[1] && r2[1] == r3[1]) )
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+}
+
+#endif

+ 41 - 0
main.cpp

@@ -0,0 +1,41 @@
+//
+//  IGL Lib - Simple C++ mesh library 
+//
+//  Copyright 2011, Daniele Panozzo. All rights reserved.
+
+// IMPORTANT DO NOT REMOVE OR MOVE
+#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET 
+
+#include <iostream>
+#include <string>
+#include <read.h>
+#include <write.h>
+#include <cotmatrix.h>
+
+using namespace std;
+
+int main (int argc, const char * argv[])
+{
+    Eigen::MatrixXd V;
+    Eigen::MatrixXi F;
+    igl::read(string(argv[1]),V,F);
+
+    std::cout << "Mesh loaded!\n";
+    cout << "Vertex Array:" << endl;
+    cout << V << endl;
+    cout << "-------------" << endl;
+    cout << "Face Array:" << endl;
+    cout << F << endl;
+    cout << "-------------" << endl;
+
+    cout << "CotMatrix:" << endl;
+    Eigen::SparseMatrix<double> L;
+    igl::cotmatrix(V,F,L);
+    cout << L << endl;
+    cout << "-------------" << endl;
+    
+    igl::write(string(argv[2]),V,F);
+    
+    return 0;
+}
+

+ 40 - 0
read.h

@@ -0,0 +1,40 @@
+//
+//  IGL Lib - Simple C++ mesh library 
+//
+//  Copyright 2011, Daniele Panozzo. All rights reserved.
+
+#ifndef READ_H
+#define READ_H
+
+#include <Eigen/Core>
+#include <string>
+
+#include <readOBJ.h>
+#include <readOFF.h>
+
+namespace igl 
+{
+    // read mesh from an ascii file with automatic detection of file format. supported: obj, off)
+    void read(std::string str, Eigen::MatrixXd& V, Eigen::MatrixXi& F)
+    {
+        const char* p;
+        for (p = str.c_str(); *p != '\0'; p++)
+            ;
+        while (*p != '.')
+            p--;
+        
+        if (!strcmp(p, ".obj") || !strcmp(p, ".OBJ"))
+        {
+            igl::readOBJ(str,V,F);
+            return;
+        }
+        
+        if (!strcmp(p, ".off") || !strcmp(p, ".OFF"))
+        {
+            igl::readOFF(str,V,F);
+            return;
+        }
+    }
+}
+
+#endif

+ 54 - 0
readOBJ.h

@@ -0,0 +1,54 @@
+//
+//  IGL Lib - Simple C++ mesh library 
+//
+//  Copyright 2011, Daniele Panozzo. All rights reserved.
+
+#ifndef READOBJ_H
+#define READOBJ_H
+
+#include <Eigen/Core>
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <vector>
+
+namespace igl 
+{
+    //! Read a mesh from an ascii obj file
+    void readOBJ(std::string str, Eigen::MatrixXd& V, Eigen::MatrixXi& F)
+    {
+        std::ifstream s(str.c_str());
+        std::vector<Eigen::Vector3d> Vtemp;
+        std::vector<Eigen::Vector3i> Ftemp;
+        char buf[1000];
+        while(!s.eof())
+        {
+            s.getline(buf, 1000);
+            if (buf[0] == 'v') // vertex coordinates found
+            {
+                char v;
+                double v1,v2,v3;
+                sscanf(buf, "%c %lf %lf %lf",&v,&v1,&v2,&v3);
+                Vtemp.push_back(Eigen::Vector3d(v1,v2,v3));
+            }
+            else if (buf[0] == 'f') // face description found
+            {
+                char v;
+                int v1,v2,v3;
+                sscanf(buf, "%c %d %d %d",&v,&v1,&v2,&v3);
+                Ftemp.push_back(Eigen::Vector3i(v1-1,v2-1,v3-1));
+            }
+        }
+        s.close();
+        
+        V = Eigen::MatrixXd(Vtemp.size(),3);
+        for(int i=0;i<V.rows();++i)
+            V.row(i) = Vtemp[i];
+        
+        F = Eigen::MatrixXi(Ftemp.size(),3);
+        for(int i=0;i<F.rows();++i)
+            F.row(i) = Ftemp[i];
+    }
+}
+
+#endif

+ 38 - 0
readOFF.h

@@ -0,0 +1,38 @@
+//
+//  IGL Lib - Simple C++ mesh library 
+//
+//  Copyright 2011, Daniele Panozzo. All rights reserved.
+
+#ifndef READOFF_H
+#define READOFF_H
+
+#include <Eigen/Core>
+#include <string>
+
+namespace igl 
+{
+    // read mesh from a ascii off file
+    void readOFF (std::string meshfile, Eigen::MatrixXd& V, Eigen::MatrixXi& F)
+    {
+        int vnum, fnum;
+        FILE *fp = fopen (meshfile.c_str(), "r");
+        
+        if (!fp)
+            fprintf (stderr, "readOFF(): could not open file %s", meshfile.c_str());
+        
+        fscanf (fp, "OFF\n%d %d 0\n",  &vnum, &fnum);
+        
+        V = Eigen::MatrixXd (vnum, 3);
+        F = Eigen::MatrixXi (fnum, 3);
+        
+        for (unsigned i = 0; i < V.rows(); i++)
+            fscanf (fp, "%lf %lf %lf\n", &V(i,0), &V(i,1), &V(i,2));
+        
+        for (unsigned i = 0; i < F.rows(); i++)
+            fscanf (fp, "3 %d %d %d\n", &F(i,0), &F(i,1), &F(i,2));
+        
+        fclose (fp);
+    }
+}
+
+#endif

+ 28 - 0
readme.txt

@@ -0,0 +1,28 @@
+igl Library - A simple c++ mesh library
+Copyright 2011 - Daniele Panozzo, Alec Jacobson, Olga Diamanti
+Interactive Geometry Lab - ETH Zurich
+
+Naming standards:
+
+- Every function must be written in a .h file with the same name of the function
+- cpp files are NOT allowed
+- A function can return a value only if it is a single scalar, elsewhere
+  the output parameters must be passed as references. 
+- Pointers are not allowed, if you need to make optional parameters 
+  you should prepare a wrapper for any possible combination of them
+- If an external dependency is needed it must be clearly stated at the
+  top of the file. If the dependency is header only it must be placed in the "external"
+  folder
+- Do not use the using namespace directive anywhere. The only exception is for
+  the igl namespace
+  
+Allowed types:
+
+- Eigen Matrices
+- Eigen Sparse Matrices
+- bool
+- int
+- unsigned int
+- double (float is NOT allowed)
+- string
+

+ 47 - 0
tt.h

@@ -0,0 +1,47 @@
+//
+//  IGL Lib - Simple C++ mesh library 
+//
+//  Copyright 2011, Daniele Panozzo. All rights reserved.
+
+#ifndef TT_H
+#define TT_H
+
+#include <Eigen/Core>
+#include <string>
+
+namespace igl 
+{
+    // Compute triangle-triangle adjacency
+    void tt(Eigen::MatrixXd& V, Eigen::MatrixXd& F, Eigen::MatrixXd& TT)
+    {
+        assert(isManifold());
+        vector<vector<int> > TTT;
+        for(int f=0;f<F.rows();++f)
+            for (int i=0;i<3;++i)
+            {
+                // v1 v2 f ei 
+                int v1 = F(f,i);
+                int v2 = F(f,(i+1)%3);
+                if (v1 > v2) std::swap(v1,v2);
+                vector<int> r(4);
+                r[0] = v1; r[1] = v2;
+                r[2] = f;  r[3] = i;
+                TTT.push_back(r);
+            }
+        std::sort(TTT.begin(),TTT.end());
+        TT = MatrixXi::Constant((int)(F.rows()),3,-1);
+        
+        for(int i=1;i<TTT.size();++i)
+        {
+            vector<int>& r1 = TTT[i-1];
+            vector<int>& r2 = TTT[i];
+            if ((r1[0] == r2[0]) && (r1[1] == r2[1]))
+            {
+                TT(r1[2],r1[3]) = r2[2];
+                TT(r2[2],r2[3]) = r1[2];
+            }
+        }
+    }
+}
+
+#endif

+ 34 - 0
write.h

@@ -0,0 +1,34 @@
+//
+//  IGL Lib - Simple C++ mesh library 
+//
+//  Copyright 2011, Daniele Panozzo. All rights reserved.
+
+#ifndef WRITE_H
+#define WRITE_H
+
+#include <Eigen/Core>
+#include <string>
+
+#include <writeOBJ.h>
+#include <writeOFF.h>
+
+namespace igl 
+{
+    // write mesh to an ascii file with automatic detection of file format. supported: obj, off)
+    void write(std::string str, Eigen::MatrixXd& V, Eigen::MatrixXi& F)
+    {
+        const char* p;
+        for (p = str.c_str(); *p != '\0'; p++)
+            ;
+        while (*p != '.')
+            p--;
+        
+        if (!strcmp(p, ".obj") || !strcmp(p, ".OBJ"))
+            return igl::writeOBJ(str,V,F);
+        
+        if (!strcmp(p, ".off") || !strcmp(p, ".OFF"))
+            return igl::writeOFF(str,V,F);
+    }
+}
+
+#endif

+ 30 - 0
writeOBJ.h

@@ -0,0 +1,30 @@
+//
+//  IGL Lib - Simple C++ mesh library 
+//
+//  Copyright 2011, Daniele Panozzo. All rights reserved.
+
+#ifndef WRITEOBJ_H
+#define WRITEOBJ_H
+
+#include <Eigen/Core>
+#include <string>
+#include <iostream>
+#include <fstream>
+
+namespace igl 
+{
+    // Write a mesh in an ascii obj file
+    void writeOBJ(std::string str, Eigen::MatrixXd& V, Eigen::MatrixXi& F)
+    {
+        std::ofstream s(str.c_str());
+        for(int i=0;i<V.rows();++i)
+            s << "v " << V(i,0) << " " << V(i,1) << " " << V(i,2) << std::endl;
+        
+        for(int i=0;i<F.rows();++i)
+            s << "f " << F(i,0)+1 << " " << F(i,1)+1 << " " << F(i,2)+1 << std::endl;
+        
+        s.close();
+    }
+}
+
+#endif

+ 34 - 0
writeOFF.h

@@ -0,0 +1,34 @@
+//
+//  IGL Lib - Simple C++ mesh library 
+//
+//  Copyright 2011, Daniele Panozzo. All rights reserved.
+
+#ifndef WRITEOFF_H
+#define WRITEOFF_H
+
+#include <Eigen/Core>
+#include <string>
+
+namespace igl 
+{
+    // write mesh to an ascii off file
+    void writeOFF (std::string fname, Eigen::MatrixXd& V, Eigen::MatrixXi& F)
+    {
+        FILE *fp = fopen (fname.c_str(), "w");
+        
+        if (!fp)
+            fprintf (stderr, "writeOFF(): could not open file %s", fname.c_str());
+        
+        fprintf (fp, "OFF\n%d %d 0\n",  (int) V.rows(), (int) F.rows());
+        
+        for (unsigned i = 0; i < V.rows(); i++)
+            fprintf (fp, "%f %f %f\n", V(i,0), V(i,1), V(i,2));
+        
+        for (unsigned i = 0; i < F.rows(); i++)
+            fprintf (fp, "3 %d %d %d\n", F(i,0), F(i,1), F(i,2));
+        
+        fclose (fp);
+    }
+}
+
+#endif