HTML Canvas+TypeScript:二次曲线控制点计算异常排查求助
问题分析与修正
1. 角度计算函数的核心错误
你的getAngleRelativeToOrigin存在三个关键问题:
- 方向逻辑颠倒:dx和dy应该取
end.x - start.x、end.y - start.y,这样计算的是从start指向end的线段方向角,而非反向。 - 冗余的单位转换:函数返回角度值,但后续计算又要转回弧度,既浪费性能又可能引入精度误差,直接返回弧度更合理。
- 命名误导:这个函数计算的是线段自身的方向角,和原点无关,改名更贴合实际功能。
修正后的角度函数:
getLineDirectionAngle(start: Point, end: Point): number { const dx = end.x - start.x; const dy = end.y - start.y; return Math.atan2(dy, dx); }
2. 旋转公式的符号错误
你在计算y坐标时的旋转矩阵符号有误,标准2D绕点旋转公式为:
x' = cosθ * (x - cx) - sinθ * (y - cy) + cx y' = sinθ * (x - cx) + cosθ * (y - cy) + cy
你的代码中y分量写成了- Math.cos(theta) * (start.y - midPoint.y),减号会导致旋转方向错乱,直接引发曲线变形。
3. 控制点的向量选择错误
你当前用start.x - midPoint.x和start.y - midPoint.y作为旋转向量,这是从mid指向start的线段半长向量,旋转后无法保证控制点处于线段的垂直方向(这是构建对称二次曲线的关键)。
修正后的控制点计算函数
假设你需要控制点位于线段的垂直方向,且距离中点的长度为线段半长(形成等腰三角形),修正后的代码如下:
getControlPoint(start: Point, end: Point): Point { const midPoint = this.lineMidPoint(start, end); // 计算线段的方向角 const lineAngle = this.getLineDirectionAngle(start, end); // 垂直方向角度(+π/2为向上偏移,-π/2为向下偏移,按需调整) const perpendicularAngle = lineAngle + Math.PI / 2; // 计算线段半长(作为控制点的偏移距离) const dx = end.x - start.x; const dy = end.y - start.y; const halfLength = Math.hypot(dx, dy) / 2; // 计算最终控制点坐标 const x = midPoint.x + Math.cos(perpendicularAngle) * halfLength; const y = midPoint.y + Math.sin(perpendicularAngle) * halfLength; return { x, y } as Point; }
快速验证技巧
- 测试角度函数:取
start=(0,0)、end=(1,0),正确返回值应为0弧度;取start=(0,0)、end=(0,1),返回值应为Math.PI/2弧度。 - 测试控制点:取
start=(0,0)、end=(2,0),修正后的函数应返回(1,1)(向上偏移)或(1,-1)(向下偏移)。
内容的提问来源于stack exchange,提问作者m.tracey
相关产品推荐
相关产品推荐

