From 0f63750e7932f55746a5353178e48d830f4fb05e Mon Sep 17 00:00:00 2001 From: That-One-Nerd Date: Sat, 2 Apr 2022 12:57:00 -0400 Subject: [PATCH] brand new --- .gitignore | 10 + Nerd_STF.dll | Bin 62976 -> 0 bytes Nerd_STF/Nerd_STF/Fill.cs | 4 + Nerd_STF/Nerd_STF/IGroup.cs | 8 + Nerd_STF/Nerd_STF/LogMessage.cs | 25 + Nerd_STF/Nerd_STF/LogSeverity.cs | 11 + Nerd_STF/Nerd_STF/Logger.cs | 72 ++ Nerd_STF/Nerd_STF/Mathematics/Double2.cs | 190 +++ Nerd_STF/Nerd_STF/Mathematics/Double3.cs | 211 ++++ Nerd_STF/Nerd_STF/Mathematics/Double4.cs | 227 ++++ .../Mathematics/Geometry/ITriangulatable.cs | 13 + .../Nerd_STF/Mathematics/Geometry/Line.cs | 149 +++ .../Nerd_STF/Mathematics/Geometry/Triangle.cs | 243 ++++ .../Nerd_STF/Mathematics/Geometry/Vert.cs | 95 ++ Nerd_STF/Nerd_STF/Mathematics/Int2.cs | 184 +++ Nerd_STF/Nerd_STF/Mathematics/Int3.cs | 206 ++++ Nerd_STF/Nerd_STF/Mathematics/Int4.cs | 222 ++++ Nerd_STF/Nerd_STF/Mathematics/Mathf.cs | 205 +++ .../bin/Release/net6.0/ref/Nerd_STF.dll | Bin 0 -> 4608 bytes README.md | 27 +- Scripts/Files.cs | 261 ---- Scripts/General.cs | 119 -- Scripts/Lists.cs | 1095 ----------------- Scripts/Mathematics.cs | 1009 --------------- changelog.md | 165 --- 25 files changed, 2101 insertions(+), 2650 deletions(-) create mode 100644 .gitignore delete mode 100644 Nerd_STF.dll create mode 100644 Nerd_STF/Nerd_STF/Fill.cs create mode 100644 Nerd_STF/Nerd_STF/IGroup.cs create mode 100644 Nerd_STF/Nerd_STF/LogMessage.cs create mode 100644 Nerd_STF/Nerd_STF/LogSeverity.cs create mode 100644 Nerd_STF/Nerd_STF/Logger.cs create mode 100644 Nerd_STF/Nerd_STF/Mathematics/Double2.cs create mode 100644 Nerd_STF/Nerd_STF/Mathematics/Double3.cs create mode 100644 Nerd_STF/Nerd_STF/Mathematics/Double4.cs create mode 100644 Nerd_STF/Nerd_STF/Mathematics/Geometry/ITriangulatable.cs create mode 100644 Nerd_STF/Nerd_STF/Mathematics/Geometry/Line.cs create mode 100644 Nerd_STF/Nerd_STF/Mathematics/Geometry/Triangle.cs create mode 100644 Nerd_STF/Nerd_STF/Mathematics/Geometry/Vert.cs create mode 100644 Nerd_STF/Nerd_STF/Mathematics/Int2.cs create mode 100644 Nerd_STF/Nerd_STF/Mathematics/Int3.cs create mode 100644 Nerd_STF/Nerd_STF/Mathematics/Int4.cs create mode 100644 Nerd_STF/Nerd_STF/Mathematics/Mathf.cs create mode 100644 Nerd_STF/Nerd_STF/bin/Release/net6.0/ref/Nerd_STF.dll delete mode 100644 Scripts/Files.cs delete mode 100644 Scripts/General.cs delete mode 100644 Scripts/Lists.cs delete mode 100644 Scripts/Mathematics.cs delete mode 100644 changelog.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ef4a27b --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +# Visual Studio stuff +*.sln +*.csproj + +/Nerd_STF/.vs +/Nerd_STF/Nerd_STF/obj +/Nerd_STF/Nerd_STF/bin/Debug +/Nerd_STF/Nerd_STF/bin/Release/net6.0/Nerd_STF.deps.json +/Nerd_STF/Nerd_STF/bin/Release/net6.0/Nerd_STF.dll +/Nerd_STF/Nerd_STF/bin/Release/net6.0/Nerd_STF.pdb diff --git a/Nerd_STF.dll b/Nerd_STF.dll deleted file mode 100644 index 3218a2da14dcd981f358fe1baadbf7642dc4a4ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62976 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 index); +} diff --git a/Nerd_STF/Nerd_STF/IGroup.cs b/Nerd_STF/Nerd_STF/IGroup.cs new file mode 100644 index 0000000..06459c9 --- /dev/null +++ b/Nerd_STF/Nerd_STF/IGroup.cs @@ -0,0 +1,8 @@ +namespace Nerd_STF +{ + public interface IGroup : IEnumerable + { + public T[] ToArray(); + public List ToList(); + } +} diff --git a/Nerd_STF/Nerd_STF/LogMessage.cs b/Nerd_STF/Nerd_STF/LogMessage.cs new file mode 100644 index 0000000..c33b94f --- /dev/null +++ b/Nerd_STF/Nerd_STF/LogMessage.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Nerd_STF +{ + public struct LogMessage + { + public string Message; + public LogSeverity Severity; + public DateTime Timestamp; + + public LogMessage() : this("", LogSeverity.Information, null) { } + public LogMessage(string msg, LogSeverity severity, DateTime? time = null) + { + Message = msg; + Severity = severity; + Timestamp = time ?? DateTime.Now; + } + + public override string ToString() => Timestamp + " " + Severity.ToString().ToUpper() + ": " + Message; + } +} diff --git a/Nerd_STF/Nerd_STF/LogSeverity.cs b/Nerd_STF/Nerd_STF/LogSeverity.cs new file mode 100644 index 0000000..51c598e --- /dev/null +++ b/Nerd_STF/Nerd_STF/LogSeverity.cs @@ -0,0 +1,11 @@ +namespace Nerd_STF +{ + public enum LogSeverity + { + Debug = 1, + Information = 2, + Warning = 4, + Error = 8, + Fatal = 16, + } +} diff --git a/Nerd_STF/Nerd_STF/Logger.cs b/Nerd_STF/Nerd_STF/Logger.cs new file mode 100644 index 0000000..0ca41c7 --- /dev/null +++ b/Nerd_STF/Nerd_STF/Logger.cs @@ -0,0 +1,72 @@ +using System.Text; + +namespace Nerd_STF +{ + public class Logger + { + public event Action OnMessageRecieved = DefaultLogHandler; + + public LogMessage[] Cache => msgs.ToArray(); + public int CacheSize = 64; + public List IncludeSeverities = new() + { + LogSeverity.Warning, + LogSeverity.Error, + LogSeverity.Fatal, + }; + public Stream? LogStream; + public int WriteSize; + + private readonly List msgs; + private readonly List writeCache; + + public Logger(Stream? logStream = null, int cacheSize = 64, int writeSize = 1) + { + CacheSize = cacheSize; + LogStream = logStream; + WriteSize = writeSize; + + msgs = new(CacheSize); + writeCache = new(); + } + + public void Send(LogMessage msg) + { + if (!IncludeSeverities.Contains(msg.Severity)) return; + + msgs.Insert(0, msg); + writeCache.Add(msg.ToString()); + while (msgs.Count > CacheSize) msgs.RemoveAt(CacheSize); + OnMessageRecieved(msg); + + if (writeCache.Count >= WriteSize && LogStream != null) + { + string s = ""; + foreach (string cache in writeCache) s += cache + "\n" + (cache.Contains('\n') ? "\n" : ""); + LogStream.Write(Encoding.Default.GetBytes(s)); + LogStream.Flush(); + writeCache.Clear(); + } + } + + public static void DefaultLogHandler(LogMessage msg) + { + ConsoleColor color = msg.Severity switch + { + LogSeverity.Debug => ConsoleColor.DarkGray, + LogSeverity.Information => ConsoleColor.White, + LogSeverity.Warning => ConsoleColor.DarkYellow, + LogSeverity.Error => ConsoleColor.Red, + LogSeverity.Fatal => ConsoleColor.DarkRed, + _ => throw new Exception("Unknown log severity " + msg.Severity), + }; + + ConsoleColor originalCol = Console.ForegroundColor; + + Console.ForegroundColor = color; + Console.WriteLine(msg.ToString()); + + Console.ForegroundColor = originalCol; + } + } +} diff --git a/Nerd_STF/Nerd_STF/Mathematics/Double2.cs b/Nerd_STF/Nerd_STF/Mathematics/Double2.cs new file mode 100644 index 0000000..ed56033 --- /dev/null +++ b/Nerd_STF/Nerd_STF/Mathematics/Double2.cs @@ -0,0 +1,190 @@ +using Nerd_STF.Mathematics.Geometry; +using System.Collections; +using System.Diagnostics.CodeAnalysis; + +namespace Nerd_STF.Mathematics +{ + public struct Double2 : ICloneable, IComparable, IEquatable, IGroup + { + public static Double2 Down => new(0, -1); + public static Double2 Left => new(-1, 0); + public static Double2 Right => new(1, 0); + public static Double2 Up => new(0, 1); + + public static Double2 One => new(1, 1); + public static Double2 Zero => new(0, 0); + + public double Magnitude => Mathf.Sqrt(x * x + y * y); + public Double2 Normalized => this / Magnitude; + + public double x, y; + + public Double2(double all) : this(all, all) { } + public Double2(double x, double y) + { + this.x = x; + this.y = y; + } + public Double2(Fill fill) : this(fill(0), fill(1)) { } + public Double2(Fill fill) : this(fill(0), fill(1)) { } + + public double this[int index] + { + get => index switch + { + 0 => x, + 1 => y, + _ => throw new IndexOutOfRangeException(nameof(index)), + }; + set + { + switch (index) + { + case 0: + x = value; + break; + + case 1: + y = value; + break; + + default: throw new IndexOutOfRangeException(nameof(index)); + } + } + } + + public static Double2 Absolute(Double2 val) => + new(Mathf.Absolute(val.x), Mathf.Absolute(val.y)); + public static Double2 Average(params Double2[] vals) => Sum(vals) / vals.Length; + public static Double2 Ceiling(Double2 val) => + new(Mathf.Ceiling(val.x), Mathf.Ceiling(val.y)); + public static Double2 Clamp(Double2 val, Double2 min, Double2 max) => + new(Mathf.Clamp(val.x, min.x, max.x), + Mathf.Clamp(val.y, min.y, max.y)); + public static Double2 ClampMagnitude(Double2 val, double minMag, double maxMag) + { + if (maxMag < minMag) throw new ArgumentOutOfRangeException(nameof(maxMag), + nameof(maxMag) + " must be greater than or equal to " + nameof(minMag)); + double mag = val.Magnitude; + if (mag >= minMag && mag <= maxMag) return val; + val = val.Normalized; + if (mag < minMag) val *= minMag; + else if (mag > maxMag) val *= maxMag; + return val; + } + public static Double3 Cross(Double2 a, Double2 b, bool normalized = false) => + Double3.Cross(a, b, normalized); + public static Double2 Divide(Double2 num, params Double2[] vals) + { + foreach (Double2 d in vals) num /= d; + return num; + } + public static double Dot(Double2 a, Double2 b) => a.x * b.x + a.y * b.y; + public static double Dot(params Double2[] vals) + { + if (vals.Length < 1) return 0; + double x = 1, y = 1; + foreach (Double2 d in vals) + { + x *= d.x; + y *= d.y; + } + return x + y; + } + public static Double2 Floor(Double2 val) => + new(Mathf.Floor(val.x), Mathf.Floor(val.y)); + public static Double2 Lerp(Double2 a, Double2 b, double t, bool clamp = true) => + new(Mathf.Lerp(a.x, b.x, t, clamp), Mathf.Lerp(a.y, b.y, t, clamp)); + public static Double2 Median(params Double2[] vals) + { + double index = Mathf.Average(0, vals.Length - 1); + Double2 valA = vals[Mathf.Floor(index)], valB = vals[Mathf.Ceiling(index)]; + return Average(valA, valB); + } + public static Double2 Max(params Double2[] vals) + { + if (vals.Length < 1) return Zero; + Double2 val = vals[0]; + foreach (Double2 d in vals) val = d > val ? d : val; + return val; + } + public static Double2 Min(params Double2[] vals) + { + if (vals.Length < 1) return Zero; + Double2 val = vals[0]; + foreach (Double2 d in vals) val = d < val ? d : val; + return val; + } + public static Double2 Multiply(params Double2[] vals) + { + if (vals.Length < 1) return Zero; + Double2 val = One; + foreach (Double2 d in vals) val *= d; + return val; + } + public static Double2 Subtract(Double2 num, params Double2[] vals) + { + foreach (Double2 d in vals) num -= d; + return num; + } + public static Double2 Sum(params Double2[] vals) + { + Double2 val = Zero; + foreach (Double2 d in vals) val += d; + return val; + } + + public int CompareTo(Double2 other) + { + double magA = Magnitude, magB = other.Magnitude; + return magA == magB ? 0 : magA > magB ? 1 : -1; + } + public override bool Equals([NotNullWhen(true)] object? obj) + { + if (obj == null || obj.GetType() != typeof(Double2)) return false; + return Equals((Double2)obj); + } + public bool Equals(Double2 other) => x == other.x && y == other.y; + public override int GetHashCode() => x.GetHashCode() ^ y.GetHashCode(); + public override string ToString() => ToString((string?)null); + public string ToString(string? provider) => + "X: " + x.ToString(provider) + " Y: " + y.ToString(provider); + public string ToString(IFormatProvider provider) => + "X: " + x.ToString(provider) + " Y: " + y.ToString(provider); + + public object Clone() => new Double2(x, y); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + public IEnumerator GetEnumerator() + { + yield return x; + yield return y; + } + + public double[] ToArray() => new[] { x, y }; + public List ToList() => new() { x, y }; + + public static Double2 operator +(Double2 a, Double2 b) => new(a.x + b.x, a.y + b.y); + public static Double2 operator -(Double2 d) => new(-d.x, -d.y); + public static Double2 operator -(Double2 a, Double2 b) => new(a.x - b.x, a.y - b.y); + public static Double2 operator *(Double2 a, Double2 b) => new(a.x * b.x, a.y * b.y); + public static Double2 operator *(Double2 a, double b) => new(a.x * b, a.y * b); + public static Double2 operator /(Double2 a, Double2 b) => new(a.x / b.x, a.y / b.y); + public static Double2 operator /(Double2 a, double b) => new(a.x / b, a.y / b); + public static bool operator ==(Double2 a, Double2 b) => a.Equals(b); + public static bool operator !=(Double2 a, Double2 b) => !a.Equals(b); + public static bool operator >(Double2 a, Double2 b) => a.CompareTo(b) > 0; + public static bool operator <(Double2 a, Double2 b) => a.CompareTo(b) < 0; + public static bool operator >=(Double2 a, Double2 b) => a == b || a > b; + public static bool operator <=(Double2 a, Double2 b) => a == b || a < b; + + public static explicit operator Double2(Double3 val) => new(val.x, val.y); + public static explicit operator Double2(Double4 val) => new(val.x, val.y); + public static implicit operator Double2(Int2 val) => new(val.x, val.y); + public static explicit operator Double2(Int3 val) => new(val.x, val.y); + public static explicit operator Double2(Int4 val) => new(val.x, val.y); + public static explicit operator Double2(Vert val) => new(val.position.x, val.position.y); + public static implicit operator Double2(Fill fill) => new(fill); + public static implicit operator Double2(Fill fill) => new(fill); + } +} diff --git a/Nerd_STF/Nerd_STF/Mathematics/Double3.cs b/Nerd_STF/Nerd_STF/Mathematics/Double3.cs new file mode 100644 index 0000000..5109015 --- /dev/null +++ b/Nerd_STF/Nerd_STF/Mathematics/Double3.cs @@ -0,0 +1,211 @@ +using Nerd_STF.Mathematics.Geometry; +using System.Collections; +using System.Diagnostics.CodeAnalysis; + +namespace Nerd_STF.Mathematics +{ + public struct Double3 : ICloneable, IComparable, IEquatable, IGroup + { + public static Double3 Back => new(0, 0, -1); + public static Double3 Down => new(0, -1, 0); + public static Double3 Forward => new(0, 0, 1); + public static Double3 Left => new(-1, 0, 0); + public static Double3 Right => new(1, 0, 0); + public static Double3 Up => new(0, 1, 0); + + public static Double3 One => new(1, 1, 1); + public static Double3 Zero => new(0, 0, 0); + + public double Magnitude => Mathf.Sqrt(x * x + y * y + z * z); + public Double3 Normalized => this / Magnitude; + + public Double2 XY => new(x, y); + public Double2 XZ => new(x, z); + public Double2 YZ => new(y, z); + + public double x, y, z; + + public Double3(double all) : this(all, all, all) { } + public Double3(double x, double y) : this(x, y, 0) { } + public Double3(double x, double y, double z) + { + this.x = x; + this.y = y; + this.z = z; + } + public Double3(Fill fill) : this(fill(0), fill(1), fill(2)) { } + public Double3(Fill fill) : this(fill(0), fill(1), fill(2)) { } + + public double this[int index] + { + get => index switch + { + 0 => x, + 1 => y, + 2 => z, + _ => throw new IndexOutOfRangeException(nameof(index)), + }; + set + { + switch (index) + { + case 0: + x = value; + break; + + case 1: + y = value; + break; + + case 2: + z = value; + break; + + default: throw new IndexOutOfRangeException(nameof(index)); + } + } + } + + public static Double3 Absolute(Double3 val) => + new(Mathf.Absolute(val.x), Mathf.Absolute(val.y), Mathf.Absolute(val.z)); + public static Double3 Average(params Double3[] vals) => Sum(vals) / vals.Length; + public static Double3 Ceiling(Double3 val) => + new(Mathf.Ceiling(val.x), Mathf.Ceiling(val.y), Mathf.Ceiling(val.z)); + public static Double3 Clamp(Double3 val, Double3 min, Double3 max) => + new(Mathf.Clamp(val.x, min.x, max.x), + Mathf.Clamp(val.y, min.y, max.y), + Mathf.Clamp(val.z, min.z, max.z)); + public static Double3 ClampMagnitude(Double3 val, double minMag, double maxMag) + { + if (maxMag < minMag) throw new ArgumentOutOfRangeException(nameof(maxMag), + nameof(maxMag) + " must be greater than or equal to " + nameof(minMag)); + double mag = val.Magnitude; + if (mag >= minMag && mag <= maxMag) return val; + val = val.Normalized; + if (mag < minMag) val *= minMag; + else if (mag > maxMag) val *= maxMag; + return val; + } + public static Double3 Cross(Double3 a, Double3 b, bool normalized = false) + { + Double3 val = new(a.y * b.z - b.y * a.z, + b.x * a.z - a.x * b.z, + a.x * b.y - b.x * a.y); + return normalized ? val.Normalized : val; + } + public static Double3 Divide(Double3 num, params Double3[] vals) + { + foreach (Double3 d in vals) num /= d; + return num; + } + public static double Dot(Double3 a, Double3 b) => a.x * b.x + a.y * b.y + a.z * b.z; + public static double Dot(params Double3[] vals) + { + if (vals.Length < 1) return 0; + double x = 1, y = 1, z = 1; + foreach (Double3 d in vals) + { + x *= d.x; + y *= d.y; + z *= d.z; + } + return x + y + z; + } + public static Double3 Floor(Double3 val) => + new(Mathf.Floor(val.x), Mathf.Floor(val.y), Mathf.Floor(val.z)); + public static Double3 Lerp(Double3 a, Double3 b, double t, bool clamp = true) => + new(Mathf.Lerp(a.x, b.x, t, clamp), Mathf.Lerp(a.y, b.y, t, clamp), Mathf.Lerp(a.z, b.z, t, clamp)); + public static Double3 Median(params Double3[] vals) + { + double index = Mathf.Average(0, vals.Length - 1); + Double3 valA = vals[Mathf.Floor(index)], valB = vals[Mathf.Ceiling(index)]; + return Average(valA, valB); + } + public static Double3 Max(params Double3[] vals) + { + if (vals.Length < 1) return Zero; + Double3 val = vals[0]; + foreach (Double3 d in vals) val = d > val ? d : val; + return val; + } + public static Double3 Min(params Double3[] vals) + { + if (vals.Length < 1) return Zero; + Double3 val = vals[0]; + foreach (Double3 d in vals) val = d < val ? d : val; + return val; + } + public static Double3 Multiply(params Double3[] vals) + { + if (vals.Length < 1) return Zero; + Double3 val = One; + foreach (Double3 d in vals) val *= d; + return val; + } + public static Double3 Subtract(Double3 num, params Double3[] vals) + { + foreach (Double3 d in vals) num -= d; + return num; + } + public static Double3 Sum(params Double3[] vals) + { + Double3 val = Zero; + foreach (Double3 d in vals) val += d; + return val; + } + + public int CompareTo(Double3 other) + { + double magA = Magnitude, magB = other.Magnitude; + return magA == magB ? 0 : magA > magB ? 1 : -1; + } + public override bool Equals([NotNullWhen(true)] object? obj) + { + if (obj == null || obj.GetType() != typeof(Double3)) return false; + return Equals((Double3)obj); + } + public bool Equals(Double3 other) => x == other.x && y == other.y && z == other.z; + public override int GetHashCode() => x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode(); + public override string ToString() => ToString((string?)null); + public string ToString(string? provider) => + "X: " + x.ToString(provider) + " Y: " + y.ToString(provider) + " Z: " + z.ToString(provider); + public string ToString(IFormatProvider provider) => + "X: " + x.ToString(provider) + " Y: " + y.ToString(provider) + " Z: " + z.ToString(provider); + + public object Clone() => new Double3(x, y, z); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + public IEnumerator GetEnumerator() + { + yield return x; + yield return y; + yield return z; + } + + public double[] ToArray() => new[] { x, y, z }; + public List ToList() => new() { x, y, z }; + + public static Double3 operator +(Double3 a, Double3 b) => new(a.x + b.x, a.y + b.y, a.z + b.z); + public static Double3 operator -(Double3 d) => new(-d.x, -d.y, -d.z); + public static Double3 operator -(Double3 a, Double3 b) => new(a.x - b.x, a.y - b.y, a.z - b.z); + public static Double3 operator *(Double3 a, Double3 b) => new(a.x * b.x, a.y * b.y, a.z * b.z); + public static Double3 operator *(Double3 a, double b) => new(a.x * b, a.y * b, a.z * b); + public static Double3 operator /(Double3 a, Double3 b) => new(a.x / b.x, a.y / b.y, a.z / b.z); + public static Double3 operator /(Double3 a, double b) => new(a.x / b, a.y / b, a.z / b); + public static bool operator ==(Double3 a, Double3 b) => a.Equals(b); + public static bool operator !=(Double3 a, Double3 b) => !a.Equals(b); + public static bool operator >(Double3 a, Double3 b) => a.CompareTo(b) > 0; + public static bool operator <(Double3 a, Double3 b) => a.CompareTo(b) < 0; + public static bool operator >=(Double3 a, Double3 b) => a == b || a > b; + public static bool operator <=(Double3 a, Double3 b) => a == b || a < b; + + public static implicit operator Double3(Double2 val) => new(val.x, val.y, 0); + public static explicit operator Double3(Double4 val) => new(val.x, val.y, val.z); + public static implicit operator Double3(Int2 val) => new(val.x, val.y, 0); + public static implicit operator Double3(Int3 val) => new(val.x, val.y, val.z); + public static explicit operator Double3(Int4 val) => new(val.x, val.y, val.z); + public static implicit operator Double3(Vert val) => new(val.position.x, val.position.y, val.position.z); + public static implicit operator Double3(Fill fill) => new(fill); + public static implicit operator Double3(Fill fill) => new(fill); + } +} diff --git a/Nerd_STF/Nerd_STF/Mathematics/Double4.cs b/Nerd_STF/Nerd_STF/Mathematics/Double4.cs new file mode 100644 index 0000000..e02c62a --- /dev/null +++ b/Nerd_STF/Nerd_STF/Mathematics/Double4.cs @@ -0,0 +1,227 @@ +using Nerd_STF.Mathematics.Geometry; +using System.Collections; +using System.Diagnostics.CodeAnalysis; + +namespace Nerd_STF.Mathematics +{ + public struct Double4 : ICloneable, IComparable, IEquatable, IGroup + { + public static Double4 Back => new(0, 0, -1, 0); + public static Double4 Deep => new(0, 0, 0, -1); + public static Double4 Down => new(0, -1, 0, 0); + public static Double4 Far => new(0, 0, 0, 1); + public static Double4 Forward => new(0, 0, 1, 0); + public static Double4 Left => new(-1, 0, 0, 0); + public static Double4 Right => new(1, 0, 0, 0); + public static Double4 Up => new(0, 1, 0, 0); + + public static Double4 One => new(1, 1, 1, 1); + public static Double4 Zero => new(0, 0, 0, 0); + + public double Magnitude => Mathf.Sqrt(x * x + y * y + z * z + w * w); + public Double4 Normalized => this / Magnitude; + + public Double2 XY => new(x, y); + public Double2 XZ => new(x, z); + public Double2 XW => new(x, w); + public Double2 YW => new(y, w); + public Double2 YZ => new(y, z); + public Double2 ZW => new(z, w); + + public Double3 XYW => new(x, y, w); + public Double3 XYZ => new(x, y, z); + public Double3 YZW => new(y, z, w); + public Double3 XZW => new(x, z, w); + + public double x, y, z, w; + + public Double4(double all) : this(all, all, all, all) { } + public Double4(double x, double y) : this(x, y, 0, 0) { } + public Double4(double x, double y, double z) : this(x, y, z, 0) { } + public Double4(double x, double y, double z, double w) + { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } + public Double4(Fill fill) : this(fill(0), fill(1), fill(2), fill(3)) { } + public Double4(Fill fill) : this(fill(0), fill(1), fill(2), fill(3)) { } + + public double this[int index] + { + get => index switch + { + 0 => x, + 1 => y, + 2 => z, + 3 => w, + _ => throw new IndexOutOfRangeException(nameof(index)), + }; + set + { + switch (index) + { + case 0: + x = value; + break; + + case 1: + y = value; + break; + + case 2: + z = value; + break; + + case 3: + w = value; + break; + + default: throw new IndexOutOfRangeException(nameof(index)); + } + } + } + + public static Double4 Absolute(Double4 val) => + new(Mathf.Absolute(val.x), Mathf.Absolute(val.y), Mathf.Absolute(val.z), Mathf.Absolute(val.w)); + public static Double4 Average(params Double4[] vals) => Sum(vals) / vals.Length; + public static Double4 Ceiling(Double4 val) => + new(Mathf.Ceiling(val.x), Mathf.Ceiling(val.y), Mathf.Ceiling(val.z), Mathf.Ceiling(val.w)); + public static Double4 Clamp(Double4 val, Double4 min, Double4 max) => + new(Mathf.Clamp(val.x, min.x, max.x), + Mathf.Clamp(val.y, min.y, max.y), + Mathf.Clamp(val.z, min.z, max.z), + Mathf.Clamp(val.w, min.w, max.w)); + public static Double4 ClampMagnitude(Double4 val, double minMag, double maxMag) + { + if (maxMag < minMag) throw new ArgumentOutOfRangeException(nameof(maxMag), + nameof(maxMag) + " must be greater than or equal to " + nameof(minMag)); + double mag = val.Magnitude; + if (mag >= minMag && mag <= maxMag) return val; + val = val.Normalized; + if (mag < minMag) val *= minMag; + else if (mag > maxMag) val *= maxMag; + return val; + } + public static Double4 Divide(Double4 num, params Double4[] vals) + { + foreach (Double4 d in vals) num /= d; + return num; + } + public static double Dot(Double4 a, Double4 b) => a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; + public static double Dot(params Double4[] vals) + { + if (vals.Length < 1) return 0; + double x = 1, y = 1, z = 1, w = 1; + foreach (Double4 d in vals) + { + x *= d.x; + y *= d.y; + z *= d.z; + w *= d.w; + } + return x + y + z; + } + public static Double4 Floor(Double4 val) => + new(Mathf.Floor(val.x), Mathf.Floor(val.y), Mathf.Floor(val.z), Mathf.Floor(val.w)); + public static Double4 Lerp(Double4 a, Double4 b, double t, bool clamp = true) => + new(Mathf.Lerp(a.x, b.x, t, clamp), Mathf.Lerp(a.y, b.y, t, clamp), Mathf.Lerp(a.z, b.z, t, clamp), + Mathf.Lerp(a.w, b.w, t, clamp)); + public static Double4 Median(params Double4[] vals) + { + double index = Mathf.Average(0, vals.Length - 1); + Double4 valA = vals[Mathf.Floor(index)], valB = vals[Mathf.Ceiling(index)]; + return Average(valA, valB); + } + public static Double4 Max(params Double4[] vals) + { + if (vals.Length < 1) return Zero; + Double4 val = vals[0]; + foreach (Double4 d in vals) val = d > val ? d : val; + return val; + } + public static Double4 Min(params Double4[] vals) + { + if (vals.Length < 1) return Zero; + Double4 val = vals[0]; + foreach (Double4 d in vals) val = d < val ? d : val; + return val; + } + public static Double4 Multiply(params Double4[] vals) + { + if (vals.Length < 1) return Zero; + Double4 val = One; + foreach (Double4 d in vals) val *= d; + return val; + } + public static Double4 Subtract(Double4 num, params Double4[] vals) + { + foreach (Double4 d in vals) num -= d; + return num; + } + public static Double4 Sum(params Double4[] vals) + { + Double4 val = Zero; + foreach (Double4 d in vals) val += d; + return val; + } + + public int CompareTo(Double4 other) + { + double magA = Magnitude, magB = other.Magnitude; + return magA == magB ? 0 : magA > magB ? 1 : -1; + } + public override bool Equals([NotNullWhen(true)] object? obj) + { + if (obj == null || obj.GetType() != typeof(Double4)) return false; + return Equals((Double4)obj); + } + public bool Equals(Double4 other) => x == other.x && y == other.y && z == other.z && w == other.w; + public override int GetHashCode() => x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode(); + public override string ToString() => ToString((string?)null); + public string ToString(string? provider) => + "X: " + x.ToString(provider) + " Y: " + y.ToString(provider) + " Z: " + z.ToString(provider) + + " W: " + w.ToString(provider); + public string ToString(IFormatProvider provider) => + "X: " + x.ToString(provider) + " Y: " + y.ToString(provider) + " Z: " + z.ToString(provider) + + " W: " + w.ToString(provider); + + public object Clone() => new Double4(x, y, z, w); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + public IEnumerator GetEnumerator() + { + yield return x; + yield return y; + yield return z; + yield return w; + } + + public double[] ToArray() => new[] { x, y, z, w }; + public List ToList() => new() { x, y, z, w }; + + public static Double4 operator +(Double4 a, Double4 b) => new(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w); + public static Double4 operator -(Double4 d) => new(-d.x, -d.y, -d.z, -d.w); + public static Double4 operator -(Double4 a, Double4 b) => new(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w); + public static Double4 operator *(Double4 a, Double4 b) => new(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w); + public static Double4 operator *(Double4 a, double b) => new(a.x * b, a.y * b, a.z * b, a.w * b); + public static Double4 operator /(Double4 a, Double4 b) => new(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w); + public static Double4 operator /(Double4 a, double b) => new(a.x / b, a.y / b, a.z / b, a.w / b); + public static bool operator ==(Double4 a, Double4 b) => a.Equals(b); + public static bool operator !=(Double4 a, Double4 b) => !a.Equals(b); + public static bool operator >(Double4 a, Double4 b) => a.CompareTo(b) > 0; + public static bool operator <(Double4 a, Double4 b) => a.CompareTo(b) < 0; + public static bool operator >=(Double4 a, Double4 b) => a == b || a > b; + public static bool operator <=(Double4 a, Double4 b) => a == b || a < b; + + public static implicit operator Double4(Double2 val) => new(val.x, val.y, 0, 0); + public static implicit operator Double4(Double3 val) => new(val.x, val.y, val.z, 0); + public static implicit operator Double4(Int2 val) => new(val.x, val.y, 0, 0); + public static implicit operator Double4(Int3 val) => new(val.x, val.y, val.z, 0); + public static implicit operator Double4(Int4 val) => new(val.x, val.y, val.z, val.w); + public static implicit operator Double4(Vert val) => new(val.position.x, val.position.y, val.position.z, 0); + public static implicit operator Double4(Fill fill) => new(fill); + public static implicit operator Double4(Fill fill) => new(fill); + } +} diff --git a/Nerd_STF/Nerd_STF/Mathematics/Geometry/ITriangulatable.cs b/Nerd_STF/Nerd_STF/Mathematics/Geometry/ITriangulatable.cs new file mode 100644 index 0000000..eb8c89a --- /dev/null +++ b/Nerd_STF/Nerd_STF/Mathematics/Geometry/ITriangulatable.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Nerd_STF.Mathematics.Geometry +{ + public interface ITriangulatable + { + public Triangle[] Triangulate(); + } +} diff --git a/Nerd_STF/Nerd_STF/Mathematics/Geometry/Line.cs b/Nerd_STF/Nerd_STF/Mathematics/Geometry/Line.cs new file mode 100644 index 0000000..542d38d --- /dev/null +++ b/Nerd_STF/Nerd_STF/Mathematics/Geometry/Line.cs @@ -0,0 +1,149 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Nerd_STF.Mathematics.Geometry +{ + public struct Line : ICloneable, IEquatable, IGroup + { + public static Line Back => new(Vert.Zero, Vert.Back); + public static Line Down => new(Vert.Zero, Vert.Down); + public static Line Forward => new(Vert.Zero, Vert.Forward); + public static Line Left => new(Vert.Zero, Vert.Left); + public static Line Right => new(Vert.Zero, Vert.Right); + public static Line Up => new(Vert.Zero, Vert.Up); + + public static Line One => new(Vert.Zero, Vert.One); + public static Line Zero => new(Vert.Zero, Vert.Zero); + + public double Length => (end - start).Magnitude; + + public Vert start, end; + + public Line(Vert start, Vert end) + { + this.start = start; + this.end = end; + } + public Line(double x1, double y1, double x2, double y2) : this(new(x1, y1), new(x2, y2)) { } + public Line(double x1, double y1, double z1, double x2, double y2, double z2) + : this(new(x1, y1, z1), new(x2, y2, z2)) { } + public Line(Fill fill) : this(fill(0), fill(1)) { } + public Line(Fill fill) : this(new(fill(0)), new(fill(1))) { } + public Line(Fill fill) : this(new(fill(0)), new(fill(1))) { } + public Line(Fill fill) : this(new(fill(0), fill(1), fill(2)), new(fill(3), fill(4), fill(5))) { } + public Line(Fill fill) : this(new(fill(0), fill(1), fill(2)), new(fill(3), fill(4), fill(5))) { } + + public Vert this[int index] + { + get => index switch + { + 0 => start, + 1 => end, + _ => throw new IndexOutOfRangeException(nameof(index)), + }; + set + { + switch (index) + { + case 0: + start = value; + break; + + case 1: + end = value; + break; + + default: throw new IndexOutOfRangeException(nameof(index)); + } + } + } + + public static Line Absolute(Line val) => new(Vert.Absolute(val.start), Vert.Absolute(val.end)); + public static Line Average(params Line[] vals) + { + (Vert[] starts, Vert[] ends) = SplitArray(vals); + return new(Vert.Average(starts), Vert.Average(ends)); + } + public static Line Ceiling(Line val) => new(Vert.Ceiling(val.start), Vert.Ceiling(val.end)); + public static Line Clamp(Line val, Line min, Line max) => + new(Vert.Clamp(val.start, min.start, max.start), Vert.Clamp(val.end, min.end, max.end)); + public static Line Floor(Line val) => new(Vert.Floor(val.start), Vert.Floor(val.end)); + public static Line Lerp(Line a, Line b, double t, bool clamp = true) => + new(Vert.Lerp(a.start, b.start, t, clamp), Vert.Lerp(a.end, b.end, t, clamp)); + public static Line Median(params Line[] vals) + { + (Vert[] starts, Vert[] ends) = SplitArray(vals); + return new(Vert.Median(starts), Vert.Median(ends)); + } + public static Line Max(params Line[] vals) + { + (Vert[] starts, Vert[] ends) = SplitArray(vals); + return new(Vert.Max(starts), Vert.Max(ends)); + } + public static Line Min(params Line[] vals) + { + (Vert[] starts, Vert[] ends) = SplitArray(vals); + return new(Vert.Min(starts), Vert.Min(ends)); + } + + public static (Vert[] starts, Vert[] ends) SplitArray(params Line[] lines) + { + Vert[] starts = new Vert[lines.Length], ends = new Vert[lines.Length]; + for (int i = 0; i < lines.Length; i++) + { + starts[i] = lines[i].start; + ends[i] = lines[i].end; + } + return (starts, ends); + } + + public override bool Equals([NotNullWhen(true)] object? obj) + { + if (obj == null || obj.GetType() != typeof(Line)) return false; + return Equals((Line)obj); + } + public bool Equals(Line other) => start == other.start && end == other.end; + public override int GetHashCode() => start.GetHashCode() ^ end.GetHashCode(); + public override string ToString() => ToString((string?)null); + public string ToString(string? provider) => + "A: " + start.ToString(provider) + " B: " + end.ToString(provider); + public string ToString(IFormatProvider provider) => + "A: " + start.ToString(provider) + " B: " + end.ToString(provider); + + public object Clone() => new Line(start, end); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + public IEnumerator GetEnumerator() + { + yield return start; + yield return end; + } + + public Vert[] ToArray() => new Vert[] { start, end }; + public List ToList() => new() { start, end }; + + public static Line operator +(Line a, Line b) => new(a.start + b.start, a.end + b.end); + public static Line operator +(Line a, Vert b) => new(a.start + b, a.end + b); + public static Line operator -(Line a, Line b) => new(a.start - b.start, a.end - b.end); + public static Line operator -(Line a, Vert b) => new(a.start - b, a.end - b); + public static Line operator *(Line a, Line b) => new(a.start * b.start, a.end * b.end); + public static Line operator *(Line a, Vert b) => new(a.start * b, a.end * b); + public static Line operator *(Line a, double b) => new(a.start * b, a.end * b); + public static Line operator /(Line a, Line b) => new(a.start / b.start, a.end / b.end); + public static Line operator /(Line a, Vert b) => new(a.start / b, a.end / b); + public static Line operator /(Line a, double b) => new(a.start / b, a.end / b); + public static bool operator ==(Line a, Line b) => a.Equals(b); + public static bool operator !=(Line a, Line b) => !a.Equals(b); + + public static implicit operator Line(Fill fill) => new(fill); + public static implicit operator Line(Fill fill) => new(fill); + public static implicit operator Line(Fill fill) => new(fill); + public static implicit operator Line(Fill fill) => new(fill); + public static implicit operator Line(Fill fill) => new(fill); + } +} diff --git a/Nerd_STF/Nerd_STF/Mathematics/Geometry/Triangle.cs b/Nerd_STF/Nerd_STF/Mathematics/Geometry/Triangle.cs new file mode 100644 index 0000000..8709918 --- /dev/null +++ b/Nerd_STF/Nerd_STF/Mathematics/Geometry/Triangle.cs @@ -0,0 +1,243 @@ +using System.Collections; +using System.Diagnostics.CodeAnalysis; + +namespace Nerd_STF.Mathematics.Geometry +{ + public struct Triangle : ICloneable, IEquatable, IGroup + { + public Vert A + { + get => p_a; + set + { + p_a = value; + p_l1 = new(value, p_b); + p_l3 = new(p_c, value); + } + } + public Vert B + { + get => p_b; + set + { + p_b = value; + p_l1 = new(p_a, value); + p_l2 = new(value, p_c); + } + } + public Vert C + { + get => p_c; + set + { + p_c = value; + p_l2 = new(p_b, value); + p_l3 = new(value, p_a); + } + } + public Line L1 + { + get => p_l1; + set + { + p_a = value.start; + p_b = value.end; + p_l2 = new(value.end, p_c); + p_l3 = new(p_c, value.start); + } + } + public Line L2 + { + get => p_l2; + set + { + p_b = value.start; + p_c = value.end; + p_l1 = new(p_a, value.start); + p_l3 = new(value.end, p_a); + } + } + public Line L3 + { + get => p_l3; + set + { + p_a = value.end; + p_c = value.start; + p_l1 = new(value.end, p_b); + p_l2 = new(p_b, value.start); + } + } + + private Vert p_a, p_b, p_c; + private Line p_l1, p_l2, p_l3; + + public Triangle(Vert a, Vert b, Vert c) + { + p_a = a; + p_b = b; + p_c = c; + p_l1 = new(a, b); + p_l2 = new(b, c); + p_l3 = new(c, a); + } + public Triangle(Line l1, Line l2, Line l3) + { + if (l1.start != l3.end && l1.end != l2.start && l2.end != l3.start) + throw new ArgumentException("Lines are not connected."); + + p_a = l1.start; + p_b = l2.start; + p_c = l3.start; + p_l1 = l1; + p_l2 = l2; + p_l3 = l3; + } + public Triangle(double x1, double y1, double x2, double y2, double x3, double y3) + : this(new Vert(x1, y1), new Vert(x2, y2), new Vert(x3, y3)) { } + public Triangle(double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, + double z3) : this(new Vert(x1, y1, z1), new Vert(x2, y2, z2), new Vert(x3, y3, z3)) { } + public Triangle(Fill fill) : this(fill(0), fill(1), fill(2)) { } + public Triangle(Fill fill) : this(fill(0), fill(1), fill(2)) { } + public Triangle(Fill fill) : this(fill(0), fill(1), fill(2)) { } + public Triangle(Fill fill) : this(fill(0), fill(1), fill(2)) { } + public Triangle(Fill fill) : this(fill(0), fill(1), fill(2), fill(3), fill(4), fill(5), fill(6), + fill(7), fill(8)) + { } + public Triangle(Fill fill) : this(fill(0), fill(1), fill(2), fill(3), fill(4), fill(5), fill(6), + fill(7), fill(8)) + { } + + public Vert this[int index] + { + get => index switch + { + 0 => A, + 1 => B, + 2 => C, + _ => throw new IndexOutOfRangeException(nameof(index)), + }; + set + { + switch (index) + { + case 0: + A = value; + break; + + case 1: + B = value; + break; + + case 2: + C = value; + break; + + default: throw new IndexOutOfRangeException(nameof(index)); + } + } + } + + public static Triangle Absolute(Triangle val) => + new(Vert.Absolute(val.A), Vert.Absolute(val.B), Vert.Absolute(val.C)); + public static Triangle Average(params Triangle[] vals) + { + (Vert[] As, Vert[] Bs, Vert[] Cs) = SplitVertArray(vals); + return new(Vert.Average(As), Vert.Average(Bs), Vert.Average(Cs)); + } + public static Triangle Ceiling(Triangle val) => + new(Vert.Ceiling(val.A), Vert.Ceiling(val.B), Vert.Ceiling(val.C)); + public static Triangle Clamp(Triangle val, Triangle min, Triangle max) => + new(Vert.Clamp(val.A, min.A, max.A), Vert.Clamp(val.B, min.B, max.B), Vert.Clamp(val.C, min.C, max.C)); + public static Triangle Floor(Triangle val) => + new(Vert.Floor(val.A), Vert.Floor(val.B), Vert.Floor(val.C)); + public static Triangle Lerp(Triangle a, Triangle b, double t, bool clamp = false) => + new(Vert.Lerp(a.A, b.A, t, clamp), Vert.Lerp(a.B, b.B, t, clamp), Vert.Lerp(a.C, b.C, t, clamp)); + public static Triangle Median(params Triangle[] vals) + { + (Vert[] As, Vert[] Bs, Vert[] Cs) = SplitVertArray(vals); + return new(Vert.Median(As), Vert.Median(Bs), Vert.Median(Cs)); + } + public static Triangle Max(params Triangle[] vals) + { + (Vert[] As, Vert[] Bs, Vert[] Cs) = SplitVertArray(vals); + return new(Vert.Max(As), Vert.Max(Bs), Vert.Max(Cs)); + } + public static Triangle Min(params Triangle[] vals) + { + (Vert[] As, Vert[] Bs, Vert[] Cs) = SplitVertArray(vals); + return new(Vert.Min(As), Vert.Min(Bs), Vert.Min(Cs)); + } + + public static (Vert[] As, Vert[] Bs, Vert[] Cs) SplitVertArray(params Triangle[] tris) + { + Vert[] a = new Vert[tris.Length], b = new Vert[tris.Length], c = new Vert[tris.Length]; + for (int i = 0; i < tris.Length; i++) + { + a[i] = tris[i].A; + b[i] = tris[i].B; + c[i] = tris[i].C; + } + + return (a, b, c); + } + public static (Line[] L1s, Line[] L2s, Line[] L3s) SplitLineArray(params Triangle[] tris) + { + Line[] l1 = new Line[tris.Length], l2 = new Line[tris.Length], l3 = new Line[tris.Length]; + for (int i = 0; i < tris.Length; i++) + { + l1[i] = tris[i].L1; + l2[i] = tris[i].L2; + l3[i] = tris[i].L3; + } + + return (l1, l2, l3); + } + + public override bool Equals([NotNullWhen(true)] object? obj) + { + if (obj == null || obj.GetType() != typeof(Triangle)) return false; + return Equals((Triangle)obj); + } + public bool Equals(Triangle other) => A == other.A && B == other.B && C == other.C; + public override int GetHashCode() => A.GetHashCode() ^ B.GetHashCode() ^ C.GetHashCode(); + public override string ToString() => ToString((string?)null); + public string ToString(string? provider) => + "A: " + A.ToString(provider) + " B: " + B.ToString(provider) + " C: " + C.ToString(provider); + public string ToString(IFormatProvider provider) => + "A: " + A.ToString(provider) + " B: " + B.ToString(provider) + " C: " + C.ToString(provider); + + public object Clone() => new Triangle(A, B, C); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + public IEnumerator GetEnumerator() + { + yield return A; + yield return B; + yield return C; + } + + public Vert[] ToArray() => new Vert[] { A, B, C }; + public List ToList() => new() { A, B, C }; + + public static Triangle operator +(Triangle a, Triangle b) => new(a.A + b.A, a.B + b.B, a.C + b.C); + public static Triangle operator +(Triangle a, Vert b) => new(a.A + b, a.B + b, a.C + b); + public static Triangle operator -(Triangle a, Triangle b) => new(a.A - b.A, a.B - b.B, a.C - b.C); + public static Triangle operator -(Triangle a, Vert b) => new(a.A - b, a.B - b, a.C - b); + public static Triangle operator *(Triangle a, Triangle b) => new(a.A * b.A, a.B * b.B, a.C * b.C); + public static Triangle operator *(Triangle a, Vert b) => new(a.A * b, a.B * b, a.C * b); + public static Triangle operator *(Triangle a, double b) => new(a.A * b, a.B * b, a.C * b); + public static Triangle operator /(Triangle a, Triangle b) => new(a.A / b.A, a.B / b.B, a.C / b.C); + public static Triangle operator /(Triangle a, Vert b) => new(a.A / b, a.B / b, a.C / b); + public static Triangle operator /(Triangle a, double b) => new(a.A / b, a.B / b, a.C / b); + public static bool operator ==(Triangle a, Triangle b) => a.Equals(b); + public static bool operator !=(Triangle a, Triangle b) => !a.Equals(b); + + public static implicit operator Triangle(Fill fill) => new(fill); + public static implicit operator Triangle(Fill fill) => new(fill); + public static implicit operator Triangle(Fill fill) => new(fill); + public static implicit operator Triangle(Fill fill) => new(fill); + public static implicit operator Triangle(Fill fill) => new(fill); + public static implicit operator Triangle(Fill fill) => new(fill); + } +} diff --git a/Nerd_STF/Nerd_STF/Mathematics/Geometry/Vert.cs b/Nerd_STF/Nerd_STF/Mathematics/Geometry/Vert.cs new file mode 100644 index 0000000..9e41d85 --- /dev/null +++ b/Nerd_STF/Nerd_STF/Mathematics/Geometry/Vert.cs @@ -0,0 +1,95 @@ +using System.Diagnostics.CodeAnalysis; + +namespace Nerd_STF.Mathematics.Geometry +{ + public struct Vert : ICloneable, IEquatable + { + public static Vert Back => new(0, 0, -1); + public static Vert Down => new(0, -1, 0); + public static Vert Forward => new(0, 0, 1); + public static Vert Left => new(-1, 0, 0); + public static Vert Right => new(1, 0, 0); + public static Vert Up => new(0, 1, 0); + + public static Vert One => new(1, 1, 1); + public static Vert Zero => new(0, 0, 0); + + public double Magnitude => position.Magnitude; + public Vert Normalized => new(this / Magnitude); + + public Double3 position; + + public Vert(Double2 pos) : this(pos.x, pos.y, 0) { } + public Vert(Double3 pos) => position = pos; + public Vert(double x, double y) : this(new Double2(x, y)) { } + public Vert(double x, double y, double z) : this(new Double3(x, y, z)) { } + public Vert(Fill fill) : this(new Double3(fill)) { } + public Vert(Fill fill) : this(new Double3(fill)) { } + + public double this[int index] + { + get => position[index]; + set => position[index] = value; + } + + public static Vert Absolute(Vert val) => new(Double3.Absolute(val.position)); + public static Vert Average(params Vert[] vals) => Double3.Average(ToDouble3Array(vals)); + public static Vert Ceiling(Vert val) => new(Double3.Ceiling(val.position)); + public static Vert Clamp(Vert val, Vert min, Vert max) => + new(Double3.Clamp(val.position, min.position, max.position)); + public static Vert ClampMagnitude(Vert val, double minMag, double maxMag) => + new(Double3.ClampMagnitude(val.position, minMag, maxMag)); + public static Vert Cross(Vert a, Vert b, bool normalized = false) => + new(Double3.Cross(a.position, b.position, normalized)); + public static double Dot(Vert a, Vert b) => Double3.Dot(a.position, b.position); + public static double Dot(params Vert[] vals) => Double3.Dot(ToDouble3Array(vals)); + public static Vert Floor(Vert val) => new(Double3.Floor(val.position)); + public static Vert Lerp(Vert a, Vert b, double t, bool clamp = true) => + new(Double3.Lerp(a.position, b.position, t, clamp)); + public static Vert Median(params Vert[] vals) => + Double3.Median(ToDouble3Array(vals)); + public static Vert Max(params Vert[] vals) => + Double3.Max(ToDouble3Array(vals)); + public static Vert Min(params Vert[] vals) => + Double3.Min(ToDouble3Array(vals)); + public static Double3[] ToDouble3Array(params Vert[] vals) + { + Double3[] doubles = new Double3[vals.Length]; + for (int i = 0; i < vals.Length; i++) doubles[i] = vals[i].position; + return doubles; + } + public static List ToDouble3List(params Vert[] vals) => ToDouble3Array(vals).ToList(); + + public override bool Equals([NotNullWhen(true)] object? obj) + { + if (obj == null || obj.GetType() != typeof(Vert)) return false; + return Equals((Vert)obj); + } + public bool Equals(Vert other) => position == other.position; + public override int GetHashCode() => position.GetHashCode(); + public override string ToString() => ToString((string?)null); + public string ToString(string? provider) => position.ToString(provider); + public string ToString(IFormatProvider provider) => position.ToString(provider); + + public object Clone() => new Vert(position); + + public static Vert operator +(Vert a, Vert b) => new(a.position + b.position); + public static Vert operator -(Vert d) => new(-d.position); + public static Vert operator -(Vert a, Vert b) => new(a.position - b.position); + public static Vert operator *(Vert a, Vert b) => new(a.position * b.position); + public static Vert operator *(Vert a, double b) => new(a.position * b); + public static Vert operator /(Vert a, Vert b) => new(a.position / b.position); + public static Vert operator /(Vert a, double b) => new(a.position / b); + public static bool operator ==(Vert a, Vert b) => a.Equals(b); + public static bool operator !=(Vert a, Vert b) => !a.Equals(b); + + public static implicit operator Vert(Double2 val) => new(val); + public static implicit operator Vert(Double3 val) => new(val); + public static explicit operator Vert(Double4 val) => new(val.XYZ); + public static implicit operator Vert(Int2 val) => new(val); + public static implicit operator Vert(Int3 val) => new(val); + public static explicit operator Vert(Int4 val) => new(val.XYZ); + public static implicit operator Vert(Fill fill) => new(fill); + public static implicit operator Vert(Fill fill) => new(fill); + } +} diff --git a/Nerd_STF/Nerd_STF/Mathematics/Int2.cs b/Nerd_STF/Nerd_STF/Mathematics/Int2.cs new file mode 100644 index 0000000..7023457 --- /dev/null +++ b/Nerd_STF/Nerd_STF/Mathematics/Int2.cs @@ -0,0 +1,184 @@ +using Nerd_STF.Mathematics.Geometry; +using System.Collections; +using System.Diagnostics.CodeAnalysis; + +namespace Nerd_STF.Mathematics +{ + public struct Int2 : ICloneable, IComparable, IEquatable, IGroup + { + public static Int2 Down => new(0, -1); + public static Int2 Left => new(-1, 0); + public static Int2 Right => new(1, 0); + public static Int2 Up => new(0, 1); + + public static Int2 One => new(1, 1); + public static Int2 Zero => new(0, 0); + + public double Magnitude => Mathf.Sqrt(x * x + y * y); + public Int2 Normalized => (Int2)((Double2)this / Magnitude); + + public int x, y; + + public Int2(int all) : this(all, all) { } + public Int2(int x, int y) + { + this.x = x; + this.y = y; + } + public Int2(Fill fill) : this(fill(0), fill(1)) { } + + public int this[int index] + { + get => index switch + { + 0 => x, + 1 => y, + _ => throw new IndexOutOfRangeException(nameof(index)), + }; + set + { + switch (index) + { + case 0: + x = value; + break; + + case 1: + y = value; + break; + + default: throw new IndexOutOfRangeException(nameof(index)); + } + } + } + + public static Int2 Absolute(Int2 val) => + new(Mathf.Absolute(val.x), Mathf.Absolute(val.y)); + public static Int2 Average(params Int2[] vals) => Sum(vals) / vals.Length; + public static Int2 Clamp(Int2 val, Int2 min, Int2 max) => + new(Mathf.Clamp(val.x, min.x, max.x), + Mathf.Clamp(val.y, min.y, max.y)); + public static Int2 ClampMagnitude(Int2 val, int minMag, int maxMag) + { + if (maxMag < minMag) throw new ArgumentOutOfRangeException(nameof(maxMag), + nameof(maxMag) + " must be greater than or equal to " + nameof(minMag)); + double mag = val.Magnitude; + if (mag >= minMag && mag <= maxMag) return val; + val = val.Normalized; + if (mag < minMag) val *= minMag; + else if (mag > maxMag) val *= maxMag; + return val; + } + public static Int3 Cross(Int2 a, Int2 b, bool normalized = false) => + Int3.Cross(a, b, normalized); + public static Int2 Divide(Int2 num, params Int2[] vals) + { + foreach (Int2 d in vals) num /= d; + return num; + } + public static int Dot(Int2 a, Int2 b) => a.x * b.x + a.y * b.y; + public static int Dot(params Int2[] vals) + { + if (vals.Length < 1) return 0; + int x = 1, y = 1; + foreach (Int2 d in vals) + { + x *= d.x; + y *= d.y; + } + return x + y; + } + public static Int2 Lerp(Int2 a, Int2 b, double t, bool clamp = true) => + new(Mathf.Lerp(a.x, b.x, t, clamp), Mathf.Lerp(a.y, b.y, t, clamp)); + public static Int2 Median(params Int2[] vals) + { + int index = Mathf.Average(0, vals.Length - 1); + Int2 valA = vals[Mathf.Floor(index)], valB = vals[Mathf.Ceiling(index)]; + return Average(valA, valB); + } + public static Int2 Max(params Int2[] vals) + { + if (vals.Length < 1) return Zero; + Int2 val = vals[0]; + foreach (Int2 d in vals) val = d > val ? d : val; + return val; + } + public static Int2 Min(params Int2[] vals) + { + if (vals.Length < 1) return Zero; + Int2 val = vals[0]; + foreach (Int2 d in vals) val = d < val ? d : val; + return val; + } + public static Int2 Multiply(params Int2[] vals) + { + if (vals.Length < 1) return Zero; + Int2 val = One; + foreach (Int2 d in vals) val *= d; + return val; + } + public static Int2 Subtract(Int2 num, params Int2[] vals) + { + foreach (Int2 d in vals) num -= d; + return num; + } + public static Int2 Sum(params Int2[] vals) + { + Int2 val = Zero; + foreach (Int2 d in vals) val += d; + return val; + } + + public int CompareTo(Int2 other) + { + double magA = Magnitude, magB = other.Magnitude; + return magA == magB ? 0 : magA > magB ? 1 : -1; + } + public override bool Equals([NotNullWhen(true)] object? obj) + { + if (obj == null || obj.GetType() != typeof(Int2)) return false; + return Equals((Int2)obj); + } + public bool Equals(Int2 other) => x == other.x && y == other.y; + public override int GetHashCode() => x.GetHashCode() ^ y.GetHashCode(); + public override string ToString() => ToString((string?)null); + public string ToString(string? provider) => + "X: " + x.ToString(provider) + " Y: " + y.ToString(provider); + public string ToString(IFormatProvider provider) => + "X: " + x.ToString(provider) + " Y: " + y.ToString(provider); + + public object Clone() => new Int2(x, y); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + public IEnumerator GetEnumerator() + { + yield return x; + yield return y; + } + + public int[] ToArray() => new[] { x, y }; + public List ToList() => new() { x, y }; + + public static Int2 operator +(Int2 a, Int2 b) => new(a.x + b.x, a.y + b.y); + public static Int2 operator -(Int2 i) => new(-i.x, -i.y); + public static Int2 operator -(Int2 a, Int2 b) => new(a.x - b.x, a.y - b.y); + public static Int2 operator *(Int2 a, Int2 b) => new(a.x * b.x, a.y * b.y); + public static Int2 operator *(Int2 a, int b) => new(a.x * b, a.y * b); + public static Int2 operator /(Int2 a, Int2 b) => new(a.x / b.x, a.y / b.y); + public static Int2 operator /(Int2 a, int b) => new(a.x / b, a.y / b); + public static bool operator ==(Int2 a, Int2 b) => a.Equals(b); + public static bool operator !=(Int2 a, Int2 b) => !a.Equals(b); + public static bool operator >(Int2 a, Int2 b) => a.CompareTo(b) > 0; + public static bool operator <(Int2 a, Int2 b) => a.CompareTo(b) < 0; + public static bool operator >=(Int2 a, Int2 b) => a == b || a > b; + public static bool operator <=(Int2 a, Int2 b) => a == b || a < b; + + public static explicit operator Int2(Double2 val) => new((int)val.x, (int)val.y); + public static explicit operator Int2(Double3 val) => new((int)val.x, (int)val.y); + public static explicit operator Int2(Double4 val) => new((int)val.x, (int)val.y); + public static explicit operator Int2(Int3 val) => new(val.x, val.y); + public static explicit operator Int2(Int4 val) => new(val.x, val.y); + public static explicit operator Int2(Vert val) => new((int)val.position.x, (int)val.position.y); + public static implicit operator Int2(Fill fill) => new(fill); + } +} diff --git a/Nerd_STF/Nerd_STF/Mathematics/Int3.cs b/Nerd_STF/Nerd_STF/Mathematics/Int3.cs new file mode 100644 index 0000000..20b827e --- /dev/null +++ b/Nerd_STF/Nerd_STF/Mathematics/Int3.cs @@ -0,0 +1,206 @@ +using Nerd_STF.Mathematics.Geometry; +using System.Collections; +using System.Diagnostics.CodeAnalysis; + +namespace Nerd_STF.Mathematics +{ + public struct Int3 : ICloneable, IComparable, IEquatable, IGroup + { + public static Int3 Back => new(0, 0, -1); + public static Int3 Down => new(0, -1, 0); + public static Int3 Forward => new(0, 0, 1); + public static Int3 Left => new(-1, 0, 0); + public static Int3 Right => new(1, 0, 0); + public static Int3 Up => new(0, 1, 0); + + public static Int3 One => new(1, 1, 1); + public static Int3 Zero => new(0, 0, 0); + + public double Magnitude => Mathf.Sqrt(x * x + y * y + z * z); + public Int3 Normalized => (Int3)((Double3)this / Magnitude); + + public Int2 XY => new(x, y); + public Int2 XZ => new(x, z); + public Int2 YZ => new(y, z); + + public int x, y, z; + + public Int3(int all) : this(all, all, all) { } + public Int3(int x, int y) : this(x, y, 0) { } + public Int3(int x, int y, int z) + { + this.x = x; + this.y = y; + this.z = z; + } + public Int3(Fill fill) : this(fill(0), fill(1), fill(2)) { } + + public int this[int index] + { + get => index switch + { + 0 => x, + 1 => y, + 2 => z, + _ => throw new IndexOutOfRangeException(nameof(index)), + }; + set + { + switch (index) + { + case 0: + x = value; + break; + + case 1: + y = value; + break; + + case 2: + z = value; + break; + + default: throw new IndexOutOfRangeException(nameof(index)); + } + } + } + + public static Int3 Absolute(Int3 val) => + new(Mathf.Absolute(val.x), Mathf.Absolute(val.y), Mathf.Absolute(val.z)); + public static Int3 Average(params Int3[] vals) => Sum(vals) / vals.Length; + public static Int3 Clamp(Int3 val, Int3 min, Int3 max) => + new(Mathf.Clamp(val.x, min.x, max.x), + Mathf.Clamp(val.y, min.y, max.y), + Mathf.Clamp(val.z, min.z, max.z)); + public static Int3 ClampMagnitude(Int3 val, int minMag, int maxMag) + { + if (maxMag < minMag) throw new ArgumentOutOfRangeException(nameof(maxMag), + nameof(maxMag) + " must be greater than or equal to " + nameof(minMag)); + double mag = val.Magnitude; + if (mag >= minMag && mag <= maxMag) return val; + val = val.Normalized; + if (mag < minMag) val *= minMag; + else if (mag > maxMag) val *= maxMag; + return val; + } + public static Int3 Cross(Int3 a, Int3 b, bool normalized = false) + { + Int3 val = new(a.y * b.z - b.y * a.z, + b.x * a.z - a.x * b.z, + a.x * b.y - b.x * a.y); + return normalized ? val.Normalized : val; + } + public static Int3 Divide(Int3 num, params Int3[] vals) + { + foreach (Int3 d in vals) num /= d; + return num; + } + public static int Dot(Int3 a, Int3 b) => a.x * b.x + a.y * b.y + a.z * b.z; + public static int Dot(params Int3[] vals) + { + if (vals.Length < 1) return 0; + int x = 1, y = 1, z = 1; + foreach (Int3 d in vals) + { + x *= d.x; + y *= d.y; + z *= d.z; + } + return x + y + z; + } + public static Int3 Lerp(Int3 a, Int3 b, double t, bool clamp = true) => + new(Mathf.Lerp(a.x, b.x, t, clamp), Mathf.Lerp(a.y, b.y, t, clamp), Mathf.Lerp(a.z, b.z, t, clamp)); + public static Int3 Median(params Int3[] vals) + { + int index = Mathf.Average(0, vals.Length - 1); + Int3 valA = vals[Mathf.Floor(index)], valB = vals[Mathf.Ceiling(index)]; + return Average(valA, valB); + } + public static Int3 Max(params Int3[] vals) + { + if (vals.Length < 1) return Zero; + Int3 val = vals[0]; + foreach (Int3 d in vals) val = d > val ? d : val; + return val; + } + public static Int3 Min(params Int3[] vals) + { + if (vals.Length < 1) return Zero; + Int3 val = vals[0]; + foreach (Int3 d in vals) val = d < val ? d : val; + return val; + } + public static Int3 Multiply(params Int3[] vals) + { + if (vals.Length < 1) return Zero; + Int3 val = One; + foreach (Int3 d in vals) val *= d; + return val; + } + public static Int3 Subtract(Int3 num, params Int3[] vals) + { + foreach (Int3 d in vals) num -= d; + return num; + } + public static Int3 Sum(params Int3[] vals) + { + Int3 val = Zero; + foreach (Int3 d in vals) val += d; + return val; + } + + public int CompareTo(Int3 other) + { + double magA = Magnitude, magB = other.Magnitude; + return magA == magB ? 0 : magA > magB ? 1 : -1; + } + public override bool Equals([NotNullWhen(true)] object? obj) + { + if (obj == null || obj.GetType() != typeof(Int3)) return false; + return Equals((Int3)obj); + } + public bool Equals(Int3 other) => x == other.x && y == other.y && z == other.z; + public override int GetHashCode() => x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode(); + public override string ToString() => ToString((string?)null); + public string ToString(string? provider) => + "X: " + x.ToString(provider) + " Y: " + y.ToString(provider) + " Z: " + z.ToString(provider); + public string ToString(IFormatProvider provider) => + "X: " + x.ToString(provider) + " Y: " + y.ToString(provider) + " Z: " + z.ToString(provider); + + public object Clone() => new Int3(x, y, z); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + public IEnumerator GetEnumerator() + { + yield return x; + yield return y; + yield return z; + } + + public int[] ToArray() => new[] { x, y, z }; + public List ToList() => new() { x, y, z }; + + public static Int3 operator +(Int3 a, Int3 b) => new(a.x + b.x, a.y + b.y, a.z + b.z); + public static Int3 operator -(Int3 i) => new(-i.x, -i.y, -i.z); + public static Int3 operator -(Int3 a, Int3 b) => new(a.x - b.x, a.y - b.y, a.z - b.z); + public static Int3 operator *(Int3 a, Int3 b) => new(a.x * b.x, a.y * b.y, a.z * b.z); + public static Int3 operator *(Int3 a, int b) => new(a.x * b, a.y * b, a.z * b); + public static Int3 operator /(Int3 a, Int3 b) => new(a.x / b.x, a.y / b.y, a.z / b.z); + public static Int3 operator /(Int3 a, int b) => new(a.x / b, a.y / b, a.z / b); + public static bool operator ==(Int3 a, Int3 b) => a.Equals(b); + public static bool operator !=(Int3 a, Int3 b) => !a.Equals(b); + public static bool operator >(Int3 a, Int3 b) => a.CompareTo(b) > 0; + public static bool operator <(Int3 a, Int3 b) => a.CompareTo(b) < 0; + public static bool operator >=(Int3 a, Int3 b) => a == b || a > b; + public static bool operator <=(Int3 a, Int3 b) => a == b || a < b; + + public static explicit operator Int3(Double2 val) => new((int)val.x, (int)val.y, 0); + public static explicit operator Int3(Double3 val) => new((int)val.x, (int)val.y, (int)val.z); + public static explicit operator Int3(Double4 val) => new((int)val.x, (int)val.y, (int)val.z); + public static implicit operator Int3(Int2 val) => new(val.x, val.y, 0); + public static explicit operator Int3(Int4 val) => new(val.x, val.y, val.z); + public static explicit operator Int3(Vert val) => new((int)val.position.x, (int)val.position.y, + (int)val.position.z); + public static implicit operator Int3(Fill fill) => new(fill); + } +} diff --git a/Nerd_STF/Nerd_STF/Mathematics/Int4.cs b/Nerd_STF/Nerd_STF/Mathematics/Int4.cs new file mode 100644 index 0000000..c58bc39 --- /dev/null +++ b/Nerd_STF/Nerd_STF/Mathematics/Int4.cs @@ -0,0 +1,222 @@ +using Nerd_STF.Mathematics.Geometry; +using System.Collections; +using System.Diagnostics.CodeAnalysis; + +namespace Nerd_STF.Mathematics +{ + public struct Int4 : ICloneable, IComparable, IEquatable, IGroup + { + public static Int4 Back => new(0, 0, -1, 0); + public static Int4 Deep => new(0, 0, 0, -1); + public static Int4 Down => new(0, -1, 0, 0); + public static Int4 Far => new(0, 0, 0, 1); + public static Int4 Forward => new(0, 0, 1, 0); + public static Int4 Left => new(-1, 0, 0, 0); + public static Int4 Right => new(1, 0, 0, 0); + public static Int4 Up => new(0, 1, 0, 0); + + public static Int4 One => new(1, 1, 1, 1); + public static Int4 Zero => new(0, 0, 0, 0); + + public double Magnitude => Mathf.Sqrt(x * x + y * y + z * z + w * w); + public Int4 Normalized => (Int4)((Double4)this / Magnitude); + + public Int2 XY => new(x, y); + public Int2 XZ => new(x, z); + public Int2 XW => new(x, w); + public Int2 YW => new(y, w); + public Int2 YZ => new(y, z); + public Int2 ZW => new(z, w); + + public Int3 XYW => new(x, y, w); + public Int3 XYZ => new(x, y, z); + public Int3 YZW => new(y, z, w); + public Int3 XZW => new(x, z, w); + + public int x, y, z, w; + + public Int4(int all) : this(all, all, all, all) { } + public Int4(int x, int y) : this(x, y, 0, 0) { } + public Int4(int x, int y, int z) : this(x, y, z, 0) { } + public Int4(int x, int y, int z, int w) + { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } + public Int4(Fill fill) : this(fill(0), fill(1), fill(2), fill(3)) { } + + public int this[int index] + { + get => index switch + { + 0 => x, + 1 => y, + 2 => z, + 3 => w, + _ => throw new IndexOutOfRangeException(nameof(index)), + }; + set + { + switch (index) + { + case 0: + x = value; + break; + + case 1: + y = value; + break; + + case 2: + z = value; + break; + + case 3: + w = value; + break; + + default: throw new IndexOutOfRangeException(nameof(index)); + } + } + } + + public static Int4 Absolute(Int4 val) => + new(Mathf.Absolute(val.x), Mathf.Absolute(val.y), Mathf.Absolute(val.z), Mathf.Absolute(val.w)); + public static Int4 Average(params Int4[] vals) => Sum(vals) / vals.Length; + public static Int4 Clamp(Int4 val, Int4 min, Int4 max) => + new(Mathf.Clamp(val.x, min.x, max.x), + Mathf.Clamp(val.y, min.y, max.y), + Mathf.Clamp(val.z, min.z, max.z), + Mathf.Clamp(val.w, min.w, max.w)); + public static Int4 ClampMagnitude(Int4 val, int minMag, int maxMag) + { + if (maxMag < minMag) throw new ArgumentOutOfRangeException(nameof(maxMag), + nameof(maxMag) + " must be greater than or equal to " + nameof(minMag)); + double mag = val.Magnitude; + if (mag >= minMag && mag <= maxMag) return val; + val = val.Normalized; + if (mag < minMag) val *= minMag; + else if (mag > maxMag) val *= maxMag; + return val; + } + public static Int4 Divide(Int4 num, params Int4[] vals) + { + foreach (Int4 d in vals) num /= d; + return num; + } + public static int Dot(Int4 a, Int4 b) => a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; + public static int Dot(params Int4[] vals) + { + if (vals.Length < 1) return 0; + int x = 1, y = 1, z = 1, w = 1; + foreach (Int4 d in vals) + { + x *= d.x; + y *= d.y; + z *= d.z; + w *= d.w; + } + return x + y + z; + } + public static Int4 Lerp(Int4 a, Int4 b, double t, bool clamp = true) => + new(Mathf.Lerp(a.x, b.x, t, clamp), Mathf.Lerp(a.y, b.y, t, clamp), Mathf.Lerp(a.z, b.z, t, clamp), + Mathf.Lerp(a.w, b.w, t, clamp)); + public static Int4 Median(params Int4[] vals) + { + int index = Mathf.Average(0, vals.Length - 1); + Int4 valA = vals[Mathf.Floor(index)], valB = vals[Mathf.Ceiling(index)]; + return Average(valA, valB); + } + public static Int4 Max(params Int4[] vals) + { + if (vals.Length < 1) return Zero; + Int4 val = vals[0]; + foreach (Int4 d in vals) val = d > val ? d : val; + return val; + } + public static Int4 Min(params Int4[] vals) + { + if (vals.Length < 1) return Zero; + Int4 val = vals[0]; + foreach (Int4 d in vals) val = d < val ? d : val; + return val; + } + public static Int4 Multiply(params Int4[] vals) + { + if (vals.Length < 1) return Zero; + Int4 val = One; + foreach (Int4 d in vals) val *= d; + return val; + } + public static Int4 Subtract(Int4 num, params Int4[] vals) + { + foreach (Int4 d in vals) num -= d; + return num; + } + public static Int4 Sum(params Int4[] vals) + { + Int4 val = Zero; + foreach (Int4 d in vals) val += d; + return val; + } + + public int CompareTo(Int4 other) + { + double magA = Magnitude, magB = other.Magnitude; + return magA == magB ? 0 : magA > magB ? 1 : -1; + } + public override bool Equals([NotNullWhen(true)] object? obj) + { + if (obj == null || obj.GetType() != typeof(Int4)) return false; + return Equals((Int4)obj); + } + public bool Equals(Int4 other) => x == other.x && y == other.y && z == other.z && w == other.w; + public override int GetHashCode() => x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode(); + public override string ToString() => ToString((string?)null); + public string ToString(string? provider) => + "X: " + x.ToString(provider) + " Y: " + y.ToString(provider) + " Z: " + z.ToString(provider) + + " W: " + w.ToString(provider); + public string ToString(IFormatProvider provider) => + "X: " + x.ToString(provider) + " Y: " + y.ToString(provider) + " Z: " + z.ToString(provider) + + " W: " + w.ToString(provider); + + public object Clone() => new Int4(x, y, z, w); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + public IEnumerator GetEnumerator() + { + yield return x; + yield return y; + yield return z; + yield return w; + } + + public int[] ToArray() => new[] { x, y, z, w }; + public List ToList() => new() { x, y, z, w }; + + public static Int4 operator +(Int4 a, Int4 b) => new(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w); + public static Int4 operator -(Int4 d) => new(-d.x, -d.y, -d.z, -d.w); + public static Int4 operator -(Int4 a, Int4 b) => new(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w); + public static Int4 operator *(Int4 a, Int4 b) => new(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w); + public static Int4 operator *(Int4 a, int b) => new(a.x * b, a.y * b, a.z * b, a.w * b); + public static Int4 operator /(Int4 a, Int4 b) => new(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w); + public static Int4 operator /(Int4 a, int b) => new(a.x / b, a.y / b, a.z / b, a.w / b); + public static bool operator ==(Int4 a, Int4 b) => a.Equals(b); + public static bool operator !=(Int4 a, Int4 b) => !a.Equals(b); + public static bool operator >(Int4 a, Int4 b) => a.CompareTo(b) > 0; + public static bool operator <(Int4 a, Int4 b) => a.CompareTo(b) < 0; + public static bool operator >=(Int4 a, Int4 b) => a == b || a > b; + public static bool operator <=(Int4 a, Int4 b) => a == b || a < b; + + public static explicit operator Int4(Double2 val) => new((int)val.x, (int)val.y, 0, 0); + public static explicit operator Int4(Double3 val) => new((int)val.x, (int)val.y, (int)val.z, 0); + public static explicit operator Int4(Double4 val) => new((int)val.x, (int)val.y, (int)val.z, (int)val.w); + public static implicit operator Int4(Int2 val) => new(val.x, val.y, 0, 0); + public static implicit operator Int4(Int3 val) => new(val.x, val.y, val.z, 0); + public static explicit operator Int4(Vert val) => new((int)val.position.x, (int)val.position.y, + (int)val.position.z, 0); + public static implicit operator Int4(Fill fill) => new(fill); + } +} diff --git a/Nerd_STF/Nerd_STF/Mathematics/Mathf.cs b/Nerd_STF/Nerd_STF/Mathematics/Mathf.cs new file mode 100644 index 0000000..2fd958c --- /dev/null +++ b/Nerd_STF/Nerd_STF/Mathematics/Mathf.cs @@ -0,0 +1,205 @@ +namespace Nerd_STF.Mathematics +{ + public static class Mathf + { + public const double DegToRad = 0.0174532925199; // Pi / 180 + public const double E = 2.71828182846; + public const double GoldenRatio = 1.61803398875; // (1 + Sqrt(5)) / 2 + public const double HalfPi = 1.57079632679; // Pi / 2 + public const double Pi = 3.14159265359; + public const double RadToDeg = 57.2957795131; // 180 / Pi + public const double Tau = 6.28318530718; // 2 * Pi + + public static double Absolute(double val) => val < 0 ? -val : val; + public static int Absolute(int val) => val < 0 ? -val : val; + + public static double ArcCos(double value) => -ArcSin(value) + HalfPi; + + public static double ArcCot(double value) => ArcCos(value / Sqrt(1 + value * value)); + + public static double ArcCsc(double value) => ArcSin(1 / value); + + public static double ArcSec(double value) => ArcCos(1 / value); + + // Maybe one day I'll have a polynomial for this, but the RMSE for an order 10 polynomial is only 0.00876. + public static double ArcSin(double value) => Math.Asin(value); + + public static double ArcTan(double value) => ArcSin(value / Sqrt(1 + value * value)); + + public static double Average(params double[] vals) => Sum(vals) / vals.Length; + public static int Average(params int[] vals) => Sum(vals) / vals.Length; + + public static int Ceiling(double val) => (int)(val + (1 - (val % 1))); + + public static double Clamp(double val, double min, double max) + { + if (max < min) throw new ArgumentOutOfRangeException(nameof(max), + nameof(max) + " must be greater than or equal to " + nameof(min)); + val = val < min ? min : val; + val = val > max ? max : val; + return val; + } + public static int Clamp(int val, int min, int max) + { + if (max < min) throw new ArgumentOutOfRangeException(nameof(max), + nameof(max) + " must be greater than or equal to " + nameof(min)); + val = val < min ? min : val; + val = val > max ? max : val; + return val; + } + + public static double Cos(double radians) => Sin(radians + HalfPi); + + public static double Cot(double radians) => Cos(radians) / Sin(radians); + + public static double Csc(double radians) => 1 / Sin(radians); + + public static double Divide(double val, params double[] dividends) + { + foreach (double d in dividends) val /= d; + return val; + } + public static int Divide(int val, params int[] dividends) + { + foreach (int i in dividends) val /= i; + return val; + } + + public static int Factorial(int amount) + { + if (amount < 0) return 0; + int val = 1; + for (int i = 2; i <= amount; i++) val *= i; + return val; + } + + public static int Floor(double val) => (int)(val - (val % 1)); + + public static double Lerp(double a, double b, double t, bool clamp = true) + { + double v = a + t * (b - a); + if (clamp) v = Clamp(v, a, b); + return v; + } + public static int Lerp(int a, int b, double value, bool clamp = true) => Floor(Lerp(a, b, value, clamp)); + + public static double Max(params double[] vals) + { + if (vals.Length < 1) return 0; + double val = vals[0]; + foreach (double d in vals) val = d > val ? d : val; + return val; + } + public static int Max(params int[] vals) + { + if (vals.Length < 1) return 0; + int val = vals[0]; + foreach (int i in vals) val = i > val ? i : val; + return val; + } + + public static double Median(params double[] vals) + { + double index = Average(0, vals.Length - 1); + double valA = vals[Floor(index)], valB = vals[Ceiling(index)]; + return Average(valA, valB); + } + public static int Median(params int[] vals) => vals[Floor(Average(0, vals.Length - 1))]; + + public static double Min(params double[] vals) + { + if (vals.Length < 1) return 0; + double val = vals[0]; + foreach (double d in vals) val = d < val ? d : val; + return val; + } + public static int Min(params int[] vals) + { + if (vals.Length < 1) return 0; + int val = vals[0]; + foreach (int i in vals) val = i < val ? i : val; + return val; + } + + public static double Multiply(params double[] vals) + { + if (vals.Length < 1) return 0; + double val = 1; + foreach (double d in vals) val *= d; + return val; + } + public static int Multiply(params int[] vals) + { + if (vals.Length < 1) return 0; + int val = 1; + foreach (int i in vals) val *= i; + return val; + } + + public static double Power(double num, double pow) => Math.Pow(num, pow); + public static int Power(int num, int pow) + { + if (pow < 0) return 0; + int val = 1; + for (int i = 0; i < Absolute(pow); i++) val *= num; + return val; + } + + public static double Root(double value, double index) => Math.Exp(index * Math.Log(value)); + + public static double Round(double num) => num % 1 >= 0.5 ? Ceiling(num) : Floor(num); + public static double Round(double num, double nearest) => nearest * Round(num / nearest); + public static int RoundInt(double num) => (int)Round(num); + + public static double Sec(double radians) => 1 / Cos(radians); + + public static double Sin(double radians) + { + // Really close polynomial to sin(x) (when modded by 2pi). RMSE of 0.000003833 + const double a = 0.000013028, + b = 0.999677, + c = 0.00174164, + d = -0.170587, + e = 0.0046494, + f = 0.00508955, + g = 0.00140205, + h = -0.000577413, + i = 0.0000613134, + j = -0.00000216852; + double x = radians % Tau; + + return + a + (b * x) + (c * x * x) + (d * x * x * x) + (e * x * x * x * x) + (f * x * x * x * x * x) + + (g * x * x * x * x * x * x) + (h * x * x * x * x * x * x * x) + (i * x * x * x * x * x * x * x * x) + + (j * x * x * x * x * x * x * x * x * x); + } + + public static double Sqrt(double value) => Root(value, 2); + + public static double Subtract(double num, params double[] vals) + { + foreach (double d in vals) num -= d; + return num; + } + public static int Subtract(int num, params int[] vals) + { + foreach (int i in vals) num -= i; + return num; + } + + public static double Sum(params double[] vals) + { + double val = 0; + foreach (double d in vals) val += d; + return val; + } + public static int Sum(params int[] vals) + { + int val = 0; + foreach (int i in vals) val += i; + return val; + } + + public static double Tan(double radians) => Sin(radians) / Cos(radians); + } +} diff --git a/Nerd_STF/Nerd_STF/bin/Release/net6.0/ref/Nerd_STF.dll b/Nerd_STF/Nerd_STF/bin/Release/net6.0/ref/Nerd_STF.dll new file mode 100644 index 0000000000000000000000000000000000000000..c5862fd3e938691fb20655a86dc1f9d0365f32f9 GIT binary patch literal 4608 zcmeHKPiz!b82>%k)}_$e#!B!{V6Yf9lF62WkqWYHw~NKn*6spYP1@P*>oPh!vzeJK z)PvT8#&9y82=Rai?nFHh6B7@bm>8moG2v*8M*=qv#)!Z7W@dNVA_q?f__p(V@B1^~ z`@ZkZd~bSu?h|YVkl}UvHgJWbqP)ht!z$H1yT0zhS6i;`z9J^C?k=CU1Eb-4HQ%Zm zRm*j~(5OhmZ@Px<8inbSQTG<5+1=f>Cw4tE4or#+{@8cpYO>mIc*@u+azG~~*+@D^ zI~|mv`Ch1TQxvz7sQ5KqB*x5UEPM#`>c93FvynBj^gFHQ3&4}A5bJ3b*hbm)0`=>4 zcjNP|(6v>T{3|JYv%YLEl4o>Ca!KM&%<{mf8OpOE1q&Sn3Up0WT~cIFZTf*h&22Pal1Lvwo4jer(QQ&xu{I`l9b-W5kMQmZ> zXg{z;F@K67Y>(paj&wSbt(>b%<)tnl6w%m;pYWyV#37;ZIb0ME;}@zrk=2qi<|rQ! z9}_P_VO`@njW;zO*7&>lK)Z~NEL8!)*aiAxBX)6Z zH6JAQ;-JP6jT0JQ)A)u)OQXq*cEZFXc!u}{io^k)W+t9TnK*=V#FucMIEG8aSMde0 zq~&iCGpk887?`F$V)}S_6pzOm4r7iL1cNwq+*@oq@?}g(e{sH4E~2y>BhVHr>#! zOB7_KS*uwUM~;Nt)=D#!7zqMduQ)4ZJ4}nqmS2-$k>3mQjOV|z(Y|Oq@}%?w+jBQ6 zC)_2^uUjFNmh-PxW1hQY*P6bzYdab9>J8h`!ddB9XZ0*->ywCQe5P9s+lpDaBz@^t zWn$4*B@*S^a#z}lxHMWG+7;We!<2Sy{meKMz7MSun~RPUm$_AKx#Y;I${l7k^!!9# zu&tWw1)*IH5>dRm8Ko@!lJuADstn?t;zHa~veT8f=`q>x4QE5f5F)$Tfau_)uTQZ( z*~>@f-|zdiYd9<7Z?&E3xi4?pe#*BRQ=U71wkjJc%JOO7I}-@n@r5O2)XQ=}V23$1 zULNy&InrqCjZ;6o{DPUIm!AICqfxMfhGVTv@kv29*J?d{*e380cTie^+$eXL(* zqr?A|MD;6R2e7&}tf-r_pc~}MPMsaEFR(91`>I5o?NTcgxvHRABgs#3Q8n(iR#e9s z`tTS*ll2HwQQo|v3-xK<$Xl? S=zqbt4%|mMKS;Gzfqwutn#&FV literal 0 HcmV?d00001 diff --git a/README.md b/README.md index a77e040..c800eef 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,28 @@ # Nerd_STF -Nerd_STF is a C# library I made that adds general things I think I (and whoever uses it) will use. I will add onto this library as time passes. Nerd_STF runs on .NET 5.0. Giving me suggestions and calling out bugs would be much appreciated! +## What is it? + +Nerd_STF is a C# library that runs on .Net 6.0, and contains added structures and classes I feel would help the default C# library package. Feel free to do with it what you would like. + +Nerd_STF has recently been remade, completely rebuilding many of its topics. + +## What does it include? +Nerd_STF will include math structures as well as other computer science topics. Right now, it is mainly focused on mathematics, but will branch out in the future. It currently contains things like lists of 3 doubles or ints, or `Vert`, `Line`, and `Triangle` classes, that are rich in implementation. + +## What about Nerd_STF Versions `2021`? +Nerd_STF `2021` used an different version scheme, based on the year, as you might have guessed (it is not the year `2` right now), and while I will be keeping the `2021` versions up, I wouldn't recommend using them, and the code is old code, written by a more naive me. Hell, I wrote an entire `List` class there before I knew of the `System.Collections.Generic.List` class that did literally everything for me already. Oh well. So, keep that in mind when you check out those versions of the library. + +## How do I install it? +Well, unfortunately I don't have a nuget package for this library yet (maybe in the future), so here, I'll walk you through installing it in Visual Studio. + +Step 1: Find the `.dll` for this library, found in `/Nerd_STF/Nerd_STF/bin/Release/net6.0/ref/Nerd_STF.dll`. You can either move it, or simply remember where it is. +Step 2: Search for "Add Project Reference" in the Visual Studio 2019 or 2022 search bar. +Step 3: Click the "Browse" tab on the left, then click the "Browse" button on the bottom-right. +Step 4: Select the `.dll` we found earlier. +Step 5: Click OK. + +This is what happens the first time you import it. Any other times, simply go to the "Add Project Reference" Window, then the "Browse" tab, and the `.dll` will already be in the list in the middle. Find it, and click the box on its left. Then click OK. + +--- + +I hope you enjoy using Nerd_STF! diff --git a/Scripts/Files.cs b/Scripts/Files.cs deleted file mode 100644 index 1fb28f7..0000000 --- a/Scripts/Files.cs +++ /dev/null @@ -1,261 +0,0 @@ -using System; -using System.Text; -using Nerd_STF.Lists; -using System.IO; -using System.Runtime.Serialization.Formatters.Binary; - -namespace Nerd_STF.File.Saving -{ - [Obsolete(nameof(BinaryFile) + " uses the " + nameof(BinaryFormatter) + ", which is considered dangerous. Go to 'https://aka.ms/binaryformatter/' for more information.")] - [Serializable] - public class BinaryFile - { - public object Data { get; set; } - public string Path { get; set; } - - public BinaryFile(string path) => Path = path; - public BinaryFile(string path, object data) - { - Data = data; - Path = path; - } - - public static BinaryFile Load(string path) - { - BinaryFile file = new(path); - FileStream stream = new(path, FileMode.Open); - BinaryFormatter formatter = new(); - file.Data = formatter.Deserialize(stream); - stream.Close(); - return file; - } - - public void Erase() => Data = null; - public void Load() - { - FileStream stream = new(Path, FileMode.Open); - BinaryFormatter formatter = new(); - Data = formatter.Deserialize(stream); - stream.Close(); - } - public void Save() - { - FileStream stream = new(Path, FileMode.Create); - BinaryFormatter formatter = new(); - formatter.Serialize(stream, Data); - stream.Close(); - } - } - [Obsolete(nameof(BinaryFile) + " uses the " + nameof(BinaryFormatter) + ", which is considered dangerous. Go to 'https://aka.ms/binaryformatter/' for more information.")] - [Serializable] - public class BinaryFile - { - public T Data { get; set; } - public string Path { get; set; } - - public BinaryFile(string path) => Path = path; - public BinaryFile(string path, T data) - { - Data = data; - Path = path; - } - - public static BinaryFile Load(string path) - { - BinaryFile file = new(path); - FileStream stream = new(path, FileMode.Open); - BinaryFormatter formatter = new(); - file.Data = (T)formatter.Deserialize(stream); - stream.Close(); - return file; - } - - public void Erase() => Data = default; - public void Load() - { - FileStream stream = new(Path, FileMode.Open); - BinaryFormatter formatter = new(); - Data = (T)formatter.Deserialize(stream); - stream.Close(); - } - public void Save() - { - FileStream stream = new(Path, FileMode.Create); - BinaryFormatter formatter = new(); - formatter.Serialize(stream, Data); - stream.Close(); - } - } - [Serializable] - public class ByteFile : File> - { - public byte this[int index] - { - get - { - if (index < 0 || index >= Data.Length) throw new ArgumentOutOfRangeException(nameof(index)); - return Data[index]; - } - set { Data[index] = value; } - } - - public ByteFile(string path) => Path = path; - public ByteFile(string path, params byte[] data) - { - Data = new List(data); - Path = path; - } - public ByteFile(string path, List data) - { - Data = data; - Path = path; - } - - public static ByteFile Load(string path) - { - ByteFile file = new(path); - FileStream stream = new(file.Path, FileMode.Open); - byte[] b = new byte[stream.Length]; - while (stream.Read(b, 0, b.Length) > 0) ; - file.Data = new(b); - stream.Close(); - return file; - } - - public override void Erase() => Data = new(); - public void Fill(int length, byte fill = 0) => Data = new List(length, fill); - public override void Load(bool erase = true) - { - if (erase) Erase(); - FileStream stream = new(Path, FileMode.Open); - byte[] b = new byte[stream.Length]; - while (stream.Read(b, 0, b.Length) > 0) ; - Data.AddRange(b); - stream.Close(); - } - public void Remove(int start, int amount) - { - List old = Data; - Data = new List(old.Length - amount); - for (int i = 0; i < old.Length; i++) - { - if (i > start && i < start + amount) i = start + amount; - Data[i] = old[i]; - } - } - public override void Save() - { - FileStream stream = new(Path, FileMode.Create); - stream.Write(Data.ToArray(), 0, Data.Length); - stream.Close(); - } - public override bool TryLoad(out File> file) - { - bool success = false; - try - { - file = new ByteFile(Path); - FileStream stream = new(file.Path, FileMode.Open); - byte[] b = new byte[stream.Length]; - while (stream.Read(b, 0, b.Length) > 0) ; - file.Data.AddRange(b); - stream.Close(); - success = true; - } - catch { file = null; } - - return success; - } - public void Write(byte write, bool toFile = false) - { - Data += write; - if (toFile) Save(); - } - public override void Write(List write, bool toFile = false) - { - Data += write; - if (toFile) Save(); - } - } - [Serializable] - public class TextFile : File - { - public TextFile(string path) => Path = path; - public TextFile(string path, string data) - { - Data = data; - Path = path; - } - - public static TextFile Load(string path) - { - TextFile file = new(path); - FileStream stream = new(file.Path, FileMode.Open); - byte[] b = new byte[stream.Length]; - while (stream.Read(b, 0, b.Length) > 0) ; - file.Data += Encoding.Default.GetString(b); - stream.Close(); - return file; - } - - public override void Erase() => Data = ""; - public override void Load(bool erase = true) - { - if (erase) Erase(); - FileStream stream = new(Path, FileMode.Open); - byte[] b = new byte[stream.Length]; - while (stream.Read(b, 0, b.Length) > 0) ; - Data += Encoding.Default.GetString(b); - stream.Close(); - } - public void Remove(int start, int amount) => Data = Data.Remove(start, amount); - public override void Save() - { - FileStream stream = new(Path, FileMode.Create); - byte[] b = Encoding.Default.GetBytes(Data); - stream.Write(b, 0, b.Length); - stream.Close(); - } - public override bool TryLoad(out File file) - { - bool success = false; - try - { - file = new TextFile(Path); - FileStream stream = new(file.Path, FileMode.Open); - byte[] b = new byte[stream.Length]; - while (stream.Read(b, 0, b.Length) > 0) ; - file.Data += Encoding.Default.GetString(b); - stream.Close(); - success = true; - } - catch { file = null; } - - return success; - } - public void Write(char write, bool toFile = false) - { - Data += write; - if (toFile) Save(); - } - public override void Write(string write, bool toFile = false) - { - Data += write; - if (toFile) Save(); - } - } - - [Serializable] - public abstract class File - { - public T Data { get; set; } - public bool Exists => System.IO.File.Exists(Path); - public string Path { get; set; } - - public abstract void Erase(); - public abstract void Load(bool erase = true); - public abstract void Save(); - public abstract bool TryLoad(out File file); - public abstract void Write(T write, bool toFile = false); - } -} \ No newline at end of file diff --git a/Scripts/General.cs b/Scripts/General.cs deleted file mode 100644 index c5640da..0000000 --- a/Scripts/General.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System; -using System.Text; - -namespace Nerd_STF -{ - public static class Hashes - { - public static int Default(object obj) => obj.GetHashCode(); - public static byte[] MD5(byte[] input) => System.Security.Cryptography.MD5.Create().ComputeHash(input); - public static string MD5(string input) - { - System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create(); - - byte[] inputB = Encoding.ASCII.GetBytes(input); - byte[] hash = md5.ComputeHash(inputB); - - string s = ""; - for (int i = 0; i < hash.Length; i++) s += hash[i].ToString("X2"); - return s; - } - public static uint SchechterTurbulence(uint seed) - { - seed ^= 2747636419u; - seed *= 2654435769u; - seed ^= seed >> 16; - seed *= 2654435769u; - seed ^= seed >> 16; - seed *= 2654435769u; - - return seed; - } - public static byte[] SHA1(byte[] input) => System.Security.Cryptography.SHA1.Create().ComputeHash(input); - public static string SHA1(string input) - { - System.Security.Cryptography.SHA1 sha1 = System.Security.Cryptography.SHA1.Create(); - - byte[] inputB = Encoding.ASCII.GetBytes(input); - byte[] hash = sha1.ComputeHash(inputB); - - string s = ""; - for (int i = 0; i < hash.Length; i++) s += hash[i].ToString("X2"); - return s; - } - public static byte[] SHA256(byte[] input) => System.Security.Cryptography.SHA256.Create().ComputeHash(input); - public static string SHA256(string input) - { - System.Security.Cryptography.SHA256 sha256 = System.Security.Cryptography.SHA256.Create(); - - byte[] inputB = Encoding.ASCII.GetBytes(input); - byte[] hash = sha256.ComputeHash(inputB); - - string s = ""; - for (int i = 0; i < hash.Length; i++) s += hash[i].ToString("X2"); - return s; - } - public static byte[] SHA384(byte[] input) => System.Security.Cryptography.SHA384.Create().ComputeHash(input); - public static string SHA384(string input) - { - System.Security.Cryptography.SHA384 sha384 = System.Security.Cryptography.SHA384.Create(); - - byte[] inputB = Encoding.ASCII.GetBytes(input); - byte[] hash = sha384.ComputeHash(inputB); - - string s = ""; - for (int i = 0; i < hash.Length; i++) s += hash[i].ToString("X2"); - return s; - } - public static byte[] SHA512(byte[] input) => System.Security.Cryptography.SHA512.Create().ComputeHash(input); - public static string SHA512(string input) - { - System.Security.Cryptography.SHA512 sha512 = System.Security.Cryptography.SHA512.Create(); - - byte[] inputB = Encoding.ASCII.GetBytes(input); - byte[] hash = sha512.ComputeHash(inputB); - - string s = ""; - for (int i = 0; i < hash.Length; i++) s += hash[i].ToString("X2"); - return s; - } - } - - public static class Misc - { - public static string PlaceMaker(int num) - { - return num.ToString()[^1] switch - { - '1' => num + "st", - '2' => num + "nd", - '3' => num + "rd", - _ => num + "th", - }; - } - } - - public static class Stats - { - public static readonly string Creator = "That_One_Nerd"; - public static readonly string[] Links = new[] - { - "Discord: https://discord.gg/ySXMtWDTYY/", - "Github: https://https://github.com/that-one-nerd", - "Itch: https://that-one-nerd.itch.io/" - }; - public static readonly string Version = "2021.2"; - } - - [Serializable] - public struct Optional - { - public bool Exists => Value != null; - public T Value { get; internal set; } - - public Optional(T input) => Value = input; - - public static explicit operator T(Optional input) => input.Value; - public static explicit operator Optional(T input) => new(input); - } -} \ No newline at end of file diff --git a/Scripts/Lists.cs b/Scripts/Lists.cs deleted file mode 100644 index 356295a..0000000 --- a/Scripts/Lists.cs +++ /dev/null @@ -1,1095 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using Nerd_STF.Mathematics; - -namespace Nerd_STF.Lists -{ - [Serializable] - public class List : IEnumerable, IEnumerable - { - public static List Empty => new(); - - internal T[] array; - - public int this[T item] - { - get => FindIndex(item); - set => Insert(value, item); - } - public T this[int index] - { - get => array[index]; - set => array[index] = value; - } - - public List Duplicate => new(array); - public bool IsEmpty => array == Array.Empty(); - public bool IsNull => array == null; - public bool IsNullOrEmpty => IsNull || IsEmpty; - public int Length => array.Length; - - public List() => array = Array.Empty(); - public List(params T[] items) => array = items; - public List(int length) => array = new T[length]; - public List(int length, T itemAll) - { - array = new T[length]; - for (int i = 0; i < array.Length; i++) array[i] = itemAll; - } - public List(IEnumerable items) - { - int length = 0; - foreach (object _ in items) length++; - array = new T[length]; - - AddRange(items); - } - public List(IEnumerable items) - { - int length = 0; - foreach (object _ in items) length++; - if (length == 0) array = Array.Empty(); - - AddRange(items); - } - public List(List list) => array = list.array; - - public void Add() => Add(default); - public void Add(T item) - { - if (array == null || array == Array.Empty()) array = new T[1] { item }; - else - { - T[] old = array; - array = new T[old.Length + 1]; - for (int i = 0; i < old.Length; i++) array[i] = old[i]; - array[old.Length] = item; - } - } - public void AddRange(IEnumerable items) { foreach (T t in items) Add(t); } - public void AddRange(IEnumerable items) { foreach (T t in items) Add(t); } - public void AddRange(List items) { foreach (T t in items) Add(t); } - public void AddRange(params T[] items) { foreach (T t in items) Add(t); } - public bool Any(Predicate predicate) - { - foreach (T t in array) if (predicate.Invoke(t)) return true; - return false; - } - public bool Any(T match) - { - foreach (T t in array) if (t.Equals(match)) return true; - return false; - } - public void Clear(bool resetSize = false) - { - if (resetSize) array = Array.Empty(); - else { for (int i = 0; i < array.Length; i++) array[i] = default; } - } - public bool Contains(Predicate predicate) - { - foreach (T t in array) if (predicate.Invoke(t)) return true; - return false; - } - public bool Contains(T match) - { - foreach (T t in array) if (t.Equals(match)) return true; - return false; - } - public int Count() - { - int r = 0; - foreach (T _ in array) r++; - return r; - } - public int Count(Predicate predicate) - { - if (!Contains(predicate)) return 0; - int r = 0; - foreach (T t in array) if (predicate.Invoke(t)) r++; - return r; - } - public int Count(T match) - { - if (!Contains(match)) return 0; - int r = 0; - foreach (T t in array) if (t.Equals(match)) r++; - return r; - } - public void Fill(T item) { for (int i = 0; i < Length; i++) array[i] = item; } - public T Find(Predicate predicate) - { - foreach (T t in array) if (predicate.Invoke(t)) return t; - throw new Exception("Parameter " + nameof(predicate) + " does not exist in the list."); - } - public T Find(T match) - { - foreach (T t in array) if (t.Equals(match)) return t; - throw new Exception("Parameter " + nameof(match) + " does not exist in the list."); - } - public T Find(Predicate predicate, int start) - { - for (int i = start; i < array.Length; i++) if (predicate.Invoke(array[i])) return array[i]; - throw new Exception("Parameter " + nameof(predicate) + " does not exist in the list."); - } - public T Find(T match, int start) - { - for (int i = start; i < array.Length; i++) if (array[i].Equals(match)) return array[i]; - throw new Exception("Parameter " + nameof(match) + " does not exist in the list."); - } - public T Find(Predicate predicate, int start, int max) - { - for (int i = start; i <= max; i++) if (predicate.Invoke(array[i])) return array[i]; - throw new Exception("Parameter " + nameof(predicate) + " does not exist in the list."); - } - public T Find(T match, int start, int max) - { - for (int i = start; i <= max; i++) if (array[i].Equals(match)) return array[i]; - throw new Exception("Parameter " + nameof(match) + " does not exist in the list."); - } - public T FindOrDefault(Predicate predicate) - { - foreach (T t in array) if (predicate.Invoke(t)) return t; - return default; - } - public T FindOrDefault(T match) - { - foreach (T t in array) if (t.Equals(match)) return t; - return default; - } - public T FindOrDefault(Predicate predicate, int start) - { - for (int i = start; i < array.Length; i++) if (predicate.Invoke(array[i])) return array[i]; - return default; - } - public T FindOrDefault(T match, int start) - { - for (int i = start; i < array.Length; i++) if (array[i].Equals(match)) return array[i]; - return default; - } - public T FindOrDefault(Predicate predicate, int start, int max) - { - for (int i = start; i <= max; i++) if (predicate.Invoke(array[i])) return array[i]; - return default; - } - public T FindOrDefault(T match, int start, int max) - { - for (int i = start; i <= max; i++) if (array[i].Equals(match)) return array[i]; - return default; - } - public List FindAll(Predicate predicate) - { - List r = new(); - foreach (T t in array) if (predicate.Invoke(t)) r.Add(t); - return r; - } - public List FindAll(T match) - { - List r = new(); - foreach (T t in array) if (t.Equals(match)) r.Add(t); - return r; - } - public List FindAll(Predicate predicate, int start) - { - List r = new(); - for (int i = start; i < array.Length; i++) if (predicate.Invoke(array[i])) r.Add(array[i]); - return r; - } - public List FindAll(T match, int start) - { - List r = new(); - for (int i = start; i < array.Length; i++) if (array[i].Equals(match)) r.Add(array[i]); - return r; - } - public List FindAll(Predicate predicate, int start, int max) - { - List r = new(); - for (int i = start; i <= max; i++) if (predicate.Invoke(array[i])) r.Add(array[i]); - return r; - } - public List FindAll(T match, int start, int max) - { - List r = new(); - for (int i = start; i <= max; i++) if (array[i].Equals(match)) r.Add(array[i]); - return r; - } - public T FindLast(Predicate predicate) - { - for (int i = array.Length - 1; i >= 0; i--) if (predicate.Invoke(array[i])) return array[i]; - throw new Exception("Parameter " + nameof(predicate) + " does not exist in the list."); - } - public T FindLast(T match) - { - for (int i = array.Length - 1; i >= 0; i--) if (array[i].Equals(match)) return array[i]; - throw new Exception("Parameter " + nameof(match) + " does not exist in the list."); - } - public T FindLast(Predicate predicate, int start) - { - for (int i = array.Length - 1; i >= start; i--) if (predicate.Invoke(array[i])) return array[i]; - throw new Exception("Parameter " + nameof(predicate) + " does not exist in the list."); - } - public T FindLast(T match, int start) - { - for (int i = array.Length - 1; i >= start; i--) if (array[i].Equals(match)) return array[i]; - throw new Exception("Parameter " + nameof(match) + " does not exist in the list."); - } - public T FindLast(Predicate predicate, int start, int max) - { - for (int i = max; i >= start; i--) if (predicate.Invoke(array[i])) return array[i]; - throw new Exception("Parameter " + nameof(predicate) + " does not exist in the list."); - } - public T FindLast(T match, int start, int max) - { - for (int i = max; i >= start; i--) if (array[i].Equals(match)) return array[i]; - throw new Exception("Parameter " + nameof(match) + " does not exist in the list."); - } - public T FindLastOrDefault(Predicate predicate) - { - for (int i = array.Length - 1; i >= 0; i--) if (predicate.Invoke(array[i])) return array[i]; - return default; - } - public T FindLastOrDefault(T match) - { - for (int i = array.Length - 1; i >= 0; i--) if (array[i].Equals(match)) return array[i]; - return default; - } - public T FindLastOrDefault(Predicate predicate, int start) - { - for (int i = array.Length - 1; i >= start; i--) if (predicate.Invoke(array[i])) return array[i]; - return default; - } - public T FindLastOrDefault(T match, int start) - { - for (int i = array.Length - 1; i >= start; i--) if (array[i].Equals(match)) return array[i]; - return default; - } - public T FindLastOrDefault(Predicate predicate, int start, int max) - { - for (int i = max; i >= start; i--) if (predicate.Invoke(array[i])) return array[i]; - return default; - } - public T FindLastOrDefault(T match, int start, int max) - { - for (int i = max; i >= start; i--) if (array[i].Equals(match)) return array[i]; - return default; - } - public int FindIndex(Predicate predicate) - { - for (int i = 0; i < array.Length; i++) if (predicate.Invoke(array[i])) return i; - return -1; - } - public int FindIndex(T match) - { - for (int i = 0; i < array.Length; i++) if (array[i].Equals(match)) return i; - return -1; - } - public int FindIndex(Predicate predicate, int start) - { - for (int i = start; i < array.Length; i++) if (predicate.Invoke(array[i])) return i; - return -1; - } - public int FindIndex(T match, int start) - { - for (int i = start; i < array.Length; i++) if (array[i].Equals(match)) return i; - return -1; - } - public int FindIndex(Predicate predicate, int start, int max) - { - for (int i = start; i <= max; i++) if (predicate.Invoke(array[i])) return i; - return -1; - } - public int FindIndex(T match, int start, int max) - { - for (int i = start; i <= max; i++) if (array[i].Equals(match)) return i; - return -1; - } - public List FindAllIndex() - { - List ret = new(); - for (int i = 0; i < array.Length; i++) ret.Add(i); - return ret; - } - public List FindAllIndex(Predicate predicate) - { - List r = new(); - for (int i = 0; i < array.Length; i++) if (predicate.Invoke(array[i])) r.Add(i); - return r; - } - public List FindAllIndex(T match) - { - List r = new(); - for (int i = 0; i < array.Length; i++) if (array[i].Equals(match)) r.Add(i); - return r; - } - public List FindAllIndex(int start) - { - List ret = new(); - for (int i = start; i < array.Length; i++) ret.Add(i); - return ret; - } - public List FindAllIndex(Predicate predicate, int start) - { - List r = new(); - for (int i = start; i < array.Length; i++) if (predicate.Invoke(array[i])) r.Add(i); - return r; - } - public List FindAllIndex(T match, int start) - { - List r = new(); - for (int i = start; i < array.Length; i++) if (array[i].Equals(match)) r.Add(i); - return r; - } - public List FindAllIndex(int start, int max) - { - List ret = new(); - for (int i = start; i <= max; i++) ret.Add(i); - return ret; - } - public List FindAllIndex(Predicate predicate, int start, int max) - { - List r = new(); - for (int i = start; i <= max; i++) if (predicate.Invoke(array[i])) r.Add(i); - return r; - } - public List FindAllIndex(T match, int start, int max) - { - List r = new(); - for (int i = start; i <= max; i++) if (array[i].Equals(match)) r.Add(i); - return r; - } - public int FindLastIndex(Predicate predicate) - { - for (int i = array.Length - 1; i >= 0; i--) if (predicate.Invoke(array[i])) return i; - return -1; - } - public int FindLastIndex(T match) - { - for (int i = array.Length - 1; i >= 0; i--) if (array[i].Equals(match)) return i; - return -1; - } - public int FindLastIndex(Predicate predicate, int start) - { - for (int i = array.Length - 1; i >= start; i--) if (predicate.Invoke(array[i])) return i; - return -1; - } - public int FindLastIndex(T match, int start) - { - for (int i = array.Length - 1; i >= start; i--) if (array[i].Equals(match)) return i; - return -1; - } - public int FindLastIndex(Predicate predicate, int start, int max) - { - for (int i = max; i >= start; i--) if (predicate.Invoke(array[i])) return i; - return -1; - } - public int FindLastIndex(T match, int start, int max) - { - for (int i = max; i >= start; i--) if (array[i].Equals(match)) return i; - return -1; - } - public IEnumerator GetEnumerator() => array.GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => (IEnumerator)array.GetEnumerator(); - public List GetRange(int start, int max) - { - List r = new(); - for (int i = start; i <= max; i++) r.Add(array[i]); - return r; - } - public void Insert(int index, T item) - { - T[] old = array; - array = new T[old.Length + 1]; - for (int i = 0; i < index; i++) array[i] = old[i]; - array[index] = item; - for (int i = index + 1; i < array.Length; i++) array[i] = old[i - 1]; - } - public void InsertRange(int index, IEnumerable items) - { - List list = new(items); - - T[] old = array; - array = new T[old.Length + list.Length]; - for (int i = 0; i < index; i++) array[i] = old[i]; - for (int i = 0; i < list.Length; i++) array[index + i] = list[i]; - for (int i = index + list.Length; i < array.Length; i++) array[i] = old[i - list.Length]; - } - public bool MatchesAll(Predicate predicate) => FindAll(predicate).array == array; - public bool MatchesAll(T match) => FindAll(match).array == array; - public void Randomize() - { - List newL = new(); - List possibleIndexes = FindAllIndex(); - for (int i = 0; i < possibleIndexes.Length; i++) - { - int index = possibleIndexes[new Random().Next(0, possibleIndexes.Length)]; - newL.Add(array[index]); - possibleIndexes.Remove(x => x == index); - } - array = newL.ToArray(); - } - public void Remove(Predicate predicate) => Remove(FindIndex(predicate)); - public void Remove(T item) => Remove(FindIndex(item)); - public void Remove(int index) - { - List newList = new(); - for (int i = 0; i < array.Length; i++) if (i != index) newList.Add(array[i]); - array = newList.array; - } - public void RemoveAll(Predicate predicate) { foreach (int i in FindAllIndex(predicate)) Remove(i); } - public void RemoveAll(T match) { foreach (int i in FindAllIndex(match)) Remove(i); } - public void RemoveLast(Predicate predicate) => Remove(FindLastIndex(predicate)); - public void RemoveLast(T item) => Remove(FindLastIndex(item)); - public void RemoveRange(int index, int max) - { - List newList = new(); - for (int i = 0; i < array.Length; i++) if (i < index || i > max) newList.Add(array[i]); - array = newList.array; - } - public void Reverse() - { - T[] old = array; - array = new T[old.Length]; - - for (int i = old.Length - 1; i >= 0; i--) array[i] = old[i]; - } - public void Shuffle() => Randomize(); - public T[] ToArray() => array; - public ReadOnlyList ToReadOnly() { return new ReadOnlyList(array); } - public ReadOnlyCollection ToSystemReadOnly() { return new ReadOnlyCollection(array); } - public System.Collections.Generic.List ToSystemList() { return new System.Collections.Generic.List(array); } - - public override bool Equals(object obj) => base.Equals(obj); - public bool Equals(T[] other) - { - bool returned = true; - if (Length == other.Length) - { - for (int i = 0; i < Length; i++) - { - returned &= array[i].Equals(other[i]); - } - } - return returned; - } - public bool Equals(List list) - { - if (Length != list.Length) return false; - bool equal = true; - for (int i = 0; i < Length; i++) equal &= array[i].Equals(list[i]); - return equal; - } - public bool Equals(IEnumerable list) => Equals(new List(list)); - public override int GetHashCode() => base.GetHashCode(); - public override string ToString() => ToString(false); - public string ToString(bool showAll = false) - { - string ret = "List of " + Length + " Elements (" + typeof(T).ToString() + ")"; - if (showAll) for (int i = 0; i < Length; i++) ret += "\n" + i + ": " + array[i]; - return ret; - } - - public static List operator +(List a, T b) - { - a.Add(b); - return a; - } - public static List operator +(List a, IEnumerable b) - { - a.AddRange(b); - return a; - } - public static List operator +(List a, List b) - { - a.AddRange(b); - return a; - } - public static List operator +(List a, T[] b) - { - a.AddRange(b); - return a; - } - public static List operator -(List a, int remove) - { - List returned = new(a.Length - remove); - for (int i = 0; i < returned.Length; i++) - { - returned[i] = a[i]; - } - return returned; - } - public static List operator -(List a, int[] removes) - { - foreach (int remove in removes) - { - a.Remove(remove); - } - return a; - } - public static List operator -(List a, List removes) - { - foreach (int remove in removes) - { - a.Remove(remove); - } - return a; - } - public static List operator -(List a, T b) - { - a.Remove(b); - return a; - } - public static bool operator ==(List a, List b) => a.Equals(b); - public static bool operator ==(List a, T[] b) - { - return a.Equals(b); - } - public static bool operator ==(T[] a, List b) - { - return b.Equals(a); - } - public static bool operator !=(List a, List b) => !a.Equals(b); - public static bool operator !=(List a, T[] b) - { - return !a.Equals(b); - } - public static bool operator !=(T[] a, List b) - { - return !b.Equals(a); - } - } - - [Serializable] - [Obsolete("This class will be removed or heavily modified in a future release.")] - public class Matrix - { - internal List> lists; - - public Vector2 Length => new(lists[0].Length, lists.Length); - public int LengthX => lists[0].Length; - public int LengthY => lists.Length; - - public static Matrix Empty => new() { lists = List>.Empty }; - - public Matrix() => lists = new List>(1, new List(1, default)); - public Matrix(int lengthX, int lengthY) - { - if (lengthX < 1) throw new ArgumentOutOfRangeException(nameof(lengthX), "Do not include a length of less than 1"); - if (lengthY < 1) throw new ArgumentOutOfRangeException(nameof(lengthY), "Do not include a width of less than 1"); - lists = new List>(lengthY, new List(lengthX)); - } - public Matrix(int lengthX, int lengthY, T inputAll) - { - if (lengthX < 1) throw new ArgumentOutOfRangeException(nameof(lengthX), "Do not include a length of less than 1"); - if (lengthY < 1) throw new ArgumentOutOfRangeException(nameof(lengthY), "Do not include a width of less than 1"); - lists = new List>(lengthY, new List(lengthX, inputAll)); - } - public T this[int indexX, int indexY] - { - get => Get(indexX, indexY); - set => Set(indexX, indexY, value); - } - - public void Add(Matrix input, DirectionType addDir) - { - if (addDir == DirectionType.y) - { - foreach (List list in input.lists) AddY(list); - return; - } - - foreach (List list in input.lists) AddX(list); - } - public void AddX() { foreach (List list in lists) list.Add(); } - public void AddX(T input) { foreach (List list in lists) list.Add(input); } - public void AddX(T[] input) { foreach (T t in input) AddX(t); } - public void AddX(List input) { foreach (T t in input) AddX(t); } - public void AddY() => lists.Add(new List(lists[0].Length)); - public void AddY(T input) => lists.Add(new List(lists[0].Length, input)); - public void AddY(T[] input) - { - if (input.Length > lists[0].Length) throw new OverflowException(); - lists.Add(new List(input)); - } - public void AddY(List input) - { - if (input.Length > lists[0].Length) throw new OverflowException(); - lists.Add(input); - } - public bool Check(int placeX, int placeY) => lists[placeY][placeX] != null; - public bool Compare(T input) - { - foreach (List list in lists) if (list.Contains(input)) return true; - - return false; - } - public void Convert(T input) { for (int i = 0; i < lists.Length; i++) lists[i] = new(input); } - public void Convert(T[] input) { for (int i = 0; i < lists.Length; i++) lists[i] = new(input); } - public void Convert(List input) { for (int i = 0; i < lists.Length; i++) lists[i] = input; } - public void Convert(Matrix input) => lists = input.lists; - public int Count() - { - int returned = 0; - - foreach (List list in lists) returned += list.Count(); - - return returned; - } - public int Count(DirectionType type) - { - if (type == DirectionType.y) return LengthY; - return LengthX; - } - public Vector2 CountXY() => Length; - public T Get(int placeX, int placeY) => lists[placeY][placeX]; - public void Get(int placeX, int placeY, out T output) => output = Get(placeX, placeY); - public List GetAll() - { - List returned = new(); - - foreach (List list in lists) returned.AddRange(list); - - return returned; - } - public void GetAll(out List output) - { - List returned = new(); - - foreach (List list in lists) returned.AddRange(list); - - output = returned; - } - public IEnumerator GetEnumerator() { foreach (List list in lists) foreach (T t in list) yield return t; } - public void Remove(int placeX, int placeY) => lists[placeY].Remove(placeX); - public void Set(int placeX, int placeY, T input) => lists[placeY][placeX] = input; - public void SetAll(T input) { for (int i = 0; i < lists.Length; i++) for (int j = 0; j < lists[i].Length; j++) lists[i][j] = input; } - - public static Matrix AllDefault(int lengthX, int lengthY) => new(lengthX, lengthY, default); - - public override bool Equals(object obj) => base.Equals(obj); - public bool Equals(Matrix other) => GetAll() == other.GetAll(); - public override int GetHashCode() => base.GetHashCode(); - public override string ToString() => lists.ToString(); - public string ToString(bool showAll) - { - if (showAll) - { - string r = ""; - for (int i = 0; i < lists.Length; i++) - { - for (int j = 0; j < lists[i].Length; j++) - { - r += lists[i][j]; - if (j != lists[i].Length - 1) r += ", "; - } - if (i != lists.Length - 1) r += "\n"; - } - return r; - } - else return ToString(); - } - - public static bool operator ==(Matrix a, Matrix b) => a.Equals(b); - public static bool operator !=(Matrix a, Matrix b) => !a.Equals(b); - - public enum DirectionType - { - x, - y, - } - } - - [Serializable] - public class ReadOnlyList : IEnumerable, IEnumerable - { - public static ReadOnlyList Empty => new(); - - internal T[] array; - - public T this[int index] => array[index]; - - public List Duplicate => new(array); - public bool IsEmpty => array == Array.Empty(); - public bool IsNull => array == null; - public bool IsNullOrEmpty => IsNull || IsEmpty; - public int Length => array.Length; - - public ReadOnlyList() => array = Array.Empty(); - public ReadOnlyList(params T[] items) => array = items; - public ReadOnlyList(int length) => array = new T[length]; - public ReadOnlyList(int length, T itemAll) - { - array = new T[length]; - for (int i = 0; i < array.Length; i++) array[i] = itemAll; - } - public ReadOnlyList(IEnumerable items) => array = new List(items).ToArray(); - - public bool Contains(Predicate predicate) - { - foreach (T t in array) if (predicate.Invoke(t)) return true; - return false; - } - public bool Contains(T match) - { - foreach (T t in array) if (t.Equals(match)) return true; - return false; - } - public int Count() - { - int r = 0; - foreach (T _ in array) r++; - return r; - } - public int Count(Predicate predicate) - { - if (!Contains(predicate)) return 0; - int r = 0; - foreach (T t in array) if (predicate.Invoke(t)) r++; - return r; - } - public int Count(T match) - { - if (!Contains(match)) return 0; - int r = 0; - foreach (T t in array) if (t.Equals(match)) r++; - return r; - } - public T Find(Predicate predicate) - { - foreach (T t in array) if (predicate.Invoke(t)) return t; - throw new Exception("Parameter " + nameof(predicate) + " does not exist in the list."); - } - public T Find(T match) - { - foreach (T t in array) if (t.Equals(match)) return t; - throw new Exception("Parameter " + nameof(match) + " does not exist in the list."); - } - public T Find(Predicate predicate, int start) - { - for (int i = start; i < array.Length; i++) if (predicate.Invoke(array[i])) return array[i]; - throw new Exception("Parameter " + nameof(predicate) + " does not exist in the list."); - } - public T Find(T match, int start) - { - for (int i = start; i < array.Length; i++) if (array[i].Equals(match)) return array[i]; - throw new Exception("Parameter " + nameof(match) + " does not exist in the list."); - } - public T Find(Predicate predicate, int start, int max) - { - for (int i = start; i <= max; i++) if (predicate.Invoke(array[i])) return array[i]; - throw new Exception("Parameter " + nameof(predicate) + " does not exist in the list."); - } - public T Find(T match, int start, int max) - { - for (int i = start; i <= max; i++) if (array[i].Equals(match)) return array[i]; - throw new Exception("Parameter " + nameof(match) + " does not exist in the list."); - } - public T FindOrDefault(Predicate predicate) - { - foreach (T t in array) if (predicate.Invoke(t)) return t; - return default; - } - public T FindOrDefault(T match) - { - foreach (T t in array) if (t.Equals(match)) return t; - return default; - } - public T FindOrDefault(Predicate predicate, int start) - { - for (int i = start; i < array.Length; i++) if (predicate.Invoke(array[i])) return array[i]; - return default; - } - public T FindOrDefault(T match, int start) - { - for (int i = start; i < array.Length; i++) if (array[i].Equals(match)) return array[i]; - return default; - } - public T FindOrDefault(Predicate predicate, int start, int max) - { - for (int i = start; i <= max; i++) if (predicate.Invoke(array[i])) return array[i]; - return default; - } - public T FindOrDefault(T match, int start, int max) - { - for (int i = start; i <= max; i++) if (array[i].Equals(match)) return array[i]; - return default; - } - public List FindAll(Predicate predicate) - { - List r = new(); - foreach (T t in array) if (predicate.Invoke(t)) r.Add(t); - return r; - } - public List FindAll(T match) - { - List r = new(); - foreach (T t in array) if (t.Equals(match)) r.Add(t); - return r; - } - public List FindAll(Predicate predicate, int start) - { - List r = new(); - for (int i = start; i < array.Length; i++) if (predicate.Invoke(array[i])) r.Add(array[i]); - return r; - } - public List FindAll(T match, int start) - { - List r = new(); - for (int i = start; i < array.Length; i++) if (array[i].Equals(match)) r.Add(array[i]); - return r; - } - public List FindAll(Predicate predicate, int start, int max) - { - List r = new(); - for (int i = start; i <= max; i++) if (predicate.Invoke(array[i])) r.Add(array[i]); - return r; - } - public List FindAll(T match, int start, int max) - { - List r = new(); - for (int i = start; i <= max; i++) if (array[i].Equals(match)) r.Add(array[i]); - return r; - } - public T FindLast(Predicate predicate) - { - for (int i = array.Length - 1; i >= 0; i--) if (predicate.Invoke(array[i])) return array[i]; - throw new Exception("Parameter " + nameof(predicate) + " does not exist in the list."); - } - public T FindLast(T match) - { - for (int i = array.Length - 1; i >= 0; i--) if (array[i].Equals(match)) return array[i]; - throw new Exception("Parameter " + nameof(match) + " does not exist in the list."); - } - public T FindLast(Predicate predicate, int start) - { - for (int i = array.Length - 1; i >= start; i--) if (predicate.Invoke(array[i])) return array[i]; - throw new Exception("Parameter " + nameof(predicate) + " does not exist in the list."); - } - public T FindLast(T match, int start) - { - for (int i = array.Length - 1; i >= start; i--) if (array[i].Equals(match)) return array[i]; - throw new Exception("Parameter " + nameof(match) + " does not exist in the list."); - } - public T FindLast(Predicate predicate, int start, int max) - { - for (int i = max; i >= start; i--) if (predicate.Invoke(array[i])) return array[i]; - throw new Exception("Parameter " + nameof(predicate) + " does not exist in the list."); - } - public T FindLast(T match, int start, int max) - { - for (int i = max; i >= start; i--) if (array[i].Equals(match)) return array[i]; - throw new Exception("Parameter " + nameof(match) + " does not exist in the list."); - } - public T FindLastOrDefault(Predicate predicate) - { - for (int i = array.Length - 1; i >= 0; i--) if (predicate.Invoke(array[i])) return array[i]; - return default; - } - public T FindLastOrDefault(T match) - { - for (int i = array.Length - 1; i >= 0; i--) if (array[i].Equals(match)) return array[i]; - return default; - } - public T FindLastOrDefault(Predicate predicate, int start) - { - for (int i = array.Length - 1; i >= start; i--) if (predicate.Invoke(array[i])) return array[i]; - return default; - } - public T FindLastOrDefault(T match, int start) - { - for (int i = array.Length - 1; i >= start; i--) if (array[i].Equals(match)) return array[i]; - return default; - } - public T FindLastOrDefault(Predicate predicate, int start, int max) - { - for (int i = max; i >= start; i--) if (predicate.Invoke(array[i])) return array[i]; - return default; - } - public T FindLastOrDefault(T match, int start, int max) - { - for (int i = max; i >= start; i--) if (array[i].Equals(match)) return array[i]; - return default; - } - public int FindIndex(Predicate predicate) - { - for (int i = 0; i < array.Length; i++) if (predicate.Invoke(array[i])) return i; - return -1; - } - public int FindIndex(T match) - { - for (int i = 0; i < array.Length; i++) if (array[i].Equals(match)) return i; - return -1; - } - public int FindIndex(Predicate predicate, int start) - { - for (int i = start; i < array.Length; i++) if (predicate.Invoke(array[i])) return i; - return -1; - } - public int FindIndex(T match, int start) - { - for (int i = start; i < array.Length; i++) if (array[i].Equals(match)) return i; - return -1; - } - public int FindIndex(Predicate predicate, int start, int max) - { - for (int i = start; i <= max; i++) if (predicate.Invoke(array[i])) return i; - return -1; - } - public int FindIndex(T match, int start, int max) - { - for (int i = start; i <= max; i++) if (array[i].Equals(match)) return i; - return -1; - } - public List FindAllIndex() - { - List ret = new(); - for (int i = 0; i < array.Length; i++) ret.Add(i); - return ret; - } - public List FindAllIndex(Predicate predicate) - { - List r = new(); - for (int i = 0; i < array.Length; i++) if (predicate.Invoke(array[i])) r.Add(i); - return r; - } - public List FindAllIndex(T match) - { - List r = new(); - for (int i = 0; i < array.Length; i++) if (array[i].Equals(match)) r.Add(i); - return r; - } - public List FindAllIndex(int start) - { - List ret = new(); - for (int i = start; i < array.Length; i++) ret.Add(i); - return ret; - } - public List FindAllIndex(Predicate predicate, int start) - { - List r = new(); - for (int i = start; i < array.Length; i++) if (predicate.Invoke(array[i])) r.Add(i); - return r; - } - public List FindAllIndex(T match, int start) - { - List r = new(); - for (int i = start; i < array.Length; i++) if (array[i].Equals(match)) r.Add(i); - return r; - } - public List FindAllIndex(int start, int max) - { - List ret = new(); - for (int i = start; i <= max; i++) ret.Add(i); - return ret; - } - public List FindAllIndex(Predicate predicate, int start, int max) - { - List r = new(); - for (int i = start; i <= max; i++) if (predicate.Invoke(array[i])) r.Add(i); - return r; - } - public List FindAllIndex(T match, int start, int max) - { - List r = new(); - for (int i = start; i <= max; i++) if (array[i].Equals(match)) r.Add(i); - return r; - } - public int FindLastIndex(Predicate predicate) - { - for (int i = array.Length - 1; i >= 0; i--) if (predicate.Invoke(array[i])) return i; - return -1; - } - public int FindLastIndex(T match) - { - for (int i = array.Length - 1; i >= 0; i--) if (array[i].Equals(match)) return i; - return -1; - } - public int FindLastIndex(Predicate predicate, int start) - { - for (int i = array.Length - 1; i >= start; i--) if (predicate.Invoke(array[i])) return i; - return -1; - } - public int FindLastIndex(T match, int start) - { - for (int i = array.Length - 1; i >= start; i--) if (array[i].Equals(match)) return i; - return -1; - } - public int FindLastIndex(Predicate predicate, int start, int max) - { - for (int i = max; i >= start; i--) if (predicate.Invoke(array[i])) return i; - return -1; - } - public int FindLastIndex(T match, int start, int max) - { - for (int i = max; i >= start; i--) if (array[i].Equals(match)) return i; - return -1; - } - public IEnumerator GetEnumerator() => array.GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => (IEnumerator)array.GetEnumerator(); - public List GetRange(int start, int max) - { - List r = new(); - for (int i = start; i <= max; i++) r.Add(array[i]); - return r; - } - public bool MatchesAll(Predicate predicate) => FindAll(predicate).array == array; - public bool MatchesAll(T match) => FindAll(match).array == array; - public T[] ToArray() => array; - public List ToList() => new(array); - public System.Collections.Generic.List ToSystemList() => new(array); - public ReadOnlyCollection ToSystemReadOnly() => new(array); - - public override bool Equals(object obj) => base.Equals(obj); - public bool Equals(T[] other) - { - bool returned = true; - if (Length == other.Length) - { - for (int i = 0; i < Length; i++) - { - returned &= array[i].Equals(other[i]); - } - } - return returned; - } - public bool Equals(ReadOnlyList list) - { - if (Length != list.Length) return false; - bool equal = true; - for (int i = 0; i < Length; i++) equal &= array[i].Equals(list[i]); - return equal; - } - public bool Equals(IEnumerable list) => Equals(new ReadOnlyList(list)); - public override int GetHashCode() => base.GetHashCode(); - public override string ToString() => ToString(false); - public string ToString(bool showAll = false) - { - string ret = "List of " + Length + " Elements (" + typeof(T).ToString() + ")"; - if (showAll) for (int i = 0; i < Length; i++) ret += "\n" + i + ": " + array[i]; - return ret; - } - - public static bool operator ==(ReadOnlyList a, ReadOnlyList b) => a.Equals(b); - public static bool operator ==(ReadOnlyList a, T[] b) - { - return a.Equals(b); - } - public static bool operator ==(T[] a, ReadOnlyList b) - { - return b.Equals(a); - } - public static bool operator ==(IEnumerable a, ReadOnlyList b) => a.Equals(b); - public static bool operator ==(ReadOnlyList a, IEnumerable b) => a.Equals(b); - public static bool operator !=(ReadOnlyList a, ReadOnlyList b) => !a.Equals(b); - public static bool operator !=(ReadOnlyList a, T[] b) - { - return !a.Equals(b); - } - public static bool operator !=(T[] a, ReadOnlyList b) - { - return !b.Equals(a); - } - public static bool operator !=(IEnumerable a, ReadOnlyList b) => !a.Equals(b); - public static bool operator !=(ReadOnlyList a, IEnumerable b) => !a.Equals(b); - } -} \ No newline at end of file diff --git a/Scripts/Mathematics.cs b/Scripts/Mathematics.cs deleted file mode 100644 index 1830e35..0000000 --- a/Scripts/Mathematics.cs +++ /dev/null @@ -1,1009 +0,0 @@ -using Nerd_STF.Mathematics.Interfaces; -using System; - -namespace Nerd_STF.Mathematics -{ - [Serializable] - public struct Angle : IMathFunctions, INegatives - { - public float value; - - public Angle Clamped - { - get - { - Angle returned = this; - while (returned.value >= 360) returned.value -= 360; - while (returned.value < 0) returned.value += 360; - return returned; - } - } - public Angle Absolute - { - get - { - Angle returned = new(value); - if (value < 0) returned *= -1; - return returned; - } - } - public bool IsAcute => Clamped.value > 0 && Clamped.value < 90; - public bool IsClamped => value < 360 && value >= 0; - public bool IsNegative => value < 0; - public bool IsObtuse => Clamped.value > 90 && Clamped.value < 180; - public bool IsReflex => Clamped.value > 180 && Clamped.value < 360; - public bool IsRight => Clamped.value == 90; - public bool IsStraight => Clamped.value == 180; - public bool IsZero => Clamped.value == 0; - public Angle Negative - { - get - { - Angle returned = new(value); - if (value > 0) returned *= -1; - return returned; - } - } - public Angle Positive => Absolute; - public AngleType Type - { - get - { - if (IsAcute) return AngleType.Acute; - else if (IsObtuse) return AngleType.Obtuse; - else if (IsReflex) return AngleType.Reflex; - else if (IsRight) return AngleType.Right; - else if (IsStraight) return AngleType.Straight; - else if (IsZero) return AngleType.Zero; - else throw new ArithmeticException(); - } - } - - public Angle(float degree) => value = degree; - - public static Angle Acute => new(45); - public static Angle Obtuse => new(135); - public static Angle Reflex => new(270); - public static Angle Right => new(90); - public static Angle Straight => new(180); - public static Angle Zero => new(0); - - public override bool Equals(object obj) => base.Equals(obj); - public bool Equals(Angle other) => value == other.value; - public bool Equals(float other) => value == other; - public override int GetHashCode() => base.GetHashCode(); - public override string ToString() => value.ToString() + "°"; - public string ToString(string format) => value.ToString(format) + "°"; - - public Angle Average(params Angle[] objs) - { - float[] average = new float[objs.Length + 1]; - for (int i = 0; i < objs.Length; i++) average[i] = objs[i].value; - average[objs.Length] = value; - return new(Math.Average(average)); - } - public Angle Max(params Angle[] objs) - { - float[] max = new float[objs.Length + 1]; - for (int i = 0; i < objs.Length; i++) max[i] = objs[i].value; - max[objs.Length] = value; - return new(Math.Max(max)); - } - public Angle Min(params Angle[] objs) - { - float[] min = new float[objs.Length + 1]; - for (int i = 0; i < objs.Length; i++) min[i] = objs[i].value; - min[objs.Length] = value; - return new(Math.Min(min)); - } - - public static Angle operator +(Angle a, Angle b) => new(a.value + b.value); - public static Angle operator +(Angle a, float b) => new(a.value + b); - public static Angle operator +(float a, Angle b) => new(a + b.value); - public static Angle operator -(Angle a, Angle b) => new(a.value - b.value); - public static Angle operator -(Angle a, float b) => new(a.value - b); - public static Angle operator -(float a, Angle b) => new(a - b.value); - public static Angle operator *(Angle a, Angle b) => new(a.value * b.value); - public static Angle operator *(Angle a, float b) => new(a.value * b); - public static Angle operator *(float a, Angle b) => new(a * b.value); - public static Angle operator /(Angle a, Angle b) => new(a.value / b.value); - public static Angle operator /(Angle a, float b) => new(a.value / b); - public static Angle operator /(float a, Angle b) => new(a / b.value); - public static bool operator ==(Angle a, Angle b) => a.Equals(b); - public static bool operator ==(Angle a, float b) => a.Equals(b); - public static bool operator ==(float a, Angle b) => b.Equals(a); - public static bool operator !=(Angle a, Angle b) => !a.Equals(b); - public static bool operator !=(Angle a, float b) => !a.Equals(b); - public static bool operator !=(float a, Angle b) => !b.Equals(a); - public static bool operator >(Angle a, Angle b) => a.value > b.value; - public static bool operator >(Angle a, float b) => a.value > b; - public static bool operator >(float a, Angle b) => a > b.value; - public static bool operator <(Angle a, Angle b) => a.value < b.value; - public static bool operator <(Angle a, float b) => a.value < b; - public static bool operator <(float a, Angle b) => a < b.value; - public static bool operator >=(Angle a, Angle b) => a.value > b.value || a.Equals(b); - public static bool operator >=(Angle a, float b) => a.value > b || a.Equals(b); - public static bool operator >=(float a, Angle b) => a > b.value || b.Equals(a); - public static bool operator <=(Angle a, Angle b) => a.value < b.value || a.Equals(b); - public static bool operator <=(Angle a, float b) => a.value < b || a.Equals(b); - public static bool operator <=(float a, Angle b) => a < b.value || b.Equals(a); - - public static explicit operator float(Angle input) => input.value; - public static explicit operator Angle(float input) => new(input); - - public enum AngleType - { - Acute, - Obtuse, - Reflex, - Right, - Straight, - Zero, - } - } - - [Serializable] - public struct Color : IMathFunctions - { - public float r, g, b, a; - - public bool IsBlue => b != 0; - public bool IsClear => a == 0; - public bool IsGreen => g != 0; - public bool IsRed => a != 0; - public bool IsTransparent => a > 0 && a < 1; - public bool IsBroken - { - get - { - bool returned = false; - returned |= r < 0 || r > 1; - returned |= g < 0 || g > 1; - returned |= b < 0 || b > 1; - returned |= a < 0 || a > 1; - return returned; - } - } - - public static Color Black => new(0, 0, 0); - public static Color Blue => new(0, 0, 1); - public static Color Clear => new(0, 0, 0, 0); - public static Color Cyan => new(0, 1, 1); - public static Color Gray => new(0.5f, 0.5f, 0.5f); - public static Color Green => new(0, 1, 0); - public static Color Magenta => new(1, 0, 1); - public static Color Orange => new(1, 0.5f, 0); - public static Color Purple => new(0.5f, 0, 1); - public static Color Red => new(1, 0, 0); - public static Color White => new(1, 1, 1); - public static Color Yellow => new(1, 1, 0); - - public Color(float r, float g, float b) - { - this = new(r, g, b, 1); - } - public Color(float r, float g, float b, float a) - { - r = Math.Clamp(r, 0, 1); - g = Math.Clamp(g, 0, 1); - b = Math.Clamp(b, 0, 1); - a = Math.Clamp(a, 0, 1); - - this.r = r; - this.g = g; - this.b = b; - this.a = a; - } - - public void Check() - { - r = Math.Clamp(r, 0, 1); - g = Math.Clamp(g, 0, 1); - b = Math.Clamp(b, 0, 1); - a = Math.Clamp(a, 0, 1); - } - - public Color Average(params Color[] objs) - { - float[] averageR = new float[objs.Length + 1]; - float[] averageG = new float[objs.Length + 1]; - float[] averageB = new float[objs.Length + 1]; - float[] averageA = new float[objs.Length + 1]; - for (int i = 0; i < objs.Length; i++) - { - averageR[i] = objs[i].r; - averageG[i] = objs[i].g; - averageB[i] = objs[i].b; - averageA[i] = objs[i].a; - } - averageR[objs.Length] = r; - averageG[objs.Length] = g; - averageB[objs.Length] = b; - averageA[objs.Length] = a; - return new(Math.Average(averageR), Math.Average(averageG), Math.Average(averageB), Math.Average(averageA)); - } - public Color Max(params Color[] objs) - { - float[] maxR = new float[objs.Length + 1]; - float[] maxG = new float[objs.Length + 1]; - float[] maxB = new float[objs.Length + 1]; - float[] maxA = new float[objs.Length + 1]; - for (int i = 0; i < objs.Length; i++) - { - maxR[i] = objs[i].r; - maxG[i] = objs[i].g; - maxB[i] = objs[i].b; - maxA[i] = objs[i].a; - } - maxR[objs.Length] = r; - maxG[objs.Length] = g; - maxB[objs.Length] = b; - maxA[objs.Length] = a; - return new(Math.Max(maxR), Math.Max(maxG), Math.Max(maxB), Math.Max(maxA)); - } - public Color Min(params Color[] objs) - { - float[] minR = new float[objs.Length + 1]; - float[] minG = new float[objs.Length + 1]; - float[] minB = new float[objs.Length + 1]; - float[] minA = new float[objs.Length + 1]; - for (int i = 0; i < objs.Length; i++) - { - minR[i] = objs[i].r; - minG[i] = objs[i].g; - minB[i] = objs[i].b; - minA[i] = objs[i].a; - } - minR[objs.Length] = r; - minG[objs.Length] = g; - minB[objs.Length] = b; - minA[objs.Length] = a; - return new(Math.Min(minR), Math.Min(minG), Math.Min(minB), Math.Min(minA)); - } - - public override bool Equals(object obj) => base.Equals(obj); - public bool Equals(Color other) => r == other.r && g == other.g && b == other.b && a == other.a; - public override int GetHashCode() => base.GetHashCode(); - public override string ToString() => "R: " + r.ToString() + " | G: " + g.ToString() + " | B: " + b.ToString() + " | A: " + a.ToString(); - public string ToString(string format) => "R: " + r.ToString(format) + " | G: " + g.ToString(format) + " | B: " + b.ToString(format) + " | A: " + a.ToString(format); - - public static Color operator +(Color a, Color b) => new(a.r + b.r, a.g + b.g, a.b + b.b, a.a + b.a); - public static Color operator +(Color a, float b) => new(a.r + b, a.g + b, a.b + b, a.a + b); - public static Color operator +(float a, Color b) => new(a + b.r, a + b.g, a + b.b, a + b.a); - public static Color operator -(Color a, Color b) => new(a.r - b.r, a.g - b.g, a.b - b.b, a.a - b.a); - public static Color operator -(Color a, float b) => new(a.r - b, a.g - b, a.b - b, a.a - b); - public static Color operator -(float a, Color b) => new(a - b.r, a - b.g, a - b.b, a - b.a); - public static Color operator *(Color a, Color b) => new(a.r * b.r, a.g * b.g, a.b * b.b, a.a * b.a); - public static Color operator *(Color a, float b) => new(a.r * b, a.g * b, a.b * b, a.a * b); - public static Color operator *(float a, Color b) => new(a * b.r, a * b.g, a * b.b, a * b.a); - public static Color operator /(Color a, Color b) => new(a.r / b.r, a.g / b.g, a.b / b.b, a.a / b.a); - public static Color operator /(Color a, float b) => new(a.r / b, a.g / b, a.b / b, a.a / b); - public static Color operator /(float a, Color b) => new(a / b.r, a / b.g, a / b.b, a / b.a); - public static bool operator ==(Color a, Color b) => a.Equals(b); - public static bool operator !=(Color a, Color b) => !a.Equals(b); - - public static implicit operator Color(ColorByte input) => new(input.r / 255, input.g / 255, input.b / 255, input.a / 255); - public static explicit operator Color(Vector3 input) => new(input.x, input.y, input.z, 1); - public static explicit operator Color(Vector4 input) => new(input.x, input.y, input.z, input.w); - } - [Serializable] - public struct ColorByte : IMathFunctions - { - public byte r, g, b, a; - - public bool IsBlue => b != byte.MinValue; - public bool IsClear => a == byte.MinValue; - public bool IsGreen => g != byte.MinValue; - public bool IsRed => a != byte.MinValue; - public bool IsTransparent => a > byte.MinValue && a < byte.MaxValue; - - public static ColorByte Black => new(0, 0, 0); - public static ColorByte Blue => new(0, 0, 255); - public static ColorByte Clear => new(0, 0, 0, 0); - public static ColorByte Cyan => new(0, 255, 255); - public static ColorByte Gray => new(128, 128, 128); - public static ColorByte Green => new(0, 255, 0); - public static ColorByte Magenta => new(255, 0, 255); - public static ColorByte Orange => new(1, 128, 0); - public static ColorByte Purple => new(128, 0, 1); - public static ColorByte Red => new(255, 0, 0); - public static ColorByte White => new(255, 255, 255); - public static ColorByte Yellow => new(255, 255, 0); - - public ColorByte(byte r, byte g, byte b) => this = new(r, g, b, byte.MaxValue); - public ColorByte(byte r, byte g, byte b, byte a) - { - this.r = r; - this.g = g; - this.b = b; - this.a = a; - } - public ColorByte(int r, int g, int b) => this = new(r, g, b, byte.MaxValue); - public ColorByte(int r, int g, int b, int a) - { - this.r = (byte)r; - this.g = (byte)g; - this.b = (byte)b; - this.a = (byte)a; - } - - public ColorByte Average(params ColorByte[] objs) - { - float[] averageR = new float[objs.Length + 1]; - float[] averageG = new float[objs.Length + 1]; - float[] averageB = new float[objs.Length + 1]; - float[] averageA = new float[objs.Length + 1]; - for (int i = 0; i < objs.Length; i++) - { - averageR[i] = objs[i].r; - averageG[i] = objs[i].g; - averageB[i] = objs[i].b; - averageA[i] = objs[i].a; - } - averageR[objs.Length] = r; - averageG[objs.Length] = g; - averageB[objs.Length] = b; - averageA[objs.Length] = a; - return new(Math.RoundToInt(Math.Average(averageR)), Math.RoundToInt(Math.Average(averageG)), Math.RoundToInt(Math.Average(averageB)), Math.RoundToInt(Math.Average(averageA))); - } - public ColorByte Max(params ColorByte[] objs) - { - float[] maxR = new float[objs.Length + 1]; - float[] maxG = new float[objs.Length + 1]; - float[] maxB = new float[objs.Length + 1]; - float[] maxA = new float[objs.Length + 1]; - for (int i = 0; i < objs.Length; i++) - { - maxR[i] = objs[i].r; - maxG[i] = objs[i].g; - maxB[i] = objs[i].b; - maxA[i] = objs[i].a; - } - maxR[objs.Length] = r; - maxG[objs.Length] = g; - maxB[objs.Length] = b; - maxA[objs.Length] = a; - return new(Math.RoundToInt(Math.Max(maxR)), Math.RoundToInt(Math.Max(maxG)), Math.RoundToInt(Math.Max(maxB)), Math.RoundToInt(Math.Max(maxA))); - } - public ColorByte Min(params ColorByte[] objs) - { - float[] minR = new float[objs.Length + 1]; - float[] minG = new float[objs.Length + 1]; - float[] minB = new float[objs.Length + 1]; - float[] minA = new float[objs.Length + 1]; - for (int i = 0; i < objs.Length; i++) - { - minR[i] = objs[i].r; - minG[i] = objs[i].g; - minB[i] = objs[i].b; - minA[i] = objs[i].a; - } - minR[objs.Length] = r; - minG[objs.Length] = g; - minB[objs.Length] = b; - minA[objs.Length] = a; - return new(Math.RoundToInt(Math.Min(minR)), Math.RoundToInt(Math.Min(minG)), Math.RoundToInt(Math.Min(minB)), Math.RoundToInt(Math.Min(minA))); - } - - public override bool Equals(object obj) => base.Equals(obj); - public bool Equals(ColorByte other) => r == other.r && g == other.g && b == other.b && a == other.a; - public override int GetHashCode() => base.GetHashCode(); - public override string ToString() => "R: " + r.ToString() + " | G: " + g.ToString() + " | B: " + b.ToString() + " | A: " + a.ToString(); - public string ToString(string format) => "R: " + r.ToString(format) + " | G: " + g.ToString(format) + " | B: " + b.ToString(format) + " | A: " + a.ToString(format); - - public static ColorByte operator +(ColorByte a, ColorByte b) => new(a.r + b.r, a.g + b.g, a.b + b.b, a.a + b.a); - public static ColorByte operator +(ColorByte a, byte b) => new(a.r + b, a.g + b, a.b + b, a.a + b); - public static ColorByte operator +(byte a, ColorByte b) => new(a + b.r, a + b.g, a + b.b, a + b.a); - public static ColorByte operator -(ColorByte a, ColorByte b) => new(a.r - b.r, a.g - b.g, a.b - b.b, a.a - b.a); - public static ColorByte operator -(ColorByte a, byte b) => new(a.r - b, a.g - b, a.b - b, a.a - b); - public static ColorByte operator -(byte a, ColorByte b) => new(a - b.r, a - b.g, a - b.b, a - b.a); - public static ColorByte operator *(ColorByte a, ColorByte b) => new(a.r * b.r, a.g * b.g, a.b * b.b, a.a * b.a); - public static ColorByte operator *(ColorByte a, byte b) => new(a.r * b, a.g * b, a.b * b, a.a * b); - public static ColorByte operator *(byte a, ColorByte b) => new(a * b.r, a * b.g, a * b.b, a * b.a); - public static ColorByte operator /(ColorByte a, ColorByte b) => new(a.r / b.r, a.g / b.g, a.b / b.b, a.a / b.a); - public static ColorByte operator /(ColorByte a, byte b) => new(a.r / b, a.g / b, a.b / b, a.a / b); - public static ColorByte operator /(byte a, ColorByte b) => new(a / b.r, a / b.g, a / b.b, a / b.a); - public static bool operator ==(ColorByte a, ColorByte b) => a.Equals(b); - public static bool operator !=(ColorByte a, ColorByte b) => !a.Equals(b); - - public static explicit operator ColorByte(Color input) => new((byte)(input.r * 255), (byte)(input.g * 255), (byte)(input.b * 255), (byte)(input.a * 255)); - } - - public static class Math - { - public const float E = 2.7182818284590451f; - public const float Pi = 3.1415926535897931f; - public const float Tau = 6.2831853071795862f; - - public static float Absolute(float input) - { - if (input < 0) input *= -1; - return input; - } - - public static float Add(params float[] input) - { - float returned = 0; - foreach (float f in input) returned += f; - return returned; - } - - public static float Average(params float[] input) - { - float returned = 0; - foreach (float f in input) returned += f; - returned /= input.Length; - return returned; - } - - public static float Clamp(float input, float min, float max) - { - if (min > max) throw new ArgumentException("Minimun cannot be greater than maximum."); - - if (input > max) input = max; - else if (input < min) input = min; - - return input; - } - - public static int Clamp(float input, int min, int max) - { - if (min > max) throw new ArgumentException("Minimun cannot be greater than maximum."); - - if (input > max) input = max; - else if (input < min) input = min; - - return (int)input; - } - - public static float Divide(params float[] input) - { - float returned = input[0]; - for (uint i = 1; i < input.Length; i++) returned /= input[i]; - return returned; - } - - public static float Max(params float[] input) - { - float returned = input[0]; - for (uint i = 0; i < input.Length; i++) if (input[i] > returned) returned = input[i]; - return returned; - } - - public static float Min(params float[] input) - { - float returned = input[0]; - for (uint i = 0; i < input.Length; i++) if (input[i] < returned) returned = input[0]; - return returned; - } - - public static float Multiply(params float[] input) - { - float returned = 1; - foreach (float f in input) returned *= f; - return returned; - } - - public static float Power(float input, int power) - { - float returned = 1; - for (uint i = 0; i < Absolute(power); i++) returned *= input; - if (power < 0) returned = 1 / returned; - return returned; - } - - public static float Round(float value) - { - if (value % 1 >= 0.5f) value += 1 - (value % 1); - else value -= value % 1; - - return value; - } - public static float Round(float value, float dividend) => Round(value / dividend) * dividend; - public static int RoundToInt(float value) => (int)Round(value); - - public static float Subtract(params float[] input) - { - float returned = input[0]; - for (uint i = 1; i < input.Length; i++) returned -= input[i]; - return returned; - } - - public static class Formulas - { - public static float CircleArea(float radius) => Pi * radius * radius; - public static float CircleCircum(float radius) => 2 * radius * Pi; - public static float CircleDiam(float radius) => radius * 2; - public static float CircleRadius(float circumference) => circumference / Pi / 2; - - public static float Perimeter(params float[] sideLengths) => Add(sideLengths); - - public static float RectangleArea(float length, float width) => length * width; - - public static float SquareArea(float length) => RectangleArea(length, length); - } - } - - [Serializable] - public struct Percent : IMathFunctions, INegatives - { - public float value; - - public Percent Absolute - { - get - { - Percent returned = new(value); - if (returned < 0) returned *= -1; - return returned; - } - } - public bool IsFull { get => value == 100; } - public bool IsNegative { get => value < 0; } - public bool IsOverflow { get => value > 100; } - public bool IsZero { get => value == 0; } - public Percent Negative - { - get - { - Percent returned = new(value); - if (returned > 0) returned *= -1; - return returned; - } - } - public Percent Positive { get => Absolute; } - - public static Percent Full { get => new(100); } - public static Percent One { get => new(1); } - public static Percent Zero { get => new(0); } - - public Percent(float value) => this = new(value, 0, 100); - public Percent(float value, float maxValue) => this = new(value, 0, maxValue); - public Percent(float value, float minValue, float maxValue) => this.value = value / (maxValue - minValue); - - public Percent Average(params Percent[] objs) - { - float[] average = new float[objs.Length + 1]; - for (int i = 0; i < objs.Length; i++) average[i] = objs[i].value; - average[objs.Length] = value; - return new(Math.Average(average)); - } - public Percent Max(params Percent[] objs) - { - float[] max = new float[objs.Length]; - for (int i = 0; i < objs.Length; i++) max[i] = objs[i].value; - max[objs.Length] = value; - return new(Math.Max(max)); - } - public Percent Min(params Percent[] objs) - { - float[] min = new float[objs.Length]; - for (int i = 0; i < objs.Length; i++) min[i] = objs[i].value; - min[objs.Length] = value; - return new(Math.Min(min)); - } - - public override bool Equals(object obj) => base.Equals(obj); - public bool Equals(float other) => value == other || value == (other / 100); - public bool Equals(Percent other) => value == other.value; - public override int GetHashCode() => base.GetHashCode(); - public override string ToString() => value.ToString() + "%"; - public string ToString(string format) => value.ToString(format) + "%"; - - public static Percent operator +(Percent a, Percent b) => new() { value = a.value + b.value }; - public static Percent operator +(Percent a, float b) => new() { value = a.value + (b / 100) }; - public static Percent operator +(float a, Percent b) => new() { value = (a / 100) + b.value }; - public static Percent operator -(Percent a, Percent b) => new() { value = a.value - b.value }; - public static Percent operator -(Percent a, float b) => new() { value = a.value - (b / 100) }; - public static Percent operator -(float a, Percent b) => new() { value = (a / 100) + b.value }; - public static Percent operator *(Percent a, Percent b) => new() { value = a.value * b.value }; - public static Percent operator *(Percent a, float b) => new() { value = a.value * (b / 100) }; - public static Percent operator *(float a, Percent b) => new() { value = (a / 100) + b.value }; - public static Percent operator /(Percent a, Percent b) => new() { value = a.value / b.value }; - public static Percent operator /(Percent a, float b) => new() { value = a.value / b / 100 }; - public static Percent operator /(float a, Percent b) => new() { value = (a / 100) + b.value }; - public static bool operator ==(Percent a, Percent b) => a.Equals(b); - public static bool operator ==(Percent a, float b) => a.Equals(b); - public static bool operator ==(float a, Percent b) => b.Equals(a); - public static bool operator !=(Percent a, Percent b) => !a.Equals(b); - public static bool operator !=(Percent a, float b) => !a.Equals(b); - public static bool operator !=(float a, Percent b) => !b.Equals(a); - public static bool operator >(Percent a, Percent b) => a.value > b.value; - public static bool operator >(Percent a, float b) => a.value > b; - public static bool operator >(float a, Percent b) => a > b.value; - public static bool operator <(Percent a, Percent b) => a.value < b.value; - public static bool operator <(Percent a, float b) => a.value < b; - public static bool operator <(float a, Percent b) => a < b.value; - public static bool operator >=(Percent a, Percent b) => a.value > b.value || a.Equals(b); - public static bool operator >=(Percent a, float b) => a.value > b || a.Equals(b); - public static bool operator >=(float a, Percent b) => a > b.value || b.Equals(a); - public static bool operator <=(Percent a, Percent b) => a.value < b.value || a.Equals(b); - public static bool operator <=(Percent a, float b) => a.value < b || a.Equals(b); - public static bool operator <=(float a, Percent b) => a < b.value || b.Equals(a); - - public static explicit operator float(Percent input) => input.value; - public static explicit operator Percent(float input) => new(input); - } - - [Serializable] - public struct Vector : IMathFunctions - { - public Angle direction; - public float strength; - - public Vector Inverse { get => new(direction.value - 180, -strength); } - public Vector Reflected { get => new(360 - direction, strength); } - - public static Vector Zero { get => new(0, 0); } - - public Vector(Angle direction, float strength, bool clampDir = true) - { - if (clampDir) direction = direction.Clamped; - this.direction = direction; - this.strength = strength; - } - public Vector(float direction, float strength, bool clampDir = true) => this = new Vector(new Angle(direction), strength, clampDir); - - public Vector Average(params Vector[] objs) - { - float[] averageD = new float[objs.Length + 1]; - float[] averageS = new float[objs.Length + 1]; - for (int i = 0; i < objs.Length; i++) - { - averageD[i] = objs[i].direction.Clamped.value; - averageS[i] = objs[i].strength; - } - averageD[objs.Length] = direction.Clamped.value; - averageS[objs.Length] = strength; - return new(Math.Average(averageD), Math.Average(averageS)); - } - public Vector Max(params Vector[] objs) - { - float[] maxD = new float[objs.Length + 1]; - float[] maxS = new float[objs.Length + 1]; - for (int i = 0; i < objs.Length; i++) - { - maxD[i] = objs[i].direction.Clamped.value; - maxS[i] = objs[i].strength; - } - maxD[objs.Length] = direction.Clamped.value; - maxS[objs.Length] = strength; - return new(Math.Max(maxD), Math.Max(maxS)); - } - public Vector Min(params Vector[] objs) - { - float[] minD = new float[objs.Length + 1]; - float[] minS = new float[objs.Length + 1]; - for (int i = 0; i < objs.Length; i++) - { - minD[i] = objs[i].direction.Clamped.value; - minS[i] = objs[i].strength; - } - minD[objs.Length] = direction.Clamped.value; - minS[objs.Length] = strength; - return new(Math.Min(minD), Math.Min(minS)); - } - - public override bool Equals(object obj) => base.Equals(obj); - public bool Equals(Vector other) => direction == other.direction && strength == other.strength; - public override int GetHashCode() => base.GetHashCode(); - public override string ToString() => "D: " + direction.ToString() + " | S: " + strength.ToString(); - public string ToString(string format) => "D: " + direction.ToString(format) + " | S: " + strength.ToString(format); - - public static Vector operator +(Vector a, Vector b) => new(a.direction + b.direction, a.strength + b.strength, false); - public static Vector operator -(Vector a, Vector b) => new(a.direction - b.direction, a.strength - b.strength, false); - public static Vector operator *(Vector a, Vector b) => new(a.direction * b.direction, a.strength * b.strength, false); - public static Vector operator /(Vector a, Vector b) => new(a.direction / b.direction, a.strength / b.strength, false); - public static bool operator ==(Vector a, Vector b) => a.Equals(b); - public static bool operator !=(Vector a, Vector b) => !a.Equals(b); - } - - [Serializable] - public struct Vector2 : IMathFunctions - { - public float x, y; - - public static Vector2 NegativeInfinity { get => new(float.NegativeInfinity, float.NegativeInfinity); } - public static Vector2 One { get => new(1, 1); } - public static Vector2 PositiveInfinity { get => new(float.PositiveInfinity, float.PositiveInfinity); } - public static Vector2 Zero { get => new(0, 0); } - - public Vector2(float x) => this = new Vector2(x, 0); - public Vector2(float x, float y) - { - this.x = x; - this.y = y; - } - - public Vector2 Average(params Vector2[] objs) - { - float[] averageX = new float[objs.Length + 1]; - float[] averageY = new float[objs.Length + 1]; - for (int i = 0; i < objs.Length; i++) - { - averageX[i] = objs[i].x; - averageY[i] = objs[i].y; - } - averageX[objs.Length] = x; - averageY[objs.Length] = y; - return new(Math.Average(averageX), Math.Average(averageY)); - } - public Vector2 Max(params Vector2[] objs) - { - float[] maxX = new float[objs.Length + 1]; - float[] maxY = new float[objs.Length + 1]; - for (int i = 0; i < objs.Length; i++) - { - maxX[i] = objs[i].x; - maxY[i] = objs[i].y; - } - maxX[objs.Length] = x; - maxY[objs.Length] = y; - return new(Math.Max(maxX), Math.Max(maxY)); - } - public Vector2 Min(params Vector2[] objs) - { - float[] minX = new float[objs.Length + 1]; - float[] minY = new float[objs.Length + 1]; - for (int i = 0; i < objs.Length; i++) - { - minX[i] = objs[i].x; - minY[i] = objs[i].y; - } - minX[objs.Length] = x; - minY[objs.Length] = y; - return new(Math.Min(minX), Math.Min(minY)); - } - - public override bool Equals(object obj) => base.Equals(obj); - public bool Equals(Vector2 other) => x == other.x && y == other.y; - public override int GetHashCode() => base.GetHashCode(); - public override string ToString() => "X: " + x.ToString() + " | Y: " + y.ToString(); - public string ToString(string format) => "X: " + x.ToString(format) + " | Y: " + y.ToString(format); - - public static Vector2 operator +(Vector2 a, Vector2 b) => new(a.x + b.x, a.y + b.y); - public static Vector2 operator +(Vector2 a, float b) => new(a.x + b, a.y + b); - public static Vector2 operator +(float a, Vector2 b) => new(a + b.x, a + b.y); - public static Vector2 operator -(Vector2 a, Vector2 b) => new(a.x - b.x, a.y - b.y); - public static Vector2 operator -(Vector2 a, float b) => new(a.x - b, a.y - b); - public static Vector2 operator -(float a, Vector2 b) => new(a - b.x, a - b.y); - public static Vector2 operator *(Vector2 a, Vector2 b) => new(a.x * b.x, a.y * b.y); - public static Vector2 operator *(Vector2 a, float b) => new(a.x * b, a.y * b); - public static Vector2 operator *(float a, Vector2 b) => new(a * b.x, a * b.y); - public static Vector2 operator /(Vector2 a, Vector2 b) => new(a.x / b.x, a.y / b.y); - public static Vector2 operator /(Vector2 a, float b) => new(a.x / b, a.y / b); - public static Vector2 operator /(float a, Vector2 b) => new(a / b.x, a / b.y); - public static bool operator ==(Vector2 a, Vector2 b) => a.Equals(b); - public static bool operator !=(Vector2 a, Vector2 b) => !a.Equals(b); - public static bool operator >(Vector2 a, Vector2 b) => a.x > b.x && a.y > b.y; - public static bool operator <(Vector2 a, Vector2 b) => a.x < b.x && a.y < b.y; - public static bool operator >=(Vector2 a, Vector2 b) => (a.x > b.x && a.y > b.y) || a.Equals(b); - public static bool operator <=(Vector2 a, Vector2 b) => (a.x < b.x && a.y < b.y) || a.Equals(b); - - public static explicit operator Vector2(Vector3 input) => new(input.x, input.y); - public static explicit operator Vector2(Vector4 input) => new(input.x, input.y); - } - [Serializable] - public struct Vector3 : IMathFunctions - { - public float x, y, z; - - public static Vector3 NegativeInfinity { get => new(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity); } - public static Vector3 One { get => new(1, 1, 1); } - public static Vector3 PositiveInfinity { get => new(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity); } - public static Vector3 Zero { get => new(0, 0, 0); } - - public Vector3(float x) => this = new(x, 0, 0); - public Vector3(float x, float y) => this = new(x, y, 0); - public Vector3(float x, float y, float z) - { - this.x = x; - this.y = y; - this.z = z; - } - - public Vector3 Average(params Vector3[] objs) - { - float[] averageX = new float[objs.Length + 1]; - float[] averageY = new float[objs.Length + 1]; - float[] averageZ = new float[objs.Length + 1]; - for (int i = 0; i < objs.Length; i++) - { - averageX[i] = objs[i].x; - averageY[i] = objs[i].y; - averageZ[i] = objs[i].z; - } - averageX[objs.Length] = x; - averageY[objs.Length] = y; - averageZ[objs.Length] = z; - return new(Math.Average(averageX), Math.Average(averageY), Math.Average(averageZ)); - } - public Vector3 Max(params Vector3[] objs) - { - float[] maxX = new float[objs.Length + 1]; - float[] maxY = new float[objs.Length + 1]; - float[] maxZ = new float[objs.Length + 1]; - for (int i = 0; i < objs.Length; i++) - { - maxX[i] = objs[i].x; - maxY[i] = objs[i].y; - maxZ[i] = objs[i].z; - } - maxX[objs.Length] = x; - maxY[objs.Length] = y; - maxZ[objs.Length] = z; - return new(Math.Max(maxX), Math.Max(maxY), Math.Max(maxZ)); - } - public Vector3 Min(params Vector3[] objs) - { - float[] minX = new float[objs.Length + 1]; - float[] minY = new float[objs.Length + 1]; - float[] minZ = new float[objs.Length + 1]; - for (int i = 0; i < objs.Length; i++) - { - minX[i] = objs[i].x; - minY[i] = objs[i].y; - minZ[i] = objs[i].z; - } - minX[objs.Length] = x; - minY[objs.Length] = y; - minZ[objs.Length] = z; - return new(Math.Min(minX), Math.Min(minY), Math.Min(minZ)); - } - - public override bool Equals(object obj) => base.Equals(obj); - public bool Equals(Vector3 other) => x == other.x && y == other.y && z == other.z; - public override int GetHashCode() => base.GetHashCode(); - public override string ToString() => "X: " + x.ToString() + " | Y: " + y.ToString() + " | Z:" + z.ToString(); - public string ToString(string format) => "X: " + x.ToString(format) + " | Y: " + y.ToString(format) + " | Z:" + z.ToString(format); - - public static Vector3 operator +(Vector3 a, Vector3 b) => new(a.x + b.x, a.y + b.y, a.z + b.z); - public static Vector3 operator +(Vector3 a, float b) => new(a.x + b, a.y + b, a.z + b); - public static Vector3 operator +(float a, Vector3 b) => new(a + b.x, a + b.y, a + b.z); - public static Vector3 operator -(Vector3 a, Vector3 b) => new(a.x - b.x, a.y - b.y, a.z - b.z); - public static Vector3 operator -(Vector3 a, float b) => new(a.x - b, a.y - b, a.z - b); - public static Vector3 operator -(float a, Vector3 b) => new(a - b.x, a - b.y, a - b.z); - public static Vector3 operator *(Vector3 a, Vector3 b) => new(a.x * b.x, a.y * b.y, a.z * b.z); - public static Vector3 operator *(Vector3 a, float b) => new(a.x * b, a.y * b, a.z * b); - public static Vector3 operator *(float a, Vector3 b) => new(a * b.x, a * b.y, a * b.z); - public static Vector3 operator /(Vector3 a, Vector3 b) => new(a.x / b.x, a.y / b.y, a.z / b.z); - public static Vector3 operator /(Vector3 a, float b) => new(a.x / b, a.y / b, a.z / b); - public static Vector3 operator /(float a, Vector3 b) => new(a / b.x, a / b.y, a / b.z); - public static bool operator ==(Vector3 a, Vector3 b) => a.Equals(b); - public static bool operator !=(Vector3 a, Vector3 b) => !a.Equals(b); - public static bool operator >(Vector3 a, Vector3 b) => a.x > b.x && a.y > b.y && a.z > b.z; - public static bool operator <(Vector3 a, Vector3 b) => a.x < b.x && a.y < b.y && a.z < b.z; - public static bool operator >=(Vector3 a, Vector3 b) => (a.x > b.x && a.y > b.y && a.z > b.z) || a.Equals(b); - public static bool operator <=(Vector3 a, Vector3 b) => (a.x < b.x && a.y < b.y && a.z < b.z) || a.Equals(b); - - public static implicit operator Vector3(Color input) => new(input.r, input.g, input.b); - public static implicit operator Vector3(Vector2 input) => new(input.x, input.y); - public static explicit operator Vector3(Vector4 input) => new(input.x, input.y, input.z); - } - [Serializable] - public struct Vector4 : IMathFunctions - { - public float x, y, z, w; - - public static Vector4 NegativeInfinity { get => new(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity); } - public static Vector4 One { get => new(1, 1, 1, 1); } - public static Vector4 PositiveInfinity { get => new(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity); } - public static Vector4 Zero { get => new(0, 0, 0, 0); } - - public Vector4(float x) => this = new(x, 0, 0, 0); - public Vector4(float x, float y) => this = new(x, y, 0, 0); - public Vector4(float x, float y, float z) => this = new(x, y, z, 0); - public Vector4(float x, float y, float z, float w) - { - this.x = x; - this.y = y; - this.z = z; - this.w = w; - } - - public Vector4 Average(params Vector4[] objs) - { - float[] averageX = new float[objs.Length + 1]; - float[] averageY = new float[objs.Length + 1]; - float[] averageZ = new float[objs.Length + 1]; - float[] averageW = new float[objs.Length + 1]; - for (int i = 0; i < objs.Length; i++) - { - averageX[i] = objs[i].x; - averageY[i] = objs[i].y; - averageZ[i] = objs[i].z; - averageW[i] = objs[i].w; - } - averageX[objs.Length] = x; - averageY[objs.Length] = y; - averageZ[objs.Length] = z; - averageW[objs.Length] = w; - return new(Math.Average(averageX), Math.Average(averageY), Math.Average(averageZ), Math.Average(averageW)); - } - public Vector4 Max(params Vector4[] objs) - { - float[] maxX = new float[objs.Length + 1]; - float[] maxY = new float[objs.Length + 1]; - float[] maxZ = new float[objs.Length + 1]; - float[] maxW = new float[objs.Length + 1]; - for (int i = 0; i < objs.Length; i++) - { - maxX[i] = objs[i].x; - maxY[i] = objs[i].y; - maxZ[i] = objs[i].z; - maxW[i] = objs[i].w; - } - maxX[objs.Length] = x; - maxY[objs.Length] = y; - maxZ[objs.Length] = z; - maxW[objs.Length] = w; - return new(Math.Max(maxX), Math.Max(maxY), Math.Max(maxZ), Math.Max(maxW)); - } - public Vector4 Min(params Vector4[] objs) - { - float[] minX = new float[objs.Length + 1]; - float[] minY = new float[objs.Length + 1]; - float[] minZ = new float[objs.Length + 1]; - float[] minW = new float[objs.Length + 1]; - for (int i = 0; i < objs.Length; i++) - { - minX[i] = objs[i].x; - minY[i] = objs[i].y; - minZ[i] = objs[i].z; - minW[i] = objs[i].w; - } - minX[objs.Length] = x; - minY[objs.Length] = y; - minZ[objs.Length] = z; - minW[objs.Length] = w; - return new(Math.Min(minX), Math.Min(minY), Math.Min(minZ), Math.Min(minW)); - } - - public override bool Equals(object obj) => base.Equals(obj); - public bool Equals(Vector4 other) => x == other.x && y == other.y && z == other.z && w == other.w; - public override int GetHashCode() => base.GetHashCode(); - public override string ToString() => "X: " + x.ToString() + " | Y: " + y.ToString() + " | Z: " + z.ToString() + " | W: " + w.ToString(); - public string ToString(string format) => "X: " + x.ToString(format) + " | Y: " + y.ToString(format) + " | Z: " + z.ToString(format) + " | W: " + w.ToString(format); - - public static Vector4 operator +(Vector4 a, Vector4 b) => new(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w); - public static Vector4 operator +(Vector4 a, float b) => new(a.x + b, a.y + b, a.z + b, a.w + b); - public static Vector4 operator +(float a, Vector4 b) => new(a + b.x, a + b.y, a + b.z, a + b.w); - public static Vector4 operator -(Vector4 a, Vector4 b) => new(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w); - public static Vector4 operator -(Vector4 a, float b) => new(a.x - b, a.y - b, a.z - b, a.w - b); - public static Vector4 operator -(float a, Vector4 b) => new(a - b.x, a - b.y, a - b.z, a - b.w); - public static Vector4 operator *(Vector4 a, Vector4 b) => new(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w); - public static Vector4 operator *(Vector4 a, float b) => new(a.x * b, a.y * b, a.z * b, a.w * b); - public static Vector4 operator *(float a, Vector4 b) => new(a * b.x, a * b.y, a * b.z, a * b.w); - public static Vector4 operator /(Vector4 a, Vector4 b) => new(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w); - public static Vector4 operator /(Vector4 a, float b) => new(a.x / b, a.y / b, a.z / b, a.w / b); - public static Vector4 operator /(float a, Vector4 b) => new(a / b.x, a / b.y, a / b.z, a / b.w); - public static bool operator ==(Vector4 a, Vector4 b) => a.Equals(b); - public static bool operator !=(Vector4 a, Vector4 b) => !a.Equals(b); - public static bool operator >(Vector4 a, Vector4 b) => a.x > b.x && a.y > b.y && a.z > b.z && a.w > b.w; - public static bool operator <(Vector4 a, Vector4 b) => a.x < b.x && a.y < b.y && a.z < b.z && a.w < b.w; - public static bool operator >=(Vector4 a, Vector4 b) => (a.x > b.x && a.y > b.y && a.z > b.z && a.w > b.w) || a.Equals(b); - public static bool operator <=(Vector4 a, Vector4 b) => (a.x < b.x && a.y < b.y && a.z < b.z && a.w < b.w) || a.Equals(b); - - public static implicit operator Vector4(Color input) => new(input.r, input.g, input.b, input.a); - public static implicit operator Vector4(Vector2 input) => new(input.x, input.y); - public static implicit operator Vector4(Vector3 input) => new(input.x, input.y, input.z); - } - - namespace Interfaces - { - public interface IMathFunctions - { - public T Average(params T[] objs); - public T Max(params T[] objs); - public T Min(params T[] objs); - } - - public interface INegatives - { - public T Absolute { get; } - public bool IsNegative { get; } - public T Negative { get; } - public T Positive { get; } - } - } -} \ No newline at end of file diff --git a/changelog.md b/changelog.md deleted file mode 100644 index 72c6c80..0000000 --- a/changelog.md +++ /dev/null @@ -1,165 +0,0 @@ -# Version 2021.0: - The Original Release of the Library. - Includes: - * Nerd_STF: - * public static class Hashes - * Nerd_STF.Interfaces: - * public interface INegatives - * Nerd_STF.Lists: - * public class List - * public class Matrix - * Nerd_STF.Mathematics: - * public struct Angle - * public struct Color - * public struct ColorByte - * public static class Math - * public struct Percent - * public struct Vector - * public struct Vector2 - * public struct Vector3 - * public struct Vector4 - * public class Miscellaneous - * public struct Optional - * public static class Stats - -# Version 2021.1: - This update is mainly centered around files and filesaving. - * Nerd_STF - + Nerd_STF.Filesaving - + File - + BinaryFile - + ByteFile - + TextFile - - public class Miscellaneous - -# Version 2021.2: - This update is centered around lists. - * Nerd_STF: - * public static class Hashes: - + public static string SHA1(string) - + public static string SHA256(string) - + public static string SHA384(string) - + public static string SHA512(string) - + public static byte[] MD5(byte[]) - + public static byte[] SHA1(byte[]) - + public static byte[] SHA256(byte[]) - + public static byte[] SHA384(byte[]) - + public static byte[] SHA512(byte[]) - = Made `public static string MD5(string)` include more of my own scripting - * Nerd_STF.File: - = Nerd_STF.Filesaving: Moved to Nerd_STF.File.Saving - * Nerd_STF.File.Saving: - + public class BinaryFile - * public class ByteFile: - + public override bool TryLoad(out File>) - = Made `public static ByteFile Load(string)` load files faster - = Made `public override void Load(bool)` load files faster - = Made `public override void Save()` save files faster - = Made `public override void Write(byte, bool)` save files faster - = Made `public override void Write(List, bool)` save files faster - * public abstract class File: - + public bool Exists; - + public abstract bool TryLoad(out File) - * public class TextFile: - + public override bool TryLoad(out File) - = Made `public static TextFile Load(string)` load files faster - = Made `public override void Load(bool)` load files faster - = Made `public override Save()` save files faster - = Made `public override void Write(char, bool)` save files faster - = Made `public override void Write(string, bool)` save files faster - - Nerd_STF.Interfaces: - = Moved `public interface INegatives` to `Nerd_STF.Mathematics.Interfaces` - * Nerd_STF.Lists: - + public class ReadOnlyList - = public class List: Completely reworked everything in `List` - + public int this[T] { get; set; } - + public List(IEnumerable) - + public bool IsEmpty { get; } - + public bool IsNull { get; } - + public bool IsNullOrEmpty { get; } - + public bool Contains(Predicate) - + public int Count (Predicate) - + public void AddRange(IEnumerable) - + public bool Any(Predicate) - + public bool Any(T) - + public T Find(Predicate) - + public T Find(Predicate, int) - + public T Find(Predicate, int, int) - + public T FindOrDefault(Predicate) - + public T FindOrDefault(T) - + public T FindOrDefault(Predicate, int) - + public T FindOrDefault(T, int) - + public T FindOrDefault(Predicate, int, int) - + public T FindOrDefault(T, int, int) - + public List FindAll(Predicate) - + public List FindAll(Predicate, int) - + public List FindAll(Predicate, int, int) - + public List FindLast(Predicate) - + public List FindLast(Predicate, int) - + public List FindLast(Predicate, int, int) - + public T FindLastOrDefault(Predicate) - + public T FindLastOrDefault(T) - + public T FindLastOrDefault(Predicate, int) - + public T FindLastOrDefault(T, int) - + public T FindLastOrDefault(Predicate, int, int) - + public T FindLastOrDefault(T, int, int) - + public int FindIndex(Predicate) - + public int FindIndex(Predicate, int) - + public int FindIndex(Predicate, int, int) - + public List FindAllIndex(Predicate) - + public List FindAllIndex(Predicate, int) - + public List FindAllIndex(Predicate, int, int) - + public int FindLastIndex(Predicate) - + public int FindLastIndex(Predicate, int) - + public int FindLastIndex(Predicate, int, int) - + public bool MatchesAll(Predicate) - + public void Remove(Predicate) - + public void RemoveAll(Predicate) - + public void RemoveAll(T) - + public void RemoveLast(Predicate) - + public void RemoveLast(T) - + IEnumerator IEnumerable.GetEnumerator() - + public void Randomize() - + public List FindAllIndex() - + public void Shuffle() - + public List FindAllIndex(int) - + public List FindAllIndex(int, int) - + public ReadOnlyList ToReadOnly() - = Made `public List Duplicate()` a readonly variable and better (`public List Duplicate { get; }`) - = Renamed the internal array to `array,` as opposed to `list` - = Renamed `public void Add(T[])` to `public void AddRange(T[])` - = Renamed `public void Add(List)` to `public void AddRange(List)` - = Renamed `public bool Compare(T)` to `public bool Contains(T)` - = Renamed `public void Remove(int, bool)` to `public void Remove(int)` - = Renamed `public void SetAll(T)` to `public void Fill(T)` - = Made `public string ToString(bool)` count up from zero instead of one when the bool is set to true. - = Renamed `public ReadOnlyCollection AsReadOnly()` to `public ReadOnlyCollection ToSystemReadOnly()` - - public bool Check(int) - - public void Convert(T) - - public void Convert(T[]) - - public void Convert(List) - - public T Get(int) - - public void Get(int, out T) - - public T[] GetAll() - - public void Set(int, T) - - public void Set(T[]) - - public void Set(List) - - public static List AllDefault(int) - - public static List operator +(T[], List) - - public static List operator +(List, int) - - public static List operator +(T, List) - - public static List operator *(List, int) - - public static explicit operator T[](List) - - public static explicit operator List(T[]) - = Marked `public class Nerd_STF.Lists.Matrix` as deprecated. This class will be removed or heavily modified in a future release. Also removed all instances of removed List methods and replaced them with work-arounds. - * Nerd_STF.Mathematics: - = Marked `public struct Angle` as serializable - = Marked `public struct Color` as serializable - = Marked `public struct ColorByte` as serializable - = Marked `public struct Percent` as serializable - = Marked `public struct Vector` as serializable - = Marked `public struct Vector2` as serializable - = Marked `public struct Vector3` as serializable - = Marked `public struct Vector4` as serializable - + public static class Misc - + public static string PlaceMaker(int) \ No newline at end of file