From 7b133fc555d7e73a7a37aedb4c23eb716aedc865 Mon Sep 17 00:00:00 2001 From: Daniele Panozzo Date: Tue, 17 Jun 2014 22:29:22 +0200 Subject: [PATCH] fixed deprecated types in cotmatrix improved matlabinterface to support sending sparse matrices to matlab added matlab example for the tutorial Former-commit-id: d23c7f1fbc39fc5a50f42e0ee9748853940bbeff --- include/igl/cotmatrix.cpp | 4 +- include/igl/matlab/matlabinterface.cpp | 127 ++++++++++++++-------- include/igl/matlab/matlabinterface.h | 38 ++++--- tutorial/106_Matlab/CMakeLists.txt | 20 ++++ tutorial/106_Matlab/main.cpp | 82 ++++++++++++++ tutorial/106_Matlab/run.sh | 10 ++ tutorial/shared/3holes.off.REMOVED.git-id | 1 + 7 files changed, 217 insertions(+), 65 deletions(-) create mode 100644 tutorial/106_Matlab/CMakeLists.txt create mode 100755 tutorial/106_Matlab/main.cpp create mode 100644 tutorial/106_Matlab/run.sh create mode 100644 tutorial/shared/3holes.off.REMOVED.git-id diff --git a/include/igl/cotmatrix.cpp b/include/igl/cotmatrix.cpp index dfc057cf9..6087d5f2b 100644 --- a/include/igl/cotmatrix.cpp +++ b/include/igl/cotmatrix.cpp @@ -23,9 +23,9 @@ IGL_INLINE void igl::cotmatrix( { using namespace igl; using namespace Eigen; - Eigen::DynamicSparseMatrix foo; + Eigen::SparseMatrix foo; - DynamicSparseMatrix dyn_L (V.rows(), V.rows()); + SparseMatrix dyn_L (V.rows(), V.rows()); Matrix edges; int simplex_size = F.cols(); // 3 for triangles, 4 for tets diff --git a/include/igl/matlab/matlabinterface.cpp b/include/igl/matlab/matlabinterface.cpp index 89cf33a19..b2a3b96ca 100644 --- a/include/igl/matlab/matlabinterface.cpp +++ b/include/igl/matlab/matlabinterface.cpp @@ -1,15 +1,15 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2013 Alec Jacobson -// -// 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 // 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 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 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 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 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(m,n); - + double *pM = mxGetPr(ary); - + int c = 0; for(int j=0; j' && 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& M) +{ + int count = 0; +// // Count non-zero +// for (unsigned k=0; k::InnerIterator it(M,k); it; ++it) +// if (it.value() != 0) +// ++count; + + Eigen::MatrixXd T(M.nonZeros(),3); + for (unsigned k=0; k::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"); +} diff --git a/include/igl/matlab/matlabinterface.h b/include/igl/matlab/matlabinterface.h index a95578424..ec43f1103 100644 --- a/include/igl/matlab/matlabinterface.h +++ b/include/igl/matlab/matlabinterface.h @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2013 Alec Jacobson -// -// 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 +// +// Copyright (C) 2013 Daniele Panozzo +// +// 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_MATLAB_INTERFACE_H #define IGL_MATLAB_INTERFACE_H @@ -21,6 +21,7 @@ // PATH = /opt/local/bin:/opt/local/sbin:/Applications/MATLAB_R2011a.app/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/texbin:/usr/X11/bin #include +#include #include #include @@ -31,48 +32,51 @@ #include "engine.h" // Matlab engine header -namespace igl +namespace igl { - // 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 mlinit(Engine** engine); - + // Closes the MATLAB engine IGL_INLINE void mlclose(Engine** engine); - + // Send a matrix to MATLAB IGL_INLINE void mlsetmatrix(Engine** engine, std::string name, const Eigen::MatrixXd& M); - + // Send a matrix to MATLAB IGL_INLINE void mlsetmatrix(Engine** engine, std::string name, const Eigen::MatrixXf& M); // Send a matrix to MATLAB IGL_INLINE void mlsetmatrix(Engine** engine, std::string name, const Eigen::MatrixXi& M); - + // Send a matrix to MATLAB IGL_INLINE void mlsetmatrix(Engine** mlengine, std::string name, const Eigen::Matrix& M); - + // Receive a matrix from MATLAB IGL_INLINE void mlgetmatrix(Engine** engine, std::string name, Eigen::MatrixXd& M); - + // Receive a matrix from MATLAB IGL_INLINE void mlgetmatrix(Engine** engine, std::string name, Eigen::MatrixXf& M); // Receive a matrix from MATLAB IGL_INLINE void mlgetmatrix(Engine** engine, std::string name, Eigen::MatrixXi& M); - + // Receive a matrix from MATLAB IGL_INLINE void mlgetmatrix(Engine** mlengine, std::string name, Eigen::Matrix& M); // Send a single scalar to MATLAB IGL_INLINE void mlsetscalar(Engine** engine, std::string name, double s); - + // Receive a single scalar from MATLAB IGL_INLINE double mlgetscalar(Engine** engine, std::string name); - + // Execute arbitrary MATLAB code and return the MATLAB output IGL_INLINE std::string mleval(Engine** engine, std::string code); - + + // Send a sparse matrix to MATLAB + IGL_INLINE void mlsetmatrix(Engine** mlengine, std::string name, const Eigen::SparseMatrix& M); + } // Be sure that this is not compiled into libigl.a diff --git a/tutorial/106_Matlab/CMakeLists.txt b/tutorial/106_Matlab/CMakeLists.txt new file mode 100644 index 000000000..9359f14dc --- /dev/null +++ b/tutorial/106_Matlab/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 2.6) +project(106_Matlab) + +include("../CMakeLists.shared") + +find_package(MATLAB REQUIRED) +include_directories( ${MATLAB_INCLUDE_DIR} ) + +set(SOURCES +${PROJECT_SOURCE_DIR}/main.cpp +) + +if(APPLE) + set(CMAKE_EXE_LINKER_FLAGS "-rpath ${MATLAB_INCLUDE_DIR}/../../bin/maci64"}) +endif (APPLE) #APPLE + +#message(FATAL_ERROR ${CMAKE_EXE_LINKER_FLAGS}) + +add_executable(106_Matlab ${SOURCES} ${SHARED_SOURCES}) +target_link_libraries(106_Matlab ${SHARED_LIBRARIES} ${MATLAB_LIBRARIES}) diff --git a/tutorial/106_Matlab/main.cpp b/tutorial/106_Matlab/main.cpp new file mode 100755 index 000000000..3938067a5 --- /dev/null +++ b/tutorial/106_Matlab/main.cpp @@ -0,0 +1,82 @@ +#define IGL_HEADER_ONLY +#include +#include +#include +#include +#include + +// Base mesh +Eigen::MatrixXd V; +Eigen::MatrixXi F; + +// Matlab instance +Engine* engine; + +// Eigenvectors of the laplacian +Eigen::MatrixXd EV; + +void plotEV(igl::Viewer& viewer, int id) +{ + Eigen::VectorXd v = EV.col(id); + v = v.array() - v.minCoeff(); + v = v.array() / v.maxCoeff(); + + // Map to colors using jet colorramp + Eigen::MatrixXd C(V.rows(),3); + for (unsigned i=0; i= '1' && key <= '9') + plotEV(viewer,(key - '1') + 1); + + return false; +} + +int main(int argc, char *argv[]) +{ + // Load a mesh in OFF format + igl::readOFF("../shared/3holes.off", V, F); + + // Launch MATLAB + igl::mlinit(&engine); + + // Compute the discrete Laplacian operator + Eigen::SparseMatrix L; + igl::cotmatrix(V,F,L); + + // Send Laplacian matrix to matlab + igl::mlsetmatrix(&engine,"L",L); + + // Plot the laplacian matri using matlab spy + igl::mleval(&engine,"spy(L)"); + + // Extract the first 10 eigenvectors + igl::mleval(&engine,"[EV,~] = eigs(-L,10,'sm')"); + + // Plot the size of EV (only for demostration purposes) + std::cerr << igl::mleval(&engine,"size(EV)") << std::endl; + + // Retrieve the result + igl::mlgetmatrix(&engine,"EV",EV); + + // Plot the mesh + igl::Viewer viewer; + viewer.callback_key_down = &key_down; + viewer.draw_mesh(V, F); + + // Plot the first non-trivial eigenvector + plotEV(viewer,1); + + // Launch the viewer + viewer.launch(); +} diff --git a/tutorial/106_Matlab/run.sh b/tutorial/106_Matlab/run.sh new file mode 100644 index 000000000..a77d7e1fc --- /dev/null +++ b/tutorial/106_Matlab/run.sh @@ -0,0 +1,10 @@ +# Make sure that matlab can be launched from the commandline +# if it is not the case use the following commands: +# cd /usr/local/bin +# sudo ln -s /Applications/MATLAB_R2012b.app/bin/matlab + +# Tested on MAC only + +DYLD_LIBRARY_PATH=/Applications/MATLAB_R2012b.app/bin/maci64/ + +./build/106_Matlab diff --git a/tutorial/shared/3holes.off.REMOVED.git-id b/tutorial/shared/3holes.off.REMOVED.git-id new file mode 100644 index 000000000..a6fcec24e --- /dev/null +++ b/tutorial/shared/3holes.off.REMOVED.git-id @@ -0,0 +1 @@ +e677b373d990a5ee037947ed5cdce68542637afa \ No newline at end of file