I want to have the operators overridden once for all preferably since they're all completely identical. In C++ I can just define class Vector { float x,y,z; }, and do typedef Point = Vector, typedef Direction = Vector; In C# there is no equivalent ("using Point=Vector;" sucks as you have to place it in every single document you use, and it's not enforced by the compiler).
I tried to define 3 different classes and override the operators for each, then do implicit type casting which would make the code run slower, etc.
I tried defining just Vector, then Point:Vector and Direction:Vector, this way I only write the operators once but then I can't do implicit type casting Point <-> Vector or Direction <->Vector.
I could simply define the Vector class and use that everywhere, but that would create ambiguity as to weather a variable is supposed to be a position in space (Point), a relative position in space (Vector) or a unit vector (Direction). For example the function:
Vector GetOrthogon(Vector a, Vector b) {
// ....
}
You can't know whether it's expecting any vectors or unit vectors. In C++ you could do that, so why not in C#?
Note: having structs instead of classes would be ideal if possible.
Mathematically, Points are Vectors. There are no absolute points in space. Points are defined as vectors from some arbitrary origin. So, I use Vectors for both points and differences between points.
Because a direction is a unit vector, there's no need for a distinction there either. It's like trying to define different static types for the integer 1 and other integers. So I use vectors for both directions and differences between points.
So, define a single Vector type. It'll make your life easier because you'll have fewer classes and overloaded operators/functions to write and test and will be mathematically "purer" (if that matters to you).
On a purist level, I'd argue that a Vector
and a Point
are not the same, by algebra:
Point
+ Vector
=> Point
(translation)Vector
+ Vector
=> Vector
(addition)Point
+ Point
(not defined)I would have 2 immutable structs with implicit (where they are logically equivalent) or explicit (otherwise) conversion operators. I probably wouldn't have a Direction
struct, though... I might have a Direction
property on a Vector
that scales it to unit, but that is about it...
I've stubbed out a primitive Vector
and Point
to show the interactions; I haven't filled in all of Point
(since it is simpler):
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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With