如何通过点制作直线曲线

我正在寻找一种通过多个点制作直线曲线的方法。 最好使用3个点,尽管我认为为了给出进入点的线的角度的上下文,可能需要更多来给出曲线的上下文。

通常,起点P1,控制点P2和终点P3,该线应从P1弯曲到P2,然后从P2到P3弯曲。

事实上,这是我希望实现的效果的完美示例:

Irwin Hall Spline

如果我能做到这一点,我真的会永远感激!

到目前为止,在Java中,我尝试过使用QuadCurve2D.Double , Cub icCurve2D.Double以及Path2D.Double (使用带有Path2D.Double的curveTo)之类的东西,但无济于事 – 绘制的曲线甚至不接近通过指定的控制点。

这是我到目前为止尝试过的方法的图像:

在此处输入图像描述

这是我用来生成图像中的点和曲线的代码:

Graphics2D g = (Graphics2D) window.getGraphics(); g.setColor(Color.blue); int d = 4; // P0 int x0 = window.getWidth()/8; int y0 = 250; g.drawString("P0", x0, y0 + 4*d); g.fillRect(x0, y0, d, d); // P1 int x1 = (window.getWidth()/7)*2; int y1 = 235; g.drawString("P1", x1, y1 + 4*d); g.fillRect(x1, y1, d, d); // P2 int x2 = (window.getWidth()/2); int y2 = 200; g.drawString("P2", x2, y2 - 2*d); g.fillRect(x2, y2, d, d); // P3 int x3 = (window.getWidth()/7)*5; int y3 = 235; g.drawString("P3", x3, y3 + 4*d); g.fillRect(x3, y3, d, d); // P4 int x4 = (window.getWidth()/8)*7; int y4 = 250; g.drawString("P4", x4, y4 + 4*d); g.fillRect(x4, y4, d, d); g.setColor(Color.cyan); QuadCurve2D quadCurve = new QuadCurve2D.Double(x0, y0, x2, y2, x4, y4); g.draw(quadCurve); g.setColor(Color.YELLOW); CubicCurve2D.Double cubicCurve = new CubicCurve2D.Double((double)x0, (double)y0, (double)x1, (double)y1, (double)x2, (double)y2, (double)x4, (double)y4); g.draw(cubicCurve); g.setColor(Color.red); Path2D.Double path1 = new Path2D.Double(); path1.moveTo(x1, y1); path1.curveTo(x0, y0, x2, y2, x4, y4); g.draw(path1); 

我希望曲线穿过点的原因是我想要“平滑”我写过的折线图上的顶点之间的过渡。 在任何人提到它之前, JFree Chart不是一个选择 。 我知道使用了不同类型的曲线和样条曲线但是我没有太多运气来理解它们的确切工作方式或如何实现适合我需要的东西。

如果有任何帮助,我将非常感激 – 提前致谢。

我想你错过了控制点是什么的想法。 控制点通常不在路径本身上。 相反,它们控制路径的曲线在点之间的形状。 有关完整详细信息,请参阅样条线教程 。

现在针对手头的问题,曲线上有点,但没有实际的控制点。 有一些技术,如Cardinal Spline,用于导出控制点,然后传递给您提到的曲线绘制API之一。 您可能需要Path2D.Double选项,以便您可以平滑地将各个曲线串在一起。

因此,从P1到P2到P3,而不是

 Path2D.Double path1 = new Path2D.Double(); path1.moveTo(x1, y1); path1.curveTo(x0, y0, x2, y2, x4, y4); g.draw(path1); 

你要

 Path2D.Double path1 = new Path2D.Double(); path1.moveTo(x1, y1); path1.curveTo(cx1a, cy1a, cx1b, cy1b, x2, y2); path1.curveTo(cx2a, cy2a, cx2b, cy2b, x3, y3); g.draw(path1); 

其中cxcy坐标是您的派生控制点,每个三次样条线段有两个控制点。 可能的话,

 cx1a = x1 + (x2 - x1) / 3; cy1a = y1 + (y2 - y1) / 3; cx1b = x2 - (x3 - x1) / 3; cy1b = y2 - (y3 - y1) / 3; cx2a = x2 + (x3 - x1) / 3; cy2a = y2 + (y3 - y1) / 3; cx2b = x3 - (x3 - x2) / 3; cy2b = y3 - (y3 - y2) / 3; 

这里的模式是对于内部点(在这种情况下仅为P2),其前后的控制点(c1b和c2a)被它之前和之后的点(P1和P3)之间的线的斜率偏移。 对于边缘点,控制点基于该点与下一个最近点之间的斜率。

如果您有特定于域的信息,则可以选择不同的控制点。 例如,您可能希望强制终点处的斜率为0。

好吧也许这可能会有所帮助:P

Catmull-Rom通过示例曲线相同的原理不同的语言… http://schepers.cc/svg/path/dotty.svg

基本上你要问的是Cubic Spline Interpolation ,我能在网上找到这个程序Interp2.java 。 它实际上包括多项式样条和三次样条。

不幸的是它是一个applet,而不是一个真正的类,但你仍然可以通过代码了解它们是如何做到的。 这总是一件好事。