2012-07-12 22 views
5

मैं अपने स्पेसशिप के लिए पथ के रूप में बेजियर वक्र का उपयोग कर रहा हूं, जब वे स्टेशन पर डॉक में आ रहे हों।घन बेजियर वक्र: अधिकतम ग्रेडियेंट और टक्कर से बचने का?

public class BezierMovement{ 
    public BezierMovement(){ 
     // start docking straight away in this test version 
     initDocking(); 
    } 

    private Vector3 p0; 
    private Vector3 p1; 
    private Vector3 p2; 
    private Vector3 p3; 

    private double tInc = 0.001d; 
    private double t = tInc; 

    protected void initDocking(){ 

     // get current location 
     Vector3 location = getCurrentLocation(); 

     // get docking point 
     Vector3 dockingPoint = getDockingPoint(); 

     // ship's normalised direction vector 
     Vector3 direction = getDirection(); 

     // docking point's normalised direction vector 
     Vector3 dockingDirection = getDockingDirection(); 

     // scalars to multiply normalised vectors by 
     // The higher the number, the "curvier" the curve 
     float curveFactorShip = 10000.0f; 
     float curveFactorDock = 2000.0f; 

     p0 = new Vector3(location.x,location.y,location.z); 

     p1 = new Vector3(location.x + (direction.x * curveFactorShip), 
         location.y + (direction.y * curveFactorShip), 
         location.z + (direction.z * curveFactorShip)); 

     p2 = new Vector3(dockingPoint.x + (dockingDirection.x * curveFactorDock), 
         dockingPoint.y + (dockingDirection.y * curveFactorDock), 
         dockingPoint.z + (dockingDirection.z * curveFactorDock)); 

     p3 = new Vector3(dockingPoint.x, dockingPoint.y, dockingPoint.z); 


    } 

    public void incrementPosition() { 

     bezier(p0, p1, p2, p3, t, getCurrentLocation()); 

     // make ship go back and forth along curve for testing    
     t += tInc; 

     if(t>=1){ 
      tInc = 0-tInc; 
     } else if(t<0){ 
      tInc = 0-tInc; 
     } 

    } 

    protected void bezier(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, double t, Vector3 outputVector){ 

     double a = (1-t)*(1-t)*(1-t); 
     double b = 3*((1-t)*(1-t))*t; 
     double c = 3*(1-t)*(t*t); 
     double d = t*t*t; 

     outputVector.x = a*p0.x + b*p1.x + c*p2.x + d*p3.x; 
     outputVector.y = a*p0.y + b*p1.y + c*p2.y + d*p3.y; 
     outputVector.z = a*p0.z + b*p1.z + c*p2.z + d*p3.z; 

    } 
} 

वक्र प्रारंभ बिंदु अंतरिक्ष यान स्थान है, और अंत बिंदु डॉकिंग बे के लिए प्रवेश द्वार है (लाल बिंदु: मैं गणना करने के लिए जहां जहाज एक घन बेज़ियर वक्र साथ समय t पर होना चाहिए एक सरल एल्गोरिथ्म है आरेख पर)। स्पेसशिप में इसकी दिशा के लिए एक सामान्यीकृत वेक्टर होता है, और डॉकिंग बे में एक और सामान्यीकृत वेक्टर होता है जिससे जहाज को यात्रा की दिशा को इंगित किया जा सके ताकि इसे आने पर डॉकिंग बे पर सीधे गठबंधन किया जा सके (आरेख पर पीले रंग की रेखाएं)

हरी रेखा स्पेसशिप का एक संभावित मार्ग है, और बैंगनी सर्कल, स्पेसशिप त्रिज्या है। अंत में, काला बॉक्स स्टेशन के लिए बाध्यकारी बॉक्स है।

enter image description here

मैं दो समस्याएं हैं:

  1. अंतरिक्ष यान केवल प्रति सेकंड
  2. अंतरिक्ष यान स्टेशन के माध्यम से उड़ नहीं सकते आर रेडियंस में चालू करने के लिए सक्षम होने के लिए माना जाता है

मुझे लगता है कि यह अनुवाद करता है:

ए)। "वक्र कारक" (नियंत्रण बिंदु लंबाई) ढूँढना जो एक रास्ता देगा जहां जहाज को बहुत कसकर

बी) चालू करना होगा। स्पेसशिप स्थान/दिशा ढूँढना जिससे वह स्टेशन के साथ टकराने से बच नहीं सकता (और उस स्थिति से इसे मार्गदर्शन करने के लिए पथ बना रहा है, इसलिए यह भाग के साथ मिल सकता है))

हालांकि, इनमें से दोनों के साथ , मुझे समाधान खोजने में बहुत भाग्य नहीं मिला है। मेरे पास पहले से ही वैक्टर, बक्से, अंक और गोलाकारों के बीच चौराहे का पता लगाने के लिए कोड है, लेकिन अभी तक बेजियर वक्र नहीं हैं। मेरे पास दो बिंदुओं के बीच दूरी खोजने के लिए भी कार्य हैं।

कोई मदद सबसे की सराहना की होगी

धन्यवाद, जेम्स

उत्तर

3

एक घन बेज़ियर वक्र की सटीक चौराहे ढूंढ़ना शामिल एक 5 वीं या 6 डिग्री बहुपद को सुलझाने। अधिक व्यवहार्य समाधान या तो संख्यात्मक तरीकों का उपयोग कर रहे हैं, या बेजियर वक्र को विभाजित कर रहे हैं।

protected void subdivide(
     Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, 
     Vector3 q0, Vector3 q1, Vector3 q2, Vector3 q3, 
     Vector3 q4, Vector3 q5, Vector3 q6) { 

    q0.x = p0.x; q0.y = p0.y; q0.z = p0.z; 
    q6.x = p3.x; q6.y = p3.y; q6.z = p3.z; 

    q1.x = (p0.x + p1.x) * 0.5; 
    q1.y = (p0.y + p1.y) * 0.5; 
    q1.z = (p0.z + p1.z) * 0.5; 

    q5.x = (p2.x + p3.x) * 0.5; 
    q5.y = (p2.y + p3.y) * 0.5; 
    q5.z = (p2.z + p3.z) * 0.5; 

    double x3 = (p1.x + p2.x) * 0.5; 
    double y3 = (p1.y + p2.y) * 0.5; 
    double z3 = (p1.z + p2.z) * 0.5; 

    q2.x = (q1.x + x3) * 0.5; 
    q2.y = (q1.y + y3) * 0.5; 
    q2.z = (q1.z + z3) * 0.5; 

    q4.x = (x3 + q1.x) * 0.5; 
    q4.y = (y3 + q1.y) * 0.5; 
    q4.z = (z3 + q1.z) * 0.5; 

    q3.x = (q2.x + q4.x) * 0.5; 
    q3.y = (q2.y + q4.y) * 0.5; 
    q3.z = (q2.z + q4.z) * 0.5; 
} 

q1 .. q3 प्रथम खंड हो जाता है। q3 .. q6 दूसरा खंड बन गया।

वक्र को 2-5 बार उप-विभाजित करें, और नियंत्रण-बिंदुओं को पॉलीलाइन के रूप में उपयोग करें।


curvature प्रत्येक खंड के अंत-बिंदुओं पर गणना की जा सकती:

protected double curvatureAtStart(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3) { 
    double dx1 = p1.x - p0.x; 
    double dy1 = p1.y - p0.y; 
    double dz1 = p1.z - p0.z; 

    double A = dx1 * dx1 + dy1 * dy1 + dz1 * dz1; 

    double dx2 = p0.x - 2*p1.x + p2.x; 
    double dy2 = p0.y - 2*p1.y + p2.y; 
    double dz2 = p0.z - 2*p1.z + p2.z; 

    double B = dx1 * dx2 + dy1 * dy2 + dz1 * dz2; 

    double Rx = (dx2 - dx1*B/A)/A*2/3; 
    double Ry = (dy2 - dy1*B/A)/A*2/3; 
    double Rz = (dz2 - dz1*B/A)/A*2/3; 

    return Math.sqrt(Rx * Rx + Ry * Ry + Rz * Rz); 
} 

समस्या 1 का समाधान, वक्र कई बार उप-विभाजन, और कम से वक्रता की गणना करने के प्रत्येक सेगमेंट का एंडपॉइंट। यह केवल एक अनुमान होगा, लेकिन आप उस क्षेत्र में बेहतर अनुमान लगाने के लिए चुनिंदा उच्च वक्रता वाले खंडों को उप-विभाजित कर सकते हैं।


हल करने के लिए समस्या 2, आप तीन घटता का उप-विभाजन कर सकते हैं:

  • वेग शून्य के साथ दोनों अंतिमबिंदुओं में एक (C0)। यह एक सीधी रेखा का उत्पादन करेगा।
  • पहले एंडपॉइंट पर वेग शून्य के साथ, और दूसरे पर एक (C1)।
  • पहला अंतराल पर वेग वाला एक, और दूसरे पर शून्य (C2)।

यदि आप सभी वक्रों को उसी तरह से विभाजित करते हैं, तो आप अंतिम वक्र के नियंत्रण-बिंदुओं का त्वरित मूल्यांकन कर सकते हैं। आप इसी नियंत्रण अंक, अंत बिंदुओं पर वेग से parametrized मिश्रण:

C[i] = C0[i] + (C1[i] - C0[i])*v1 + (C2[i] - C0[i])*v2 

आप इस के साथ वैध पैरामीटर पर्वतमाला मिल सकता है, ताकि कोई खंड (एक सीधी रेखा खंड के रूप में मूल्यांकन) काटती है स्टेशन। (v1 और v2 1.0 से ऊपर जा सकते हैं)।

+0

धन्यवाद! और आपको वापस आने के लिए बहुत लंबा समय लेने के लिए खेद है। मैंने सवाल को सही तरीके से चिह्नित किया, हालांकि अंत में मैं एक अलग विधि के लिए गया, जहां मैं 'साइड प्वाइंट' का उपयोग करता हूं, जो डॉकिंग पॉइंट पर जारी रखने से पहले जहाजों के रास्ते में पहले जाते हैं। –

संबंधित मुद्दे