通过三点的贝塞尔曲线

问题描述:

我已阅读过类似主题以找到解决方案,但没有成功。 我想要做的是使工具相同,可以在CorelDraw中找到,名为“钢笔工具”。我通过连接贝塞尔三次曲线来完成,但仍然缺少一个特征,即拖动曲线(而不是控制点)以编辑其形状。通过三点的贝塞尔曲线

我可以成功确定拖动应该开始的曲线上的“t”参数,但不知道如何重新计算该曲线的控制点。

在这里,我想强调一些与CorelDraw的PenTool行为有关的东西,这些行为可以用作为constaints。我注意到,严格垂直或水平拖动曲线时,该贝塞尔曲线的控制点会相应地表现出来,即它们分别在垂直或水平方向上移动。

那么,如何在曲线拖动时重新计算控制点的位置?

+0

您认为每个人都被告知有关CorelDraw的行为... – 2011-01-29 18:41:17

+0

我认为我已经很清楚地描述CorelDraw的与问题相关的PenTool行为。但是,您可以忽略PenTool属于CorelDraw。只关注提到的行为。 – Rasa 2011-01-29 19:00:49

+0

对我来说还不够清楚。如果Bezier是通过控制点定义的,那么对它的任何操作都应该通过修改控制点来完成。你正在解释另一种拖动,但不清楚你在拖动什么。曲线是一个等式,其唯一的参数是t和ctrl点。 – 2011-01-29 19:08:15

我刚看着Inkspace来源,发现这样的代码,可它帮助你:

// Magic Bezier Drag Equations follow! 
// "weight" describes how the influence of the drag should be distributed 
// among the handles; 0 = front handle only, 1 = back handle only. 
double weight, t = _t; 
if (t <= 1.0/6.0) weight = 0; 
else if (t <= 0.5) weight = (pow((6 * t - 1)/2.0, 3))/2; 
else if (t <= 5.0/6.0) weight = (1 - pow((6 * (1-t) - 1)/2.0, 3))/2 + 0.5; 
else weight = 1; 

Geom::Point delta = new_pos - position(); 
Geom::Point offset0 = ((1-weight)/(3*t*(1-t)*(1-t))) * delta; 
Geom::Point offset1 = (weight/(3*t*t*(1-t))) * delta; 

first->front()->move(first->front()->position() + offset0); 
second->back()->move(second->back()->position() + offset1); 

在你的情况下“一线>前()”和“第二 - > back()“将意味着两个控制点

当你点击曲线时,你已经知道当前控制点的位置。因此,您可以计算偏移量X,并将该点从该点偏移到鼠标位置。在鼠标移动的情况下,您可以在X/Y偏移的帮助下重新计算新的控制点。

对不起,我的英语

贝塞尔曲线只不过是两个多项式:X(t), Y(t)

立方之一:

x = ax*t^3 + bx*t^2 + cx*t + dx 
           0 <= t <= 1 
y = ay*t^3 + by*t^2 + cy*t + dy 

所以,如果你有一个曲线 - 你有聚系数。如果你移动你的点并且你知道它是t参数 - 那么你可以简单地重新计算poly的系数 - 它将是一个系数为6的线性方程组(对于每个点)。系统按照两个系统(x和y)进行细分,并且可以精确求解或使用一些数值方法 - 它们也不难。

因此,您现在的任务是在知道曲线的显式方程时计算曲线的控制点。

它也可以带到线性系统。对于广义Bezier曲线我不知道该怎么做,但对于三次曲线或二次曲线并不难。

通过控制点的三次曲线:你所要做的

B(t) = (1-t)^3*P0 + 3(1-t)^2*t*P1 + 3(1-t)*t^2*P2 + t^3*P3 

一切生产标准的多项式形式(只要打开支架)和等同的系数。这将为控制点提供最终的系统!