gpt4 book ai didi

java - 如何在 2D 中的 2 点之间创建一条曲线并返回使该曲线每隔 d 距离的点?

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:51:38 26 4
gpt4 key购买 nike

我数学不好

我有 2 个点,A(x1, y1)B(x2, y2) 二维。

我需要创建一条从点 AB 的虚拟路径,以 R(半径)弯曲,然后返回一个描述这条弯曲路径的点数组,并非所有可能彼此之间的每个 D(距离)。

在 Java 中我需要这样的方法:

private ArrayList<PointF> generateCurve(PointF pFrom,PointF pTo,float pRadius,float pMinDistance){

ArrayList<PointF> pOutPut = new ArrayList<PointF>();
// ...generate result to pOutPut

return pOutPut;
}

如何做到这一点?

最佳答案

我没有放弃,而且我已经为此努力了几个小时。结果如下:

我创建了一个方法,您可以在其中指定是否需要点之间的最长弧中的最短弧。

下面是对它的一些调用,以及生成的输出:

generateCurve(pFrom, pTo, 100f, 7f, false, false);

generateCurve(pFrom, pTo, 100f, 7f, false, false);


generateCurve(pFrom, pTo, 100f, 7f, true, false);

generateCurve(pFrom, pTo, 100f, 7f, true, false);


generateCurve(pFrom, pTo, 100f, 7f, false, true);

generateCurve(pFrom, pTo, 100f, 7f, false, true);


generateCurve(pFrom, pTo, 100f, 7f, true, true);

generateCurve(pFrom, pTo, 100f, 7f, true, true);

如您所见,它运行得非常棒。这是代码:

package curve;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;

/**
*
* @author martijn
*/
public class Main
{

/**
* @param args the command line arguments
*/
public static void main(String[] args) throws IOException
{
PointF pFrom = new PointF(-10f, 30.0f);
PointF pTo = new PointF(-100f, 0.0f);
List<PointF> points = generateCurve(pFrom, pTo, 100f, 7f, true, true);

System.out.println(points);

// Calculate the bounds of the curve
Rectangle2D.Float bounds = new Rectangle2D.Float(points.get(0).x, points.get(0).y, 0, 0);
for (int i = 1; i < points.size(); ++i) {
bounds.add(points.get(i).x, points.get(i).y);
}
bounds.add(pFrom.x, pFrom.y);
bounds.add(pTo.x, pTo.y);

BufferedImage img = new BufferedImage((int) (bounds.width - bounds.x + 50), (int) (bounds.height - bounds.y + 50), BufferedImage.TYPE_4BYTE_ABGR_PRE);
Graphics2D g = img.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

g.translate(25.0f - bounds.getX(), 25.0f - bounds.getY());
g.setStroke(new BasicStroke(1.0f));


g.setColor(Color.DARK_GRAY);
g.drawLine(-1000, 0, 1000, 0);
g.drawLine(0, -1000, 0, 1000);

g.setColor(Color.RED);
for (int i = 0; i < points.size(); ++i) {
if (i > 0) {
Line2D.Float f = new Line2D.Float(points.get(i - 1).x, points.get(i - 1).y, points.get(i).x, points.get(i).y);
System.out.println("Dist : " + f.getP1().distance(f.getP2()));
// g.draw(f);
}

g.fill(new Ellipse2D.Float(points.get(i).x - 0.8f, points.get(i).y - 0.8f, 1.6f, 1.6f));

}
g.setColor(Color.BLUE);
g.fill(new Ellipse2D.Float(pFrom.x - 1, pFrom.y - 1, 3, 3));
g.fill(new Ellipse2D.Float(pTo.x - 1, pTo.y - 1, 3, 3));

g.dispose();

ImageIO.write(img, "PNG", new File("result.png"));
}

static class PointF
{

public float x, y;

public PointF(float x, float y)
{
this.x = x;
this.y = y;
}

@Override
public String toString()
{
return "(" + x + "," + y + ")";
}
}

private static List<PointF> generateCurve(PointF pFrom, PointF pTo, float pRadius, float pMinDistance, boolean shortest, boolean side)
{

List<PointF> pOutPut = new ArrayList<PointF>();

// Calculate the middle of the two given points.
PointF mPoint = new PointF(pFrom.x + pTo.x, pFrom.y + pTo.y);
mPoint.x /= 2.0f;
mPoint.y /= 2.0f;
System.out.println("Middle Between From and To = " + mPoint);


// Calculate the distance between the two points
float xDiff = pTo.x - pFrom.x;
float yDiff = pTo.y - pFrom.y;
float distance = (float) Math.sqrt(xDiff * xDiff + yDiff * yDiff);
System.out.println("Distance between From and To = " + distance);

if (pRadius * 2.0f < distance) {
throw new IllegalArgumentException("The radius is too small! The given points wont fall on the circle.");
}

// Calculate the middle of the expected curve.
float factor = (float) Math.sqrt((pRadius * pRadius) / ((pTo.x - pFrom.x) * (pTo.x - pFrom.x) + (pTo.y - pFrom.y) * (pTo.y - pFrom.y)) - 0.25f);
PointF circleMiddlePoint = new PointF(0, 0);
if (side) {
circleMiddlePoint.x = 0.5f * (pFrom.x + pTo.x) + factor * (pTo.y - pFrom.y);
circleMiddlePoint.y = 0.5f * (pFrom.y + pTo.y) + factor * (pFrom.x - pTo.x);
} else {
circleMiddlePoint.x = 0.5f * (pFrom.x + pTo.x) - factor * (pTo.y - pFrom.y);
circleMiddlePoint.y = 0.5f * (pFrom.y + pTo.y) - factor * (pFrom.x - pTo.x);
}
System.out.println("Middle = " + circleMiddlePoint);

// Calculate the two reference angles
float angle1 = (float) Math.atan2(pFrom.y - circleMiddlePoint.y, pFrom.x - circleMiddlePoint.x);
float angle2 = (float) Math.atan2(pTo.y - circleMiddlePoint.y, pTo.x - circleMiddlePoint.x);

// Calculate the step.
float step = pMinDistance / pRadius;
System.out.println("Step = " + step);

// Swap them if needed
if (angle1 > angle2) {
float temp = angle1;
angle1 = angle2;
angle2 = temp;

}
boolean flipped = false;
if (!shortest) {
if (angle2 - angle1 < Math.PI) {
float temp = angle1;
angle1 = angle2;
angle2 = temp;
angle2 += Math.PI * 2.0f;
flipped = true;
}
}
for (float f = angle1; f < angle2; f += step) {
PointF p = new PointF((float) Math.cos(f) * pRadius + circleMiddlePoint.x, (float) Math.sin(f) * pRadius + circleMiddlePoint.y);
pOutPut.add(p);
}
if (flipped ^ side) {
pOutPut.add(pFrom);
} else {
pOutPut.add(pTo);
}

return pOutPut;
}
}

尽情享受吧!
PS:我创建了两个关于数学的问题来解决你的问题:

关于java - 如何在 2D 中的 2 点之间创建一条曲线并返回使该曲线每隔 d 距离的点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6641977/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com