AI 协作日志

学生 Web 实验作品平台

学号:202412211401030 · 来源:ai-log.md

# 实验二 AI协作记录

> 使用工具:Trae 内置 AI 助手(WebGL2 / GLSL ES 3.00 方向)。以下三次协作均按“先自己判断 → 提问 → 独立测试 → 决定是否采纳”的流程进行;所有结论均已在浏览器中实测核验,代码中保留了对应的自测输出与注释。

## AI协作1 · Koch算法

### 我的目标与初步判断
Task B 中起始三角形 `baseTriangle=[[-0.82,-0.43],[0.82,-0.43],[0,0.99]]` 是按**逆时针**排列的(我用叉积验证:AB=(1.64,0),AC=(0.82,1.42),叉积 1.64×1.42>0,确为 CCW)。我初步判断:沿逆时针方向行走时,轮廓内部在左侧,外部在右侧,所以底边 A→B 上的凸起应朝下,即把向量 P→Q **顺时针旋转 60°(−60°)**,而不是凭截图随便选符号。另外我预测 Level 3 的线段数应为 3×4³=192,因为每条边每次替换 1 段变 4 段。

### 关键提示词(原文)
> 初始三角形三个顶点按逆时针排列,边按 A→B→C→A 行走。Koch 替换时向量 PQ 应该旋转 +60° 还是 −60° 才能保证凸起在轮廓外侧?请只解释方向判断方法,不要给完整程序。另:为什么 Level 3 是 192 段而不是 3×3^3?

### AI关键建议摘要
1. 凸起方向由边的绕行方向决定,与屏幕朝向无关:CCW 行走时外侧恒为行进方向的右侧,对 PQ 做 −60° 旋转(给出旋转矩阵 cos(−60°)=0.5、sin(−60°)=−√3/2)。
2. 建议先用一段单独的水平线段(不接三角形)打印替换后坐标验证方向,再放进三条边。
3. 段数按 4 的幂增长:每次 1 段被替换成 4 段,故第 n 层为初始 3 条边 ×4ⁿ;3 的幂是 Sierpinski 三角形数(Task A)的增长规律,二者不要混淆。

### 我的测试方法与结果
在 `js/task-b.js` 中写了页面加载即执行的自测(Console 可见):
1. 单段测试:`subdivideSegment([-3,0],[3,0],1,one)` 输出
   `(-3,0),(-1,0),(0,-1.73205…),(1,0)`,与手算的 (−3,0)、(−1,0)、(0,−√3)、(1,0) 完全一致,凸起确实朝下。
2. 层数测试:`[TaskB 自测] Level 0..4:顶点数 3/12/48/192/768,期望 3/12/48/192/768,全部一致`。
3. 浏览器画面:Level 0 为正向等边三角形,Level 1 起六个方向的凸起全部朝外、无内凹;Level 4 共 768 个连续顶点,`LINE_LOOP` 自动闭合,边界连续无断点。

### 采纳情况及修正结论
全部采纳,但旋转公式坚持自己推导一遍:R = P + rot(−60°)·(Q−P),即
`rx=px+0.5dx+√3/2·dy`、`ry=py−√3/2·dx+0.5dy`。结论:符号由 CCW 绕行方向决定;若以后改成 CW 初始三角形,必须同步翻成 +60°。每边只压入“起点”、终点由下一段起点承担,所以 LINE_LOOP 缓冲区顶点数恰好等于线段数 3×4ⁿ。

## AI协作2 · 绘图板调试

### 具体错误现象(如一次成功,可先人为注入并恢复一个小错误)
正式逻辑一次通过。按实验要求人为注入一个错误:把 `pointerToNDC` 中的 Y 翻转暂时去掉,写成 `yNDC=2*yCanvas/canvas.height-1`(与 X 同号),保存后在画布四角点击。
现象:在 Canvas **上方**点击,点却画在**下方**,上下镜像;在矩形模式下从左上拖到右下(两次点击),得到的矩形出现在镜像位置。恢复 Y 翻转后一切正常。调试过程中另观察到:浏览器窗口不是最大化时(CSS 显示尺寸小于 720×620),若不乘 `canvas.width/rect.width`,点击位置会整体向左上偏移。

### 我的初步排查
1. 先确认 `event.clientX/clientY` 是相对浏览器视口的,不是相对 Canvas 的,必须减去 `getBoundingClientRect()` 的 left/top;
2. Y 方向错误怀疑是漏了 NDC 与窗口坐标系 Y 轴方向相反这一步;
3. 缩放后的偏移怀疑是 CSS 尺寸与 Canvas 像素尺寸不一致造成的。

### 关键提示词(原文)
> WebGL2 画布宽高属性是 720×620,但 CSS 把它缩放到了约 600px 宽显示。点击后画出来的点上下颠倒、而且整体偏左上。请给出可能原因的排查清单和验证步骤,不要直接重写我的事件处理函数。

### AI建议及逐项测试
1. 打印 `rect` 的 left/top/width/height 与 `canvas.width/height`:实测 rect.width≈620 时,两组尺寸确实不相等 → 需要 `(clientX-rect.left)*canvas.width/rect.width` 做换算。
2. Y 轴必须翻转:NDC 原点在中心、Y 向上,窗口像素 Y 向下,公式应为 `yNDC=1-2*yCanvas/canvas.height`。恢复后四角点击测试:左上≈(−1,+1)、右下≈(+1,−1),位置正确。
3. 两次点击状态混乱的风险点:第一点必须保存在跨事件变量中,且在工具切换、对象完成、清空三个时机都复位。按建议逐一检查:线段/矩形第二次点击后 `pending=null`;`tool` 的 change 事件里 `pending=null`;清空按钮同时清 `objects` 和 `pending`。
4. 矩形对角顺序:先取 `min/max` 包围盒再按 左下→右下→右上→左上 输出四个点给 `LINE_LOOP`,实测两个对角点击顺序都能得到正确矩形。

### 最终原因及修复证据
最终实现采用指导书课堂公式(含 CSS 缩放校正 + Y 翻转)。验证:① 四角附近点击,状态栏显示的 NDC 坐标符号正确;② 改变窗口大小后点中心仍落在中心;③ 点、线、矩形依次创建后全部保留;④ 线段第一点后切换工具,旧第一点不再被复用;⑤ 清空后画布全白,Console 无报错。注入的 Y 轴错误已恢复为正确实现。

## AI协作3 · 主题整合

### 主题及预期效果
HTML 骨架已预留"绽放"主题词、层数滑块、尺度滑块、toggle 按钮、设计说明 textarea,以及三个已生成的几何雏形:外层圆环(`makeCircle(1.10,96)`)、12 条放射线(从中心辐射到圆环)、12 个节点(沿圆环均匀分布的 POINTS)。预期复用 B 的 Koch 雪花生成、C 的 uniform 旋转 + rAF、D 的鼠标 NDC 坐标转换三项能力。核心思路:Koch 雪花 + 圆环 + 放射线 + 节点组成"绽放"主体;toggle 控制自转;点击移动中心。

### 两个方案的AI提示词(原文)
> 骨架已经给了"绽放"主题和三个几何组成(圆环 + 放射线 + 节点),Koch 雪花作为中心主体。我需要决定:① 这三个几何哪些应该自转、哪些应该静止;② toggle 按钮应该只让雪花自转,还是让全部几何一起转;③ 点击画布移动中心时,Koch 雪花是否应该跟随移动。请给这三个点分别给出两种方案(A/B),并解释每种方案在视觉效果、uniform 参数传递数量、与 Task B/C/D 复用程度上的利弊。

### AI提出的可选方案
1. 自转范围:
   - 方案 A:**雪花自转、圆环静止、放射线和节点也一起自转**(和雪花共角速度)。理由:放射线和节点贴在圆环上,视觉上像"绽放"时花瓣展开,旋转有动感;只需给它们都用同一个 uTheta uniform,不增加 uniform 数量。
   - 方案 B:雪花单独自转、其他全部静止。优点是 uniform 最少,但"绽放"的整体流动感弱,看起来像静止背景上一片转动雪花。
2. toggle 语义:toggle 控制 `running` 布尔,animate 里 `if(running)` 条件驱动 theta 增量——这是骨架已有的模式,不需要改骨架;toggle 只翻转 running 并重绘,天然符合"开始/暂停"语义。
3. 中心移动:全部几何(雪花 + 圆环 + 放射线 + 节点)共用 `uOffset` uniform,点击更新 `center` 数组后整套图案一起平移。这是骨架里 `drawShape` 函数的已有行为(`off=center` 为默认参数),不需要任何改动。

### 方案取舍与理由
采用方案 A。理由:① 复用程度最高——旋转只走骨架现成的 `uTheta` uniform,不传新 uniform;② 骨架 `drawShape(pts,mode,color,angle=0,sc=1,off=center)` 已把 theta/scale/offset 统一封装,我只需要调用时传对参数就行;③ 视觉上雪花、放射线、节点一起转,圆环静止,像"绽放"的花瓣在旋转,与主题词契合。

### 实际实现、测试与结果
TODO 填充位置:
- E1(圆环):骨架已生成,我在 TODO 注释里写清"外层圆轨道,LINE_LOOP 96 段,静止不旋转"
- E2(放射线 + 节点):骨架已生成,我写清"12 条从中心辐射的放射线 LINES + 12 个节点 POINTS,跟随雪花自转(用同一个 theta)"
- E3(鼠标 NDC 转换):完整复用 Task D 的公式——`(clientX-rect.left)*canvas.width/rect.width` 校正 CSS 缩放,`2*x/canvas.width-1` 映射到 X NDC,`1-2*y/canvas.height` 映射到 Y NDC(翻转),最后赋值给 `center=[xNDC,yNDC]`
- E4(toggle 控制):翻转 `running=!running` 并更新按钮文字为"暂停/开始/暂停旋转"
实测:初始状态中心静止,三层几何组成都在中心;toggle 后雪花 + 放射线 + 节点一起自转、圆环静止;点击任意位置整套几何(圆环 + 雪花 + 放射线 + 节点)平移到点击处;层数滑块改变雪花段数(3×4ⁿ 在状态栏可见);尺度滑块整体缩放;复位恢复默认。Console 无错误。

## 其他AI使用(若有)
- 工具:Trae AI 助手。
- Task A:询问“改变递归层次与改变 uniform 颜色在数据更新上的区别”,据此把代码组织成 `rebuildGeometry()`(重新生成顶点并 `bufferData`)与 `draw()`(只更新 `uColor`)两条路径,并在代码注释中标明顶点何时重新上传 GPU。
- Task C:询问“多个 requestAnimationFrame 循环同时运行会怎样”,回答是角度被多次累加、速度随循环数翻倍且无法用单一 paused 停止;实现中只在脚本末尾启动一次 rAF,所有控件只修改状态变量。