java 如何通过点制作直线曲线

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15864441/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 21:06:03  来源:igfitidea点击:

How to make a line curve through points

javaawtcurvessplines

提问by James C

I'm looking for a way to make a line curve through a number of points. It would be preferable to use 3 points although I've considered that in order to give context to the angle of the line entering a point more may be needed to give context to the curve so to speak.

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

In general a start point P1, a control point P2 and an end point P3, the line should curve to P2 from P1 and then curve from P2 to P3.

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

In fact here is a perfect example of the effect I would like to achieve:

事实上,这是我想要达到的效果的完美示例:

Irwin Hall Spline

欧文霍尔样条

If I could do this I really would be eternally grateful!

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

In Java so far, I have tried playing around with things such as QuadCurve2D.Double, Cub icCurve2D.Doubleand also Path2D.Double(using curveTo with Path2D.Double) but to no avail - the curves which are painted aren't even close to passing through the control point specified.

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

Here is an image of the methods I have tried so far :

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

enter image description here

在此处输入图片说明

And here is the code I used to generate the points and curves in the image :

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

    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);

My reasons for wanting a curved line to pass through points is that I want to 'smoothen' the transition between vertices on a line graph I have written. Before anyone mentions it JFree Chart is not an option. I understand there are different types of curves and splines that are used but I've not had much luck in understanding exactly how they work or how to implement something that suits my needs.

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

I would be really grateful for any help offered - Thanks in advance.

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

回答by xan

I think you're missing the idea of what a control pointis. Control points are generally not on the path itself. Instead they control how the curve of the path is shaped between points. See a spline tutorialfor full details.

我认为您缺少控制点的概念。控制点通常不在路径本身上。相反,它们控制点之间路径曲线的形状。有关完整详细信息,请参阅样条教程

Now to the problem at hand, you have points on the curve but no actual control points. There are some techniques, like Cardinal Spline, for deriving control points to then pass to one of the curve drawing APIs you mention. You probably want the Path2D.Doubleoption so you can smoothly string together individual curves.

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

So for drawing from P1 to P2 to P3, instead of

所以对于从 P1 到 P2 到 P3 的绘制,而不是

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

You want

你要

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);

where the cxand cycoordinates are your derived control points, two control points per cubic spline segment. Possibly,

其中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;

The pattern here is that for the interior points (only P2 in this case) the control points before and after it (c1b and c2a) are offset by the slope of the line between the points before and after it (P1 and P3). For the edge points, the control points are based on the slope between that point and the next closest point.

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

If you have domain-specific information you might choose different control points. For instance, you might want to force the slopes at the end points to be 0.

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

回答by swirm

well maybe this could help :P

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

Catmull-Rom curves by example the same principles different lang... http://schepers.cc/svg/path/dotty.svg

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

回答by Joban Dhillon

Basically what you are asking is for is Cubic Spline Interpolation, I was able to find this program online Interp2.java. It actually includes a polynomial spline and cubic spline.

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

Unfortunately its an applet and not an actual class, but you can still look through the code are learn how they did it. Which is always a good thing.

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