Add tests and implement boundary smoothing and cutout functionality

- Introduced tests for boundary smoothing in `test_boundary_smoothing.py`, verifying that smoothing reduces stair-step artifacts while preserving boundary integrity.
- Added tests for cutout boundary behavior in `test_cutout_boundary.py`, ensuring proper handling of boundary triangles and normal blending.
- Created `test_temporary_attributes.py` to check the cleanup of temporary attributes across depth modifier branches, ensuring no warnings are raised.
- Implemented point culling functionality in `test_validity.py`, confirming that invalid points are removed without affecting adjacent geometry.
- Developed boundary smoothing logic in `boundary_smoothing.py`, allowing for depth smoothing while maintaining edge integrity.
- Added cutout boundary management in `cutout_boundary.py`, including functions for removing boundary triangles and tapering thickness profiles.
- Implemented validity checks in `validity.py` to ensure proper deletion of invalid vertices and associated wire edges.
This commit is contained in:
2026-09-11 20:37:20 +08:00
parent e8129fe495
commit 31074bd511
85 changed files with 2501 additions and 1451 deletions

View File

@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-09-11

View File

@@ -0,0 +1,70 @@
## Context
本次只读核对了当前构建源码和保存资产。以下为组内节点数量,嵌套引用单独追踪,实施前须重新确认基线。
| 几何节点组 | Capture | Store |
| --- | ---: | ---: |
| O Image Plane | 1 | 2 |
| O Image Depth Plane | 6 | 0 |
| O Image Relief Plane | 0 | 0 |
| O Image Cutout | 0 | 1 |
| O Image Depth Cutout | 8 | 3 |
| O Image Depth Balloon | 0 | 1 |
| O Image Depth Panorama | 6 | 1 |
| 合计 | 21 | 8 |
Depth Plane、Relief Plane 引用 Image Plane。三个材质组作为命名属性消费者纳入核查。工作区已有节点逻辑、测试和资产修改,基线采用实施开始时的实际工作区状态。
## Goals / Non-Goals
目标是全部几何组及其嵌套组 Capture 为零、字段消费关系清晰、存储具有实际必要性,源码、资产、规范与测试一致。保持公开接口、几何效果、UV、材质及用户输入属性行为;交付包括节点资产构建与测试。
## Decisions
### 字段在消费位置求值
```mermaid
flowchart TD
A[字段及实际消费者] --> B{需要按名称访问}
B -->|是| C[保留必要命名属性]
B -->|否| D{消费上下文求值等价}
D -->|是| E[字段直连并显式转换域]
D -->|否| F[调整消费顺序或在源几何采样]
F --> G{仍需保存源数据}
G -->|否| E
G -->|是| H[仅存储必要命名数据]
H --> I[最后消费者后清理临时属性]
```
Capture Attribute 在生产构建、嵌套组、保存资产和相关测试辅助图中均禁止使用。多个消费者、跨区域或连线较长不构成存值理由。Evaluate on Domain 用于域转换;它不固定几何版本。源几何采样必须明确源几何、域与索引对应关系,并同时评估布局和求值开销。
每处保留的 Store 记录名称、类型、域、Selection、写入阶段、实际读者和必要性。跨变形或拓扑变化仍需保存时,先减少携带的数据,再使用必要命名属性;不按现有 Capture 的字段清单逐项替换 Store。内部临时属性使用专用前缀,在最后消费者后清理;避免覆盖或删除已有用户属性,必要时通过名称冲突检查与更具体的命名解决。
### 按业务链拆解现有捕获
| 范围 | 当前用途 | 实施方向 |
| --- | --- | --- |
| boundary_smoothing、smoothing;三个深度组共 12 个 Capture | 原边界、影响范围、循环边界、源索引及最近边界映射 | 拓扑不变时直接消费 Boundary 和 Influence;Panorama 的闭合初始球面使用 False 表示原边界。其他原边界及固定映射逐项审查源几何采样或最小命名数据,保持原轮廓保护和循环映射语义 |
| depth_surface 的切分;3 个 Capture | Camera、Cut 跨 Split Edges 与删面传播 | 分开审查面采样与切分标记,在源几何计算或采样,保持 FACE、CORNER、POINT 转换顺序;实际需要传播的最少信息才存值 |
| depth_surface 的厚度;2 个 Capture | Position、Vertex、Normal 跨展平、挤出、合并、恢复 | 优先简化厚度构建顺序和源表面采样,保持独立重叠表面身份及零厚度行为;论证剩余源身份或数据的必要存储 |
| image_depth_cutout;2 个 Capture | center、front_normal、structure、inflation_normal、edge_weight、front_delta、thickness、normal | 前表面计算尽量在原消费几何完成,保留独立中心表面供采样;逐字段核对圆化和壳体消费者,合并可复用的源数据,保持 Balloon、Uniform 两分支行为 |
| material;2 个 Capture | Source 标记 Join 后待删除的输入网格 | 改为可明确验证的来源选择或材质传递流程,优先由几何数量及分支关系得到选择;验证空输入、多材质和生成几何保留 |
| 现有 8 次 Store | UVMap、o_normal_scale | 保留命名协议,审查重复写入合并机会,保持角 UV、正背面与侧壁掩码 |
表中替代路径是待求值验证的候选。对于跨拓扑数据,实施中以真实结果确认直接求值是否等价;结构可读性和语义一致性共同决定最终方案。Capture 为零是硬性条件。
### 规范和测试一起纠正
更新 AGENTS.md、docs/internals/node-assets.md 及实际受影响的当前内部说明。规范明确禁止 Capture,描述直连、显式域转换、源几何采样、必要命名存储及清理规则,流程图从上到下。旧变更文件保留历史记录,本提案作为后续实施依据。
资产清单测试同时检查构建定义与保存资产,递归遍历嵌套几何组并去重;断言 Capture 为零。删除 capture_fields 辅助函数及测试用法,替换 test_depth_relief_planes、test_boundary_smoothing 中强制 Capture 的断言。原测试只允许 UVMap、o_normal_scale 的 Store 名称白名单应按经审查的必要存储更新,不把数量下降作为行为正确的替代。
复用真实求值用例,覆盖域转换、非均匀深度、断层、原边界保护、平滑影响范围与固定映射、厚度、Balloon/Uniform、法线、UV、材质和用户属性。布局通过完整图检查区域关系、连线跨度、交叉、节点重叠和标题可读性;零重叠仅是其中一项。
## Risks / Trade-offs
- 直连改变求值几何或属性版本 → 使用非均匀输入和跨阶段场景对比实施前基线,明确每处采样域。
- 变形后最近邻映射漂移、重叠表面串值 → 优先稳定索引对应,验证循环平滑与独立重叠表面。
- 源几何采样增加连线或重复计算 → 结合逐组图审查及代表场景耗时选择简单方案;必要命名存储需逐项证明。
- 临时命名属性冲突或清理影响用户数据 → 明确名称与生命周期,测试输入用户属性保留及临时属性消失。
- 资产与源码不同步 → 执行 uv run node-group build,独立加载保存资产验证,再运行 uv run pytest 并确认正常退出。

View File

@@ -0,0 +1,30 @@
## Why
之前的属性整理将大量 Store Named Attribute 替换为 Capture Attribute,保留了中间值存储并增加跨阶段连线,偏离了直接消费字段、提高结构可读性的要求。当前七个几何节点组共有 21 个 Capture;规范与部分测试还在强制沿用这一方向,需要一并纠正。
## What Changes
- 全面检查全部几何节点、嵌套组与共享构建函数,禁止使用 Capture Attribute。
- 优先让字段在消费位置直接求值,显式表达必要域转换;通过调整处理顺序或源几何采样减少中间存储。
- 逐项论证 Store Named Attribute 的必要性:保留实际命名协议,以及确实需要跨几何变化保存的最少数据;禁止机械替换 Capture。
- 更新 AGENTS.md、节点资产规范和相关当前实现说明,统一禁止 Capture、优先直连的规则。
- 更新测试,移除依赖 Capture 的结构断言及测试辅助用法,检查全部资产与嵌套几何组中 Capture 为零,并验证真实几何行为。
- 重建节点资产,核对布局、接口、UV、材质与几何结果。
## Capabilities
### New Capabilities
- `geometry-field-flow`: 几何节点字段直连、必要命名存储、禁止 Capture 及对应资产验证规则。
### Modified Capabilities
无。
## Impact
- tools/nodes/common、tools/nodes/groups,以及实际受影响的排列代码。
- tests/tools/nodes、tests/support 及相关材质、Operator 测试。
- src/anyimage/assets/O_AnyImage.blend。
- AGENTS.md、docs/internals/node-assets.md 及检索确认受影响的当前内部说明。
- 公开接口、几何功能与属性协议保持一致;实施时保留工作区已有修改。该提案取代 simplify-node-attribute-flow 中关于 Capture 的设计决策。

View File

@@ -0,0 +1,57 @@
## ADDED Requirements
### Requirement: Geometry graphs prohibit Capture Attribute
全部生产几何节点定义、嵌套几何组、保存资产及相关测试辅助图 MUST 不使用 GeometryNodeCaptureAttribute。
#### Scenario: Inspect definitions and saved assets
- **WHEN** 分别构建节点定义并加载保存资产,递归检查全部几何组及嵌套组
- **THEN** 每个已访问几何组的 Capture Attribute 数量均为零
### Requirement: Fields are consumed directly when evaluation is equivalent
字段 SHALL 在消费位置直接连接,明确必要域转换;跨几何变化时 SHALL 优先审查调整消费顺序及源几何采样,以减少中间存储。多个消费者或跨区域连线 MUST 不作为存值的充分理由。
#### Scenario: Reuse a field without geometry changes
- **WHEN** 多个消费者所在几何状态、域、类型与输入属性版本允许等价求值
- **THEN** 消费者直接使用字段及必要域转换,保持原结果而不新增存储
#### Scenario: Consume a field after topology changes
- **WHEN** 切分、删面、挤出或合并改变源字段求值上下文
- **THEN** 实现明确源几何与映射,验证结果等价,并仅保存无法通过合理调整消费或采样消除的必要数据
### Requirement: Named storage has an explicit purpose and lifetime
每处 Store Named Attribute SHALL 有明确的实际消费者与存储必要性,记录名称、类型、域、Selection 和阶段。必要命名协议 SHALL 保留;临时属性 SHALL 在最后消费者后清理,并保留已有用户属性。
#### Scenario: Preserve material protocols
- **WHEN** 输出几何供材质消费 UVMap 或 o_normal_scale
- **THEN** 属性域与数值保持正确,包括角 UV 以及正背面和侧壁掩码
#### Scenario: Finish consuming temporary data
- **WHEN** 几何处理完成临时命名数据的最后一次消费
- **THEN** 最终输出不携带新增内部临时属性,且输入已有用户属性的名称、类型和值按原行为保留
### Requirement: Geometry behavior and graph readability are preserved
重构 SHALL 保持修改器接口、几何结果、UV 和材质行为,并逐组检查字段消费关系与完整节点布局的可读性。
#### Scenario: Validate depth processing
- **WHEN** 使用非均匀深度测试 Split 开关、零与正厚度、独立重叠表面、Balloon/Uniform、圆化、膨胀及法线平滑
- **THEN** 实际几何与实施前行为基线等价,索引重排按拓扑和对应几何数据比较
#### Scenario: Validate cut boundary smoothing and panorama
- **WHEN** 对原轮廓、切分边界、平滑迭代和 Panorama 接缝、极点、无效像素及 Valid Only 求值
- **THEN** 原轮廓保护、影响范围、固定映射、球面采样与 UV 保持预期行为
#### Scenario: Inspect material inheritance
- **WHEN** 输入为空或带有多个材质槽,执行 Image Plane 或 Panorama 的材质继承
- **THEN** 材质槽及面材质索引符合原行为,生成几何保留且输入来源几何正确处理
### Requirement: Rules tests and saved assets agree
项目规范及当前节点资产说明 SHALL 明确禁止 Capture 并采用一致的字段传递规则。测试 SHALL 覆盖结构约束与真实行为;节点资产 SHALL 重建并经过独立加载验证,相关测试及全量测试正常退出后完成交付。
#### Scenario: Deliver a geometry graph change
- **WHEN** 本次节点整理完成
- **THEN** 源码、规范、测试和 O_AnyImage.blend 同步,Capture 旧结构断言已替换,uv run node-group build 与 uv run pytest 成功且正常退出

View File

@@ -0,0 +1,29 @@
## 1. 基线与规范
- [x] 1.1 核对实施时工作区已有修改、七个几何组及嵌套引用,记录 Capture/Store 数量、各存值字段的域、阶段、实际消费者和必要性;运行现有节点测试,记录基线及已有失败。
- [x] 1.2 保存代表场景的几何、UV、材质索引与属性行为基线,覆盖深度切分、厚度、边界平滑、重叠表面、两种 Cutout 模式与 Panorama。
- [x] 1.3 更新 AGENTS.md、docs/internals/node-assets.md 及实际受影响的当前内部说明,统一禁止 Capture、字段直连、显式域转换、源几何采样与必要命名存储规则;核对当前规则一致。
## 2. 几何节点整理
- [x] 2.1 整理原边界与 Influence:Panorama 原边界使用闭合源面的常量语义,拓扑不变的字段直接求值,其余保护数据选择必要传递方式;验证原轮廓保护与平滑影响范围。
- [x] 2.2 整理平滑循环的 Boundary、SourceIndex、BoundaryIndex,明确稳定源几何与映射,移除 Capture;验证迭代前后映射、边界运动和拓扑行为。
- [x] 2.3 整理共用深度切分的 Camera、Cut,保持面采样、角域及点域转换与切分前后语义;验证非均匀深度、Split 开关和删面。
- [x] 2.4 整理厚度构建的源位置、顶点身份及法线,简化几何阶段或源采样,论证剩余必要命名数据;验证零厚度、封口、法线及独立重叠表面。
- [x] 2.5 整理 Depth Cutout 的中心、结构、圆化、厚度和膨胀字段,减少跨阶段存值;验证 Balloon/Uniform、厚度连续性、Edge Round、Front Inflation 和 Normal Smooth。
- [x] 2.6 整理材质继承的来源选择,移除 Source 捕获;验证 Image Plane、Panorama 的空输入、多材质槽、材质索引及生成几何保留。
- [x] 2.7 完成所有几何组和三个材质消费者的复查,保留 UVMap、o_normal_scale 等必要协议,逐项审查重复 Store;清理临时命名数据并验证用户属性保留。
- [x] 2.8 删除 capture_fields 及失去用途的辅助函数、导入和节点相关支持项;沿实际调用链确认旧实现引用消失,使用明确节点或 socket 引用接线。
## 3. 测试与可读性
- [x] 3.1 将 Capture 禁用检查加入构建定义及保存资产测试,递归遍历嵌套几何组并去重;更新 Store 名称规则以反映逐项批准的必要存储。
- [x] 3.2 替换 test_depth_relief_planes、test_boundary_smoothing 中强制 Capture 的断言,移除 test_depth_cutout 等测试辅助图中的 Capture 用法,保留有效行为覆盖与状态隔离。
- [x] 3.3 补齐本次受影响的域转换、边界固定映射、临时属性清理和用户属性保留测试;运行相关节点、材质及 Operator 测试并修复回归。
- [x] 3.4 逐组检查完整节点图的消费关系、跨区连线、交叉、重叠和接口显示,按需调整布局;验证排列前后实际连接与求值一致。
## 4. 资产与交付
- [x] 4.1 运行 uv run node-group build,更新 O_AnyImage.blend,完成保存后独立 Blender 加载与几何验证,确认全部几何组及嵌套组 Capture 为零。
- [x] 4.2 运行 uv run pytest 并确认正常退出;对比实施前行为基线,检查接口、几何、UV、材质及用户属性。
- [x] 4.3 检查最终差异、旧引用与当前规范一致性,交付逐组调整和保留 Store 的必要性清单、数量及验证结果;确认源码、规范、测试和资产同步,保留已有其他修改,不构建文档或打包扩展。

View File

@@ -0,0 +1,52 @@
# 几何节点核查
## 实施基线
- 基线采用实施开始时工作区源码,保留已有无效点清理、边界平滑、模型目录与粘贴预览等修改。
- 节点基线测试:295 项通过,正常退出。
- 保存 41 个场景、236 组数组,包含 Balloon/Uniform、Split、零与正厚度、法线平滑、膨胀、四边面与三角面边界平滑、Depth/Relief Plane、Panorama 有效性及重叠表面。
- 本地核查文件:build/attributes-capture-before.json、build/geometry-capture-before.npz;实现后的对应文件以 capture-after 命名。
## 存储决策
| 范围 | 最终实现与必要性 |
| --- | --- |
| 原边界 | Depth Plane 直接消费 UV 矩形边缘,Panorama 使用闭合源面的 False;Depth Cutout 的任意输入轮廓跨切分后无法从当前拓扑恢复,保留一个 POINT/BOOLEAN 标记 |
| 平滑 Boundary、Influence | 直接由不变拓扑和受保护轮廓计算,不保存字段 |
| 平滑 SourceIndex、BoundaryIndex | 分别分离源边界与当前边界,保持相同紧凑索引顺序;用原网格按 Index 采样的位置查询源边界,再按结果索引消费当前边界位置,不保存索引 |
| 切分 Camera | 面相机采样在当前面直接求值,保持显式 FACE 域,不保存 Camera |
| 切分 Cut | 原顶点受切分影响的标记跨分裂及删面使用,每个深度组保留一个 CORNER/BOOLEAN 标记;完成投影后精确删除 |
| 厚度 Position、Vertex、Normal | 将源索引编码进构造网格坐标后再挤出,按整数解码后的索引从独立源表面采样位置、厚度与法线,不保存字段;保留独立重叠表面身份 |
| Depth Cutout 中心、结构、圆化、膨胀字段 | 直接在投影源表面求值并按壳体源索引采样;仅厚度构建需要的圆化厚度额外在对应前表面索引上求值 |
| 材质 Source | 按输入网格顶点数量和 Join 的实际输入顺序识别待删除范围,不保存标记;验证空输入、多材质槽与排列前后结果 |
| UVMap | Image Plane 两个分支、Panorama 各有实际输出 UV 写入,共 3 次,CORNER/FLOAT2,材质按名称消费 |
| o_normal_scale | Image Cutout、Depth Balloon 各一次 POINT/FLOAT;Depth Cutout 原面 1、合并背面与侧壁后 0 两次 FACE/FLOAT,共 4 次;形状和材质按名称消费 |
所有保留 Store 的 Selection 均为 True。新增临时名称为 `.o_anyimage_depth_cut`、`.o_anyimage_original_boundary`,清理按完整名称执行;用户的其他属性,包括同前缀属性,保留原行为。
## 数量
| 节点组 | Capture 前 → 后 | Store 前 → 后 |
| --- | --- | --- |
| O Image Plane | 1 → 0 | 2 → 2 |
| O Image Depth Plane | 6 → 0 | 0 → 1 |
| O Image Relief Plane | 0 → 0 | 0 → 0 |
| O Image Cutout | 0 → 0 | 1 → 1 |
| O Image Depth Cutout | 8 → 0 | 3 → 4 |
| O Image Depth Balloon | 0 → 0 | 1 → 1 |
| O Image Depth Panorama | 6 → 0 | 1 → 2 |
| 合计 | 21 → 0 | 8 → 11 |
按节点组自身计数,嵌套 Image Plane 在递归结构检查中去重。11 次 Store 由 7 次实际输出协议写入和 4 次必要拓扑标记写入组成。
## 验证结果
- 41 个场景的顶点位置、带方向的面、角 UV、材质索引和法线掩码与基线一致;面按顶点坐标及角 UV 对应比较,允许输出索引重排。
- 源码和保存资产递归检查 Capture 为零;相关测试辅助图中已无 Capture。
- 已修正全量测试发现的旧模型名称断言,匹配工作区当前模型名称。
- 已刷新本地 BlendJob 0.1.17 wheel 的锁文件哈希;版本、依赖声明及 Manifest 保持一致。
- uv run node-group build 成功且正常退出:Blender 4.5.10 LTS 重建资产,独立进程重新加载并验证全部 10 个节点组,递归几何组 Capture 为零。
- 构建命令串行调用的全量 pytest:1237 项通过,耗时 221.33 秒,正常退出;覆盖新增跨 4096 索引行的厚度采样、临时属性精确清理、多材质继承、空输入和排列前后求值。
- 逐组检查最终布局、字段连接与共享源几何路径,7 个几何组均无节点重叠,排列前后行为及保存布局稳定性测试通过;交互预览位于 build/capture-nodes.html。
- git diff --check 与 OpenSpec 严格校验通过。源码检索中的 GeometryNodeCaptureAttribute 仅存在于禁止该节点的检查断言。
- 源码、规范、测试与资产同步完成,未构建文档或打包扩展。