OpenMesh中如何利用CGAL提供的API定位距离给定点最近的面(使用AABB tree)
前言:CGAL的locate函数每调用一次都会调用建立AABB tree的函数,再在建好的树上进行点的最近面查找。因此时间就分为建树+查找两部分,建树的时间长而查找的时间短。所以如果查找操作要进行多次的话,就要判断是不是已经建立好了树,以免浪费不必要的时间。
再结合博主的特殊要求,因为项目的代码依赖于OpenMesh,在建树之前需要将OpenMesh提供的网格结构通过调用CGAL的copy_face_graph函数转化成CGAL的网格结构,这个过程和建树一样耗时且不必每次都执行,所以可以与建树操作一起被判断。
以上就是这篇博文相对于OpenMesh中如何利用CGAL提供的API定位距离给定点最近的面(不使用AABB tree)博文主要区别。
locateVertexInFace.cpp
#include <string>
#include <fstream>
#include <OpenMesh/Core/Mesh/DefaultTriMesh.hh>
#include <OpenMesh/Core/Mesh/PolyConnectivity.hh>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/Polygon_mesh_processing/locate.h>
#include <CGAL/boost/graph/copy_face_graph.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/AABB_face_graph_triangle_primitive.h>
#include <CGAL/AABB_tree.h>
#include <CGAL/AABB_traits.h>
#include "locateVertexInFace.h"
#include <windows.h>
boost::unordered_map<tm_vertex_descriptor, pm_vertex_descriptor> v2v;
boost::unordered_map<tm_halfedge_descriptor, pm_halfedge_descriptor> h2h;
boost::unordered_map< tm_face_descriptor, pm_face_descriptor> f2f;
PolyMesh CGAL_mesh;
CGAL::AABB_tree<AABB_face_graph_traits> tree;
FaceHandle locateVertexInFace(TriMesh& _OM_mesh, const double& _x, const double& _y, const double& _z) {
std::clog << "initial ==" << initial << std::endl;
if (initial == false) {//仅当定位操作第一次被执行才进行如下操作
initial = true;
// 1.将OpenMesh:TriMesh的mesh转化为CGAL:Surface_mesh<Point_3>的mesh
CGAL::copy_face_graph(_OM_mesh, CGAL_mesh,
CGAL::parameters::vertex_to_vertex_map(boost::make_assoc_property_map(v2v)).
halfedge_to_halfedge_output_iterator(std::inserter(h2h, h2h.end())).
face_to_face_map(boost::make_assoc_property_map(f2f))
);
// 2.建立AABB树,以后的定位都可以复用这棵树
PMP::build_AABB_tree(CGAL_mesh, tree);
}
const Point_3 query(_x, _y, _z);//用传入的三维坐标初始化点
LARGE_INTEGER tbg, tend, tfre;
QueryPerformanceFrequency(&tfre);
//开始计时
QueryPerformanceCounter(&tbg);
Face_location query_location = PMP::locate_with_AABB_tree(query, tree, CGAL_mesh);//核心步骤
//结束计时
QueryPerformanceCounter(&tend);
double locateTime = (double)(tend.QuadPart - tbg.QuadPart) / (double)tfre.QuadPart;
std::clog << "花费平均时是" << locateTime << "s" << std::endl;
FaceHandle faceHandle_(query_location.first);// CGAL:Face_location转化为OpenMesh:faceHandle
std::clog << faceHandle_ << std::endl;
return faceHandle_;
}
locateVertexInFace.h
#ifndef LOCATEVERTEXINFACE_H
#define LOCATEVERTEXINFACE_H
#include <OpenMesh/Core/Mesh/DefaultTriMesh.hh>
#include <OpenMesh/Core/Mesh/PolyConnectivity.hh>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/Polygon_mesh_processing/locate.h>
#include <CGAL/boost/graph/copy_face_graph.h>
#include <boost/unordered_map.hpp>
#include <CGAL/Surface_mesh.h>
#include <CGAL/boost/graph/graph_traits_TriMesh_ArrayKernelT.h>
#include <CGAL/boost/graph/graph_traits_PolyMesh_ArrayKernelT.h>
typedef OpenMesh::TriMesh TriMesh;
typedef TriMesh::FaceHandle FaceHandle;
typedef TriMesh::Point Point;
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::Point_3 Point_3;
typedef CGAL::Surface_mesh<Point_3> PolyMesh;
namespace PMP = CGAL::Polygon_mesh_processing;
typedef PMP::Face_location<PolyMesh, Kernel::FT> Face_location;
typedef boost::graph_traits<TriMesh>::vertex_descriptor tm_vertex_descriptor;
typedef boost::graph_traits<TriMesh>::halfedge_descriptor tm_halfedge_descriptor;
typedef boost::graph_traits<TriMesh>::face_descriptor tm_face_descriptor;
typedef boost::graph_traits<PolyMesh>::vertex_descriptor pm_vertex_descriptor;
typedef boost::graph_traits<PolyMesh>::halfedge_descriptor pm_halfedge_descriptor;
typedef boost::graph_traits<PolyMesh>::face_descriptor pm_face_descriptor;
typedef CGAL::AABB_face_graph_triangle_primitive<PolyMesh> AABB_face_graph_primitive;
typedef CGAL::AABB_traits<Kernel, AABB_face_graph_primitive> AABB_face_graph_traits;
FaceHandle locateVertexInFace(TriMesh& mesh, const double& _x, const double& _y, const double& _z);
static bool initial = false;
#endif
main.cpp
#include <iostream>
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/DefaultTriMesh.hh>
#include <OpenMesh/Core/Mesh/PolyConnectivity.hh>
#include "locateVertexInFace.h"
#include <windows.h>
int main() {
TriMesh mesh;
//读入文件
OpenMesh::IO::read_mesh(mesh, "E:\\3d_model_files\\1160382.off");
locateVertexInFace(mesh, 289, 302, 98);
return 0;
}
浙公网安备 33010602011771号