Add Vector struct
This commit is contained in:
parent
5b734c315d
commit
8c109a741b
190
src/fart/vector.d
Normal file
190
src/fart/vector.d
Normal file
@ -0,0 +1,190 @@
|
||||
module fart.vector;
|
||||
|
||||
import std.math;
|
||||
|
||||
/**
|
||||
* Structure to represent a 3-dimensional vector.
|
||||
*/
|
||||
struct Vector
|
||||
{
|
||||
/** Vector X coordinate. */
|
||||
double x;
|
||||
|
||||
/** Vector Y coordinate. */
|
||||
double y;
|
||||
|
||||
/** Vector Z coordinate. */
|
||||
double z;
|
||||
|
||||
/**
|
||||
* Compute the cross product of two vectors.
|
||||
*/
|
||||
public Vector cross()(auto ref const Vector other) const
|
||||
{
|
||||
return Vector(y * other.z - z * other.y,
|
||||
z * other.x - x * other.z,
|
||||
x * other.y - y * other.x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the dot product of two vectors.
|
||||
*/
|
||||
public double dot()(auto ref const Vector other) const
|
||||
{
|
||||
return x * other.x + y * other.y + z * other.z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the magnitude of the vector.
|
||||
*/
|
||||
public double mag() const
|
||||
{
|
||||
return sqrt(mag2());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the squared magnitude of the vector.
|
||||
*/
|
||||
public double mag2() const
|
||||
{
|
||||
return x * x + y * y + z * z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize the vector to have unit length.
|
||||
*/
|
||||
public ref Vector normalize()
|
||||
{
|
||||
double mag = mag();
|
||||
x /= mag;
|
||||
y /= mag;
|
||||
z /= mag;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a normalized vector in the same direction as this.
|
||||
*/
|
||||
public Vector normalized() const
|
||||
{
|
||||
double mag = mag();
|
||||
return Vector(x / mag, y / mag, z / mag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Project the vector onto a target vector.
|
||||
*/
|
||||
public Vector proj()(auto ref const Vector other) const
|
||||
{
|
||||
Vector on = other.normalized();
|
||||
return on * dot(on);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add two vectors.
|
||||
*/
|
||||
public Vector opBinary(string op : "+")(auto ref const Vector other) const
|
||||
{
|
||||
return Vector(x + other.x, y + other.y, z + other.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add two vectors and assign to self.
|
||||
*/
|
||||
public Vector opOpAssign(string op : "+")(auto ref const Vector other)
|
||||
{
|
||||
x += other.x;
|
||||
y += other.y;
|
||||
z += other.z;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Negate a vector.
|
||||
*/
|
||||
public Vector opUnary(string op : "-")() const
|
||||
{
|
||||
return Vector(-x, -y, -z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtract two vectors.
|
||||
*/
|
||||
public Vector opBinary(string op : "-")(auto ref const Vector other) const
|
||||
{
|
||||
return Vector(x - other.x, y - other.y, z - other.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtract two vectors and assign to self.
|
||||
*/
|
||||
public Vector opOpAssign(string op : "-")(auto ref const Vector other)
|
||||
{
|
||||
x -= other.x;
|
||||
y -= other.y;
|
||||
z -= other.z;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale a vector.
|
||||
*/
|
||||
public Vector opBinary(string op : "*")(double m) const
|
||||
{
|
||||
return Vector(x * m, y * m, z * m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale a vector.
|
||||
*/
|
||||
public Vector opBinaryRight(string op : "*")(double m) const
|
||||
{
|
||||
return Vector(x * m, y * m, z * m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the cross product of two vectors.
|
||||
*/
|
||||
public Vector opBinary(string op : "*")(auto ref const Vector other) const
|
||||
{
|
||||
return cross(other);
|
||||
}
|
||||
|
||||
public static immutable Vector X = Vector(1.0, 0.0, 0.0);
|
||||
public static immutable Vector Y = Vector(0.0, 1.0, 0.0);
|
||||
public static immutable Vector Z = Vector(0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
Vector v = Vector(1, 2, 3);
|
||||
const Vector w = Vector(0, 4, 5);
|
||||
|
||||
Vector v_times_2 = v * 2;
|
||||
assert(v_times_2.x == 2);
|
||||
assert(v_times_2.y == 4);
|
||||
assert(v_times_2.z == 6);
|
||||
|
||||
Vector v_plus_w = v + w;
|
||||
assert(v_plus_w == Vector(1, 6, 8));
|
||||
|
||||
Vector v_minus_w = v - w;
|
||||
assert(v_minus_w == Vector(1, -2, -2));
|
||||
|
||||
assert(v_minus_w.mag2() == 9.0);
|
||||
assert(v_minus_w.mag() == 3.0);
|
||||
|
||||
v += v_minus_w;
|
||||
assert(v == 2 * Vector.X + 0 * Vector.Y + Vector.Z);
|
||||
|
||||
assert(Vector.X * Vector.Y == Vector.Z);
|
||||
assert(Vector.Y * Vector.Z == Vector.X);
|
||||
assert(Vector.Z * Vector.X == Vector.Y);
|
||||
assert(Vector.Y * Vector.X == -Vector.Z);
|
||||
assert(Vector.Z * Vector.Y == -Vector.X);
|
||||
assert(Vector.X * Vector.Z == -Vector.Y);
|
||||
|
||||
assert(w.proj(Vector.X) == Vector(0, 0, 0));
|
||||
assert(w.proj(Vector.Y) == Vector(0, 4, 0));
|
||||
assert(w.proj(Vector.Z) == Vector(0, 0, 5));
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user