220 lines
5.7 KiB
C++
220 lines
5.7 KiB
C++
//
|
|
// 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 |