तीन बिंदुओं से कोण की गणना कैसे करें? [बन्द है]


120

आप यह कहते हैं:

P1 = (x=2, y=50)
P2 = (x=9, y=40)
P3 = (x=5, y=20)

मान लें कि P1एक वृत्त का केंद्र बिंदु है। यह हमेशा एक ही है। मैं वह कोण चाहता हूं जो कि P2और P3, या दूसरे शब्दों में जिस कोण के बगल में बना है P1। आंतरिक कोण सटीक होना। यह हमेशा एक तीव्र कोण होगा, इसलिए -90 डिग्री से कम होगा।

मैंने सोचा: यार, यह सरल ज्यामिति गणित है। लेकिन मैंने अब लगभग 6 घंटे के लिए एक सूत्र की तलाश की है, और केवल जटिल नासा सामान जैसे कि आर्कोस और वेक्टर स्केल उत्पाद उत्पाद के बारे में बात करने वाले लोगों को ढूंढते हैं। मेरा सिर ऐसा लगता है जैसे फ्रिज में है।

कुछ गणित गुरु यहाँ सोचते हैं कि यह एक साधारण समस्या है? मुझे नहीं लगता कि प्रोग्रामिंग भाषा यहां मायने रखती है, लेकिन जो सोचते हैं, उनके लिए यह है: जावा और उद्देश्य-सी। मुझे दोनों की आवश्यकता है, लेकिन इसके लिए इसे टैग नहीं किया है।

जवाबों:


87

यदि आपको लगता है कि P1 को कोसाइन का उपयोग करना है तो कोण को कोण बनाना चाहिए:

ARccOS((पी 12 2 + पी 13 2 - पी 23 2 ) / (2 * पी 12 * पी 13 ))

जहां P 12 , P1 से P2 के सेगमेंट की लंबाई है, जिसकी गणना

sqrt ((P1 x - P2 x ) 2 + (P1 y - P2 y ) 2 )



@ राफा फिरेंज़े कॉस ^ -1 एकोस के लिए एक आम धारणा है, लेकिन एकोस कम अस्पष्ट है। en.wikipedia.org/wiki/Inverse_trigonometric_functions
geon

मैं संपादन छोड़ दूंगा क्योंकि इसमें कुछ भी चोट नहीं लगी है, लेकिन Math / CS / EE की डिग्री, cos ^ -1 निश्चित रूप से सबसे आम अंकन है।
लांस रॉबर्ट्स

1
केवल कुछ मुट्ठी भर भाषाएं 'शक्ति' के लिए एक कैरेट का उपयोग करती हैं, इसलिए यदि आप इसे आर्कोस नहीं कहना चाहते हैं, तो कृपया cos⁻¹ टाइप करें। (यदि आप एक वाणिज्यिक ऑपरेटिंग सिस्टम का उपयोग कर रहे हैं, जो एक्सपट्र्स को टाइप करना मुश्किल बना देता है, तो मुझे उम्मीद है कि आपके द्वारा खरीदे जा सकने वाले कीकैप एप्लिकेशन हो सकते हैं, या हो सकता है कि एक ब्राउज़र प्लग-इन आप इंस्टॉल कर सकते हैं। या आप वेबसर्च और कॉपी और पेस्ट कर सकते हैं।)
माइकल शेपर

1
@MichaelScheper, मैं केवल उन टिप्पणियों में कार्यवाहक का उपयोग कर रहा था जहां html सीमित है। मैं निश्चित रूप से किसी भी वास्तविक उत्तर में उप / सुपरस्क्रिप्ट नोटेशन का उपयोग करूंगा।
लांस रॉबर्ट्स

47

यह बहुत सरल हो जाता है यदि आप इसे दो वैक्टर मानते हैं, एक बिंदु P1 से P2 तक और एक P1 से P3 तक

so:
a = (p1.x - P2.x, p1.y - P2.y)
b = (p1.x - p3.x, p1.y - p3.y)

तब आप डॉट उत्पाद फॉर्मूले को उल्टा कर सकते हैं:
डॉट उत्पाद
कोण प्राप्त करने के लिए:
दो वैक्टर के बीच का कोण

याद रखें कि डॉट उत्पादबस का अर्थ है: a1 * b1 + a2 * b2 (सिर्फ 2 आयाम यहां ...)


1
वेक्टर की आह परिमाण
डैनियल लिटिल

Atan2 समाधान की जाँच करें।
ल्यूक बोइसैय

25

कोण संगणना से निपटने का सबसे अच्छा तरीका यह है atan2(y, x)कि किसी बिंदु x, yको उस बिंदु से कोण लौटाया X+जाए और मूल के संबंध में अक्ष।

यह देखते हुए कि गणना है

double result = atan2(P3.y - P1.y, P3.x - P1.x) -
                atan2(P2.y - P1.y, P2.x - P1.x);

यानी आप मूल रूप से दो बिंदुओं का अनुवाद करते हैं -P1(दूसरे शब्दों में आप सब कुछ अनुवाद करते हैं ताकि P1मूल में समाप्त हो जाए ) और तब आप के पूर्ण कोणों के अंतर पर विचार करते P3हैं P2

इसका लाभ atan2यह है कि पूर्ण सर्कल का प्रतिनिधित्व किया जाता है (आप किसी भी संख्या के बीच -π और the) प्राप्त कर सकते हैं, जहां इसके बजाय acosआपको सही परिणाम की गणना करने के लिए संकेतों के आधार पर कई मामलों को संभालने की आवश्यकता होती है।

के लिए एकमात्र विलक्षण बिंदु atan2है (0, 0)... जिसका अर्थ है कि दोनों P2और P3अलग-अलग होने चाहिए P1क्योंकि उस मामले में कोण के बारे में बात करने का कोई मतलब नहीं है।


आपके उत्तर के लिए धन्यवाद। मुझे इसी की तो तलाश थी। सरल समाधान और आप आसानी से काउंटर क्लॉकवाइज कोण प्राप्त कर सकते हैं यदि मैं सिर्फ 2pi जोड़ता हूं तो मूल्य नकारात्मक है।
मारियो

@marcpt: atan2वास्तव में इस समस्या के लिए क्या आवश्यक है, लेकिन ऐसा लगता है कि ज्यादातर लोगों को इस सवाल का सामना करना पड़ रहा है या समझ नहीं आ रहा है कि क्यों- acosआधारित समाधान खराब नहीं है। मेरे लिए सौभाग्य से मैंने कई साल पहले "किसी ने इंटरनेट पर गलत है" ( xkcd.com/386 ) चरण छोड़ दिया और मैं स्पष्ट बचाव के लिए लड़ाई शुरू नहीं करने जा रहा हूं :-)
6502

इसे इंगित करने के लिए धन्यवाद, लेकिन क्या आप 3D को इस तरह से संभाल सकते हैं?
12

1
@nicoco: तीन आयामों में आप कोण को कैसे परिभाषित करते हैं? अधिक विशेष रूप से कोण नकारात्मक या पीआई (180 डिग्री) से अधिक हो सकता है? 3 डी में दो गैर समानांतर वैक्टर एक विमान को परिभाषित करते हैं, लेकिन विमान को दो तरफ से "देखा" जा सकता है: एक तरफ से देखा गया A, B के "बाएं" और दूसरे से "दाईं ओर" दिखाई देगा। ।
6502

@ 6505 आपके उत्तर के लिए धन्यवाद, मैंने अपनी समस्या सोचने से पहले पोस्ट की। मैं समझ गया कि यह अब बाहर है।
निकोको

19

मुझे जावास्क्रिप्ट में एक उदाहरण दें, मैंने उसके साथ बहुत संघर्ष किया है:

/**
 * Calculates the angle (in radians) between two vectors pointing outward from one center
 *
 * @param p0 first point
 * @param p1 second point
 * @param c center point
 */
function find_angle(p0,p1,c) {
    var p0c = Math.sqrt(Math.pow(c.x-p0.x,2)+
                        Math.pow(c.y-p0.y,2)); // p0->c (b)   
    var p1c = Math.sqrt(Math.pow(c.x-p1.x,2)+
                        Math.pow(c.y-p1.y,2)); // p1->c (a)
    var p0p1 = Math.sqrt(Math.pow(p1.x-p0.x,2)+
                         Math.pow(p1.y-p0.y,2)); // p0->p1 (c)
    return Math.acos((p1c*p1c+p0c*p0c-p0p1*p0p1)/(2*p1c*p0c));
}

बोनस: HTML5- कैनवास के साथ उदाहरण


5
आप इसे कम sqrtऔर चौकोर करके अधिक कुशल बना सकते हैं । यहां मेरा उत्तर देखें (रूबी में लिखा गया है), या इस अपडेटेड डेमो (जावास्क्रिप्ट) में।
मेंढक

आप एक सरल समाधान के लिए atan2 का उपयोग कर सकते हैं।
ल्यूक बोइसैय

15

मूल रूप से आपके पास दो वैक्टर हैं, एक वेक्टर पी 1 से पी 2 और दूसरा पी 1 से पी 3 तक। तो आप सभी की जरूरत है दो वैक्टर के बीच कोण की गणना करने के लिए एक सूत्र है।

एक अच्छी व्याख्या और सूत्र के लिए यहां एक नज़र डालें ।

वैकल्पिक शब्द


12

यदि आप P1 को एक सर्कल के केंद्र के रूप में सोच रहे हैं, तो आप बहुत जटिल सोच रहे हैं। आपके पास एक साधारण त्रिभुज है, इसलिए आपकी समस्या कोज़नेस के नियम से हल हो सकती है । किसी भी ध्रुवीय समन्वय के लिए कोई आवश्यकता नहीं है दूरी P1-P2 = A, P2-P3 = B और P3-P1 = C हैं:

कोण = आर्कोस ((B ^ 2-A ^ 2-C ^ 2) / 2AC)

आपको केवल ए, बी और सी की दूरी की गणना करने की आवश्यकता है। जो आपके बिंदुओं के x- और y- निर्देशांक और पाइथागोरस के प्रमेय से आसानी से उपलब्ध हैं।

लंबाई = sqrt ((X2-X1) ^ 2 + (Y2-Y1) ^ 2)


मैं थोड़ा उलझन में हूँ कि वास्तव में इसे कैसे लागू किया जाए क्योंकि आप P1 इत्यादि को व्यक्तिगत मान के बजाय मान रहे हैं (x, y)
डोमिनिक

@ मुख्य टॉबी: नोटेशन P1-P2 = Aको "ए 1 की गणना करने के लिए, पी 1 से पी 2 को घटाएं" के रूप में नहीं पढ़ा जाना चाहिए, लेकिन "मैं पी 1 से पी 2 की दूरी के रूप में ए को परिभाषित कर रहा हूं", जिसे तब दूसरे समीकरण का उपयोग करके गणना की जा सकती है। मैं बस समीकरणों को अधिक पठनीय बनाने के लिए, दूरियों के लिए एक आशुलिपि को परिभाषित करना चाहता था।
ट्रेब

8

मैं हाल ही में इसी तरह की समस्या में भाग गया, केवल मुझे सकारात्मक और नकारात्मक कोणों के बीच अंतर करने की आवश्यकता थी। मामले में यह किसी के लिए भी है, मैं एंड्रॉइड के लिए एक टच इवेंट में रोटेशन का पता लगाने के बारे में इस मेलिंग सूची से पकड़े गए कोड स्निपेट की सिफारिश करता हूं :

 @Override
 public boolean onTouchEvent(MotionEvent e) {
    float x = e.getX();
    float y = e.getY();
    switch (e.getAction()) {
    case MotionEvent.ACTION_MOVE:
       //find an approximate angle between them.

       float dx = x-cx;
       float dy = y-cy;
       double a=Math.atan2(dy,dx);

       float dpx= mPreviousX-cx;
       float dpy= mPreviousY-cy;
       double b=Math.atan2(dpy, dpx);

       double diff  = a-b;
       this.bearing -= Math.toDegrees(diff);
       this.invalidate();
    }
    mPreviousX = x;
    mPreviousY = y;
    return true;
 }

7

स्पष्टीकरण के साथ बहुत सरल ज्यामितीय समाधान

कुछ दिन पहले, उसी समस्या में पड़ गए और उन्हें गणित की किताब के साथ बैठना पड़ा। मैंने कुछ बुनियादी सूत्रों के संयोजन और सरलीकरण द्वारा समस्या को हल किया।


आइए इस आंकड़े पर विचार करें-

कोण

हम जानना चाहते हैं Θ , इसलिए हम यह पता करना है α और बीटा पहले। अब, किसी भी सीधी रेखा के लिए-

y = m * x + c

आज्ञा देना- ए = (कुल्हाड़ी, एय) , बी = (बीएक्स, बाय) , और ओ = (बैल, ऑय) । तो लाइन OA के लिए -

oy = m1 * ox + c   ⇒ c = oy - m1 * ox   ...(eqn-1)

ay = m1 * ax + c   ⇒ ay = m1 * ax + oy - m1 * ox   [from eqn-1]
                   ⇒ ay = m1 * ax + oy - m1 * ox
                   ⇒ m1 = (ay - oy) / (ax - ox)
                   ⇒ tan α = (ay - oy) / (ax - ox)   [m = slope = tan ϴ]   ...(eqn-2)

उसी तरह, लाइन ओबी के लिए -

tan β = (by - oy) / (bx - ox)   ...(eqn-3)

अब, हमें चाहिए ϴ = β - α। त्रिकोणमिति में हमारे पास एक सूत्र है-

tan (β-α) = (tan β + tan α) / (1 - tan β * tan α)   ...(eqn-4)

tan α(Eqn-2 से) के मान को बदलने के बाद और tan beqn-4 में (eqn-3 से), और हमारे द्वारा प्राप्त सरलीकरण को लागू करते हैं-

tan (β-α) = ( (ax-ox)*(by-oy)+(ay-oy)*(bx-ox) ) / ( (ax-ox)*(bx-ox)-(ay-oy)*(by-oy) )

इसलिए,

ϴ = β-α = tan^(-1) ( ((ax-ox)*(by-oy)+(ay-oy)*(bx-ox)) / ((ax-ox)*(bx-ox)-(ay-oy)*(by-oy)) )

बस इतना ही!


अब, निम्नलिखित आंकड़ा लें-

कोण

यह C # या जावा विधि कोण (की गणना करता है Θ ) -

    private double calculateAngle(double P1X, double P1Y, double P2X, double P2Y,
            double P3X, double P3Y){

        double numerator = P2Y*(P1X-P3X) + P1Y*(P3X-P2X) + P3Y*(P2X-P1X);
        double denominator = (P2X-P1X)*(P1X-P3X) + (P2Y-P1Y)*(P1Y-P3Y);
        double ratio = numerator/denominator;

        double angleRad = Math.Atan(ratio);
        double angleDeg = (angleRad*180)/Math.PI;

        if(angleDeg<0){
            angleDeg = 180+angleDeg;
        }

        return angleDeg;
    }

इस पद्धति का उपयोग एक समभुज त्रिभुज के लिए कैसे किया जा सकता है?
विक्रांत

1
खैर, आपका जवाब अब ठीक काम कर रहा है। सप्ताह पहले मेरे कोड में यह कुछ तर्क था।
विक्रांत

6

ऑब्जेक्टिव-सी में आप ऐसा कर सकते हैं

float xpoint = (((atan2((newPoint.x - oldPoint.x) , (newPoint.y - oldPoint.y)))*180)/M_PI);

या यहाँ और पढ़ें


7
उह, नहीं। तीन बिंदु हैं, केंद्र (0,0) पर नहीं है, और यह एक समकोण त्रिभुज का कोण देता है, न कि शीर्ष का कोण। और कोण के लिए किस तरह का नाम "xpoint" है?
जिम बाल्टर

4

आपने एक हस्ताक्षरित कोण (-90) का उल्लेख किया है। कई अनुप्रयोगों में कोणों के संकेत (सकारात्मक और नकारात्मक हो सकते हैं, http://en.wikipedia.org/wiki/Angle देखें )। यदि अंक हैं (कहते हैं) P2 (1,0), P1 (0,0), P3 (0,1) तो कोण P3-P1-P2 पारंपरिक रूप से सकारात्मक है (PI / 2) जबकि कोण P2-P1- पी 3 नकारात्मक है। पक्षों की लंबाई का उपयोग करना + और - के बीच अंतर नहीं करेगा, इसलिए यदि यह मायने रखता है तो आपको वैक्टर या फ़ंक्शन जैसे कि Math.atan2 (a, b) का उपयोग करने की आवश्यकता होगी।

कोण 2 * PI से आगे भी बढ़ सकते हैं और जबकि यह वर्तमान प्रश्न के लिए प्रासंगिक नहीं है यह पर्याप्त रूप से महत्वपूर्ण था कि मैंने अपना खुद का कोण वर्ग (यह भी सुनिश्चित करने के लिए कि डिग्री और रेडियन मिश्रित नहीं हुआ)। कोण 2 कोण 2 से कम है या नहीं, इस सवाल पर आलोचनात्मक रूप से निर्भर करती है कि कोण कैसे परिभाषित किए जाते हैं। यह तय करना भी महत्वपूर्ण हो सकता है कि क्या एक लाइन (-1,0) (0,0) (1,0) को Math.PI या -Math.PI के रूप में दर्शाया गया है


4

मेरा एंगल डेमो प्रोग्राम

हाल ही में, मुझे भी यही समस्या है ... डेल्फी में यह ऑब्जेक्टिव-सी के समान है।

procedure TForm1.FormPaint(Sender: TObject);
var ARect: TRect;
    AWidth, AHeight: Integer;
    ABasePoint: TPoint;
    AAngle: Extended;
begin
  FCenter := Point(Width div 2, Height div 2);
  AWidth := Width div 4;
  AHeight := Height div 4;
  ABasePoint := Point(FCenter.X+AWidth, FCenter.Y);
  ARect := Rect(Point(FCenter.X - AWidth, FCenter.Y - AHeight),
    Point(FCenter.X + AWidth, FCenter.Y + AHeight));
  AAngle := ArcTan2(ClickPoint.Y-Center.Y, ClickPoint.X-Center.X) * 180 / pi;
  AngleLabel.Caption := Format('Angle is %5.2f', [AAngle]);
  Canvas.Ellipse(ARect);
  Canvas.MoveTo(FCenter.X, FCenter.Y);
  Canvas.LineTo(FClickPoint.X, FClickPoint.Y);
  Canvas.MoveTo(FCenter.X, FCenter.Y);
  Canvas.LineTo(ABasePoint.X, ABasePoint.Y);
end;

2

यहां एक सर्कल पर एक बिंदु के लिए क्षैतिज से कोण (0-360) एंटीक्लॉकवाइज सी # विधि है।

    public static double GetAngle(Point centre, Point point1)
    {
        // Thanks to Dave Hill
        // Turn into a vector (from the origin)
        double x = point1.X - centre.X;
        double y = point1.Y - centre.Y;
        // Dot product u dot v = mag u * mag v * cos theta
        // Therefore theta = cos -1 ((u dot v) / (mag u * mag v))
        // Horizontal v = (1, 0)
        // therefore theta = cos -1 (u.x / mag u)
        // nb, there are 2 possible angles and if u.y is positive then angle is in first quadrant, negative then second quadrant
        double magnitude = Math.Sqrt(x * x + y * y);
        double angle = 0;
        if(magnitude > 0)
            angle = Math.Acos(x / magnitude);

        angle = angle * 180 / Math.PI;
        if (y < 0)
            angle = 360 - angle;

        return angle;
    }

चीयर्स, पॉल


2

function p(x, y) {return {x,y}}

function normaliseToInteriorAngle(angle) {
	if (angle < 0) {
		angle += (2*Math.PI)
	}
	if (angle > Math.PI) {
		angle = 2*Math.PI - angle
	}
	return angle
}

function angle(p1, center, p2) {
	const transformedP1 = p(p1.x - center.x, p1.y - center.y)
	const transformedP2 = p(p2.x - center.x, p2.y - center.y)

	const angleToP1 = Math.atan2(transformedP1.y, transformedP1.x)
	const angleToP2 = Math.atan2(transformedP2.y, transformedP2.x)

	return normaliseToInteriorAngle(angleToP2 - angleToP1)
}

function toDegrees(radians) {
	return 360 * radians / (2 * Math.PI)
}

console.log(toDegrees(angle(p(-10, 0), p(0, 0), p(0, -10))))


0

वहाँ हाई स्कूल गणित का उपयोग कर इस के लिए एक सरल जवाब है ..

मान लीजिए कि आपके 3 अंक हैं

बिंदु A से B तक कोण प्राप्त करने के लिए

angle = atan2(A.x - B.x, B.y - A.y)

बिंदु B से C तक कोण प्राप्त करने के लिए

angle2 = atan2(B.x - C.x, C.y - B.y)

Answer = 180 + angle2 - angle
If (answer < 0){
    return answer + 360
}else{
    return answer
}

मैंने हाल ही में अपने द्वारा बनाए गए प्रोजेक्ट में इस कोड का उपयोग किया है, B को P1 में बदलें .. आप चाहें तो "180 +" भी निकाल सकते हैं।


-1

ठीक है, अन्य उत्तर आवश्यक हर चीज को कवर करते प्रतीत होते हैं, इसलिए मैं इसे जोड़ना चाहूंगा यदि आप JMonkeyEngine का उपयोग कर रहे हैं:

Vector3f.angleBetween(otherVector)

जैसा कि मैं यहाँ देख रहा हूँ :)


-2
      Atan2        output in degrees
       PI/2              +90
         |                | 
         |                |    
   PI ---.--- 0   +180 ---.--- 0       
         |                |
         |                |
       -PI/2             +270

public static double CalculateAngleFromHorizontal(double startX, double startY, double endX, double endY)
{
    var atan = Math.Atan2(endY - startY, endX - startX); // Angle in radians
    var angleDegrees = atan * (180 / Math.PI);  // Angle in degrees (can be +/-)
    if (angleDegrees < 0.0)
    {
        angleDegrees = 360.0 + angleDegrees;
    }
    return angleDegrees;
}

// Angle from point2 to point 3 counter clockwise
public static double CalculateAngle0To360(double centerX, double centerY, double x2, double y2, double x3, double y3)
{
    var angle2 = CalculateAngleFromHorizontal(centerX, centerY, x2, y2);
    var angle3 = CalculateAngleFromHorizontal(centerX, centerY, x3, y3);
    return (360.0 + angle3 - angle2)%360;
}

// Smaller angle from point2 to point 3
public static double CalculateAngle0To180(double centerX, double centerY, double x2, double y2, double x3, double y3)
{
    var angle = CalculateAngle0To360(centerX, centerY, x2, y2, x3, y3);
    if (angle > 180.0)
    {
        angle = 360 - angle;
    }
    return angle;
}

}

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.