mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-06-11 14:33:04 +00:00
1028 lines
31 KiB
Markdown
1028 lines
31 KiB
Markdown
# Rib Wipe Tower Brim Layer-by-Layer Reduction - Technical Documentation
|
||
|
||
## 文档概述 (Document Overview)
|
||
|
||
本文档详细说明了从BambuStudio的WipeTower类迁移"裙边逐层递减"(Brim Chamfer)功能到OrcaSlicer的WipeTower2类的完整技术实现。
|
||
|
||
This document provides comprehensive technical details on migrating the "brim layer-by-layer reduction" (brim chamfer) feature from BambuStudio's WipeTower class to OrcaSlicer's WipeTower2 class.
|
||
|
||
---
|
||
|
||
## 功能说明 (Feature Description)
|
||
|
||
### 什么是裙边逐层递减?(What is Brim Chamfer?)
|
||
|
||
裙边逐层递减是一种优化技术,用于在多材料打印的擦除塔底部创建一个渐变的过渡效果:
|
||
|
||
- **第一层**:打印完整宽度的裙边(例如6mm)以确保良好的床面附着力
|
||
- **后续层**:每层减少一圈裙边,形成倒角/渐变效果
|
||
- **最终层**:裙边完全消失,只剩擦除塔主体
|
||
|
||
这种设计的优点:
|
||
1. 保持第一层的良好附着力
|
||
2. 减少材料使用
|
||
3. 提高打印速度(减少不必要的裙边打印)
|
||
4. 改善美观效果(平滑的倒角过渡)
|
||
|
||
### 视觉效果示例 (Visual Example)
|
||
|
||
```
|
||
侧视图 (Side View):
|
||
Layer 7+ | (无裙边)
|
||
Layer 6 | █ (1圈裙边)
|
||
Layer 5 | ██ (2圈裙边)
|
||
Layer 4 | ███ (3圈裙边)
|
||
Layer 3 | ████ (4圈裙边)
|
||
Layer 2 | █████ (5圈裙边)
|
||
Layer 1 | ██████ (6圈裙边)
|
||
Layer 0 | ███████████████ (完整裙边,15圈)
|
||
|________________
|
||
床面 (Bed)
|
||
|
||
形成一个倒角/渐变效果
|
||
```
|
||
|
||
---
|
||
|
||
## BambuStudio原始实现分析 (BambuStudio Original Implementation)
|
||
|
||
### 代码位置 (Code Location)
|
||
|
||
- **文件路径**: `D:\work\Projects\BambuStudio\src\libslic3r\GCode\WipeTower.cpp`
|
||
- **函数**: `WipeTower::finish_layer()`
|
||
- **关键代码段**: 第1300-1331行
|
||
|
||
### 核心算法 (Core Algorithm)
|
||
|
||
BambuStudio的实现基于**box_coordinates**(矩形坐标系统)架构:
|
||
|
||
```cpp
|
||
// BambuStudio 实现 (原始代码)
|
||
int loops_num = (m_wipe_tower_brim_width + spacing / 2.f) / spacing;
|
||
const float max_chamfer_width = 3.f; // 硬编码的最大倒角宽度
|
||
|
||
if (!first_layer) {
|
||
// 如果擦除塔深度发生变化,停止打印裙边
|
||
if (m_layer_info->depth != m_plan.front().depth) {
|
||
loops_num = 0;
|
||
}
|
||
else {
|
||
// 限制最大倒角宽度为3mm
|
||
int chamfer_loops_num = (int)(max_chamfer_width / spacing);
|
||
int dist_to_1st = m_layer_info - m_plan.begin();
|
||
loops_num = std::min(loops_num, chamfer_loops_num) - dist_to_1st;
|
||
}
|
||
}
|
||
|
||
// 使用box_coordinates扩展矩形
|
||
if (loops_num > 0) {
|
||
for (size_t i = 0; i < loops_num; ++i) {
|
||
box.expand(spacing); // 矩形扩展
|
||
writer.rectangle(box.ld, box.ru.x() - box.lu.x(), box.ru.y() - box.rd.y());
|
||
}
|
||
}
|
||
```
|
||
|
||
### 关键特征 (Key Features)
|
||
|
||
1. **架构**: 基于`box_coordinates`的矩形扩展
|
||
- 使用`box.expand(spacing)`方法扩展矩形边界
|
||
- 适合规则的矩形擦除塔
|
||
|
||
2. **递减规则**: 线性递减,每层减少1圈
|
||
- 公式: `loops_on_layer_N = min(original_loops, max_chamfer_loops) - distance_from_first_layer`
|
||
- 最大倒角宽度硬编码为3mm
|
||
|
||
3. **深度检测**: 检测塔深度变化
|
||
- 如果深度改变,立即停止打印裙边
|
||
- 确保裙边不会与擦除塔主体冲突
|
||
|
||
4. **层级追踪**: 使用`m_plan.begin()`作为基准
|
||
- 假设第一层总是`m_plan.begin()`
|
||
- 简单的迭代器算术计算距离
|
||
|
||
### 数值示例 (Numerical Example)
|
||
|
||
假设参数:
|
||
- 裙边宽度配置: 6mm
|
||
- 喷嘴直径: 0.4mm
|
||
- 层高: 0.2mm
|
||
- 计算出的spacing: ~0.4mm
|
||
- 最大倒角宽度: 3mm(硬编码)
|
||
|
||
计算过程:
|
||
```
|
||
原始圈数 = 6mm / 0.4mm = 15圈
|
||
最大倒角圈数 = 3mm / 0.4mm = 7圈(限制)
|
||
|
||
第0层(首层): min(15, 7) - 0 = 7圈 → 2.8mm裙边
|
||
第1层: min(15, 7) - 1 = 6圈 → 2.4mm裙边
|
||
第2层: min(15, 7) - 2 = 5圈 → 2.0mm裙边
|
||
第3层: min(15, 7) - 3 = 4圈 → 1.6mm裙边
|
||
第4层: min(15, 7) - 4 = 3圈 → 1.2mm裙边
|
||
第5层: min(15, 7) - 5 = 2圈 → 0.8mm裙边
|
||
第6层: min(15, 7) - 6 = 1圈 → 0.4mm裙边
|
||
第7层+: min(15, 7) - 7 = 0圈 → 无裙边
|
||
```
|
||
|
||
### 限制和问题 (Limitations)
|
||
|
||
1. **架构限制**: 只适用于矩形擦除塔
|
||
- `box_coordinates`和`expand()`方法不支持复杂形状
|
||
- 无法处理对角线加强筋(rib wall)的不规则多边形
|
||
|
||
2. **硬编码值**: 最大倒角宽度固定为3mm
|
||
- 用户无法自定义
|
||
- 不同打印机可能需要不同的值
|
||
|
||
3. **层级追踪**: 假设第一层总是`m_plan.begin()`
|
||
- 如果启用"跳过稀疏层"功能,可能不准确
|
||
- OrcaSlicer需要更精确的`m_first_layer_idx`追踪
|
||
|
||
---
|
||
|
||
## OrcaSlicer实现方案 (OrcaSlicer Implementation)
|
||
|
||
### 架构适配 (Architecture Adaptation)
|
||
|
||
OrcaSlicer的WipeTower2类使用**Polygon + offset()**架构,比BambuStudio更灵活:
|
||
|
||
```cpp
|
||
// OrcaSlicer WipeTower2架构
|
||
Polygon poly; // 任意多边形形状
|
||
poly = offset(poly, scale_(spacing)); // Clipper2偏移算法
|
||
```
|
||
|
||
这种架构的优势:
|
||
- ✅ 支持矩形擦除塔
|
||
- ✅ 支持对角线加强筋(rib wall)的复杂多边形
|
||
- ✅ 使用Clipper2库的高精度偏移算法
|
||
- ✅ 可以处理任意凸多边形
|
||
|
||
### 完整实现代码 (Complete Implementation)
|
||
|
||
#### 1. 配置参数定义 (Configuration Parameters)
|
||
|
||
**文件**: `src/libslic3r/PrintConfig.hpp` (第1388-1391行)
|
||
|
||
```cpp
|
||
((ConfigOptionFloat, prime_tower_brim_width))
|
||
((ConfigOptionBool, prime_tower_brim_chamfer)) // 新增
|
||
((ConfigOptionFloat, prime_tower_brim_chamfer_max_width)) // 新增
|
||
((ConfigOptionFloat, wipe_tower_bridging))
|
||
```
|
||
|
||
**文件**: `src/libslic3r/PrintConfig.cpp` (第5737-5758行)
|
||
|
||
```cpp
|
||
def = this->add("prime_tower_brim_chamfer", coBool);
|
||
def->label = L("Brim chamfer");
|
||
def->tooltip = L("Enable gradual layer-by-layer reduction of the brim around the prime tower. "
|
||
"This creates a chamfered/tapered effect, reducing material usage while "
|
||
"maintaining first layer adhesion.");
|
||
def->mode = comAdvanced;
|
||
def->set_default_value(new ConfigOptionBool(true)); // 默认启用
|
||
|
||
def = this->add("prime_tower_brim_chamfer_max_width", coFloat);
|
||
def->label = L("Max chamfer width");
|
||
def->tooltip = L("Maximum width of the chamfer zone measured from the tower perimeter. "
|
||
"The brim will reduce within this distance. Larger values create a more "
|
||
"gradual taper but take more layers to complete.");
|
||
def->sidetext = "mm";
|
||
def->mode = comAdvanced;
|
||
def->min = 0.;
|
||
def->set_default_value(new ConfigOptionFloat(3.0)); // 默认3mm,与Bambu一致
|
||
```
|
||
|
||
配置说明:
|
||
- **prime_tower_brim_chamfer**: 布尔值,启用/禁用倒角功能
|
||
- **prime_tower_brim_chamfer_max_width**: 浮点数,最大倒角宽度(mm)
|
||
- 默认3.0mm,与BambuStudio保持一致
|
||
- 用户可以根据需要自定义(例如2mm或5mm)
|
||
|
||
#### 2. 类成员变量 (Class Member Variables)
|
||
|
||
**文件**: `src/libslic3r/GCode/WipeTower2.hpp` (第190-194行)
|
||
|
||
```cpp
|
||
float m_wipe_tower_brim_width = 0.f; // 裙边宽度配置(mm)
|
||
float m_wipe_tower_brim_width_real = 0.f; // 实际生成的裙边宽度(mm)
|
||
bool m_prime_tower_brim_chamfer = true; // 启用倒角
|
||
float m_prime_tower_brim_chamfer_max_width = 3.f; // 最大倒角宽度(mm)
|
||
```
|
||
|
||
#### 3. 构造函数初始化 (Constructor Initialization)
|
||
|
||
**文件**: `src/libslic3r/GCode/WipeTower2.cpp` (第1256-1260行)
|
||
|
||
```cpp
|
||
WipeTower2::WipeTower2(const PrintConfig& config, ...) :
|
||
// ... 其他成员初始化 ...
|
||
m_wipe_tower_rotation_angle(float(config.wipe_tower_rotation_angle)),
|
||
m_wipe_tower_brim_width(float(config.prime_tower_brim_width)),
|
||
m_prime_tower_brim_chamfer(config.prime_tower_brim_chamfer),
|
||
m_prime_tower_brim_chamfer_max_width(float(config.prime_tower_brim_chamfer_max_width)),
|
||
m_wipe_tower_cone_angle(float(config.wipe_tower_cone_angle)),
|
||
// ...
|
||
```
|
||
|
||
#### 4. 核心算法实现 (Core Algorithm Implementation)
|
||
|
||
**文件**: `src/libslic3r/GCode/WipeTower2.cpp` (第2086-2133行)
|
||
|
||
```cpp
|
||
// brim with chamfer (gradual layer-by-layer reduction)
|
||
int loops_num = (m_wipe_tower_brim_width + spacing/2.f) / spacing;
|
||
|
||
// Apply chamfer reduction if feature is enabled and brim width is configured
|
||
if (m_wipe_tower_brim_width > 0 && m_prime_tower_brim_chamfer) {
|
||
if (!first_layer) {
|
||
// Calculate distance from first layer with tool changes
|
||
size_t current_idx = m_layer_info - m_plan.begin();
|
||
int dist_to_1st = (int)current_idx - (int)m_first_layer_idx;
|
||
|
||
// Stop print chamfer if depth changes
|
||
bool depth_changed = (m_layer_info->depth != m_plan[m_first_layer_idx].depth);
|
||
if (depth_changed) {
|
||
loops_num = 0;
|
||
}
|
||
else {
|
||
// Limit max chamfer width to configured value
|
||
int chamfer_loops_num = (int)(m_prime_tower_brim_chamfer_max_width / spacing);
|
||
loops_num = std::min(loops_num, chamfer_loops_num) - dist_to_1st;
|
||
// Ensure loops_num doesn't go negative
|
||
if (loops_num < 0) loops_num = 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (loops_num > 0) {
|
||
writer.append("; WIPE_TOWER_BRIM_START\n");
|
||
|
||
for (int i = 0; i < loops_num; ++i) {
|
||
poly = offset(poly, scale_(spacing)).front();
|
||
int cp = poly.closest_point_index(Point::new_scale(writer.x(), writer.y()));
|
||
writer.travel(unscale(poly.points[cp]).cast<float>());
|
||
for (int j = cp+1; true; ++j) {
|
||
if (j == int(poly.points.size()))
|
||
j = 0;
|
||
writer.extrude(unscale(poly.points[j]).cast<float>());
|
||
if (j == cp)
|
||
break;
|
||
}
|
||
}
|
||
|
||
writer.append("; WIPE_TOWER_BRIM_END\n");
|
||
|
||
// Save actual brim width only on first layer
|
||
if (first_layer) {
|
||
m_wipe_tower_brim_width_real = loops_num * spacing;
|
||
}
|
||
}
|
||
```
|
||
|
||
### 算法详解 (Algorithm Explanation)
|
||
|
||
#### 第1步:计算初始圈数 (Step 1: Calculate Initial Loop Count)
|
||
|
||
```cpp
|
||
int loops_num = (m_wipe_tower_brim_width + spacing/2.f) / spacing;
|
||
```
|
||
|
||
- **spacing**: 相邻挤出线之间的间距(约等于线宽)
|
||
- 公式: `spacing = m_perimeter_width - m_layer_height * (1 - π/4)`
|
||
- 典型值: 0.4mm (对于0.4mm喷嘴,0.2mm层高)
|
||
|
||
- **m_wipe_tower_brim_width**: 用户配置的裙边宽度(mm)
|
||
- 例如: 6mm
|
||
|
||
- **+spacing/2.f**: 四舍五入修正
|
||
- 确保边界情况正确计算
|
||
|
||
- **示例**: 6mm / 0.4mm = 15圈
|
||
|
||
#### 第2步:应用倒角递减 (Step 2: Apply Chamfer Reduction)
|
||
|
||
```cpp
|
||
if (m_wipe_tower_brim_width > 0 && m_prime_tower_brim_chamfer) {
|
||
```
|
||
|
||
- 仅当裙边宽度大于0且倒角功能启用时执行
|
||
- 允许用户完全禁用倒角(保持传统单层裙边)
|
||
|
||
#### 第3步:计算层级距离 (Step 3: Calculate Layer Distance)
|
||
|
||
```cpp
|
||
size_t current_idx = m_layer_info - m_plan.begin();
|
||
int dist_to_1st = (int)current_idx - (int)m_first_layer_idx;
|
||
```
|
||
|
||
- **m_layer_info**: 当前层的迭代器(指向m_plan向量中的当前元素)
|
||
- **m_plan**: 存储所有层信息的向量
|
||
- **m_first_layer_idx**: 第一个有工具更换的层的索引
|
||
- 在`plan_toolchange()`中设置(第2211-2212行)
|
||
- 处理"跳过稀疏层"功能
|
||
|
||
- **迭代器算术**: `current_idx = m_layer_info - m_plan.begin()`
|
||
- 指针/迭代器相减得到索引距离
|
||
- 例如: 如果当前在第5层,首层在第0层,距离=5
|
||
|
||
#### 第4步:深度变化检测 (Step 4: Depth Change Detection)
|
||
|
||
```cpp
|
||
bool depth_changed = (m_layer_info->depth != m_plan[m_first_layer_idx].depth);
|
||
if (depth_changed) {
|
||
loops_num = 0;
|
||
}
|
||
```
|
||
|
||
- **depth**: 每层擦除塔的深度(Y方向尺寸)
|
||
- 随着工具更换次数减少,深度可能变化
|
||
|
||
- **深度变化检测**:
|
||
- 比较当前层深度与首层深度
|
||
- 如果不同,立即停止裙边打印
|
||
- 避免裙边与缩小的塔身冲突
|
||
|
||
#### 第5步:限制最大倒角宽度 (Step 5: Limit Max Chamfer Width)
|
||
|
||
```cpp
|
||
int chamfer_loops_num = (int)(m_prime_tower_brim_chamfer_max_width / spacing);
|
||
loops_num = std::min(loops_num, chamfer_loops_num) - dist_to_1st;
|
||
if (loops_num < 0) loops_num = 0;
|
||
```
|
||
|
||
- **chamfer_loops_num**: 倒角区域最大圈数
|
||
- 例如: 3mm / 0.4mm = 7圈
|
||
|
||
- **min(original, max_chamfer)**: 取两者中较小值
|
||
- 如果裙边宽度很大(例如10mm),限制倒角只在前3mm内递减
|
||
- 避免倒角区域过宽,影响首层附着力
|
||
|
||
- **减去距离**: 线性递减
|
||
- 每层减少1圈
|
||
|
||
- **负数保护**: 确保不会出现负值
|
||
- 负值会在第`max_chamfer_loops + 1`层出现
|
||
- 截断为0,停止打印裙边
|
||
|
||
#### 第6步:生成裙边路径 (Step 6: Generate Brim Path)
|
||
|
||
```cpp
|
||
for (int i = 0; i < loops_num; ++i) {
|
||
poly = offset(poly, scale_(spacing)).front();
|
||
int cp = poly.closest_point_index(Point::new_scale(writer.x(), writer.y()));
|
||
writer.travel(unscale(poly.points[cp]).cast<float>());
|
||
for (int j = cp+1; true; ++j) {
|
||
if (j == int(poly.points.size()))
|
||
j = 0;
|
||
writer.extrude(unscale(poly.points[j]).cast<float>());
|
||
if (j == cp)
|
||
break;
|
||
}
|
||
}
|
||
```
|
||
|
||
- **offset(poly, spacing)**: Clipper2偏移算法
|
||
- 将多边形向外扩展指定距离
|
||
- 处理复杂形状(包括对角线加强筋)
|
||
- 返回偏移后的多边形
|
||
|
||
- **closest_point_index()**: 找到距离当前喷嘴位置最近的点
|
||
- 减少移动距离
|
||
- 优化打印路径
|
||
|
||
- **环形挤出**: 从最近点开始,绕多边形一圈
|
||
- `j = cp+1`开始,循环到`j == cp`结束
|
||
- 索引回绕处理: `if (j == size) j = 0`
|
||
|
||
### 完整数值示例 (Complete Numerical Example)
|
||
|
||
假设配置:
|
||
- 裙边宽度: 6mm
|
||
- 喷嘴直径: 0.4mm
|
||
- 层高: 0.2mm
|
||
- 线宽: 0.5mm (Width_To_Nozzle_Ratio = 1.25)
|
||
- 最大倒角宽度: 3mm
|
||
|
||
计算过程:
|
||
|
||
```
|
||
spacing = 0.5 - 0.2 * (1 - π/4) ≈ 0.4mm
|
||
|
||
原始圈数 = (6 + 0.4/2) / 0.4 = 6.2 / 0.4 = 15.5 → 15圈
|
||
最大倒角圈数 = 3 / 0.4 = 7.5 → 7圈
|
||
|
||
第一层追踪索引: m_first_layer_idx = 0
|
||
|
||
第0层(首层):
|
||
- first_layer = true
|
||
- 跳过倒角逻辑
|
||
- loops_num = 15圈
|
||
- 实际宽度 = 15 * 0.4 = 6mm ✓
|
||
|
||
第1层:
|
||
- current_idx = 1
|
||
- dist_to_1st = 1 - 0 = 1
|
||
- depth_changed = false (假设深度不变)
|
||
- loops_num = min(15, 7) - 1 = 7 - 1 = 6圈
|
||
- 实际宽度 = 6 * 0.4 = 2.4mm
|
||
|
||
第2层:
|
||
- dist_to_1st = 2
|
||
- loops_num = 7 - 2 = 5圈
|
||
- 实际宽度 = 2.0mm
|
||
|
||
第3层:
|
||
- dist_to_1st = 3
|
||
- loops_num = 7 - 3 = 4圈
|
||
- 实际宽度 = 1.6mm
|
||
|
||
第4层:
|
||
- dist_to_1st = 4
|
||
- loops_num = 7 - 4 = 3圈
|
||
- 实际宽度 = 1.2mm
|
||
|
||
第5层:
|
||
- dist_to_1st = 5
|
||
- loops_num = 7 - 5 = 2圈
|
||
- 实际宽度 = 0.8mm
|
||
|
||
第6层:
|
||
- dist_to_1st = 6
|
||
- loops_num = 7 - 6 = 1圈
|
||
- 实际宽度 = 0.4mm
|
||
|
||
第7层:
|
||
- dist_to_1st = 7
|
||
- loops_num = 7 - 7 = 0圈
|
||
- 无裙边
|
||
|
||
第8层及之后:
|
||
- loops_num = 7 - 8 = -1 → 截断为0
|
||
- 无裙边
|
||
```
|
||
|
||
总结:
|
||
- 第一层: 完整裙边(6mm,15圈)
|
||
- 第1-7层: 倒角区域(从2.4mm递减到0.4mm)
|
||
- 第8层开始: 无裙边
|
||
|
||
---
|
||
|
||
## 关键差异对比 (Key Differences Comparison)
|
||
|
||
| 方面 | BambuStudio WipeTower | OrcaSlicer WipeTower2 |
|
||
|------|----------------------|----------------------|
|
||
| **架构** | box_coordinates + expand() | Polygon + offset() |
|
||
| **形状支持** | 仅矩形 | 任意凸多边形(含rib) |
|
||
| **倒角配置** | 硬编码3mm | 可配置(默认3mm) |
|
||
| **功能开关** | 无(总是启用) | 有(prime_tower_brim_chamfer) |
|
||
| **首层追踪** | m_plan.begin() | m_first_layer_idx(更精确) |
|
||
| **深度检测** | 与front()比较 | 与first_layer_idx比较 |
|
||
| **偏移算法** | 矩形扩展 | Clipper2偏移 |
|
||
| **路径生成** | 直接画矩形 | 遍历多边形顶点 |
|
||
| **代码位置** | WipeTower.cpp:1300-1331 | WipeTower2.cpp:2086-2133 |
|
||
|
||
### 架构优势详解 (Architectural Advantages)
|
||
|
||
#### BambuStudio的box_coordinates方法:
|
||
```cpp
|
||
// 矩形扩展
|
||
box.expand(spacing);
|
||
writer.rectangle(box.ld, box.ru.x() - box.lu.x(), box.ru.y() - box.rd.y());
|
||
```
|
||
|
||
优点:
|
||
- ✅ 代码简单直观
|
||
- ✅ 矩形扩展计算快速
|
||
|
||
缺点:
|
||
- ❌ 只支持矩形形状
|
||
- ❌ 无法处理对角线加强筋(diagonal rib)
|
||
- ❌ 无法处理任意多边形
|
||
|
||
#### OrcaSlicer的Polygon偏移方法:
|
||
```cpp
|
||
// 多边形偏移
|
||
poly = offset(poly, scale_(spacing)).front();
|
||
// 然后遍历多边形顶点挤出
|
||
for (auto& pt : poly.points) { ... }
|
||
```
|
||
|
||
优点:
|
||
- ✅ 支持任意凸多边形
|
||
- ✅ 完美处理对角线加强筋(16个顶点的复杂形状)
|
||
- ✅ 使用Clipper2高精度偏移算法
|
||
- ✅ 自动处理角点和边缘情况
|
||
|
||
缺点:
|
||
- ❌ 代码稍复杂
|
||
- ❌ 偏移计算相对较慢(但可接受)
|
||
|
||
---
|
||
|
||
## 代码迁移总结 (Migration Summary)
|
||
|
||
### 迁移步骤 (Migration Steps)
|
||
|
||
1. **配置层** (Configuration Layer)
|
||
- ✅ 添加`prime_tower_brim_chamfer`布尔开关
|
||
- ✅ 添加`prime_tower_brim_chamfer_max_width`浮点配置
|
||
- ✅ 提供默认值(true, 3.0mm)
|
||
|
||
2. **类成员** (Class Members)
|
||
- ✅ 在WipeTower2.hpp添加成员变量
|
||
- ✅ 在构造函数中初始化
|
||
|
||
3. **核心算法** (Core Algorithm)
|
||
- ✅ 替换`finish_layer()`中的裙边生成代码
|
||
- ✅ 从单层逻辑改为多层倒角逻辑
|
||
- ✅ 适配Polygon偏移架构
|
||
|
||
4. **基础设施** (Infrastructure)
|
||
- ✅ 使用现有的`m_first_layer_idx`(无需新增)
|
||
- ✅ 使用现有的`m_plan`和`m_layer_info`
|
||
- ✅ 使用现有的`depth`字段
|
||
|
||
### 未修改的部分 (Unchanged Components)
|
||
|
||
以下基础设施已存在,无需修改:
|
||
- ✅ `m_plan`向量:存储所有层信息
|
||
- ✅ `m_layer_info`迭代器:当前层指针
|
||
- ✅ `m_first_layer_idx`:首层索引追踪(第204行已存在)
|
||
- ✅ `WipeTowerInfo::depth`:每层深度字段(第290行)
|
||
- ✅ `plan_toolchange()`:设置首层索引(第2211-2212行)
|
||
|
||
### 关键适配点 (Key Adaptation Points)
|
||
|
||
1. **从box到Polygon**:
|
||
```cpp
|
||
// Bambu方式
|
||
box.expand(spacing);
|
||
writer.rectangle(box);
|
||
|
||
// Orca方式
|
||
poly = offset(poly, scale_(spacing)).front();
|
||
// 遍历poly.points挤出
|
||
```
|
||
|
||
2. **从front()到first_layer_idx**:
|
||
```cpp
|
||
// Bambu方式
|
||
int dist = m_layer_info - m_plan.begin();
|
||
|
||
// Orca方式
|
||
size_t current_idx = m_layer_info - m_plan.begin();
|
||
int dist_to_1st = (int)current_idx - (int)m_first_layer_idx;
|
||
```
|
||
|
||
3. **从硬编码到可配置**:
|
||
```cpp
|
||
// Bambu方式
|
||
const float max_chamfer_width = 3.f;
|
||
|
||
// Orca方式
|
||
float max_chamfer_width = m_prime_tower_brim_chamfer_max_width;
|
||
```
|
||
|
||
---
|
||
|
||
## 测试验证 (Testing and Verification)
|
||
|
||
### 测试场景 (Test Scenarios)
|
||
|
||
1. **基础功能测试**
|
||
- 场景:标准多材料模型,6mm裙边
|
||
- 预期:第一层完整裙边,后续层逐层递减
|
||
- 验证:G-code预览显示倒角效果
|
||
|
||
2. **配置测试**
|
||
- 场景:启用/禁用`prime_tower_brim_chamfer`
|
||
- 预期:禁用时回到传统单层裙边
|
||
- 验证:仅第一层有裙边
|
||
|
||
3. **自定义倒角宽度测试**
|
||
- 场景:设置`max_width`为2mm或5mm
|
||
- 预期:倒角区域相应变小/变大
|
||
- 验证:递减完成的层数改变
|
||
|
||
4. **深度变化测试**
|
||
- 场景:打印过程中塔深度减少
|
||
- 预期:深度变化时立即停止裙边
|
||
- 验证:无冲突,无悬空挤出
|
||
|
||
5. **Rib Wall测试**
|
||
- 场景:对角线加强筋擦除塔
|
||
- 预期:倒角正确应用于复杂多边形
|
||
- 验证:16个顶点的多边形正确偏移
|
||
|
||
### 预期输出 (Expected Output)
|
||
|
||
#### G-code标记 (G-code Markers)
|
||
```gcode
|
||
; WIPE_TOWER_BRIM_START
|
||
G1 X... Y... E... F... ; 第一圈裙边
|
||
G1 X... Y... E... F...
|
||
...
|
||
G1 X... Y... E... F... ; 第N圈裙边
|
||
; WIPE_TOWER_BRIM_END
|
||
```
|
||
|
||
#### 裙边宽度变化 (Brim Width Changes)
|
||
```
|
||
Layer 0: 6.0mm (15 loops) - FULL BRIM
|
||
Layer 1: 2.4mm (6 loops) - START CHAMFER
|
||
Layer 2: 2.0mm (5 loops)
|
||
Layer 3: 1.6mm (4 loops)
|
||
Layer 4: 1.2mm (3 loops)
|
||
Layer 5: 0.8mm (2 loops)
|
||
Layer 6: 0.4mm (1 loop)
|
||
Layer 7: 0.0mm (0 loops) - CHAMFER COMPLETE
|
||
Layer 8+: 0.0mm - NO BRIM
|
||
```
|
||
|
||
### 测试工具 (Testing Tools)
|
||
|
||
1. **G-code预览器**: 使用OrcaSlicer内置预览功能
|
||
2. **文本编辑器**: 检查生成的G-code文件
|
||
3. **实际打印**: 验证附着力和倒角效果
|
||
|
||
---
|
||
|
||
## 配置指南 (Configuration Guide)
|
||
|
||
### 用户配置选项 (User Configuration Options)
|
||
|
||
#### 1. 裙边宽度 (Brim Width)
|
||
- **参数**: `prime_tower_brim_width`
|
||
- **类型**: 浮点数(mm)
|
||
- **默认值**: 6.0mm(示例)
|
||
- **范围**: 0-20mm
|
||
- **说明**: 第一层裙边的总宽度
|
||
|
||
#### 2. 启用倒角 (Enable Chamfer)
|
||
- **参数**: `prime_tower_brim_chamfer`
|
||
- **类型**: 布尔值
|
||
- **默认值**: true(启用)
|
||
- **说明**:
|
||
- `true`: 启用逐层递减,创建倒角效果
|
||
- `false`: 传统模式,仅第一层打印裙边
|
||
|
||
#### 3. 最大倒角宽度 (Max Chamfer Width)
|
||
- **参数**: `prime_tower_brim_chamfer_max_width`
|
||
- **类型**: 浮点数(mm)
|
||
- **默认值**: 3.0mm
|
||
- **范围**: 0-10mm
|
||
- **说明**: 从塔体到裙边边缘的倒角区域最大宽度
|
||
|
||
### 配置示例 (Configuration Examples)
|
||
|
||
#### 示例1:标准倒角(默认)
|
||
```ini
|
||
prime_tower_brim_width = 6.0
|
||
prime_tower_brim_chamfer = 1
|
||
prime_tower_brim_chamfer_max_width = 3.0
|
||
```
|
||
效果:6mm裙边,3mm倒角区域,约7层完成递减
|
||
|
||
#### 示例2:快速倒角
|
||
```ini
|
||
prime_tower_brim_width = 6.0
|
||
prime_tower_brim_chamfer = 1
|
||
prime_tower_brim_chamfer_max_width = 2.0
|
||
```
|
||
效果:6mm裙边,2mm倒角区域,约5层完成递减
|
||
|
||
#### 示例3:渐进倒角
|
||
```ini
|
||
prime_tower_brim_width = 10.0
|
||
prime_tower_brim_chamfer = 1
|
||
prime_tower_brim_chamfer_max_width = 5.0
|
||
```
|
||
效果:10mm裙边,5mm倒角区域,约12层完成递减
|
||
|
||
#### 示例4:禁用倒角(传统模式)
|
||
```ini
|
||
prime_tower_brim_width = 6.0
|
||
prime_tower_brim_chamfer = 0
|
||
prime_tower_brim_chamfer_max_width = 3.0
|
||
```
|
||
效果:仅第一层6mm裙边,后续层无裙边
|
||
|
||
---
|
||
|
||
## 常见问题 (FAQ)
|
||
|
||
### Q1: 为什么倒角宽度不能超过配置的最大值?
|
||
|
||
**A:** 这是为了平衡首层附着力和材料节省。如果允许整个裙边区域倒角:
|
||
- 裙边很宽时(例如10mm),倒角会延续很多层(25+层)
|
||
- 首层附着力的核心区域(最内3mm)最重要
|
||
- 外围区域(3mm之外)可以快速递减,节省材料
|
||
|
||
公式:`effective_brim = inner_full_width + chamfer_zone`
|
||
|
||
### Q2: 深度变化检测的作用是什么?
|
||
|
||
**A:** 擦除塔的深度(Y方向尺寸)随着工具更换次数减少而可能改变。如果不检测深度变化:
|
||
- 裙边可能超出缩小后的塔体范围
|
||
- 造成悬空挤出,影响打印质量
|
||
- 可能与塔体发生碰撞
|
||
|
||
深度检测确保裙边始终在塔体支撑范围内。
|
||
|
||
### Q3: 为什么使用m_first_layer_idx而不是m_plan.begin()?
|
||
|
||
**A:** OrcaSlicer支持"跳过稀疏层"功能:
|
||
- 某些层可能没有工具更换,不需要擦除塔
|
||
- 这些层会被跳过,不打印任何内容
|
||
- 第一个有工具更换的层可能不是m_plan[0]
|
||
|
||
使用`m_first_layer_idx`确保距离计算准确,无论是否跳过稀疏层。
|
||
|
||
### Q4: Polygon偏移比box扩展慢多少?
|
||
|
||
**A:** 性能差异很小:
|
||
- Polygon偏移:使用Clipper2优化的C++算法,时间复杂度O(n*log n)
|
||
- Box扩展:简单的坐标运算,时间复杂度O(1)
|
||
|
||
但在实际使用中:
|
||
- 裙边生成仅占整个切片过程的<0.1%时间
|
||
- 多边形通常只有4-16个顶点,计算非常快
|
||
- Clipper2高度优化,性能接近C语言实现
|
||
|
||
结论:性能差异可以忽略不计,但功能灵活性大幅提升。
|
||
|
||
### Q5: 能否为不同材料设置不同的倒角参数?
|
||
|
||
**A:** 当前实现是全局配置,所有材料使用相同的倒角参数。如需材料特定配置:
|
||
1. 修改`PrintConfig`添加per-filament参数
|
||
2. 修改`WipeTower2`构造函数接收材料特定值
|
||
3. 修改`finish_layer()`根据当前工具选择参数
|
||
|
||
这个功能可以作为未来增强实现。
|
||
|
||
---
|
||
|
||
## 技术细节补充 (Additional Technical Details)
|
||
|
||
### Spacing计算公式 (Spacing Calculation)
|
||
|
||
```cpp
|
||
const float spacing = m_perimeter_width - m_layer_height * float(1. - M_PI_4);
|
||
```
|
||
|
||
公式推导:
|
||
- `m_perimeter_width`: 挤出线的目标宽度(通常是喷嘴直径的1.1-1.25倍)
|
||
- `m_layer_height`: 当前层高
|
||
- `1 - π/4 ≈ 0.2146`: 挤出线横截面的圆角修正系数
|
||
|
||
物理意义:
|
||
- 挤出线横截面近似椭圆形(不是完美矩形)
|
||
- 两条相邻线之间需要轻微重叠以确保粘合
|
||
- spacing比线宽略小,形成约15-20%的重叠
|
||
|
||
示例计算:
|
||
```
|
||
perimeter_width = 0.4mm * 1.25 = 0.5mm
|
||
layer_height = 0.2mm
|
||
spacing = 0.5 - 0.2 * 0.2146 = 0.5 - 0.043 = 0.457mm
|
||
```
|
||
|
||
### Polygon偏移技术 (Polygon Offset Technology)
|
||
|
||
OrcaSlicer使用**Clipper2**库进行多边形偏移:
|
||
|
||
```cpp
|
||
poly = offset(poly, scale_(spacing)).front();
|
||
```
|
||
|
||
Clipper2特性:
|
||
- **高精度**: 使用整数坐标系统,避免浮点误差
|
||
- **健壮性**: 处理自交、退化等边缘情况
|
||
- **性能**: 高度优化的C++实现
|
||
- **多边形支持**: 凸多边形、凹多边形、多孔多边形
|
||
|
||
偏移类型:
|
||
- **正偏移(向外)**: `offset > 0`,用于生成裙边
|
||
- **负偏移(向内)**: `offset < 0`,用于内缩
|
||
|
||
坐标缩放:
|
||
- `scale_(value)`: 将mm转换为内部整数单位(通常×1000或×1000000)
|
||
- `unscale(value)`: 将内部单位转换回mm
|
||
|
||
### 迭代器算术 (Iterator Arithmetic)
|
||
|
||
```cpp
|
||
size_t current_idx = m_layer_info - m_plan.begin();
|
||
int dist_to_1st = (int)current_idx - (int)m_first_layer_idx;
|
||
```
|
||
|
||
C++迭代器特性:
|
||
- `m_plan`是`std::vector<WipeTowerInfo>`
|
||
- `m_layer_info`是`std::vector<WipeTowerInfo>::iterator`
|
||
- 两个迭代器相减得到元素间的距离(指针算术)
|
||
|
||
类型转换:
|
||
- `size_t`: 无符号整数,用于索引
|
||
- `int`: 有符号整数,用于距离(可能为负,但后续会截断)
|
||
|
||
安全性:
|
||
- `m_first_layer_idx`保证是有效的索引
|
||
- `current_idx >= m_first_layer_idx`(层级单调递增)
|
||
|
||
---
|
||
|
||
## 未来改进方向 (Future Improvements)
|
||
|
||
### 1. 材料特定倒角参数 (Material-Specific Chamfer)
|
||
|
||
**当前**: 全局配置,所有材料相同
|
||
**建议**: 根据材料特性自定义
|
||
|
||
示例:
|
||
- **PLA**: 附着力好,可以用小裙边(4mm,2mm倒角)
|
||
- **ABS**: 翘曲风险高,需要大裙边(10mm,5mm倒角)
|
||
- **TPU**: 柔性材料,中等裙边(6mm,3mm倒角)
|
||
|
||
实现:
|
||
- 在`FilamentConfig`中添加`brim_chamfer_enabled`和`brim_chamfer_max_width`
|
||
- 修改`WipeTower2`根据`m_current_tool`选择参数
|
||
|
||
### 2. 非线性递减曲线 (Non-Linear Reduction)
|
||
|
||
**当前**: 线性递减(每层-1圈)
|
||
**建议**: 支持曲线递减
|
||
|
||
曲线类型:
|
||
- **指数递减**: 前几层快速减少,后续缓慢
|
||
- **对数递减**: 前几层缓慢,后续加速
|
||
- **S曲线**: 两端缓慢,中间快速
|
||
|
||
公式示例:
|
||
```cpp
|
||
// 指数递减
|
||
float factor = exp(-0.5 * dist_to_1st);
|
||
loops_num = int(max_loops * factor);
|
||
|
||
// S曲线
|
||
float factor = 1.0 / (1.0 + exp((dist_to_1st - 4) / 2));
|
||
loops_num = int(max_loops * factor);
|
||
```
|
||
|
||
### 3. 自适应倒角宽度 (Adaptive Chamfer Width)
|
||
|
||
**当前**: 固定最大倒角宽度
|
||
**建议**: 根据打印条件自动调整
|
||
|
||
调整因素:
|
||
- **层高**: 薄层可以更快递减
|
||
- **打印速度**: 高速打印需要更宽裙边
|
||
- **床温**: 高床温可以减少裙边
|
||
|
||
### 4. GUI增强 (GUI Enhancements)
|
||
|
||
**建议功能**:
|
||
- 3D预览中高亮显示倒角区域
|
||
- 实时计算倒角完成层数
|
||
- 可视化裙边宽度变化曲线
|
||
- 材料使用量对比(倒角 vs 传统)
|
||
|
||
### 5. G-code优化 (G-code Optimization)
|
||
|
||
**当前**: 每圈独立路径
|
||
**建议**: 连续螺旋路径
|
||
|
||
优点:
|
||
- 减少Z轴移动(裙边在层间连续)
|
||
- 提高打印速度
|
||
- 更好的层间粘合
|
||
|
||
挑战:
|
||
- 需要重构路径生成逻辑
|
||
- Z轴插值计算复杂
|
||
|
||
---
|
||
|
||
## 总结 (Conclusion)
|
||
|
||
### 实现成果 (Implementation Achievements)
|
||
|
||
✅ **成功迁移**:从BambuStudio的WipeTower类成功迁移裙边倒角功能到OrcaSlicer的WipeTower2类
|
||
|
||
✅ **架构适配**:完美适配WipeTower2的Polygon架构,支持对角线加强筋
|
||
|
||
✅ **功能增强**:
|
||
- 添加可配置的倒角开关
|
||
- 添加可配置的最大倒角宽度
|
||
- 更精确的首层追踪(m_first_layer_idx)
|
||
|
||
✅ **代码质量**:
|
||
- 清晰的注释和文档
|
||
- 健壮的错误处理(负数截断、深度检测)
|
||
- 保持与现有代码风格一致
|
||
|
||
### 关键技术亮点 (Key Technical Highlights)
|
||
|
||
1. **Polygon偏移算法**:使用Clipper2实现高精度多边形偏移,支持任意凸多边形形状
|
||
|
||
2. **精确层级追踪**:使用m_first_layer_idx而非简单的m_plan.begin(),正确处理稀疏层跳过
|
||
|
||
3. **深度变化检测**:自动检测塔体深度变化,避免裙边冲突
|
||
|
||
4. **用户友好配置**:提供开关和数值配置,满足不同用户需求
|
||
|
||
5. **后向兼容**:禁用倒角时完全回到传统单层裙边模式
|
||
|
||
### 测试建议 (Testing Recommendations)
|
||
|
||
建议进行以下测试验证:
|
||
1. 标准多材料模型切片测试
|
||
2. 对角线加强筋(rib wall)擦除塔测试
|
||
3. 不同裙边宽度配置测试
|
||
4. 倒角开关启用/禁用测试
|
||
5. 实际打印验证附着力和材料节省效果
|
||
|
||
### 文档维护 (Documentation Maintenance)
|
||
|
||
本文档应该:
|
||
- 随代码更新保持同步
|
||
- 添加新的测试案例和结果
|
||
- 收集用户反馈和常见问题
|
||
- 记录未来改进的实现进度
|
||
|
||
---
|
||
|
||
## 附录 (Appendix)
|
||
|
||
### A. 相关源代码文件 (Related Source Files)
|
||
|
||
```
|
||
OrcaSlicer/
|
||
├── src/libslic3r/
|
||
│ ├── PrintConfig.hpp (配置参数声明)
|
||
│ ├── PrintConfig.cpp (配置参数定义)
|
||
│ └── GCode/
|
||
│ ├── WipeTower2.hpp (类定义)
|
||
│ └── WipeTower2.cpp (核心实现)
|
||
```
|
||
|
||
### B. 配置参数完整列表 (Complete Configuration Parameters)
|
||
|
||
| 参数名称 | 类型 | 默认值 | 范围 | 说明 |
|
||
|---------|------|--------|------|------|
|
||
| prime_tower_brim_width | float | 6.0 | 0-20 | 裙边总宽度(mm)|
|
||
| prime_tower_brim_chamfer | bool | true | - | 启用倒角功能 |
|
||
| prime_tower_brim_chamfer_max_width | float | 3.0 | 0-10 | 最大倒角宽度(mm)|
|
||
| wipe_tower_rotation_angle | float | 0.0 | 0-360 | 擦除塔旋转角度 |
|
||
| wipe_tower_cone_angle | float | 0.0 | 0-45 | 锥形稳定角度 |
|
||
|
||
### C. 关键常量 (Key Constants)
|
||
|
||
```cpp
|
||
const float Width_To_Nozzle_Ratio = 1.25f; // 线宽与喷嘴直径比
|
||
const float WT_EPSILON = 1e-3f; // 浮点比较容差
|
||
const double M_PI_4 = 0.785398163397448; // π/4
|
||
```
|
||
|
||
### D. 参考资料 (References)
|
||
|
||
1. **BambuStudio源代码**
|
||
- 路径: `D:\work\Projects\BambuStudio\src\libslic3r\GCode\WipeTower.cpp`
|
||
- 关键函数: `finish_layer()` (第1300-1331行)
|
||
|
||
2. **OrcaSlicer源代码**
|
||
- 路径: `C:\WorkCode\orca1.1111111111111\OrcaSlicer\src\libslic3r\GCode\WipeTower2.cpp`
|
||
- 关键函数: `finish_layer()` (第2086-2133行)
|
||
|
||
3. **Clipper2文档**
|
||
- 官网: http://www.angusj.com/clipper2/
|
||
- 多边形偏移算法参考
|
||
|
||
4. **3D打印术语**
|
||
- Brim(裙边):第一层周围的额外材料,增加附着力
|
||
- Prime Tower(擦除塔):多材料打印中的工具更换塔
|
||
- Chamfer(倒角):斜面过渡,这里指逐层递减效果
|
||
|
||
---
|
||
|
||
## 版本历史 (Version History)
|
||
|
||
### v1.0 - 2024-12-16
|
||
- 初始实现,基于BambuStudio WipeTower代码
|
||
- 完整功能迁移到OrcaSlicer WipeTower2
|
||
- 添加配置参数和用户控制
|
||
- 适配Polygon架构,支持对角线加强筋
|
||
- 完整文档编写
|
||
|
||
---
|
||
|
||
**文档作者**: Claude AI
|
||
**日期**: 2024年12月16日
|
||
**版本**: 1.0
|
||
|
||
---
|
||
|
||
*本文档详细记录了从BambuStudio到OrcaSlicer的裙边倒角功能迁移过程,包括技术细节、算法解释、配置指南和测试建议。如有疑问或需要更新,请参考源代码或联系开发团队。*
|