Python如何计算一条线和水平轴之间的角度?

问题:

在一种编程语言(Python,C#等)中,我需要确定如何计算一条线和水平轴之间的角度?
我认为一个形象描述了我想要的最好的:
no words can describe this
给定(P1 x,P1 y)和(P2 x,P2 y)计算该角度的最佳方法是什么?起点处于折叠状态,仅使用正象限。

回答:

首先找到起始点和终点之间的区别(这里,这更多是一个有向的线段,而不是一条“线”,因为行可以无限延伸而不是在特定的点开始)。

deltaY = P2_y - P1_y
deltaX = P2_x - P1_x

然后计算从P1处的正X轴到P1处的正Y轴的角度)。

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

但是,arctan可能不是理想的,因为以这种方式划分差异将消除区分哪个象限的角度所需的区别(见下文)。如果您的语言包含atan2功能,请使用以下代码:

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

编辑(2017年2月22日):然而,一般来说,仅仅为了获得cossin的适当角度,调用atan2(deltaY,deltaX)可能是不合适的。在这些情况下,您可以经常执行以下操作:

  1. (deltaX, deltaY)视为向量。
  2. 将该向量归一化为单位向量。要做到这一点,除以deltaXdeltaY的向量的长度(sqrt(deltaX*deltaX+deltaY*deltaY)),除非长度为0。
  3. 之后,deltaX现在将是向量和水平轴之间的角度的余弦(在从正X到正Y轴的方向P1)的方向。
  4. 现在deltaY将是这个角度的正义。
  5. 如果矢量的长度为0,则它​​与水平轴之间不会有一个角度(因此它不会有一个有意义的正弦和余弦)。

编辑(2017年2月28日):即使没有规范化(deltaX, deltaY)

  • deltaX的符号将告诉您步骤3中描述的余弦是正或负。
  • deltaY的符号将告诉您,步骤4中描述的正弦是正还是负。
  • 相对于P1处的正X轴,deltaXdeltaY的符号将告诉您角度在哪个象限:
    • +deltaX, +deltaY: 0 to 90 degrees.
    • -deltaX, +deltaY: 90 to 180 degrees.
    • -deltaX, -deltaY: 180 to 270 degrees (-180 to -90 degrees).
    • +deltaX, -deltaY: 270 to 360 degrees (-90 to 0 degrees).

Python中使用弧度的实现(由Eric Leschinski于2015年7月19日提供,编辑我的答案):

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

翻译整理: codewenda.com
英文原文:stackoverflow

C#中的typeof, GetType和is的用法比较

在C#中,虽然typeof,GetType和is虽然都用于类型的判断,但是各有区别。

typeof关键字

typeof为C#的关键字,typeof的参数为类型名称,返回一个System.Type的对象,它的返回值在编译是确定。

GetType()方法

GetType为C#的Object类提供的方法,GetType方法在运行时返回一个对象的类型。

is关键字

is是C#中的运算符关键字(operator keywords),is表达式返回的是bool类型,表示一个对象是否为某个类型的实例。

比较代码

具体用法的代码如下:

class Animal { } 
class Dog : Animal { }

void PrintTypes(Animal a) { 
    print(a.GetType() == typeof(Animal)) // false 
    print(a is Animal)                   // true 
    print(a.GetType() == typeof(Dog))    // true
}

Dog spot = new Dog(); 
PrintTypes(spot);

is关键字用法补充

class Animal { } 
class Dog : Animal { }

Animal just_a_animal = new Animal();
var check1 just_a_animal is Animal(); // true
var check2 just_a_animal is Dog(); // false

Animal probably_a_dog = new Dog();
var check3 = probably_a_dog is Dog; // true
var check4 = probably_a_dog is Animal; // true

Dog definitely_a_dog = new Dog();
var check5 = definitely_a_dog is Animal; // true
var check6 = definitely_a_dog is Dog; // true