2011-07-10 19 views
6

मैं गणित में अच्छा नहीं हूँ।2 डी में 2 अंक के बीच वक्र कैसे बनाएं और उन बिंदुओं को वापस प्राप्त करें जो उस वक्र को हर डी दूरी बनाता है?

मेरे पास 2 अंक, A(x1, y1) और B(x2, y2) 2 डी में 2 अंक हैं।

मैं B आर (त्रिज्या) पर घुमावदार इंगित A से वर्चुअल पथ बनाते हैं और फिर अंक हैं जो एक दूसरे से इस घुमावदार मार्ग, सभी शायद नहीं हर डी (दूरी) का वर्णन कर रहे हैं की एक सरणी वापस जाने के लिए की जरूरत है।

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

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

    return pOutPut; 
} 

यह कैसे करना है:

जावा में मैं इस तरह एक विधि की आवश्यकता है?

+0

आप थोड़ा बेहतर है कि तुम क्या दूरी के साथ हासिल करना चाहते हैं समझाने की कोशिश कर सकते हैं? परिणामी बिंदुओं के बीच की दूरी? –

+0

हां, कुछ मामलों में परिणाम 1000 से अधिक अंक हो सकता है लेकिन यह बहुत अधिक है, इसलिए प्रत्येक बिंदु पर नहीं बल्कि अंक जो कि एक दूसरे से 10px हैं। –

+0

ठीक है, और आप किस तरह का वक्र चाहते हैं? –

उत्तर

8

मैं छोड़ दिया नहीं किया था और मैं इस पर काम कर रहा है कुछ और घंटों के लिए। और यहां परिणाम है:

मैंने एक विधि बनाई है जहां आप निर्दिष्ट कर सकते हैं यदि आप अंक के बीच सबसे लंबी चाप का सबसे छोटा चाहते हैं।

यहाँ का उत्पादन उत्पादन के साथ, यह करने के लिए कुछ कॉल कर रहे हैं:

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

आनंद लें!
पुनश्च: मैं आपके सवाल का हल करने के लिए गणित पर दो सवाल पैदा की:

+0

जॉर्जस, बहुत बहुत धन्यवाद! –

+0

आपका स्वागत है! –

+0

बहुत प्रभावशाली! – Fattie

4

यह काम करता है:

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

यहाँ मैं क्या मिलता है जब मैं इसे इस तरह कहते हैं: generateCurve(new Point2D.Double(10,10), new Point2D.Double(400, 400), 300, 15)

enter image description here

+0

के लिए धन्यवाद, ए (10,10), बी (400,400), आर = 150 के लिए यह केवल एक बिंदु (10,10) –

+1

देता है। यदि त्रिज्या 150 है तो सर्कल का व्यास 300 है, लेकिन आपके द्वारा दिए गए बिंदुओं के बीच की दूरी (10,10) और (400,400)> 300 है। –

+0

लॉल, आप सही हैं, धन्यवाद! –