Procházet zdrojové kódy

added matlab interface and usage example

dpanozzo před 13 roky
rodič
revize
bb8a60d094
3 změnil soubory, kde provedl 306 přidání a 37 odebrání
  1. 55 0
      example2.cpp
  2. 31 37
      main.cpp
  3. 220 0
      matlabinterface.h

+ 55 - 0
example2.cpp

@@ -0,0 +1,55 @@
+//
+//  IGL Lib - Simple C++ mesh library 
+//
+//  Copyright 2011, Daniele Panozzo. All rights reserved.
+//
+//
+//  Example that shows the integration with matlab
+//
+
+// 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 <matlabinterface.h>
+
+using namespace std;
+
+int main (int argc, const char * argv[])
+{
+    // read the header of matlabinterface.h for compilation instructions
+    
+    Eigen::MatrixXd V,V2;
+    Eigen::MatrixXi F,F2;
+    
+    // Read mesh from file
+    igl::read(string(argv[1]),V,F);
+    
+    // Send mesh to matlab
+    igl::mlsetmatrix("V",V);
+    igl::mlsetmatrix("F",F);
+
+    // Plot the mesh from matlab
+    igl::mleval("trimesh(F,V(:,1),V(:,2),V(:,3))");
+
+    // Receive mesh from matlab
+    igl::mlgetmatrix("V",V2);
+    igl::mlgetmatrix("F",F2);
+
+    // Plot the received mesh
+    cerr << "V " << endl << V2  << endl;
+    cerr << "F " << endl << F2  << endl;
+    
+    // It is also possible to send scalars
+    igl::mlsetscalar("s", 3);
+    cerr << "s = " << igl::mlgetscalar("s") << endl;
+
+    // If the program closes the matlab session is killed too..
+    getchar();
+    
+    return 0;
+}
+

+ 31 - 37
main.cpp

@@ -2,6 +2,10 @@
 //  IGL Lib - Simple C++ mesh library 
 //
 //  Copyright 2011, Daniele Panozzo. All rights reserved.
+//
+//
+//  Example that shows the integration with matlab
+//
 
 // IMPORTANT DO NOT REMOVE OR MOVE
 #define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET 
@@ -9,52 +13,42 @@
 #include <iostream>
 #include <string>
 #include <read.h>
-#include <write.h>
-#include <cotmatrix.h>
-#include <tt.h>
-#include <edgetopology.h>
+
+#include <matlabinterface.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;
+    // read the header of matlabinterface.h for compilation instructions
     
-    igl::write(string(argv[2]),V,F);
+    Eigen::MatrixXd V,V2;
+    Eigen::MatrixXi F,F2;
     
-    // Face Topology
-    cout << "TT Topology:" << endl;
-    Eigen::MatrixXi TT;
-    igl::tt(V,F,TT);
-    cout << TT << endl;
-    cout << "-------------" << endl;
-
-    // Edge Topology
-    cout << "Edge Topology:" << endl;
-    Eigen::MatrixXi EV;
-    Eigen::MatrixXi FE;
-    Eigen::MatrixXi EF;
+    // Read mesh from file
+    igl::read(string(argv[1]),V,F);
     
-    igl::edgetopology(V,F,EV,FE, EF);
-    cout << EV << endl << FE << endl << EF << endl;
-    cout << "-------------" << endl;
+    // Send mesh to matlab
+    igl::mlsetmatrix("V",V);
+    igl::mlsetmatrix("F",F);
+
+    // Plot the mesh from matlab
+    igl::mleval("trimesh(F,V(:,1),V(:,2),V(:,3))");
+
+    // Receive mesh from matlab
+    igl::mlgetmatrix("V",V2);
+    igl::mlgetmatrix("F",F2);
+
+    // Plot the received mesh
+    cerr << "V " << endl << V2  << endl;
+    cerr << "F " << endl << F2  << endl;
     
+    // It is also possible to send scalars
+    igl::mlsetscalar("s", 3);
+    cerr << "s = " << igl::mlgetscalar("s") << endl;
+
+    // If the program closes the matlab session is killed too..
+    getchar();
     
     return 0;
 }

+ 220 - 0
matlabinterface.h

@@ -0,0 +1,220 @@
+//
+//  IGL Lib - Simple C++ mesh library 
+//
+//  Copyright 2011, Daniele Panozzo. All rights reserved.
+
+// WARNING: These functions require matlab installed
+// Additional header folder required:
+//   /Applications/MATLAB_R2010b.app/extern/include
+// Additional binary lib to be linked with:
+// /Applications/MATLAB_R2010b.app/bin/maci64/libeng.dylib
+// /Applications/MATLAB_R2010b.app/bin/maci64/libmx.dylib
+
+// MAC ONLY:
+// Add to the environment variables:
+// DYLD_LIBRARY_PATH = /Applications/MATLAB_R2010b.app/bin/maci64
+// PATH = /opt/local/bin:/opt/local/sbin:/Applications/MATLAB_R2010b.app/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/texbin:/usr/X11/bin
+
+#ifndef MATLAB_INTERFACE_H
+#define MATLAB_INTERFACE_H
+
+#include <Eigen/Core>
+#include <string>
+
+#include <complex>
+#include <cassert>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "engine.h"  // Matlab engine header
+
+namespace igl 
+{
+    // Global pointer to the matlab engine
+    Engine* mlengine = 0;
+
+    // Init the MATLAB engine 
+    // (no need to call it directly since it is automatically invoked by any other command)
+    void mlinit()
+    {
+        mlengine = engOpen("\0");
+    }
+    
+    // Closes the MATLAB engine
+    void mlclose(Engine* engine)
+    {
+        engClose(mlengine);
+        mlengine = 0;
+    }
+
+    // Send a matrix to MATLAB
+    void mlsetmatrix(std::string name, Eigen::MatrixXd& M)
+    {
+        if (mlengine == 0)
+            mlinit();
+        
+        mxArray *A = mxCreateDoubleMatrix(M.rows(), M.cols(), mxREAL);
+        double *pM = mxGetPr(A);
+        
+        int c = 0;
+        for(int j=0; j<M.cols();++j)
+            for(int i=0; i<M.rows();++i)
+                pM[c++] = double(M(i,j));
+        
+        engPutVariable(mlengine, name.c_str(), A);
+        mxDestroyArray(A);
+    }
+    
+    // Send a matrix to MATLAB
+    void mlsetmatrix(std::string name, Eigen::MatrixXi& M)
+    {
+        if (mlengine == 0)
+            mlinit();
+        
+        mxArray *A = mxCreateDoubleMatrix(M.rows(), M.cols(), mxREAL);
+        double *pM = mxGetPr(A);
+        
+        int c = 0;
+        for(int j=0; j<M.cols();++j)
+            for(int i=0; i<M.rows();++i)
+                pM[c++] = double(M(i,j))+1;
+        
+        engPutVariable(mlengine, name.c_str(), A);
+        mxDestroyArray(A);
+    }
+    
+    // Receive a matrix from MATLAB
+    void mlgetmatrix(std::string name, Eigen::MatrixXd& M)
+    {
+        if (mlengine == 0)
+            mlinit();
+
+        unsigned long m = 0;
+        unsigned long n = 0;
+        std::vector<double> t;
+        
+        mxArray *ary = engGetVariable(mlengine, name.c_str());
+        if (ary == NULL)
+        {
+            m = 0;
+            n = 0;
+            M = Eigen::MatrixXd(0,0);
+        }
+        else
+        {
+            m = mxGetM(ary);
+            n = mxGetN(ary);
+            M = Eigen::MatrixXd(m,n);
+            
+            double *pM = mxGetPr(ary);
+            
+            int c = 0;
+            for(int j=0; j<M.cols();++j)
+                for(int i=0; i<M.rows();++i)
+                    M(i,j) = pM[c++];
+        }
+        
+        mxDestroyArray(ary);
+    }
+
+    // Receive a matrix from MATLAB
+    void mlgetmatrix(std::string name, Eigen::MatrixXi& M)
+    {
+        if (mlengine == 0)
+            mlinit();
+
+        unsigned long m = 0;
+        unsigned long n = 0;
+        std::vector<double> t;
+        
+        mxArray *ary = engGetVariable(mlengine, name.c_str());
+        if (ary == NULL)
+        {
+            m = 0;
+            n = 0;
+            M = Eigen::MatrixXi(0,0);
+        }
+        else
+        {
+            m = mxGetM(ary);
+            n = mxGetN(ary);
+            M = Eigen::MatrixXi(m,n);
+            
+            double *pM = mxGetPr(ary);
+            
+            int c = 0;
+            for(int j=0; j<M.cols();++j)
+                for(int i=0; i<M.rows();++i)
+                    M(i,j) = int(pM[c++])-1;
+        }
+        
+        mxDestroyArray(ary);
+    }
+
+    // Send a single scalar to MATLAB
+    void mlsetscalar(std::string name, double s)
+    {
+        if (mlengine == 0)
+            mlinit();
+
+        Eigen::MatrixXd M(1,1);
+        M(0,0) = s;
+        mlsetmatrix(name, M);
+    }
+    
+    // Receive a single scalar from MATLAB
+    double mlgetscalar(std::string name)
+    {
+        if (mlengine == 0)
+            mlinit();
+
+        Eigen::MatrixXd M;
+        mlgetmatrix(name,M);
+        return M(0,0);
+    }
+
+    // Execute arbitrary MATLAB code and return the MATLAB output
+    std::string mleval(std::string code)
+    {
+        if (mlengine == 0)
+            mlinit();
+
+        const char *matlab_code = code.c_str();
+        const int BUF_SIZE = 4096*4096;
+        // allocate on the heap to avoid running out of stack
+        std::string bufauto(BUF_SIZE+1, '\0');
+        char *buf = &bufauto[0];
+        
+        assert(matlab_code != NULL);
+        
+        // Use RAII ensure that on leaving this scope, the output buffer is
+        // always nullified (to prevent Matlab from accessing memory that might
+        // have already been deallocated).
+        struct cleanup {
+            Engine *m_ep;
+            cleanup(Engine *ep) : m_ep(ep) { }
+            ~cleanup() { engOutputBuffer(m_ep, NULL, 0); }
+        } cleanup_obj(mlengine);
+        
+        if (buf != NULL)
+            engOutputBuffer(mlengine, buf, BUF_SIZE);
+        
+        int res = engEvalString(mlengine, matlab_code);
+        
+        if (res != 0) {
+            std::ostringstream oss;
+            oss << "ERROR: Matlab command failed with error code " << res << ".\n";
+            return oss.str();
+        }
+        
+        if (buf[0] == '>' && buf[1] == '>' && buf[2] == ' ')
+            buf += 3;
+        if (buf[0] == '\n') ++buf;
+        
+        return std::string(buf);
+    }
+
+}
+
+#endif