Java 如何在2D中的两个点之间创建一条曲线,并获取每d距离生成该曲线的返回点?
我的数学不好 我有两个点,Java 如何在2D中的两个点之间创建一条曲线,并获取每d距离生成该曲线的返回点?,java,math,2d,java-2d,Java,Math,2d,Java 2d,我的数学不好 我有两个点,A(x1,y1)和B(x2,y2)在2D中 我需要创建一个从点a到B在R(半径)处弯曲的虚拟路径,然后返回一个描述该弯曲路径的点数组,这些点之间可能不是每D(距离)一个点 在Java中,我需要这样一种方法: private ArrayList<PointF> generateCurve(PointF pFrom,PointF pTo,float pRadius,float pMinDistance){ ArrayList<PointF>
A(x1,y1)
和B(x2,y2)
在2D中
我需要创建一个从点a
到B
在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;
}
private ArrayList generateCurve(PointF pFrom、PointF pTo、float pRadius、float pMinDistance){
ArrayList pOutPut=新的ArrayList();
//…生成要输出的结果
回灌;
}
如何做到这一点 这是有效的:
private static double GetAngle(Point2D x, Point2D o, double R){
double cosa = (x.getX()-o.getX())/R;
double sina = (x.getY()-o.getY())/R;
double angle = Math.acos(cosa);
return Math.sin(angle)*sina >= 0 ? angle : 2*Math.PI - angle;
}
private static ArrayList<Point2D> generateCurve(Point2D pFrom,Point2D pTo,float pRadius,float pMinDistance){
ArrayList<Point2D> pOutPut = new ArrayList<Point2D>();
double dist = pFrom.distance(pTo);
double h = Math.sqrt(pRadius * pRadius - (dist * dist / 4.0));
double angleStep = pMinDistance/pRadius;
if(2*pRadius <= dist)
throw new Error("Radius is too small");
//find center
double x1 = pFrom.getX(), x2 = pFrom.getY();
double y1 = pTo.getX(), y2 = pTo.getY();
double m1 = (x1+y1)/2, m2 = (x2+y2)/2;
double u1 = - (y2-x2)/dist, u2 = (y1-x1)/dist;
double o1 = m1 + h * u1, o2 = m2 + h * u2;
Point2D o = new Point2D.Double(o1, o2);
double startAngle = GetAngle(pFrom, o, pRadius);
double endAngle = GetAngle(pTo, o, pRadius);
if(endAngle < startAngle)
endAngle += 2 * Math.PI;
for(double a = startAngle; a < endAngle; a+=angleStep){
pOutPut.add(new Point2D.Double(o1+pRadius*Math.cos(a), o2+pRadius*Math.sin(a)));
}
pOutPut.add(pTo);
return pOutPut;
}
私有静态双GetAngle(点2D x、点2D o、双R){
双cosa=(x.getX()-o.getX())/R;
双新浪=(x.getY()-o.getY())/R;
双角度=数学acos(cosa);
返回Math.sin(角度)*sina>=0?角度:2*Math.PI-角度;
}
专用静态ArrayList generateCurve(点2D pFrom、点2D pTo、浮点pRadius、浮点P状态){
ArrayList pOutPut=新的ArrayList();
双距离=pFrom.距离(pTo);
双h=数学sqrt(pRadius*pRadius-(dist*dist/4.0));
双角度步进=pMinDistance/pRadius;
如果(2*pRadius我没有放弃,我已经为此工作了几个小时。结果如下:
我创建了一个方法,您可以指定是否需要点之间最长弧中的最短弧
下面是对它的一些调用,以及生成的输出:
generateCurve(pFrom, pTo, 100f, 7f, false, false);
正如你所看到的,它就像一个魔咒。下面是代码:
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;
}
}
包装曲线;
导入java.awt.BasicStroke;
导入java.awt.Color;
导入java.awt.Graphics2D;
导入java.awt.RenderingHints;
导入java.awt.geom.Ellipse2D;
导入java.awt.geom.Line2D;
导入java.awt.geom.Rectangle2D;
导入java.awt.image.buffereImage;
导入java.io.File;
导入java.io.IOException;
导入java.util.ArrayList;
导入java.util.List;
导入javax.imageio.imageio;
/**
*
*@作者martijn
*/
公共班机
{
/**
*@param指定命令行参数
*/
公共静态void main(字符串[]args)引发IOException
{
点F pFrom=新点F(-10f,30.0f);
点F pTo=新点F(-100f,0.0f);
列表点=发电机曲线(pFrom、pTo、100f、7f、true、true);
系统输出打印项次(点数);
//计算曲线的边界
Float bounds=new Rectangle2D.Float(points.get(0).x,points.get(0).y,0,0);
对于(int i=1;i0){
Line2D.Float f=新的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.抽签(f);
}
g、 填充(新的椭圆E2D.浮点(points.get(i).x-0.8f,points.get(i).y-0.8f,1.6f,1.6f));
}
g、 setColor(Color.BLUE);
g、 填充(新的椭圆E2D浮动(pFrom.x-1,pFrom.y-1,3,3));
g、 填充(新的椭圆E2D浮子(pTo.x-1、pTo.y-1、3、3));
g、 处置();
write(img,“PNG”,新文件(“result.PNG”);
}
静态类PointF
{
公共浮动x,y;
公共点F(浮点x,浮点y)
{
这个.x=x;
这个。y=y;
}
@凌驾
公共字符串toString()
{
返回“(“+x+”、“+y+”)”;
}
}
私有静态列表generateCurve(PointF pFrom、PointF pTo、float pRadius、float pMinDistance、布尔最短、布尔边)
{
List pOutPut=new ArrayList();
//计算两个给定点的中间。
点F mPoint=新点F(pFrom.x+pTo.x,pFrom.y+pTo.y);
mPoint.x/=2.0f;
mPoint.y/=2.0f;
System.out.println(“介于From和To=“+mPoint”)之间;
//计算两点之间的距离
浮动xDiff=pTo.x-pFrom.x;
浮动yDiff=pTo.y-pFrom.y;
浮点距离=(float)Math.sqrt(xDiff*xDiff+yDiff*yDiff);
System.out.println(“从到之间的距离=”+距离);
如果(pRadius*2.0f<距离){
抛出新的IllegalArgumentException(“半径太小!给定的点不会落在圆上。”);
}
//计算预期曲线的中间。
浮动系数=(浮动)数学sqrt((pRadius*pRadius)/(pTo.x-pFrom.x)*(pTo.x-pFrom.x)+(pTo.y-pFrom.y)*(pTo.y-pFrom.y))-0.25f;
PointF circleMiddlePoint=新的点F(0,0);
如果(侧面){
圆中点x=0.5f*(pFrom.x+pTo.x)+系数*(pTo.y-pFrom.y);
圆中点y=0.5f*(pFrom.y+pTo.y)+系数*(pFrom.x-pTo.x);
}否则{
圆中点x=0.5f*(pFrom.x+pTo.x)-系数*(pTo.y-pFrom.y);
圆中点y=0.5f*(pFrom.y+pTo.y)-系数*(pFrom.x-pTo.x);
}
System.out.println(“Middle=“+circleMiddlePoint”);
//计算两个参考角
浮动角度1=(fl
generateCurve(pFrom, pTo, 100f, 7f, false, 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;
}
}