【问题标题】:How to make a line curve through points如何通过点制作直线曲线
【发布时间】:2013-04-07 16:00:44
【问题描述】:

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

一般一个起点P1,一个控制点P2,一个终点P3,线应该从P1弯到P2,再从P2弯到P3。

其实这里是我想要达到的效果的一个完美例子:

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

到目前为止,在 Java 中,我尝试过使用诸如 QuadCurve2D.DoubleCub icCurve2D.DoublePath2D.Double 之类的东西(将 curveTo 与 Path2D.Double 一起使用)但无济于事 - 绘制的曲线不是甚至接近通过指定的控制点。

这是我迄今为止尝试过的方法的图片:

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

    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 不是一个选项。我知道使用了不同类型的曲线和样条曲线,但我没有多少运气能够准确了解它们的工作原理或如何实现适合我需要的东西。

如果能提供任何帮助,我将不胜感激 - 提前致谢。

【问题讨论】:

  • 让我澄清一下,您是否要求能够通过一组点绘制曲线?
  • 是的,所以考虑一下 Irwin-Hall 样条线上的每个点都是数组中的一个元素。

标签: java awt curves splines


【解决方案1】:

我认为您错过了 控制点 的概念。控制点通常不在路径本身上。相反,它们控制路径曲线在点之间的形状。详情请参阅spline tutorial

现在到了手头的问题,曲线上有点,但没有实际的控制点。有一些技术,如 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。

【讨论】:

  • 很确定 cx1b 和 cy1b 不应该被复制?他们不应该是 cx1a cy1a cx1b cy1b 吗?
  • 感谢@JamesC。现已修复。
  • 如果不是太麻烦,您能否解释一下为什么选择这样的 x 和 y 值来构建控制点?为什么除了最后一对控制点之外的所有控制点都使用 x1,y1?同样在第二对 cx1b 和 cy1b 中,它们似乎取决于曲线接近点之后的点的位置,但在最后一对中,您显然不能采取额外的步骤,因为您正在接近最后一点。所以我假设你可能会使用未来点 x3,y3 来证明曲线接近第二点的角度是合理的,因为它会顺利地继续到未来点?
  • 对。我的答案中添加了有关控制点公式的更多信息。
【解决方案2】:

也许这会有所帮助:P

Catmull-Rom曲线举例原理相同不同语言...http://schepers.cc/svg/path/dotty.svg

【讨论】:

  • Catmull-rom 样条曲线与 Irwin-hall 样条曲线的不同之处在于曲线的绘制方式。查看此资源并画一些要点,blog.ivank.net/interpolation-with-cubic-splines.html
  • 感谢Joban的链接,但是如果您考虑我在您提供的链接上创建的this example,您可以看到曲线(至少在我的情况下)会错误地给人一种存在更大值的印象最后到点之间。与游泳相关的 Catmull-Rom 示例是可以接受的,但实施尚不清楚 - 有什么想法吗?
  • 好的,那么你想要一个 catmull-rom 样条线,嗯,这可能应该更容易一些。
【解决方案3】:

基本上你要求的是三次样条插值,我可以在网上找到这个程序Interp2.java。它实际上包括多项式样条和三次样条。

不幸的是,它是一个小程序而不是一个实际的类,但您仍然可以查看代码以了解它们是如何做到的。这总是一件好事。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-25
    • 1970-01-01
    • 2012-03-31
    • 1970-01-01
    相关资源
    最近更新 更多