javascript - HTML Canvas quadraticCurveTo() 不准确吗?
问题描述
编辑:我刚刚将控制点更改为交叉点。这就是为什么它不能再适合了。
我知道这是非常冒昧的。但我正在开发一个 Web 应用程序,我需要计算与二次贝塞尔曲线和一条线的交点。
- 线性贝塞尔曲线:
P=s(W-V)+V
- 二次贝塞尔曲线:
P=t²(A-2B+C)+t(-2A+2B)+A
因为W
, V
, A
, B
, 和C
是点,所以我可以做两个等式。我将第一个方程重新排列为单独的 s 来求解方程。我很确定我做对了,但我的路口不在线上。所以我想知道并通过正确的公式制作了我自己的二次贝塞尔曲线,我的交点达到了这条曲线。现在我想知道我做错了什么?
那是我的功能:
intersectsWithLineAtT(lineStartPoint, lineEndPoint)
{
let result = []
let A = this.startPoint, B = this.controlPoint, C = this.endPoint, V = lineStartPoint, W = lineEndPoint
if (!Common.isLineIntersectingLine(A, B, V, W)
&& !Common.isLineIntersectingLine(B, C, V, W)
&& !Common.isLineIntersectingLine(A, C, V, W))
return null
let alpha = Point.add(Point.subtract(A, Point.multiply(B, 2)), C)
let beta = Point.add(Point.multiply(A, -2), Point.multiply(B, 2))
let gamma = A
let delta = V
let epsilon = Point.subtract(W, V)
let a = alpha.x * (epsilon.y / epsilon.x) - alpha.y
let b = beta.x * (epsilon.y / epsilon.x) - beta.y
let c = (gamma.x - delta.x) * (epsilon.y / epsilon.x) - gamma.y + delta.y
let underSquareRoot = b * b - 4 * a * c
if (Common.compareFloats(0, underSquareRoot))
result.push(-b / 2 * a)
else if (underSquareRoot > 0)
{
result.push((-b + Math.sqrt(underSquareRoot)) / (2 * a))
result.push((-b - Math.sqrt(underSquareRoot)) / (2 * a))
}
result = result.filter((t) =>
{
return (t >= 0 && t <= 1)
})
return result.length > 0 ? result : null
}
我希望有一个人可以帮助我。
莉娜
解决方案
曲线/直线相交问题与求根问题相同,在我们旋转所有坐标以使直线最终位于 x 轴顶部之后:
这涉及一个涉及atan2的快速技巧:
const d = W.minus(V);
const angle = -atan2(d.y, d.x);
const rotated = [A,B,C].map(p => p.minus(V).rotate(angle));
假设您正在使用理解矢量操作的点类。{x, y}
如果没有,使用标准对象很容易做到:
const rotated = [A,B,C].map(p => {
p.x -= V.x;
p.y -= V.y;
return {
x: p.x * cos(a) - p.y * sin(a),
y: p.x * sin(a) + p.y * cos(a)
};
});
然后我们只需要找出哪些t
值 yield y=0
,这(正如您也使用过的)只是应用二次公式。而且我们不需要为折叠维度而烦恼:我们已经将问题简化为仅在y
维度中寻找解决方案,因此采取
const a = rotated[0].y;
const b = rotated[1].y;
const c = rotated[2].y;
并将其与我们知道的事实相结合,Py = t²(a-b+c)+t(-2a+2b)+a
我们只是t = -b/2a +/- sqrt(b² - 4ac))/2a
通过通常检查负、零和正判别式以及检查除以零来解决这个问题。
这为我们t
的旋转情况下的 y=0 截距以及未旋转情况下曲线和直线之间的交点提供了零个或多个值。无需额外计算。当然,除了“评估 B(t) 以获得实际的 (x,y) 坐标”。
推荐阅读
- python - 如何使用谷歌 API 每天从 youtube 上抓取 10k 条记录
- javascript - 无法使用节点 js process.kill(pid) 杀死 linux 进程
- macos - kext开发macOS的等待和信号机制
- javascript - 在再次调用之前销毁 javascript 中的函数
- r - 创建子目录并存储文件
- python - 在矩阵 M (m,k) 中找到向量 v (1,k) 的出现
- database - 推荐在使用 Spring Boot 开发时使用 H2 数据库?
- android - 合并 dex 档案时如何解决错误?
- vue.js - Vuejs 获取当前路由名称并显示在菜单上
- scala - 我需要在spark scala中使用rest API在hdfs中存储json文件