AI 协作日志

学生 Web 实验作品平台

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

# 实验二 AI协作记录

## AI协作1 · Koch算法(Task B)

### 我的目标与初步判断
目标:独立实现 Koch 雪花,重点确认"如何保证突起朝外"。
我自己的预测:初始三角形 `[(-0.82,-0.43),(0.82,-0.43),(0,0.99)]` 是逆时针排列。沿边 A→B 行走时,多边形内部在左手侧,外侧应在右手侧,因此应把向量 Q-P **顺时针旋转 60°**(右转)加到 P 上。如果用逆时针旋转 60°,底边的突起会朝三角形内部,雪花向内凹。

### 关键提示词(原文)
> "我有一个逆时针排列的等边三角形,要实现 Koch 雪花:把每条边 A→B 三等分得到 P、Q,再以 PQ 为底向外作等边三角形得到 R。请问 R 应该用向量 Q-P 旋转 +60° 还是 -60°?如何只看边方向判断而不看截图?另外为什么 Level n 的线段数是 3×4^n?"

### AI关键建议摘要
- 对逆时针(CCW)绕行的闭合多边形,外法线在前进方向的右侧,即把边向量 **顺时针旋转 60°**(即角度 -60°)后与 P 相加。
- 旋转公式:`R = P + (dx·cos60° + dy·sin60°, -dx·sin60° + dy·cos60°)`。
- 每条原始线段被替换成 4 条新线段,初始有 3 条,所以递归 n 层后线段数 = `3·4^n`;顶点数(LINE_LOOP 下)等于线段数。

### 我的测试方法与结果
1. 先只画 Level 0,确认三个顶点按 `(-0.82,-0.43)→(0.82,-0.43)→(0,0.99)` 连线,闭合为向上的三角形。
2. 单独测底边 A=(-0.82,-0.43)→B=(0.82,-0.43):按顺时针 60° 公式算出 R≈(0,-0.904),即底边向下凸——与"外侧在下方"的预测一致。
3. 改成逆时针 +60° 试了一次,R≈(0,0.044) 朝三角形内部,图案向内凹,证实方向判断正确,改回顺时针。
4. 在 Console 打印 `buildKoch(n).length`:Level 0=3、1=12、2=48、3=192、4=768,与实验指导书验收表完全一致。

### 采纳情况及修正结论
完全采纳 AI 建议的旋转方向,但**没有直接粘贴整段 Koch 代码**——自己按 A→P→R→Q→B 四段递归写 `subdivideSegment`,并用 LINE_LOOP 让末点自动闭合回首点。结论:逆时针多边形外侧 = 右转 60°;线段数随 4^n 增长是因为每段被替换成 4 段。

---

## AI协作2 · 绘图板调试(Task D)

### 具体错误现象
程序第一次写完后,人为把 Y 轴翻转那一行删掉(即 `yNDC = 2*yCanvas/canvas.height - 1`,不做 `1 - ...`)做 Bug Hunt。现象:在 Canvas 视觉顶部点击,点却出现在底部;在四角测试时左上角的点跑到右下角附近。

### 我的初步排查
- 先查 `getBoundingClientRect()` 是否取对——打印 `rect.left/top` 与 `event.clientX/Y`,数值合理。
- 怀疑是 CSS 尺寸与 Canvas 像素尺寸不一致,检查发现 HTML 里 `canvas{max-width:100%}` 会缩放显示,但 `canvas.width=720` 不变,所以必须用 `(clientX-rect.left)*canvas.width/rect.width` 把 CSS 像素换算回 Canvas 内部像素——这一步原代码已经正确。
- 锁定到 Y 方向:WebGL NDC 原点在屏幕左下角,而鼠标 `clientY` 原点在左上角,必须翻转。

### 关键提示词(原文)
> "我用 WebGL 在 Canvas 上画鼠标点击的点,点出来上下颠倒:我点画布顶部,点却画在底部。我已经做了 `getBoundingClientRect` 并按 canvas.width 缩放。可能是什么原因?正确的 clientY→NDC 公式是什么?另外线段两次点击后如何避免第一点被下一个工具误用?"

### AI建议与逐项测试
1. AI 指出 Y 轴翻转:`yNDC = 1 - 2*yCanvas/canvas.height`,而不是 `2*yCanvas/h - 1`。改回公式后,四角点击全部落在预期象限,Y 方向正确。
2. AI 提醒:切换工具或点"清空"时必须把 `firstPoint` 置空,否则线段的第一点会残留并被矩形工具误用。我在 `tool.change` 和 `clear` 里都加了 `firstPoint=null`。
3. AI 建议把对象数组在 JS 端完整保存(类型+顶点+颜色),每帧 clear 后重新遍历上传,而不是只往 GPU 追加顶点——这样"清空"和"保留已画对象"都简单。我采用了 `bufferData` 整体重传的方式。

### 最终原因及修复证据
根因:Y 轴未翻转 + 工具切换时未重置 `firstPoint`。
修复后验证:(1) 四角分别画点,位置全部正确;(2) 先画一点、一线、一矩形,再画新对象,旧对象保留;(3) 线段点完第一点后切换到矩形再点一次,没有出现错位的旧线;(4) 清空后旧图形消失。测试完毕已把故意删掉的翻转行恢复。

---

## AI协作3 · 主题整合(Task E)

### 主题及预期效果
主题词:**绽放**。视觉上想表现一朵旋转的花:外层锯齿花瓣(复用 Koch 雪花)、一圈外环、中心花芯、向外辐射的花蕊节点。交互上希望既能旋转动画,又能用鼠标把花心拖到任意位置,还能用滑块改变花瓣层数和整体大小。

### 两个方案的AI提示词(原文)
> "我要用 WebGL 基本图元(POINTS/LINES/LINE_LOOP)表达主题'绽放',必须复用 Koch 雪花和旋转动画,再新增至少两个几何组成、至少两种交互。请给我两种方案,从图元数量、交互难度、可解释性三方面比较。"

### AI提出的方案
- **方案甲(同心圆+放射线)**:外环 LINE_LOOP、内层花芯圆 LINE_LOOP、12 条 LINE 花蕊、12 个 POINTS 节点,中心是旋转的 Koch 花瓣。图元总数约 96+48+24+12+Koch 顶点 ≈ 200+。
- **方案乙(递归分支树)**:从中心递归长出枝条,每条末端画一个点,类似分形树。图元数量随深度指数增长(类似 Koch),交互可做"生长速度",但需要新写一套递归分支算法,工作量大且与前面任务复用度低。

### 方案比较、取舍理由
| 维度 | 方案甲 | 方案乙 |
|---|---|---|
| 图元数量 | 约 200,性能宽裕 | 随深度指数膨胀,Level 3 后上千顶点 |
| 交互难度 | 旋转/点击移中心/滑块,都已在 B/C/D 实现过 | 需新写生长动画与分支参数 |
| 可解释性 | 圆环=花冠、花蕊=放射线、节点=光点,直观 | 分形树枝与"绽放"关联较弱 |

**选择方案甲**:它真正复用了 Task B 的 Koch 生成、Task C 的 rAF 旋转 uniform、Task D 的鼠标 NDC 转换,新增的外环/花芯/花蕊/节点都是可一眼识别的几何组成;放弃方案乙因为它需要另写一套递归,与"不重新搭底层系统"的要求不符,且性能边界难控。

### 实际实现、测试与结果
- 复用:Koch 生成函数(B)、`uTheta` uniform 旋转与单个 rAF 循环(C)、`getBoundingClientRect`→NDC 坐标转换(D)。
- 新增几何:① 外环 `makeCircle(1.10,96)`;② 内层花芯圆 `makeCircle(0.32,48)`;③ 12 条放射花蕊;④ 12 个端点光点。
- 新增交互:① 点击画布任意位置把 `center` 移到该 NDC(改变 `uOffset`);② level 滑块实时重建 Koch 几何;③ scale 滑块调整整体缩放;④ 开始/暂停旋转。
- 验证:初始状态花朵居中;点击右下角后花朵中心跳到右下;拖动 level 到 4 花瓣变密;scale 调到 30 花朵缩小;暂停按钮切换后 theta 停止增长。无 Console 报错。

---

## 其他AI使用
- 工具:豆包(对话)。
- 排错时让 AI 列出 WebGL 常见问题对照表(Shader 版本、Buffer 绑定、uniform 位置),用于自查 Console;没有让 AI 整段重写代码。
- Task C 的 rAF 时间积分:AI 提醒要用 `(time-lastTime)/1000` 算 dt 并钳制到 0.1s,防止切后台回来 theta 跳变,已采纳。