Geometry 三点贝塞尔曲线

Geometry 三点贝塞尔曲线,geometry,drawing,bezier,Geometry,Drawing,Bezier,为了找到解决方案,我读过类似的主题,但没有成功。 我想做的是让这个工具和CorelDraw中的一样,叫做钢笔工具。我通过连接Bezier三次曲线实现了这一点,但仍然缺少一个功能,即拖动曲线而不是控制点以编辑其形状 我可以成功地确定曲线上开始拖动的t参数,但不知道如何重新计算该曲线的控制点 在这里,我想强调一些与CorelDraws PenTool行为有关的东西,这些行为可能被用作Constant。我注意到,当严格垂直或水平拖动曲线时,贝塞尔曲线的控制点会相应地动作,即它们分别在其垂直或水平方向上

为了找到解决方案,我读过类似的主题,但没有成功。 我想做的是让这个工具和CorelDraw中的一样,叫做钢笔工具。我通过连接Bezier三次曲线实现了这一点,但仍然缺少一个功能,即拖动曲线而不是控制点以编辑其形状

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

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


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

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


对不起,我的英语不好

我刚刚查看了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);

在你的例子中,第一个->前面和第二个->后面意味着两个控制点,贝塞尔曲线就是两个多项式:Xt,Yt

三次方:

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

你所要做的一切就是生成标准多项式形式,只需打开括号并将系数相等。这将为控制点提供最终系统

你们假设每个人都知道CorelDraw的行为……我想我已经非常清楚地描述了CorelDraw的PenTool行为,这与问题有关。但是,您可以忽略PenTool属于CorelDraw。只关注上面提到的行为,对我来说还不够清楚。如果贝塞尔曲线是通过其控制点定义的,那么对它的任何操作都应该通过修改控制点来完成。您正在解释另一种拖动,但不清楚您正在拖动什么。曲线是一个方程式,其唯一参数是t和ctrl点。我正在位置t处拖动曲线。我不确定在重新计算控制点位置时鼠标指针是否会停留在曲线上。拖动时,鼠标指针不能飞离曲线。我认为这是正确的。在我的场景中,在偏移的帮助下,您将移动控制点,而不是曲线,并且在使用双重预测的情况下,它将给出卓越的结果。当然,将鼠标指针直接放在cure上是非常困难的,我想你们有1px宽的曲线,在大多数情况下,鼠标不会直接放在cure上,所以一切都会好的-有两个控制点。您的建议可能只适用于t=0.5,但不适用于其他值。对不起,我认为您使用的是二次贝塞尔曲线。如果是立方体,则只能移动最近的控制点或同时移动这两个控制点。在分析coreldraw的行为时,我认为它移动了最近的点。我刚刚检查了它,找不到用户拖动的曲线点位移和最近的控制点之间有效的任何特定比例。非常感谢!我用Java实现了这个过程,它马上就成功了。不确定它是否与CorelDraw中的工作方式相同,但目前看起来非常相似。稍后将测试它的beahviour。再次感谢你的帮助。我不确定你是对的。你看,在三次曲线上,我有P0,P3,t和P点,对应于t。这些数据给了我一系列三次曲线。没有单一的解决方案,除非涉及到一些额外的约束。是的,你是对的。作为一个额外的条件,你可以使用这样的东西。在曲线上取一个额外的点,该点也将被移动。例如,如果在用户点t<0.5,则可以在t1=t/2处取点,并以用户点的一半速度移动。如果t>0.5,则t1=t+0.5*1-t;我已经想到了这一点,但这并不能解决问题,因为必须确定另一个点的确切位置;它的t型位置是不够的。所以,Inkscape提出的解决方案已经足够好了。我试过了。你有四点——够了。四-因为P0,P3,参数为t0的点,用户正在移动,参数为t1的点根据用户的移动,如我所说,假设用户在t=1/5处取了一个点。你是说t1=1/10或t1=3/5的点应该有相同的速度。i、 用户选择的点的一半速度?
B(t) = (1-t)^3*P0 + 3(1-t)^2*t*P1 + 3(1-t)*t^2*P2 + t^3*P3