diff --git a/Nerd_STF/Mathematics/Geometry/Box2D.cs b/Nerd_STF/Mathematics/Geometry/Box2D.cs deleted file mode 100644 index 1691184..0000000 --- a/Nerd_STF/Mathematics/Geometry/Box2D.cs +++ /dev/null @@ -1,115 +0,0 @@ -namespace Nerd_STF.Mathematics.Geometry; - -public record class Box2d : IAbsolute, IAverage, ICeiling, IClamp, IContains, - IEquatable, IFloor, ILerp, IMedian, IRound, IShape2d, - ISplittable -{ - public static Box2d Unit => new(Float3.Zero, Float2.One); - - public Float3 MaxVert - { - get => center + (size / 2); - set - { - Float3 diff = center - value; - size = (Float2)diff * 2f; - } - } - public Float3 MinVert - { - get => center - (size / 2); - set - { - Float3 diff = center + value; - size = (Float2)diff * 2f; - } - } - - public float Area => size.x * size.y; - public float Perimeter => 2 * (size.x + size.y); - - public Float3 center; - public Float2 size; - - public Box2d(Float3 min, Float3 max) : this(Float3.Average(min, max), (Float2)(min - max)) { } - public Box2d(Float3 center, Float2 size) - { - this.center = center; - this.size = size; - } - public Box2d(Fill fill) : this(fill, new Float2(fill(3), fill(4))) { } - - public float this[int index] - { - get => size[index]; - set => size[index] = value; - } - - public static Box2d Absolute(Box2d val) => new(Float3.Absolute(val.MinVert), Float3.Absolute(val.MaxVert)); - public static Box2d Average(params Box2d[] vals) - { - (Float3[] centers, Float2[] sizes) = SplitArray(vals); - return new(Float3.Average(centers), Float2.Average(sizes)); - } - public static Box2d Ceiling(Box2d val) => new(Float3.Ceiling(val.center), Float2.Ceiling(val.size)); - public static Box2d Clamp(Box2d val, Box2d min, Box2d max) => - new(Float3.Clamp(val.center, min.center, max.center), Float2.Clamp(val.size, min.size, max.size)); - public static Box2d Floor(Box2d val) => new(Float3.Floor(val.center), Float2.Floor(val.size)); - public static Box2d Lerp(Box2d a, Box2d b, float t, bool clamp = true) => - new(Float3.Lerp(a.center, b.center, t, clamp), Float2.Lerp(a.size, b.size, t, clamp)); - public static Box2d Median(params Box2d[] vals) - { - (Float3[] verts, Float2[] sizes) = SplitArray(vals); - return new(Float3.Median(verts), Float2.Median(sizes)); - } - public static Box2d Round(Box2d val) => new(Float3.Round(val.center), Float2.Round(val.size)); - - public static (Float3[] centers, Float2[] sizes) SplitArray(params Box2d[] vals) - { - Float3[] centers = new Float3[vals.Length]; - Float2[] sizes = new Float2[vals.Length]; - - for (int i = 0; i < vals.Length; i++) - { - centers[i] = vals[i].center; - sizes[i] = vals[i].size; - } - - return (centers, sizes); - } - - public virtual bool Equals(Box2d? other) - { - if (other is null) return false; - return center == other.center && size == other.size; - } - public override int GetHashCode() => base.GetHashCode(); - - public bool Contains(Float3 vert) - { - Float2 diff = Float2.Absolute((Float2)(center - vert)); - return diff.x <= size.x && diff.y <= size.y; - } - - protected virtual bool PrintMembers(StringBuilder builder) - { - builder.Append("Min = "); - builder.Append(MinVert); - builder.Append(", Max = "); - builder.Append(MaxVert); - return true; - } - - public static Box2d operator +(Box2d a, Float3 b) => new(a.center + b, a.size); - public static Box2d operator +(Box2d a, Float2 b) => new(a.center, a.size + b); - public static Box2d operator -(Box2d b) => new(-b.MaxVert, -b.MinVert); - public static Box2d operator -(Box2d a, Float3 b) => new(a.center - b, a.size); - public static Box2d operator -(Box2d a, Float2 b) => new(a.center, a.size - b); - public static Box2d operator *(Box2d a, float b) => new(a.center * b, a.size * b); - public static Box2d operator *(Box2d a, Float2 b) => new(a.center, a.size * b); - public static Box2d operator /(Box2d a, float b) => new(a.center / b, a.size / b); - public static Box2d operator /(Box2d a, Float2 b) => new(a.center, a.size / b); - - public static implicit operator Box2d(Fill fill) => new(fill); - public static explicit operator Box2d(Box3d box) => new(box.center, (Float2)box.size); -} diff --git a/Nerd_STF/Mathematics/Geometry/Box3D.cs b/Nerd_STF/Mathematics/Geometry/Box3D.cs deleted file mode 100644 index 3d527b7..0000000 --- a/Nerd_STF/Mathematics/Geometry/Box3D.cs +++ /dev/null @@ -1,118 +0,0 @@ -using Nerd_STF.Mathematics.Abstract; - -namespace Nerd_STF.Mathematics.Geometry; - -public record class Box3d : IAbsolute, IAverage, ICeiling, IClamp, - IContains, IEquatable, IFloor, ILerp, IMedian, - IRound, IShape3d, ISplittable -{ - public static Box3d Unit => new(Float3.Zero, Float3.One); - - public Float3 MaxVert - { - get => center + (size / 2); - set - { - Float3 diff = center - value; - size = diff * 2; - } - } - public Float3 MinVert - { - get => center - (size / 2); - set - { - Float3 diff = center + value; - size = diff * 2; - } - } - - public float Perimeter => 2 * (size.x + size.y + size.z); - public float SurfaceArea => 2 * (size.x * size.y + size.y * size.z + size.x * size.z); - public float Volume => size.x * size.y * size.z; - - public Float3 center; - public Float3 size; - - public Box3d(Box2d box) : this(box.center, (Float3)box.size) { } - public Box3d(Float3 min, Float3 max) - { - this.center = Float3.Average(min, max); - this.size = max - min; - } - public Box3d(Fill fill) : this(fill, new Float3(fill(3), fill(4), fill(5))) { } - - public float this[int index] - { - get => size[index]; - set => size[index] = value; - } - - public static Box3d Absolute(Box3d val) => new(Float3.Absolute(val.MinVert), Float3.Absolute(val.MaxVert)); - public static Box3d Average(params Box3d[] vals) - { - (Float3[] centers, Float3[] sizes) = SplitArray(vals); - return new(Float3.Average(centers), Float3.Average(sizes)); - } - public static Box3d Ceiling(Box3d val) => - new(Float3.Ceiling(val.center), (Float3)Float3.Ceiling(val.size)); - public static Box3d Clamp(Box3d val, Box3d min, Box3d max) => - new(Float3.Clamp(val.center, min.center, max.center), Float3.Clamp(val.size, min.size, max.size)); - public static Box3d Floor(Box3d val) => - new(Float3.Floor(val.center), (Float3)Float3.Floor(val.size)); - public static Box3d Lerp(Box3d a, Box3d b, float t, bool clamp = true) => - new(Float3.Lerp(a.center, b.center, t, clamp), Float3.Lerp(a.size, b.size, t, clamp)); - public static Box3d Median(params Box3d[] vals) - { - (Float3[] verts, Float3[] sizes) = SplitArray(vals); - return new(Float3.Median(verts), Float3.Median(sizes)); - } - public static Box3d Round(Box3d val) => new(Float3.Ceiling(val.center), (Float3)Float3.Ceiling(val.size)); - - public static (Float3[] centers, Float3[] sizes) SplitArray(params Box3d[] vals) - { - Float3[] centers = new Float3[vals.Length]; - Float3[] sizes = new Float3[vals.Length]; - - for (int i = 0; i < vals.Length; i++) - { - centers[i] = vals[i].center; - sizes[i] = vals[i].size; - } - - return (centers, sizes); - } - - public virtual bool Equals(Box3d? other) - { - if (other is null) return false; - return center == other.center && size == other.size; - } - public override int GetHashCode() => base.GetHashCode(); - - public bool Contains(Float3 vert) - { - Float3 diff = Float3.Absolute(center - vert); - return diff.x <= size.x && diff.y <= size.y && diff.z <= size.z; - } - - protected virtual bool PrintMembers(StringBuilder builder) - { - builder.Append("Min = "); - builder.Append(MinVert); - builder.Append(", Max = "); - builder.Append(MaxVert); - return true; - } - - public static Box3d operator +(Box3d a, Float3 b) => new(a.center + b, a.size); - public static Box3d operator -(Box3d b) => new(-b.MaxVert, -b.MinVert); - public static Box3d operator -(Box3d a, Float3 b) => new(a.center - b, a.size); - public static Box3d operator *(Box3d a, float b) => new(a.center * b, a.size * b); - public static Box3d operator *(Box3d a, Float3 b) => new(a.center, a.size * b); - public static Box3d operator /(Box3d a, float b) => new(a.center / b, a.size / b); - public static Box3d operator /(Box3d a, Float3 b) => new(a.center, a.size / b); - - public static implicit operator Box3d(Fill fill) => new(fill); - public static implicit operator Box3d(Box2d box) => new(box); -} diff --git a/Nerd_STF/Mathematics/Geometry/Line.cs b/Nerd_STF/Mathematics/Geometry/Line.cs deleted file mode 100644 index d9438df..0000000 --- a/Nerd_STF/Mathematics/Geometry/Line.cs +++ /dev/null @@ -1,228 +0,0 @@ -using Nerd_STF.Mathematics.Abstract; - -namespace Nerd_STF.Mathematics.Geometry; - -public record class Line : IAbsolute, IAverage, ICeiling, IClamp, IClosestTo, - IComparable, IContains, IEquatable, IFloor, IFromTuple, - IGroup, IIndexAll, IIndexRangeAll, ILerp, IMedian, IPresets3d, - IRound, ISplittable, ISubdivide -{ - public static Line Back => new(Float3.Zero, Float3.Back); - public static Line Down => new(Float3.Zero, Float3.Down); - public static Line Forward => new(Float3.Zero, Float3.Forward); - public static Line Left => new(Float3.Zero, Float3.Left); - public static Line Right => new(Float3.Zero, Float3.Right); - public static Line Up => new(Float3.Zero, Float3.Up); - - public static Line One => new(Float3.Zero, Float3.One); - public static Line Zero => new(Float3.Zero, Float3.Zero); - - public float Length => (b - a).Magnitude; - public Float3 Midpoint => Float3.Average(a, b); - - public Float3 a, b; - - public Line(Float3 a, Float3 b) - { - this.a = a; - this.b = b; - } - public Line(float x1, float y1, float x2, float y2) : this(new(x1, y1), new(x2, y2)) { } - public Line(float x1, float y1, float z1, float x2, float y2, float z2) - : this(new(x1, y1, z1), new(x2, y2, z2)) { } - public Line(Fill fill) : this(fill(0), fill(1)) { } - public Line(Fill fill) : this(fill(0), 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 Float3 this[int index] - { - get => index switch - { - 0 => a, - 1 => b, - _ => throw new IndexOutOfRangeException(nameof(index)), - }; - set - { - switch (index) - { - case 0: - a = value; - break; - - case 1: - b = value; - break; - - default: throw new IndexOutOfRangeException(nameof(index)); - } - } - } - public Float3 this[Index index] - { - get => this[index.IsFromEnd ? 2 - index.Value : index.Value]; - set => this[index.IsFromEnd ? 2 - index.Value : index.Value] = value; - } - public Float3[] this[Range range] - { - get - { - int start = range.Start.IsFromEnd ? 2 - range.Start.Value : range.Start.Value; - int end = range.End.IsFromEnd ? 2 - range.End.Value : range.End.Value; - List res = new(); - for (int i = start; i < end; i++) res.Add(this[i]); - return res.ToArray(); - } - set - { - int start = range.Start.IsFromEnd ? 2 - range.Start.Value : range.Start.Value; - int end = range.End.IsFromEnd ? 2 - range.End.Value : range.End.Value; - for (int i = start; i < end; i++) this[i] = value[i]; - } - } - - public static Line Absolute(Line val) => new(Float3.Absolute(val.a), Float3.Absolute(val.b)); - public static Line Average(params Line[] vals) - { - (Float3[] starts, Float3[] ends) = SplitArray(vals); - return new(Float3.Average(starts), Float3.Average(ends)); - } - public static Line Ceiling(Line val) => new(Float3.Ceiling(val.a), Float3.Ceiling(val.b)); - public static Line Clamp(Line val, Line min, Line max) => - new(Float3.Clamp(val.a, min.a, max.a), Float3.Clamp(val.b, min.b, max.b)); - public static Line Floor(Line val) => new(Float3.Floor(val.a), Float3.Floor(val.b)); - public static Line Lerp(Line a, Line b, float t, bool clamp = true) => - new(Float3.Lerp(a.a, b.a, t, clamp), Float3.Lerp(a.b, b.b, t, clamp)); - public static Line Median(params Line[] vals) - { - (Float3[] starts, Float3[] ends) = SplitArray(vals); - return new(Float3.Median(starts), Float3.Median(ends)); - } - public static Line Round(Line val) => new(Float3.Round(val.a), Float3.Round(val.b)); - - public static (Float3[] starts, Float3[] ends) SplitArray(params Line[] lines) - { - Float3[] starts = new Float3[lines.Length], ends = new Float3[lines.Length]; - for (int i = 0; i < lines.Length; i++) - { - starts[i] = lines[i].a; - ends[i] = lines[i].b; - } - return (starts, ends); - } - - public virtual bool Equals(Line? other) - { - if (other is null) return false; - return a == other.a && b == other.b; - } - public override int GetHashCode() => base.GetHashCode(); - - [Obsolete("This method is a bit ambiguous. You should instead compare " + - nameof(Length) + "s directly.")] - public int CompareTo(Line? line) - { - if (line is null) return -1; - return Length.CompareTo(line.Length); - } - - public bool Contains(Float3 vert) - { - Float3 diffA = a - vert, diffB = a - b; - float lerpVal = diffA.Magnitude * diffB.InverseMagnitude; - return Float3.Lerp(a, b, lerpVal) == vert; - } - - public Float3 ClosestTo(Float3 vert) => ClosestTo(vert, Calculus.DefaultStep); - public Float3 ClosestTo(Float3 vert, float step) - { - Float3 closestA = a, closestB = b; - for (float t = 0; t <= 1; t += step) - { - Float3 valA = Float3.Lerp(a, b, t); - Float3 valB = Float3.Lerp(b, a, t); - closestA = (valA - vert).Magnitude < (closestA - vert).Magnitude ? valA : closestA; - closestB = (valB - vert).Magnitude < (closestB - vert).Magnitude ? valB : closestB; - } - - return (closestA - vert).Magnitude >= (closestB - vert).Magnitude ? closestA : closestB; - } - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - public IEnumerator GetEnumerator() - { - yield return a; - yield return b; - } - - public Line[] Subdivide() - { - Float3 middle = Float3.Lerp(a, b, 0.5f); - return new Line[] { new(a, middle), new(middle, b) }; - } - public Line[] Subdivide(int iterations) - { - if (iterations < 1) return Array.Empty(); - List lines = new(Subdivide()); - for (int i = 1; i < iterations; i++) - { - List add = new(); - for (int j = 0; j < lines.Count; j++) add.AddRange(lines[j].Subdivide()); - lines = add; - } - return lines.ToArray(); - } - - public Float3[] ToArray() => new Float3[] { a, b }; - public Fill ToFill() - { - Line @this = this; - return i => @this[i]; - } - public List ToList() => new() { a, b }; - - public float[] ToFloatArray() => new float[] { a.x, a.y, a.z, - b.x, b.y, b.z }; - public List ToFloatList() => new() { a.x, a.y, a.z, - b.x, b.y, b.z }; - - protected virtual bool PrintMembers(StringBuilder builder) - { - builder.Append("A = "); - builder.Append(a); - builder.Append(", B = "); - builder.Append(b); - return true; - } - - public static Line operator +(Line a, Line b) => new(a.a + b.a, a.b + b.b); - public static Line operator +(Line a, Float3 b) => new(a.a + b, a.b + b); - public static Line operator -(Line l) => new(-l.a, -l.b); - public static Line operator -(Line a, Line b) => new(a.a - b.a, a.b - b.b); - public static Line operator -(Line a, Float3 b) => new(a.a - b, a.b - b); - public static Line operator *(Line a, Line b) => new(a.a * b.a, a.b * b.b); - public static Line operator *(Line a, Float3 b) => new(a.a * b, a.b * b); - public static Line operator *(Line a, float b) => new(a.a * b, a.b * b); - public static Line operator /(Line a, Line b) => new(a.a / b.a, a.b / b.b); - public static Line operator /(Line a, Float3 b) => new(a.a / b, a.b / b); - public static Line operator /(Line a, float b) => new(a.a / b, a.b / b); - [Obsolete("This operator is a bit ambiguous. You should instead compare " + - nameof(Length) + "s directly.")] - public static bool operator >(Line a, Line b) => a.CompareTo(b) > 0; - [Obsolete("This operator is a bit ambiguous. You should instead compare " + - nameof(Length) + "s directly.")] - public static bool operator <(Line a, Line b) => a.CompareTo(b) < 0; - [Obsolete("This operator is a bit ambiguous (and misleading at times). " + - "You should instead compare " + nameof(Length) + "s directly.")] - public static bool operator >=(Line a, Line b) => a > b || a == b; - [Obsolete("This operator is a bit ambiguous (and misleading at times). " + - "You should instead compare " + nameof(Length) + "s directly.")] - public static bool operator <=(Line a, Line b) => a < b || a == 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((Float3 start, Float3 end) val) => new(val.start, val.end); -} diff --git a/Nerd_STF/Mathematics/Geometry/Polygon.cs b/Nerd_STF/Mathematics/Geometry/Polygon.cs deleted file mode 100644 index 4fe7e71..0000000 --- a/Nerd_STF/Mathematics/Geometry/Polygon.cs +++ /dev/null @@ -1,452 +0,0 @@ -namespace Nerd_STF.Mathematics.Geometry; - -[Obsolete("This struct is a garbage fire. This will be completely redesigned in v2.5.0")] -public struct Polygon : ICloneable, IEquatable, IGroup, ISubdivide, ITriangulate -{ - public Line[] Lines - { - get => p_lines; - set - { - p_lines = value; - p_verts = GenerateVerts(value); - } - } - public Float3 Midpoint => Float3.Average(Verts); - public Float3[] Verts - { - get => p_verts; - set - { - p_verts = value; - p_lines = GenerateLines(value); - } - } - - private Line[] p_lines; - private Float3[] p_verts; - - [Obsolete("This method uses the Polygon.Triangulate() function, which has issues. It will be fixed in a " + - "future update.")] - public float Area - { - get - { - float val = 0; - foreach (Triangle t in Triangulate()) val += t.Area; - return val; - } - } - public float Perimeter - { - get - { - float val = 0; - foreach (Line l in Lines) val += l.Length; - return val; - } - } - - public Polygon() - { - p_lines = Array.Empty(); - p_verts = Array.Empty(); - } - public Polygon(Fill fill) - { - List verts = new(); - int i = 0; - while (true) - { - Float3? v = fill(i); - if (!v.HasValue) break; - verts.Add(v.Value); - } - this = new(verts.ToArray()); - } - public Polygon(Fill fill) - { - List lines = new(); - int i = 0; - while (true) - { - Line? v = fill(i); - if (v is null) break; - lines.Add(v); - } - this = new(lines.ToArray()); - } - public Polygon(Fill fill, int length) - { - List verts = new(); - for (int i = 0; i < length; i++) verts.Add(fill(i)); - this = new(verts.ToArray()); - } - public Polygon(Fill fill, int length) - { - List lines = new(); - for (int i = 0; i < length; i++) lines.Add(fill(i)); - this = new(lines.ToArray()); - } - public Polygon(params Float3[] verts) - { - p_verts = new Float3[verts.Length]; - for (int i = 0; i < verts.Length; i++) p_verts[i] = verts[i]; - p_lines = GenerateLines(p_verts); - } - public Polygon(params Line[] lines) - { - p_lines = lines; - p_verts = GenerateVerts(lines); - } - - public Float3 this[int index] - { - get => Verts[index]; - set => Verts[index] = value; - } - - public static Polygon CreateCircle(int vertCount) - { - List parts = new(); - for (int i = 0; i < vertCount; i++) - { - float val = Constants.Tau * i / vertCount; - parts.Add(new(Mathf.Cos(val), Mathf.Sin(val))); - } - return new(parts.ToArray()); - } - - public static Polygon Absolute(Polygon val) - { - Float3[] v = val.Verts; - for (int i = 0; i < v.Length; i++) v[i] = Float3.Absolute(v[i]); - return new(v); - } - public static Polygon Average(params Polygon[] vals) - { - if (!CheckVerts(vals)) throw new DifferingVertCountException(nameof(vals), vals); - if (vals.Length < 1) return default; - - Line[][] lines = new Line[vals.Length][]; - for (int i = 0; i < vals.Length; i++) lines[i] = vals[i].Lines; - - Line[] res = new Line[vals[0].Lines.Length]; - for (int i = 0; i < res.Length; i++) - { - Line[] row = new Line[vals.Length]; - for (int j = 0; j < vals[0].Lines.Length; j++) row[j] = vals[j].Lines[i]; - res[i] = Line.Average(row); - } - - return new(res); - } - public static Polygon Ceiling(Polygon val) - { - Float3[] v = val.Verts; - for (int i = 0; i < v.Length; i++) v[i] = Float3.Ceiling(v[i]); - return new(v); - } - public static Polygon Clamp(Polygon val, Polygon min, Polygon max) - { - if (!CheckVerts(val, min, max)) throw new DifferingVertCountException(val, min, max); - Line[][] lines = new Line[3][] { val.Lines, min.Lines, max.Lines }; - Line[] res = new Line[val.Lines.Length]; - for (int i = 0; i < res.Length; i++) res[i] = Line.Clamp(lines[0][i], lines[1][i], lines[2][i]); - return new(res); - } - public static Polygon Floor(Polygon val) - { - Float3[] v = val.Verts; - for (int i = 0; i < v.Length; i++) v[i] = Float3.Floor(v[i]); - return new(v); - } - public static Polygon Lerp(Polygon a, Polygon b, float t, bool clamp = true) - { - if (!CheckVerts(a, b)) throw new DifferingVertCountException(a, b); - Line[][] lines = new Line[2][] { a.Lines, b.Lines }; - Line[] res = new Line[a.Lines.Length]; - for (int i = 0; i < res.Length; i++) res[i] = Line.Lerp(lines[0][i], lines[1][i], t, clamp); - return new(res); - } - public static Polygon Median(params Polygon[] vals) - { - if (!CheckVerts(vals)) throw new DifferingVertCountException(nameof(vals), vals); - if (vals.Length < 1) return default; - - Line[][] lines = new Line[vals.Length][]; - for (int i = 0; i < vals.Length; i++) lines[i] = vals[i].Lines; - - Line[] res = new Line[vals[0].Lines.Length]; - for (int i = 0; i < res.Length; i++) - { - Line[] row = new Line[vals.Length]; - for (int j = 0; j < vals[0].Lines.Length; j++) row[j] = vals[j].Lines[i]; - res[i] = Line.Median(row); - } - - return new(res); - } - - public static float[] ToFloatArrayAll(params Polygon[] polys) => ToFloatListAll(polys).ToArray(); - public static List ToFloatListAll(params Polygon[] polys) - { - List vals = new(); - foreach (Polygon poly in polys) vals.AddRange(poly.ToFloatArray()); - return vals; - } - - public override bool Equals([NotNullWhen(true)] object? obj) - { - if (obj == null || obj.GetType() != typeof(Polygon)) return base.Equals(obj); - return Equals((Polygon)obj); - } - public bool Equals(Polygon other) - { - if (!CheckVerts(this, other)) return false; - return Lines == other.Lines; - } - public override int GetHashCode() => Lines.GetHashCode(); - public override string ToString() - { - string s = ""; - for (int i = 0; i < Lines.Length; i++) s += "L" + i + ": " + Lines[i] + " "; - return s; - } - - public object Clone() => new Polygon(Lines); - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - public IEnumerator GetEnumerator() { foreach (Float3 v in Verts) yield return v; } - - public Float3[] ToArray() => Verts; - public Fill ToFill() - { - Polygon @this = this; - return i => @this[i]; - } - public List ToList() => new(Verts); - - public float[] ToFloatArray() - { - float[] vals = new float[Verts.Length * 3]; - for (int i = 0; i < Verts.Length; i++) - { - int pos = i * 3; - vals[pos + 0] = Verts[i].x; - vals[pos + 1] = Verts[i].y; - vals[pos + 2] = Verts[i].z; - } - return vals; - } - public List ToFloatList() => new(ToFloatArray()); - - public Polygon Subdivide() - { - Polygon poly = new(); - List lines = new(); - for (int i = 0; i < Lines.Length; i++) lines.AddRange(Lines[i].Subdivide()); - return poly; - } - public Polygon Subdivide(int iterations) - { - if (iterations < 1) return new(); - Polygon poly = this; - for (int i = 0; i < iterations; i++) poly = poly.Subdivide(); - return poly; - } - - public Polygon SubdivideCatmullClark(int segments) - { - // Thanks Saalty for making this accidentally. - List newVerts = new(); - for (int i = 0; i < Verts.Length; i++) - { - for (int factor = 0; factor < segments; factor++) - { - float unit = factor / (float)(segments * 2), unit2 = unit + 0.5f, lastUnit = unit * 2; - Float3 p1, p2; - if (i == Verts.Length - 1) - { - p1 = Verts[^1] + (Verts[0] - Verts[^1]) * unit2; - p2 = Verts[0] + (Verts[1] - Verts[0]) * unit; - } - else if (i == Verts.Length - 2) - { - p1 = Verts[^2] + (Verts[^1] - Verts[^2]) * unit2; - p2 = Verts[^1] + (Verts[0] - Verts[^1]) * unit; - } - else - { - p1 = Verts[i] + (Verts[i + 1] - Verts[i]) * unit2; - p2 = Verts[i + 1] + (Verts[i + 2] - Verts[i + 1]) * unit; - } - newVerts.Add(p1 + (p2 - p1) * lastUnit); - } - } - return new(newVerts.ToArray()); - } - - [Obsolete("This method doesn't work very well, and will give very weird results in certain cases. " + - "This will be fixed in a future update.")] - public Triangle[] Triangulate() - { - // This may cause issues. FIXME - // Tbh, not even sure if this works. This was a bit confusing. - - if (Verts.Length == 3) return new Triangle[] { new(Verts[0], Verts[1], Verts[2]) }; - - (int posA, int posB, Line line)? closest = null; - for (int i = 0; i < Verts.Length; i++) - { - for (int j = 0; j < Verts.Length; j++) - { - if (i == j) continue; - Line l = new(Verts[i], Verts[j]); - if (Lines.Contains(l)) continue; - - if (!closest.HasValue || closest.Value.line.Length > l.Length) closest = (i, j, l); - } - } - - if (closest == null) - throw new Nerd_STFException("Unknown error triangulating the polygon."); - - if (closest.Value.posB > closest.Value.posA) - closest = (closest.Value.posB, closest.Value.posA, closest.Value.line); - - List partA = new(Lines[closest.Value.posA..(closest.Value.posB - 1)]) - { - closest.Value.line - }; - - Polygon pA = new(partA.ToArray()); - - List partB = new(Lines[0..(closest.Value.posA - 1)]); - partB.AddRange(Lines[closest.Value.posB..(Lines.Length - 1)]); - partB.Add(closest.Value.line); - - Polygon pB = new(partB.ToArray()); - - List tris = new(pA.Triangulate()); - tris.AddRange(pB.Triangulate()); - return tris.ToArray(); - } - - private static bool CheckVerts(params Polygon[] polys) - { - int len = -1; - foreach (Polygon poly in polys) - { - if (len == -1) - { - len = poly.Verts.Length; - continue; - } - if (poly.Verts.Length != len) return false; - } - return true; - } - private static Line[] GenerateLines(Float3[] verts) - { - Line[] lines = new Line[verts.Length]; - for (int i = 0; i < lines.Length; i++) - lines[i] = new(verts[i], verts[i == lines.Length - 1 ? 0 : i + 1]); - return lines; - } - private static Float3[] GenerateVerts(Line[] lines) - { - Float3[] verts = new Float3[lines.Length]; - for (int i = 0; i < verts.Length; i++) - { - verts[i] = lines[i].a; - if (lines[i].b != lines[i == verts.Length - 1 ? 0 : i + 1].a) - throw new DisconnectedLinesException(nameof(lines), lines); - } - return verts; - } - - public static Polygon operator +(Polygon a, Polygon b) - { - if (!CheckVerts(a, b)) throw new DifferingVertCountException(a, b); - Line[][] lines = new Line[2][] { a.Lines, b.Lines }; - Line[] res = new Line[a.Lines.Length]; - for (int i = 0; i < res.Length; i++) res[i] = lines[0][i] + lines[1][i]; - return new(res); - } - public static Polygon operator +(Polygon a, Float3 b) - { - Line[] lines = a.Lines; - for (int i = 0; i < lines.Length; i++) lines[i] += b; - return new(lines); - } - public static Polygon operator -(Polygon p) - { - Line[] lines = p.Lines; - for (int i = 0; i < lines.Length; i++) lines[i] = -lines[i]; - return new(lines); - } - public static Polygon operator -(Polygon a, Polygon b) - { - if (!CheckVerts(a, b)) throw new DifferingVertCountException(a, b); - Line[][] lines = new Line[2][] { a.Lines, b.Lines }; - Line[] res = new Line[a.Lines.Length]; - for (int i = 0; i < res.Length; i++) res[i] = lines[0][i] - lines[1][i]; - return new(res); - } - public static Polygon operator -(Polygon a, Float3 b) - { - Line[] lines = a.Lines; - for (int i = 0; i < lines.Length; i++) lines[i] -= b; - return new(lines); - } - public static Polygon operator *(Polygon a, Polygon b) - { - if (!CheckVerts(a, b)) throw new DifferingVertCountException(a, b); - Line[][] lines = new Line[2][] { a.Lines, b.Lines }; - Line[] res = new Line[a.Lines.Length]; - for (int i = 0; i < res.Length; i++) res[i] = lines[0][i] * lines[1][i]; - return new(res); - } - public static Polygon operator *(Polygon a, Float3 b) - { - Line[] lines = a.Lines; - for (int i = 0; i < lines.Length; i++) lines[i] *= b; - return new(lines); - } - public static Polygon operator *(Polygon a, float b) - { - Line[] lines = a.Lines; - for (int i = 0; i < lines.Length; i++) lines[i] *= b; - return new(lines); - } - public static Polygon operator /(Polygon a, Polygon b) - { - if (!CheckVerts(a, b)) throw new DifferingVertCountException(a, b); - Line[][] lines = new Line[2][] { a.Lines, b.Lines }; - Line[] res = new Line[a.Lines.Length]; - for (int i = 0; i < res.Length; i++) res[i] = lines[0][i] / lines[1][i]; - return new(res); - } - public static Polygon operator /(Polygon a, Float3 b) - { - Line[] lines = a.Lines; - for (int i = 0; i < lines.Length; i++) lines[i] /= b; - return new(lines); - } - public static Polygon operator /(Polygon a, float b) - { - Line[] lines = a.Lines; - for (int i = 0; i < lines.Length; i++) lines[i] /= b; - return new(lines); - } - public static bool operator ==(Polygon a, Polygon b) => a.Equals(b); - public static bool operator !=(Polygon a, Polygon b) => !a.Equals(b); - - public static implicit operator Polygon(Fill fill) => new(fill); - public static implicit operator Polygon(Fill fill) => new(fill); - public static implicit operator Polygon(Float3[] verts) => new(verts); - public static implicit operator Polygon(Line[] lines) => new(lines); - public static implicit operator Polygon(Triangle tri) => new(tri.AB, tri.BC, tri.CA); - public static implicit operator Polygon(Quadrilateral quad) => new(quad.AB, quad.BC, quad.CD, quad.DA); -} diff --git a/Nerd_STF/Mathematics/Geometry/Quadrilateral.cs b/Nerd_STF/Mathematics/Geometry/Quadrilateral.cs deleted file mode 100644 index 6a6efc0..0000000 --- a/Nerd_STF/Mathematics/Geometry/Quadrilateral.cs +++ /dev/null @@ -1,366 +0,0 @@ -namespace Nerd_STF.Mathematics.Geometry; - -public record class Quadrilateral : IAbsolute, IAverage, ICeiling, - IClamp, IEquatable, IFloor, - IFromTuple, IGroup, IIndexAll, IIndexRangeAll, - ILerp, IRound, IShape2d, ITriangulate -{ - public Float3 A - { - get => p_a; - set - { - p_a = value; - p_ab.a = value; - p_da.b = value; - } - } - public Float3 B - { - get => p_b; - set - { - p_b = value; - p_ab.b = value; - p_bc.a = value; - } - } - public Float3 C - { - get => p_c; - set - { - p_c = value; - p_bc.b = value; - p_cd.a = value; - } - } - public Float3 D - { - get => p_d; - set - { - p_d = value; - p_cd.b = value; - p_da.a = value; - } - } - public Line AB - { - get => p_ab; - set - { - p_ab = value; - p_a = value.a; - p_b = value.b; - p_bc.a = value.b; - p_da.b = value.a; - } - } - public Line BC - { - get => p_bc; - set - { - p_bc = value; - p_b = value.a; - p_c = value.b; - p_cd.a = value.b; - p_ab.b = value.a; - } - } - public Line CD - { - get => p_cd; - set - { - p_cd = value; - p_c = value.a; - p_d = value.b; - p_da.a = value.b; - p_bc.b = value.a; - } - } - public Line DA - { - get => p_da; - set - { - p_da = value; - p_d = value.a; - p_a = value.b; - p_ab.a = value.b; - p_cd.b = value.a; - } - } - - private Float3 p_a, p_b, p_c, p_d; - private Line p_ab, p_bc, p_cd, p_da; - - [Obsolete("This field doesn't account for the Z-axis. This will be fixed in v2.4.0")] - public float Area - { - get - { - float val = 0; - foreach (Triangle t in Triangulate()) val += t.Area; - return val; - } - } - public Float3 Midpoint => Float3.Average(A, B, C, D); - public float Perimeter => AB.Length + BC.Length + CD.Length + DA.Length; - - public Quadrilateral(Float3 a, Float3 b, Float3 c, Float3 d) - { - p_a = a; - p_b = b; - p_c = c; - p_d = d; - p_ab = new(a, b); - p_bc = new(b, c); - p_cd = new(c, d); - p_da = new(d, a); - } - public Quadrilateral(Line ab, Line bc, Line cd, Line da) - { - if (ab.a != da.b || ab.b != bc.a || bc.b != cd.a || cd.b != da.a) - throw new DisconnectedLinesException(ab, bc, cd, da); - p_a = ab.a; - p_b = bc.a; - p_c = cd.a; - p_d = da.a; - p_ab = ab; - p_bc = bc; - p_cd = cd; - p_da = da; - } - public Quadrilateral(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) - : this(new Float3(x1, y1), new(x2, y2), new(x3, y3), new(x4, y4)) { } - public Quadrilateral(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, - float z3, float x4, float y4, float z4) - : this(new Float3(x1, y1, z1), new(x2, y2, z2), new(x3, y3, z3), new(x4, y4, z4)) { } - public Quadrilateral(Fill fill) : this(fill(0), fill(1), fill(2), fill(3)) { } - public Quadrilateral(Fill fill) : this(fill(0), fill(1), fill(2), fill(3)) { } - public Quadrilateral(Fill fill) : this(fill(0), fill(1), fill(2), fill(3)) { } - public Quadrilateral(Fill fill) : this(fill(0), fill(1), fill(2), fill(3), fill(4), fill(5), fill(6), - fill(7), fill(8), fill(9), fill(10), fill(11)) { } - public Quadrilateral(Fill fill) : this(fill(0), fill(1), fill(2), fill(3), fill(4), fill(5), fill(6), - fill(7), fill(8), fill(9), fill(10), fill(11)) { } - - public Float3 this[int index] - { - get => index switch - { - 0 => A, - 1 => B, - 2 => C, - 3 => D, - _ => throw new IndexOutOfRangeException(nameof(index)), - }; - set - { - switch (index) - { - case 0: - A = value; - break; - - case 1: - B = value; - break; - - case 2: - C = value; - break; - - case 3: - D = value; - break; - - default: throw new IndexOutOfRangeException(nameof(index)); - } - } - } - public Float3 this[Index index] - { - get => this[index.IsFromEnd ? 4 - index.Value : index.Value]; - set => this[index.IsFromEnd ? 4 - index.Value : index.Value] = value; - } - public Float3[] this[Range range] - { - get - { - int start = range.Start.IsFromEnd ? 4 - range.Start.Value : range.Start.Value; - int end = range.End.IsFromEnd ? 4 - range.End.Value : range.End.Value; - List res = new(); - for (int i = start; i < end; i++) res.Add(this[i]); - return res.ToArray(); - } - set - { - int start = range.Start.IsFromEnd ? 4 - range.Start.Value : range.Start.Value; - int end = range.End.IsFromEnd ? 4 - range.End.Value : range.End.Value; - for (int i = start; i < end; i++) this[i] = value[i]; - } - } - - public static Quadrilateral Absolute(Quadrilateral val) => - new(Float3.Absolute(val.A), Float3.Absolute(val.B), Float3.Absolute(val.C), Float3.Absolute(val.D)); - public static Quadrilateral Average(params Quadrilateral[] vals) - { - (Float3[] As, Float3[] Bs, Float3[] Cs, Float3[] Ds) = SplitVertArray(vals); - return new(Float3.Average(As), Float3.Average(Bs), Float3.Average(Cs), Float3.Average(Ds)); - } - public static Quadrilateral Ceiling(Quadrilateral val) => - new(Float3.Ceiling(val.A), Float3.Ceiling(val.B), Float3.Ceiling(val.C), Float3.Ceiling(val.D)); - public static Quadrilateral Clamp(Quadrilateral val, Quadrilateral min, Quadrilateral max) => - new(Float3.Clamp(val.A, min.A, max.A), Float3.Clamp(val.B, min.B, max.B), Float3.Clamp(val.C, min.C, max.C), - Float3.Clamp(val.D, min.D, max.D)); - public static Quadrilateral Floor(Quadrilateral val) => - new(Float3.Floor(val.A), Float3.Floor(val.B), Float3.Floor(val.C), Float3.Floor(val.D)); - public static Quadrilateral Lerp(Quadrilateral a, Quadrilateral b, float t, bool clamp = true) => - new(Float3.Lerp(a.A, b.A, t, clamp), Float3.Lerp(a.B, b.B, t, clamp), Float3.Lerp(a.C, b.C, t, clamp), - Float3.Lerp(a.D, b.D, t, clamp)); - public static Quadrilateral Max(params Quadrilateral[] vals) - { - (Float3[] As, Float3[] Bs, Float3[] Cs, Float3[] Ds) = SplitVertArray(vals); - return new(Float3.Max(As), Float3.Max(Bs), Float3.Max(Cs), Float3.Max(Ds)); - } - public static Quadrilateral Median(params Quadrilateral[] vals) - { - (Float3[] As, Float3[] Bs, Float3[] Cs, Float3[] Ds) = SplitVertArray(vals); - return new(Float3.Median(As), Float3.Median(Bs), Float3.Median(Cs), Float3.Median(Ds)); - } - public static Quadrilateral Min(params Quadrilateral[] vals) - { - (Float3[] As, Float3[] Bs, Float3[] Cs, Float3[] Ds) = SplitVertArray(vals); - return new(Float3.Min(As), Float3.Min(Bs), Float3.Min(Cs), Float3.Min(Ds)); - } - public static Quadrilateral Round(Quadrilateral val) => - new(Float3.Round(val.A), Float3.Round(val.B), Float3.Round(val.C), Float3.Round(val.D)); - - public static (Float3[] As, Float3[] Bs, Float3[] Cs, Float3[] Ds) SplitVertArray(params Quadrilateral[] quads) - { - Float3[] a = new Float3[quads.Length], b = new Float3[quads.Length], - c = new Float3[quads.Length], d = new Float3[quads.Length]; - for (int i = 0; i < quads.Length; i++) - { - a[i] = quads[i].A; - b[i] = quads[i].B; - c[i] = quads[i].C; - d[i] = quads[i].D; - } - - return (a, b, c, d); - } - public static (Line[] ABs, Line[] BCs, Line[] CDs, Line[] DAs) SplitLineArray(params Quadrilateral[] quads) - { - Line[] ab = new Line[quads.Length], bc = new Line[quads.Length], - cd = new Line[quads.Length], da = new Line[quads.Length]; - for (int i = 0; i < quads.Length; i++) - { - ab[i] = quads[i].AB; - bc[i] = quads[i].BC; - cd[i] = quads[i].CD; - da[i] = quads[i].DA; - } - - return (ab, bc, cd, da); - } - - public static float[] ToFloatArrayAll(params Quadrilateral[] quads) - { - float[] vals = new float[quads.Length * 12]; - for (int i = 0; i < quads.Length; i++) - { - int pos = i * 12; - vals[pos + 0] = quads[i].A.x; - vals[pos + 1] = quads[i].A.y; - vals[pos + 2] = quads[i].A.z; - vals[pos + 3] = quads[i].B.x; - vals[pos + 4] = quads[i].B.y; - vals[pos + 5] = quads[i].B.z; - vals[pos + 6] = quads[i].C.x; - vals[pos + 7] = quads[i].C.y; - vals[pos + 8] = quads[i].C.z; - vals[pos + 9] = quads[i].D.x; - vals[pos + 10] = quads[i].D.y; - vals[pos + 11] = quads[i].D.z; - } - return vals; - } - public static List ToFloatListAll(params Quadrilateral[] quads) => new(ToFloatArrayAll(quads)); - - public virtual bool Equals(Quadrilateral? other) - { - if (other is null) return false; - return A == other.A && B == other.B && C == other.C && D == other.D; - } - public override int GetHashCode() => base.GetHashCode(); - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - public IEnumerator GetEnumerator() - { - yield return A; - yield return B; - yield return C; - yield return D; - } - - public Float3[] ToArray() => new Float3[] { A, B, C, D }; - public Fill ToFill() - { - Quadrilateral @this = this; - return i => @this[i]; - } - public List ToList() => new() { A, B, C, D }; - - public float[] ToFloatArray() => new float[] { A.x, A.y, A.z, - B.x, B.y, B.z, - C.x, C.y, C.z, - D.x, D.y, D.z }; - public List ToFloatList() => new() { A.x, A.y, A.z, - B.x, B.y, B.z, - C.x, C.y, C.z, - D.x, D.y, D.z }; - - public Triangle[] Triangulate() => new Line(A, C).Length > new Line(B, D).Length ? - new Triangle[] { new(A, B, C), new(C, D, A) } : new Triangle[] { new(B, C, D), new(D, A, B) }; - - protected virtual bool PrintMembers(StringBuilder builder) - { - builder.Append("A = "); - builder.Append(A); - builder.Append(", B = "); - builder.Append(B); - builder.Append(", C = "); - builder.Append(C); - builder.Append(", D = "); - builder.Append(D); - return true; - } - - public static Quadrilateral operator +(Quadrilateral a, Quadrilateral b) => new(a.A + b.A, a.B + b.B, - a.C + b.C, a.D + b.D); - public static Quadrilateral operator +(Quadrilateral a, Float3 b) => new(a.A + b, a.B + b, a.C + b, a.D + b); - public static Quadrilateral operator -(Quadrilateral q) => new(-q.A, -q.B, -q.C, -q.D); - public static Quadrilateral operator -(Quadrilateral a, Quadrilateral b) => new(a.A - b.A, a.B - b.B, - a.C - b.C, a.D - b.D); - public static Quadrilateral operator -(Quadrilateral a, Float3 b) => new(a.A - b, a.B - b, a.C - b, a.D - b); - public static Quadrilateral operator *(Quadrilateral a, Quadrilateral b) => new(a.A * b.A, a.B * b.B, - a.C * b.C, a.D * b.D); - public static Quadrilateral operator *(Quadrilateral a, Float3 b) => new(a.A * b, a.B * b, a.C * b, a.D * b); - public static Quadrilateral operator *(Quadrilateral a, float b) => new(a.A * b, a.B * b, a.C * b, a.D * b); - public static Quadrilateral operator /(Quadrilateral a, Quadrilateral b) => new(a.A / b.A, a.B / b.B, - a.C / b.C, a.D / b.D); - public static Quadrilateral operator /(Quadrilateral a, Float3 b) => new(a.A / b, a.B / b, a.C / b, a.D / b); - public static Quadrilateral operator /(Quadrilateral a, float b) => new(a.A / b, a.B / b, a.C / b, a.D / b); - - public static implicit operator Quadrilateral(Fill fill) => new(fill); - public static implicit operator Quadrilateral(Fill fill) => new(fill); - public static implicit operator Quadrilateral(Fill fill) => new(fill); - public static implicit operator Quadrilateral(Fill fill) => new(fill); - public static implicit operator Quadrilateral(Fill fill) => new(fill); - public static implicit operator Quadrilateral((Float3 a, Float3 b, Float3 c, Float3 d) val) => - new(val.a, val.b, val.c, val.d); -} diff --git a/Nerd_STF/Mathematics/Geometry/Sphere.cs b/Nerd_STF/Mathematics/Geometry/Sphere.cs deleted file mode 100644 index bb09049..0000000 --- a/Nerd_STF/Mathematics/Geometry/Sphere.cs +++ /dev/null @@ -1,148 +0,0 @@ -namespace Nerd_STF.Mathematics.Geometry; - -public record class Sphere : IAverage, ICeiling, IClamp, IClosestTo, - IComparable, IComparable, IContains, IEquatable, IEquatable, IFloor, - IFromTuple, ILerp, IMax, IMedian, - IMin, IRound, ISplittable -{ - public static Sphere Unit => new(Float3.Zero, 1); - - public Float3 center; - public float radius; - - public float SurfaceArea => 4 * Constants.Pi * radius * radius; - public float Volume => 4 / 3 * (Constants.Pi * radius * radius * radius); - - public static Sphere FromDiameter(Float3 a, Float3 b) => new(Float3.Average(a, b), (a - b).Magnitude / 2); - public static Sphere FromRadius(Float3 center, Float3 radius) => new(center, (center - radius).Magnitude); - - public Sphere(Float3 center, float radius) - { - this.center = center; - this.radius = radius; - } - public Sphere(float cX, float cY, float radius) : this(new Float3(cX, cY), radius) { } - public Sphere(float cX, float cY, float cZ, float radius) : this(new Float3(cX, cY, cZ), radius) { } - public Sphere(Fill fill, float radius) : this(new Float3(fill), radius) { } - public Sphere(Fill fill) : this(new Float3(fill), fill(3)) { } - public Sphere(Fill fill, float radius) : this(new Float3(fill), radius) { } - public Sphere(Fill fill) : this(new Float3(fill), fill(3)) { } - public Sphere(Fill fill, float radius) : this(fill(0), radius) { } - public Sphere(Fill fillA, Fill fillB) : this(fillA(0), fillB(0)) { } - - public static Sphere Average(params Sphere[] vals) - { - (Float3[] centers, float[] radii) = SplitArray(vals); - return new(Float3.Average(centers), Mathf.Average(radii)); - } - public static Sphere Ceiling(Sphere val) => new(Float3.Ceiling(val.center), Mathf.Ceiling(val.radius)); - public static Sphere Clamp(Sphere val, Sphere min, Sphere max) => - new(Float3.Clamp(val.center, min.center, max.center), Mathf.Clamp(val.radius, min.radius, max.radius)); - public static Sphere Floor(Sphere val) => new(Float3.Floor(val.center), Mathf.Floor(val.radius)); - public static Sphere Lerp(Sphere a, Sphere b, float t, bool clamp = true) => - new(Float3.Lerp(a.center, b.center, t, clamp), Mathf.Lerp(a.radius, b.radius, t, clamp)); - public static Sphere Max(params Sphere[] vals) - { - (Float3[] centers, float[] radii) = SplitArray(vals); - return new(Float3.Max(centers), Mathf.Max(radii)); - } - public static Sphere Median(params Sphere[] vals) - { - (Float3[] centers, float[] radii) = SplitArray(vals); - return new(Float3.Median(centers), Mathf.Median(radii)); - } - public static Sphere Min(params Sphere[] vals) - { - (Float3[] centers, float[] radii) = SplitArray(vals); - return new(Float3.Min(centers), Mathf.Min(radii)); - } - public static Sphere Round(Sphere val) => new(Float3.Round(val.center), Mathf.Round(val.radius)); - - public static (Float3[] centers, float[] radii) SplitArray(params Sphere[] spheres) - { - Float3[] centers = new Float3[spheres.Length]; - float[] radii = new float[spheres.Length]; - for (int i = 0; i < spheres.Length; i++) - { - centers[i] = spheres[i].center; - radii[i] = spheres[i].radius; - } - return (centers, radii); - } - - [Obsolete("This method is a bit ambiguous. You should instead compare " + nameof(radius) + "es directly. " + - "This method will be removed in Nerd_STF 2.5.0.")] - public bool Equals(float other) => Volume == other; - public virtual bool Equals(Sphere? other) - { - if (other is null) return false; - return center == other.center && radius == other.radius; - } - public override int GetHashCode() => base.GetHashCode(); - - public int CompareTo(Sphere? other) - { - if (other is null) return -1; - return Volume.CompareTo(other.Volume); - } - [Obsolete("This method is a bit ambiguous. You should instead compare " + nameof(radius) + "es directly. " + - "This method will be removed in Nerd_STF 2.5.0.")] - public int CompareTo(float volume) => Volume.CompareTo(volume); - - public bool Contains(Float3 vert) => (center - vert).Magnitude <= radius; - - public Float3 ClosestTo(Float3 vert) => Contains(vert) ? vert : ((vert - center).Normalized * radius) + center; - - protected virtual bool PrintMembers(StringBuilder builder) - { - builder.Append("Center = "); - builder.Append(builder); - builder.Append(", Radius = "); - builder.Append(radius); - return true; - } - - public static Sphere operator +(Sphere a, Sphere b) => new(a.center + b.center, a.radius + b.radius); - public static Sphere operator +(Sphere a, Float3 b) => new(a.center + b, a.radius); - public static Sphere operator +(Sphere a, float b) => new(a.center, a.radius + b); - public static Sphere operator -(Sphere a, Sphere b) => new(a.center + b.center, a.radius + b.radius); - public static Sphere operator -(Sphere a, Float3 b) => new(a.center + b, a.radius); - public static Sphere operator -(Sphere a, float b) => new(a.center, a.radius + b); - public static Sphere operator *(Sphere a, Sphere b) => new(a.center * b.center, a.radius * b.radius); - public static Sphere operator *(Sphere a, float b) => new(a.center * b, a.radius * b); - public static Sphere operator /(Sphere a, Sphere b) => new(a.center * b.center, a.radius * b.radius); - public static Sphere operator /(Sphere a, float b) => new(a.center * b, a.radius * b); - [Obsolete("This method is a bit ambiguous. You should instead compare " + nameof(radius) + "es directly. " + - "This method will be removed in Nerd_STF 2.5.0.")] - public static bool operator ==(Sphere a, float b) => a.Equals(b); - [Obsolete("This method is a bit ambiguous. You should instead compare " + nameof(radius) + "es directly. " + - "This method will be removed in Nerd_STF 2.5.0.")] - public static bool operator !=(Sphere a, float b) => !a.Equals(b); - [Obsolete("This method is a bit ambiguous. You should instead compare " + nameof(radius) + "es directly. " + - "This method will be removed in Nerd_STF 2.5.0.")] - public static bool operator >(Sphere a, Sphere b) => a.CompareTo(b) > 0; - [Obsolete("This method is a bit ambiguous. You should instead compare " + nameof(radius) + "es directly. " + - "This method will be removed in Nerd_STF 2.5.0.")] - public static bool operator <(Sphere a, Sphere b) => a.CompareTo(b) < 0; - [Obsolete("This method is a bit ambiguous. You should instead compare " + nameof(radius) + "es directly. " + - "This method will be removed in Nerd_STF 2.5.0.")] - public static bool operator >(Sphere a, float b) => a.CompareTo(b) > 0; - [Obsolete("This method is a bit ambiguous. You should instead compare " + nameof(radius) + "es directly. " + - "This method will be removed in Nerd_STF 2.5.0.")] - public static bool operator <(Sphere a, float b) => a.CompareTo(b) < 0; - [Obsolete("This method is a bit ambiguous. You should instead compare " + nameof(radius) + "es directly. " + - "This method will be removed in Nerd_STF 2.5.0.")] - public static bool operator >=(Sphere a, Sphere b) => a > b || a == b; - [Obsolete("This method is a bit ambiguous. You should instead compare " + nameof(radius) + "es directly. " + - "This method will be removed in Nerd_STF 2.5.0.")] - public static bool operator <=(Sphere a, Sphere b) => a < b || a == b; - [Obsolete("This method is a bit ambiguous. You should instead compare " + nameof(radius) + "es directly. " + - "This method will be removed in Nerd_STF 2.5.0.")] - public static bool operator >=(Sphere a, float b) => a > b || a == b; - [Obsolete("This method is a bit ambiguous. You should instead compare " + nameof(radius) + "es directly. " + - "This method will be removed in Nerd_STF 2.5.0.")] - public static bool operator <=(Sphere a, float b) => a < b || a == b; - - public static implicit operator Sphere((Float3 center, float radius) val) => - new(val.center, val.radius); -} diff --git a/Nerd_STF/Mathematics/Geometry/Triangle.cs b/Nerd_STF/Mathematics/Geometry/Triangle.cs deleted file mode 100644 index 0ca6429..0000000 --- a/Nerd_STF/Mathematics/Geometry/Triangle.cs +++ /dev/null @@ -1,307 +0,0 @@ -using System.Net.Security; - -namespace Nerd_STF.Mathematics.Geometry; - -public record class Triangle : IAbsolute, IAverage, ICeiling, IClamp, - IEquatable, IFloor, IFromTuple, IGroup, - IIndexAll, IIndexRangeAll, ILerp, IRound, IShape2d -{ - public Float3 A - { - get => p_a; - set - { - p_a = value; - p_ab.a = value; - p_ca.b = value; - } - } - public Float3 B - { - get => p_b; - set - { - p_b = value; - p_ab.b = value; - p_bc.a = value; - } - } - public Float3 C - { - get => p_c; - set - { - p_c = value; - p_bc.b = value; - p_ca.a = value; - } - } - public Line AB - { - get => p_ab; - set - { - p_ab = value; - p_a = value.a; - p_b = value.b; - p_bc.a = value.b; - p_ca.b = value.a; - } - } - public Line BC - { - get => p_bc; - set - { - p_bc = value; - p_b = value.a; - p_c = value.b; - p_ca.a = value.b; - p_ab.b = value.a; - } - } - public Line CA - { - get => p_ca; - set - { - p_ca = value; - p_a = value.b; - p_c = value.a; - p_ab.a = value.b; - p_bc.b = value.a; - } - } - - private Float3 p_a, p_b, p_c; - private Line p_ab, p_bc, p_ca; - - [Obsolete("This field doesn't account for the Z-axis. This will be fixed in v2.4.0")] - public float Area => (float)Mathf.Absolute((A.x * B.y) + (B.x * C.y) + - (C.x * A.y) - ((B.x * A.y) + (C.x * B.y) + - (A.x * C.y))) * 0.5f; - public Float3 Midpoint => Float3.Average(A, B, C); - public float Perimeter => AB.Length + BC.Length + CA.Length; - - public Triangle(Float3 a, Float3 b, Float3 c) - { - p_a = a; - p_b = b; - p_c = c; - p_ab = new(a, b); - p_bc = new(b, c); - p_ca = new(c, a); - } - public Triangle(Line ab, Line bc, Line ca) - { - if (ab.a != ca.b || ab.b != bc.a || bc.b != ca.a) - throw new DisconnectedLinesException(ab, bc, ca); - - p_a = ab.a; - p_b = bc.a; - p_c = ca.a; - p_ab = ab; - p_bc = bc; - p_ca = ca; - } - public Triangle(float x1, float y1, float x2, float y2, float x3, float y3) - : this(new Float3(x1, y1), new Float3(x2, y2), new Float3(x3, y3)) { } - public Triangle(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, - float z3) : this(new Float3(x1, y1, z1), new Float3(x2, y2, z2), new Float3(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), 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 Float3 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 Float3 this[Index index] - { - get => this[index.IsFromEnd ? 3 - index.Value : index.Value]; - set => this[index.IsFromEnd ? 3 - index.Value : index.Value] = value; - } - public Float3[] this[Range range] - { - get - { - int start = range.Start.IsFromEnd ? 3 - range.Start.Value : range.Start.Value; - int end = range.End.IsFromEnd ? 3 - range.End.Value : range.End.Value; - List res = new(); - for (int i = start; i < end; i++) res.Add(this[i]); - return res.ToArray(); - } - set - { - int start = range.Start.IsFromEnd ? 3 - range.Start.Value : range.Start.Value; - int end = range.End.IsFromEnd ? 3 - range.End.Value : range.End.Value; - for (int i = start; i < end; i++) this[i] = value[i]; - } - } - - public static Triangle Absolute(Triangle val) => - new(Float3.Absolute(val.A), Float3.Absolute(val.B), Float3.Absolute(val.C)); - public static Triangle Average(params Triangle[] vals) - { - (Float3[] As, Float3[] Bs, Float3[] Cs) = SplitFloat3Array(vals); - return new(Float3.Average(As), Float3.Average(Bs), Float3.Average(Cs)); - } - public static Triangle Ceiling(Triangle val) => - new(Float3.Ceiling(val.A), Float3.Ceiling(val.B), Float3.Ceiling(val.C)); - public static Triangle Clamp(Triangle val, Triangle min, Triangle max) => - new(Float3.Clamp(val.A, min.A, max.A), Float3.Clamp(val.B, min.B, max.B), Float3.Clamp(val.C, min.C, max.C)); - public static Triangle Floor(Triangle val) => - new(Float3.Floor(val.A), Float3.Floor(val.B), Float3.Floor(val.C)); - public static Triangle Lerp(Triangle a, Triangle b, float t, bool clamp = true) => - new(Float3.Lerp(a.A, b.A, t, clamp), Float3.Lerp(a.B, b.B, t, clamp), Float3.Lerp(a.C, b.C, t, clamp)); - public static Triangle Max(params Triangle[] vals) - { - (Float3[] As, Float3[] Bs, Float3[] Cs) = SplitFloat3Array(vals); - return new(Float3.Max(As), Float3.Max(Bs), Float3.Max(Cs)); - } - public static Triangle Median(params Triangle[] vals) - { - (Float3[] As, Float3[] Bs, Float3[] Cs) = SplitFloat3Array(vals); - return new(Float3.Median(As), Float3.Median(Bs), Float3.Median(Cs)); - } - public static Triangle Min(params Triangle[] vals) - { - (Float3[] As, Float3[] Bs, Float3[] Cs) = SplitFloat3Array(vals); - return new(Float3.Min(As), Float3.Min(Bs), Float3.Min(Cs)); - } - public static Triangle Round(Triangle val) => - new(Float3.Round(val.A), Float3.Round(val.B), Float3.Round(val.C)); - - public static (Float3[] As, Float3[] Bs, Float3[] Cs) SplitFloat3Array(params Triangle[] tris) - { - Float3[] a = new Float3[tris.Length], b = new Float3[tris.Length], c = new Float3[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[] ABs, Line[] BCs, Line[] CAs) SplitLineArray(params Triangle[] tris) - { - Line[] ab = new Line[tris.Length], bc = new Line[tris.Length], ca = new Line[tris.Length]; - for (int i = 0; i < tris.Length; i++) - { - ab[i] = tris[i].AB; - bc[i] = tris[i].BC; - ca[i] = tris[i].CA; - } - return (ab, bc, ca); - } - - public static float[] ToFloatArrayAll(params Triangle[] tris) - { - float[] vals = new float[tris.Length * 9]; - for (int i = 0; i < tris.Length; i++) - { - int pos = i * 9; - vals[pos + 0] = tris[i].A.x; - vals[pos + 1] = tris[i].A.y; - vals[pos + 2] = tris[i].A.z; - vals[pos + 3] = tris[i].B.x; - vals[pos + 4] = tris[i].B.y; - vals[pos + 5] = tris[i].B.z; - vals[pos + 6] = tris[i].C.x; - vals[pos + 7] = tris[i].C.y; - vals[pos + 8] = tris[i].C.z; - } - return vals; - } - public static List ToFloatListAll(params Triangle[] tris) => new(ToFloatArrayAll(tris)); - - public virtual bool Equals(Triangle? other) - { - if (other is null) return false; - return A == other.A && B == other.B && C == other.C; - } - public override int GetHashCode() => base.GetHashCode(); - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - public IEnumerator GetEnumerator() - { - yield return A; - yield return B; - yield return C; - } - - public Float3[] ToArray() => new Float3[] { A, B, C }; - public Fill ToFill() - { - Triangle @this = this; - return i => @this[i]; - } - public List ToList() => new() { A, B, C }; - - public float[] ToFloatArray() => new float[] { A.x, A.y, A.z, - B.x, B.y, B.z, - C.x, C.y, C.z }; - public List ToFloatList() => new() { A.x, A.y, A.z, - B.x, B.y, B.z, - C.x, C.y, C.z }; - - protected virtual bool PrintMembers(StringBuilder builder) - { - builder.Append("A = "); - builder.Append(A); - builder.Append(", B = "); - builder.Append(B); - builder.Append(", C = "); - builder.Append(C); - return true; - } - - 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, Float3 b) => new(a.A + b, a.B + b, a.C + b); - public static Triangle operator -(Triangle t) => new(-t.A, -t.B, -t.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, Float3 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, Float3 b) => new(a.A * b, a.B * b, a.C * b); - public static Triangle operator *(Triangle a, float 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, Float3 b) => new(a.A / b, a.B / b, a.C / b); - public static Triangle operator /(Triangle a, float b) => new(a.A / b, a.B / b, a.C / 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((Float3 a, Float3 b, Float3 c) val) => - new(val.a, val.b, val.c); -}