MeshCoordinates l1_ls_inpainting(CMesh& mesh, const std::vector<int>& missing_idx, ParaL1LsInpainting& para) { const int totalVertCount = mesh.vertCount(); MeshLaplacian graphLaplacian; graphLaplacian.constructUmbrella(&mesh); int eigenCount = para.eigen_count; // -1 means full decomposition if (eigenCount == -1) eigenCount = totalVertCount - 1; ZGeom::EigenSystem es; graphLaplacian.meshEigenDecompose(eigenCount, &g_engineWrapper, es); ZGeom::Dictionary dictMHB; computeDictionary(DT_Fourier, es, dictMHB); ZGeom::DenseMatrixd matCoordOld = mesh.getVertCoordinates().toDenseMatrix(); ZGeom::DenseMatrixd matDict = dictMHB.toDenseMatrix(); CStopWatch timer; timer.startTimer(); ZGeom::DenseMatrixd matCoordInpainted = matlab_inpaintL1LS(matCoordOld, matDict, missing_idx, para.lambda, para.tol); timer.stopTimer("-- L1_Ls inpainting time: "); MeshCoordinates coordInpainted; coordInpainted.fromDenseMatrix(matCoordInpainted); return coordInpainted; }
void compressMesh(const std::vector<std::string>& mesh_filenames) { string mesh_file = mesh_filenames.front(); CMesh mesh; mesh.load(mesh_file); string mesh_name = mesh.getMeshName(); ofstream ofs(mesh_name + ".compress.log"); // what to do: // 1. partition mesh with each mesh of size 300, 500, 1000, 1500, 2000 // 2. For each submesh, do eigendecomposition // 3. Compute SGW dictionary // 4. S-OMP approximation // 5. Output total approximation error // // what to output: // 1. eigendecomposition time // 2. S-OMP time // 3. Approximation error vector<int> max_sizes{ 300, 600, 1000, 1500, 2000 }; for (int max_size : max_sizes) { int nPart = std::round(mesh.vertCount() / max_size); vector<int> part_idx = MetisMeshPartition(&mesh, nPart); // TODO } }
////////////////////////////////////////////////////////////////////////// // format: zmesh_operator [mesh_file_name] // currently, just output three types of Laplacian operator in .mat Matlab file int main(int argc, char *argv[]) { using namespace std; using namespace ZGeom; using namespace std::tr2::sys; if (argc < 2) { std::cerr << "Lack argument!" << std::endl; std::exit(-1); } string meshfile = argv[1]; if (!fileExist(meshfile)) { std::cerr << "Mesh file not existent!" << std::endl; std::exit(-1); } CMesh mesh; mesh.load(meshfile); mesh.scaleToUnitBox(); int N = mesh.vertCount(); mesh.scaleAndTranslate(-mesh.calMeshCenter(), 1.0); Laplacian umbrella, goemUmbrella, cotformula; umbrella.constructUmbrella(&mesh); cotformula.constructCotFormula(&mesh); auto coord = mesh.getVertCoordinates(); DenseMatrixd matCoord = coord.toDenseMatrix(); ZGeom::calMeshAttrVertNormals(mesh, ZGeom::VN_AREA_WEIGHT); auto normals = ZGeom::getMeshVertNormals(mesh); DenseMatrixd matNormal(N, 3); for (int i = 0; i < N; ++i) { for (int j = 0; j < 3; ++j) matNormal(i, j) = normals[i][j]; } calMeshAttrMixedVertAreas(mesh); ZGeom::computeMeshCurvatures(mesh, true); Laplacian anisoLap; anisoLap.constructAniso(&mesh); MatlabEngineWrapper eng; eng.open(); auto pwd = initial_path<path>(); eng.eval("cd " + pwd.string()); eng.addDenseMat(matCoord, "mat_coord"); eng.addDenseMat(matNormal, "mat_normal"); eng.addSparseMat(umbrella.getLS(), "mat_umbrella"); eng.addSparseMat(cotformula.getW(), "mat_weight"); eng.addSparseMat(cotformula.getLS(), "mat_cot"); eng.addSparseMat(anisoLap.getLS(), "mat_aniso"); eng.eval("save meshlaplace.mat mat_coord mat_normal mat_umbrella mat_weight mat_cot mat_aniso"); eng.close(); cout << "Mesh and Laplace .mat file saved!" << endl; exit(0); }
MeshCoordinates meshDLRS(CMesh& mesh, double lambda) { int totalVertCount = mesh.vertCount(); MeshCoordinates coordCurrent = mesh.getVertCoordinates(); MeshLaplacian graphLaplacian; graphLaplacian.constructUmbrella(&mesh); vector<VecNd> vDenoisedCoord = DLRS(graphLaplacian.getLS(), lambda, coordCurrent.to3Vec()); MeshCoordinates coordDenoised(totalVertCount, vDenoisedCoord); return coordDenoised; }
MeshCoordinates thin_plate_energy_fairing(CMesh& mesh, int free_vert_count) { const int totalVertCount = mesh.vertCount(); const MeshCoordinates coordOld = mesh.getVertCoordinates(); vector<VecNd> vOriginalCoords = coordOld.to3Vec(); MeshLaplacian mesh_laplacian; mesh_laplacian.constructCotFormula(&mesh); SparseMatrixd matL = mesh_laplacian.getSparseMatrix(); SparseMatrixd matL2; mulMatMat(matL, matL, matL2); vector<int> rowIdxL2, colIdxL2; vector<double> valsL2; matL2.convertToCOO(rowIdxL2, colIdxL2, valsL2, ZGeom::MAT_FULL); vector<int> rowIdxA, colIdxA; vector<double> valsA; for (int i = 0; i < (int)rowIdxL2.size(); ++i) { if (rowIdxL2[i] < free_vert_count && colIdxL2[i] < free_vert_count) { rowIdxA.push_back(rowIdxL2[i]); colIdxA.push_back(colIdxL2[i]); valsA.push_back(valsL2[i]); } } SparseMatrixd matA; matA.convertFromCOO(free_vert_count, free_vert_count, rowIdxA, colIdxA, valsA); DenseMatrixd matB(free_vert_count, 3); for (int m = 0; m < 3; ++m) { for (int i = 0; i < free_vert_count; ++i) { for (int j = free_vert_count; j < totalVertCount; ++j) matB(i, m) -= matL2(i, j) * vOriginalCoords[m][j]; } } g_engineWrapper.addSparseMat(matA, "matA"); g_engineWrapper.addDenseMat(matB, "matB"); g_engineWrapper.eval("matX=matA\\matB;"); DenseMatrixd matX = g_engineWrapper.getDenseMat("matX"); vector<VecNd> vNewCoord = vOriginalCoords; for (int m = 0; m < 3; ++m) for (int i = 0; i < free_vert_count; ++i) vNewCoord[m][i] = matX(i, m); MeshCoordinates result(totalVertCount, vNewCoord); return result; }
MeshCoordinates least_square_hole_inpainting(CMesh& mesh, const std::vector<ZGeom::MeshRegion>& hole_regions, int anchor_ring, double anchor_weight) { ZGeom::logic_assert(anchor_weight >= 0, "Illegal parameter!"); MeshCoordinates result(mesh.getVertCoordinates()); if (anchor_ring <= 0) { vector<int> hole_verts = getMeshRegionsInsideVerts(hole_regions); set<int> set_hole_verts(hole_verts.begin(), hole_verts.end()); set<int> anchor_verts; for (int vi = 0; vi < (int)mesh.vertCount(); ++vi) { if (!setHas(set_hole_verts, vi)) anchor_verts.insert(vi); } MeshCoordinates faired_coord = least_square_inpainting(mesh, vector<int>(anchor_verts.begin(),anchor_verts.end()), anchor_weight); for (int vi : hole_verts) result.setVertCoord(vi, faired_coord[vi]); return result; } for (const MeshRegion& mr : hole_regions) { const vector<int> anchor_verts = ZGeom::vertSurroundingVerts(mesh, mr.vert_inside, anchor_ring); vector<int> submesh_verts; int inside_vert_count = (int)mr.vert_inside.size(); int anchor_vert_count = (int)anchor_verts.size(); vector<int> newVert2oldVert(inside_vert_count); int newVertIdx(0); for (int vi : mr.vert_inside) { submesh_verts.push_back(vi); newVert2oldVert[newVertIdx++] = vi; } for (int vi : anchor_verts) submesh_verts.push_back(vi); CMesh submesh; mesh.getSubMesh(submesh_verts, "hole_mesh", submesh); vector<int> control_verts; for (int i = inside_vert_count; i < (int)submesh_verts.size(); ++i) control_verts.push_back(i); MeshCoordinates faired_sub_coord = least_square_inpainting(submesh, control_verts, anchor_weight); for (int sub_vIdx = 0; sub_vIdx < inside_vert_count; ++sub_vIdx) { result.setVertCoord(newVert2oldVert[sub_vIdx], faired_sub_coord[sub_vIdx]); } } return result; }
MeshCoordinates least_square_inpainting(CMesh& mesh, const std::vector<int>& anchor_verts, double anchor_weight) { const int totalVertCount = mesh.vertCount(); const MeshCoordinates coordOld = mesh.getVertCoordinates(); vector<VecNd> vOriginalCoords = coordOld.to3Vec(); MeshLaplacian matLaplacian; matLaplacian.constructTutte(&mesh); const vector<int> &vControlVerts = anchor_verts; set<int> setControlVerts{ anchor_verts.begin(), anchor_verts.end() }; int controlVertCount = (int)anchor_verts.size(); double controlWeight = anchor_weight; vector<int> rowIdxA, colIdxA; vector<double> valsA; matLaplacian.getSparseMatrix().convertToCOO(rowIdxA, colIdxA, valsA, ZGeom::MAT_FULL); for (int i = 0; i < controlVertCount; ++i) { rowIdxA.push_back(totalVertCount + i + 1); colIdxA.push_back(vControlVerts[i] + 1); valsA.push_back(controlWeight); } SparseMatrixd matA(totalVertCount + controlVertCount, totalVertCount); matA.convertFromCOO(totalVertCount + controlVertCount, totalVertCount, rowIdxA, colIdxA, valsA); DenseMatrixd matB(totalVertCount + controlVertCount, 3); for (int i = 0; i < controlVertCount; ++i) { for (int j = 0; j < 3; ++j) matB(totalVertCount + i, j) = controlWeight * vOriginalCoords[j][vControlVerts[i]]; } g_engineWrapper.addSparseMat(matA, "matA"); g_engineWrapper.addDenseMat(matB, "matB"); g_engineWrapper.eval("matX=matA\\matB;"); DenseMatrixd matX = g_engineWrapper.getDenseMat("matX"); MeshCoordinates result; result.fromDenseMatrix(matX); return result; }
////////////////////////////////////////////////////////////////////////// // usage: zmesh_partition [mesh-filename] -n/-m [partitionCount/maxPatchSize] [output-path] // int main(int argc, char *argv[]) { if (argc == 2 && argv[1] == std::string("--help")) { std::cout << "usage: zmesh_partition [mesh-filename] -n/-m [partitionCount/maxPatchSize] [output-path]" << '\n'; exit(0); } if (argc < 4) { std::cerr << "Lack " << 4 -argc << " arguments!" << std::endl; exit(-1); } else if (argc > 5) { std::cerr << "Excessive arguments ignored!" << std::endl; } /// preparation of option and parameters std::string meshFilename = argv[1]; std::string segOption = argv[2]; std::string segPara = argv[3]; std::string outputPath = "./"; if (argc == 5) { outputPath = argv[4]; if (outputPath.back() != '/') outputPath.push_back('/'); // add trailing slash if missing } if (!fileExist(meshFilename)) { std::cerr << "Mesh file not existent!" << std::endl; std::exit(-1); } bool segNumSpecified = false; if (segOption == "-n") segNumSpecified = true; else if (segOption == "-m") segNumSpecified = false; else { std::cerr << "Unrecognized option '" << segOption << " '" << std::endl; std::exit(-1); } int nPara = std::stoi(segPara); /// load mesh CMesh oriMesh; oriMesh.load(meshFilename); ZGeom::gatherMeshStatistics(oriMesh); std::string meshName = oriMesh.getMeshName(); int totalVertCount = oriMesh.vertCount(); int nPart; if (segNumSpecified) nPart = nPara; else nPart = totalVertCount / nPara + 1; if (nPart <= 0) { std::cerr << "Number of segmentations must be greater than 0" << std::endl; std::exit(-1); } std::vector<CMesh*> vSubMeshes; std::vector<std::vector<int>*> vMappedIdx; for (int i = 0; i < nPart; ++i) { vSubMeshes.push_back(new CMesh()); vMappedIdx.push_back(new std::vector<int>()); } std::vector<int> vPartIdx = MetisMeshPartition(&oriMesh, nPart); for (int vIdx = 0; vIdx < totalVertCount; ++vIdx) { vMappedIdx[vPartIdx[vIdx]]->push_back(vIdx); } double paritionTime = time_call_sec([&]() { oriMesh.partitionToSubMeshes(vMappedIdx, vSubMeshes); }); std::cout << "Partition finished! Time consumed: " << paritionTime << "s\n"; char numBuf[10]; for (int i = 0; i < nPart; ++i) { _itoa_s(i + 1, numBuf, 10); std::string subMeshName = meshName + ".sub" + std::string(numBuf); vSubMeshes[i]->setMeshName(subMeshName); } std::cout << "- number of partitions: " << nPart << '\n'; std::cout << "- sub-mesh sizes: "; for (int i = 0; i < nPart; ++i) { std::cout << vSubMeshes[i]->getMeshName() << ": " << vSubMeshes[i]->vertCount() << " | "; vSubMeshes[i]->save(outputPath + vSubMeshes[i]->getMeshName() + ".obj"); } std::cout << '\n'; for (auto p : vSubMeshes) delete p; for (auto p : vMappedIdx) delete p; #ifdef _DEBUG std::system("PAUSE"); #endif exit(0); }