在C#中实现这3个类的最佳方法:向量,方向(单位向量),Point

man*_*ock 6 c# struct class

  • 所有点都是向量,所有向量都是点.
  • 所有方向都是向量,并非所有向量都是方向(这不应该意味着不允许双向转换).

我希望所有运算符都被覆盖一次,因为它们完全相同.在C++中我可以定义类Vector {float x,y,z; },并且做typedef Point = Vector,typedef Direction = Vector; 在C#中没有等价物("使用Point = Vector;"很糟糕,因为你必须将它放在你使用的每一个文档中,并且它不是由编译器强制执行的).

我试图定义3个不同的类并覆盖每个类的运算符,然后执行隐式类型转换,这会使代码运行得更慢等等.

我尝试定义只是Vector,然后点:向量和方向:向量,这种方式我只编写一次运算符但我不能做隐式类型转换Point < - > Vector或Direction < - > Vector.

我可以简单地定义Vector类并在任何地方使用它,但这会产生模糊性,因为天气变量应该是空间中的位置(Point),空间中的相对位置(Vector)或单位矢量(Direction).例如功能:

Vector GetOrthogon(Vector a, Vector b) {
    // ....
}
Run Code Online (Sandbox Code Playgroud)

你无法知道它是否期望任何向量或单位向量.在C++中你可以这样做,为什么不在C#?

注意:如果可能的话,使用结构而不是类是理想的.

Nat*_*Nat 11

数学上,点是矢量.太空中没有绝对点.点被定义为来自某个任意来源的向量.所以,我使用矢量来获得点和点之间的差异.

因为方向是单位向量,所以也不需要区分.这就像尝试为整数1和其他整数定义不同的静态类型.所以我使用矢量用于两个方向和点之间的差异.

因此,定义一个Vector类型.它会让你的生活更轻松,因为你会有更少的类和重载的操作符/函数来编写和测试,并且在数学上会更"纯粹"(如果这对你很重要).


Mar*_*ell 8

在一个纯粹的水平,我要说的却是一个VectorPoint一样的,通过代数:

  • Point+ Vector=> Point(翻译)
  • Vector+ Vector=> Vector(另外)
  • Point+ Point(未定义)

我将有2个隐式(它们在逻辑上等价)或显式(否则)转换运算符的不可变结构.我可能不会有一个Direction结构,但是......我可能有一个Direction属性可以将Vector它扩展到单位,但这就是它...


我已经删除了一个原语VectorPoint显示了相互作用; 我没有填写所有Point(因为它更简单):

public struct Point {
    public Point(double x, double y) : this() { X = x; Y = y; }
    public double X { get; private set; }
    public double Y { get; private set; }

    // and more ;-p
}

public struct Vector : IEquatable<Vector> {
    public Vector(double x, double y) : this() { X = x; Y = y; }
    public Vector AsUnit() {
        if (X == 0 && Y == 0) throw new InvalidOperationException();
        if (X == 0) return new Vector(0, X > 0 ? 1 : -1);
        if (Y == 0) return new Vector(Y > 0 ? 1 : -1, 0);
        double sqr = Math.Sqrt((X * X) + (Y * Y));
        return new Vector(X / sqr, Y / sqr);
    }
    public double X { get; private set; }
    public double Y { get; private set; }

    public static  explicit operator Point(Vector vector) {
        return new Point(vector.X, vector.Y);
    }
    public static explicit operator Vector(Point point) {
        return new Vector(point.X, point.Y);
    }
    public override string ToString() {
        return "(" + X.ToString() + "," + Y.ToString() + ")";
    }
    public override int GetHashCode() {
        return 17 * X.GetHashCode() + Y.GetHashCode();
    }
    public override bool Equals(object obj) {
        return obj == null ? false : Equals((Vector)obj);
    }
    public bool Equals(Vector vector) {
        return X == vector.X && Y == vector.Y;
    }
    public static bool operator ==(Vector a, Vector b) {
        return a.X == b.X && a.Y == b.Y;
    }
    public static bool operator !=(Vector a, Vector b) {
        return a.X != b.X || a.Y != b.Y;
    }
    public static Point operator +(Point point, Vector vector) {
        return new Point(point.X + vector.X, point.Y + vector.Y);
    }
    public static Point operator -(Point point, Vector vector) {
        return new Point(point.X - vector.X, point.Y - vector.Y);
    }
    public static Vector operator +(Vector a, Vector b) {
        return new Vector(a.X + b.X, a.Y + b.Y);
    }
    public static Vector operator -(Vector a, Vector b) {
        return new Vector(a.X - b.X, a.Y - b.Y);
    }
}
Run Code Online (Sandbox Code Playgroud)


Dan*_*ton 6

已经有PointVector在.net> = 3.0的实施方式.不幸的是,System.Windows.Media.Media3D因为它们是WPF 3D API的一部分.

这些现有的类确实有一些有用的属性,值得研究(其他人已经提到过):

  • Point [+|-] Vector = Point
  • Vector [+|-] Vector = Vector
  • Point - Point = Vector
  • Vector 有静态方法来执行点和交叉产品
  • Vector.Normalise()vector.Negate()做他们在锡上说的话

也许您可以检查(甚至扩展)这些以供您自己使用?