我的数学不好.
我在2D中有2个点,A(x1,y1)和B(x2,y2).
我需要创建一个从R点(半径)弯曲的A点到B点的虚拟路径,然后返回一个描述这个弯曲路径的点数组,而不是每个D(距离)彼此之间的距离.
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,true,true);
generateCurve(pFrom,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,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); 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,1000,0); g.drawLine(0,-1000,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)); 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,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:我创建了两个关于数学的问题来解决你的问题:
> Analytic Geometry: Point coordinates,same distance from two points.
> Trigonometry: Solve (1−cosα)2+sin2α=d2 for α