相关章节: CGAL的STL扩展 | 循环迭代器 | 属性映射 | 组合地图 | 曲面网格

3.4 半边数据结构(HalfedgeDS)

1. 理论基础

1.1 半边数据结构的数学定义

半边数据结构(Halfedge Data Structure)是计算几何中表示多边形网格的一种高效拓扑数据结构。其核心思想是将每条边分解为两条方向相反的半边(Halfedge)

定义 1.1(半边):半边是一个有向边,定义为有序对 ,其中 是源顶点, 是目标顶点。

定义 1.2(对边):对于半边 ,其对边 满足:

定义 1.3(面):面是由半边组成的闭合环路,满足:

  • 对于面 的边界上的半边 ,有
  • 对于最后一个半边 ,有

1.2 连接关系的数学表示

半边数据结构通过以下连接关系定义拓扑:

关系数学定义说明
next(h)绕面的下一条半边逆时针方向
prev(h)绕面的上一条半边逆时针方向
opposite(h)对边反向半边
vertex(h)半边指向的顶点 的目标顶点
face(h)半边所属的面左侧面

定理 1.1(拓扑完备性):给定任意半边 ,可以通过以下操作访问所有关联元素:

  • 顶点:
  • 相邻面:
  • 相邻顶点(one-ring):

1.3 欧拉公式验证

对于闭合的流形网格,半边数据结构满足欧拉公式:

其中:

  • = 顶点数
  • = 边数(半边数 / 2)
  • = 面数
  • = 亏格(genus,洞的个数)

在半边数据结构中:

  • 半边数
  • 每个面有 条半边,总半边数

2. 架构分析

2.1 HalfedgeDS类层次结构

HalfedgeDS概念体系
├── HalfedgeDS(概念)
│   ├── Vertex
│   ├── Halfedge
│   └── Face
│
├── 具体实现
│   ├── HalfedgeDS_default<Traits, Items, Alloc>
│   │   └── HalfedgeDS_list<Traits, Items, Alloc>
│   ├── HalfedgeDS_vector<Traits, Items, Alloc>
│   └── HalfedgeDS_list_types<Traits, Items, Alloc>
│
├── Items(可定制项)
│   ├── HalfedgeDS_items_2(默认)
│   ├── HalfedgeDS_min_items
│   └── 自定义Items
│
└── 基类
    ├── HalfedgeDS_vertex_base<Refs>
    ├── HalfedgeDS_halfedge_base<Refs>
    └── HalfedgeDS_face_base<Refs>

2.2 内存布局

// 半边结构内存布局
struct Halfedge {
    Halfedge_handle next;       // 下一条半边(绕面)
    Halfedge_handle opposite;   // 对边
    Halfedge_handle prev;       // 上一条半边(可选)
    Vertex_handle vertex;       // 指向的顶点
    Face_handle face;           // 所属的面
};
 
// 顶点结构内存布局
struct Vertex {
    Halfedge_handle halfedge;   // 一条 outgoing 半边
    Point point;                // 几何位置
    // 其他属性...
};
 
// 面结构内存布局
struct Face {
    Halfedge_handle halfedge;   // 边界上的一条半边
    // 其他属性...
};

2.3 句柄(Handle)系统

CGAL使用句柄而非原始指针来引用元素:

template<typename Index>
class Handle {
    Index idx;  // 内部索引
public:
    explicit Handle(Index i) : idx(i) {}
    Index idx() const { return idx; }
    bool is_valid() const { return idx != -1; }
    
    // 比较操作
    bool operator==(const Handle& h) const { return idx == h.idx; }
    bool operator!=(const Handle& h) const { return idx != h.idx; }
    bool operator<(const Handle& h) const { return idx < h.idx; }
};

句柄类型:

  • Vertex_handle / Vertex_const_handle
  • Halfedge_handle / Halfedge_const_handle
  • Face_handle / Face_const_handle

3. 实现细节

3.1 HalfedgeDS_list实现

// 文件: CGAL/HalfedgeDS_list.h
 
namespace CGAL {
 
template<class Traits_, class HalfedgeDSItems, class Alloc>
class HalfedgeDS_list_types {
public:
    typedef Traits_ Traits;
    typedef HalfedgeDSItems Items;
    typedef Alloc Allocator;
    
    // 使用Items包装器定义具体类型
    typedef typename Items::template Vertex_wrapper<Self, Traits> Vertex_wrapper;
    typedef typename Items::template Halfedge_wrapper<Self, Traits> Halfedge_wrapper;
    typedef typename Items::template Face_wrapper<Self, Traits> Face_wrapper;
    
    // 定义具体类型
    typedef typename Vertex_wrapper::Vertex Vertex_base;
    typedef HalfedgeDS_in_place_list_vertex<Vertex_base> Vertex;
    typedef typename Halfedge_wrapper::Halfedge Halfedge_base;
    typedef HalfedgeDS_in_place_list_halfedge<Halfedge_base> Halfedge;
    typedef typename Face_wrapper::Face Face_base;
    typedef HalfedgeDS_in_place_list_face<Face_base> Face;
    
    // 定义列表类型
    typedef In_place_list<Vertex, false, Vertex_allocator> Vertex_list;
    typedef In_place_list<Halfedge, false, Halfedge_allocator> Halfedge_list;
    typedef In_place_list<Face, false, Face_allocator> Face_list;
    
    // 定义句柄类型
    typedef typename Vertex_list::iterator Vertex_handle;
    typedef typename Vertex_list::const_iterator Vertex_const_handle;
    typedef typename Halfedge_list::iterator Halfedge_handle;
    typedef typename Halfedge_list::const_iterator Halfedge_const_handle;
    typedef typename Face_list::iterator Face_handle;
    typedef typename Face_list::const_iterator Face_const_handle;
};
 
template<class Traits_, class HalfedgeDSItems, class Alloc>
class HalfedgeDS_list : public HalfedgeDS_list_types<Traits_, HalfedgeDSItems, Alloc> {
public:
    typedef HalfedgeDS_list<Traits_, HalfedgeDSItems, Alloc> Self;
    typedef HalfedgeDS_list_types<Traits_, HalfedgeDSItems, Alloc> Types;
    
    typedef typename Types::Vertex Vertex;
    typedef typename Types::Halfedge Halfedge;
    typedef typename Types::Face Face;
    
    typedef typename Types::Vertex_handle Vertex_handle;
    typedef typename Types::Halfedge_handle Halfedge_handle;
    typedef typename Types::Face_handle Face_handle;
    
    typedef Iterator_range<Prevent_deref<Vertex_iterator>> Vertex_handles;
    typedef Iterator_range<Prevent_deref<Halfedge_iterator>> Halfedge_handles;
    typedef Iterator_range<Prevent_deref<Face_iterator>> Face_handles;
    
    // 支持的特性标签
    typedef Tag_true Supports_removal;
    typedef typename Vertex::Supports_vertex_halfedge Supports_vertex_halfedge;
    typedef typename Halfedge::Supports_halfedge_prev Supports_halfedge_prev;
    typedef typename Halfedge::Supports_halfedge_vertex Supports_halfedge_vertex;
    typedef typename Halfedge::Supports_halfedge_face Supports_halfedge_face;
    typedef typename Face::Supports_face_halfedge Supports_face_halfedge;
 
private:
    Vertex_allocator vertex_allocator;
    Edge_allocator edge_allocator;  // 分配半边对
    Face_allocator face_allocator;
    
    Vertex_list vertices;
    Halfedge_list halfedges;
    Face_list faces;
    
    size_type nb_border_halfedges;
    size_type nb_border_edges;
    Halfedge_iterator border_halfedges;
 
public:
    // 构造函数
    HalfedgeDS_list() : nb_border_halfedges(0), nb_border_edges(0) {}
    
    HalfedgeDS_list(size_type v, size_type h, size_type f)
        : nb_border_halfedges(0), nb_border_edges(0) {}
    
    // 访问函数
    size_type size_of_vertices() const { return vertices.size(); }
    size_type size_of_halfedges() const { return halfedges.size(); }
    size_type size_of_faces() const { return faces.size(); }
    
    // 迭代器
    Vertex_iterator vertices_begin() { return vertices.begin(); }
    Vertex_iterator vertices_end() { return vertices.end(); }
    Vertex_handles vertex_handles() {
        return make_prevent_deref_range(vertices_begin(), vertices_end());
    }
    
    Halfedge_iterator halfedges_begin() { return halfedges.begin(); }
    Halfedge_iterator halfedges_end() { return halfedges.end(); }
    Halfedge_handles halfedge_handles() {
        return make_prevent_deref_range(halfedges_begin(), halfedges_end());
    }
    
    Face_iterator faces_begin() { return faces.begin(); }
    Face_iterator faces_end() { return faces.end(); }
    Face_handles face_handles() {
        return make_prevent_deref_range(faces_begin(), faces_end());
    }
    
    // 插入操作
    Vertex_handle vertices_push_back(const Vertex& v) {
        vertices.push_back(*get_vertex_node(v));
        Vertex_handle vh = vertices.end();
        return --vh;
    }
    
    // 半边总是成对分配
    std::pair<Halfedge_handle, Halfedge_handle> edges_push_back() {
        Halfedge h, g;  // g是h的对边
        Halfedge* h2 = get_edge_node(h, g);
        Halfedge* g2 = h2 + 1;
        halfedges.push_back(*h2);
        halfedges.push_back(*g2);
        Halfedge_handle hh = halfedges.end();
        --hh; --hh;
        Halfedge_handle gg = halfedges.end();
        --gg;
        return std::make_pair(hh, gg);
    }
    
    Face_handle faces_push_back(const Face& f) {
        faces.push_back(*get_face_node(f));
        Face_handle fh = faces.end();
        return --fh;
    }
    
    // 遍历操作
    Halfedge_handle next(Halfedge_handle h) const { return h->next(); }
    Halfedge_handle prev(Halfedge_handle h) const { return h->prev(); }
    Halfedge_handle opposite(Halfedge_handle h) const { return h->opposite(); }
    Vertex_handle vertex(Halfedge_handle h) const { return h->vertex(); }
    Face_handle face(Halfedge_handle h) const { return h->face(); }
};
 
// 默认实现
template<class Traits_, class HalfedgeDSItems = HalfedgeDS_items_2, class Alloc = CGAL_ALLOCATOR(int)>
class HalfedgeDS_default : public HalfedgeDS_list<Traits_, HalfedgeDSItems, Alloc> {
public:
    typedef Traits_ Traits;
    typedef HalfedgeDS_list<Traits_, HalfedgeDSItems, Alloc> D_S;
    typedef typename D_S::size_type size_type;
    
    HalfedgeDS_default() {}
    HalfedgeDS_default(size_type v, size_type h, size_type f)
        : HalfedgeDS_list<Traits_, HalfedgeDSItems, Alloc>(v, h, f) {}
};
 
} // namespace CGAL

3.2 遍历操作实现

// 文件: CGAL/HalfedgeDS_items_decorator.h
 
namespace CGAL {
 
// 半边装饰器,提供额外的遍历操作
template<class HDS>
class HalfedgeDS_items_decorator {
public:
    typedef HDS Halfedge_data_structure;
    typedef typename HDS::Vertex_handle Vertex_handle;
    typedef typename HDS::Halfedge_handle Halfedge_handle;
    typedef typename HDS::Face_handle Face_handle;
    
    // 绕面遍历
    void iterate_around_face(Halfedge_handle h, auto&& f) {
        Halfedge_handle start = h;
        do {
            f(h);
            h = h->next();
        } while (h != start);
    }
    
    // 顶点one-ring遍历
    void iterate_vertex_one_ring(Vertex_handle v, auto&& f) {
        Halfedge_handle h = v->halfedge();
        Halfedge_handle start = h;
        do {
            // 获取相邻顶点(通过opposite->vertex)
            Vertex_handle neighbor = h->opposite()->vertex();
            f(neighbor);
            // 移动到下一个outgoing半边
            h = h->opposite()->next();
        } while (h != start);
    }
    
    // 边遍历(跳过对边)
    void iterate_edges(HDS& hds, auto&& f) {
        for (auto h = hds.halfedges_begin(); h != hds.halfedges_end(); ++h) {
            // 只处理"主"半边(例如索引较小的)
            if (h < h->opposite()) {
                f(h);
            }
        }
    }
    
    // 获取顶点的度数
    std::size_t vertex_degree(Vertex_handle v) {
        std::size_t degree = 0;
        Halfedge_handle h = v->halfedge();
        Halfedge_handle start = h;
        do {
            ++degree;
            h = h->opposite()->next();
        } while (h != start);
        return degree;
    }
    
    // 获取面的边数
    std::size_t face_degree(Face_handle f) {
        std::size_t degree = 0;
        Halfedge_handle h = f->halfedge();
        Halfedge_handle start = h;
        do {
            ++degree;
            h = h->next();
        } while (h != start);
        return degree;
    }
};
 
} // namespace CGAL

3.3 自定义HalfedgeDS Items

// 文件: 自定义Items示例
 
#include <CGAL/HalfedgeDS_items_2.h>
#include <CGAL/HalfedgeDS_halfedge_base.h>
#include <CGAL/HalfedgeDS_vertex_base.h>
#include <CGAL/HalfedgeDS_face_base.h>
 
// 自定义顶点,包含颜色和法向量
template<class Refs, class Traits>
class My_vertex : public CGAL::HalfedgeDS_vertex_base<Refs, CGAL::Tag_true, typename Traits::Point_3> {
public:
    typedef CGAL::HalfedgeDS_vertex_base<Refs, CGAL::Tag_true, typename Traits::Point_3> Base;
    typedef typename Traits::Vector_3 Vector_3;
    typedef typename Traits::Color Color;
    
    My_vertex() : Base(), color(0, 0, 0), normal(0, 0, 0) {}
    explicit My_vertex(const typename Traits::Point_3& p) : Base(p), color(0, 0, 0), normal(0, 0, 0) {}
    
    Color color;
    Vector_3 normal;
};
 
// 自定义半边,包含边标记
template<class Refs>
class My_halfedge : public CGAL::HalfedgeDS_halfedge_base<Refs> {
public:
    typedef CGAL::HalfedgeDS_halfedge_base<Refs> Base;
    
    My_halfedge() : Base(), is_sharp(false), edge_weight(1.0) {}
    
    bool is_sharp;
    double edge_weight;
};
 
// 自定义面,包含面标记和材质ID
template<class Refs, class Traits>
class My_face : public CGAL::HalfedgeDS_face_base<Refs> {
public:
    typedef CGAL::HalfedgeDS_face_base<Refs> Base;
    typedef typename Traits::Vector_3 Vector_3;
    
    My_face() : Base(), material_id(0), area(0.0) {}
    
    int material_id;
    double area;
    Vector_3 normal;
};
 
// 自定义Items
template<class Traits>
struct My_items : public CGAL::HalfedgeDS_items_2 {
    template<class Refs, class T>
    struct Vertex_wrapper {
        typedef My_vertex<Refs, T> Vertex;
    };
    
    template<class Refs, class T>
    struct Halfedge_wrapper {
        typedef My_halfedge<Refs> Halfedge;
    };
    
    template<class Refs, class T>
    struct Face_wrapper {
        typedef My_face<Refs, T> Face;
    };
};

4. 使用示例

4.1 示例1:基本HalfedgeDS使用

#include <CGAL/HalfedgeDS_default.h>
#include <CGAL/HalfedgeDS_decorator.h>
#include <CGAL/Simple_cartesian.h>
#include <iostream>
 
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_3 Point_3;
 
// 定义HalfedgeDS类型
struct Traits {
    typedef Point_3 Point_3;
};
 
typedef CGAL::HalfedgeDS_default<Traits> HDS;
typedef CGAL::HalfedgeDS_decorator<HDS> Decorator;
typedef HDS::Vertex_handle Vertex_handle;
typedef HDS::Halfedge_handle Halfedge_handle;
typedef HDS::Face_handle Face_handle;
 
int main() {
    HDS hds;
    Decorator decorator(hds);
    
    // 创建四面体的顶点
    Vertex_handle v0 = hds.vertices_push_back(Vertex_handle::value_type(Point_3(0, 0, 0)));
    Vertex_handle v1 = hds.vertices_push_back(Vertex_handle::value_type(Point_3(1, 0, 0)));
    Vertex_handle v2 = hds.vertices_push_back(Vertex_handle::value_type(Point_3(0, 1, 0)));
    Vertex_handle v3 = hds.vertices_push_back(Vertex_handle::value_type(Point_3(0, 0, 1)));
    
    std::cout << "Created " << hds.size_of_vertices() << " vertices" << std::endl;
    
    // 创建面(需要正确连接半边)
    // 创建第一个面 (v0, v1, v2)
    auto edge_pair1 = hds.edges_push_back();
    auto edge_pair2 = hds.edges_push_back();
    auto edge_pair3 = hds.edges_push_back();
    
    Halfedge_handle h0 = edge_pair1.first;
    Halfedge_handle h1 = edge_pair2.first;
    Halfedge_handle h2 = edge_pair3.first;
    
    // 设置半边连接
    h0->set_next(h1);
    h1->set_next(h2);
    h2->set_next(h0);
    
    h0->set_prev(h2);
    h1->set_prev(h0);
    h2->set_prev(h1);
    
    // 设置顶点
    h0->set_vertex(v1);
    h1->set_vertex(v2);
    h2->set_vertex(v0);
    
    // 创建面
    Face_handle f0 = hds.faces_push_back(Face_handle::value_type());
    f0->set_halfedge(h0);
    h0->set_face(f0);
    h1->set_face(f0);
    h2->set_face(f0);
    
    // 设置顶点的halfedge
    v0->set_halfedge(h2);
    v1->set_halfedge(h0);
    v2->set_halfedge(h1);
    
    std::cout << "Created " << hds.size_of_faces() << " face" << std::endl;
    std::cout << "Total halfedges: " << hds.size_of_halfedges() << std::endl;
    
    // 遍历面的边界
    std::cout << "\nFace boundary vertices:" << std::endl;
    Halfedge_handle h = f0->halfedge();
    Halfedge_handle start = h;
    int count = 0;
    do {
        Point_3 p = h->vertex()->point();
        std::cout << "  Vertex " << count++ << ": (" 
                  << p.x() << ", " << p.y() << ", " << p.z() << ")" << std::endl;
        h = h->next();
    } while (h != start);
    
    return 0;
}

4.2 示例2:面遍历和顶点one-ring遍历

#include <CGAL/HalfedgeDS_default.h>
#include <CGAL/HalfedgeDS_decorator.h>
#include <CGAL/Simple_cartesian.h>
#include <vector>
#include <iostream>
 
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_3 Point_3;
 
template<class HDS>
class MeshTraversal {
    typedef typename HDS::Vertex_handle Vertex_handle;
    typedef typename HDS::Halfedge_handle Halfedge_handle;
    typedef typename HDS::Face_handle Face_handle;
    
    HDS& hds;
    
public:
    explicit MeshTraversal(HDS& h) : hds(h) {}
    
    // 遍历面的所有顶点
    template<typename Func>
    void traverse_face_vertices(Face_handle f, Func&& func) {
        Halfedge_handle h = f->halfedge();
        Halfedge_handle start = h;
        do {
            func(h->vertex());
            h = h->next();
        } while (h != start);
    }
    
    // 遍历面的所有边
    template<typename Func>
    void traverse_face_edges(Face_handle f, Func&& func) {
        Halfedge_handle h = f->halfedge();
        Halfedge_handle start = h;
        do {
            func(h);
            h = h->next();
        } while (h != start);
    }
    
    // 遍历顶点的one-ring邻居
    template<typename Func>
    void traverse_vertex_one_ring(Vertex_handle v, Func&& func) {
        Halfedge_handle h = v->halfedge();
        if (h == Halfedge_handle()) return;  // 孤立顶点
        
        Halfedge_handle start = h;
        do {
            // 获取相邻顶点(通过opposite->vertex)
            Vertex_handle neighbor = h->opposite()->vertex();
            func(neighbor);
            // 移动到下一个outgoing半边
            h = h->opposite()->next();
        } while (h != start);
    }
    
    // 遍历顶点的邻接面
    template<typename Func>
    void traverse_vertex_faces(Vertex_handle v, Func&& func) {
        Halfedge_handle h = v->halfedge();
        if (h == Halfedge_handle()) return;
        
        Halfedge_handle start = h;
        do {
            Face_handle f = h->face();
            if (f != Face_handle()) {
                func(f);
            }
            h = h->opposite()->next();
        } while (h != start);
    }
    
    // 获取顶点度数
    std::size_t get_vertex_degree(Vertex_handle v) {
        std::size_t degree = 0;
        traverse_vertex_one_ring(v, [&](Vertex_handle) { ++degree; });
        return degree;
    }
    
    // 计算面的面积(三角形)
    double compute_triangle_area(Face_handle f) {
        std::vector<Point_3> points;
        traverse_face_vertices(f, [&](Vertex_handle v) {
            points.push_back(v->point());
        });
        
        if (points.size() != 3) return 0.0;
        
        Kernel::Vector_3 v0 = points[1] - points[0];
        Kernel::Vector_3 v1 = points[2] - points[0];
        Kernel::Vector_3 cross = CGAL::cross_product(v0, v1);
        return std::sqrt(cross.squared_length()) / 2.0;
    }
};
 
// 使用示例
int main() {
    // 假设已经创建了一个HDS对象hds
    // 这里仅展示遍历函数的用法
    
    std::cout << "MeshTraversal functions:" << std::endl;
    std::cout << "  - traverse_face_vertices: 遍历面的所有顶点" << std::endl;
    std::cout << "  - traverse_face_edges: 遍历面的所有边" << std::endl;
    std::cout << "  - traverse_vertex_one_ring: 遍历顶点的one-ring邻居" << std::endl;
    std::cout << "  - traverse_vertex_faces: 遍历顶点的邻接面" << std::endl;
    std::cout << "  - get_vertex_degree: 获取顶点度数" << std::endl;
    std::cout << "  - compute_triangle_area: 计算三角形面积" << std::endl;
    
    return 0;
}

4.3 示例3:自定义HalfedgeDS Items

#include <CGAL/HalfedgeDS_default.h>
#include <CGAL/HalfedgeDS_decorator.h>
#include <CGAL/Simple_cartesian.h>
#include <iostream>
 
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_3 Point_3;
typedef Kernel::Vector_3 Vector_3;
 
// 颜色结构
struct Color {
    unsigned char r, g, b;
    Color(unsigned char r = 0, unsigned char g = 0, unsigned char b = 0)
        : r(r), g(g), b(b) {}
};
 
// 自定义顶点
template<class Refs, class Traits>
class Custom_vertex : public CGAL::HalfedgeDS_vertex_base<Refs, CGAL::Tag_true, Point_3> {
public:
    typedef CGAL::HalfedgeDS_vertex_base<Refs, CGAL::Tag_true, Point_3> Base;
    
    Custom_vertex() : Base(), color(255, 255, 255), normal(0, 0, 0), selected(false) {}
    explicit Custom_vertex(const Point_3& p) : Base(p), color(255, 255, 255), normal(0, 0, 0), selected(false) {}
    
    Color color;
    Vector_3 normal;
    bool selected;
    int id = -1;
};
 
// 自定义半边
template<class Refs>
class Custom_halfedge : public CGAL::HalfedgeDS_halfedge_base<Refs> {
public:
    typedef CGAL::HalfedgeDS_halfedge_base<Refs> Base;
    
    Custom_halfedge() : Base(), is_sharp(false), edge_weight(1.0), visited(false) {}
    
    bool is_sharp;
    double edge_weight;
    bool visited;
    int edge_id = -1;
};
 
// 自定义面
template<class Refs, class Traits>
class Custom_face : public CGAL::HalfedgeDS_face_base<Refs> {
public:
    typedef CGAL::HalfedgeDS_face_base<Refs> Base;
    
    Custom_face() : Base(), material_id(0), area(0.0), visible(true) {}
    
    int material_id;
    double area;
    Vector_3 normal;
    bool visible;
};
 
// 自定义Items
template<class Traits>
struct Custom_items : public CGAL::HalfedgeDS_items_2 {
    template<class Refs, class T>
    struct Vertex_wrapper {
        typedef Custom_vertex<Refs, T> Vertex;
    };
    
    template<class Refs, class T>
    struct Halfedge_wrapper {
        typedef Custom_halfedge<Refs> Halfedge;
    };
    
    template<class Refs, class T>
    struct Face_wrapper {
        typedef Custom_face<Refs, T> Face;
    };
};
 
// 使用自定义Items的HDS
struct Traits {
    typedef Point_3 Point_3;
    typedef Vector_3 Vector_3;
    typedef Color Color;
};
 
typedef CGAL::HalfedgeDS_default<Traits, Custom_items<Traits>> Custom_HDS;
typedef Custom_HDS::Vertex_handle Vertex_handle;
typedef Custom_HDS::Halfedge_handle Halfedge_handle;
typedef Custom_HDS::Face_handle Face_handle;
 
int main() {
    Custom_HDS hds;
    
    // 创建顶点
    Vertex_handle v0 = hds.vertices_push_back(Custom_vertex<Point_3>(Point_3(0, 0, 0)));
    Vertex_handle v1 = hds.vertices_push_back(Custom_vertex<Point_3>(Point_3(1, 0, 0)));
    Vertex_handle v2 = hds.vertices_push_back(Custom_vertex<Point_3>(Point_3(0, 1, 0)));
    
    // 设置自定义属性
    v0->color = Color(255, 0, 0);
    v1->color = Color(0, 255, 0);
    v2->color = Color(0, 0, 255);
    
    v0->id = 0;
    v1->id = 1;
    v2->id = 2;
    
    v0->selected = true;
    
    // 计算并设置法向量
    Vector_3 n = CGAL::cross_product(v1->point() - v0->point(), v2->point() - v0->point());
    v0->normal = n;
    v1->normal = n;
    v2->normal = n;
    
    // 输出顶点信息
    std::cout << "Vertex information:" << std::endl;
    for (auto v = hds.vertices_begin(); v != hds.vertices_end(); ++v) {
        std::cout << "  Vertex " << v->id << ":" << std::endl;
        std::cout << "    Position: (" << v->point().x() << ", " 
                  << v->point().y() << ", " << v->point().z() << ")" << std::endl;
        std::cout << "    Color: RGB(" << (int)v->color.r << ", " 
                  << (int)v->color.g << ", " << (int)v->color.b << ")" << std::endl;
        std::cout << "    Selected: " << (v->selected ? "yes" : "no") << std::endl;
    }
    
    return 0;
}

4.4 示例4:半边数据结构构建完整网格

#include <CGAL/HalfedgeDS_default.h>
#include <CGAL/HalfedgeDS_decorator.h>
#include <CGAL/Simple_cartesian.h>
#include <vector>
#include <iostream>
 
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_3 Point_3;
 
template<class HDS>
class MeshBuilder {
    typedef typename HDS::Vertex_handle Vertex_handle;
    typedef typename HDS::Halfedge_handle Halfedge_handle;
    typedef typename HDS::Face_handle Face_handle;
    
    HDS& hds;
    CGAL::HalfedgeDS_decorator<HDS> decorator;
    
public:
    explicit MeshBuilder(HDS& h) : hds(h), decorator(h) {}
    
    // 添加顶点
    Vertex_handle add_vertex(const Point_3& p) {
        return hds.vertices_push_back(typename HDS::Vertex(p));
    }
    
    // 添加面(假设顶点已存在)
    Face_handle add_face(const std::vector<Vertex_handle>& vertices) {
        std::size_t n = vertices.size();
        if (n < 3) return Face_handle();
        
        // 创建半边
        std::vector<Halfedge_handle> halfedges;
        for (std::size_t i = 0; i < n; ++i) {
            auto edge_pair = hds.edges_push_back();
            halfedges.push_back(edge_pair.first);
        }
        
        // 连接半边形成环
        for (std::size_t i = 0; i < n; ++i) {
            halfedges[i]->set_next(halfedges[(i + 1) % n]);
            halfedges[i]->set_prev(halfedges[(i + n - 1) % n]);
            halfedges[i]->set_vertex(vertices[(i + 1) % n]);
        }
        
        // 创建面
        Face_handle f = hds.faces_push_back(typename HDS::Face());
        f->set_halfedge(halfedges[0]);
        
        // 设置面的半边
        for (auto h : halfedges) {
            h->set_face(f);
        }
        
        // 更新顶点的halfedge指针
        for (std::size_t i = 0; i < n; ++i) {
            vertices[i]->set_halfedge(halfedges[(i + n - 1) % n]);
        }
        
        return f;
    }
    
    // 验证网格完整性
    bool validate() {
        // 检查每个顶点的halfedge
        for (auto v = hds.vertices_begin(); v != hds.vertices_end(); ++v) {
            if (v->halfedge() == Halfedge_handle()) {
                std::cerr << "Vertex has no halfedge" << std::endl;
                return false;
            }
            if (v->halfedge()->vertex() != v) {
                std::cerr << "Vertex halfedge inconsistency" << std::endl;
                return false;
            }
        }
        
        // 检查每个面的halfedge
        for (auto f = hds.faces_begin(); f != hds.faces_end(); ++f) {
            if (f->halfedge() == Halfedge_handle()) {
                std::cerr << "Face has no halfedge" << std::endl;
                return false;
            }
            if (f->halfedge()->face() != f) {
                std::cerr << "Face halfedge inconsistency" << std::endl;
                return false;
            }
        }
        
        // 检查半边连接
        for (auto h = hds.halfedges_begin(); h != hds.halfedges_end(); ++h) {
            if (h->next()->prev() != h) {
                std::cerr << "Halfedge next/prev inconsistency" << std::endl;
                return false;
            }
            if (h->opposite()->opposite() != h) {
                std::cerr << "Halfedge opposite inconsistency" << std::endl;
                return false;
            }
        }
        
        return true;
    }
    
    // 统计信息
    void print_statistics() {
        std::cout << "Mesh Statistics:" << std::endl;
        std::cout << "  Vertices: " << hds.size_of_vertices() << std::endl;
        std::cout << "  Halfedges: " << hds.size_of_halfedges() << std::endl;
        std::cout << "  Edges: " << hds.size_of_halfedges() / 2 << std::endl;
        std::cout << "  Faces: " << hds.size_of_faces() << std::endl;
        
        // 计算欧拉示性数
        int V = hds.size_of_vertices();
        int E = hds.size_of_halfedges() / 2;
        int F = hds.size_of_faces();
        int chi = V - E + F;
        std::cout << "  Euler characteristic: " << chi << std::endl;
    }
};
 
int main() {
    typedef CGAL::HalfedgeDS_default<Traits> HDS;
    HDS hds;
    MeshBuilder<HDS> builder(hds);
    
    // 创建四面体
    auto v0 = builder.add_vertex(Point_3(0, 0, 0));
    auto v1 = builder.add_vertex(Point_3(1, 0, 0));
    auto v2 = builder.add_vertex(Point_3(0, 1, 0));
    auto v3 = builder.add_vertex(Point_3(0, 0, 1));
    
    // 添加四个面
    builder.add_face({v0, v1, v2});
    builder.add_face({v0, v1, v3});
    builder.add_face({v0, v2, v3});
    builder.add_face({v1, v2, v3});
    
    // 验证和输出
    std::cout << "Validation: " << (builder.validate() ? "PASSED" : "FAILED") << std::endl;
    builder.print_statistics();
    
    return 0;
}

5. 复杂度分析

5.1 时间复杂度

操作复杂度说明
创建顶点O(1)列表尾部插入
创建半边对O(1)分配和初始化
创建面O(k)k为面的边数
next/prev/oppositeO(1)直接指针访问
vertex/faceO(1)直接指针访问
绕面遍历O(k)k为面的边数
one-ring遍历O(d)d为顶点度数
边遍历O(E)E为边数

5.2 空间复杂度

元素空间说明
Vertex1 × sizeof(void*) + Pointhalfedge指针 + 几何
Halfedge4 × sizeof(void*)next, prev, opposite, vertex, face
Face1 × sizeof(void*)halfedge指针
总计O(V + H + F) ≈ O(V + F)H ≈ 2E ≈ 3F(三角形网格)

5.3 与其他数据结构的对比

特性HalfedgeDSWinged-edgeQuad-edgeCorner Table
半边表示
面遍历O(k)O(k)O(k)O(k)
顶点one-ringO(d)O(d)O(d)O(d)
内存效率
边界处理自然复杂自然需要特殊处理
实现复杂度

6. 关键文件位置

文件路径说明
HalfedgeDS/include/CGAL/HalfedgeDS_default.h默认HalfedgeDS实现
HalfedgeDS/include/CGAL/HalfedgeDS_list.h基于列表的实现
HalfedgeDS/include/CGAL/HalfedgeDS_vector.h基于向量的实现
HalfedgeDS/include/CGAL/HalfedgeDS_items_2.h默认Items定义
HalfedgeDS/include/CGAL/HalfedgeDS_decorator.h遍历装饰器
HalfedgeDS/include/CGAL/HalfedgeDS_vertex_base.h顶点基类
HalfedgeDS/include/CGAL/HalfedgeDS_halfedge_base.h半边基类
HalfedgeDS/include/CGAL/HalfedgeDS_face_base.h面基类
HalfedgeDS/include/CGAL/HalfedgeDS_iterator.h迭代器定义

7. 最佳实践

7.1 使用建议

  1. 使用HalfedgeDS_decorator简化遍历

    CGAL::HalfedgeDS_decorator<HDS> decorator(hds);
    decorator.iterate_around_face(h, [&](auto v) { ... });
  2. 自定义Items时继承基类

    class My_vertex : public CGAL::HalfedgeDS_vertex_base<Refs, CGAL::Tag_true, Point> {
        // 自定义属性
    };
  3. 验证网格完整性

    assert(decorator.is_valid());
  4. 使用句柄而非指针

    Vertex_handle v = ...;  // 推荐
    // 而非 Vertex* v = ...;

7.2 常见陷阱

  1. 忘记设置对边

    // 错误:半边对需要正确链接
    auto pair = hds.edges_push_back();
    // 对边已经自动链接,不需要手动设置
  2. 边界处理

    // 边界半边的face()返回空句柄
    if (h->face() == Face_handle()) {
        // 这是边界半边
    }
  3. 顶点halfedge选择

    // 顶点的halfedge()可以是任意一条outgoing半边
    // 如果需要特定半边,需要手动遍历