2009-04-19 18:07:22 +00:00
|
|
|
|
|
|
|
#region ================== Copyright (c) 2007 Pascal vd Heiden
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
|
|
|
|
* This program is released under GNU General Public License
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region ================== Namespaces
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
namespace CodeImp.DoomBuilder.Geometry
|
|
|
|
{
|
|
|
|
public struct Angle2D
|
|
|
|
{
|
|
|
|
#region ================== Constants
|
|
|
|
|
2020-05-18 16:14:54 +00:00
|
|
|
public const double PI = Math.PI;
|
2020-06-19 23:21:17 +00:00
|
|
|
public const double PIHALF = Math.PI * 0.5;
|
|
|
|
public const double PI2 = Math.PI * 2;
|
|
|
|
public const double PIDEG = 57.295779513082320876798154814105;
|
|
|
|
public const double SQRT2 = 1.4142135623730950488016887242097;
|
2009-04-19 18:07:22 +00:00
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region ================== Methods
|
|
|
|
|
|
|
|
// This converts doom angle to real angle
|
2020-05-18 16:14:54 +00:00
|
|
|
public static double DoomToReal(int doomangle)
|
2009-04-19 18:07:22 +00:00
|
|
|
{
|
2020-05-18 16:14:54 +00:00
|
|
|
return Math.Round(Normalized(DegToRad((doomangle + 90))), 4);
|
2009-04-19 18:07:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// This converts real angle to doom angle
|
2020-05-18 16:14:54 +00:00
|
|
|
public static int RealToDoom(double realangle)
|
2009-04-19 18:07:22 +00:00
|
|
|
{
|
|
|
|
return (int)Math.Round(RadToDeg(Normalized(realangle - PIHALF)));
|
|
|
|
}
|
|
|
|
|
|
|
|
// This converts degrees to radians
|
2020-05-18 16:14:54 +00:00
|
|
|
public static double DegToRad(double deg)
|
2009-04-19 18:07:22 +00:00
|
|
|
{
|
|
|
|
return deg / PIDEG;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This converts radians to degrees
|
2020-05-18 16:14:54 +00:00
|
|
|
public static double RadToDeg(double rad)
|
2009-04-19 18:07:22 +00:00
|
|
|
{
|
|
|
|
return rad * PIDEG;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This normalizes an angle
|
2020-05-18 16:14:54 +00:00
|
|
|
public static double Normalized(double a)
|
2009-04-19 18:07:22 +00:00
|
|
|
{
|
|
|
|
while(a < 0f) a += PI2;
|
|
|
|
while(a >= PI2) a -= PI2;
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This returns the difference between two angles
|
2020-05-18 16:14:54 +00:00
|
|
|
public static double Difference(double a, double b)
|
2009-04-19 18:07:22 +00:00
|
|
|
{
|
|
|
|
// Calculate delta angle
|
2020-05-18 16:14:54 +00:00
|
|
|
double d = Normalized(a) - Normalized(b);
|
2009-04-19 18:07:22 +00:00
|
|
|
|
|
|
|
// Make corrections for zero barrier
|
|
|
|
if(d < 0f) d += PI2;
|
|
|
|
if(d > PI) d = PI2 - d;
|
|
|
|
|
|
|
|
// Return result
|
|
|
|
return d;
|
|
|
|
}
|
2016-05-29 00:38:55 +00:00
|
|
|
|
|
|
|
//mxd. Slade 3 MathStuff::angle2DRad ripoff...
|
|
|
|
//Returns the angle between the 2d points [p1], [p2] and [p3]
|
2020-05-18 16:14:54 +00:00
|
|
|
public static double GetAngle(Vector2D p1, Vector2D p2, Vector2D p3)
|
2016-05-29 00:38:55 +00:00
|
|
|
{
|
|
|
|
// From: http://stackoverflow.com/questions/3486172/angle-between-3-points
|
|
|
|
// modified not to bother converting to degrees
|
|
|
|
Vector2D ab = new Vector2D(p2.x - p1.x, p2.y - p1.y);
|
|
|
|
Vector2D cb = new Vector2D(p2.x - p3.x, p2.y - p3.y);
|
|
|
|
|
|
|
|
// dot product
|
2020-05-18 16:14:54 +00:00
|
|
|
double dot = (ab.x * cb.x + ab.y * cb.y);
|
2016-05-29 00:38:55 +00:00
|
|
|
|
|
|
|
// length square of both vectors
|
2020-05-18 16:14:54 +00:00
|
|
|
double abSqr = ab.x * ab.x + ab.y * ab.y;
|
|
|
|
double cbSqr = cb.x * cb.x + cb.y * cb.y;
|
2016-05-29 00:38:55 +00:00
|
|
|
|
|
|
|
// square of cosine of the needed angle
|
2020-05-18 16:14:54 +00:00
|
|
|
double cosSqr = dot * dot / abSqr / cbSqr;
|
2016-05-29 00:38:55 +00:00
|
|
|
|
|
|
|
// this is a known trigonometric equality:
|
|
|
|
// cos(alpha * 2) = [ cos(alpha) ]^2 * 2 - 1
|
2020-05-18 16:14:54 +00:00
|
|
|
double cos2 = 2.0f * cosSqr - 1.0f;
|
2016-05-29 00:38:55 +00:00
|
|
|
|
|
|
|
// Here's the only invocation of the heavy function.
|
|
|
|
// It's a good idea to check explicitly if cos2 is within [-1 .. 1] range
|
2020-05-18 16:14:54 +00:00
|
|
|
double alpha2 =
|
2016-05-29 00:38:55 +00:00
|
|
|
(cos2 <= -1) ? PI :
|
2020-06-19 23:21:17 +00:00
|
|
|
(cos2 >= 1) ? 0.0 :
|
2020-05-18 16:14:54 +00:00
|
|
|
Math.Acos(cos2);
|
2016-05-29 00:38:55 +00:00
|
|
|
|
2020-06-19 23:21:17 +00:00
|
|
|
double rs = alpha2 * 0.5;
|
2016-05-29 00:38:55 +00:00
|
|
|
|
|
|
|
// Now revolve the ambiguities.
|
|
|
|
// 1. If dot product of two vectors is negative - the angle is definitely
|
|
|
|
// above 90 degrees. Still we have no information regarding the sign of the angle.
|
|
|
|
|
|
|
|
// NOTE: This ambiguity is the consequence of our method: calculating the cosine
|
|
|
|
// of the double angle. This allows us to get rid of calling sqrt.
|
|
|
|
if(dot < 0) rs = PI - rs;
|
|
|
|
|
|
|
|
// 2. Determine the sign. For this we'll use the Determinant of two vectors.
|
2020-05-18 16:14:54 +00:00
|
|
|
double det = (ab.x * cb.y - ab.y * cb.x);
|
2020-06-19 23:21:17 +00:00
|
|
|
if(det < 0) rs = (2.0 * PI) - rs;
|
2016-05-29 00:38:55 +00:00
|
|
|
|
|
|
|
return rs;
|
|
|
|
}
|
2009-04-19 18:07:22 +00:00
|
|
|
|
|
|
|
#endregion
|
|
|
|
}
|
|
|
|
}
|