Skip to content

Commit

Permalink
Continue adventures of making arenabounds local.
Browse files Browse the repository at this point in the history
  • Loading branch information
awgil committed Apr 29, 2024
1 parent a8f8988 commit 2c26efc
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 29 deletions.
1 change: 0 additions & 1 deletion BossMod/BossModule/ArenaBounds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ public abstract record class ArenaBounds(WPos Center, float Radius, float MapRes
public List<Triangle> ShapeTriangulation { get; private set; } = [];
private readonly PolygonClipper.Operand _clipOperand = new();

public List<Triangle> ClipAndTriangulate(PolygonClipper.Operand poly) => Clipper.Intersect(poly, _clipOperand).Triangulate();
public List<Triangle> ClipAndTriangulate(IEnumerable<WPos> poly) => Clipper.Intersect(new(poly), _clipOperand).Triangulate();
public List<Triangle> ClipAndTriangulate(SimplifiedComplexPolygon poly) => Clipper.Intersect(new(poly), _clipOperand).Triangulate();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ private static ArenaBoundsCustom BuildTriBounds()
var center = new WPos(-945, 948.5f);
var hw = NormalBounds.Radius * 0.86602540378443864676372317075294f; // sqrt(3) / 2;
var hh = NormalBounds.Radius * 0.5f;
ReadOnlySpan<WPos> verts = [
List<WPos> verts = [
center + new WDir(-hw, hh),
center + new WDir(+hw, hh),
center + new WDir(0, -NormalBounds.Radius)
Expand Down
52 changes: 28 additions & 24 deletions BossMod/Util/CurveApprox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,66 +18,70 @@ public static int CalculateCircleSegments(float radius, Angle angularLength, flo

// return polygon points approximating full circle; implicitly closed path - last point is not included
// winding: points are in CCW order
public static IEnumerable<WPos> Circle(WPos center, float radius, float maxError)
public static IEnumerable<WDir> Circle(float radius, float maxError)
{
int numSegments = CalculateCircleSegments(radius, (2 * MathF.PI).Radians(), maxError);
var angle = (2 * MathF.PI / numSegments).Radians();
for (int i = 0; i < numSegments; ++i) // note: do not include last point
yield return PolarToCartesian(center, radius, i * angle);
yield return PolarToCartesian(radius, i * angle);
}
public static IEnumerable<WPos> Circle(WPos center, float radius, float maxError) => Circle(radius, maxError).Select(off => center + off);

// return polygon points approximating circle arc; both start and end points are included
// winding: points are either in CCW order (if length is positive) or CW order (if length is negative)
public static IEnumerable<WPos> CircleArc(WPos center, float radius, Angle angleStart, Angle angleEnd, float maxError)
public static IEnumerable<WDir> CircleArc(float radius, Angle angleStart, Angle angleEnd, float maxError)
{
var length = angleEnd - angleStart;
int numSegments = CalculateCircleSegments(radius, length.Abs(), maxError);
var angle = length / numSegments;
for (int i = 0; i <= numSegments; ++i)
yield return PolarToCartesian(center, radius, angleStart + i * angle);
yield return PolarToCartesian(radius, angleStart + i * angle);
}
public static IEnumerable<WPos> CircleArc(WPos center, float radius, Angle angleStart, Angle angleEnd, float maxError) => CircleArc(radius, angleStart, angleEnd, maxError).Select(off => center + off);

// return polygon points approximating circle sector; implicitly closed path - center + arc
public static IEnumerable<WPos> CircleSector(WPos center, float radius, Angle angleStart, Angle angleEnd, float maxError)
public static IEnumerable<WDir> CircleSector(float radius, Angle angleStart, Angle angleEnd, float maxError)
{
yield return center;
foreach (var v in CircleArc(center, radius, angleStart, angleEnd, maxError))
yield return default;
foreach (var v in CircleArc(radius, angleStart, angleEnd, maxError))
yield return v;
}
public static IEnumerable<WPos> CircleSector(WPos center, float radius, Angle angleStart, Angle angleEnd, float maxError) => CircleSector(radius, angleStart, angleEnd, maxError).Select(off => center + off);

// return polygon points approximating full donut; implicitly closed path - outer arc + inner arc
public static IEnumerable<WPos> Donut(WPos center, float innerRadius, float outerRadius, float maxError)
public static IEnumerable<WDir> Donut(float innerRadius, float outerRadius, float maxError)
{
foreach (var v in Circle(center, outerRadius, maxError))
foreach (var v in Circle(outerRadius, maxError))
yield return v;
yield return PolarToCartesian(center, outerRadius, 0.0f.Radians());
yield return PolarToCartesian(center, innerRadius, 0.0f.Radians());
foreach (var v in Circle(center, innerRadius, maxError).Reverse())
yield return PolarToCartesian(outerRadius, 0.0f.Radians());
yield return PolarToCartesian(innerRadius, 0.0f.Radians());
foreach (var v in Circle(innerRadius, maxError).Reverse())
yield return v;
}
public static IEnumerable<WPos> Donut(WPos center, float innerRadius, float outerRadius, float maxError) => Donut(innerRadius, outerRadius, maxError).Select(off => center + off);

// return polygon points approximating donut sector; implicitly closed path - outer arc + inner arc
public static IEnumerable<WPos> DonutSector(WPos center, float innerRadius, float outerRadius, Angle angleStart, Angle angleEnd, float maxError)
public static IEnumerable<WDir> DonutSector(float innerRadius, float outerRadius, Angle angleStart, Angle angleEnd, float maxError)
{
foreach (var v in CircleArc(center, outerRadius, angleStart, angleEnd, maxError))
foreach (var v in CircleArc(outerRadius, angleStart, angleEnd, maxError))
yield return v;
foreach (var v in CircleArc(center, innerRadius, angleEnd, angleStart, maxError))
foreach (var v in CircleArc(innerRadius, angleEnd, angleStart, maxError))
yield return v;
}
public static IEnumerable<WPos> DonutSector(WPos center, float innerRadius, float outerRadius, Angle angleStart, Angle angleEnd, float maxError) => DonutSector(innerRadius, outerRadius, angleStart, angleEnd, maxError).Select(off => center + off);

// return polygon points for rectangle - it's not really a curve, but whatever...
public static IEnumerable<WPos> Rect(WPos center, WDir dx, WDir dz)
public static IEnumerable<WDir> Rect(WDir dx, WDir dz)
{
yield return center + dx - dz;
yield return center + dx + dz;
yield return center - dx + dz;
yield return center - dx - dz;
yield return dx - dz;
yield return dx + dz;
yield return -dx + dz;
yield return -dx - dz;
}
public static IEnumerable<WDir> Rect(WDir dirZ, float halfWidth, float halfHeight) => Rect(dirZ.OrthoL() * halfWidth, dirZ * halfHeight);
public static IEnumerable<WPos> Rect(WPos center, WDir dx, WDir dz) => Rect(dx, dz).Select(off => center + off);
public static IEnumerable<WPos> Rect(WPos center, WDir dirZ, float halfWidth, float halfHeight) => Rect(center, dirZ.OrthoL() * halfWidth, dirZ * halfHeight);

// for angles, we use standard FF convention: 0 is 'south'/down/(0, -r), and then increases clockwise
private static WPos PolarToCartesian(WPos center, float r, Angle phi)
{
return center + r * phi.ToDirection();
}
private static WDir PolarToCartesian(float r, Angle phi) => r * phi.ToDirection();
}
4 changes: 1 addition & 3 deletions BossMod/Util/Polygon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ public record class PolygonWithHoles(List<WPos> Vertices, List<int> HoleStarts)
{
// constructor for simple polygon
public PolygonWithHoles(List<WPos> simpleVertices) : this(simpleVertices, []) { }
public PolygonWithHoles(ReadOnlySpan<WPos> simpleVertices) : this([.. simpleVertices], []) { }
public PolygonWithHoles(IEnumerable<WPos> simpleVertices) : this([.. simpleVertices], []) { }

public ReadOnlySpan<WPos> AllVertices => Vertices.AsSpan();
public ReadOnlySpan<WPos> Exterior => AllVertices[..ExteriorEnd];
Expand Down Expand Up @@ -176,7 +174,7 @@ private static void BuildResult(SimplifiedComplexPolygon result, PolyPath64 pare
for (var i = 0; i < parent.Count; ++i)
{
var exterior = parent[i];
PolygonWithHoles poly = new(exterior.Polygon?.Select(ConvertPoint) ?? throw new InvalidOperationException("Unexpected null polygon list"));
PolygonWithHoles poly = new([.. exterior.Polygon?.Select(ConvertPoint) ?? throw new InvalidOperationException("Unexpected null polygon list")]);
result.Parts.Add(poly);
for (var j = 0; j < exterior.Count; ++j)
{
Expand Down

0 comments on commit 2c26efc

Please sign in to comment.