# Geometry::VoronoiUtils 类概述
本模块提供Voronoi图处理工具集,主要用于处理基于线段生成的Voronoi图元数据,支持单元格范围遍历、抛物线离散化等操作。关键功能包括:
- **Voronoi单元格分析**:计算围绕线段的梯形单元格范围
- **几何转换工具**:坐标类型转换与范围校验
- **抛物线离散化**:将Voronoi抛物线边转换为折线近似
- **源数据回溯**:通过Voronoi单元反向定位输入几何元素
---
## 核心数据结构
### `SegmentCellRange<PT>`
```cpp
template<typename PT> struct SegmentCellRange {
const PT segment_start_point; // 源线段的起点
const PT segment_end_point; // 源线段的终点
const VD::edge_type *edge_begin; // 单元格遍历起始边
const VD::edge_type *edge_end; // 单元格遍历终止边
bool is_valid() const; // 验证范围有效性
};
- 作用:表示围绕输入线段的梯形Voronoi单元格边界
- 应用场景:遍历单元格周边边时作为迭代范围容器
静态工具类 VoronoiUtils
基础转换方法
static Vec2i64 to_point(const VD::vertex_type *vertex);
static bool is_finite(const VD::vertex_type &vertex);
- 实现细节:处理Boost.Polygon的double精度坐标到整型的转换
几何变换
static VD::vertex_type make_rotated_vertex(VD::vertex_type &vertex, double angle);
- 功能:创建旋转后的顶点副本
- 参数:
angle
为弧度制的旋转角度
源数据回溯
template<typename SIter>
static auto get_source_segment(...);
template<typename SIter>
static auto get_source_point(...);
template<typename SIter>
static auto get_source_point_index(...);
- 核心逻辑:通过
cell.source_index()
反向查找输入线段集合中的对应元素
抛物线离散化
template<typename Segment>
static Points discretize_parabola(...);
- 参数:
source_point
:抛物线焦点(输入线段端点)source_segment
:输入线段start/end
:抛物线起止点approximate_step_size
:沿线段方向的离散步长
- 输出:离散化后的点序列
单元格范围计算
template<typename SIter>
static SegmentCellRange<...> compute_segment_cell_range(...);
- 流程:
- 通过
cell.incident_edge()
遍历关联边 - 过滤有效边建立循环范围
- 返回包含源线段信息的
SegmentCellRange
数值范围校验
template<typename T> static bool is_in_range(double value);
template<typename T> static bool is_in_range(const VD::vertex_type &vertex);
template<typename T> static bool is_in_range(const VD::edge_type &edge);
- 作用:验证坐标是否在目标类型(T)的可表示范围内
- 特化应用:防止整型溢出时使用
关键技术点
Voronoi单元格遍历
- 双指针标记法:
edge_begin
和edge_end
定义半开区间[begin, end)
- 循环终止条件:通过
next->twin()->next()
链式遍历直到回到起点
抛物线近似算法
- 自适应步长:根据
transitioning_angle
动态调整离散密度 - 几何变换:将抛物线方程转换为参数形式计算采样点
类型安全处理
- SFINAE约束:通过
boost::polygon
类型特征确保模板参数符合线段概念 - 坐标溢出防护:
is_in_range<T>
模板方法实现编译期类型安全检查
典型应用流程
- 获取单元格源数据
auto& cell = vd.cells()[0];
auto src_segment = VoronoiUtils::get_source_segment(cell, lines.begin(), lines.end());
- 计算单元格边界范围
auto range = VoronoiUtils::compute_segment_cell_range(cell, lines.begin(), lines.end());
for (auto* edge = range.edge_begin; edge != range.edge_end; edge = edge->next()) {
}
- 离散化抛物线边
Points discretized = VoronoiUtils::discretize_parabola(
source_point, source_segment,
start_point, end_point,
0.1mm, 15.0f);
- 坐标安全转换
if (VoronoiUtils::is_in_range<int32_t>(vertex)) {
Point pt = VoronoiUtils::to_point(vertex).cast<int32_t>();
}
性能优化策略
- 惰性计算:
compute_segment_cell_range
仅在需要时遍历边 - 内存预判:
discretize_parabola
通过角度预判分配点容器大小 - 分支预测:
is_finite
快速过滤无限顶点避免复杂计算