-
Notifications
You must be signed in to change notification settings - Fork 24
Angle changes #121
base: master
Are you sure you want to change the base?
Angle changes #121
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,6 +1,5 @@ | ||||||
| using System; | ||||||
| using System.Numerics; | ||||||
| using System.Runtime.CompilerServices; | ||||||
| using JetBrains.Annotations; | ||||||
| using Robust.Shared.Utility; | ||||||
|
|
||||||
|
|
@@ -19,6 +18,9 @@ namespace Robust.Shared.Maths | |||||
| /// </summary> | ||||||
| public readonly double Theta; | ||||||
|
|
||||||
| private const double PiOver2 = Math.PI / 2.0; | ||||||
| private const double TwoPi = 2.0 * Math.PI; | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just use Math.Tau |
||||||
|
|
||||||
| /// <summary> | ||||||
| /// Angle in degrees. | ||||||
| /// </summary> | ||||||
|
|
@@ -44,7 +46,7 @@ public Angle(Vector2 dir) | |||||
|
|
||||||
| public static Angle FromWorldVec(Vector2 dir) | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. documentation. |
||||||
| { | ||||||
| return new Angle(dir) + Math.PI / 2; | ||||||
| return new Angle(Math.Atan2(dir.Y, dir.X) + PiOver2); | ||||||
| } | ||||||
|
|
||||||
| /// <summary> | ||||||
|
|
@@ -56,52 +58,51 @@ public static Angle FromWorldVec(Vector2 dir) | |||||
| /// where an angle of zero is usually considered "south" (0, -1). | ||||||
| /// </remarks> | ||||||
| /// <returns>Unit Direction Vector</returns> | ||||||
| public readonly Vector2 ToVec() | ||||||
| public Vector2 ToVec() | ||||||
| { | ||||||
| var x = Math.Cos(Theta); | ||||||
| var y = Math.Sin(Theta); | ||||||
| return new Vector2((float) x, (float) y); | ||||||
| } | ||||||
|
|
||||||
| public readonly Vector2 ToWorldVec() | ||||||
| public Vector2 ToWorldVec() | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add documentation while you are at it |
||||||
| { | ||||||
| return (this - MathHelper.PiOver2).ToVec(); | ||||||
| var theta = Theta - PiOver2; | ||||||
| var x = Math.Cos(theta); | ||||||
| var y = Math.Sin(theta); | ||||||
| return new Vector2((float) x, (float) y); | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
formatting convention |
||||||
| } | ||||||
|
|
||||||
| private const double Segment = 2 * Math.PI / 8.0; // Cut the circle into 8 pieces | ||||||
| private const double Offset = Segment / 2.0; // offset the pieces by 1/2 their size | ||||||
| private const double InvSegment = 1.0 / Segment; | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure the compiler doesn't just do this for you? |
||||||
|
|
||||||
| public readonly Direction GetDir() | ||||||
| public Direction GetDir() | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. docs |
||||||
| { | ||||||
| var ang = Theta % (2 * Math.PI); | ||||||
|
|
||||||
| if (ang < 0) // convert -PI > PI to 0 > 2PI | ||||||
| ang += 2 * Math.PI; | ||||||
|
|
||||||
| return (Direction) (Math.Floor((ang + Offset) / Segment) % 8); | ||||||
| return GetDir(Theta); | ||||||
| } | ||||||
|
|
||||||
| public Direction RotateDir(Direction dir) | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. docs |
||||||
| { | ||||||
| var ang = (Theta + Segment * (int)dir) % (2 * Math.PI); | ||||||
| var ang = (Theta + Segment * (int)dir) % TwoPi; | ||||||
| if (ang < 0) | ||||||
| ang += 2 * Math.PI; | ||||||
| ang += TwoPi; | ||||||
|
|
||||||
| return (Direction)(Math.Floor((ang + Offset) / Segment) % 8); | ||||||
| return (Direction) ((int) ((ang + Offset) * InvSegment) & 7); | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| } | ||||||
|
|
||||||
| private const double CardinalSegment = 2 * Math.PI / 4.0; // Cut the circle into 4 pieces | ||||||
| private const double CardinalOffset = CardinalSegment / 2.0; // offset the pieces by 1/2 their size | ||||||
| private const double InvCardinalSegment = 1.0 / CardinalSegment; | ||||||
|
|
||||||
| [Pure] | ||||||
| public readonly Direction GetCardinalDir() | ||||||
| public Direction GetCardinalDir() | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. docs |
||||||
| { | ||||||
| var ang = Theta % (2 * Math.PI); | ||||||
|
|
||||||
| if (ang < 0.0f) // convert -PI > PI to 0 > 2PI | ||||||
| ang += 2 * Math.PI; | ||||||
| var ang = Theta % TwoPi; | ||||||
| if (ang < 0) // convert -PI > PI to 0 > 2PI | ||||||
| ang += TwoPi; | ||||||
|
|
||||||
| return (Direction) (Math.Floor((ang + CardinalOffset) / CardinalSegment) * 2 % 8); | ||||||
| return (Direction) (((int) ((ang + CardinalOffset) * InvCardinalSegment) * 2) & 7); | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| } | ||||||
|
|
||||||
| /// <summary> | ||||||
|
|
@@ -120,7 +121,7 @@ public Angle RoundToCardinalAngle() | |||||
| /// <param name="vec">Vector to rotate.</param> | ||||||
| /// <returns>New rotated vector.</returns> | ||||||
| [Pure] | ||||||
| public readonly Vector2 RotateVec(in Vector2 vec) | ||||||
| public Vector2 RotateVec(in Vector2 vec) | ||||||
| { | ||||||
| // No calculation necessery when theta is zero | ||||||
| if (Theta == 0) return vec; | ||||||
|
|
@@ -155,8 +156,8 @@ private static bool EqualsApprox(Angle a, Angle b) | |||||
| // The second two expressions cover an edge case where one number is barely non-negative while the other number is negative. | ||||||
| // In this case, the negative number will get FlipPositived to ~2pi and the comparison will give a false negative. | ||||||
| return MathHelper.CloseToPercent(aPositive, bPositive) | ||||||
| || MathHelper.CloseToPercent(aPositive + MathHelper.TwoPi, bPositive) | ||||||
| || MathHelper.CloseToPercent(aPositive, bPositive + MathHelper.TwoPi); | ||||||
| || MathHelper.CloseToPercent(aPositive + TwoPi, bPositive) | ||||||
| || MathHelper.CloseToPercent(aPositive, bPositive + TwoPi); | ||||||
| } | ||||||
|
|
||||||
| private static bool EqualsApprox(Angle a, Angle b, double tolerance) | ||||||
|
|
@@ -171,15 +172,15 @@ private static bool EqualsApprox(Angle a, Angle b, double tolerance) | |||||
| // The second two expressions cover an edge case where one number is barely non-negative while the other number is negative. | ||||||
| // In this case, the negative number will get FlipPositived to ~2pi and the comparison will give a false negative. | ||||||
| return MathHelper.CloseToPercent(aPositive, bPositive, tolerance) | ||||||
| || MathHelper.CloseToPercent(aPositive + MathHelper.TwoPi, bPositive, tolerance) | ||||||
| || MathHelper.CloseToPercent(aPositive, bPositive + MathHelper.TwoPi, tolerance); | ||||||
| || MathHelper.CloseToPercent(aPositive + TwoPi, bPositive, tolerance) | ||||||
| || MathHelper.CloseToPercent(aPositive, bPositive + TwoPi, tolerance); | ||||||
| } | ||||||
|
|
||||||
| /// <summary> | ||||||
| /// Removes revolutions from a positive or negative angle to make it as small as possible. | ||||||
| /// </summary> | ||||||
| [Pure] | ||||||
| public readonly Angle Reduced() | ||||||
| public Angle Reduced() | ||||||
| { | ||||||
| return new(Reduce(Theta)); | ||||||
| } | ||||||
|
|
@@ -190,29 +191,26 @@ public readonly Angle Reduced() | |||||
| private static double Reduce(double theta) | ||||||
| { | ||||||
| // int truncates value (round to 0) | ||||||
| var aTurns = (int) (theta / (2 * Math.PI)); | ||||||
| return theta - aTurns * (2 * Math.PI); | ||||||
| var aTurns = (int) (theta / TwoPi); | ||||||
| return theta - aTurns * TwoPi; | ||||||
| } | ||||||
|
|
||||||
| /// <inheritdoc /> | ||||||
| public readonly bool Equals(Angle other) | ||||||
| public bool Equals(Angle other) | ||||||
| { | ||||||
| return Theta.Equals(other.Theta); | ||||||
| } | ||||||
|
|
||||||
| /// <inheritdoc /> | ||||||
| public readonly override bool Equals(object? obj) | ||||||
| public override bool Equals(object? obj) | ||||||
| { | ||||||
| if (ReferenceEquals(null, obj)) return false; | ||||||
| return obj is Angle angle && Equals(angle); | ||||||
| } | ||||||
|
|
||||||
| /// <inheritdoc /> | ||||||
| public readonly override int GetHashCode() | ||||||
| public override int GetHashCode() | ||||||
| { | ||||||
|
|
||||||
| return Theta.GetHashCode(); | ||||||
|
|
||||||
| } | ||||||
|
|
||||||
| public static bool operator ==(Angle a, Angle b) | ||||||
|
|
@@ -226,13 +224,13 @@ public readonly override int GetHashCode() | |||||
| } | ||||||
|
|
||||||
| [Pure] | ||||||
| public readonly Angle Opposite() | ||||||
| public Angle Opposite() | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. docs, same below |
||||||
| { | ||||||
| return new Angle(FlipPositive(Theta-Math.PI)); | ||||||
| return new Angle(FlipPositive(Theta - Math.PI)); | ||||||
| } | ||||||
|
|
||||||
| [Pure] | ||||||
| public readonly Angle FlipPositive() | ||||||
| public Angle FlipPositive() | ||||||
| { | ||||||
| return new(FlipPositive(Theta)); | ||||||
| } | ||||||
|
|
@@ -245,7 +243,16 @@ private static double FlipPositive(double theta) | |||||
| if (theta >= 0) | ||||||
| return theta; | ||||||
|
|
||||||
| return theta + 2 * Math.PI; | ||||||
| return theta + TwoPi; | ||||||
| } | ||||||
|
|
||||||
| private static Direction GetDir(double theta) | ||||||
| { | ||||||
| var ang = theta % TwoPi; | ||||||
| if (ang < 0) // convert -PI > PI to 0 > 2PI | ||||||
| ang += TwoPi; | ||||||
|
|
||||||
| return (Direction) ((int) ((ang + Offset) * InvSegment) & 7); | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| } | ||||||
|
|
||||||
| /// <summary> | ||||||
|
|
@@ -262,8 +269,8 @@ public static Angle Lerp(in Angle a, in Angle b, float factor) | |||||
| /// </summary> | ||||||
| public static Angle ShortestDistance(in Angle a, in Angle b) | ||||||
| { | ||||||
| var delta = (b - a) % Math.Tau; | ||||||
| return 2 * delta % Math.Tau - delta; | ||||||
| var delta = (b - a) % TwoPi; | ||||||
| return 2 * delta % TwoPi - delta; | ||||||
| } | ||||||
|
|
||||||
| /// <summary> | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are you sure the compiler does not already do this for you as a very obvious optimization?