একটি রেখা এবং অনুভূমিক অক্ষের মধ্যে কোণটি কীভাবে গণনা করব?


247

প্রোগ্রামিং ল্যাঙ্গুয়েজে (পাইথন, সি # ইত্যাদি) আমাকে কীভাবে একটি লাইন এবং অনুভূমিক অক্ষের মধ্যবর্তী কোণটি গণনা করতে হবে তা নির্ধারণ করতে হবে?

আমি মনে করি একটি চিত্র আমার যা চাই তা বর্ণনা করে:

কোনও শব্দই এটি বর্ণনা করতে পারে না

প্রদত্ত (P1 x , P1 y ) এবং (P2 x , P2 y ) এই কোণটি গণনা করার সবচেয়ে ভাল উপায় কী? উত্সটি শীর্ষ বামে রয়েছে এবং কেবলমাত্র ইতিবাচক চতুর্ভুজ ব্যবহৃত হয়।


উত্তর:


386

প্রথমে শুরুর পয়েন্ট এবং শেষ পয়েন্টের মধ্যে পার্থক্যটি সন্ধান করুন (এখানে, এটি একটি নির্দেশিত রেখাংশের বেশি, একটি "লাইন" নয়, যেহেতু লাইনগুলি সীমিতভাবে প্রসারিত হয় এবং কোনও নির্দিষ্ট বিন্দুতে শুরু হয় না)।

deltaY = P2_y - P1_y
deltaX = P2_x - P1_x

তারপরে কোণটি গণনা করুন (যা ইতিবাচক এক্স অক্ষ P1থেকে ধনাত্মক Y অক্ষের দিকে চলে P1)।

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

তবে arctanআদর্শ হতে পারে না, কারণ এইভাবে পার্থক্যগুলিকে ভাগ করে নিলে কোণটি যে চতুর্ভুজটিতে রয়েছে তা আলাদা করার জন্য প্রয়োজনীয় পার্থক্য মুছে ফেলবে (নীচে দেখুন)। পরিবর্তে আপনার ভাষাতে কোনও atan2ফাংশন অন্তর্ভুক্ত থাকলে নিম্নলিখিতটি ব্যবহার করুন :

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

সম্পাদনা (ফেব্রুয়ারি 22, 2017): সাধারণভাবে, atan2(deltaY,deltaX)কেবলমাত্র উপযুক্ত কোণটি পেতে কল করা cosএবং sinতা নিষ্ক্রিয় হতে পারে। এই ক্ষেত্রে, আপনি প্রায়শই পরিবর্তে নিম্নলিখিতগুলি করতে পারেন:

  1. (deltaX, deltaY)ভেক্টর হিসাবে আচরণ করুন ।
  2. সেই ভেক্টরটিকে ইউনিট ভেক্টরে সাধারণ করুন। এটি করার জন্য, দৈর্ঘ্য 0 না হওয়া পর্যন্ত ভাগ deltaXএবং deltaYভেক্টরের দৈর্ঘ্য ( sqrt(deltaX*deltaX+deltaY*deltaY)) দ্বারা বিভক্ত করুন ।
  3. এর পরে, deltaXএখন ভেক্টর এবং অনুভূমিক অক্ষের মধ্যে কোণটির কোসাইন হবে (ধনাত্মক এক্স থেকে ধনাত্মক Y অক্ষের দিকে P1)।
  4. এবং deltaYএখন সেই কোণটির সাইন হবে।
  5. যদি ভেক্টরের দৈর্ঘ্য 0 হয় তবে এর মধ্যে অনুভূমিক অক্ষের মধ্যে একটি কোণ থাকবে না (সুতরাং এটিতে কোনও অর্থবহ সাইন এবং কোসাইন থাকবে না)।

সম্পাদনা (ফেব্রুয়ারি 28, 2017): এমনকি সাধারণ না করেও (deltaX, deltaY):

  • সাইনটি deltaXআপনাকে বলবে যে 3 য় ধাপে বর্ণিত কোসাইন ইতিবাচক বা নেতিবাচক।
  • সাইনটি deltaYআপনাকে জানাবে যে চতুর্থ ধাপে বর্ণিত সাইনটি ইতিবাচক বা নেতিবাচক।
  • এর ধনাত্মক এক্স অক্ষের সাথে সম্পর্কিত কোণের কোণের কোণটি রয়েছে deltaXএবং এর লক্ষণগুলি deltaYআপনাকে জানাবে P1:
    • +deltaX, +deltaY: 0 থেকে 90 ডিগ্রি।
    • -deltaX, +deltaY: 90 থেকে 180 ডিগ্রি।
    • -deltaX, -deltaY: 180 থেকে 270 ডিগ্রি (-180 থেকে -90 ডিগ্রি)।
    • +deltaX, -deltaY: 270 থেকে 360 ডিগ্রি (-90 থেকে 0 ডিগ্রি)।

রেডিয়ান ব্যবহার করে পাইথনে একটি বাস্তবায়ন (আমার উত্তর সম্পাদনা করেছেন এরিক লেসচিনস্কি 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.wikedia.org/wiki/Unit_circ দেখুন


35
যদি আপনি এটি খুঁজে পেয়েছেন এবং আপনি জাভাসক্রিপিটি ব্যবহার করছেন তবে এটি গুরুত্বপূর্ণ যে ম্যাথ.সিন এবং ম্যাথ.কোস রেডিয়েন গ্রহণ করে তাই আপনার ফলাফলকে ডিগ্রিতে রূপান্তর করার দরকার নেই! সুতরাং * 180 / পিআই বিট উপেক্ষা করুন। এটি জানতে আমার 4 ঘন্টা সময় লেগেছে। :)
সিডোনাল্ডসন

উল্লম্ব অক্ষ বরাবর কোণ গণনা করার জন্য কোনটি ব্যবহার করা উচিত?
জেমমুন

3
@akashg: 90 - angleInDegrees ?
jbaums

কেন আমাদের 90 - AngInDegree করা দরকার, এর কোনও কারণ আছে কি? দয়া করে একই ব্যাখ্যা করুন।
প্রবীণ মতনম

2
@ সিডোনাল্ডসন এটি কেবল জাভাস্ক্রিপ্টের চেয়ে বেশি নয়, এটি সি, সি #, সি ++, জাভা ইত্যাদি সত্যই আমি বলতে সাহস করি যে বেশিরভাগ ভাষায় তাদের গণিতের পাঠাগারটি মূলত রেডিয়ানদের সাথে কাজ করে। আমি এখনও এমন একটি ভাষা দেখতে পাই যা ডিফল্টরূপে কেবলমাত্র ডিগ্রি সমর্থন করে।
ফারাপ

50

দুঃখিত, তবে আমি নিশ্চিত যে পিটারের উত্তরটি ভুল। নোট করুন যে y অক্ষটি পৃষ্ঠায় নেমে গেছে (গ্রাফিক্সে সাধারণ)। যেমন বদ্বীপ গণনার বিপরীত হতে হয়, বা আপনি ভুল উত্তর পেতে পারেন।

বিবেচনা:

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) এবং পি 2 হ'ল (2,2) [কারণ পৃষ্ঠার উপরে Y বৃদ্ধি হয়], উপরের কোডটি উদাহরণের জন্য 45.0 ডিগ্রি দেবে, যা ভুল wrong বদ্বীপ গণনার ক্রম পরিবর্তন করুন এবং এটি সঠিকভাবে কাজ করে।


3
আপনার পরামর্শ অনুসারে আমি এটিকে বিপরীত করেছি এবং আমার ঘূর্ণনটি পিছনের দিকে ছিল।
ডেভিলের অ্যাডভোকেট

1
আমার কোডে আমি এটিকে ঠিক করে দিচ্ছি: double arc = Math.atan2(mouse.y - obj.getPy(), mouse.x - obj.getPx()); degrees = Math.toDegrees(arc); if (degrees < 0) degrees += 360; else if (degrees > 360) degrees -= 360;
মার্কাস বেকার ২

এটি আপনার কোণে রয়েছে এমন চক্রের চতুর্থাংশের উপর নির্ভর করে: যদি আপনি প্রথম কোয়ার্টারে (90 ডিগ্রি পর্যন্ত) ডেল্টেক্স এবং ডেল্টাওয়াই (ম্যাথ.অ্যাবস) এর জন্য দ্বিতীয় (90-180) ব্যবহারের জন্য ইতিবাচক মান ব্যবহার করেন একটি ডেল্টাক্সের বিমূর্ত মানকে তিরস্কার করুন, তৃতীয় (180-270) -তে উভয়ই ডেল্টাক্স এবং ডেল্টাওয়াই এবং চতুর্থ (270-360) অবহেলা করুন কেবল ডেল্টাওয়াই - আমার উত্তর নীচে দেখুন
মমশেয়ারে

1

পাইথনে আমি একটি সমাধান পেয়েছি যা ভালভাবে কাজ করছে!

from math import atan2,degrees

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

print GetAngleOfLineBetweenTwoPoints(1,3)

1

সঠিক প্রশ্নটি বিবেচনা করে, আমাদেরকে একটি "বিশেষ" স্থানাঙ্ক সিস্টেমে স্থাপন করা যেখানে ইতিবাচক অক্ষের অর্থ ডাউন ডাউন (একটি স্ক্রিন বা ইন্টারফেস ভিউয়ের মতো) সরানো, আপনাকে এই ফাংশনটি এইভাবে খাপ খাইয়ে নিতে হবে এবং ওয়াই কোঅর্ডিনেটগুলি নেতিবাচক:

সুইফট ২.০-তে উদাহরণ

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

"পিটার ও" রেফারেন্সের ভিত্তিতে .. এখানে জাভা সংস্করণ দেওয়া আছে

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

0

মতলব ফাংশন:

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

0

0 থেকে 2 পিআই পর্যন্ত একটি কোণের সূত্র।

এখানে x = x2-x1 এবং y = y2-y1 রয়েছে formula সূত্রটি কাজ করছে

x এবং y এর যে কোনও মান। X = y = 0 এর জন্য ফলাফল অপরিজ্ঞাত।

চ (X, Y) = PI () - Pi () / 2 * (1 + চিহ্ন (এক্স)) * (1-চিহ্ন (Y ^ 2))

     -pi()/4*(2+sign(x))*sign(y)

     -sign(x*y)*atan((abs(x)-abs(y))/(abs(x)+abs(y)))

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;

আপনার কোডটির কোনও অর্থ নেই: অন্যথায় (270-360) .. কি?
ডাব্লুডিউউ

0
import math
from collections import namedtuple


Point = namedtuple("Point", ["x", "y"])


def get_angle(p1: Point, p2: Point) -> float:
    """Get the angle of this line with the horizontal axis."""
    dx = p2.x - p1.x
    dy = p2.y - p1.y
    theta = math.atan2(dy, dx)
    angle = math.degrees(theta)  # angle is in (-180, 180]
    if angle < 0:
        angle = 360 + angle
    return angle

পরীক্ষামূলক

পরীক্ষার জন্য অনুমানটি পরীক্ষার কেস তৈরি করতে দেয় gene

এখানে চিত্র বর্ণনা লিখুন

import hypothesis.strategies as s
from hypothesis import given


@given(s.floats(min_value=0.0, max_value=360.0))
def test_angle(angle: float):
    epsilon = 0.0001
    x = math.cos(math.radians(angle))
    y = math.sin(math.radians(angle))
    p1 = Point(0, 0)
    p2 = Point(x, y)
    assert abs(get_angle(p1, p2) - angle) < epsilon
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.