Math 画一个二次Bé;通过三个给定点的zier曲线

Math 画一个二次Bé;通过三个给定点的zier曲线,math,bezier,curve,quadratic,Math,Bezier,Curve,Quadratic,我在2D中有三个点,我想画一条通过它们的二次Bézier曲线。我如何计算中间控制点(x1和y1如quadTo)?我从大学就知道线性代数,但在这方面需要一些简单的帮助 如何计算中间控制点,使曲线也通过它?让P0、P1、P2为控制点,Pc为您希望曲线通过的固定点 然后,贝塞尔曲线由以下公式定义: P(t) = P0*t^2 + P1*2*t*(1-t) + P2*(1-t)^2 …其中t从0到1 你的问题有无限多的答案,因为它可能会通过你的任何价值的t点。。。所以只需选择一个,比如t=0.5,然后

我在2D中有三个点,我想画一条通过它们的二次Bézier曲线。我如何计算中间控制点(
x1
y1
如quadTo)?我从大学就知道线性代数,但在这方面需要一些简单的帮助


如何计算中间控制点,使曲线也通过它?

让P0、P1、P2为控制点,Pc为您希望曲线通过的固定点

然后,贝塞尔曲线由以下公式定义:

P(t) = P0*t^2 + P1*2*t*(1-t) + P2*(1-t)^2
…其中t从0到1

你的问题有无限多的答案,因为它可能会通过你的任何价值的t点。。。所以只需选择一个,比如t=0.5,然后求解P1:

Pc = P0*.25 + P1*2*.25 + P2*.25

P1 = (Pc - P0*.25 - P2*.25)/.5

   = 2*Pc - P0/2 - P2/2
这里的“p”值是(x,y)对,因此只需对x应用一次方程式,对y应用一次方程式:

x1 = 2*xc - x0/2 - x2/2
y1 = 2*yc - y0/2 - y2/2

…其中(xc,yc)是您希望它通过的点,(x0,y0)是起点,(x2,y2)是终点。这将为您提供一个在t=0.5时通过(xc,yc)的贝塞尔曲线。

如果您不想要精确的中点,而是想要t(0到1)的任何值,则公式为:

controlX = pointToPassThroughX/t - startX*t - endX*t;
controlY = pointToPassThroughY/t - startY*t - endY*t;

当然,这也适用于中点,只需将t设置为0.5。简单!:-)

我在JavaFX应用程序中使用了Nemos answer,但我的目标是绘制曲线,以便曲线的可视转折点始终与choosen fixed one(CP)相匹配

CP=控制点
SP=起始点
EP=终点
BP(t)=贝西曲线上的可变点,其中t介于0和1之间

为了实现这一点,我制作了一个变量t(不是fix 0.5)。如果扼流点CP不再位于SP和EP之间,则必须改变T或向下一点点。 作为第一步,您需要知道CP是否更接近SP或EP: 设distanceSP为CP和SP之间的距离 和DistanceP CP和EP之间的距离 然后我将比率定义为:

ratio = (distanceSP - distanceEP) / (distanceSP + distanceEP);
现在我们要用它来上下改变t:

ratio = 0.5 - (1/3) * ratio;
注意:这仍然是一个近似值,1/3由try-and-error选择

以下是我的Java函数: (Point2D是JavaFX的一个类)


我希望这能有所帮助。

让我们想要的四次贝塞尔函数为p(t)=P1t^2+PC2t(1-t)+P2*(1-t)^2 那四个贝塞尔传球,投P1,Pt,P2

通过三个点P1、Pt、P3的最佳四次bezier具有控制点PC,张力指向曲线切线的垂直方向。这一点也是贝塞尔曲线的平分线。从P1开始到P3结束的任何贝塞尔曲线,PC位于通过throw PC和Pt的直线上,以相同的参数t值切割四个贝塞尔曲线

PC点不是通过bezier的参数位置t=.5实现的。一般来说,对于任何P1,Pt,P2,我们得到了一个Pc,如下一个公式所述

生成的PC也是bezier到Pt的近点,通过Pt和PC的直线是三角形P1,Pt,PC的平分线

这是一篇文章,其中描述了teorem和公式——在我的网站上

这里还有代码

(函数(){
变量画布,ctx,点,样式,拖动=null,dPoint;
//定义初始点
函数Init(){
点={
p1:{x:200,y:350},
p2:{x:600,y:350}
};
point.cp1={x:500,y:200};
//默认样式
样式={
曲线:{宽度:2,颜色:{333},
cpline:{宽度:1,颜色:#C00},
曲线1:{宽度:1,颜色:#2f94e2},
曲线2:{宽度:1,颜色:#2f94e2},
点:{半径:10,宽度:2,颜色:#2f94e2,填充:“rgba(200200,0.5)”,arc1:0,arc2:2*Math.PI}
}
//线条样式默认值
ctx.lineCap=“圆形”;
ctx.lineJoin=“圆形”;
//事件处理程序
canvas.onmousedown=DragStart;
canvas.onmousemove=拖动;
canvas.onmouseup=canvas.onmouseout=DragEnd;
画布();
}
//画画布
函数DrawCanvas(){
clearRect(0,0,canvas.width,canvas.height);
//控制线
ctx.lineWidth=style.cpline.width;
ctx.strokeStyle=style.cpline.color;
ctx.beginPath();
ctx.moveTo(点p1.x,点p1.y);
ctx.lineTo(点cp1.x,点cp1.y);
ctx.lineTo(点p2.x,点p2.y);
ctx.stroke();
//曲线
ctx.lineWidth=style.curve.width;
ctx.strokeStyle=style.curve.color;
ctx.beginPath();
ctx.moveTo(点p1.x,点p1.y);
通过=!document.getElementById(“cbThrough”)。已选中;
如果(通过)
{
tmpx1=点p1.x-点cp1.x;
tmpx2=点p2.x-point.cp1.x;
tmpy1=点p1.y-point.cp1.y;
tmpy2=点p2.y-point.cp1.y;
dist1=Math.sqrt(tmpx1*tmpx1+tmpy1*tmpy1);
dist2=Math.sqrt(tmpx2*tmpx2+tmpy2*tmpy2);
tmpx=point.cp1.x-Math.sqrt(dist1*dist2)*(tmpx1/dist1+tmpx2/dist2)/2;
tmpy=point.cp1.y-Math.sqrt(dist1*dist2)*(tmpy1/dist1+tmpy2/dist2)/2;
ctx.二次曲线(tmpx,tmpy,点p2.x,点p2.y);
}
其他的
{
ctx.二次曲线(点cp1.x,点cp1.y,点p2.x,点p2.y);
}
ctx.stroke();
//新的,t范围是[0,1]
ctx.beginPath();
ctx.lineWidth=style.curve1.width;
ctx.strokeStyle=style.curve1.color;
ctx.moveTo(点p1.x,点p1.y);
//控制点
对于(var p in point){
ctx.lineWidth=style.point.width;
ctx.strokeStyle=style.point.color;
ctx.fillStyle=style.point.fill;
ctx.beginPath();
ctx.arc(点[p].x,点[p].y,style.point.radius,style.point.arc1,sty
private Point2D adjustControlPoint(Point2D start, Point2D end, Point2D visualControlPoint) {
    // CP = ControlPoint, SP = StartPoint, EP = EndPoint, BP(t) = variable Point on BeziérCurve where t is between 0 and 1
    // BP(t) = SP*t^2 + CP*2*t*(1-t) + EP*(1-t)^2
    // CP = (BP(t) - SP*t^2 - EP*(1-t)^2) / ( 2*t*(1-t) )
    // but we are missing t the goal is to approximate t
    double distanceStart  = visualControlPoint.distance(start);
    double distanceEnd    = visualControlPoint.distance(end);
    double ratio          = (distanceStart - distanceEnd) / (distanceStart + distanceEnd);
    // now approximate ratio to be t
    ratio = 0.5 - (1.0 / 3) * ratio;

    double ratioInv = 1 - ratio;
    Point2D term2 = start.multiply( ratio * ratio );
    Point2D term3 = end.multiply( ratioInv * ratioInv );
    double  term4 = 2 * ratio * ratioInv;

    return visualControlPoint.subtract(term2).subtract(term3).multiply( 1 / term4);
}