• 网格的补洞操作


    简介

    网格补洞操作,里面有有奖征集答案,欢迎大家踊跃回答。第一个留言为有效留言
    那个horse.off请到github下载

    算法描述

    找到网格的所有的边界半边。

    for循环选定一个孔洞的关键点

    以来点来遍历整个孔洞
    补洞

    代码

    // 网格 补洞的操作
    
    #include <iostream>
    #include <OpenMesh/Core/IO/MeshIO.hh>
    #include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
    #include <cmath>
    #include <vector>
    #include <map>
    #define pi 3.1415926
    
    using namespace std;
    typedef OpenMesh::TriMesh_ArrayKernelT<> MyMesh;
    
    int main() {
    	MyMesh mesh;
    	map<MyMesh::HalfedgeHandle, int>holeHalfedgeHandle;// 半边 对应的 int
    	vector<MyMesh::HalfedgeHandle> halfedgeHandle;//选定的孔洞集合
    	MyMesh::VertexHandle vertexHandle;
    	if (!OpenMesh::IO::read_mesh(mesh, "horse.off")) {
    		std::cerr << "Cannot read mesh to file ' horse.off ' " << std::endl;
    		return 1;
    	}
    	for (auto he_it = mesh.halfedges_begin(); he_it != mesh.halfedges_end(); ++he_it) {
    		if (mesh.is_boundary(*he_it)) {
    			holeHalfedgeHandle.insert(make_pair(*he_it, 0));// 在有边界半边加入到集合中
    		}
    	}
    	for (map<MyMesh::HalfedgeHandle, int>::iterator mh_it = holeHalfedgeHandle.begin(); mh_it != holeHalfedgeHandle.end(); ++mh_it) {
    		if (mh_it->second == 0) {//将这个集合中还没处理过的边界点
    			halfedgeHandle.clear();// 临时处理的半边钩子清空
    			halfedgeHandle.push_back(mh_it->first);// 将边界的半边钩子放入其中
    			holeHalfedgeHandle[mh_it->first] = 1;// 将边界的半边钩子设定为已经处理
    			vertexHandle = mesh.from_vertex_handle(mh_it->first);//把正在处理的半边的来点找到
    			//选定孔洞
    			for (map<MyMesh::HalfedgeHandle, int>::iterator mit = holeHalfedgeHandle.begin(); mit != holeHalfedgeHandle.end(); ++mit) {
    				//再次遍历整个边界集  是对应  上一层的for循环的选定的孔洞。
    				if (mesh.to_vertex_handle(mit->first) == vertexHandle) {// 如果这个边界集合中的某个点的去点是这个关键点
    					halfedgeHandle.push_back(mit->first);// 将这个去点关键点加入半边集合中
    					holeHalfedgeHandle[mit->first] = 1;// 将整个半边集合中去掉求点关键点所在的半边
    					vertexHandle = mesh.from_vertex_handle(mit->first);// 将这个去点作为来点成为一个钩子关键点
    					if (mesh.from_vertex_handle(mit->first) == mesh.to_vertex_handle(mh_it->first))// 当遍历这个孔洞
    						// 如果上一层选定的孔洞的半边的去点 等于 此时的选定的半边的来点 说明整个孔洞已经遍历完毕了
    						break;
    					mit = holeHalfedgeHandle.begin();// 感觉效率有点低,如果找到了这个关键点,可能要重新遍历所有空洞元素  
    				}
    				else {
    					continue;
    				}
    			}
    			vector<MyMesh::VertexHandle>ver;
    			vector<MyMesh::VertexHandle>face;
    			// 将这个孔洞的边界点都加入的数组ver中
    			for (vector<MyMesh::HalfedgeHandle>::iterator halfe = halfedgeHandle.begin(); halfe != halfedgeHandle.end(); ++halfe) {
    				vertexHandle = mesh.from_vertex_handle(*halfe);
    				ver.push_back(vertexHandle);
    			}
    			// 设定第一个点为角点(ver.end() - 1),然后构成一个平面
    			for (vector<MyMesh::VertexHandle>::iterator v_it = ver.begin() + 1; v_it != ver.end() - 1; ++v_it) {
    				face.clear();
    				face.push_back(*(ver.end() - 1));
    				face.push_back(*(v_it));
    				face.push_back(*(v_it - 1));
    				mesh.add_face(face);
    			}
    		}
    	}
    	// 将生成的新网格输出
    	if (!OpenMesh::IO::write_mesh(mesh, "rocker_result.off")) {
    		std::cerr << "Cannot write mesh to file ' rocker_result.off ' " << std::endl;
    		return 1;
    	}
    	return 0;
    }
    

    代码二

    采用下一条半边来构建整个模型,但是有bug,为了应对bug不得已加了一些代码,大的孔洞已经填补,但是小得多孔洞没有填补,不知道为什么?
    任何人找到我的bug,解决我的bug,留下支付宝号(在留言中),本人将会转1元人民币。

    // 网格 补洞的操作
    
    #include <iostream>
    #include <OpenMesh/Core/IO/MeshIO.hh>
    #include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
    #include <cmath>
    #include <vector>
    #include <map>
    #define pi 3.1415926
    
    using namespace std;
    typedef OpenMesh::TriMesh_ArrayKernelT<> MyMesh;
    
    int main() {
    	MyMesh mesh;
    	map<MyMesh::HalfedgeHandle, int>holeHalfedgeHandle;// 半边 对应的 int
    	vector<MyMesh::HalfedgeHandle> halfedgeHandle;//选定的孔洞集合
    	MyMesh::VertexHandle vertexHandle;
    	if (!OpenMesh::IO::read_mesh(mesh, "horse.off")) {
    		std::cerr << "Cannot read mesh to file ' horse.off ' " << std::endl;
    		return 1;
    	}
    	for (auto he_it = mesh.halfedges_begin(); he_it != mesh.halfedges_end(); ++he_it) {
    		if (mesh.is_boundary(*he_it)) {
    			holeHalfedgeHandle.insert(make_pair(*he_it, 0));// 在有边界半边加入到集合中
    		}
    	}
    	for (map<MyMesh::HalfedgeHandle, int>::iterator mh_it = holeHalfedgeHandle.begin(); mh_it != holeHalfedgeHandle.end(); ++mh_it) {
    		if (mh_it->second == 0) {//将这个集合中还没处理过的边界点
    			halfedgeHandle.clear();// 临时处理的半边钩子清空
    			halfedgeHandle.push_back(mh_it->first);// 将边界的半边钩子放入其中
    			holeHalfedgeHandle[mh_it->first] = 1;// 将边界的半边钩子设定为已经处理
    			vertexHandle = mesh.to_vertex_handle(mh_it->first);//把正在处理的半边的来点找到
    			OpenMesh::ArrayKernel::VertexHandle to_v;
    			//选定孔洞
    			bool check = false;
    			// 重写了寻找孔洞的代码,但是有bug
    			do {
    				for (auto vh_it = mesh.voh_begin(vertexHandle); vh_it != mesh.voh_end(vertexHandle); ++vh_it) // 半边迭代器
    				{
    					OpenMesh::ArrayKernel::HalfedgeHandle h = mesh.next_halfedge_handle(*vh_it);// 这个顶点的下一条半边
    					if (mesh.is_boundary(h)) {
    						if (holeHalfedgeHandle[h] == 1) {
    							check = true;
    							break;
    						}
    						halfedgeHandle.push_back(h);
    						holeHalfedgeHandle[h] = 1;
    						vertexHandle = mesh.to_vertex_handle(h);// 下一条半边的来点(handle)
    						break;
    					}
    					else {
    						continue;
    					}
    					// 如果下一条半边的来点等于最初选定点的去点,那么整个孔洞已经遍历完毕
    					++vh_it;
    					if (vh_it == mesh.voh_end(vertexHandle))
    						check = true;
    				}
    				if (check == true) {
    					break;
    				}
    			} while (vertexHandle != mesh.to_vertex_handle(mh_it->first));// 如果上一层选定的孔洞的半边的去点 等于 此时的选定的半边的来点 说明整个孔洞已经遍历完毕了
    			vector<MyMesh::VertexHandle>ver;
    			vector<MyMesh::VertexHandle>face;
    			// 将这个孔洞的边界点都加入的数组ver中
    			for (vector<MyMesh::HalfedgeHandle>::iterator halfe = halfedgeHandle.begin(); halfe != halfedgeHandle.end(); ++halfe) {
    				vertexHandle = mesh.from_vertex_handle(*halfe);
    				ver.push_back(vertexHandle);
    			}
    			// 设定第一个点为角点(ver.end() - 1),然后构成一个平面
    			if (ver.size() <= 3) {
    				break;
    			}
    			for (vector<MyMesh::VertexHandle>::iterator v_it = ver.begin() + 1; v_it != ver.end() - 1; ++v_it) {
    				face.clear();
    				face.push_back(*(ver.end() - 1));
    				face.push_back(*(v_it - 1));
    				face.push_back(*(v_it));
    				
    				mesh.add_face(face);
    			}
    		}
    	}
    	// 将生成的新网格输出
    	if (!OpenMesh::IO::write_mesh(mesh, "rocker_result.off")) {
    		std::cerr << "Cannot write mesh to file ' rocker_result.off ' " << std::endl;
    		return 1;
    	}
    	return 0;
    }
    
    
    
    
    Hope is a good thing,maybe the best of things,and no good thing ever dies.----------- Andy Dufresne
  • 相关阅读:
    destoon自定义函数获取地区名称
    dt开发之-自定义函数获取分类名称
    dt二次开发之-地区链接伪静态标签用法
    DT二次开发之-采购页面加入好看的倒计时
    DT二次开发之-资讯列表中调用 TAG 关键词
    DT系统中tag如何使用like与%来进行模糊查询
    如何防护DDOS攻击策略
    织梦阿里云OSS解决方案
    漫画解读“跨视图粒度计算”,了解有数分析利器
    [译] 关于 SPA,你需要掌握的 4 层 (1)
  • 原文地址:https://www.cnblogs.com/eat-too-much/p/11177089.html
Copyright © 2020-2023  润新知