diff --git a/tutorial/712_DataSmoothing/CMakeLists.txt b/tutorial/712_DataSmoothing/CMakeLists.txt new file mode 100644 index 000000000..cd71d8881 --- /dev/null +++ b/tutorial/712_DataSmoothing/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 2.8.12) +project(712_DataSmoothing) + +add_executable(${PROJECT_NAME}_bin + main.cpp) +target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS}) +target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS}) +target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES} ${LIBIGL_OPENGL_EXTRA_LIBRARIES} ${LIBIGL_OPENGL_GLFW_EXTRA_LIBRARIES}) diff --git a/tutorial/712_DataSmoothing/isolines.h b/tutorial/712_DataSmoothing/isolines.h new file mode 100644 index 000000000..e7c807749 --- /dev/null +++ b/tutorial/712_DataSmoothing/isolines.h @@ -0,0 +1,90 @@ + +#include +#include +#include + +#include + + +static void isolines(const Eigen::MatrixXd& V, + const Eigen::MatrixXi& F, + const Eigen::VectorXd& z, + const int grads, + Eigen::MatrixXd& isoV, + Eigen::MatrixXi& isoE) +{ + const double min = z.minCoeff(), max = z.maxCoeff(); + + //Following http://www.alecjacobson.com/weblog/?p=2529 + Eigen::VectorXd iso(grads+1); + for(int i=0; i1) + t12(i,j) = std::numeric_limits::quiet_NaN(); + if(t23(i,j)<0 || t23(i,j)>1) + t23(i,j) = std::numeric_limits::quiet_NaN(); + if(t31(i,j)<0 || t31(i,j)>1) + t31(i,j) = std::numeric_limits::quiet_NaN(); + } + } + + std::vector F12, F23, F31, I12, I23, I31; + for(int i=0; i +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "tutorial_shared_path.h" + +#include "isolines.h" + + +int main(int argc, char * argv[]) +{ + typedef Eigen::SparseMatrix SparseMat; + + //Read our mesh + Eigen::MatrixXd V; + Eigen::MatrixXi F, E; + if(!igl::read_triangle_mesh( + argc>1?argv[1]: TUTORIAL_SHARED_PATH "/beetle.off",V,F)) { + std::cout << "Failed to load mesh." << std::endl; + } + igl::edges(F,E); + + //Constructing an exact function to smooth + Eigen::VectorXd zexact = V.block(0,2,V.rows(),1).array() + + 0.5*V.block(0,1,V.rows(),1).array() + + V.block(0,1,V.rows(),1).array().pow(2) + + V.block(0,2,V.rows(),1).array().pow(3); + + //Make the exact function noisy + srand(0); + const double s = 0.2*(zexact.maxCoeff() - zexact.minCoeff()); + Eigen::VectorXd znoisy = zexact + s*Eigen::VectorXd::Random(zexact.size()); + + //Constructing the squared Laplacian and squared Hessian energy + SparseMat L, M; + igl::cotmatrix(V, F, L); + igl::massmatrix(V, F, igl::MASSMATRIX_TYPE_BARYCENTRIC, M); + Eigen::SimplicialLDLT solver(M); + SparseMat MinvL = solver.solve(L); + SparseMat QL = L.transpose()*MinvL; + SparseMat QH; + igl::hessian_energy(V, F, QH); + + //Solve to find Laplacian-smoothed and Hessian-smoothed solutions + const double al = 5e-4; + Eigen::SimplicialLDLT lapSolver(al*QL + (1.-al)*M); + Eigen::VectorXd zl = lapSolver.solve(al*M*znoisy); + const double ah = 3e-6; + Eigen::SimplicialLDLT hessSolver(ah*QH + (1.-ah)*M); + Eigen::VectorXd zh = hessSolver.solve(ah*M*znoisy); + + //Viewer that shows all functions: zexact, znoisy, zl, zh + igl::viewer::Viewer viewer; + viewer.data.set_mesh(V,F); + viewer.core.show_lines = false; + viewer.callback_key_down = + [&](igl::viewer::Viewer & viewer, unsigned char key, int mod)->bool { + //Graduate result to show isolines, then compute color matrix + const Eigen::VectorXd* z; + switch(key) { + case '1': + z = &zexact; + break; + case '2': + z = &znoisy; + break; + case '3': + z = &zl; + break; + case '4': + z = &zh; + break; + default: + return false; + } + Eigen::MatrixXd isoV; + Eigen::MatrixXi isoE; + isolines(V, F, *z, 30, isoV, isoE); + viewer.data.set_edges(isoV,isoE,Eigen::RowVector3d(0,0,0)); + Eigen::MatrixXd colors; + igl::jet(*z, true, colors); + viewer.data.set_colors(colors); + }; + viewer.launch(); + + return 0; +}