2011-09-28 19 views
236

एक प्रोग्रामिंग भाषा (पायथन, सी #, आदि) में मुझे यह निर्धारित करने की आवश्यकता है कि रेखा और क्षैतिज धुरी के बीच कोण की गणना कैसे करें?एक रेखा और क्षैतिज धुरी के बीच कोण की गणना कैसे करें?

मुझे लगता है कि एक छवि का सबसे अच्छा वर्णन मैं क्या चाहते हैं:

no words can describe this

को देखते हुए (P1 एक्स, P1 y) और (P2 एक्स, P2 y) क्या है इस कोण की गणना करने का सबसे अच्छा तरीका है? उत्पत्ति टोपी में है और केवल सकारात्मक चतुर्भुज का उपयोग किया जाता है।

उत्तर

376

सबसे पहले प्रारंभ बिंदु और अंत बिंदु के बीच का अंतर पाएं (यहां, यह एक निर्देशित लाइन सेगमेंट है, न कि "लाइन", क्योंकि रेखाएं असीमित रूप से बढ़ती हैं और किसी विशेष बिंदु पर शुरू नहीं होती हैं)।

deltaY = P2_y - P1_y 
deltaX = P2_x - P1_x 

फिर कोण (जो P1 पर सकारात्मक Y अक्ष को P1 पर सकारात्मक एक्स अक्ष से चलाता है) की गणना।

angleInDegrees = arctan(deltaY/deltaX) * 180/PI 

लेकिन arctan, आदर्श नहीं हो सकता है क्योंकि इस तरह के मतभेदों को भेद भेद करने के लिए जो कोण वृत्त का चतुर्थ भाग की जरूरत मिटा देगा में है विभाजित (नीचे देखें)।

angleInDegrees = atan2(deltaY, deltaX) * 180/PI 

संपादित करें (फरवरी 22, 2017): निम्नलिखित बजाय यदि अपनी भाषा एक atan2 समारोह भी शामिल है का उपयोग करें सामान्य में, तथापि, atan2(deltaY,deltaX) बुला सिर्फ cos के लिए उचित कोण पाने के लिए और sin असजीला हो सकता है। उन मामलों में, आप अक्सर निम्नलिखित कार्य कर सकते हैं:

  1. (deltaX, deltaY) एक वेक्टर के रूप में व्यवहार करें।
  2. वेक्टर को एक वेक्टर वेक्टर को सामान्यीकृत करें। जब तक लंबाई 0.
  3. उसके बाद तो, वेक्टर की दूरी (sqrt(deltaX*deltaX+deltaY*deltaY)) द्वारा deltaX और deltaY विभाजित करने के लिए, deltaX अब (वेक्टर और क्षैतिज अक्ष के बीच के कोण की कोज्या हो जाएगा से दिशा में 0 एक्सपर सकारात्मक वाई धुरी के लिए सकारात्मक एक्स)।
  4. और deltaY अब कि कोण की ज्या हो जाएगा।
  5. तो वेक्टर की दूरी 0 है, यह यह और क्षैतिज अक्ष के बीच एक कोण के लिए नहीं होगा (इसलिए यह एक सार्थक साइन और कोसाइन की ज़रूरत नहीं होगी)।

संपादित करें (फरवरी 28, 2017): यहां तक ​​कि (deltaX, deltaY) सामान्य बिना:

  • deltaX के हस्ताक्षर आपको बताएगा कि कोज्या चरण 3 में वर्णित सकारात्मक या नकारात्मक है।
  • deltaY के हस्ताक्षर आपको बताएगा कि ज्या चरण 4 में वर्णित सकारात्मक या नकारात्मक है।
  • deltaX और deltaY के संकेत आपको बता देंगे जो P1 पर वृत्त का चतुर्थ भाग कोण में है सकारात्मक एक्स अक्ष के संबंध में,:
    • +deltaX, +deltaY: 0 से 90 डिग्री कम है।
    • -deltaX, +deltaY: 90 से 180 डिग्री।
    • -deltaX, -deltaY: 180 से 270 डिग्री (-180 से -90 डिग्री)।
    • +deltaX, -deltaY: 270 से 360 डिग्री (-90 से 0 डिग्री)।

(एरिक Leschinski, जो मेरा उत्तर संपादित द्वारा 19 जुलाई, 2015 को प्रदान की गई) रेडियंस का उपयोग कर पायथन में एक कार्यान्वयन:

from math import * 
def angle_trunc(a): 
    while a < 0.0: 
     a += pi * 2 
    return a 

def getAngleBetweenPoints(x_orig, y_orig, x_landmark, y_landmark): 
    deltaY = y_landmark - y_orig 
    deltaX = x_landmark - x_orig 
    return angle_trunc(atan2(deltaY, deltaX)) 

angle = getAngleBetweenPoints(5, 2, 1,4) 
assert angle >= 0, "angle must be >= 0" 
angle = getAngleBetweenPoints(1, 1, 2, 1) 
assert angle == 0, "expecting angle to be 0" 
angle = getAngleBetweenPoints(2, 1, 1, 1) 
assert abs(pi - angle) <= 0.01, "expecting angle to be pi, it is: " + str(angle) 
angle = getAngleBetweenPoints(2, 1, 2, 3) 
assert abs(angle - pi/2) <= 0.01, "expecting angle to be pi/2, it is: " + str(angle) 
angle = getAngleBetweenPoints(2, 1, 2, 0) 
assert abs(angle - (pi+pi/2)) <= 0.01, "expecting angle to be pi+pi/2, it is: " + str(angle) 
angle = getAngleBetweenPoints(1, 1, 2, 2) 
assert abs(angle - (pi/4)) <= 0.01, "expecting angle to be pi/4, it is: " + str(angle) 
angle = getAngleBetweenPoints(-1, -1, -2, -2) 
assert abs(angle - (pi+pi/4)) <= 0.01, "expecting angle to be pi+pi/4, it is: " + str(angle) 
angle = getAngleBetweenPoints(-1, -1, -1, 2) 
assert abs(angle - (pi/2)) <= 0.01, "expecting angle to be pi/2, it is: " + str(angle) 

सभी परीक्षण पास। https://en.wikipedia.org/wiki/Unit_circle

+31

आप इस पाया है और आप जावास्क्रिप्ट का उपयोग कर रहे यह बहुत महत्वपूर्ण है ध्यान दें कि Math.sin और मठ।क्योंकि आप रेडियंस लेते हैं ताकि आपको परिणाम को डिग्री में परिवर्तित करने की आवश्यकता न हो! तो * 180/पीआई बिट को नजरअंदाज करें। मुझे यह पता लगाने में 4 घंटे लग गए। :) – sidonaldson

+0

वर्टिकल धुरी के साथ कोण की गणना करने के लिए किसी को क्या उपयोग करना चाहिए? – ZeMoon

+3

@akashg: '90 - कोण इन डिग्री '? – jbaums

47

क्षमा करें, लेकिन मुझे पूरा यकीन है कि पीटर का जवाब गलत है। ध्यान दें कि वाई अक्ष पृष्ठ (नीचे ग्राफिक्स में आम) नीचे चला जाता है। जैसे डेल्टा गणना को उलट दिया जाना चाहिए, या आपको गलत जवाब मिल गया है।

पर विचार करें:

System.out.println (Math.toDegrees(Math.atan2(1,1))); 
System.out.println (Math.toDegrees(Math.atan2(-1,1))); 
System.out.println (Math.toDegrees(Math.atan2(1,-1))); 
System.out.println (Math.toDegrees(Math.atan2(-1,-1))); 

देता

45.0 
-45.0 
135.0 
-135.0 

तो अगर ऊपर के उदाहरण में, पी 1 (1,1) और P2 (2,2) है [क्योंकि वाई पेज नीचे बढ़ जाती है ], उपरोक्त कोड दिखाए गए उदाहरण के लिए 45.0 डिग्री देगा, जो गलत है। डेल्टा गणना का क्रम बदलें और यह ठीक से काम करता है।

+3

स्विच करने की आवश्यकता है, जैसा कि आपने सुझाव दिया था और मेरा घूर्णन पिछड़ा था। –

+8

अच्छा होगा यदि आप सही तरीके से प्रदर्शित कर सकते हैं। –

+1

मेरे कोड में मैं इसे ठीक कर रहा हूं: 'डबल आर्क = Math.atan2 (mouse.y - obj.getPy(), mouse.x - obj.getPx()); \t \t डिग्री = Math.toDegrees (आर्क); \t \t यदि (डिग्री <0) \t \t डिग्री + = 360; \t \t अन्यथा (डिग्री> 360) \t \t \t डिग्री - = 360; ' –

1

मुझे पाइथन में एक समाधान मिला है जो अच्छी तरह से काम कर रहा है!

from math import atan2,degrees 

def GetAngleOfLineBetweenTwoPoints(p1, p2): 
    return degrees(atan2(p2 - p1, 1)) 

print GetAngleOfLineBetweenTwoPoints(1,3) 
0

संदर्भ "पीटर ओ" .. यहाँ के आधार पर, जावा संस्करण

private static final float angleBetweenPoints(PointF a, PointF b) { 
float deltaY = b.y - a.y; 
float deltaX = b.x - a.x; 
return (float) (Math.atan2(deltaY, deltaX)); } 
1

सही प्रश्न का विचार कर रहा है एक "विशेष" में डाल जहां सकारात्मक अक्ष नीचे जा मतलब है प्रणाली का समन्वय करता है (जैसे एक स्क्रीन या एक अंतरफलक दृश्य), तो आप इस तरह इस समारोह अनुकूलित करने की आवश्यकता है, और नकारात्मक वाई निर्देशांक:

उदाहरण स्विफ्ट 2.0 में

func angle_between_two_points(pa:CGPoint,pb:CGPoint)->Double{ 
    let deltaY:Double = (Double(-pb.y) - Double(-pa.y)) 
    let deltaX:Double = (Double(pb.x) - Double(pa.x)) 
    var a = atan2(deltaY,deltaX) 
    while a < 0.0 { 
     a = a + M_PI*2 
    } 
    return a 
} 

यह फ़ंक्शन प्रश्न का सही उत्तर देता है। उत्तर रेडियंस में है, इसलिए उपयोग, डिग्री में कोण देखने पर, यह है:

let p1 = CGPoint(x: 1.5, y: 2) //estimated coords of p1 in question 
let p2 = CGPoint(x: 2, y : 3) //estimated coords of p2 in question 

print(angle_between_two_points(p1, pb: p2)/(M_PI/180)) 
//returns 296.56 
0
deltaY = Math.Abs(P2.y - P1.y); 
deltaX = Math.Abs(P2.x - P1.x); 

angleInDegrees = Math.atan2(deltaY, deltaX) * 180/PI 

if(p2.y > p1.y) // Second point is lower than first, angle goes down (180-360) 
{ 
    if(p2.x < p1.x)//Second point is to the left of first (180-270) 
    angleInDegrees += 180; 
    else (270-360) 
    angleInDegrees += 270; 
} 
else if (p2.x < p1.x) //Second point is top left of first (90-180) 
    angleInDegrees += 90; 
0

matlab समारोह:

function [lineAngle] = getLineAngle(x1, y1, x2, y2) 
    deltaY = y2 - y1; 
    deltaX = x2 - x1; 

    lineAngle = rad2deg(atan2(deltaY, deltaX)); 

    if deltaY < 0 
     lineAngle = lineAngle + 360; 
    end 
end 
संबंधित मुद्दे