在 C# 中找到直线与 X 轴的最小角度

find the least angle of a line to X axis in C#

假设我们通过减去两条线的端点来定义两个向量。

V1 = Pa - Pb;
V2 = Pc - Pd;

我们将X轴定义为如下向量。

var V = new System.Windows.Vector(1, 0);

我们如何知道两个向量V1和V2中哪一个与X轴的角度最小

对两者进行归一化并找到 x 绝对值较高的一个。

或者,两个向量 ab 之间的角度是 arccos((a.x*b.x+a.y*b.y)/(a.Length*b.Length))(如果其中一个向量为零,则未定义)

您有两个选择:您可以使用 AngleBetween 函数计算 V1V 以及 V2V 之间的角度:

var angle1 = Vector.AngleBetween(V1,V);
var angle2 = Vector.AngleBetween(V2,V);

if (angle1 < angle2) {
    //V1 is closer to V
}else{
    //V2 is closer to V
}

或者你也可以规范化你的向量,然后比较它们的 y 值:

V1.Normalize();
V2.Normalize();
if(Math.Abs(V1.Y) < Math.Abs(V2.Y)){
    //V1 is closer
}else{
    //V2 is closer
}

我更喜欢第一种方法,因为 Normalize() 函数实际上更改了原始 Vector,因此如果您以后想使用它们,则需要制作一个副本。您也可以使用第一个版本将它们与任何其他向量进行比较 V,而无需调整代码。

编辑:实际上第一个版本只选择与V向量成最小角度的向量,而不是而不是到x轴的向量。因此,如果你想与轴进行比较而不仅仅是向量,你应该使用 V1V2 的副本与绝对 xy 值进行角度计算:

var ref1 = new System.Windows.Vector(Math.Abs(V1.X),Math.Abs(V1.Y));
var ref2 = new System.Windows.Vector(Math.Abs(V2.X),Math.Abs(V2.Y));
var angle1 = Vector.AngleBetween(ref1,V);
var angle2 = Vector.AngleBetween(ref2,V);

if (angle1 < angle2) {
    //V1 is closer to V
}else{
    //V2 is closer to V
}

这样看,归一化方法可能毕竟是更好的选择。 (但一定要在副本上调用Normalize()

   double compare() {
        Point p0 = new Point(0, 0);
        Point p1 = new Point(100, 100);
        Point p2 = new Point(100, -100);
        Vector v0 = new System.Windows.Vector(1, 0);

        var v1 = p1 - p0;
        var v2 = p2 - p0;

        var value1 = Vector.AngleBetween(v0, v1); //value = 45 
        var value2 = Vector.AngleBetween(v0, v2); //value = -45

        value1 = Math.Abs(value1);
        value2 = Math.Abs(value2);

        /* Or if you want to compare the value of the angle
        if (value1 < 0)
            value1 += 360;

        if (value2 < 0)
            value2 += 360;
        */

        return Math.Min(value1,value2);

    }

检查以下解决方案。可以完成您的 query.Add 参考 Windowsbase 项目。非常重要。

using System;
using System.Windows;

namespace Vectors
{

    class Program
    {

        static void Main(string[] args)
        {
            // Define Points
            Point Pa = new Point(5.0,1.0);
            Point Pb = new Point(10.0,3.0);
            Point Pc = new Point(7.0,10.0);
            Point Pd = new Point(1.0,3.0);
            Vector V1 = Pa - Pb;
            Vector V2 = Pc - Pd;

            Vector V = new Vector(1, 0);

            double Phi1 = Math.Atan2(V1.Y, V1.X)*180/Math.PI;
            double Phi2 = Math.Atan2(V2.Y, V2.X)*180/Math.PI;

            // Check for -ve angle and take 180 degree complement.
            Phi1 = (Phi1 >= 0) ? Phi1 : 180 + Phi1;
            Phi2 = (Phi2 >= 0) ? Phi2 : 180 + Phi2;

            if(Phi1<=Phi2)
            {
                Console.WriteLine("Vector V1 has a least angle");
            }
            else
            {
                Console.WriteLine("Vector V2 has a least angle");
            }
            Console.ReadLine();
        }
    }
}