|
@@ -1,15 +1,15 @@
|
|
|
// This file is part of libigl, a simple c++ geometry processing library.
|
|
|
-//
|
|
|
+//
|
|
|
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
|
|
|
-//
|
|
|
-// 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
|
|
|
+//
|
|
|
+// 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 <igl/matlab/matlabinterface.h>
|
|
|
|
|
|
// Implementation
|
|
|
|
|
|
-// Init the MATLAB engine
|
|
|
+// Init the MATLAB engine
|
|
|
// (no need to call it directly since it is automatically invoked by any other command)
|
|
|
IGL_INLINE void igl::mlinit(Engine** mlengine)
|
|
|
{
|
|
@@ -28,15 +28,15 @@ IGL_INLINE void igl::mlsetmatrix(Engine** mlengine, std::string name, const Eige
|
|
|
{
|
|
|
if (*mlengine == 0)
|
|
|
mlinit(mlengine);
|
|
|
-
|
|
|
+
|
|
|
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);
|
|
|
}
|
|
@@ -46,15 +46,15 @@ IGL_INLINE void igl::mlsetmatrix(Engine** mlengine, std::string name, const Eige
|
|
|
{
|
|
|
if (*mlengine == 0)
|
|
|
mlinit(mlengine);
|
|
|
-
|
|
|
+
|
|
|
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);
|
|
|
}
|
|
@@ -64,15 +64,15 @@ IGL_INLINE void igl::mlsetmatrix(Engine** mlengine, std::string name, const Eige
|
|
|
{
|
|
|
if (*mlengine == 0)
|
|
|
mlinit(mlengine);
|
|
|
-
|
|
|
+
|
|
|
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);
|
|
|
}
|
|
@@ -82,15 +82,15 @@ IGL_INLINE void igl::mlsetmatrix(Engine** mlengine, std::string name, const Eige
|
|
|
{
|
|
|
if (*mlengine == 0)
|
|
|
mlinit(mlengine);
|
|
|
-
|
|
|
+
|
|
|
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);
|
|
|
}
|
|
@@ -100,11 +100,11 @@ IGL_INLINE void igl::mlgetmatrix(Engine** mlengine, std::string name, Eigen::Mat
|
|
|
{
|
|
|
if (*mlengine == 0)
|
|
|
mlinit(mlengine);
|
|
|
-
|
|
|
+
|
|
|
unsigned long m = 0;
|
|
|
unsigned long n = 0;
|
|
|
std::vector<double> t;
|
|
|
-
|
|
|
+
|
|
|
mxArray *ary = engGetVariable(*mlengine, name.c_str());
|
|
|
if (ary == NULL)
|
|
|
{
|
|
@@ -117,7 +117,7 @@ IGL_INLINE void igl::mlgetmatrix(Engine** mlengine, std::string name, Eigen::Mat
|
|
|
m = mxGetM(ary);
|
|
|
n = mxGetN(ary);
|
|
|
M = Eigen::MatrixXd(m,n);
|
|
|
-
|
|
|
+
|
|
|
double *pM = mxGetPr(ary);
|
|
|
|
|
|
int c = 0;
|
|
@@ -125,7 +125,7 @@ IGL_INLINE void igl::mlgetmatrix(Engine** mlengine, std::string name, Eigen::Mat
|
|
|
for(int i=0; i<M.rows();++i)
|
|
|
M(i,j) = pM[c++];
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
mxDestroyArray(ary);
|
|
|
}
|
|
|
|
|
@@ -133,11 +133,11 @@ IGL_INLINE void igl::mlgetmatrix(Engine** mlengine, std::string name, Eigen::Mat
|
|
|
{
|
|
|
if (*mlengine == 0)
|
|
|
mlinit(mlengine);
|
|
|
-
|
|
|
+
|
|
|
unsigned long m = 0;
|
|
|
unsigned long n = 0;
|
|
|
std::vector<double> t;
|
|
|
-
|
|
|
+
|
|
|
mxArray *ary = engGetVariable(*mlengine, name.c_str());
|
|
|
if (ary == NULL)
|
|
|
{
|
|
@@ -150,15 +150,15 @@ IGL_INLINE void igl::mlgetmatrix(Engine** mlengine, std::string name, Eigen::Mat
|
|
|
m = mxGetM(ary);
|
|
|
n = mxGetN(ary);
|
|
|
M = Eigen::MatrixXf(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);
|
|
|
}
|
|
|
|
|
@@ -167,11 +167,11 @@ IGL_INLINE void igl::mlgetmatrix(Engine** mlengine, std::string name, Eigen::Mat
|
|
|
{
|
|
|
if (*mlengine == 0)
|
|
|
mlinit(mlengine);
|
|
|
-
|
|
|
+
|
|
|
unsigned long m = 0;
|
|
|
unsigned long n = 0;
|
|
|
std::vector<double> t;
|
|
|
-
|
|
|
+
|
|
|
mxArray *ary = engGetVariable(*mlengine, name.c_str());
|
|
|
if (ary == NULL)
|
|
|
{
|
|
@@ -184,15 +184,15 @@ IGL_INLINE void igl::mlgetmatrix(Engine** mlengine, std::string name, Eigen::Mat
|
|
|
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);
|
|
|
}
|
|
|
|
|
@@ -201,11 +201,11 @@ IGL_INLINE void igl::mlgetmatrix(Engine** mlengine, std::string name, Eigen::Mat
|
|
|
{
|
|
|
if (*mlengine == 0)
|
|
|
mlinit(mlengine);
|
|
|
-
|
|
|
+
|
|
|
unsigned long m = 0;
|
|
|
unsigned long n = 0;
|
|
|
std::vector<double> t;
|
|
|
-
|
|
|
+
|
|
|
mxArray *ary = engGetVariable(*mlengine, name.c_str());
|
|
|
if (ary == NULL)
|
|
|
{
|
|
@@ -218,15 +218,15 @@ IGL_INLINE void igl::mlgetmatrix(Engine** mlengine, std::string name, Eigen::Mat
|
|
|
m = mxGetM(ary);
|
|
|
n = mxGetN(ary);
|
|
|
M = Eigen::Matrix<unsigned int, Eigen::Dynamic, Eigen::Dynamic >(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) = (unsigned int)(pM[c++])-1;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
mxDestroyArray(ary);
|
|
|
}
|
|
|
|
|
@@ -236,7 +236,7 @@ IGL_INLINE void igl::mlsetscalar(Engine** mlengine, std::string name, double s)
|
|
|
{
|
|
|
if (*mlengine == 0)
|
|
|
mlinit(mlengine);
|
|
|
-
|
|
|
+
|
|
|
Eigen::MatrixXd M(1,1);
|
|
|
M(0,0) = s;
|
|
|
mlsetmatrix(mlengine, name, M);
|
|
@@ -247,7 +247,7 @@ IGL_INLINE double igl::mlgetscalar(Engine** mlengine, std::string name)
|
|
|
{
|
|
|
if (*mlengine == 0)
|
|
|
mlinit(mlengine);
|
|
|
-
|
|
|
+
|
|
|
Eigen::MatrixXd M;
|
|
|
mlgetmatrix(mlengine, name,M);
|
|
|
return M(0,0);
|
|
@@ -258,15 +258,15 @@ IGL_INLINE std::string igl::mleval(Engine** mlengine, std::string code)
|
|
|
{
|
|
|
if (*mlengine == 0)
|
|
|
mlinit(mlengine);
|
|
|
-
|
|
|
+
|
|
|
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).
|
|
@@ -275,21 +275,56 @@ IGL_INLINE std::string igl::mleval(Engine** mlengine, std::string code)
|
|
|
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);
|
|
|
}
|
|
|
+
|
|
|
+// Send a sparse matrix
|
|
|
+IGL_INLINE void igl::mlsetmatrix(Engine** mlengine, std::string name, const Eigen::SparseMatrix<double>& M)
|
|
|
+{
|
|
|
+ int count = 0;
|
|
|
+// // Count non-zero
|
|
|
+// for (unsigned k=0; k<M.outerSize(); ++k)
|
|
|
+// for (Eigen::SparseMatrix<double>::InnerIterator it(M,k); it; ++it)
|
|
|
+// if (it.value() != 0)
|
|
|
+// ++count;
|
|
|
+
|
|
|
+ Eigen::MatrixXd T(M.nonZeros(),3);
|
|
|
+ for (unsigned k=0; k<M.outerSize(); ++k)
|
|
|
+ {
|
|
|
+ for (Eigen::SparseMatrix<double>::InnerIterator it(M,k); it; ++it)
|
|
|
+ {
|
|
|
+ T(count,0) = it.row();
|
|
|
+ T(count,1) = it.col();
|
|
|
+ T(count,2) = it.value();
|
|
|
+ ++count;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ T.col(0) = T.col(0).array()+1;
|
|
|
+ T.col(1) = T.col(1).array()+1;
|
|
|
+
|
|
|
+ mlsetmatrix(mlengine,"temp93765",T);
|
|
|
+
|
|
|
+ std::string temp = name + " = sparse(temp93765(:,1),temp93765(:,2),temp93765(:,3),"
|
|
|
+ + std::to_string(M.rows()) + ","
|
|
|
+ + std::to_string(M.cols()) + ");";
|
|
|
+
|
|
|
+ mleval(mlengine,temp);
|
|
|
+ mleval(mlengine,"clear temp93765");
|
|
|
+}
|