我正在制作一个HTML5画布游戏。
我想绘制两个点之间的S形三次贝塞尔曲线,但我正在寻找一种计算控制点坐标的方法,以使曲线本身的长度始终相同,无论这些点有多近,直到达到曲线变成直线的点。
我想绘制两个点之间的S形三次贝塞尔曲线,但我正在寻找一种计算控制点坐标的方法,以使曲线本身的长度始终相同,无论这些点有多近,直到达到曲线变成直线的点。
b = sqrt(D*sin(C/4)/4 - (D^2)/16)
我还没有检查它是否正确,如果有人得到不同的结果,请留言评论。
编辑:当解方程时,您应该考虑负解,并检查哪个是正确的。
b = -sqrt(D*sin(C/4)/4 - (D^2)/16)
这是一个使用SVG的工作示例,非常接近完美:
http://phrogz.net/svg/constant-length-bezier.xhtml
通过实验我确定当端点重合时,处理柄应该与处理点距离为
desiredLength × cos(30°)
而且(当然),当端点之间最远距离时,处理柄应该重合。所有理想点的绘制看起来像一个椭圆形:
蓝线是实际的理想方程,而上面的红线是近似理想的椭圆形。使用椭圆形的方程(如我上面的示例所示)允许线在中间部分过长约9%。
以下是相关的JavaScript代码:
// M is the MoveTo command in SVG (the first point on the path)
// C is the CurveTo command in SVG:
// C.x is the end point of the path
// C.x1 is the first control point
// C.x2 is the second control point
function makeFixedLengthSCurve(path,length){
var dx = C.x - M.x, dy = C.y - M.y;
var len = Math.sqrt(dx*dx+dy*dy);
var angle = Math.atan2(dy,dx);
if (len >= length){
C.x = M.x + 100 * Math.cos(angle);
C.y = M.y + 100 * Math.sin(angle);
C.x1 = M.x; C.y1 = M.y;
C.x2 = C.x; C.y2 = C.y;
}else{
// Ellipse of major axis length and minor axis length*cos(30°)
var a = length, b = length*Math.cos(30*Math.PI/180);
var handleDistance = Math.sqrt( b*b * ( 1 - len*len / (a*a) ) );
C.x1 = M.x + handleDistance * Math.sin(angle);
C.y1 = M.y - handleDistance * Math.cos(angle);
C.x2 = C.x - handleDistance * Math.sin(angle);
C.y2 = C.y + handleDistance * Math.cos(angle);
}
}