Partial commit. Code is finished btu I need to complete the changelog.
This commit is contained in:
parent
4093fd6538
commit
1517f317e7
@ -10,6 +10,10 @@ Here's the full changelog:
|
||||
* UnsafeHelper
|
||||
+ Q_rsqrt
|
||||
* Mathematics
|
||||
* Geometry
|
||||
- Vert
|
||||
* Float2
|
||||
- operator Float2(Vert)
|
||||
* Mathf
|
||||
= Modified `InverseSqrt(float)` to use the faster unsafe inverse square root method.
|
||||
```
|
||||
|
||||
@ -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(Int3 val) => (Vector2d)val.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 implicit operator Vector2d((Angle angle, float mag) val) => new(val.angle, val.mag);
|
||||
}
|
||||
|
||||
@ -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(Int3 val) => val.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((Angle yaw, Angle pitch, float mag) val) =>
|
||||
new(val.yaw, val.pitch, val.mag);
|
||||
|
||||
@ -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(Matrix m) => new(m[0, 0], m[1, 0]);
|
||||
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<int> fill) => new(fill);
|
||||
public static implicit operator Float2((float x, float y) val) => new(val.x, val.y);
|
||||
|
||||
@ -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(Matrix m) => new(m[0, 0], m[1, 0], m[2, 0]);
|
||||
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(HSVA val) => new(val.H.Normalized, val.S, val.V);
|
||||
public static explicit operator Float3(RGBAByte val) => (Float3)val.ToRGBA();
|
||||
|
||||
@ -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 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 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 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);
|
||||
|
||||
@ -1,38 +1,38 @@
|
||||
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>,
|
||||
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);
|
||||
set
|
||||
{
|
||||
Vert diff = center - value;
|
||||
size = (Float2)diff.position * 2f;
|
||||
Float3 diff = center - value;
|
||||
size = (Float2)diff * 2f;
|
||||
}
|
||||
}
|
||||
public Vert MinVert
|
||||
public Float3 MinFloat3
|
||||
{
|
||||
get => center - (size / 2);
|
||||
set
|
||||
{
|
||||
Vert diff = center + value;
|
||||
size = (Float2)diff.position * 2f;
|
||||
Float3 diff = center + value;
|
||||
size = (Float2)diff * 2f;
|
||||
}
|
||||
}
|
||||
|
||||
public float Area => size.x * size.y;
|
||||
public float Perimeter => 2 * (size.x + size.y);
|
||||
|
||||
public Vert center;
|
||||
public Float3 center;
|
||||
public Float2 size;
|
||||
|
||||
public Box2d(Vert min, Vert max) : this(Vert.Average(min, max), (Float2)(min - max)) { }
|
||||
public Box2d(Vert center, Float2 size)
|
||||
public Box2d(Float3 min, Float3 max) : this(Float3.Average(min, max), (Float2)(min - max)) { }
|
||||
public Box2d(Float3 center, Float2 size)
|
||||
{
|
||||
this.center = center;
|
||||
this.size = size;
|
||||
@ -45,28 +45,28 @@ public record class Box2d : IAbsolute<Box2d>, IAverage<Box2d>, ICeiling<Box2d>,
|
||||
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)
|
||||
{
|
||||
(Vert[] centers, Float2[] sizes) = SplitArray(vals);
|
||||
return new(Vert.Average(centers), Float2.Average(sizes));
|
||||
(Float3[] centers, Float2[] sizes) = SplitArray(vals);
|
||||
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) =>
|
||||
new(Vert.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));
|
||||
new(Float3.Clamp(val.center, min.center, max.center), Float2.Clamp(val.size, min.size, max.size));
|
||||
public static Box2d Floor(Box2d val) => new(Float3.Floor(val.center), Float2.Floor(val.size));
|
||||
public static Box2d Lerp(Box2d a, Box2d b, float t, bool clamp = true) =>
|
||||
new(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)
|
||||
{
|
||||
(Vert[] verts, Float2[] sizes) = SplitArray(vals);
|
||||
return new(Vert.Median(verts), Float2.Median(sizes));
|
||||
(Float3[] verts, Float2[] sizes) = SplitArray(vals);
|
||||
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];
|
||||
|
||||
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 bool Contains(Vert vert)
|
||||
public bool Contains(Float3 vert)
|
||||
{
|
||||
Float2 diff = Float2.Absolute((Float2)(center - vert));
|
||||
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)
|
||||
{
|
||||
builder.Append("Min = ");
|
||||
builder.Append(MinVert);
|
||||
builder.Append(MinFloat3);
|
||||
builder.Append(", Max = ");
|
||||
builder.Append(MaxVert);
|
||||
builder.Append(MaxFloat3);
|
||||
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 b) => new(-b.MaxVert, -b.MinVert);
|
||||
public static Box2d operator -(Box2d a, Vert b) => new(a.center - b, a.size);
|
||||
public static Box2d operator -(Box2d b) => new(-b.MaxFloat3, -b.MinFloat3);
|
||||
public static Box2d operator -(Box2d a, Float3 b) => new(a.center - b, a.size);
|
||||
public static Box2d operator -(Box2d a, Float2 b) => new(a.center, a.size - b);
|
||||
public static Box2d operator *(Box2d a, float b) => new(a.center * b, a.size * b);
|
||||
public static Box2d operator *(Box2d a, Float2 b) => new(a.center, a.size * b);
|
||||
|
||||
@ -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>,
|
||||
IContains<Vert>, IEquatable<Box3d>, IFloor<Box3d>, ILerp<Box3d, float>, IMedian<Box3d>,
|
||||
IRound<Box3d>, IShape3d<float>, ISplittable<Box3d, (Vert[] centers, Float3[] sizes)>
|
||||
IContains<Float3>, IEquatable<Box3d>, IFloor<Box3d>, ILerp<Box3d, float>, IMedian<Box3d>,
|
||||
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
|
||||
{
|
||||
Vert diff = center - value;
|
||||
size = diff.position * 2;
|
||||
Float3 diff = center - value;
|
||||
size = diff * 2;
|
||||
}
|
||||
}
|
||||
public Vert MinVert
|
||||
public Float3 MinFloat3
|
||||
{
|
||||
get => center - (Vert)(size / 2);
|
||||
get => center - (size / 2);
|
||||
set
|
||||
{
|
||||
Vert diff = center + value;
|
||||
size = diff.position * 2;
|
||||
Float3 diff = center + value;
|
||||
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 Volume => size.x * size.y * size.z;
|
||||
|
||||
public Vert center;
|
||||
public Float3 center;
|
||||
public Float3 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(Vert center, Float3 size)
|
||||
public Box3d(Float3 min, Float3 max)
|
||||
{
|
||||
this.center = center;
|
||||
this.size = size;
|
||||
this.center = Float3.Average(min, max);
|
||||
this.size = max - min;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
(Vert[] centers, Float3[] sizes) = SplitArray(vals);
|
||||
return new(Vert.Average(centers), Float3.Average(sizes));
|
||||
(Float3[] centers, Float3[] sizes) = SplitArray(vals);
|
||||
return new(Float3.Average(centers), Float3.Average(sizes));
|
||||
}
|
||||
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) =>
|
||||
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) =>
|
||||
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) =>
|
||||
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)
|
||||
{
|
||||
(Vert[] verts, Float3[] sizes) = SplitArray(vals);
|
||||
return new(Vert.Median(verts), Float3.Median(sizes));
|
||||
(Float3[] verts, Float3[] sizes) = SplitArray(vals);
|
||||
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];
|
||||
|
||||
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 bool Contains(Vert vert)
|
||||
public bool Contains(Float3 vert)
|
||||
{
|
||||
Float3 diff = Float3.Absolute(center - vert);
|
||||
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)
|
||||
{
|
||||
builder.Append("Min = ");
|
||||
builder.Append(MinVert);
|
||||
builder.Append(MinFloat3);
|
||||
builder.Append(", Max = ");
|
||||
builder.Append(MaxVert);
|
||||
builder.Append(MaxFloat3);
|
||||
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, a.size + b);
|
||||
public static Box3d operator -(Box3d b) => new(-b.MaxVert, -b.MinVert);
|
||||
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, Float3 b) => new(a.center + b, a.size);
|
||||
public static Box3d operator -(Box3d b) => new(-b.MaxFloat3, -b.MinFloat3);
|
||||
public static Box3d operator -(Box3d a, Float3 b) => new(a.center - b, a.size);
|
||||
public static Box3d operator *(Box3d a, float b) => new(a.center * b, a.size * b);
|
||||
public static Box3d operator *(Box3d a, Float3 b) => new(a.center, a.size * b);
|
||||
public static Box3d operator /(Box3d a, float b) => new(a.center / b, a.size / b);
|
||||
|
||||
@ -2,27 +2,27 @@
|
||||
|
||||
namespace Nerd_STF.Mathematics.Geometry;
|
||||
|
||||
public record class Line : IAbsolute<Line>, IAverage<Line>, ICeiling<Line>, IClamp<Line>, IClosestTo<Vert>,
|
||||
IComparable<Line>, IContains<Vert>, IEquatable<Line>, IFloor<Line>, IFromTuple<Line, (Vert start, Vert end)>,
|
||||
IGroup<Vert>, IIndexAll<Vert>, IIndexRangeAll<Vert>, ILerp<Line, float>, IMedian<Line>, IPresets3d<Line>,
|
||||
IRound<Line>, ISplittable<Line, (Vert[] starts, Vert[] ends)>, ISubdivide<Line[]>
|
||||
public record class Line : IAbsolute<Line>, IAverage<Line>, ICeiling<Line>, IClamp<Line>, IClosestTo<Float3>,
|
||||
IComparable<Line>, IContains<Float3>, IEquatable<Line>, IFloor<Line>, IFromTuple<Line, (Float3 start, Float3 end)>,
|
||||
IGroup<Float3>, IIndexAll<Float3>, IIndexRangeAll<Float3>, ILerp<Line, float>, IMedian<Line>, IPresets3d<Line>,
|
||||
IRound<Line>, ISplittable<Line, (Float3[] starts, Float3[] ends)>, ISubdivide<Line[]>
|
||||
{
|
||||
public static Line Back => new(Vert.Zero, Vert.Back);
|
||||
public static Line Down => new(Vert.Zero, Vert.Down);
|
||||
public static Line Forward => new(Vert.Zero, Vert.Forward);
|
||||
public static Line Left => new(Vert.Zero, Vert.Left);
|
||||
public static Line Right => new(Vert.Zero, Vert.Right);
|
||||
public static Line Up => new(Vert.Zero, Vert.Up);
|
||||
public static Line Back => new(Float3.Zero, Float3.Back);
|
||||
public static Line Down => new(Float3.Zero, Float3.Down);
|
||||
public static Line Forward => new(Float3.Zero, Float3.Forward);
|
||||
public static Line Left => new(Float3.Zero, Float3.Left);
|
||||
public static Line Right => new(Float3.Zero, Float3.Right);
|
||||
public static Line Up => new(Float3.Zero, Float3.Up);
|
||||
|
||||
public static Line One => new(Vert.Zero, Vert.One);
|
||||
public static Line Zero => new(Vert.Zero, Vert.Zero);
|
||||
public static Line One => new(Float3.Zero, Float3.One);
|
||||
public static Line Zero => new(Float3.Zero, Float3.Zero);
|
||||
|
||||
public float Length => (b - a).Magnitude;
|
||||
public 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.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 z1, float x2, float y2, float 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(new(fill(0)), new(fill(1))) { }
|
||||
public Line(Fill<Int3> fill) : this(new(fill(0)), new(fill(1))) { }
|
||||
public Line(Fill<Float3> fill) : this(fill(0), fill(1)) { }
|
||||
public Line(Fill<Int3> fill) : this(fill(0), 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<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
|
||||
{
|
||||
@ -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];
|
||||
set => this[index.IsFromEnd ? 2 - index.Value : index.Value] = value;
|
||||
}
|
||||
public Vert[] this[Range range]
|
||||
public Float3[] this[Range range]
|
||||
{
|
||||
get
|
||||
{
|
||||
int start = range.Start.IsFromEnd ? 2 - range.Start.Value : range.Start.Value;
|
||||
int end = range.End.IsFromEnd ? 2 - range.End.Value : range.End.Value;
|
||||
List<Vert> res = new();
|
||||
List<Float3> res = new();
|
||||
for (int i = start; i < end; i++) res.Add(this[i]);
|
||||
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)
|
||||
{
|
||||
(Vert[] starts, Vert[] ends) = SplitArray(vals);
|
||||
return new(Vert.Average(starts), Vert.Average(ends));
|
||||
(Float3[] starts, Float3[] ends) = SplitArray(vals);
|
||||
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) =>
|
||||
new(Vert.Clamp(val.a, min.a, max.a), Vert.Clamp(val.b, min.b, max.b));
|
||||
public static Line Floor(Line val) => new(Vert.Floor(val.a), Vert.Floor(val.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(Float3.Floor(val.a), Float3.Floor(val.b));
|
||||
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)
|
||||
{
|
||||
(Vert[] starts, Vert[] ends) = SplitArray(vals);
|
||||
return new(Vert.Median(starts), Vert.Median(ends));
|
||||
(Float3[] starts, Float3[] ends) = SplitArray(vals);
|
||||
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++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
public bool Contains(Vert vert)
|
||||
public bool Contains(Float3 vert)
|
||||
{
|
||||
Float3 diffA = a - vert, diffB = a - b;
|
||||
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 Vert ClosestTo(Vert vert, float step)
|
||||
public Float3 ClosestTo(Float3 vert) => ClosestTo(vert, Calculus.DefaultStep);
|
||||
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)
|
||||
{
|
||||
Vert valA = Vert.Lerp(a, b, t);
|
||||
Vert valB = Vert.Lerp(b, a, t);
|
||||
Float3 valA = Float3.Lerp(a, b, t);
|
||||
Float3 valB = Float3.Lerp(b, a, t);
|
||||
closestA = (valA - vert).Magnitude < (closestA - vert).Magnitude ? valA : closestA;
|
||||
closestB = (valB - vert).Magnitude < (closestB - vert).Magnitude ? valB : closestB;
|
||||
}
|
||||
@ -151,7 +150,7 @@ public record class Line : IAbsolute<Line>, IAverage<Line>, ICeiling<Line>, ICla
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
public IEnumerator<Vert> GetEnumerator()
|
||||
public IEnumerator<Float3> GetEnumerator()
|
||||
{
|
||||
yield return a;
|
||||
yield return b;
|
||||
@ -159,7 +158,7 @@ public record class Line : IAbsolute<Line>, IAverage<Line>, ICeiling<Line>, ICla
|
||||
|
||||
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) };
|
||||
}
|
||||
public Line[] Subdivide(int iterations)
|
||||
@ -175,18 +174,18 @@ public record class Line : IAbsolute<Line>, IAverage<Line>, ICeiling<Line>, ICla
|
||||
return lines.ToArray();
|
||||
}
|
||||
|
||||
public Vert[] ToArray() => new Vert[] { a, b };
|
||||
public Fill<Vert> ToFill()
|
||||
public Float3[] ToArray() => new Float3[] { a, b };
|
||||
public Fill<Float3> ToFill()
|
||||
{
|
||||
Line @this = this;
|
||||
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,
|
||||
b.position.x, b.position.y, b.position.z };
|
||||
public List<float> ToFloatList() => new() { a.position.x, a.position.y, a.position.z,
|
||||
b.position.x, b.position.y, b.position.z };
|
||||
public float[] ToFloatArray() => new float[] { a.x, a.y, a.z,
|
||||
b.x, b.y, b.z };
|
||||
public List<float> ToFloatList() => new() { a.x, a.y, a.z,
|
||||
b.x, b.y, b.z };
|
||||
|
||||
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, 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 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, 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, 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);
|
||||
[Obsolete("This operator is a bit ambiguous. You should instead compare " +
|
||||
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.")]
|
||||
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<Int3> 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((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);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
namespace Nerd_STF.Mathematics.Geometry;
|
||||
|
||||
[Obsolete("This struct is a garbage fire. This will be completely redesigned in v2.5.0")]
|
||||
public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivide<Polygon>, ITriangulate
|
||||
public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Float3>, ISubdivide<Polygon>, ITriangulate
|
||||
{
|
||||
public Line[] Lines
|
||||
{
|
||||
@ -9,11 +9,11 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
|
||||
set
|
||||
{
|
||||
p_lines = value;
|
||||
p_verts = GenerateVerts(value);
|
||||
p_verts = GenerateFloat3s(value);
|
||||
}
|
||||
}
|
||||
public Vert Midpoint => Vert.Average(Verts);
|
||||
public Vert[] Verts
|
||||
public Float3 Midpoint => Float3.Average(Float3s);
|
||||
public Float3[] Float3s
|
||||
{
|
||||
get => p_verts;
|
||||
set
|
||||
@ -24,7 +24,7 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
|
||||
}
|
||||
|
||||
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 " +
|
||||
"future update.")]
|
||||
@ -50,27 +50,15 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
|
||||
public Polygon()
|
||||
{
|
||||
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)
|
||||
{
|
||||
List<Vert> verts = new();
|
||||
List<Float3> verts = new();
|
||||
int i = 0;
|
||||
while (true)
|
||||
{
|
||||
Vert? v = fill(i);
|
||||
Float3? v = fill(i);
|
||||
if (!v.HasValue) break;
|
||||
verts.Add(v.Value);
|
||||
}
|
||||
@ -88,15 +76,9 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
|
||||
}
|
||||
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)
|
||||
{
|
||||
List<Vert> verts = new();
|
||||
List<Float3> verts = new();
|
||||
for (int i = 0; i < length; i++) verts.Add(fill(i));
|
||||
this = new(verts.ToArray());
|
||||
}
|
||||
@ -108,30 +90,25 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
|
||||
}
|
||||
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];
|
||||
p_lines = GenerateLines(p_verts);
|
||||
}
|
||||
public Polygon(params Vert[] verts)
|
||||
{
|
||||
p_verts = verts;
|
||||
p_lines = GenerateLines(verts);
|
||||
}
|
||||
public Polygon(params Line[] 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];
|
||||
set => Verts[index] = value;
|
||||
get => Float3s[index];
|
||||
set => Float3s[index] = value;
|
||||
}
|
||||
|
||||
public static Polygon CreateCircle(int vertCount)
|
||||
{
|
||||
List<Vert> parts = new();
|
||||
List<Float3> parts = new();
|
||||
for (int i = 0; i < vertCount; i++)
|
||||
{
|
||||
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)
|
||||
{
|
||||
Vert[] v = val.Verts;
|
||||
for (int i = 0; i < v.Length; i++) v[i] = Vert.Absolute(v[i]);
|
||||
Float3[] v = val.Float3s;
|
||||
for (int i = 0; i < v.Length; i++) v[i] = Float3.Absolute(v[i]);
|
||||
return new(v);
|
||||
}
|
||||
public static Polygon Average(params Polygon[] vals)
|
||||
{
|
||||
if (!CheckVerts(vals)) throw new DifferingVertCountException(nameof(vals), vals);
|
||||
if (!CheckFloat3s(vals)) throw new DifferingVertCountException(nameof(vals), vals);
|
||||
if (vals.Length < 1) return default;
|
||||
|
||||
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)
|
||||
{
|
||||
Vert[] v = val.Verts;
|
||||
for (int i = 0; i < v.Length; i++) v[i] = Vert.Ceiling(v[i]);
|
||||
Float3[] v = val.Float3s;
|
||||
for (int i = 0; i < v.Length; i++) v[i] = Float3.Ceiling(v[i]);
|
||||
return new(v);
|
||||
}
|
||||
public static Polygon Clamp(Polygon val, Polygon min, Polygon max)
|
||||
{
|
||||
if (!CheckVerts(val, min, max)) throw new DifferingVertCountException(val, min, max);
|
||||
if (!CheckFloat3s(val, min, max)) throw new DifferingVertCountException(val, min, max);
|
||||
Line[][] lines = new Line[3][] { val.Lines, min.Lines, max.Lines };
|
||||
Line[] res = new Line[val.Lines.Length];
|
||||
for (int i = 0; i < res.Length; i++) res[i] = Line.Clamp(lines[0][i], lines[1][i], lines[2][i]);
|
||||
@ -180,13 +157,13 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
|
||||
}
|
||||
public static Polygon Floor(Polygon val)
|
||||
{
|
||||
Vert[] v = val.Verts;
|
||||
for (int i = 0; i < v.Length; i++) v[i] = Vert.Floor(v[i]);
|
||||
Float3[] v = val.Float3s;
|
||||
for (int i = 0; i < v.Length; i++) v[i] = Float3.Floor(v[i]);
|
||||
return new(v);
|
||||
}
|
||||
public static Polygon Lerp(Polygon a, Polygon b, float t, bool clamp = true)
|
||||
{
|
||||
if (!CheckVerts(a, b)) throw new DifferingVertCountException(a, b);
|
||||
if (!CheckFloat3s(a, b)) throw new DifferingVertCountException(a, b);
|
||||
Line[][] lines = new Line[2][] { a.Lines, b.Lines };
|
||||
Line[] res = new Line[a.Lines.Length];
|
||||
for (int i = 0; i < res.Length; i++) res[i] = Line.Lerp(lines[0][i], lines[1][i], t, clamp);
|
||||
@ -194,7 +171,7 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
|
||||
}
|
||||
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;
|
||||
|
||||
Line[][] lines = new Line[vals.Length][];
|
||||
@ -226,7 +203,7 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
|
||||
}
|
||||
public bool Equals(Polygon other)
|
||||
{
|
||||
if (!CheckVerts(this, other)) return false;
|
||||
if (!CheckFloat3s(this, other)) return false;
|
||||
return Lines == other.Lines;
|
||||
}
|
||||
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);
|
||||
|
||||
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 Fill<Vert> ToFill()
|
||||
public Float3[] ToArray() => Float3s;
|
||||
public Fill<Float3> ToFill()
|
||||
{
|
||||
Polygon @this = this;
|
||||
return i => @this[i];
|
||||
}
|
||||
public List<Vert> ToList() => new(Verts);
|
||||
public List<Float3> ToList() => new(Float3s);
|
||||
|
||||
public float[] ToFloatArray()
|
||||
{
|
||||
float[] vals = new float[Verts.Length * 3];
|
||||
for (int i = 0; i < Verts.Length; i++)
|
||||
float[] vals = new float[Float3s.Length * 3];
|
||||
for (int i = 0; i < Float3s.Length; i++)
|
||||
{
|
||||
int pos = i * 3;
|
||||
vals[pos + 0] = Verts[i].position.x;
|
||||
vals[pos + 1] = Verts[i].position.y;
|
||||
vals[pos + 2] = Verts[i].position.z;
|
||||
vals[pos + 0] = Float3s[i].x;
|
||||
vals[pos + 1] = Float3s[i].y;
|
||||
vals[pos + 2] = Float3s[i].z;
|
||||
}
|
||||
return vals;
|
||||
}
|
||||
@ -282,32 +259,32 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
|
||||
public Polygon SubdivideCatmullClark(int segments)
|
||||
{
|
||||
// Thanks Saalty for making this accidentally.
|
||||
List<Vert> newVerts = new();
|
||||
for (int i = 0; i < Verts.Length; i++)
|
||||
List<Float3> newFloat3s = new();
|
||||
for (int i = 0; i < Float3s.Length; i++)
|
||||
{
|
||||
for (int factor = 0; factor < segments; factor++)
|
||||
{
|
||||
float unit = factor / (float)(segments * 2), unit2 = unit + 0.5f, lastUnit = unit * 2;
|
||||
Vert p1, p2;
|
||||
if (i == Verts.Length - 1)
|
||||
Float3 p1, p2;
|
||||
if (i == Float3s.Length - 1)
|
||||
{
|
||||
p1 = Verts[^1] + (Verts[0] - Verts[^1]) * unit2;
|
||||
p2 = Verts[0] + (Verts[1] - Verts[0]) * unit;
|
||||
p1 = Float3s[^1] + (Float3s[0] - Float3s[^1]) * unit2;
|
||||
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;
|
||||
p2 = Verts[^1] + (Verts[0] - Verts[^1]) * unit;
|
||||
p1 = Float3s[^2] + (Float3s[^1] - Float3s[^2]) * unit2;
|
||||
p2 = Float3s[^1] + (Float3s[0] - Float3s[^1]) * unit;
|
||||
}
|
||||
else
|
||||
{
|
||||
p1 = Verts[i] + (Verts[i + 1] - Verts[i]) * unit2;
|
||||
p2 = Verts[i + 1] + (Verts[i + 2] - Verts[i + 1]) * unit;
|
||||
p1 = Float3s[i] + (Float3s[i + 1] - Float3s[i]) * unit2;
|
||||
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. " +
|
||||
@ -317,15 +294,15 @@ public struct Polygon : ICloneable, IEquatable<Polygon>, IGroup<Vert>, ISubdivid
|
||||
// This may cause issues. FIXME
|
||||
// Tbh, not even sure if this works. This was a bit confusing.
|
||||
|
||||
if (Verts.Length == 3) return new Triangle[] { new(Verts[0], Verts[1], Verts[2]) };
|
||||
if (Float3s.Length == 3) return new Triangle[] { new(Float3s[0], Float3s[1], Float3s[2]) };
|
||||
|
||||
(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;
|
||||
Line l = new(Verts[i], Verts[j]);
|
||||
Line l = new(Float3s[i], Float3s[j]);
|
||||
if (Lines.Contains(l)) continue;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
private static bool CheckVerts(params Polygon[] polys)
|
||||
private static bool CheckFloat3s(params Polygon[] polys)
|
||||
{
|
||||
int len = -1;
|
||||
foreach (Polygon poly in polys)
|
||||
{
|
||||
if (len == -1)
|
||||
{
|
||||
len = poly.Verts.Length;
|
||||
len = poly.Float3s.Length;
|
||||
continue;
|
||||
}
|
||||
if (poly.Verts.Length != len) return false;
|
||||
if (poly.Float3s.Length != len) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private static Line[] GenerateLines(Vert[] verts)
|
||||
private static Line[] GenerateLines(Float3[] verts)
|
||||
{
|
||||
Line[] lines = new Line[verts.Length];
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
lines[i] = new(verts[i], verts[i == lines.Length - 1 ? 0 : i + 1]);
|
||||
return lines;
|
||||
}
|
||||
private static 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++)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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[] res = new Line[a.Lines.Length];
|
||||
for (int i = 0; i < res.Length; i++) res[i] = lines[0][i] + lines[1][i];
|
||||
return new(res);
|
||||
}
|
||||
public static Polygon operator +(Polygon a, Vert b)
|
||||
public static Polygon operator +(Polygon a, Float3 b)
|
||||
{
|
||||
Line[] lines = a.Lines;
|
||||
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)
|
||||
{
|
||||
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[] res = new Line[a.Lines.Length];
|
||||
for (int i = 0; i < res.Length; i++) res[i] = lines[0][i] - lines[1][i];
|
||||
return new(res);
|
||||
}
|
||||
public static Polygon operator -(Polygon a, Vert b)
|
||||
public static Polygon operator -(Polygon a, Float3 b)
|
||||
{
|
||||
Line[] lines = a.Lines;
|
||||
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)
|
||||
{
|
||||
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[] res = new Line[a.Lines.Length];
|
||||
for (int i = 0; i < res.Length; i++) res[i] = lines[0][i] * lines[1][i];
|
||||
return new(res);
|
||||
}
|
||||
public static Polygon operator *(Polygon a, Vert b)
|
||||
public static Polygon operator *(Polygon a, Float3 b)
|
||||
{
|
||||
Line[] lines = a.Lines;
|
||||
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)
|
||||
{
|
||||
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[] res = new Line[a.Lines.Length];
|
||||
for (int i = 0; i < res.Length; i++) res[i] = lines[0][i] / lines[1][i];
|
||||
return new(res);
|
||||
}
|
||||
public static Polygon operator /(Polygon a, Vert b)
|
||||
public static Polygon operator /(Polygon a, Float3 b)
|
||||
{
|
||||
Line[] lines = a.Lines;
|
||||
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 implicit operator Polygon(Fill<Vert?> 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(Vert[] 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(Triangle tri) => new(tri.AB, tri.BC, tri.CA);
|
||||
|
||||
@ -2,10 +2,10 @@
|
||||
|
||||
public record class Quadrilateral : IAbsolute<Quadrilateral>, IAverage<Quadrilateral>, ICeiling<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
|
||||
{
|
||||
public Vert A
|
||||
public Float3 A
|
||||
{
|
||||
get => p_a;
|
||||
set
|
||||
@ -15,7 +15,7 @@ public record class Quadrilateral : IAbsolute<Quadrilateral>, IAverage<Quadrilat
|
||||
p_da.b = value;
|
||||
}
|
||||
}
|
||||
public Vert B
|
||||
public Float3 B
|
||||
{
|
||||
get => p_b;
|
||||
set
|
||||
@ -25,7 +25,7 @@ public record class Quadrilateral : IAbsolute<Quadrilateral>, IAverage<Quadrilat
|
||||
p_bc.a = value;
|
||||
}
|
||||
}
|
||||
public Vert C
|
||||
public Float3 C
|
||||
{
|
||||
get => p_c;
|
||||
set
|
||||
@ -35,7 +35,7 @@ public record class Quadrilateral : IAbsolute<Quadrilateral>, IAverage<Quadrilat
|
||||
p_cd.a = value;
|
||||
}
|
||||
}
|
||||
public Vert D
|
||||
public Float3 D
|
||||
{
|
||||
get => p_d;
|
||||
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;
|
||||
|
||||
[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;
|
||||
}
|
||||
}
|
||||
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 Quadrilateral(Vert a, Vert b, Vert c, Vert d)
|
||||
public Quadrilateral(Float3 a, Float3 b, Float3 c, Float3 d)
|
||||
{
|
||||
p_a = a;
|
||||
p_b = b;
|
||||
@ -135,20 +135,19 @@ public record class Quadrilateral : IAbsolute<Quadrilateral>, IAverage<Quadrilat
|
||||
p_da = da;
|
||||
}
|
||||
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,
|
||||
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<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<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)) { }
|
||||
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)) { }
|
||||
|
||||
public Vert this[int index]
|
||||
public Float3 this[int index]
|
||||
{
|
||||
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];
|
||||
set => this[index.IsFromEnd ? 4 - index.Value : index.Value] = value;
|
||||
}
|
||||
public Vert[] this[Range range]
|
||||
public Float3[] this[Range range]
|
||||
{
|
||||
get
|
||||
{
|
||||
int start = range.Start.IsFromEnd ? 4 - range.Start.Value : range.Start.Value;
|
||||
int end = range.End.IsFromEnd ? 4 - range.End.Value : range.End.Value;
|
||||
List<Vert> res = new();
|
||||
List<Float3> res = new();
|
||||
for (int i = start; i < end; i++) res.Add(this[i]);
|
||||
return res.ToArray();
|
||||
}
|
||||
@ -206,44 +205,44 @@ public record class Quadrilateral : IAbsolute<Quadrilateral>, IAverage<Quadrilat
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
(Vert[] As, Vert[] Bs, Vert[] Cs, Vert[] Ds) = SplitVertArray(vals);
|
||||
return new(Vert.Average(As), Vert.Average(Bs), Vert.Average(Cs), Vert.Average(Ds));
|
||||
(Float3[] As, Float3[] Bs, Float3[] Cs, Float3[] Ds) = SplitFloat3Array(vals);
|
||||
return new(Float3.Average(As), Float3.Average(Bs), Float3.Average(Cs), Float3.Average(Ds));
|
||||
}
|
||||
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) =>
|
||||
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),
|
||||
Vert.Clamp(val.D, min.D, max.D));
|
||||
new(Float3.Clamp(val.A, min.A, max.A), Float3.Clamp(val.B, min.B, max.B), Float3.Clamp(val.C, min.C, max.C),
|
||||
Float3.Clamp(val.D, min.D, max.D));
|
||||
public static Quadrilateral Floor(Quadrilateral val) =>
|
||||
new(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) =>
|
||||
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),
|
||||
Vert.Lerp(a.D, b.D, 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),
|
||||
Float3.Lerp(a.D, b.D, t, clamp));
|
||||
public static Quadrilateral Max(params Quadrilateral[] vals)
|
||||
{
|
||||
(Vert[] As, Vert[] Bs, Vert[] Cs, Vert[] Ds) = SplitVertArray(vals);
|
||||
return new(Vert.Max(As), Vert.Max(Bs), Vert.Max(Cs), Vert.Max(Ds));
|
||||
(Float3[] As, Float3[] Bs, Float3[] Cs, Float3[] Ds) = SplitFloat3Array(vals);
|
||||
return new(Float3.Max(As), Float3.Max(Bs), Float3.Max(Cs), Float3.Max(Ds));
|
||||
}
|
||||
public static Quadrilateral Median(params Quadrilateral[] vals)
|
||||
{
|
||||
(Vert[] As, Vert[] Bs, Vert[] Cs, Vert[] Ds) = SplitVertArray(vals);
|
||||
return new(Vert.Median(As), Vert.Median(Bs), Vert.Median(Cs), Vert.Median(Ds));
|
||||
(Float3[] As, Float3[] Bs, Float3[] Cs, Float3[] Ds) = SplitFloat3Array(vals);
|
||||
return new(Float3.Median(As), Float3.Median(Bs), Float3.Median(Cs), Float3.Median(Ds));
|
||||
}
|
||||
public static Quadrilateral Min(params Quadrilateral[] vals)
|
||||
{
|
||||
(Vert[] As, Vert[] Bs, Vert[] Cs, Vert[] Ds) = SplitVertArray(vals);
|
||||
return new(Vert.Min(As), Vert.Min(Bs), Vert.Min(Cs), Vert.Min(Ds));
|
||||
(Float3[] As, Float3[] Bs, Float3[] Cs, Float3[] Ds) = SplitFloat3Array(vals);
|
||||
return new(Float3.Min(As), Float3.Min(Bs), Float3.Min(Cs), Float3.Min(Ds));
|
||||
}
|
||||
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],
|
||||
c = new Vert[quads.Length], d = new Vert[quads.Length];
|
||||
Float3[] a = new Float3[quads.Length], b = new Float3[quads.Length],
|
||||
c = new Float3[quads.Length], d = new Float3[quads.Length];
|
||||
for (int i = 0; i < quads.Length; i++)
|
||||
{
|
||||
a[i] = quads[i].A;
|
||||
@ -275,18 +274,18 @@ public record class Quadrilateral : IAbsolute<Quadrilateral>, IAverage<Quadrilat
|
||||
for (int i = 0; i < quads.Length; i++)
|
||||
{
|
||||
int pos = i * 12;
|
||||
vals[pos + 0] = quads[i].A.position.x;
|
||||
vals[pos + 1] = quads[i].A.position.y;
|
||||
vals[pos + 2] = quads[i].A.position.z;
|
||||
vals[pos + 3] = quads[i].B.position.x;
|
||||
vals[pos + 4] = quads[i].B.position.y;
|
||||
vals[pos + 5] = quads[i].B.position.z;
|
||||
vals[pos + 6] = quads[i].C.position.x;
|
||||
vals[pos + 7] = quads[i].C.position.y;
|
||||
vals[pos + 8] = quads[i].C.position.z;
|
||||
vals[pos + 9] = quads[i].D.position.x;
|
||||
vals[pos + 10] = quads[i].D.position.y;
|
||||
vals[pos + 11] = quads[i].D.position.z;
|
||||
vals[pos + 0] = quads[i].A.x;
|
||||
vals[pos + 1] = quads[i].A.y;
|
||||
vals[pos + 2] = quads[i].A.z;
|
||||
vals[pos + 3] = quads[i].B.x;
|
||||
vals[pos + 4] = quads[i].B.y;
|
||||
vals[pos + 5] = quads[i].B.z;
|
||||
vals[pos + 6] = quads[i].C.x;
|
||||
vals[pos + 7] = quads[i].C.y;
|
||||
vals[pos + 8] = quads[i].C.z;
|
||||
vals[pos + 9] = quads[i].D.x;
|
||||
vals[pos + 10] = quads[i].D.y;
|
||||
vals[pos + 11] = quads[i].D.z;
|
||||
}
|
||||
return vals;
|
||||
}
|
||||
@ -300,7 +299,7 @@ public record class Quadrilateral : IAbsolute<Quadrilateral>, IAverage<Quadrilat
|
||||
public override int GetHashCode() => base.GetHashCode();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
public IEnumerator<Vert> GetEnumerator()
|
||||
public IEnumerator<Float3> GetEnumerator()
|
||||
{
|
||||
yield return A;
|
||||
yield return B;
|
||||
@ -308,22 +307,22 @@ public record class Quadrilateral : IAbsolute<Quadrilateral>, IAverage<Quadrilat
|
||||
yield return D;
|
||||
}
|
||||
|
||||
public Vert[] ToArray() => new Vert[] { A, B, C, D };
|
||||
public Fill<Vert> ToFill()
|
||||
public Float3[] ToArray() => new Float3[] { A, B, C, D };
|
||||
public Fill<Float3> ToFill()
|
||||
{
|
||||
Quadrilateral @this = this;
|
||||
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,
|
||||
B.position.x, B.position.y, B.position.z,
|
||||
C.position.x, C.position.y, C.position.z,
|
||||
D.position.x, D.position.y, D.position.z };
|
||||
public List<float> ToFloatList() => new() { A.position.x, A.position.y, A.position.z,
|
||||
B.position.x, B.position.y, B.position.z,
|
||||
C.position.x, C.position.y, C.position.z,
|
||||
D.position.x, D.position.y, D.position.z };
|
||||
public float[] ToFloatArray() => new float[] { A.x, A.y, A.z,
|
||||
B.x, B.y, B.z,
|
||||
C.x, C.y, C.z,
|
||||
D.x, D.y, D.z };
|
||||
public List<float> ToFloatList() => new() { A.x, A.y, A.z,
|
||||
B.x, B.y, B.z,
|
||||
C.x, C.y, C.z,
|
||||
D.x, D.y, D.z };
|
||||
|
||||
public Triangle[] Triangulate() => new Line(A, C).Length > new Line(B, D).Length ?
|
||||
new Triangle[] { new(A, B, C), new(C, D, A) } : new Triangle[] { new(B, C, D), new(D, A, B) };
|
||||
@ -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,
|
||||
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 a, Quadrilateral b) => new(a.A - b.A, a.B - b.B,
|
||||
a.C - b.C, a.D - b.D);
|
||||
public static Quadrilateral operator -(Quadrilateral a, 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,
|
||||
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, Quadrilateral b) => new(a.A / b.A, a.B / b.B,
|
||||
a.C / b.C, a.D / b.D);
|
||||
public static Quadrilateral operator /(Quadrilateral a, 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 implicit operator Quadrilateral(Fill<Vert> 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<Line> 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((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);
|
||||
}
|
||||
|
||||
@ -1,66 +1,66 @@
|
||||
namespace Nerd_STF.Mathematics.Geometry;
|
||||
|
||||
public record class Sphere : IAverage<Sphere>, ICeiling<Sphere>, IClamp<Sphere>, IClosestTo<Vert>,
|
||||
IComparable<Sphere>, IComparable<float>, IContains<Vert>, IEquatable<Sphere>, IEquatable<float>, IFloor<Sphere>,
|
||||
IFromTuple<Sphere, (Vert center, float radius)>, ILerp<Sphere, float>, IMax<Sphere>, IMedian<Sphere>,
|
||||
IMin<Sphere>, IRound<Sphere>, ISplittable<Sphere, (Vert[] centers, float[] radii)>
|
||||
public record class Sphere : IAverage<Sphere>, ICeiling<Sphere>, IClamp<Sphere>, IClosestTo<Float3>,
|
||||
IComparable<Sphere>, IComparable<float>, IContains<Float3>, IEquatable<Sphere>, IEquatable<float>, IFloor<Sphere>,
|
||||
IFromTuple<Sphere, (Float3 center, float radius)>, ILerp<Sphere, float>, IMax<Sphere>, IMedian<Sphere>,
|
||||
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 SurfaceArea => 4 * Constants.Pi * 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 FromRadius(Vert center, Vert radius) => new(center, (center - radius).Magnitude);
|
||||
public static Sphere FromDiameter(Float3 a, Float3 b) => new(Float3.Average(a, b), (a - b).Magnitude / 2);
|
||||
public static Sphere FromRadius(Float3 center, Float3 radius) => new(center, (center - radius).Magnitude);
|
||||
|
||||
public Sphere(Vert center, float radius)
|
||||
public Sphere(Float3 center, float radius)
|
||||
{
|
||||
this.center = center;
|
||||
this.radius = radius;
|
||||
}
|
||||
public Sphere(float cX, float cY, float radius) : this(new Vert(cX, cY), radius) { }
|
||||
public Sphere(float cX, float cY, float cZ, float radius) : this(new Vert(cX, cY, cZ), radius) { }
|
||||
public Sphere(Fill<float> fill, float radius) : this(new Vert(fill), radius) { }
|
||||
public Sphere(Fill<float> fill) : this(new Vert(fill), fill(3)) { }
|
||||
public Sphere(Fill<int> fill, float radius) : this(new Vert(fill), radius) { }
|
||||
public Sphere(Fill<int> fill) : this(new Vert(fill), fill(3)) { }
|
||||
public Sphere(Fill<Vert> fill, float radius) : this(fill(0), radius) { }
|
||||
public Sphere(Fill<Vert> fillA, Fill<float> fillB) : this(fillA(0), fillB(0)) { }
|
||||
public Sphere(float cX, float cY, float radius) : this(new Float3(cX, cY), radius) { }
|
||||
public Sphere(float cX, float cY, float cZ, float radius) : this(new Float3(cX, cY, cZ), radius) { }
|
||||
public Sphere(Fill<float> fill, float radius) : this(new Float3(fill), radius) { }
|
||||
public Sphere(Fill<float> fill) : this(new Float3(fill), fill(3)) { }
|
||||
public Sphere(Fill<int> fill, float radius) : this(new Float3(fill), radius) { }
|
||||
public Sphere(Fill<int> fill) : this(new Float3(fill), fill(3)) { }
|
||||
public Sphere(Fill<Float3> fill, float radius) : this(fill(0), radius) { }
|
||||
public Sphere(Fill<Float3> fillA, Fill<float> fillB) : this(fillA(0), fillB(0)) { }
|
||||
|
||||
public static Sphere Average(params Sphere[] vals)
|
||||
{
|
||||
(Vert[] centers, float[] radii) = SplitArray(vals);
|
||||
return new(Vert.Average(centers), Mathf.Average(radii));
|
||||
(Float3[] centers, float[] radii) = SplitArray(vals);
|
||||
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) =>
|
||||
new(Vert.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));
|
||||
new(Float3.Clamp(val.center, min.center, max.center), Mathf.Clamp(val.radius, min.radius, max.radius));
|
||||
public static Sphere Floor(Sphere val) => new(Float3.Floor(val.center), Mathf.Floor(val.radius));
|
||||
public static Sphere Lerp(Sphere a, Sphere b, float t, bool clamp = true) =>
|
||||
new(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)
|
||||
{
|
||||
(Vert[] centers, float[] radii) = SplitArray(vals);
|
||||
return new(Vert.Max(centers), Mathf.Max(radii));
|
||||
(Float3[] centers, float[] radii) = SplitArray(vals);
|
||||
return new(Float3.Max(centers), Mathf.Max(radii));
|
||||
}
|
||||
public static Sphere Median(params Sphere[] vals)
|
||||
{
|
||||
(Vert[] centers, float[] radii) = SplitArray(vals);
|
||||
return new(Vert.Median(centers), Mathf.Median(radii));
|
||||
(Float3[] centers, float[] radii) = SplitArray(vals);
|
||||
return new(Float3.Median(centers), Mathf.Median(radii));
|
||||
}
|
||||
public static Sphere Min(params Sphere[] vals)
|
||||
{
|
||||
(Vert[] centers, float[] radii) = SplitArray(vals);
|
||||
return new(Vert.Min(centers), Mathf.Min(radii));
|
||||
(Float3[] centers, float[] radii) = SplitArray(vals);
|
||||
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];
|
||||
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.")]
|
||||
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)
|
||||
{
|
||||
@ -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, 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, 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, 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);
|
||||
@ -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.")]
|
||||
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);
|
||||
}
|
||||
|
||||
@ -3,10 +3,10 @@
|
||||
namespace Nerd_STF.Mathematics.Geometry;
|
||||
|
||||
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>,
|
||||
IIndexAll<Vert>, IIndexRangeAll<Vert>, ILerp<Triangle, float>, IRound<Triangle>, IShape2d<float>
|
||||
IEquatable<Triangle>, IFloor<Triangle>, IFromTuple<Triangle, (Float3 a, Float3 b, Float3 c)>, IGroup<Float3>,
|
||||
IIndexAll<Float3>, IIndexRangeAll<Float3>, ILerp<Triangle, float>, IRound<Triangle>, IShape2d<float>
|
||||
{
|
||||
public Vert A
|
||||
public Float3 A
|
||||
{
|
||||
get => p_a;
|
||||
set
|
||||
@ -16,7 +16,7 @@ public record class Triangle : IAbsolute<Triangle>, IAverage<Triangle>, ICeiling
|
||||
p_ca.b = value;
|
||||
}
|
||||
}
|
||||
public Vert B
|
||||
public Float3 B
|
||||
{
|
||||
get => p_b;
|
||||
set
|
||||
@ -26,7 +26,7 @@ public record class Triangle : IAbsolute<Triangle>, IAverage<Triangle>, ICeiling
|
||||
p_bc.a = value;
|
||||
}
|
||||
}
|
||||
public Vert C
|
||||
public Float3 C
|
||||
{
|
||||
get => p_c;
|
||||
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;
|
||||
|
||||
[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) +
|
||||
(C.position.x * A.position.y) - ((B.position.x * A.position.y) + (C.position.x * B.position.y) +
|
||||
(A.position.x * C.position.y))) * 0.5f;
|
||||
public Vert Midpoint => Vert.Average(A, B, C);
|
||||
public float Area => (float)Mathf.Absolute((A.x * B.y) + (B.x * C.y) +
|
||||
(C.x * A.y) - ((B.x * A.y) + (C.x * B.y) +
|
||||
(A.x * C.y))) * 0.5f;
|
||||
public Float3 Midpoint => Float3.Average(A, B, C);
|
||||
public float Perimeter => AB.Length + BC.Length + CA.Length;
|
||||
|
||||
public Triangle(Vert a, Vert b, Vert c)
|
||||
public Triangle(Float3 a, Float3 b, Float3 c)
|
||||
{
|
||||
p_a = a;
|
||||
p_b = b;
|
||||
@ -105,19 +105,18 @@ public record class Triangle : IAbsolute<Triangle>, IAverage<Triangle>, ICeiling
|
||||
p_ca = ca;
|
||||
}
|
||||
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,
|
||||
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<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<float> fill) : this(fill(0), fill(1), fill(2), fill(3), fill(4), fill(5), fill(6),
|
||||
fill(7), fill(8)) { }
|
||||
public Triangle(Fill<int> fill) : this(fill(0), fill(1), fill(2), fill(3), fill(4), fill(5), fill(6),
|
||||
fill(7), fill(8)) { }
|
||||
|
||||
public Vert this[int index]
|
||||
public Float3 this[int index]
|
||||
{
|
||||
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];
|
||||
set => this[index.IsFromEnd ? 3 - index.Value : index.Value] = value;
|
||||
}
|
||||
public Vert[] this[Range range]
|
||||
public Float3[] this[Range range]
|
||||
{
|
||||
get
|
||||
{
|
||||
int start = range.Start.IsFromEnd ? 3 - range.Start.Value : range.Start.Value;
|
||||
int end = range.End.IsFromEnd ? 3 - range.End.Value : range.End.Value;
|
||||
List<Vert> res = new();
|
||||
List<Float3> res = new();
|
||||
for (int i = start; i < end; i++) res.Add(this[i]);
|
||||
return res.ToArray();
|
||||
}
|
||||
@ -170,41 +169,41 @@ public record class Triangle : IAbsolute<Triangle>, IAverage<Triangle>, ICeiling
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
(Vert[] As, Vert[] Bs, Vert[] Cs) = SplitVertArray(vals);
|
||||
return new(Vert.Average(As), Vert.Average(Bs), Vert.Average(Cs));
|
||||
(Float3[] As, Float3[] Bs, Float3[] Cs) = SplitFloat3Array(vals);
|
||||
return new(Float3.Average(As), Float3.Average(Bs), Float3.Average(Cs));
|
||||
}
|
||||
public static Triangle Ceiling(Triangle val) =>
|
||||
new(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) =>
|
||||
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) =>
|
||||
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) =>
|
||||
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)
|
||||
{
|
||||
(Vert[] As, Vert[] Bs, Vert[] Cs) = SplitVertArray(vals);
|
||||
return new(Vert.Max(As), Vert.Max(Bs), Vert.Max(Cs));
|
||||
(Float3[] As, Float3[] Bs, Float3[] Cs) = SplitFloat3Array(vals);
|
||||
return new(Float3.Max(As), Float3.Max(Bs), Float3.Max(Cs));
|
||||
}
|
||||
public static Triangle Median(params Triangle[] vals)
|
||||
{
|
||||
(Vert[] As, Vert[] Bs, Vert[] Cs) = SplitVertArray(vals);
|
||||
return new(Vert.Median(As), Vert.Median(Bs), Vert.Median(Cs));
|
||||
(Float3[] As, Float3[] Bs, Float3[] Cs) = SplitFloat3Array(vals);
|
||||
return new(Float3.Median(As), Float3.Median(Bs), Float3.Median(Cs));
|
||||
}
|
||||
public static Triangle Min(params Triangle[] vals)
|
||||
{
|
||||
(Vert[] As, Vert[] Bs, Vert[] Cs) = SplitVertArray(vals);
|
||||
return new(Vert.Min(As), Vert.Min(Bs), Vert.Min(Cs));
|
||||
(Float3[] As, Float3[] Bs, Float3[] Cs) = SplitFloat3Array(vals);
|
||||
return new(Float3.Min(As), Float3.Min(Bs), Float3.Min(Cs));
|
||||
}
|
||||
public static Triangle Round(Triangle val) =>
|
||||
new(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++)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
int pos = i * 9;
|
||||
vals[pos + 0] = tris[i].A.position.x;
|
||||
vals[pos + 1] = tris[i].A.position.y;
|
||||
vals[pos + 2] = tris[i].A.position.z;
|
||||
vals[pos + 3] = tris[i].B.position.x;
|
||||
vals[pos + 4] = tris[i].B.position.y;
|
||||
vals[pos + 5] = tris[i].B.position.z;
|
||||
vals[pos + 6] = tris[i].C.position.x;
|
||||
vals[pos + 7] = tris[i].C.position.y;
|
||||
vals[pos + 8] = tris[i].C.position.z;
|
||||
vals[pos + 0] = tris[i].A.x;
|
||||
vals[pos + 1] = tris[i].A.y;
|
||||
vals[pos + 2] = tris[i].A.z;
|
||||
vals[pos + 3] = tris[i].B.x;
|
||||
vals[pos + 4] = tris[i].B.y;
|
||||
vals[pos + 5] = tris[i].B.z;
|
||||
vals[pos + 6] = tris[i].C.x;
|
||||
vals[pos + 7] = tris[i].C.y;
|
||||
vals[pos + 8] = tris[i].C.z;
|
||||
}
|
||||
return vals;
|
||||
}
|
||||
@ -253,27 +252,27 @@ public record class Triangle : IAbsolute<Triangle>, IAverage<Triangle>, ICeiling
|
||||
public override int GetHashCode() => base.GetHashCode();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
public IEnumerator<Vert> GetEnumerator()
|
||||
public IEnumerator<Float3> GetEnumerator()
|
||||
{
|
||||
yield return A;
|
||||
yield return B;
|
||||
yield return C;
|
||||
}
|
||||
|
||||
public Vert[] ToArray() => new Vert[] { A, B, C };
|
||||
public Fill<Vert> ToFill()
|
||||
public Float3[] ToArray() => new Float3[] { A, B, C };
|
||||
public Fill<Float3> ToFill()
|
||||
{
|
||||
Triangle @this = this;
|
||||
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,
|
||||
B.position.x, B.position.y, B.position.z,
|
||||
C.position.x, C.position.y, C.position.z };
|
||||
public List<float> ToFloatList() => new() { A.position.x, A.position.y, A.position.z,
|
||||
B.position.x, B.position.y, B.position.z,
|
||||
C.position.x, C.position.y, C.position.z };
|
||||
public float[] ToFloatArray() => new float[] { A.x, A.y, A.z,
|
||||
B.x, B.y, B.z,
|
||||
C.x, C.y, C.z };
|
||||
public List<float> ToFloatList() => new() { A.x, A.y, A.z,
|
||||
B.x, B.y, B.z,
|
||||
C.x, C.y, C.z };
|
||||
|
||||
protected virtual bool PrintMembers(StringBuilder builder)
|
||||
{
|
||||
@ -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, 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 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, 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, 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 implicit operator Triangle(Fill<Vert> 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<Line> 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((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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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(Int3 val) => new(val.x, val.y);
|
||||
public static explicit operator Int2(Int4 val) => new(val.x, val.y);
|
||||
public static explicit operator Int2(Vert val) => new((int)val.position.x, (int)val.position.y);
|
||||
public static implicit operator Int2(Fill<int> fill) => new(fill);
|
||||
public static implicit operator Int2((int x, int y) val) => new(val.x, val.y);
|
||||
}
|
||||
|
||||
@ -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(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(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(HSVA val) => (Int3)val.ToHSVAByte();
|
||||
public static explicit operator Int3(RGBAByte val) => new(val.R, val.G, val.B);
|
||||
|
||||
@ -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 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(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(CMYKA val) => (Int4)val.ToCMYKAByte();
|
||||
public static explicit operator Int4(HSVA val) => val.ToHSVAByte();
|
||||
|
||||
@ -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(Matrix m) => new(m[0, 0], m[1, 0]);
|
||||
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<int> fill) => new(fill);
|
||||
public static implicit operator Complex((float u, float i) val) => new(val.u, val.i);
|
||||
|
||||
@ -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 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 implicit operator Quaternion(Vert val) => new(val);
|
||||
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((float u, float i, float j, float k) val) =>
|
||||
|
||||
@ -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 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`?
|
||||
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.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user