BambuStudio学习笔记:MarchingSquares类
# Marching Squares算法头文件分析
## 文件结构概览
```cpp
#ifndef MARCHINGSQUARES_HPP
#define MARCHINGSQUARES_HPP
// 包含标准库头文件
// 命名空间定义
namespace marchsq {
// 基础数据结构
struct Coord;
using Ring = std::vector<Coord>;
// 栅格适配器模板
template<class T, class Enable> struct _RasterTraits;
template<class ExecutionPolicy, class Enable> struct _Loop;
namespace __impl {
// 核心算法实现
enum class SquareTag : uint8_t; // 单元格状态标记
enum class Dir: uint8_t; // 遍历方向
template<class Rst> class Grid; // 网格处理核心类
}
// 对外接口函数
template<class Raster> std::vector<Ring> execute(...);
}
#endif
核心数据结构
坐标表示
struct Coord {
long r = 0, c = 0; // 行/列坐标
size_t seq(const Coord &res) const; // 序列化坐标
// 运算符重载...
};
闭合轮廓环
using Ring = std::vector<Coord>; // 由坐标点组成的闭合环
算法实现原理
单元格状态标记(SquareTag)
enum class SquareTag : uint8_t {
none, a, b, ab, c, ..., full // 16种可能状态
};
表示2x2像素单元格的四种顶点组合状态,对应Marching Squares的16种基础情况
方向控制(Dir)
enum class Dir: uint8_t { left, down, right, up, none };
用于控制等值线在单元格之间的遍历方向
核心类设计
Grid模板类
template<class Rst> class Grid {
// 成员变量
const Rst* m_rst; // 栅格数据指针
Coord m_cellsize; // 单元格尺寸
std::vector<uint8_t> m_tags; // 单元格状态标记集合
// 关键方法
uint8_t get_tag_for_cell(...); // 计算单元格标记
std::vector<Ring> scan_rings(); // 扫描生成轮廓环
void interpolate_rings(...); // 精确插值坐标
};
算法流程
执行步骤
关键阶段说明
-
单元格标记:
- 遍历每个2x2单元格
- 根据顶点值与等值阈值比较生成4bit标记
- 处理栅格边界特殊情况
-
环扫描算法:
- 使用深度优先搜索遍历相邻单元格
- 处理16种基础情况及2种模糊情况
- 记录遍历方向防止重复访问
-
坐标插值:
Edge e = edge(ringvertex); CellIt found = std::lower_bound(e.from, e.to, isoval);
- 在单元格边界上进行二分查找
- 确定等值线与边界的精确交点
设计亮点
栅格数据适配
template<class T> struct _RasterTraits {
static size_t rows(const T&);
static size_t cols(const T&);
static ValueType get(const T&, size_t, size_t);
};
允许适配任意类型的栅格数据,包括:
- 内存数组
- 图像缓冲区
- 稀疏数据结构
并行处理支持
template<class ExecutionPolicy>
void tag_grid(ExecutionPolicy&& policy, ...)
{
for_each(policy, m_tags.begin(), m_tags.end(), ...);
}
通过策略模式实现:
- 单线程顺序执行
- OpenMP并行
- TBB并行等多种执行策略
性能优化
内存布局优化
- 使用紧凑的uint8_t存储单元格标记(4bit标记+4bit访问状态)
- 坐标计算完全基于整型运算
搜索优化
size_t search_start_cell(size_t i = 0) const
{
while ((i < m_tags.size()) && (is_visited(i) || is_ambiguous(i))) ++i;
return i;
}
- 跳过已处理单元格
- 延迟处理模糊情况
使用示例
基本调用
std::vector<marchsq::Ring> contours =
marchsq::execute(image_data, 128);
自定义栅格适配
struct MyRaster {
using ValueType = uint8_t;
// 实现数据访问接口...
};
template<> struct marchsq::_RasterTraits<MyRaster> {
// 特化适配方法...
};
注意事项
-
栅格边界处理:
- 自动限制坐标在有效范围内
- 处理部分覆盖的边界单元格
-
模糊情况处理:
- 对ac和bd两种模糊情况特殊处理
- 通过方向追踪避免歧义
-
精度控制:
- 使用整数坐标运算避免浮点误差
- 插值时采用精确的二分查找
扩展接口
执行策略选择
// 使用OpenMP并行
marchsq::execute_with_policy(omp_policy{}, data, isoval);
// 单线程执行
marchsq::execute_with_policy(seq_policy{}, data, isoval);
高级参数调节
marchsq::execute(data, isoval,
{2, 2}, // 单元格尺寸
{1, 1} // 重叠像素
);
潜在优化方向
-
多分辨率处理:
- 动态调整单元格尺寸
- 层次化轮廓生成
-
GPU加速:
- 将标记阶段移植到GPU
- 使用CUDA/OpenCL加速
-
增量更新:
- 局部区域重新计算
- 动态等值线更新