[英]Tangent of bezier curve given a point with x and y coords rather than 0 < t < 1
I have a bezier curve and a line which intersects with the bezier curve (the one in the top left).我有一条贝塞尔曲线和一条与贝塞尔曲线相交的线(左上角的那条)。
I am able to find the points at which the line intersects with the curve.我能够找到直线与曲线相交的点。 I would like to find the tangent of the bezier curve at both of those point.
我想在这两个点找到贝塞尔曲线的切线。 I have a function which finds the tangent at a point t on the curve, though this t is a value between 0 and 1, rather than a coordinate.
我有一个 function,它在曲线上的点 t 处找到切线,尽管这个 t 是介于 0 和 1 之间的值,而不是坐标。 It looks like this:
它看起来像这样:
let bezierCurveTangent = function(start: Point, end: Point, controlPoint: Point, t: number): Point {
let x = 2 * (1 - t) * (controlPoint.x - start.x) + 2 * t * (end.x - controlPoint.x);
let y = 2 * (1 - t) * (controlPoint.y - start.y) + 2 * t * (end.y - controlPoint.y);
return { x, y };
}
How do I find the tangent for a point with x and y coordinates rather than a value for t?如何找到具有 x 和 y 坐标而不是 t 值的点的切线?
The formula for a point on a bezier is curve looks like this:贝塞尔曲线上的一个点的公式如下所示:
Can I simply rearrange this equation for t, and then use that value in my function above?我可以简单地重新排列 t 的这个等式,然后在上面的 function 中使用该值吗?
There seems like there would be a better way of achieving this, rather than converting backwards and forwards between the value t and some point.似乎有更好的方法来实现这一点,而不是在值 t 和某个点之间来回转换。
Just search curve-line intersection in terms of t
.只需根据
t
搜索曲线交点。
Having parametric equation of line (through points L0, L1
)具有线的参数方程(通过点
L0, L1
)
L(u) = L0 + (L1-L0)*u = L0 + DL*u
we can write equation system我们可以写方程组
P0x*(1-t)^2+2*(1-t)*t*P1x+t^2*P2x = L0x+u*DLx
P0y*(1-t)^2+2*(1-t)*t*P1y+t^2*P2y = L0y+u*DLy
Express u
from the first equation, substitute it in the second one,从第一个方程中表达
u
,代入第二个方程,
u = (P0x*(1-t)^2+2*(1-t)*t*P1x+t^2*P2x - L0x)/Dlx
substitute it in the second one,将其替换为第二个,
(P0y*(1-t)^2+2*(1-t)*t*P1y+t^2*P2y-L0y)*Dlx=
(P0x*(1-t)^2+2*(1-t)*t*P1x+t^2*P2x-L0x)*DLy
solve resulting quadratic eqiation, get t1
and t2
solutions (if they do exist and lie in 0..1 range)解决由此产生的二次方程,得到
t1
和t2
解决方案(如果它们确实存在并且位于 0..1 范围内)
You could expand and solve the polynomials, but I believe there is a computationally simpler solution.您可以扩展并求解多项式,但我相信有一个计算更简单的解决方案。 Let P 0 =(a 1 ,a 2 ), P 1 =(b 1 ,b 2 ), P 2 =(c 1 ,c 2 ).
令 P 0 =(a 1 ,a 2 ), P 1 =(b 1 ,b 2 ), P 2 =(c 1 ,c 2 )。 Let (x,y) be the point where you want to find the tangent.
让 (x,y) 成为您要找到切线的点。
First I want to move coordinates so that P 1 is the origin: let x=x'+b 1 , y=y'+b 2 .首先,我想移动坐标,使 P 1成为原点:令 x=x'+b 1 , y=y'+b 2 。 Now in the (x',y') coordinates the curve is given by
现在在 (x',y') 坐标中,曲线由下式给出
B(t) = (1-t) 2 P 0 + t 2 P 2
B(t) = (1-t) 2 P 0 + t 2 P 2
After that the coordinates of P 0 and P 2 will be recalculated, I will use prime signs for them as well.之后会重新计算P 0和P 2的坐标,我也会对它们使用素号。
Then I want to rotate and scale the coodinate system in such a way that P 0 and P 2 move to points (0,1) and (1,0).然后我想以 P 0和 P 2移动到点 (0,1) 和 (1,0) 的方式旋转和缩放坐标系。 This can be done by inverting the following matrix:
这可以通过反转以下矩阵来完成:
Note that this always has an inverse if points P 0 , P 1 , P 2 don't lie on one line and it looks like this:请注意,如果点 P 0 、 P 1 、 P 2不在一条线上,则它总是有一个倒数,它看起来像这样:
So the new coordinates (x'',y'') are given by (x',y')=A(x'',y'').因此新坐标 (x'',y'') 由 (x',y')=A(x'',y'') 给出。 In this coordinate system the curve is given by
在这个坐标系中,曲线由下式给出
B(t) = (1-t) 2 e 1 + t 2 e 2
B(t) = (1-t) 2 e 1 + t 2 e 2
Where e 1 =(1,0) and e 2 =(0,1).其中 e 1 =(1,0) 和 e 2 =(0,1)。 This simplifies to
这简化为
x''(t) = (1-t) 2
x''(t) = (1-t) 2
y''(t) = t 2y''(t) = t 2
If you know y'', it is trivial to find t=sqrt(y'').如果您知道 y'',则很容易找到 t=sqrt(y'')。 Note that the square root always exists (if you started with a point that lies on the bezier curve) since we changed coordinates in such a way that the curve lies where x>0 and y>0.
请注意,平方根始终存在(如果您从贝塞尔曲线上的一个点开始),因为我们以曲线位于 x>0 和 y>0 的方式更改坐标。 And it is quite easy to find (x'',y'') knowing (x,y) from the formula (x'',y'')=(x+c 1 , y+c 2 )B.
从公式(x'',y'')=(x+c 1 , y+c 2 )B 知道(x,y) 很容易找到(x'',y'')。 This is what it looks like
这就是它的样子
const getT = (start: Point, end: Point, controlPoint: Point, x: number, y: number) => {
// xp stands for x'
const xp = x - controlPoint.x
const yp = y - controlPoint.y
const a1p = start.x - controlPoint.x
const a2p = start.y - controlPoint.y
const c1p = end.x - controlPoint.x
const c2p = end.y - controlPoint.y
const det = a1p * c2p - a2p * c1p
// This variable is redundant, but I left it for clarity
const xpp = (xp * c2p - yp * c1p) / det
const ypp = (- xp * a2p + yp * a1p) / det
return Math.sqrt(ypp)
}
Or shorter或者更短
const getT = (start: Point, end: Point, controlPoint: Point, x: number, y: number) => Math.sqrt(
(- (x - controlPoint.x) * (start.y - controlPoint.y)
+ (y - controlPoint.y) * (start.x - controlPoint.x)) /
((start.x - controlPoint.x) * (end.y - controlPoint.y) -
(start.y - controlPoint.y) * (end.x - controlPoint.x))
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.