迭代平滑曲线
我一整天都在尝试这样做。基本上,我有一条线和一个点。我希望线弯曲并通过该点,但我不想要平滑的曲线。我不希望能够定义曲线中的步数,如下所示(注意粗略的 mspaint 绘图):
等等。我尝试了各种方法,例如从初始线的中心获取角度,然后在角度引导的点处分割线,但我对长度有疑问。我只需将初始长度除以我所处的步数,但这不太正确。
有人知道有办法做到这一点吗?
谢谢。
I've been trying to do this the whole day. Basically, I have a line and a point. I want the line to curve and pass through that point, but I don't want a smooth curve. I wan't to be able to define the number of steps in my curve, like so (beware crude mspaint drawing):
And so on. I tried various things, like taking the angle from the center of the initial line and then splitting the line at the point where the angle leads, but I have a problem with the length. I would just take the initial length and divide it by the number of steps I was at, but that wasn't quite right.
Anyone knows a way to do that?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以采取相反的方法:首先找到一条匹配的曲线,然后使用曲线上的点来绘制线条。例如:
该图是通过以下方式获得的:
假设您有三个起点 {x0,0} ,{x1,y1},{x2,0}
然后您会发现两条抛物线在 {x1,y1} 处相交,附加条件是在该点处具有最大值(为了平滑过渡)。这些曲线是:
我们找到的地方(经过一些微积分):
所以
我们有两条曲线。
现在您应该注意,如果您希望点等距,x1/x2 应该是一个有理数。并且您的步骤选择是有限的。您可以选择从 x0 开始时经过 x1 和 x2 的步骤。 (它们的形式为 x1/(n * x2))
仅此而已。现在,根据点 {x,yLeft[x]} 或 {x,yRight[x]} 形成线条,具体取决于您位于 x1 的哪一侧。
注意:您可以选择仅绘制一条经过三个点的抛物线,但在一般情况下会导致高度不对称。
如果点 x1 位于中间,结果会更好:
You could go the other way around : first find a matching curve and then use the points on the curve to draw the lines. For example:
This plot was obtained in the following way:
Suppose you have the three starting points {x0,0},{x1,y1},{x2,0}
Then you find two parabolic curves intersecting at {x1,y1}, with the additional condition of having a maxima at that point (for a smooth transition). Those curves are:
Where we find (after some calculus):
and
so we have our two curves.
Now you should note that if you want your points equally spaced, x1/x2 should be a rational number.and your choices for steps are limited. You may chose steps passing by x1 AND x2 while starting from x0. (those are of the form x1/(n * x2))
And that's all. Now you form your lines according to the points {x,yLeft[x]} or {x,yRight[x]} depending upon on which side of x1 you are.
Note: You may chose to draw only one parabolic curve that pass by your three points, but it will result highly asymmetrical in the general case.
If the point x1 is in the middle, the results are nicer:
您可能需要自己编写代码。我认为你可以通过在代码中实现二次贝塞尔曲线函数来做到这一点,可以找到该函数 这里。您只需求解几个值即可决定增量的精细程度。如果你想要一条直线,只需求解 0 和 1 并用线连接这些点。如果您想要单角度示例,请求解 0、0.5 和 1,并按顺序连接这些点。如果您想要第三个示例,请求解 0、0.25、0.5、0.75 和 1。最好将其放入 for 循环中,如下所示:
编辑:实际上,看起来您希望该行穿过您的控制点。如果是这种情况,您就不想使用二次贝塞尔曲线。相反,您可能需要拉格朗日曲线。该网站可能有助于解方程:http://www.math。 ucla.edu/~baker/java/hoefer/Lagrange.htm。但无论哪种情况,您都可以使用相同类型的循环来控制平滑程度。
第二次编辑:这似乎有效。只需将 numberOfSteps 成员更改为所需的线段总数,并适当设置点数组即可。顺便说一句,你可以使用三个以上的点。它只会分布它们之间的线段总数。但我初始化了数组,以便结果看起来像你的最后一个例子。
第三次编辑:我对代码进行了一些更新,以便您可以在表单上左键单击以添加点,然后右键单击以删除最后一个点。另外,我在底部添加了 NumericUpDown,以便您可以在运行时更改段数。
You would probably need to code this yourself. I think you could do it by implementing a quadratic bezier curve function in code, which can be found here. You decide how fine you want the increments by only solving for a few values. If you want a straight line, only solve for 0 and 1 and connect those points with lines. If you want the one angle example, solve for 0, 0.5, and 1 and connect the points in order. If you want your third example, solve for 0, 0.25, 0.5, 0.75, and 1. It would probably be best to put it in a for loop like this:
Edit: Actually, it looks like you want the line to pass through your control point. If that is the case, you don't want to use a quadratic bezier curve. Instead, you probably want a Lagrange curve. This website might help with the equation: http://www.math.ucla.edu/~baker/java/hoefer/Lagrange.htm. But in either case, you can use the same type of loop to control the degree of smoothness.
2nd Edit: This seems to work. Just change the numberOfSteps member to be the overall number of line segments you want and set the points array appropriately. By the way, you can use more than three points. It will just distribute the total number of line segments across them. But I initialized the array so that the result looks like your last example.
3rd Edit: I updated the code a bit so you can left click on the form to add points and right click to remove the last point. Also, I added a NumericUpDown to the bottom so you can change the number of segments at runtime.