|
@@ -1,6 +1,6 @@
|
|
|
namespace PixiEditor.Numerics;
|
|
|
|
|
|
-public struct VecD : IEquatable<VecD>
|
|
|
+public struct VecD : IEquatable<VecD>, IComparable<VecD>
|
|
|
{
|
|
|
public double X { set; get; }
|
|
|
public double Y { set; get; }
|
|
@@ -19,27 +19,33 @@ public struct VecD : IEquatable<VecD>
|
|
|
X = x;
|
|
|
Y = y;
|
|
|
}
|
|
|
+
|
|
|
public VecD(double bothAxesValue)
|
|
|
{
|
|
|
X = bothAxesValue;
|
|
|
Y = bothAxesValue;
|
|
|
}
|
|
|
+
|
|
|
public static VecD FromAngleAndLength(double angle, double length)
|
|
|
{
|
|
|
return new VecD(Math.Cos(angle) * length, Math.Sin(angle) * length);
|
|
|
}
|
|
|
+
|
|
|
public VecD Round()
|
|
|
{
|
|
|
return new(Math.Round(X), Math.Round(Y));
|
|
|
}
|
|
|
+
|
|
|
public VecD Ceiling()
|
|
|
{
|
|
|
return new(Math.Ceiling(X), Math.Ceiling(Y));
|
|
|
}
|
|
|
+
|
|
|
public VecD Floor()
|
|
|
{
|
|
|
return new(Math.Floor(X), Math.Floor(Y));
|
|
|
}
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Rotates the vector by the specified angle in radians
|
|
|
/// </summary>
|
|
@@ -52,10 +58,12 @@ public struct VecD : IEquatable<VecD>
|
|
|
result.Y = X * Math.Sin(angleRad) + Y * Math.Cos(angleRad);
|
|
|
return result;
|
|
|
}
|
|
|
+
|
|
|
public VecD Rotate(double angleRad, VecD around)
|
|
|
{
|
|
|
return (this - around).Rotate(angleRad) + around;
|
|
|
}
|
|
|
+
|
|
|
public double DistanceToLineSegment(VecD pos1, VecD pos2)
|
|
|
{
|
|
|
VecD segment = pos2 - pos1;
|
|
@@ -65,6 +73,7 @@ public struct VecD : IEquatable<VecD>
|
|
|
return (this - pos2).Length;
|
|
|
return DistanceToLine(pos1, pos2);
|
|
|
}
|
|
|
+
|
|
|
public double DistanceToLine(VecD pos1, VecD pos2)
|
|
|
{
|
|
|
double a = (pos1 - pos2).Length;
|
|
@@ -76,12 +85,14 @@ public struct VecD : IEquatable<VecD>
|
|
|
|
|
|
return triangleArea / a * 2;
|
|
|
}
|
|
|
+
|
|
|
public VecD ProjectOntoLine(VecD pos1, VecD pos2)
|
|
|
{
|
|
|
VecD line = (pos2 - pos1).Normalize();
|
|
|
VecD point = this - pos1;
|
|
|
return (line * point) * line + pos1;
|
|
|
}
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Reflects the vector across a vertical line with the specified position
|
|
|
/// </summary>
|
|
@@ -89,6 +100,7 @@ public struct VecD : IEquatable<VecD>
|
|
|
{
|
|
|
return new(2 * lineX - X, Y);
|
|
|
}
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Reflects the vector along a horizontal line with the specified position
|
|
|
/// </summary>
|
|
@@ -96,11 +108,13 @@ public struct VecD : IEquatable<VecD>
|
|
|
{
|
|
|
return new(X, 2 * lineY - Y);
|
|
|
}
|
|
|
+
|
|
|
public VecD ReflectAcrossLine(VecD pos1, VecD pos2)
|
|
|
{
|
|
|
var onLine = ProjectOntoLine(pos1, pos2);
|
|
|
return onLine - (this - onLine);
|
|
|
}
|
|
|
+
|
|
|
public double AngleTo(VecD other)
|
|
|
{
|
|
|
return Math.Acos((this * other) / Length / other.Length);
|
|
@@ -114,22 +128,27 @@ public struct VecD : IEquatable<VecD>
|
|
|
var rot = other.Rotate(-Angle);
|
|
|
return rot.Angle;
|
|
|
}
|
|
|
+
|
|
|
public VecD Lerp(VecD other, double factor)
|
|
|
{
|
|
|
return (other - this) * factor + this;
|
|
|
}
|
|
|
+
|
|
|
public VecD Normalize()
|
|
|
{
|
|
|
return new VecD(X / Length, Y / Length);
|
|
|
}
|
|
|
+
|
|
|
public VecD Abs()
|
|
|
{
|
|
|
return new VecD(Math.Abs(X), Math.Abs(Y));
|
|
|
}
|
|
|
+
|
|
|
public VecD Signs()
|
|
|
{
|
|
|
return new VecD(X >= 0 ? 1 : -1, Y >= 0 ? 1 : -1);
|
|
|
}
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Returns the signed magnitude (Z coordinate) of the vector resulting from the cross product
|
|
|
/// </summary>
|
|
@@ -139,51 +158,62 @@ public struct VecD : IEquatable<VecD>
|
|
|
}
|
|
|
|
|
|
public double Dot(VecD other) => (X * other.X) + (Y * other.Y);
|
|
|
-
|
|
|
+
|
|
|
public VecD Multiply(VecD other)
|
|
|
{
|
|
|
return new VecD(X * other.X, Y * other.Y);
|
|
|
}
|
|
|
+
|
|
|
public VecD Divide(VecD other)
|
|
|
{
|
|
|
return new VecD(X / other.X, Y / other.Y);
|
|
|
}
|
|
|
+
|
|
|
public static VecD operator +(VecD a, VecD b)
|
|
|
{
|
|
|
return new VecD(a.X + b.X, a.Y + b.Y);
|
|
|
}
|
|
|
+
|
|
|
public static VecD operator -(VecD a, VecD b)
|
|
|
{
|
|
|
return new VecD(a.X - b.X, a.Y - b.Y);
|
|
|
}
|
|
|
+
|
|
|
public static VecD operator -(VecD a)
|
|
|
{
|
|
|
return new VecD(-a.X, -a.Y);
|
|
|
}
|
|
|
+
|
|
|
public static VecD operator *(double b, VecD a)
|
|
|
{
|
|
|
return new VecD(a.X * b, a.Y * b);
|
|
|
}
|
|
|
+
|
|
|
public static double operator *(VecD a, VecD b)
|
|
|
{
|
|
|
return a.X * b.X + a.Y * b.Y;
|
|
|
}
|
|
|
+
|
|
|
public static VecD operator *(VecD a, double b)
|
|
|
{
|
|
|
return new VecD(a.X * b, a.Y * b);
|
|
|
}
|
|
|
+
|
|
|
public static VecD operator /(VecD a, double b)
|
|
|
{
|
|
|
return new VecD(a.X / b, a.Y / b);
|
|
|
}
|
|
|
+
|
|
|
public static VecD operator %(VecD a, double b)
|
|
|
{
|
|
|
return new(a.X % b, a.Y % b);
|
|
|
}
|
|
|
+
|
|
|
public static bool operator ==(VecD a, VecD b)
|
|
|
{
|
|
|
return a.X == b.X && a.Y == b.Y;
|
|
|
}
|
|
|
+
|
|
|
public static bool operator !=(VecD a, VecD b)
|
|
|
{
|
|
|
return !(a.X == b.X && a.Y == b.Y);
|
|
@@ -193,16 +223,18 @@ public struct VecD : IEquatable<VecD>
|
|
|
{
|
|
|
return new VecI((int)vec.X, (int)vec.Y);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
public static implicit operator VecD((double, double) tuple)
|
|
|
{
|
|
|
return new VecD(tuple.Item1, tuple.Item2);
|
|
|
}
|
|
|
+
|
|
|
public void Deconstruct(out double x, out double y)
|
|
|
{
|
|
|
x = X;
|
|
|
y = Y;
|
|
|
}
|
|
|
+
|
|
|
public bool IsNaNOrInfinity()
|
|
|
{
|
|
|
return double.IsNaN(X) || double.IsNaN(Y) || double.IsInfinity(X) || double.IsInfinity(Y);
|
|
@@ -213,6 +245,17 @@ public struct VecD : IEquatable<VecD>
|
|
|
return $"({X}; {Y})";
|
|
|
}
|
|
|
|
|
|
+ public int CompareTo(VecD other)
|
|
|
+ {
|
|
|
+ int xComparison = X.CompareTo(other.X);
|
|
|
+ int yComparison = Y.CompareTo(other.Y);
|
|
|
+ if (xComparison == 0 && yComparison == 0)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ bool anyNegative = xComparison < 0 || yComparison < 0;
|
|
|
+ return anyNegative ? -1 : 1;
|
|
|
+ }
|
|
|
+
|
|
|
public override bool Equals(object? obj)
|
|
|
{
|
|
|
var item = obj as VecD?;
|