Partial commit. Code is finished btu I need to complete the changelog.

This commit is contained in:
That-One-Nerd 2023-07-24 18:52:27 -04:00
parent 4093fd6538
commit 1517f317e7
20 changed files with 347 additions and 493 deletions

View File

@ -10,6 +10,10 @@ Here's the full changelog:
* UnsafeHelper * UnsafeHelper
+ Q_rsqrt + Q_rsqrt
* Mathematics * Mathematics
* Geometry
- Vert
* Float2
- operator Float2(Vert)
* Mathf * Mathf
= Modified `InverseSqrt(float)` to use the faster unsafe inverse square root method. = Modified `InverseSqrt(float)` to use the faster unsafe inverse square root method.
``` ```

View File

@ -136,7 +136,6 @@ public record struct Vector2d : IAbsolute<Vector2d>, IAverage<Vector2d>,
public static explicit operator Vector2d(Int2 val) => val.ToVector(); public static explicit operator Vector2d(Int2 val) => val.ToVector();
public static explicit operator Vector2d(Int3 val) => (Vector2d)val.ToVector(); public static explicit operator Vector2d(Int3 val) => (Vector2d)val.ToVector();
public static explicit operator Vector2d(Matrix m) => ((Float2)m).ToVector(); public static explicit operator Vector2d(Matrix m) => ((Float2)m).ToVector();
public static explicit operator Vector2d(Vert val) => (Vector2d)val.ToVector();
public static explicit operator Vector2d(Vector3d val) => new(val.yaw, val.magnitude); public static explicit operator Vector2d(Vector3d val) => new(val.yaw, val.magnitude);
public static implicit operator Vector2d((Angle angle, float mag) val) => new(val.angle, val.mag); public static implicit operator Vector2d((Angle angle, float mag) val) => new(val.angle, val.mag);
} }

View File

@ -201,7 +201,6 @@ public record struct Vector3d : IAbsolute<Vector3d>, IAverage<Vector3d>, IClampM
public static explicit operator Vector3d(Int2 val) => val.ToVector(); public static explicit operator Vector3d(Int2 val) => val.ToVector();
public static explicit operator Vector3d(Int3 val) => val.ToVector(); public static explicit operator Vector3d(Int3 val) => val.ToVector();
public static explicit operator Vector3d(Matrix m) => ((Float3)m).ToVector(); public static explicit operator Vector3d(Matrix m) => ((Float3)m).ToVector();
public static explicit operator Vector3d(Vert val) => val.ToVector();
public static implicit operator Vector3d(Vector2d v) => new(v.theta, Angle.Zero, v.magnitude); public static implicit operator Vector3d(Vector2d v) => new(v.theta, Angle.Zero, v.magnitude);
public static implicit operator Vector3d((Angle yaw, Angle pitch, float mag) val) => public static implicit operator Vector3d((Angle yaw, Angle pitch, float mag) val) =>
new(val.yaw, val.pitch, val.mag); new(val.yaw, val.pitch, val.mag);

View File

@ -212,7 +212,6 @@ public record struct Float2 : IAbsolute<Float2>, IAverage<Float2>, ICeiling<Floa
public static explicit operator Float2(Int4 val) => new(val.x, val.y); public static explicit operator Float2(Int4 val) => new(val.x, val.y);
public static explicit operator Float2(Matrix m) => new(m[0, 0], m[1, 0]); public static explicit operator Float2(Matrix m) => new(m[0, 0], m[1, 0]);
public static explicit operator Float2(Vector2d val) => val.ToXYZ(); public static explicit operator Float2(Vector2d val) => val.ToXYZ();
public static explicit operator Float2(Vert val) => new(val.position.x, val.position.y);
public static implicit operator Float2(Fill<float> fill) => new(fill); public static implicit operator Float2(Fill<float> fill) => new(fill);
public static implicit operator Float2(Fill<int> fill) => new(fill); public static implicit operator Float2(Fill<int> fill) => new(fill);
public static implicit operator Float2((float x, float y) val) => new(val.x, val.y); public static implicit operator Float2((float x, float y) val) => new(val.x, val.y);

View File

@ -270,7 +270,6 @@ public record struct Float3 : IAbsolute<Float3>, IAverage<Float3>,
public static explicit operator Float3(Int4 val) => new(val.x, val.y, val.z); public static explicit operator Float3(Int4 val) => new(val.x, val.y, val.z);
public static explicit operator Float3(Matrix m) => new(m[0, 0], m[1, 0], m[2, 0]); public static explicit operator Float3(Matrix m) => new(m[0, 0], m[1, 0], m[2, 0]);
public static explicit operator Float3(Vector2d val) => val.ToXYZ(); public static explicit operator Float3(Vector2d val) => val.ToXYZ();
public static implicit operator Float3(Vert val) => new(val.position.x, val.position.y, val.position.z);
public static explicit operator Float3(RGBA val) => new(val.R, val.G, val.B); public static explicit operator Float3(RGBA val) => new(val.R, val.G, val.B);
public static explicit operator Float3(HSVA val) => new(val.H.Normalized, val.S, val.V); public static explicit operator Float3(HSVA val) => new(val.H.Normalized, val.S, val.V);
public static explicit operator Float3(RGBAByte val) => (Float3)val.ToRGBA(); public static explicit operator Float3(RGBAByte val) => (Float3)val.ToRGBA();

View File

@ -338,7 +338,6 @@ public record struct Float4 : IAbsolute<Float4>,
public static implicit operator Float4(Int4 val) => new(val.x, val.y, val.z, val.w); public static implicit operator Float4(Int4 val) => new(val.x, val.y, val.z, val.w);
public static explicit operator Float4(Matrix m) => new(m[0, 0], m[1, 0], m[2, 0], m[3, 0]); public static explicit operator Float4(Matrix m) => new(m[0, 0], m[1, 0], m[2, 0], m[3, 0]);
public static explicit operator Float4(Vector2d val) => val.ToXYZ(); public static explicit operator Float4(Vector2d val) => val.ToXYZ();
public static implicit operator Float4(Vert val) => new(val.position.x, val.position.y, val.position.z, 0);
public static implicit operator Float4(RGBA val) => new(val.R, val.G, val.B, val.A); public static implicit operator Float4(RGBA val) => new(val.R, val.G, val.B, val.A);
public static explicit operator Float4(CMYKA val) => new(val.C, val.M, val.Y, val.K); public static explicit operator Float4(CMYKA val) => new(val.C, val.M, val.Y, val.K);
public static explicit operator Float4(HSVA val) => new(val.H.Normalized, val.S, val.V, val.A); public static explicit operator Float4(HSVA val) => new(val.H.Normalized, val.S, val.V, val.A);

View File

@ -1,38 +1,38 @@
namespace Nerd_STF.Mathematics.Geometry; namespace Nerd_STF.Mathematics.Geometry;
public record class Box2d : IAbsolute<Box2d>, IAverage<Box2d>, ICeiling<Box2d>, IClamp<Box2d>, IContains<Vert>, public record class Box2d : IAbsolute<Box2d>, IAverage<Box2d>, ICeiling<Box2d>, IClamp<Box2d>, IContains<Float3>,
IEquatable<Box2d>, IFloor<Box2d>, ILerp<Box2d, float>, IMedian<Box2d>, IRound<Box2d>, IShape2d<float>, IEquatable<Box2d>, IFloor<Box2d>, ILerp<Box2d, float>, IMedian<Box2d>, IRound<Box2d>, IShape2d<float>,
ISplittable<Box2d, (Vert[] centers, Float2[] sizes)> ISplittable<Box2d, (Float3[] centers, Float2[] sizes)>
{ {
public static Box2d Unit => new(Vert.Zero, Float2.One); public static Box2d Unit => new(Float3.Zero, Float2.One);
public Vert MaxVert public Float3 MaxFloat3
{ {
get => center + (size / 2); get => center + (size / 2);
set set
{ {
Vert diff = center - value; Float3 diff = center - value;
size = (Float2)diff.position * 2f; size = (Float2)diff * 2f;
} }
} }
public Vert MinVert public Float3 MinFloat3
{ {
get => center - (size / 2); get => center - (size / 2);
set set
{ {
Vert diff = center + value; Float3 diff = center + value;
size = (Float2)diff.position * 2f; size = (Float2)diff * 2f;
} }
} }
public float Area => size.x * size.y; public float Area => size.x * size.y;
public float Perimeter => 2 * (size.x + size.y); public float Perimeter => 2 * (size.x + size.y);
public Vert center; public Float3 center;
public Float2 size; public Float2 size;
public Box2d(Vert min, Vert max) : this(Vert.Average(min, max), (Float2)(min - max)) { } public Box2d(Float3 min, Float3 max) : this(Float3.Average(min, max), (Float2)(min - max)) { }
public Box2d(Vert center, Float2 size) public Box2d(Float3 center, Float2 size)
{ {
this.center = center; this.center = center;
this.size = size; this.size = size;
@ -45,28 +45,28 @@ public record class Box2d : IAbsolute<Box2d>, IAverage<Box2d>, ICeiling<Box2d>,
set => size[index] = value; set => size[index] = value;
} }
public static Box2d Absolute(Box2d val) => new(Vert.Absolute(val.MinVert), Vert.Absolute(val.MaxVert)); public static Box2d Absolute(Box2d val) => new(Float3.Absolute(val.MinFloat3), Float3.Absolute(val.MaxFloat3));
public static Box2d Average(params Box2d[] vals) public static Box2d Average(params Box2d[] vals)
{ {
(Vert[] centers, Float2[] sizes) = SplitArray(vals); (Float3[] centers, Float2[] sizes) = SplitArray(vals);
return new(Vert.Average(centers), Float2.Average(sizes)); return new(Float3.Average(centers), Float2.Average(sizes));
} }
public static Box2d Ceiling(Box2d val) => new(Vert.Ceiling(val.center), Float2.Ceiling(val.size)); 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) => public static Box2d Clamp(Box2d val, Box2d min, Box2d max) =>
new(Vert.Clamp(val.center, min.center, max.center), Float2.Clamp(val.size, min.size, max.size)); new(Float3.Clamp(val.center, min.center, max.center), Float2.Clamp(val.size, min.size, max.size));
public static Box2d Floor(Box2d val) => new(Vert.Floor(val.center), Float2.Floor(val.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) => public static Box2d Lerp(Box2d a, Box2d b, float t, bool clamp = true) =>
new(Vert.Lerp(a.center, b.center, t, clamp), Float2.Lerp(a.size, b.size, t, clamp)); new(Float3.Lerp(a.center, b.center, t, clamp), Float2.Lerp(a.size, b.size, t, clamp));
public static Box2d Median(params Box2d[] vals) public static Box2d Median(params Box2d[] vals)
{ {
(Vert[] verts, Float2[] sizes) = SplitArray(vals); (Float3[] verts, Float2[] sizes) = SplitArray(vals);
return new(Vert.Median(verts), Float2.Median(sizes)); return new(Float3.Median(verts), Float2.Median(sizes));
} }
public static Box2d Round(Box2d val) => new(Vert.Round(val.center), Float2.Round(val.size)); public static Box2d Round(Box2d val) => new(Float3.Round(val.center), Float2.Round(val.size));
public static (Vert[] centers, Float2[] sizes) SplitArray(params Box2d[] vals) public static (Float3[] centers, Float2[] sizes) SplitArray(params Box2d[] vals)
{ {
Vert[] centers = new Vert[vals.Length]; Float3[] centers = new Float3[vals.Length];
Float2[] sizes = new Float2[vals.Length]; Float2[] sizes = new Float2[vals.Length];
for (int i = 0; i < vals.Length; i++) for (int i = 0; i < vals.Length; i++)
@ -85,7 +85,7 @@ public record class Box2d : IAbsolute<Box2d>, IAverage<Box2d>, ICeiling<Box2d>,
} }
public override int GetHashCode() => base.GetHashCode(); public override int GetHashCode() => base.GetHashCode();
public bool Contains(Vert vert) public bool Contains(Float3 vert)
{ {
Float2 diff = Float2.Absolute((Float2)(center - vert)); Float2 diff = Float2.Absolute((Float2)(center - vert));
return diff.x <= size.x && diff.y <= size.y; return diff.x <= size.x && diff.y <= size.y;
@ -94,16 +94,16 @@ public record class Box2d : IAbsolute<Box2d>, IAverage<Box2d>, ICeiling<Box2d>,
protected virtual bool PrintMembers(StringBuilder builder) protected virtual bool PrintMembers(StringBuilder builder)
{ {
builder.Append("Min = "); builder.Append("Min = ");
builder.Append(MinVert); builder.Append(MinFloat3);
builder.Append(", Max = "); builder.Append(", Max = ");
builder.Append(MaxVert); builder.Append(MaxFloat3);
return true; return true;
} }
public static Box2d operator +(Box2d a, Vert b) => new(a.center + b, a.size); 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, Float2 b) => new(a.center, a.size + b);
public static Box2d operator -(Box2d b) => new(-b.MaxVert, -b.MinVert); public static Box2d operator -(Box2d b) => new(-b.MaxFloat3, -b.MinFloat3);
public static Box2d operator -(Box2d a, Vert b) => new(a.center - b, a.size); 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, 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, 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, Float2 b) => new(a.center, a.size * b);

View File

@ -1,27 +1,29 @@
namespace Nerd_STF.Mathematics.Geometry; using Nerd_STF.Mathematics.Abstract;
namespace Nerd_STF.Mathematics.Geometry;
public record class Box3d : IAbsolute<Box3d>, IAverage<Box3d>, ICeiling<Box3d>, IClamp<Box3d>, public record class Box3d : IAbsolute<Box3d>, IAverage<Box3d>, ICeiling<Box3d>, IClamp<Box3d>,
IContains<Vert>, IEquatable<Box3d>, IFloor<Box3d>, ILerp<Box3d, float>, IMedian<Box3d>, IContains<Float3>, IEquatable<Box3d>, IFloor<Box3d>, ILerp<Box3d, float>, IMedian<Box3d>,
IRound<Box3d>, IShape3d<float>, ISplittable<Box3d, (Vert[] centers, Float3[] sizes)> IRound<Box3d>, IShape3d<float>, ISplittable<Box3d, (Float3[] centers, Float3[] sizes)>
{ {
public static Box3d Unit => new(Vert.Zero, Float3.One); public static Box3d Unit => new(Float3.Zero, Float3.One);
public Vert MaxVert public Float3 MaxFloat3
{ {
get => center + (Vert)(size / 2); get => center + (size / 2);
set set
{ {
Vert diff = center - value; Float3 diff = center - value;
size = diff.position * 2; size = diff * 2;
} }
} }
public Vert MinVert public Float3 MinFloat3
{ {
get => center - (Vert)(size / 2); get => center - (size / 2);
set set
{ {
Vert diff = center + value; Float3 diff = center + value;
size = diff.position * 2; size = diff * 2;
} }
} }
@ -29,15 +31,14 @@ public record class Box3d : IAbsolute<Box3d>, IAverage<Box3d>, ICeiling<Box3d>,
public float SurfaceArea => 2 * (size.x * size.y + size.y * size.z + size.x * 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 float Volume => size.x * size.y * size.z;
public Vert center; public Float3 center;
public Float3 size; public Float3 size;
public Box3d(Box2d box) : this(box.center, (Float3)box.size) { } public Box3d(Box2d box) : this(box.center, (Float3)box.size) { }
public Box3d(Vert min, Vert max) : this(Vert.Average(min, max), (Float3)(min - max)) { } public Box3d(Float3 min, Float3 max)
public Box3d(Vert center, Float3 size)
{ {
this.center = center; this.center = Float3.Average(min, max);
this.size = size; this.size = max - min;
} }
public Box3d(Fill<float> fill) : this(fill, new Float3(fill(3), fill(4), fill(5))) { } public Box3d(Fill<float> fill) : this(fill, new Float3(fill(3), fill(4), fill(5))) { }
@ -47,30 +48,30 @@ public record class Box3d : IAbsolute<Box3d>, IAverage<Box3d>, ICeiling<Box3d>,
set => size[index] = value; set => size[index] = value;
} }
public static Box3d Absolute(Box3d val) => new(Vert.Absolute(val.MinVert), Vert.Absolute(val.MaxVert)); public static Box3d Absolute(Box3d val) => new(Float3.Absolute(val.MinFloat3), Float3.Absolute(val.MaxFloat3));
public static Box3d Average(params Box3d[] vals) public static Box3d Average(params Box3d[] vals)
{ {
(Vert[] centers, Float3[] sizes) = SplitArray(vals); (Float3[] centers, Float3[] sizes) = SplitArray(vals);
return new(Vert.Average(centers), Float3.Average(sizes)); return new(Float3.Average(centers), Float3.Average(sizes));
} }
public static Box3d Ceiling(Box3d val) => public static Box3d Ceiling(Box3d val) =>
new(Vert.Ceiling(val.center), (Float3)Float3.Ceiling(val.size)); new(Float3.Ceiling(val.center), (Float3)Float3.Ceiling(val.size));
public static Box3d Clamp(Box3d val, Box3d min, Box3d max) => public static Box3d Clamp(Box3d val, Box3d min, Box3d max) =>
new(Vert.Clamp(val.center, min.center, max.center), Float3.Clamp(val.size, min.size, max.size)); new(Float3.Clamp(val.center, min.center, max.center), Float3.Clamp(val.size, min.size, max.size));
public static Box3d Floor(Box3d val) => public static Box3d Floor(Box3d val) =>
new(Vert.Floor(val.center), (Float3)Float3.Floor(val.size)); new(Float3.Floor(val.center), (Float3)Float3.Floor(val.size));
public static Box3d Lerp(Box3d a, Box3d b, float t, bool clamp = true) => public static Box3d Lerp(Box3d a, Box3d b, float t, bool clamp = true) =>
new(Vert.Lerp(a.center, b.center, t, clamp), Float3.Lerp(a.size, b.size, t, clamp)); new(Float3.Lerp(a.center, b.center, t, clamp), Float3.Lerp(a.size, b.size, t, clamp));
public static Box3d Median(params Box3d[] vals) public static Box3d Median(params Box3d[] vals)
{ {
(Vert[] verts, Float3[] sizes) = SplitArray(vals); (Float3[] verts, Float3[] sizes) = SplitArray(vals);
return new(Vert.Median(verts), Float3.Median(sizes)); return new(Float3.Median(verts), Float3.Median(sizes));
} }
public static Box3d Round(Box3d val) => new(Vert.Ceiling(val.center), (Float3)Float3.Ceiling(val.size)); public static Box3d Round(Box3d val) => new(Float3.Ceiling(val.center), (Float3)Float3.Ceiling(val.size));
public static (Vert[] centers, Float3[] sizes) SplitArray(params Box3d[] vals) public static (Float3[] centers, Float3[] sizes) SplitArray(params Box3d[] vals)
{ {
Vert[] centers = new Vert[vals.Length]; Float3[] centers = new Float3[vals.Length];
Float3[] sizes = new Float3[vals.Length]; Float3[] sizes = new Float3[vals.Length];
for (int i = 0; i < vals.Length; i++) for (int i = 0; i < vals.Length; i++)
@ -89,7 +90,7 @@ public record class Box3d : IAbsolute<Box3d>, IAverage<Box3d>, ICeiling<Box3d>,
} }
public override int GetHashCode() => base.GetHashCode(); public override int GetHashCode() => base.GetHashCode();
public bool Contains(Vert vert) public bool Contains(Float3 vert)
{ {
Float3 diff = Float3.Absolute(center - vert); Float3 diff = Float3.Absolute(center - vert);
return diff.x <= size.x && diff.y <= size.y && diff.z <= size.z; return diff.x <= size.x && diff.y <= size.y && diff.z <= size.z;
@ -98,17 +99,15 @@ public record class Box3d : IAbsolute<Box3d>, IAverage<Box3d>, ICeiling<Box3d>,
protected virtual bool PrintMembers(StringBuilder builder) protected virtual bool PrintMembers(StringBuilder builder)
{ {
builder.Append("Min = "); builder.Append("Min = ");
builder.Append(MinVert); builder.Append(MinFloat3);
builder.Append(", Max = "); builder.Append(", Max = ");
builder.Append(MaxVert); builder.Append(MaxFloat3);
return true; return true;
} }
public static Box3d operator +(Box3d a, Vert b) => new(a.center + b, a.size); public static Box3d operator +(Box3d a, Float3 b) => new(a.center + b, a.size);
public static Box3d operator +(Box3d a, Float3 b) => new(a.center, a.size + b); public static Box3d operator -(Box3d b) => new(-b.MaxFloat3, -b.MinFloat3);
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, Vert b) => new(a.center - b, a.size);
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, 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, 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, float b) => new(a.center / b, a.size / b);

View File

@ -2,27 +2,27 @@
namespace Nerd_STF.Mathematics.Geometry; namespace Nerd_STF.Mathematics.Geometry;
public record class Line : IAbsolute<Line>, IAverage<Line>, ICeiling<Line>, IClamp<Line>, IClosestTo<Vert>, public record class Line : IAbsolute<Line>, IAverage<Line>, ICeiling<Line>, IClamp<Line>, IClosestTo<Float3>,
IComparable<Line>, IContains<Vert>, IEquatable<Line>, IFloor<Line>, IFromTuple<Line, (Vert start, Vert end)>, IComparable<Line>, IContains<Float3>, IEquatable<Line>, IFloor<Line>, IFromTuple<Line, (Float3 start, Float3 end)>,
IGroup<Vert>, IIndexAll<Vert>, IIndexRangeAll<Vert>, ILerp<Line, float>, IMedian<Line>, IPresets3d<Line>, IGroup<Float3>, IIndexAll<Float3>, IIndexRangeAll<Float3>, ILerp<Line, float>, IMedian<Line>, IPresets3d<Line>,
IRound<Line>, ISplittable<Line, (Vert[] starts, Vert[] ends)>, ISubdivide<Line[]> IRound<Line>, ISplittable<Line, (Float3[] starts, Float3[] ends)>, ISubdivide<Line[]>
{ {
public static Line Back => new(Vert.Zero, Vert.Back); public static Line Back => new(Float3.Zero, Float3.Back);
public static Line Down => new(Vert.Zero, Vert.Down); public static Line Down => new(Float3.Zero, Float3.Down);
public static Line Forward => new(Vert.Zero, Vert.Forward); public static Line Forward => new(Float3.Zero, Float3.Forward);
public static Line Left => new(Vert.Zero, Vert.Left); public static Line Left => new(Float3.Zero, Float3.Left);
public static Line Right => new(Vert.Zero, Vert.Right); public static Line Right => new(Float3.Zero, Float3.Right);
public static Line Up => new(Vert.Zero, Vert.Up); public static Line Up => new(Float3.Zero, Float3.Up);
public static Line One => new(Vert.Zero, Vert.One); public static Line One => new(Float3.Zero, Float3.One);
public static Line Zero => new(Vert.Zero, Vert.Zero); public static Line Zero => new(Float3.Zero, Float3.Zero);
public float Length => (b - a).Magnitude; public float Length => (b - a).Magnitude;
public Vert Midpoint => Vert.Average(a, b); public Float3 Midpoint => Float3.Average(a, b);
public Vert a, b; public Float3 a, b;
public Line(Vert a, Vert b) public Line(Float3 a, Float3 b)
{ {
this.a = a; this.a = a;
this.b = b; this.b = b;
@ -30,13 +30,12 @@ public record class Line : IAbsolute<Line>, IAverage<Line>, ICeiling<Line>, ICla
public Line(float x1, float y1, float x2, float y2) : this(new(x1, y1), new(x2, y2)) { } 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) public Line(float x1, float y1, float z1, float x2, float y2, float z2)
: this(new(x1, y1, z1), new(x2, y2, z2)) { } : this(new(x1, y1, z1), new(x2, y2, z2)) { }
public Line(Fill<Vert> fill) : this(fill(0), fill(1)) { } public Line(Fill<Float3> fill) : this(fill(0), fill(1)) { }
public Line(Fill<Float3> fill) : this(new(fill(0)), new(fill(1))) { } public Line(Fill<Int3> fill) : this(fill(0), fill(1)) { }
public Line(Fill<Int3> fill) : this(new(fill(0)), new(fill(1))) { }
public Line(Fill<float> fill) : this(new(fill(0), fill(1), fill(2)), new(fill(3), fill(4), fill(5))) { } public Line(Fill<float> fill) : this(new(fill(0), fill(1), fill(2)), new(fill(3), fill(4), fill(5))) { }
public Line(Fill<int> fill) : this(new(fill(0), fill(1), fill(2)), new(fill(3), fill(4), fill(5))) { } public Line(Fill<int> fill) : this(new(fill(0), fill(1), fill(2)), new(fill(3), fill(4), fill(5))) { }
public Vert this[int index] public Float3 this[int index]
{ {
get => index switch get => index switch
{ {
@ -60,18 +59,18 @@ public record class Line : IAbsolute<Line>, IAverage<Line>, ICeiling<Line>, ICla
} }
} }
} }
public Vert this[Index index] public Float3 this[Index index]
{ {
get => this[index.IsFromEnd ? 2 - index.Value : index.Value]; get => this[index.IsFromEnd ? 2 - index.Value : index.Value];
set => this[index.IsFromEnd ? 2 - index.Value : index.Value] = value; set => this[index.IsFromEnd ? 2 - index.Value : index.Value] = value;
} }
public Vert[] this[Range range] public Float3[] this[Range range]
{ {
get get
{ {
int start = range.Start.IsFromEnd ? 2 - range.Start.Value : range.Start.Value; int start = range.Start.IsFromEnd ? 2 - range.Start.Value : range.Start.Value;
int end = range.End.IsFromEnd ? 2 - range.End.Value : range.End.Value; int end = range.End.IsFromEnd ? 2 - range.End.Value : range.End.Value;
List<Vert> res = new(); List<Float3> res = new();
for (int i = start; i < end; i++) res.Add(this[i]); for (int i = start; i < end; i++) res.Add(this[i]);
return res.ToArray(); return res.ToArray();
} }
@ -83,28 +82,28 @@ public record class Line : IAbsolute<Line>, IAverage<Line>, ICeiling<Line>, ICla
} }
} }
public static Line Absolute(Line val) => new(Vert.Absolute(val.a), Vert.Absolute(val.b)); public static Line Absolute(Line val) => new(Float3.Absolute(val.a), Float3.Absolute(val.b));
public static Line Average(params Line[] vals) public static Line Average(params Line[] vals)
{ {
(Vert[] starts, Vert[] ends) = SplitArray(vals); (Float3[] starts, Float3[] ends) = SplitArray(vals);
return new(Vert.Average(starts), Vert.Average(ends)); return new(Float3.Average(starts), Float3.Average(ends));
} }
public static Line Ceiling(Line val) => new(Vert.Ceiling(val.a), Vert.Ceiling(val.b)); 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) => public static Line Clamp(Line val, Line min, Line max) =>
new(Vert.Clamp(val.a, min.a, max.a), Vert.Clamp(val.b, min.b, max.b)); new(Float3.Clamp(val.a, min.a, max.a), Float3.Clamp(val.b, min.b, max.b));
public static Line Floor(Line val) => new(Vert.Floor(val.a), Vert.Floor(val.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) => public static Line Lerp(Line a, Line b, float t, bool clamp = true) =>
new(Vert.Lerp(a.a, b.a, t, clamp), Vert.Lerp(a.b, b.b, t, clamp)); new(Float3.Lerp(a.a, b.a, t, clamp), Float3.Lerp(a.b, b.b, t, clamp));
public static Line Median(params Line[] vals) public static Line Median(params Line[] vals)
{ {
(Vert[] starts, Vert[] ends) = SplitArray(vals); (Float3[] starts, Float3[] ends) = SplitArray(vals);
return new(Vert.Median(starts), Vert.Median(ends)); return new(Float3.Median(starts), Float3.Median(ends));
} }
public static Line Round(Line val) => new(Vert.Round(val.a), Vert.Round(val.b)); public static Line Round(Line val) => new(Float3.Round(val.a), Float3.Round(val.b));
public static (Vert[] starts, Vert[] ends) SplitArray(params Line[] lines) public static (Float3[] starts, Float3[] ends) SplitArray(params Line[] lines)
{ {
Vert[] starts = new Vert[lines.Length], ends = new Vert[lines.Length]; Float3[] starts = new Float3[lines.Length], ends = new Float3[lines.Length];
for (int i = 0; i < lines.Length; i++) for (int i = 0; i < lines.Length; i++)
{ {
starts[i] = lines[i].a; starts[i] = lines[i].a;
@ -128,21 +127,21 @@ public record class Line : IAbsolute<Line>, IAverage<Line>, ICeiling<Line>, ICla
return Length.CompareTo(line.Length); return Length.CompareTo(line.Length);
} }
public bool Contains(Vert vert) public bool Contains(Float3 vert)
{ {
Float3 diffA = a - vert, diffB = a - b; Float3 diffA = a - vert, diffB = a - b;
float lerpVal = diffA.Magnitude / diffB.Magnitude; float lerpVal = diffA.Magnitude / diffB.Magnitude;
return Vert.Lerp(a, b, lerpVal) == vert; return Float3.Lerp(a, b, lerpVal) == vert;
} }
public Vert ClosestTo(Vert vert) => ClosestTo(vert, Calculus.DefaultStep); public Float3 ClosestTo(Float3 vert) => ClosestTo(vert, Calculus.DefaultStep);
public Vert ClosestTo(Vert vert, float step) public Float3 ClosestTo(Float3 vert, float step)
{ {
Vert closestA = a, closestB = b; Float3 closestA = a, closestB = b;
for (float t = 0; t <= 1; t += step) for (float t = 0; t <= 1; t += step)
{ {
Vert valA = Vert.Lerp(a, b, t); Float3 valA = Float3.Lerp(a, b, t);
Vert valB = Vert.Lerp(b, a, t); Float3 valB = Float3.Lerp(b, a, t);
closestA = (valA - vert).Magnitude < (closestA - vert).Magnitude ? valA : closestA; closestA = (valA - vert).Magnitude < (closestA - vert).Magnitude ? valA : closestA;
closestB = (valB - vert).Magnitude < (closestB - vert).Magnitude ? valB : closestB; closestB = (valB - vert).Magnitude < (closestB - vert).Magnitude ? valB : closestB;
} }
@ -151,7 +150,7 @@ public record class Line : IAbsolute<Line>, IAverage<Line>, ICeiling<Line>, ICla
} }
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public IEnumerator<Vert> GetEnumerator() public IEnumerator<Float3> GetEnumerator()
{ {
yield return a; yield return a;
yield return b; yield return b;
@ -159,7 +158,7 @@ public record class Line : IAbsolute<Line>, IAverage<Line>, ICeiling<Line>, ICla
public Line[] Subdivide() public Line[] Subdivide()
{ {
Vert middle = Vert.Lerp(a, b, 0.5f); Float3 middle = Float3.Lerp(a, b, 0.5f);
return new Line[] { new(a, middle), new(middle, b) }; return new Line[] { new(a, middle), new(middle, b) };
} }
public Line[] Subdivide(int iterations) public Line[] Subdivide(int iterations)
@ -175,18 +174,18 @@ public record class Line : IAbsolute<Line>, IAverage<Line>, ICeiling<Line>, ICla
return lines.ToArray(); return lines.ToArray();
} }
public Vert[] ToArray() => new Vert[] { a, b }; public Float3[] ToArray() => new Float3[] { a, b };
public Fill<Vert> ToFill() public Fill<Float3> ToFill()
{ {
Line @this = this; Line @this = this;
return i => @this[i]; return i => @this[i];
} }
public List<Vert> ToList() => new() { a, b }; public List<Float3> ToList() => new() { a, b };
public float[] ToFloatArray() => new float[] { a.position.x, a.position.y, a.position.z, public float[] ToFloatArray() => new float[] { a.x, a.y, a.z,
b.position.x, b.position.y, b.position.z }; b.x, b.y, b.z };
public List<float> ToFloatList() => new() { a.position.x, a.position.y, a.position.z, public List<float> ToFloatList() => new() { a.x, a.y, a.z,
b.position.x, b.position.y, b.position.z }; b.x, b.y, b.z };
protected virtual bool PrintMembers(StringBuilder builder) protected virtual bool PrintMembers(StringBuilder builder)
{ {
@ -198,15 +197,15 @@ public record class Line : IAbsolute<Line>, IAverage<Line>, ICeiling<Line>, ICla
} }
public static Line operator +(Line a, Line b) => new(a.a + b.a, a.b + 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, Vert b) => new(a.a + b, a.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 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, Line b) => new(a.a - b.a, a.b - b.b);
public static Line operator -(Line a, Vert b) => new(a.a - b, a.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, Line b) => new(a.a * b.a, a.b * b.b);
public static Line operator *(Line a, Vert b) => new(a.a * b, a.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, 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, Line b) => new(a.a / b.a, a.b / b.b);
public static Line operator /(Line a, Vert b) => new(a.a / b, a.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, float b) => new(a.a / b, a.b / b);
[Obsolete("This operator is a bit ambiguous. You should instead compare " + [Obsolete("This operator is a bit ambiguous. You should instead compare " +
nameof(Length) + "s directly.")] nameof(Length) + "s directly.")]
@ -221,10 +220,9 @@ public record class Line : IAbsolute<Line>, IAverage<Line>, ICeiling<Line>, ICla
"You should instead compare " + nameof(Length) + "s directly.")] "You should instead compare " + nameof(Length) + "s directly.")]
public static bool operator <=(Line a, Line b) => a < b || a == b; public static bool operator <=(Line a, Line b) => a < b || a == b;
public static implicit operator Line(Fill<Vert> fill) => new(fill);
public static implicit operator Line(Fill<Float3> fill) => new(fill); public static implicit operator Line(Fill<Float3> fill) => new(fill);
public static implicit operator Line(Fill<Int3> fill) => new(fill); public static implicit operator Line(Fill<Int3> fill) => new(fill);
public static implicit operator Line(Fill<float> fill) => new(fill); public static implicit operator Line(Fill<float> fill) => new(fill);
public static implicit operator Line(Fill<int> fill) => new(fill); public static implicit operator Line(Fill<int> fill) => new(fill);
public static implicit operator Line((Vert start, Vert end) val) => new(val.start, val.end); public static implicit operator Line((Float3 start, Float3 end) val) => new(val.start, val.end);
} }

View File

@ -1,7 +1,7 @@
namespace Nerd_STF.Mathematics.Geometry; namespace Nerd_STF.Mathematics.Geometry;
[Obsolete("This struct is a garbage fire. This will be completely redesigned in v2.5.0")] [Obsolete("This struct is a garbage fire. This will be completely redesigned in v2.5.0")]
public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivide<Polygon>, ITriangulate public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Float3>, ISubdivide<Polygon>, ITriangulate
{ {
public Line[] Lines public Line[] Lines
{ {
@ -9,11 +9,11 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
set set
{ {
p_lines = value; p_lines = value;
p_verts = GenerateVerts(value); p_verts = GenerateFloat3s(value);
} }
} }
public Vert Midpoint => Vert.Average(Verts); public Float3 Midpoint => Float3.Average(Float3s);
public Vert[] Verts public Float3[] Float3s
{ {
get => p_verts; get => p_verts;
set set
@ -24,7 +24,7 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
} }
private Line[] p_lines; private Line[] p_lines;
private Vert[] p_verts; private Float3[] p_verts;
[Obsolete("This method uses the Polygon.Triangulate() function, which has issues. It will be fixed in a " + [Obsolete("This method uses the Polygon.Triangulate() function, which has issues. It will be fixed in a " +
"future update.")] "future update.")]
@ -50,27 +50,15 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
public Polygon() public Polygon()
{ {
p_lines = Array.Empty<Line>(); p_lines = Array.Empty<Line>();
p_verts = Array.Empty<Vert>(); p_verts = Array.Empty<Float3>();
} }
public Polygon(Fill<Vert?> fill)
{
List<Vert> verts = new();
int i = 0;
while (true)
{
Vert? v = fill(i);
if (!v.HasValue) break;
verts.Add(v.Value);
}
this = new(verts.ToArray());
}
public Polygon(Fill<Float3?> fill) public Polygon(Fill<Float3?> fill)
{ {
List<Vert> verts = new(); List<Float3> verts = new();
int i = 0; int i = 0;
while (true) while (true)
{ {
Vert? v = fill(i); Float3? v = fill(i);
if (!v.HasValue) break; if (!v.HasValue) break;
verts.Add(v.Value); verts.Add(v.Value);
} }
@ -88,15 +76,9 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
} }
this = new(lines.ToArray()); this = new(lines.ToArray());
} }
public Polygon(Fill<Vert> fill, int length)
{
List<Vert> verts = new();
for (int i = 0; i < length; i++) verts.Add(fill(i));
this = new(verts.ToArray());
}
public Polygon(Fill<Float3> fill, int length) public Polygon(Fill<Float3> fill, int length)
{ {
List<Vert> verts = new(); List<Float3> verts = new();
for (int i = 0; i < length; i++) verts.Add(fill(i)); for (int i = 0; i < length; i++) verts.Add(fill(i));
this = new(verts.ToArray()); this = new(verts.ToArray());
} }
@ -108,30 +90,25 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
} }
public Polygon(params Float3[] verts) public Polygon(params Float3[] verts)
{ {
p_verts = new Vert[verts.Length]; p_verts = new Float3[verts.Length];
for (int i = 0; i < verts.Length; i++) p_verts[i] = verts[i]; for (int i = 0; i < verts.Length; i++) p_verts[i] = verts[i];
p_lines = GenerateLines(p_verts); p_lines = GenerateLines(p_verts);
} }
public Polygon(params Vert[] verts)
{
p_verts = verts;
p_lines = GenerateLines(verts);
}
public Polygon(params Line[] lines) public Polygon(params Line[] lines)
{ {
p_lines = lines; p_lines = lines;
p_verts = GenerateVerts(lines); p_verts = GenerateFloat3s(lines);
} }
public Vert this[int index] public Float3 this[int index]
{ {
get => Verts[index]; get => Float3s[index];
set => Verts[index] = value; set => Float3s[index] = value;
} }
public static Polygon CreateCircle(int vertCount) public static Polygon CreateCircle(int vertCount)
{ {
List<Vert> parts = new(); List<Float3> parts = new();
for (int i = 0; i < vertCount; i++) for (int i = 0; i < vertCount; i++)
{ {
float val = Constants.Tau * i / vertCount; float val = Constants.Tau * i / vertCount;
@ -142,13 +119,13 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
public static Polygon Absolute(Polygon val) public static Polygon Absolute(Polygon val)
{ {
Vert[] v = val.Verts; Float3[] v = val.Float3s;
for (int i = 0; i < v.Length; i++) v[i] = Vert.Absolute(v[i]); for (int i = 0; i < v.Length; i++) v[i] = Float3.Absolute(v[i]);
return new(v); return new(v);
} }
public static Polygon Average(params Polygon[] vals) public static Polygon Average(params Polygon[] vals)
{ {
if (!CheckVerts(vals)) throw new DifferingVertCountException(nameof(vals), vals); if (!CheckFloat3s(vals)) throw new DifferingVertCountException(nameof(vals), vals);
if (vals.Length < 1) return default; if (vals.Length < 1) return default;
Line[][] lines = new Line[vals.Length][]; Line[][] lines = new Line[vals.Length][];
@ -166,13 +143,13 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
} }
public static Polygon Ceiling(Polygon val) public static Polygon Ceiling(Polygon val)
{ {
Vert[] v = val.Verts; Float3[] v = val.Float3s;
for (int i = 0; i < v.Length; i++) v[i] = Vert.Ceiling(v[i]); for (int i = 0; i < v.Length; i++) v[i] = Float3.Ceiling(v[i]);
return new(v); return new(v);
} }
public static Polygon Clamp(Polygon val, Polygon min, Polygon max) public static Polygon Clamp(Polygon val, Polygon min, Polygon max)
{ {
if (!CheckVerts(val, min, max)) throw new DifferingVertCountException(val, min, max); if (!CheckFloat3s(val, min, max)) throw new DifferingVertCountException(val, min, max);
Line[][] lines = new Line[3][] { val.Lines, min.Lines, max.Lines }; Line[][] lines = new Line[3][] { val.Lines, min.Lines, max.Lines };
Line[] res = new Line[val.Lines.Length]; 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]); for (int i = 0; i < res.Length; i++) res[i] = Line.Clamp(lines[0][i], lines[1][i], lines[2][i]);
@ -180,13 +157,13 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
} }
public static Polygon Floor(Polygon val) public static Polygon Floor(Polygon val)
{ {
Vert[] v = val.Verts; Float3[] v = val.Float3s;
for (int i = 0; i < v.Length; i++) v[i] = Vert.Floor(v[i]); for (int i = 0; i < v.Length; i++) v[i] = Float3.Floor(v[i]);
return new(v); return new(v);
} }
public static Polygon Lerp(Polygon a, Polygon b, float t, bool clamp = true) public static Polygon Lerp(Polygon a, Polygon b, float t, bool clamp = true)
{ {
if (!CheckVerts(a, b)) throw new DifferingVertCountException(a, b); if (!CheckFloat3s(a, b)) throw new DifferingVertCountException(a, b);
Line[][] lines = new Line[2][] { a.Lines, b.Lines }; Line[][] lines = new Line[2][] { a.Lines, b.Lines };
Line[] res = new Line[a.Lines.Length]; 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); for (int i = 0; i < res.Length; i++) res[i] = Line.Lerp(lines[0][i], lines[1][i], t, clamp);
@ -194,7 +171,7 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
} }
public static Polygon Median(params Polygon[] vals) public static Polygon Median(params Polygon[] vals)
{ {
if (!CheckVerts(vals)) throw new DifferingVertCountException(nameof(vals), vals); if (!CheckFloat3s(vals)) throw new DifferingVertCountException(nameof(vals), vals);
if (vals.Length < 1) return default; if (vals.Length < 1) return default;
Line[][] lines = new Line[vals.Length][]; Line[][] lines = new Line[vals.Length][];
@ -226,7 +203,7 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
} }
public bool Equals(Polygon other) public bool Equals(Polygon other)
{ {
if (!CheckVerts(this, other)) return false; if (!CheckFloat3s(this, other)) return false;
return Lines == other.Lines; return Lines == other.Lines;
} }
public override int GetHashCode() => Lines.GetHashCode(); public override int GetHashCode() => Lines.GetHashCode();
@ -240,25 +217,25 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
public object Clone() => new Polygon(Lines); public object Clone() => new Polygon(Lines);
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public IEnumerator<Vert> GetEnumerator() { foreach (Vert v in Verts) yield return v; } public IEnumerator<Float3> GetEnumerator() { foreach (Float3 v in Float3s) yield return v; }
public Vert[] ToArray() => Verts; public Float3[] ToArray() => Float3s;
public Fill<Vert> ToFill() public Fill<Float3> ToFill()
{ {
Polygon @this = this; Polygon @this = this;
return i => @this[i]; return i => @this[i];
} }
public List<Vert> ToList() => new(Verts); public List<Float3> ToList() => new(Float3s);
public float[] ToFloatArray() public float[] ToFloatArray()
{ {
float[] vals = new float[Verts.Length * 3]; float[] vals = new float[Float3s.Length * 3];
for (int i = 0; i < Verts.Length; i++) for (int i = 0; i < Float3s.Length; i++)
{ {
int pos = i * 3; int pos = i * 3;
vals[pos + 0] = Verts[i].position.x; vals[pos + 0] = Float3s[i].x;
vals[pos + 1] = Verts[i].position.y; vals[pos + 1] = Float3s[i].y;
vals[pos + 2] = Verts[i].position.z; vals[pos + 2] = Float3s[i].z;
} }
return vals; return vals;
} }
@ -282,32 +259,32 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
public Polygon SubdivideCatmullClark(int segments) public Polygon SubdivideCatmullClark(int segments)
{ {
// Thanks Saalty for making this accidentally. // Thanks Saalty for making this accidentally.
List<Vert> newVerts = new(); List<Float3> newFloat3s = new();
for (int i = 0; i < Verts.Length; i++) for (int i = 0; i < Float3s.Length; i++)
{ {
for (int factor = 0; factor < segments; factor++) for (int factor = 0; factor < segments; factor++)
{ {
float unit = factor / (float)(segments * 2), unit2 = unit + 0.5f, lastUnit = unit * 2; float unit = factor / (float)(segments * 2), unit2 = unit + 0.5f, lastUnit = unit * 2;
Vert p1, p2; Float3 p1, p2;
if (i == Verts.Length - 1) if (i == Float3s.Length - 1)
{ {
p1 = Verts[^1] + (Verts[0] - Verts[^1]) * unit2; p1 = Float3s[^1] + (Float3s[0] - Float3s[^1]) * unit2;
p2 = Verts[0] + (Verts[1] - Verts[0]) * unit; p2 = Float3s[0] + (Float3s[1] - Float3s[0]) * unit;
} }
else if (i == Verts.Length - 2) else if (i == Float3s.Length - 2)
{ {
p1 = Verts[^2] + (Verts[^1] - Verts[^2]) * unit2; p1 = Float3s[^2] + (Float3s[^1] - Float3s[^2]) * unit2;
p2 = Verts[^1] + (Verts[0] - Verts[^1]) * unit; p2 = Float3s[^1] + (Float3s[0] - Float3s[^1]) * unit;
} }
else else
{ {
p1 = Verts[i] + (Verts[i + 1] - Verts[i]) * unit2; p1 = Float3s[i] + (Float3s[i + 1] - Float3s[i]) * unit2;
p2 = Verts[i + 1] + (Verts[i + 2] - Verts[i + 1]) * unit; p2 = Float3s[i + 1] + (Float3s[i + 2] - Float3s[i + 1]) * unit;
} }
newVerts.Add(p1 + (p2 - p1) * lastUnit); newFloat3s.Add(p1 + (p2 - p1) * lastUnit);
} }
} }
return new(newVerts.ToArray()); return new(newFloat3s.ToArray());
} }
[Obsolete("This method doesn't work very well, and will give very weird results in certain cases. " + [Obsolete("This method doesn't work very well, and will give very weird results in certain cases. " +
@ -317,15 +294,15 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
// This may cause issues. FIXME // This may cause issues. FIXME
// Tbh, not even sure if this works. This was a bit confusing. // 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]) }; if (Float3s.Length == 3) return new Triangle[] { new(Float3s[0], Float3s[1], Float3s[2]) };
(int posA, int posB, Line line)? closest = null; (int posA, int posB, Line line)? closest = null;
for (int i = 0; i < Verts.Length; i++) for (int i = 0; i < Float3s.Length; i++)
{ {
for (int j = 0; j < Verts.Length; j++) for (int j = 0; j < Float3s.Length; j++)
{ {
if (i == j) continue; if (i == j) continue;
Line l = new(Verts[i], Verts[j]); Line l = new(Float3s[i], Float3s[j]);
if (Lines.Contains(l)) continue; if (Lines.Contains(l)) continue;
if (!closest.HasValue || closest.Value.line.Length > l.Length) closest = (i, j, l); if (!closest.HasValue || closest.Value.line.Length > l.Length) closest = (i, j, l);
@ -356,30 +333,30 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
return tris.ToArray(); return tris.ToArray();
} }
private static bool CheckVerts(params Polygon[] polys) private static bool CheckFloat3s(params Polygon[] polys)
{ {
int len = -1; int len = -1;
foreach (Polygon poly in polys) foreach (Polygon poly in polys)
{ {
if (len == -1) if (len == -1)
{ {
len = poly.Verts.Length; len = poly.Float3s.Length;
continue; continue;
} }
if (poly.Verts.Length != len) return false; if (poly.Float3s.Length != len) return false;
} }
return true; return true;
} }
private static Line[] GenerateLines(Vert[] verts) private static Line[] GenerateLines(Float3[] verts)
{ {
Line[] lines = new Line[verts.Length]; Line[] lines = new Line[verts.Length];
for (int i = 0; i < lines.Length; i++) for (int i = 0; i < lines.Length; i++)
lines[i] = new(verts[i], verts[i == lines.Length - 1 ? 0 : i + 1]); lines[i] = new(verts[i], verts[i == lines.Length - 1 ? 0 : i + 1]);
return lines; return lines;
} }
private static Vert[] GenerateVerts(Line[] lines) private static Float3[] GenerateFloat3s(Line[] lines)
{ {
Vert[] verts = new Vert[lines.Length]; Float3[] verts = new Float3[lines.Length];
for (int i = 0; i < verts.Length; i++) for (int i = 0; i < verts.Length; i++)
{ {
verts[i] = lines[i].a; verts[i] = lines[i].a;
@ -391,13 +368,13 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
public static Polygon operator +(Polygon a, Polygon b) public static Polygon operator +(Polygon a, Polygon b)
{ {
if (!CheckVerts(a, b)) throw new DifferingVertCountException(a, b); if (!CheckFloat3s(a, b)) throw new DifferingVertCountException(a, b);
Line[][] lines = new Line[2][] { a.Lines, b.Lines }; Line[][] lines = new Line[2][] { a.Lines, b.Lines };
Line[] res = new Line[a.Lines.Length]; Line[] res = new Line[a.Lines.Length];
for (int i = 0; i < res.Length; i++) res[i] = lines[0][i] + lines[1][i]; for (int i = 0; i < res.Length; i++) res[i] = lines[0][i] + lines[1][i];
return new(res); return new(res);
} }
public static Polygon operator +(Polygon a, Vert b) public static Polygon operator +(Polygon a, Float3 b)
{ {
Line[] lines = a.Lines; Line[] lines = a.Lines;
for (int i = 0; i < lines.Length; i++) lines[i] += b; for (int i = 0; i < lines.Length; i++) lines[i] += b;
@ -411,13 +388,13 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
} }
public static Polygon operator -(Polygon a, Polygon b) public static Polygon operator -(Polygon a, Polygon b)
{ {
if (!CheckVerts(a, b)) throw new DifferingVertCountException(a, b); if (!CheckFloat3s(a, b)) throw new DifferingVertCountException(a, b);
Line[][] lines = new Line[2][] { a.Lines, b.Lines }; Line[][] lines = new Line[2][] { a.Lines, b.Lines };
Line[] res = new Line[a.Lines.Length]; Line[] res = new Line[a.Lines.Length];
for (int i = 0; i < res.Length; i++) res[i] = lines[0][i] - lines[1][i]; for (int i = 0; i < res.Length; i++) res[i] = lines[0][i] - lines[1][i];
return new(res); return new(res);
} }
public static Polygon operator -(Polygon a, Vert b) public static Polygon operator -(Polygon a, Float3 b)
{ {
Line[] lines = a.Lines; Line[] lines = a.Lines;
for (int i = 0; i < lines.Length; i++) lines[i] -= b; for (int i = 0; i < lines.Length; i++) lines[i] -= b;
@ -425,13 +402,13 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
} }
public static Polygon operator *(Polygon a, Polygon b) public static Polygon operator *(Polygon a, Polygon b)
{ {
if (!CheckVerts(a, b)) throw new DifferingVertCountException(a, b); if (!CheckFloat3s(a, b)) throw new DifferingVertCountException(a, b);
Line[][] lines = new Line[2][] { a.Lines, b.Lines }; Line[][] lines = new Line[2][] { a.Lines, b.Lines };
Line[] res = new Line[a.Lines.Length]; Line[] res = new Line[a.Lines.Length];
for (int i = 0; i < res.Length; i++) res[i] = lines[0][i] * lines[1][i]; for (int i = 0; i < res.Length; i++) res[i] = lines[0][i] * lines[1][i];
return new(res); return new(res);
} }
public static Polygon operator *(Polygon a, Vert b) public static Polygon operator *(Polygon a, Float3 b)
{ {
Line[] lines = a.Lines; Line[] lines = a.Lines;
for (int i = 0; i < lines.Length; i++) lines[i] *= b; for (int i = 0; i < lines.Length; i++) lines[i] *= b;
@ -445,13 +422,13 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
} }
public static Polygon operator /(Polygon a, Polygon b) public static Polygon operator /(Polygon a, Polygon b)
{ {
if (!CheckVerts(a, b)) throw new DifferingVertCountException(a, b); if (!CheckFloat3s(a, b)) throw new DifferingVertCountException(a, b);
Line[][] lines = new Line[2][] { a.Lines, b.Lines }; Line[][] lines = new Line[2][] { a.Lines, b.Lines };
Line[] res = new Line[a.Lines.Length]; Line[] res = new Line[a.Lines.Length];
for (int i = 0; i < res.Length; i++) res[i] = lines[0][i] / lines[1][i]; for (int i = 0; i < res.Length; i++) res[i] = lines[0][i] / lines[1][i];
return new(res); return new(res);
} }
public static Polygon operator /(Polygon a, Vert b) public static Polygon operator /(Polygon a, Float3 b)
{ {
Line[] lines = a.Lines; Line[] lines = a.Lines;
for (int i = 0; i < lines.Length; i++) lines[i] /= b; for (int i = 0; i < lines.Length; i++) lines[i] /= b;
@ -466,10 +443,8 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
public static bool operator ==(Polygon a, Polygon b) => a.Equals(b); public static bool operator ==(Polygon a, Polygon b) => a.Equals(b);
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<Vert?> fill) => new(fill);
public static implicit operator Polygon(Fill<Float3?> fill) => new(fill); public static implicit operator Polygon(Fill<Float3?> fill) => new(fill);
public static implicit operator Polygon(Fill<Line?> fill) => new(fill); public static implicit operator Polygon(Fill<Line?> fill) => new(fill);
public static implicit operator Polygon(Vert[] verts) => new(verts);
public static implicit operator Polygon(Float3[] verts) => new(verts); public static implicit operator Polygon(Float3[] verts) => new(verts);
public static implicit operator Polygon(Line[] lines) => new(lines); 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(Triangle tri) => new(tri.AB, tri.BC, tri.CA);

View File

@ -2,10 +2,10 @@
public record class Quadrilateral : IAbsolute<Quadrilateral>, IAverage<Quadrilateral>, ICeiling<Quadrilateral>, public record class Quadrilateral : IAbsolute<Quadrilateral>, IAverage<Quadrilateral>, ICeiling<Quadrilateral>,
IClamp<Quadrilateral>, IEquatable<Quadrilateral>, IFloor<Quadrilateral>, IClamp<Quadrilateral>, IEquatable<Quadrilateral>, IFloor<Quadrilateral>,
IFromTuple<Quadrilateral, (Vert a, Vert b, Vert c, Vert d)>, IGroup<Vert>, IIndexAll<Vert>, IIndexRangeAll<Vert>, IFromTuple<Quadrilateral, (Float3 a, Float3 b, Float3 c, Float3 d)>, IGroup<Float3>, IIndexAll<Float3>, IIndexRangeAll<Float3>,
ILerp<Quadrilateral, float>, IRound<Quadrilateral>, IShape2d<float>, ITriangulate ILerp<Quadrilateral, float>, IRound<Quadrilateral>, IShape2d<float>, ITriangulate
{ {
public Vert A public Float3 A
{ {
get => p_a; get => p_a;
set set
@ -15,7 +15,7 @@ public record class Quadrilateral : IAbsolute<Quadrilateral>, IAverage<Quadrilat
p_da.b = value; p_da.b = value;
} }
} }
public Vert B public Float3 B
{ {
get => p_b; get => p_b;
set set
@ -25,7 +25,7 @@ public record class Quadrilateral : IAbsolute<Quadrilateral>, IAverage<Quadrilat
p_bc.a = value; p_bc.a = value;
} }
} }
public Vert C public Float3 C
{ {
get => p_c; get => p_c;
set set
@ -35,7 +35,7 @@ public record class Quadrilateral : IAbsolute<Quadrilateral>, IAverage<Quadrilat
p_cd.a = value; p_cd.a = value;
} }
} }
public Vert D public Float3 D
{ {
get => p_d; get => p_d;
set set
@ -94,7 +94,7 @@ public record class Quadrilateral : IAbsolute<Quadrilateral>, IAverage<Quadrilat
} }
} }
private Vert p_a, p_b, p_c, p_d; private Float3 p_a, p_b, p_c, p_d;
private Line p_ab, p_bc, p_cd, p_da; 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")] [Obsolete("This field doesn't account for the Z-axis. This will be fixed in v2.4.0")]
@ -107,10 +107,10 @@ public record class Quadrilateral : IAbsolute<Quadrilateral>, IAverage<Quadrilat
return val; return val;
} }
} }
public Vert Midpoint => Vert.Average(A, B, C, D); public Float3 Midpoint => Float3.Average(A, B, C, D);
public float Perimeter => AB.Length + BC.Length + CD.Length + DA.Length; public float Perimeter => AB.Length + BC.Length + CD.Length + DA.Length;
public Quadrilateral(Vert a, Vert b, Vert c, Vert d) public Quadrilateral(Float3 a, Float3 b, Float3 c, Float3 d)
{ {
p_a = a; p_a = a;
p_b = b; p_b = b;
@ -135,20 +135,19 @@ public record class Quadrilateral : IAbsolute<Quadrilateral>, IAverage<Quadrilat
p_da = da; p_da = da;
} }
public Quadrilateral(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) public Quadrilateral(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4)
: this(new Vert(x1, y1), new(x2, y2), new(x3, y3), new(x4, 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, 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) float z3, float x4, float y4, float z4)
: this(new Vert(x1, y1, z1), new(x2, y2, z2), new(x3, y3, z3), new(x4, y4, z4)) { } : this(new Float3(x1, y1, z1), new(x2, y2, z2), new(x3, y3, z3), new(x4, y4, z4)) { }
public Quadrilateral(Fill<Float3> fill) : this(fill(0), fill(1), fill(2), fill(3)) { } public Quadrilateral(Fill<Float3> fill) : this(fill(0), fill(1), fill(2), fill(3)) { }
public Quadrilateral(Fill<Int3> fill) : this(fill(0), fill(1), fill(2), fill(3)) { } public Quadrilateral(Fill<Int3> fill) : this(fill(0), fill(1), fill(2), fill(3)) { }
public Quadrilateral(Fill<Vert> fill) : this(fill(0), fill(1), fill(2), fill(3)) { }
public Quadrilateral(Fill<Line> fill) : this(fill(0), fill(1), fill(2), fill(3)) { } public Quadrilateral(Fill<Line> fill) : this(fill(0), fill(1), fill(2), fill(3)) { }
public Quadrilateral(Fill<float> fill) : this(fill(0), fill(1), fill(2), fill(3), fill(4), fill(5), fill(6), public Quadrilateral(Fill<float> 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)) { } fill(7), fill(8), fill(9), fill(10), fill(11)) { }
public Quadrilateral(Fill<int> fill) : this(fill(0), fill(1), fill(2), fill(3), fill(4), fill(5), fill(6), public Quadrilateral(Fill<int> 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)) { } fill(7), fill(8), fill(9), fill(10), fill(11)) { }
public Vert this[int index] public Float3 this[int index]
{ {
get => index switch get => index switch
{ {
@ -182,18 +181,18 @@ public record class Quadrilateral : IAbsolute<Quadrilateral>, IAverage<Quadrilat
} }
} }
} }
public Vert this[Index index] public Float3 this[Index index]
{ {
get => this[index.IsFromEnd ? 4 - index.Value : index.Value]; get => this[index.IsFromEnd ? 4 - index.Value : index.Value];
set => this[index.IsFromEnd ? 4 - index.Value : index.Value] = value; set => this[index.IsFromEnd ? 4 - index.Value : index.Value] = value;
} }
public Vert[] this[Range range] public Float3[] this[Range range]
{ {
get get
{ {
int start = range.Start.IsFromEnd ? 4 - range.Start.Value : range.Start.Value; int start = range.Start.IsFromEnd ? 4 - range.Start.Value : range.Start.Value;
int end = range.End.IsFromEnd ? 4 - range.End.Value : range.End.Value; int end = range.End.IsFromEnd ? 4 - range.End.Value : range.End.Value;
List<Vert> res = new(); List<Float3> res = new();
for (int i = start; i < end; i++) res.Add(this[i]); for (int i = start; i < end; i++) res.Add(this[i]);
return res.ToArray(); return res.ToArray();
} }
@ -206,44 +205,44 @@ public record class Quadrilateral : IAbsolute<Quadrilateral>, IAverage<Quadrilat
} }
public static Quadrilateral Absolute(Quadrilateral val) => public static Quadrilateral Absolute(Quadrilateral val) =>
new(Vert.Absolute(val.A), Vert.Absolute(val.B), Vert.Absolute(val.C), Vert.Absolute(val.D)); new(Float3.Absolute(val.A), Float3.Absolute(val.B), Float3.Absolute(val.C), Float3.Absolute(val.D));
public static Quadrilateral Average(params Quadrilateral[] vals) public static Quadrilateral Average(params Quadrilateral[] vals)
{ {
(Vert[] As, Vert[] Bs, Vert[] Cs, Vert[] Ds) = SplitVertArray(vals); (Float3[] As, Float3[] Bs, Float3[] Cs, Float3[] Ds) = SplitFloat3Array(vals);
return new(Vert.Average(As), Vert.Average(Bs), Vert.Average(Cs), Vert.Average(Ds)); return new(Float3.Average(As), Float3.Average(Bs), Float3.Average(Cs), Float3.Average(Ds));
} }
public static Quadrilateral Ceiling(Quadrilateral val) => public static Quadrilateral Ceiling(Quadrilateral val) =>
new(Vert.Ceiling(val.A), Vert.Ceiling(val.B), Vert.Ceiling(val.C), Vert.Ceiling(val.D)); 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) => public static Quadrilateral Clamp(Quadrilateral val, Quadrilateral min, Quadrilateral 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), 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),
Vert.Clamp(val.D, min.D, max.D)); Float3.Clamp(val.D, min.D, max.D));
public static Quadrilateral Floor(Quadrilateral val) => public static Quadrilateral Floor(Quadrilateral val) =>
new(Vert.Floor(val.A), Vert.Floor(val.B), Vert.Floor(val.C), Vert.Floor(val.D)); 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) => public static Quadrilateral Lerp(Quadrilateral a, Quadrilateral b, float t, bool clamp = true) =>
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), 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),
Vert.Lerp(a.D, b.D, t, clamp)); Float3.Lerp(a.D, b.D, t, clamp));
public static Quadrilateral Max(params Quadrilateral[] vals) public static Quadrilateral Max(params Quadrilateral[] vals)
{ {
(Vert[] As, Vert[] Bs, Vert[] Cs, Vert[] Ds) = SplitVertArray(vals); (Float3[] As, Float3[] Bs, Float3[] Cs, Float3[] Ds) = SplitFloat3Array(vals);
return new(Vert.Max(As), Vert.Max(Bs), Vert.Max(Cs), Vert.Max(Ds)); return new(Float3.Max(As), Float3.Max(Bs), Float3.Max(Cs), Float3.Max(Ds));
} }
public static Quadrilateral Median(params Quadrilateral[] vals) public static Quadrilateral Median(params Quadrilateral[] vals)
{ {
(Vert[] As, Vert[] Bs, Vert[] Cs, Vert[] Ds) = SplitVertArray(vals); (Float3[] As, Float3[] Bs, Float3[] Cs, Float3[] Ds) = SplitFloat3Array(vals);
return new(Vert.Median(As), Vert.Median(Bs), Vert.Median(Cs), Vert.Median(Ds)); return new(Float3.Median(As), Float3.Median(Bs), Float3.Median(Cs), Float3.Median(Ds));
} }
public static Quadrilateral Min(params Quadrilateral[] vals) public static Quadrilateral Min(params Quadrilateral[] vals)
{ {
(Vert[] As, Vert[] Bs, Vert[] Cs, Vert[] Ds) = SplitVertArray(vals); (Float3[] As, Float3[] Bs, Float3[] Cs, Float3[] Ds) = SplitFloat3Array(vals);
return new(Vert.Min(As), Vert.Min(Bs), Vert.Min(Cs), Vert.Min(Ds)); return new(Float3.Min(As), Float3.Min(Bs), Float3.Min(Cs), Float3.Min(Ds));
} }
public static Quadrilateral Round(Quadrilateral val) => public static Quadrilateral Round(Quadrilateral val) =>
new(Vert.Round(val.A), Vert.Round(val.B), Vert.Round(val.C), Vert.Round(val.D)); new(Float3.Round(val.A), Float3.Round(val.B), Float3.Round(val.C), Float3.Round(val.D));
public static (Vert[] As, Vert[] Bs, Vert[] Cs, Vert[] Ds) SplitVertArray(params Quadrilateral[] quads) public static (Float3[] As, Float3[] Bs, Float3[] Cs, Float3[] Ds) SplitFloat3Array(params Quadrilateral[] quads)
{ {
Vert[] a = new Vert[quads.Length], b = new Vert[quads.Length], Float3[] a = new Float3[quads.Length], b = new Float3[quads.Length],
c = new Vert[quads.Length], d = new Vert[quads.Length]; c = new Float3[quads.Length], d = new Float3[quads.Length];
for (int i = 0; i < quads.Length; i++) for (int i = 0; i < quads.Length; i++)
{ {
a[i] = quads[i].A; a[i] = quads[i].A;
@ -275,18 +274,18 @@ public record class Quadrilateral : IAbsolute<Quadrilateral>, IAverage<Quadrilat
for (int i = 0; i < quads.Length; i++) for (int i = 0; i < quads.Length; i++)
{ {
int pos = i * 12; int pos = i * 12;
vals[pos + 0] = quads[i].A.position.x; vals[pos + 0] = quads[i].A.x;
vals[pos + 1] = quads[i].A.position.y; vals[pos + 1] = quads[i].A.y;
vals[pos + 2] = quads[i].A.position.z; vals[pos + 2] = quads[i].A.z;
vals[pos + 3] = quads[i].B.position.x; vals[pos + 3] = quads[i].B.x;
vals[pos + 4] = quads[i].B.position.y; vals[pos + 4] = quads[i].B.y;
vals[pos + 5] = quads[i].B.position.z; vals[pos + 5] = quads[i].B.z;
vals[pos + 6] = quads[i].C.position.x; vals[pos + 6] = quads[i].C.x;
vals[pos + 7] = quads[i].C.position.y; vals[pos + 7] = quads[i].C.y;
vals[pos + 8] = quads[i].C.position.z; vals[pos + 8] = quads[i].C.z;
vals[pos + 9] = quads[i].D.position.x; vals[pos + 9] = quads[i].D.x;
vals[pos + 10] = quads[i].D.position.y; vals[pos + 10] = quads[i].D.y;
vals[pos + 11] = quads[i].D.position.z; vals[pos + 11] = quads[i].D.z;
} }
return vals; return vals;
} }
@ -300,7 +299,7 @@ public record class Quadrilateral : IAbsolute<Quadrilateral>, IAverage<Quadrilat
public override int GetHashCode() => base.GetHashCode(); public override int GetHashCode() => base.GetHashCode();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public IEnumerator<Vert> GetEnumerator() public IEnumerator<Float3> GetEnumerator()
{ {
yield return A; yield return A;
yield return B; yield return B;
@ -308,22 +307,22 @@ public record class Quadrilateral : IAbsolute<Quadrilateral>, IAverage<Quadrilat
yield return D; yield return D;
} }
public Vert[] ToArray() => new Vert[] { A, B, C, D }; public Float3[] ToArray() => new Float3[] { A, B, C, D };
public Fill<Vert> ToFill() public Fill<Float3> ToFill()
{ {
Quadrilateral @this = this; Quadrilateral @this = this;
return i => @this[i]; return i => @this[i];
} }
public List<Vert> ToList() => new() { A, B, C, D }; public List<Float3> ToList() => new() { A, B, C, D };
public float[] ToFloatArray() => new float[] { A.position.x, A.position.y, A.position.z, public float[] ToFloatArray() => new float[] { A.x, A.y, A.z,
B.position.x, B.position.y, B.position.z, B.x, B.y, B.z,
C.position.x, C.position.y, C.position.z, C.x, C.y, C.z,
D.position.x, D.position.y, D.position.z }; D.x, D.y, D.z };
public List<float> ToFloatList() => new() { A.position.x, A.position.y, A.position.z, public List<float> ToFloatList() => new() { A.x, A.y, A.z,
B.position.x, B.position.y, B.position.z, B.x, B.y, B.z,
C.position.x, C.position.y, C.position.z, C.x, C.y, C.z,
D.position.x, D.position.y, D.position.z }; D.x, D.y, D.z };
public Triangle[] Triangulate() => new Line(A, C).Length > new Line(B, D).Length ? 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) }; new Triangle[] { new(A, B, C), new(C, D, A) } : new Triangle[] { new(B, C, D), new(D, A, B) };
@ -343,26 +342,25 @@ public record class Quadrilateral : IAbsolute<Quadrilateral>, IAverage<Quadrilat
public static Quadrilateral operator +(Quadrilateral a, Quadrilateral b) => new(a.A + b.A, a.B + b.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); a.C + b.C, a.D + b.D);
public static Quadrilateral operator +(Quadrilateral a, Vert b) => new(a.A + b, a.B + b, a.C + b, a.D + b); 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 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, 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); a.C - b.C, a.D - b.D);
public static Quadrilateral operator -(Quadrilateral a, Vert b) => new(a.A - b, a.B - b, a.C - b, a.D - b); 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, 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); a.C * b.C, a.D * b.D);
public static Quadrilateral operator *(Quadrilateral a, Vert b) => new(a.A * b, a.B * b, a.C * b, a.D * b); 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, 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, 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); a.C / b.C, a.D / b.D);
public static Quadrilateral operator /(Quadrilateral a, Vert b) => new(a.A / b, a.B / b, a.C / b, a.D / b); 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, float b) => new(a.A / b, a.B / b, a.C / b, a.D / b);
public static implicit operator Quadrilateral(Fill<Vert> fill) => new(fill);
public static implicit operator Quadrilateral(Fill<Float3> fill) => new(fill); public static implicit operator Quadrilateral(Fill<Float3> fill) => new(fill);
public static implicit operator Quadrilateral(Fill<Int3> fill) => new(fill); public static implicit operator Quadrilateral(Fill<Int3> fill) => new(fill);
public static implicit operator Quadrilateral(Fill<Line> fill) => new(fill); public static implicit operator Quadrilateral(Fill<Line> fill) => new(fill);
public static implicit operator Quadrilateral(Fill<float> fill) => new(fill); public static implicit operator Quadrilateral(Fill<float> fill) => new(fill);
public static implicit operator Quadrilateral(Fill<int> fill) => new(fill); public static implicit operator Quadrilateral(Fill<int> fill) => new(fill);
public static implicit operator Quadrilateral((Vert a, Vert b, Vert c, Vert d) val) => public static implicit operator Quadrilateral((Float3 a, Float3 b, Float3 c, Float3 d) val) =>
new(val.a, val.b, val.c, val.d); new(val.a, val.b, val.c, val.d);
} }

View File

@ -1,66 +1,66 @@
namespace Nerd_STF.Mathematics.Geometry; namespace Nerd_STF.Mathematics.Geometry;
public record class Sphere : IAverage<Sphere>, ICeiling<Sphere>, IClamp<Sphere>, IClosestTo<Vert>, public record class Sphere : IAverage<Sphere>, ICeiling<Sphere>, IClamp<Sphere>, IClosestTo<Float3>,
IComparable<Sphere>, IComparable<float>, IContains<Vert>, IEquatable<Sphere>, IEquatable<float>, IFloor<Sphere>, IComparable<Sphere>, IComparable<float>, IContains<Float3>, IEquatable<Sphere>, IEquatable<float>, IFloor<Sphere>,
IFromTuple<Sphere, (Vert center, float radius)>, ILerp<Sphere, float>, IMax<Sphere>, IMedian<Sphere>, IFromTuple<Sphere, (Float3 center, float radius)>, ILerp<Sphere, float>, IMax<Sphere>, IMedian<Sphere>,
IMin<Sphere>, IRound<Sphere>, ISplittable<Sphere, (Vert[] centers, float[] radii)> IMin<Sphere>, IRound<Sphere>, ISplittable<Sphere, (Float3[] centers, float[] radii)>
{ {
public static Sphere Unit => new(Vert.Zero, 1); public static Sphere Unit => new(Float3.Zero, 1);
public Vert center; public Float3 center;
public float radius; public float radius;
public float SurfaceArea => 4 * Constants.Pi * radius * radius; public float SurfaceArea => 4 * Constants.Pi * radius * radius;
public float Volume => 4 / 3 * (Constants.Pi * radius * radius * radius); public float Volume => 4 / 3 * (Constants.Pi * radius * radius * radius);
public static Sphere FromDiameter(Vert a, Vert b) => new(Vert.Average(a, b), (a - b).Magnitude / 2); public static Sphere FromDiameter(Float3 a, Float3 b) => new(Float3.Average(a, b), (a - b).Magnitude / 2);
public static Sphere FromRadius(Vert center, Vert radius) => new(center, (center - radius).Magnitude); public static Sphere FromRadius(Float3 center, Float3 radius) => new(center, (center - radius).Magnitude);
public Sphere(Vert center, float radius) public Sphere(Float3 center, float radius)
{ {
this.center = center; this.center = center;
this.radius = radius; this.radius = radius;
} }
public Sphere(float cX, float cY, float radius) : this(new Vert(cX, cY), 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 Vert(cX, cY, cZ), radius) { } public Sphere(float cX, float cY, float cZ, float radius) : this(new Float3(cX, cY, cZ), radius) { }
public Sphere(Fill<float> fill, float radius) : this(new Vert(fill), radius) { } public Sphere(Fill<float> fill, float radius) : this(new Float3(fill), radius) { }
public Sphere(Fill<float> fill) : this(new Vert(fill), fill(3)) { } public Sphere(Fill<float> fill) : this(new Float3(fill), fill(3)) { }
public Sphere(Fill<int> fill, float radius) : this(new Vert(fill), radius) { } public Sphere(Fill<int> fill, float radius) : this(new Float3(fill), radius) { }
public Sphere(Fill<int> fill) : this(new Vert(fill), fill(3)) { } public Sphere(Fill<int> fill) : this(new Float3(fill), fill(3)) { }
public Sphere(Fill<Vert> fill, float radius) : this(fill(0), radius) { } public Sphere(Fill<Float3> fill, float radius) : this(fill(0), radius) { }
public Sphere(Fill<Vert> fillA, Fill<float> fillB) : this(fillA(0), fillB(0)) { } public Sphere(Fill<Float3> fillA, Fill<float> fillB) : this(fillA(0), fillB(0)) { }
public static Sphere Average(params Sphere[] vals) public static Sphere Average(params Sphere[] vals)
{ {
(Vert[] centers, float[] radii) = SplitArray(vals); (Float3[] centers, float[] radii) = SplitArray(vals);
return new(Vert.Average(centers), Mathf.Average(radii)); return new(Float3.Average(centers), Mathf.Average(radii));
} }
public static Sphere Ceiling(Sphere val) => new(Vert.Ceiling(val.center), Mathf.Ceiling(val.radius)); 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) => public static Sphere Clamp(Sphere val, Sphere min, Sphere max) =>
new(Vert.Clamp(val.center, min.center, max.center), Mathf.Clamp(val.radius, min.radius, max.radius)); new(Float3.Clamp(val.center, min.center, max.center), Mathf.Clamp(val.radius, min.radius, max.radius));
public static Sphere Floor(Sphere val) => new(Vert.Floor(val.center), Mathf.Floor(val.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) => public static Sphere Lerp(Sphere a, Sphere b, float t, bool clamp = true) =>
new(Vert.Lerp(a.center, b.center, t, clamp), Mathf.Lerp(a.radius, b.radius, t, clamp)); new(Float3.Lerp(a.center, b.center, t, clamp), Mathf.Lerp(a.radius, b.radius, t, clamp));
public static Sphere Max(params Sphere[] vals) public static Sphere Max(params Sphere[] vals)
{ {
(Vert[] centers, float[] radii) = SplitArray(vals); (Float3[] centers, float[] radii) = SplitArray(vals);
return new(Vert.Max(centers), Mathf.Max(radii)); return new(Float3.Max(centers), Mathf.Max(radii));
} }
public static Sphere Median(params Sphere[] vals) public static Sphere Median(params Sphere[] vals)
{ {
(Vert[] centers, float[] radii) = SplitArray(vals); (Float3[] centers, float[] radii) = SplitArray(vals);
return new(Vert.Median(centers), Mathf.Median(radii)); return new(Float3.Median(centers), Mathf.Median(radii));
} }
public static Sphere Min(params Sphere[] vals) public static Sphere Min(params Sphere[] vals)
{ {
(Vert[] centers, float[] radii) = SplitArray(vals); (Float3[] centers, float[] radii) = SplitArray(vals);
return new(Vert.Min(centers), Mathf.Min(radii)); return new(Float3.Min(centers), Mathf.Min(radii));
} }
public static Sphere Round(Sphere val) => new(Vert.Round(val.center), Mathf.Round(val.radius)); public static Sphere Round(Sphere val) => new(Float3.Round(val.center), Mathf.Round(val.radius));
public static (Vert[] centers, float[] radii) SplitArray(params Sphere[] spheres) public static (Float3[] centers, float[] radii) SplitArray(params Sphere[] spheres)
{ {
Vert[] centers = new Vert[spheres.Length]; Float3[] centers = new Float3[spheres.Length];
float[] radii = new float[spheres.Length]; float[] radii = new float[spheres.Length];
for (int i = 0; i < spheres.Length; i++) for (int i = 0; i < spheres.Length; i++)
{ {
@ -89,9 +89,9 @@ public record class Sphere : IAverage<Sphere>, ICeiling<Sphere>, IClamp<Sphere>,
"This method will be removed in Nerd_STF 2.5.0.")] "This method will be removed in Nerd_STF 2.5.0.")]
public int CompareTo(float volume) => Volume.CompareTo(volume); public int CompareTo(float volume) => Volume.CompareTo(volume);
public bool Contains(Vert vert) => (center - vert).Magnitude <= radius; public bool Contains(Float3 vert) => (center - vert).Magnitude <= radius;
public Vert ClosestTo(Vert vert) => Contains(vert) ? vert : ((vert - center).Normalized * radius) + center; public Float3 ClosestTo(Float3 vert) => Contains(vert) ? vert : ((vert - center).Normalized * radius) + center;
protected virtual bool PrintMembers(StringBuilder builder) protected virtual bool PrintMembers(StringBuilder builder)
{ {
@ -103,10 +103,10 @@ public record class Sphere : IAverage<Sphere>, ICeiling<Sphere>, IClamp<Sphere>,
} }
public static Sphere operator +(Sphere a, Sphere b) => new(a.center + b.center, a.radius + b.radius); public static Sphere operator +(Sphere a, Sphere b) => new(a.center + b.center, a.radius + b.radius);
public static Sphere operator +(Sphere a, Vert b) => new(a.center + b, a.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, 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, Sphere b) => new(a.center + b.center, a.radius + b.radius);
public static Sphere operator -(Sphere a, Vert b) => new(a.center + b, a.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, 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, 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, float b) => new(a.center * b, a.radius * b);
@ -143,6 +143,6 @@ public record class Sphere : IAverage<Sphere>, ICeiling<Sphere>, IClamp<Sphere>,
"This method will be removed in Nerd_STF 2.5.0.")] "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 bool operator <=(Sphere a, float b) => a < b || a == b;
public static implicit operator Sphere((Vert center, float radius) val) => public static implicit operator Sphere((Float3 center, float radius) val) =>
new(val.center, val.radius); new(val.center, val.radius);
} }

View File

@ -3,10 +3,10 @@
namespace Nerd_STF.Mathematics.Geometry; namespace Nerd_STF.Mathematics.Geometry;
public record class Triangle : IAbsolute<Triangle>, IAverage<Triangle>, ICeiling<Triangle>, IClamp<Triangle>, public record class Triangle : IAbsolute<Triangle>, IAverage<Triangle>, ICeiling<Triangle>, IClamp<Triangle>,
IEquatable<Triangle>, IFloor<Triangle>, IFromTuple<Triangle, (Vert a, Vert b, Vert c)>, IGroup<Vert>, IEquatable<Triangle>, IFloor<Triangle>, IFromTuple<Triangle, (Float3 a, Float3 b, Float3 c)>, IGroup<Float3>,
IIndexAll<Vert>, IIndexRangeAll<Vert>, ILerp<Triangle, float>, IRound<Triangle>, IShape2d<float> IIndexAll<Float3>, IIndexRangeAll<Float3>, ILerp<Triangle, float>, IRound<Triangle>, IShape2d<float>
{ {
public Vert A public Float3 A
{ {
get => p_a; get => p_a;
set set
@ -16,7 +16,7 @@ public record class Triangle : IAbsolute<Triangle>, IAverage<Triangle>, ICeiling
p_ca.b = value; p_ca.b = value;
} }
} }
public Vert B public Float3 B
{ {
get => p_b; get => p_b;
set set
@ -26,7 +26,7 @@ public record class Triangle : IAbsolute<Triangle>, IAverage<Triangle>, ICeiling
p_bc.a = value; p_bc.a = value;
} }
} }
public Vert C public Float3 C
{ {
get => p_c; get => p_c;
set set
@ -73,17 +73,17 @@ public record class Triangle : IAbsolute<Triangle>, IAverage<Triangle>, ICeiling
} }
} }
private Vert p_a, p_b, p_c; private Float3 p_a, p_b, p_c;
private Line p_ab, p_bc, p_ca; 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")] [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.position.x * B.position.y) + (B.position.x * C.position.y) + public float Area => (float)Mathf.Absolute((A.x * B.y) + (B.x * C.y) +
(C.position.x * A.position.y) - ((B.position.x * A.position.y) + (C.position.x * B.position.y) + (C.x * A.y) - ((B.x * A.y) + (C.x * B.y) +
(A.position.x * C.position.y))) * 0.5f; (A.x * C.y))) * 0.5f;
public Vert Midpoint => Vert.Average(A, B, C); public Float3 Midpoint => Float3.Average(A, B, C);
public float Perimeter => AB.Length + BC.Length + CA.Length; public float Perimeter => AB.Length + BC.Length + CA.Length;
public Triangle(Vert a, Vert b, Vert c) public Triangle(Float3 a, Float3 b, Float3 c)
{ {
p_a = a; p_a = a;
p_b = b; p_b = b;
@ -105,19 +105,18 @@ public record class Triangle : IAbsolute<Triangle>, IAverage<Triangle>, ICeiling
p_ca = ca; p_ca = ca;
} }
public Triangle(float x1, float y1, float x2, float y2, float x3, float y3) public Triangle(float x1, float y1, float x2, float y2, float x3, float y3)
: this(new Vert(x1, y1), new Vert(x2, y2), new Vert(x3, 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, public Triangle(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3,
float z3) : this(new Vert(x1, y1, z1), new Vert(x2, y2, z2), new Vert(x3, y3, z3)) { } float z3) : this(new Float3(x1, y1, z1), new Float3(x2, y2, z2), new Float3(x3, y3, z3)) { }
public Triangle(Fill<Float3> fill) : this(fill(0), fill(1), fill(2)) { } public Triangle(Fill<Float3> fill) : this(fill(0), fill(1), fill(2)) { }
public Triangle(Fill<Int3> fill) : this(fill(0), fill(1), fill(2)) { } public Triangle(Fill<Int3> fill) : this(fill(0), fill(1), fill(2)) { }
public Triangle(Fill<Vert> fill) : this(fill(0), fill(1), fill(2)) { }
public Triangle(Fill<Line> fill) : this(fill(0), fill(1), fill(2)) { } public Triangle(Fill<Line> fill) : this(fill(0), fill(1), fill(2)) { }
public Triangle(Fill<float> fill) : this(fill(0), fill(1), fill(2), fill(3), fill(4), fill(5), fill(6), public Triangle(Fill<float> fill) : this(fill(0), fill(1), fill(2), fill(3), fill(4), fill(5), fill(6),
fill(7), fill(8)) { } fill(7), fill(8)) { }
public Triangle(Fill<int> fill) : this(fill(0), fill(1), fill(2), fill(3), fill(4), fill(5), fill(6), public Triangle(Fill<int> fill) : this(fill(0), fill(1), fill(2), fill(3), fill(4), fill(5), fill(6),
fill(7), fill(8)) { } fill(7), fill(8)) { }
public Vert this[int index] public Float3 this[int index]
{ {
get => index switch get => index switch
{ {
@ -146,18 +145,18 @@ public record class Triangle : IAbsolute<Triangle>, IAverage<Triangle>, ICeiling
} }
} }
} }
public Vert this[Index index] public Float3 this[Index index]
{ {
get => this[index.IsFromEnd ? 3 - index.Value : index.Value]; get => this[index.IsFromEnd ? 3 - index.Value : index.Value];
set => this[index.IsFromEnd ? 3 - index.Value : index.Value] = value; set => this[index.IsFromEnd ? 3 - index.Value : index.Value] = value;
} }
public Vert[] this[Range range] public Float3[] this[Range range]
{ {
get get
{ {
int start = range.Start.IsFromEnd ? 3 - range.Start.Value : range.Start.Value; int start = range.Start.IsFromEnd ? 3 - range.Start.Value : range.Start.Value;
int end = range.End.IsFromEnd ? 3 - range.End.Value : range.End.Value; int end = range.End.IsFromEnd ? 3 - range.End.Value : range.End.Value;
List<Vert> res = new(); List<Float3> res = new();
for (int i = start; i < end; i++) res.Add(this[i]); for (int i = start; i < end; i++) res.Add(this[i]);
return res.ToArray(); return res.ToArray();
} }
@ -170,41 +169,41 @@ public record class Triangle : IAbsolute<Triangle>, IAverage<Triangle>, ICeiling
} }
public static Triangle Absolute(Triangle val) => public static Triangle Absolute(Triangle val) =>
new(Vert.Absolute(val.A), Vert.Absolute(val.B), Vert.Absolute(val.C)); new(Float3.Absolute(val.A), Float3.Absolute(val.B), Float3.Absolute(val.C));
public static Triangle Average(params Triangle[] vals) public static Triangle Average(params Triangle[] vals)
{ {
(Vert[] As, Vert[] Bs, Vert[] Cs) = SplitVertArray(vals); (Float3[] As, Float3[] Bs, Float3[] Cs) = SplitFloat3Array(vals);
return new(Vert.Average(As), Vert.Average(Bs), Vert.Average(Cs)); return new(Float3.Average(As), Float3.Average(Bs), Float3.Average(Cs));
} }
public static Triangle Ceiling(Triangle val) => public static Triangle Ceiling(Triangle val) =>
new(Vert.Ceiling(val.A), Vert.Ceiling(val.B), Vert.Ceiling(val.C)); new(Float3.Ceiling(val.A), Float3.Ceiling(val.B), Float3.Ceiling(val.C));
public static Triangle Clamp(Triangle val, Triangle min, Triangle max) => 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)); 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) => public static Triangle Floor(Triangle val) =>
new(Vert.Floor(val.A), Vert.Floor(val.B), Vert.Floor(val.C)); 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) => public static Triangle Lerp(Triangle a, Triangle b, float t, bool clamp = true) =>
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)); 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) public static Triangle Max(params Triangle[] vals)
{ {
(Vert[] As, Vert[] Bs, Vert[] Cs) = SplitVertArray(vals); (Float3[] As, Float3[] Bs, Float3[] Cs) = SplitFloat3Array(vals);
return new(Vert.Max(As), Vert.Max(Bs), Vert.Max(Cs)); return new(Float3.Max(As), Float3.Max(Bs), Float3.Max(Cs));
} }
public static Triangle Median(params Triangle[] vals) public static Triangle Median(params Triangle[] vals)
{ {
(Vert[] As, Vert[] Bs, Vert[] Cs) = SplitVertArray(vals); (Float3[] As, Float3[] Bs, Float3[] Cs) = SplitFloat3Array(vals);
return new(Vert.Median(As), Vert.Median(Bs), Vert.Median(Cs)); return new(Float3.Median(As), Float3.Median(Bs), Float3.Median(Cs));
} }
public static Triangle Min(params Triangle[] vals) public static Triangle Min(params Triangle[] vals)
{ {
(Vert[] As, Vert[] Bs, Vert[] Cs) = SplitVertArray(vals); (Float3[] As, Float3[] Bs, Float3[] Cs) = SplitFloat3Array(vals);
return new(Vert.Min(As), Vert.Min(Bs), Vert.Min(Cs)); return new(Float3.Min(As), Float3.Min(Bs), Float3.Min(Cs));
} }
public static Triangle Round(Triangle val) => public static Triangle Round(Triangle val) =>
new(Vert.Round(val.A), Vert.Round(val.B), Vert.Round(val.C)); new(Float3.Round(val.A), Float3.Round(val.B), Float3.Round(val.C));
public static (Vert[] As, Vert[] Bs, Vert[] Cs) SplitVertArray(params Triangle[] tris) public static (Float3[] As, Float3[] Bs, Float3[] Cs) SplitFloat3Array(params Triangle[] tris)
{ {
Vert[] a = new Vert[tris.Length], b = new Vert[tris.Length], c = new Vert[tris.Length]; Float3[] a = new Float3[tris.Length], b = new Float3[tris.Length], c = new Float3[tris.Length];
for (int i = 0; i < tris.Length; i++) for (int i = 0; i < tris.Length; i++)
{ {
a[i] = tris[i].A; a[i] = tris[i].A;
@ -231,15 +230,15 @@ public record class Triangle : IAbsolute<Triangle>, IAverage<Triangle>, ICeiling
for (int i = 0; i < tris.Length; i++) for (int i = 0; i < tris.Length; i++)
{ {
int pos = i * 9; int pos = i * 9;
vals[pos + 0] = tris[i].A.position.x; vals[pos + 0] = tris[i].A.x;
vals[pos + 1] = tris[i].A.position.y; vals[pos + 1] = tris[i].A.y;
vals[pos + 2] = tris[i].A.position.z; vals[pos + 2] = tris[i].A.z;
vals[pos + 3] = tris[i].B.position.x; vals[pos + 3] = tris[i].B.x;
vals[pos + 4] = tris[i].B.position.y; vals[pos + 4] = tris[i].B.y;
vals[pos + 5] = tris[i].B.position.z; vals[pos + 5] = tris[i].B.z;
vals[pos + 6] = tris[i].C.position.x; vals[pos + 6] = tris[i].C.x;
vals[pos + 7] = tris[i].C.position.y; vals[pos + 7] = tris[i].C.y;
vals[pos + 8] = tris[i].C.position.z; vals[pos + 8] = tris[i].C.z;
} }
return vals; return vals;
} }
@ -253,27 +252,27 @@ public record class Triangle : IAbsolute<Triangle>, IAverage<Triangle>, ICeiling
public override int GetHashCode() => base.GetHashCode(); public override int GetHashCode() => base.GetHashCode();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public IEnumerator<Vert> GetEnumerator() public IEnumerator<Float3> GetEnumerator()
{ {
yield return A; yield return A;
yield return B; yield return B;
yield return C; yield return C;
} }
public Vert[] ToArray() => new Vert[] { A, B, C }; public Float3[] ToArray() => new Float3[] { A, B, C };
public Fill<Vert> ToFill() public Fill<Float3> ToFill()
{ {
Triangle @this = this; Triangle @this = this;
return i => @this[i]; return i => @this[i];
} }
public List<Vert> ToList() => new() { A, B, C }; public List<Float3> ToList() => new() { A, B, C };
public float[] ToFloatArray() => new float[] { A.position.x, A.position.y, A.position.z, public float[] ToFloatArray() => new float[] { A.x, A.y, A.z,
B.position.x, B.position.y, B.position.z, B.x, B.y, B.z,
C.position.x, C.position.y, C.position.z }; C.x, C.y, C.z };
public List<float> ToFloatList() => new() { A.position.x, A.position.y, A.position.z, public List<float> ToFloatList() => new() { A.x, A.y, A.z,
B.position.x, B.position.y, B.position.z, B.x, B.y, B.z,
C.position.x, C.position.y, C.position.z }; C.x, C.y, C.z };
protected virtual bool PrintMembers(StringBuilder builder) protected virtual bool PrintMembers(StringBuilder builder)
{ {
@ -287,23 +286,22 @@ public record class Triangle : IAbsolute<Triangle>, IAverage<Triangle>, ICeiling
} }
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, 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, 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 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, 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, 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, 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, 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, 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, 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, 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, float b) => new(a.A / b, a.B / b, a.C / b);
public static implicit operator Triangle(Fill<Vert> fill) => new(fill);
public static implicit operator Triangle(Fill<Float3> fill) => new(fill); public static implicit operator Triangle(Fill<Float3> fill) => new(fill);
public static implicit operator Triangle(Fill<Int3> fill) => new(fill); public static implicit operator Triangle(Fill<Int3> fill) => new(fill);
public static implicit operator Triangle(Fill<Line> fill) => new(fill); public static implicit operator Triangle(Fill<Line> fill) => new(fill);
public static implicit operator Triangle(Fill<float> fill) => new(fill); public static implicit operator Triangle(Fill<float> fill) => new(fill);
public static implicit operator Triangle(Fill<int> fill) => new(fill); public static implicit operator Triangle(Fill<int> fill) => new(fill);
public static implicit operator Triangle((Vert a, Vert b, Vert c) val) => public static implicit operator Triangle((Float3 a, Float3 b, Float3 c) val) =>
new(val.a, val.b, val.c); new(val.a, val.b, val.c);
} }

View File

@ -1,106 +0,0 @@
namespace Nerd_STF.Mathematics.Geometry;
public struct Vert : ICloneable, IEquatable<Vert>, IGroup<float>
{
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 float Magnitude => position.Magnitude;
public Vert Normalized => this / Magnitude;
public Float3 position;
public Vert(Float2 pos) : this((Float3)pos) { }
public Vert(Float3 pos) => position = pos;
public Vert(float x, float y) : this(new Float2(x, y)) { }
public Vert(float x, float y, float z) : this(new Float3(x, y, z)) { }
public Vert(Fill<float> fill) : this(new Float3(fill)) { }
public Vert(Fill<int> fill) : this(new Float3(fill)) { }
public float this[int index]
{
get => position[index];
set => position[index] = value;
}
public static Vert Absolute(Vert val) => new(Float3.Absolute(val.position));
public static Vert Average(params Vert[] vals) => Float3.Average(ToFloat3Array(vals));
public static Vert Ceiling(Vert val) => new(Float3.Ceiling(val.position));
public static Vert Clamp(Vert val, Vert min, Vert max) =>
new(Float3.Clamp(val.position, min.position, max.position));
public static Vert ClampMagnitude(Vert val, float minMag, float maxMag) =>
new(Float3.ClampMagnitude(val.position, minMag, maxMag));
public static Vert Cross(Vert a, Vert b, bool normalized = false) =>
new(Float3.Cross(a.position, b.position, normalized));
public static float Dot(Vert a, Vert b) => Float3.Dot(a.position, b.position);
public static float Dot(params Vert[] vals) => Float3.Dot(ToFloat3Array(vals));
public static Vert Floor(Vert val) => new(Float3.Floor(val.position));
public static Vert Lerp(Vert a, Vert b, float t, bool clamp = true) =>
new(Float3.Lerp(a.position, b.position, t, clamp));
public static Vert Median(params Vert[] vals) =>
Float3.Median(ToFloat3Array(vals));
public static Vert Max(params Vert[] vals) =>
Float3.Max(ToFloat3Array(vals));
public static Vert Min(params Vert[] vals) =>
Float3.Min(ToFloat3Array(vals));
public static Vert Round(Vert val) =>
Float3.Round(val);
public static Float3[] ToFloat3Array(params Vert[] vals)
{
Float3[] floats = new Float3[vals.Length];
for (int i = 0; i < vals.Length; i++) floats[i] = vals[i].position;
return floats;
}
public static List<Float3> ToFloat3List(params Vert[] vals) => ToFloat3Array(vals).ToList();
public override bool Equals([NotNullWhen(true)] object? obj)
{
if (obj == null || obj.GetType() != typeof(Vert)) return base.Equals(obj);
return Equals((Vert)obj);
}
public bool Equals(Vert other) => position == other.position;
public override int GetHashCode() => position.GetHashCode();
public override string ToString() => position.ToString();
public object Clone() => new Vert(position);
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public IEnumerator<float> GetEnumerator() => position.GetEnumerator();
public float[] ToArray() => position.ToArray();
public Fill<float> ToFill()
{
Vert @this = this;
return i => @this[i];
}
public List<float> ToList() => position.ToList();
public Vector3d ToVector() => ((Float3)this).ToVector();
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, float b) => new(a.position * b);
public static Vert operator /(Vert a, Vert b) => new(a.position / b.position);
public static Vert operator /(Vert a, float 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(Float2 val) => new(val);
public static implicit operator Vert(Float3 val) => new(val);
public static explicit operator Vert(Float4 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<float> fill) => new(fill);
public static implicit operator Vert(Fill<int> fill) => new(fill);
}

View File

@ -206,7 +206,6 @@ public record struct Int2 : IAbsolute<Int2>, IAverage<Int2>, IClamp<Int2>, IClam
public static explicit operator Int2(Vector2d val) => (Int2)val.ToXYZ(); public static explicit operator Int2(Vector2d val) => (Int2)val.ToXYZ();
public static explicit operator Int2(Int3 val) => new(val.x, 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(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<int> fill) => new(fill); public static implicit operator Int2(Fill<int> fill) => new(fill);
public static implicit operator Int2((int x, int y) val) => new(val.x, val.y); public static implicit operator Int2((int x, int y) val) => new(val.x, val.y);
} }

View File

@ -256,8 +256,6 @@ public record struct Int3 : IAbsolute<Int3>, IAverage<Int3>, IClamp<Int3>, IClam
public static explicit operator Int3(Int4 val) => new(val.x, val.y, val.z); public static explicit operator Int3(Int4 val) => new(val.x, val.y, val.z);
public static explicit operator Int3(Matrix m) => new((int)m[0, 0], (int)m[1, 0], (int)m[2, 0]); public static explicit operator Int3(Matrix m) => new((int)m[0, 0], (int)m[1, 0], (int)m[2, 0]);
public static explicit operator Int3(Vector2d val) => (Int3)val.ToXYZ(); public static explicit operator Int3(Vector2d val) => (Int3)val.ToXYZ();
public static explicit operator Int3(Vert val) => new((int)val.position.x, (int)val.position.y,
(int)val.position.z);
public static explicit operator Int3(RGBA val) => (Int3)val.ToRGBAByte(); public static explicit operator Int3(RGBA val) => (Int3)val.ToRGBAByte();
public static explicit operator Int3(HSVA val) => (Int3)val.ToHSVAByte(); public static explicit operator Int3(HSVA val) => (Int3)val.ToHSVAByte();
public static explicit operator Int3(RGBAByte val) => new(val.R, val.G, val.B); public static explicit operator Int3(RGBAByte val) => new(val.R, val.G, val.B);

View File

@ -330,8 +330,6 @@ public record struct Int4 : IAbsolute<Int4>, IAverage<Int4>, IClamp<Int4>, IClam
public static implicit operator Int4(Int3 val) => new(val.x, val.y, val.z, 0); public static implicit operator Int4(Int3 val) => new(val.x, val.y, val.z, 0);
public static explicit operator Int4(Matrix m) => new((int)m[0, 0], (int)m[1, 0], (int)m[2, 0], (int)m[3, 0]); public static explicit operator Int4(Matrix m) => new((int)m[0, 0], (int)m[1, 0], (int)m[2, 0], (int)m[3, 0]);
public static explicit operator Int4(Vector2d val) => (Int4)val.ToXYZ(); public static explicit operator Int4(Vector2d val) => (Int4)val.ToXYZ();
public static explicit operator Int4(Vert val) => new((int)val.position.x, (int)val.position.y,
(int)val.position.z, 0);
public static explicit operator Int4(RGBA val) => val.ToRGBAByte(); public static explicit operator Int4(RGBA val) => val.ToRGBAByte();
public static explicit operator Int4(CMYKA val) => (Int4)val.ToCMYKAByte(); public static explicit operator Int4(CMYKA val) => (Int4)val.ToCMYKAByte();
public static explicit operator Int4(HSVA val) => val.ToHSVAByte(); public static explicit operator Int4(HSVA val) => val.ToHSVAByte();

View File

@ -202,7 +202,6 @@ public record struct Complex(float u, float i) : IAbsolute<Complex>, IAverage<Co
public static explicit operator Complex(Int4 val) => new(val.x, val.y); public static explicit operator Complex(Int4 val) => new(val.x, val.y);
public static explicit operator Complex(Matrix m) => new(m[0, 0], m[1, 0]); public static explicit operator Complex(Matrix m) => new(m[0, 0], m[1, 0]);
public static explicit operator Complex(Vector2d val) => val.ToXYZ(); public static explicit operator Complex(Vector2d val) => val.ToXYZ();
public static explicit operator Complex(Vert val) => new(val.position.x, val.position.y);
public static implicit operator Complex(Fill<float> fill) => new(fill); public static implicit operator Complex(Fill<float> fill) => new(fill);
public static implicit operator Complex(Fill<int> fill) => new(fill); public static implicit operator Complex(Fill<int> fill) => new(fill);
public static implicit operator Complex((float u, float i) val) => new(val.u, val.i); public static implicit operator Complex((float u, float i) val) => new(val.u, val.i);

View File

@ -329,7 +329,6 @@ public record struct Quaternion(float u, float i, float j, float k) : IAbsolute<
public static implicit operator Quaternion(Float4 val) => new(val.x, val.y, val.z, val.w); public static implicit operator Quaternion(Float4 val) => new(val.x, val.y, val.z, val.w);
public static explicit operator Quaternion(Matrix m) => new(m[0, 0], m[1, 0], m[2, 0], m[3, 0]); public static explicit operator Quaternion(Matrix m) => new(m[0, 0], m[1, 0], m[2, 0], m[3, 0]);
public static explicit operator Quaternion(Vector2d val) => (Quaternion)val.ToXYZ(); public static explicit operator Quaternion(Vector2d val) => (Quaternion)val.ToXYZ();
public static implicit operator Quaternion(Vert val) => new(val);
public static implicit operator Quaternion(Fill<float> fill) => new(fill); public static implicit operator Quaternion(Fill<float> fill) => new(fill);
public static implicit operator Quaternion(Fill<int> fill) => new(fill); public static implicit operator Quaternion(Fill<int> fill) => new(fill);
public static implicit operator Quaternion((float u, float i, float j, float k) val) => public static implicit operator Quaternion((float u, float i, float j, float k) val) =>

View File

@ -11,7 +11,7 @@
Nerd_STF is a multi-purpose .NET 7.0 library that contains many objects I feel would help the default C# library package. Feel free to do with it what you'd like. Nerd_STF is a multi-purpose .NET 7.0 library that contains many objects I feel would help the default C# library package. Feel free to do with it what you'd like.
Nerd_STF includes some math as well as many other computer science topics. It contains types like groups of floats/ints, geometry types like `Vert`, `Line`, and `Triangle`, and color types like `RGBA`, `CMYKA`, `HSVA`, and their byte equivalents, all of which can convert seamlessly between each other. Nerd_STF includes some math as well as many other computer science topics. It contains types like groups of floats/ints, geometry types like `Line` and `Triangle`, and color types like `RGBA`, `CMYKA`, `HSVA`, and their byte equivalents, all of which can convert seamlessly between each other.
## What about Nerd_STF Versions `2021`? ## 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<T>` class there before I knew of the `System.Collections.Generic.List<T>` class that did literally everything for me already. Oh well. So, keep that in mind when you check out those versions of the library. 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<T>` class there before I knew of the `System.Collections.Generic.List<T>` class that did literally everything for me already. Oh well. So, keep that in mind when you check out those versions of the library.