#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/Polygon_mesh_processing/compute_face_normal.h>
#include <CGAL/Vector_3.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_3 Point;
typedef K::Vector_3 Vector;
typedef CGAL::Surface_mesh<Point> Mesh;
#include <cmath>
float angle_between_vectors(const Vector& v1, const Vector& v2) {
float dot_product = v1 * v2;
float magnitude_v1 = v1.squared_length();
float magnitude_v2 = v2.squared_length();
float cosine_angle = dot_product / (sqrt(magnitude_v1) * sqrt(magnitude_v2));
return acos(cosine_angle);
}
bool is_concave_edge(Mesh& mesh, typename Mesh::Edge_index edge) {
// 获取边的两个相邻面
typename Mesh::Halfedge_index he = mesh.halfedge(edge);
typename Mesh::Face_index face1 = mesh.face(he);
typename Mesh::Face_index face2 = mesh.face(mesh.opposite(he));
// 计算两个面的法线
Vector normal1 = CGAL::Polygon_mesh_processing::compute_face_normal(mesh, face1);
Vector normal2 = CGAL::Polygon_mesh_processing::compute_face_normal(mesh, face2);
// 计算法线之间的角度
float angle = angle_between_vectors(normal1, normal2);
// 如果角度大于180度,则为凹边
return angle > K::pi();
}
// 最后,你可以在主函数中使用这个函数来判断特定面的特定边:
int main() {
Mesh mesh;
// 假设mesh已经被加载或构建
typename Mesh::Face_index face = /* 获取特定面的索引 */;
int edge_index = /* 获取特定边的索引 */;
if (is_concave_edge(mesh, face, edge_index)) {
std::cout << "The edge is concave." << std::endl;
} else {
std::cout << "The edge is convex." << std::endl;
}
return 0;
}
以上代码摘自Kimi的回答。自己补充了部分注释。
==================================================
另外在一段vcglib的代码中,找到了接口的另一种实现方式,如下
bool IsConcaveEdge(const FaceType& f0, int IndexE)
{
// 对三角面片来说,邻接面有三个,对应IndexE的值为{0,1,2}
FaceType* f1 = f0.cFFp(IndexE); // cFFp 是面(Face)的邻接信息属性,这里指的是边IndexE对应的邻接面
if (f1 == &f0)
{
return false;
}
CoordType N0 = f0.cN(); // cN()返回面的法向量
CoordType N1 = f1->cN();
// f0.cP1(IndexE) 获取面 f0 中边 IndexE 的第二个端点的坐标。
// f0.cP0(IndexE) 获取面 f0 中边 IndexE 的第一个端点的坐标。
CoordType EdgeDir = f0.cP1(IndexE) - f0.cP0(IndexE);
EdgeDir.Normalize();
CoordType Cross = N0 ^ N1;
// 计算两邻接面法向量的向量积与Edge方向向量的点乘
// 当两个邻接面共面的时候,是否会有问题??
// 应该不会。共面时Cross为0向量,点乘结果为0.此时的边无凹凸之分。
return ((Cross * EdgeDir) < LimitConcave);
}