Skip to content

Commit a364015

Browse files
committed
projection, angle & PointsInCircle stuff
1 parent fe93857 commit a364015

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

Runtime/Extensions.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,26 @@ public static Vector2 Rotate( this Vector2 v, float angRad ) {
177177
/// <inheritdoc cref="ScaleAround(Vector2,Vector2,Vector2)"/>
178178
[MethodImpl( INLINE )] public static Vector3 ScaleAround( this Vector3 p, Vector3 pivot, Vector3 scale ) => new(pivot.x + ( p.x - pivot.x ) * scale.x, pivot.y + ( p.y - pivot.y ) * scale.y, pivot.z + ( p.z - pivot.z ) * scale.z);
179179

180+
/// <summary>Projects the vector perpendicularly onto the other vector B</summary>
181+
/// <param name="a">The vector to project with</param>
182+
/// <param name="b">The vector to project perpendicularly against. The resulting vector is along this vector</param>
183+
public static Vector3 Project( this Vector3 a, Vector3 b ) {
184+
float denom = Vector3.Dot( b, b );
185+
if( Mathfs.Approximately( denom, 0 ) )
186+
throw new DivideByZeroException( "Can't project to a vector with 0 length" );
187+
return b * ( Vector3.Dot( a, b ) / denom );
188+
}
189+
190+
/// <summary>Projects the vector perpendicularly *from* the initial vector, onto the other vector B</summary>
191+
/// <param name="a">The vector to project perpendicularly from</param>
192+
/// <param name="b">The vector to project against. The resulting vector is along this vector</param>
193+
public static Vector3 ProjectPerpFrom( this Vector3 a, Vector3 b ) {
194+
float denom = Vector3.Dot( a, b );
195+
if( Mathfs.Approximately( denom, 0 ) )
196+
throw new DivideByZeroException( "Can't project to a vector with 0 length" );
197+
return b * ( Vector3.Dot( a, a ) / denom );
198+
}
199+
180200
#endregion
181201

182202
#region Quaternions

Runtime/Mathfs.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// Collected and expanded upon to by Freya Holmér (https://github.com/FreyaHolmer/Mathfs)
66

77
using System;
8+
using System.Collections.Generic;
89
using UnityEngine;
910
using Uei = UnityEngine.Internal;
1011
using System.Linq; // used for arbitrary count min/max functions, so it's safe and won't allocate garbage don't worry~
@@ -1109,6 +1110,14 @@ public static Vector3 ClampMagnitude( Vector3 v, float min, float max ) {
11091110
/// <inheritdoc cref="DistanceSquared(Vector2,Vector2)"/>
11101111
[MethodImpl( INLINE )] public static float DistanceSquared( Vector4 a, Vector4 b ) => ( a.x - b.x ).Square() + ( a.y - b.y ).Square() + ( a.z - b.z ).Square() + ( a.w - b.w ).Square();
11111112

1113+
/// <summary>The t-value (fraction) where a projected along b would be</summary>
1114+
/// <param name="a">The vector to project</param>
1115+
/// <param name="b">The vector to project onto</param>
1116+
public static float ProjectionTValue( Vector3 a, Vector3 b ) => Vector3.Dot( a, b ) / Vector3.Dot( b, b );
1117+
1118+
/// <inheritdoc cref="ProjectionTValue(Vector3,Vector3)"/>
1119+
public static float ProjectionTValue( Vector2 a, Vector2 b ) => Vector2.Dot( a, b ) / Vector2.Dot( b, b );
1120+
11121121
/// <summary>Calculates a rotation minimizing normal direction, given start and end conditions. This is usually used when evaluating rotation minimizing frames on curves.</summary>
11131122
/// <param name="posA">The start position</param>
11141123
/// <param name="tangentA">The start tangent direction</param>
@@ -1306,9 +1315,15 @@ public static Pose Lerp( Pose a, Pose b, float t ) =>
13061315
/// <summary>Returns the shortest angle between <c>a</c> and <c>b</c>, in the range 0 to tau/2 (0 to pi)</summary>
13071316
[MethodImpl( INLINE )] public static float AngleBetween( Vector2 a, Vector2 b ) => MathF.Acos( Vector2.Dot( a.normalized, b.normalized ).ClampNeg1to1() );
13081317

1318+
/// <summary>Returns the shortest angle between two normalized vectors <c>a</c> and <c>b</c>, in the range 0 to tau/2 (0 to pi)</summary>
1319+
[MethodImpl( INLINE )] public static float AngleBetweenPreNormalized( Vector2 a, Vector2 b ) => MathF.Acos( Vector2.Dot( a, b ).ClampNeg1to1() );
1320+
13091321
/// <inheritdoc cref="AngleBetween(Vector2,Vector2)"/>
13101322
[MethodImpl( INLINE )] public static float AngleBetween( Vector3 a, Vector3 b ) => MathF.Acos( Vector3.Dot( a.normalized, b.normalized ).ClampNeg1to1() );
13111323

1324+
/// <inheritdoc cref="AngleBetweenPreNormalized(Vector2,Vector2)"/>
1325+
[MethodImpl( INLINE )] public static float AngleBetweenPreNormalized( Vector3 a, Vector3 b ) => MathF.Acos( Vector3.Dot( a, b ).ClampNeg1to1() );
1326+
13121327
/// <summary>Returns the clockwise angle between <c>from</c> and <c>to</c>, in the range 0 to tau (0 to 2*pi)</summary>
13131328
[MethodImpl( INLINE )] public static float AngleFromToCW( Vector2 from, Vector2 to ) => Determinant( from, to ) < 0 ? AngleBetween( from, to ) : TAU - AngleBetween( from, to );
13141329

@@ -1341,6 +1356,25 @@ public static float InverseLerpAngle( float a, float b, float v ) {
13411356
return InverseLerpClamped( a, b, v );
13421357
}
13431358

1359+
/// <summary>An enumerable sequence of <c>count</c> number of vectors
1360+
/// on a circle with the given radius, starting from the X axis</summary>
1361+
/// <param name="count">The number of vectors to arrange on the circle.
1362+
/// A negative count will enumerate in the negative direction</param>
1363+
/// <param name="radius">The radius of the circle</param>
1364+
public static IEnumerable<Vector2> PointsInCircle( int count, float radius = 1 ) {
1365+
if( count == 0 )
1366+
yield break;
1367+
yield return new Vector2( radius, 0 );
1368+
int absCount = Math.Abs( count );
1369+
for( int i = 1; i < absCount; i++ ) {
1370+
float angle = ( TAU * i ) / count;
1371+
yield return new Vector2(
1372+
MathF.Cos( angle ) * radius,
1373+
MathF.Sin( angle ) * radius
1374+
);
1375+
}
1376+
}
1377+
13441378
#endregion
13451379

13461380
#region Angular movement helpers

0 commit comments

Comments
 (0)