source: 2014/24/EemeliK/Zombieland/Jypeli/AdvanceMath/MathHelper.cs @ 5974

Revision 5974, 13.6 KB checked in by empaheik, 4 years ago (diff)
Line 
1#region MIT License
2/*
3 * Copyright (c) 2005-2008 Jonathan Mark Porter. http://physics2d.googlepages.com/
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
17 * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#endregion
23
24
25
26
27#if UseDouble
28using Scalar = System.Double;
29#else
30using Scalar = System.Single;
31#endif
32using System;
33
34
35namespace AdvanceMath
36{
37    public static class MathHelper
38    {
39        #region consts
40        public const Scalar E = (Scalar)System.Math.E;
41        public const Scalar Pi = (Scalar)System.Math.PI;
42        public const Scalar TwoPi = (Scalar)(System.Math.PI * 2);
43        public const Scalar PiOver2 = (Scalar)(System.Math.PI / 2);
44        public const Scalar PiOver4 = (Scalar)(System.Math.PI / 4);
45        public const Scalar ThreePiOver2 = (Scalar)((3 * System.Math.PI) / 2);
46        public const Scalar RadiansPerDegree = (Scalar)(System.Math.PI / 180);
47        public const Scalar DegreesPerRadian = (Scalar)(180 / System.Math.PI);
48        public const Scalar Tolerance = 0.000000001f;
49
50        public const Scalar Epsilon = 1e-03f;
51
52        internal static Scalar Two = 2;
53        #endregion
54        #region methods
55
56        public static Scalar Lerp(Scalar left, Scalar right, Scalar amount)
57        {
58            return (right - left) * amount + left;
59        }
60        public static void Lerp(ref Scalar left, ref  Scalar right, ref  Scalar amount, out Scalar result)
61        {
62            result = (right - left) * amount + left;
63        }
64
65        public static Scalar CatmullRom(Scalar value1, Scalar value2, Scalar value3, Scalar value4, Scalar amount)
66        {
67            Scalar amountSq = amount * amount;
68            Scalar amountCu = amountSq * amount;
69            return
70                0.5f * ((2 * value2) +
71                (-value1 + value3) * amount +
72                (2 * value1 - 5 * value2 + 4 * value3 - value4) * amountSq +
73                (-value1 + 3 * value2 - 3 * value3 + value4) * amountCu);
74        }
75        public static void CatmullRom(ref Scalar value1, ref Scalar value2, ref Scalar value3, ref Scalar value4, Scalar amount, out Scalar result)
76        {
77            Scalar amountSq = amount * amount;
78            Scalar amountCu = amountSq * amount;
79            result =
80                0.5f * ((2 * value2) +
81                (-value1 + value3) * amount +
82                (2 * value1 - 5 * value2 + 4 * value3 - value4) * amountSq +
83                (-value1 + 3 * value2 - 3 * value3 + value4) * amountCu);
84        }
85
86        internal static void HermiteHelper(Scalar amount, out Scalar h1, out Scalar h2, out Scalar h3, out Scalar h4)
87        {
88            Scalar wf2 = amount * amount;
89            Scalar wf3 = wf2 * amount;
90            Scalar wf3t2 = 2 * wf3;
91            Scalar wf2t3 = 3 * wf2;
92            h1 = wf3t2 - wf2t3 + 1;
93            h2 = wf2t3 - wf3t2;
94            h3 = wf3 - 2 * wf2 + amount;
95            h4 = wf3 - wf2;
96        }
97        public static Scalar Hermite(Scalar value1, Scalar tangent1, Scalar value2, Scalar tangent2, Scalar amount)
98        {
99            Scalar result;
100            Hermite(ref value1, ref tangent1, ref value2, ref tangent2, amount, out result);
101            return result;
102        }
103        public static void Hermite(ref  Scalar value1, ref Scalar tangent1, ref Scalar value2, ref Scalar tangent2, Scalar amount, out Scalar result)
104        {
105            Scalar h1, h2, h3, h4;
106            MathHelper.HermiteHelper(amount, out h1, out h2, out h3, out h4);
107            result = h1 * value1 + h2 * value2 + h3 * tangent1 + h4 * tangent2;
108        }
109
110
111        public static Scalar Clamp(Scalar value, Scalar min, Scalar max)
112        {
113            return (value < min) ? (min) : ((value > max) ? (max) : (value));
114        }
115        public static void Clamp(ref Scalar value, ref Scalar min, ref Scalar max, out Scalar result)
116        {
117            result = (value < min) ? (min) : ((value > max) ? (max) : (value));
118        }
119
120
121        public static void Sort(Scalar value1, Scalar value2, out Scalar max, out Scalar min)
122        {
123            if (value1 > value2)
124            {
125                max = value1;
126                min = value2;
127            }
128            else
129            {
130                max = value2;
131                min = value1;
132            }
133        }
134
135
136        /// <summary>
137        /// Clamps a value between 2 values, but wraps the value around. So that one plus max would result in one plus min.
138        /// </summary>
139        /// <param name="value">the value to clamp</param>
140        /// <param name="min">the minimum value</param>
141        /// <param name="max">the maximum value</param>
142        /// <returns>the clamped result</returns>
143        public static Scalar WrapClamp(Scalar value, Scalar min, Scalar max)
144        {
145            if (min <= value && value < max) { return value; }
146            Scalar rem = (value - min) % (max - min);
147            return rem + ((rem < 0) ? (max) : (min));
148        }
149        /// <summary>
150        /// Clamps a value between 2 values, but wraps the value around. So that one plus max would result in one plus min.
151        /// </summary>
152        /// <param name="value">the value to clamp</param>
153        /// <param name="min">the minimum value</param>
154        /// <param name="max">the maximum value</param>
155        /// <param name="result">the clamped result</param>
156        public static void WrapClamp(ref Scalar value, ref Scalar min, ref Scalar max, out Scalar result)
157        {
158            if (min <= value && value < max) { result = value; return; }
159            Scalar rem = (value - min) % (max - min);
160            result = rem + ((rem < 0) ? (max) : (min));
161        }
162
163
164        public static Scalar ClampAngle(Scalar angle)
165        {
166            if (-Pi <= angle && angle < Pi) { return angle; }
167            Scalar rem = (angle + Pi) % (TwoPi);
168            return rem + ((rem < 0) ? (Pi) : (-Pi));
169        }
170        [CLSCompliant(false)]
171        public static void ClampAngle(ref Scalar angle)
172        {
173            if (-Pi <= angle && angle < Pi) { return; }
174            Scalar rem = (angle + Pi) % (TwoPi);
175            angle = rem + ((rem < 0) ? (Pi) : (-Pi));
176        }
177        public static void ClampAngle(ref Scalar angle, out Scalar result)
178        {
179            if (-Pi <= angle && angle < Pi) { result = angle; return; }
180            Scalar rem = (angle + Pi) % (TwoPi);
181            result = rem + ((rem < 0) ? (Pi) : (-Pi));
182        }
183
184        public static Scalar AngleSubtract(Scalar angle1, Scalar angle2)
185        {
186            return ClampAngle(angle1 - angle2);
187        }
188        public static void AngleSubtract(ref Scalar angle1, ref  Scalar angle2, out Scalar result)
189        {
190            result = angle1 - angle2;
191            ClampAngle(ref result);
192        }
193
194        /// <summary>
195        /// Trys to Solve for x in the equation: (a * (x * x) + b * x + c == 0)
196        /// </summary>
197        /// <param name="a"></param>
198        /// <param name="b"></param>
199        /// <param name="c"></param>
200        /// <param name="plus">The result of (b + Math.Sqrt((b * b) - (4 * a * c))) / (2 * a)</param>
201        /// <param name="minus">The result of (b - Math.Sqrt((b * b) - (4 * a * c))) / (2 * a)</param>
202        /// <returns><see langword="false" /> if an error would have been thrown; otherwise <see langword="true" />.</returns>
203        public static bool TrySolveQuadratic(Scalar a, Scalar b, Scalar c, out Scalar plus, out Scalar minus)
204        {
205            if (0 == a)
206            {
207                plus = -c / b;
208                minus = plus;
209                return true;
210            }
211            c = (b * b) - (4 * a * c);
212            if (0 <= c)
213            {
214                c = Sqrt(c);
215                a = .5f / a;
216                plus = ((c - b) * a);
217                minus = ((-c - b) * a);
218                return true;
219            }
220            plus = 0;
221            minus = 0;
222            return false;
223        }
224        public static Scalar InvSqrt(Scalar number)
225        {
226            return 1 / Sqrt(number);
227        }
228
229        public static Scalar Max(params Scalar[] vals)
230        {
231            if (vals == null) { throw new ArgumentNullException("vals"); }
232            if (vals.Length == 0) { throw new ArgumentException("There must be at least one value to compare", "vals"); }
233            Scalar max = vals[0];
234            if (Scalar.IsNaN(max)) { return max; }
235            for (int i = 1; i < vals.Length; i++)
236            {
237                Scalar val = vals[i];
238                if (val > max) { max = val; }
239                else if (Scalar.IsNaN(val)) { return val; }
240            }
241            return max;
242        }
243        public static Scalar Min(params Scalar[] vals)
244        {
245            if (vals == null) { throw new ArgumentNullException("vals"); }
246            if (vals.Length == 0) { throw new ArgumentException("There must be at least one value to compare", "vals"); }
247            Scalar min = vals[0];
248            if (Scalar.IsNaN(min)) { return min; }
249            for (int i = 1; i < vals.Length; i++)
250            {
251                Scalar val = vals[i];
252                if (val < min) { min = val; }
253                else if (Scalar.IsNaN(val)) { return val; }
254            }
255            return min;
256        }
257
258        public static bool PointInTri2D(Vector2D point, Vector2D a, Vector2D b, Vector2D c)
259        {
260            Vector2D vect1, vect2;
261            Scalar temp;
262            Vector2D.Subtract(ref b, ref a, out vect1);
263            Vector2D.Subtract(ref point, ref b, out vect2);
264            Vector2D.ZCross(ref vect1, ref vect2, out temp);
265            bool bClockwise = temp >= 0;
266            Vector2D.Subtract(ref c, ref b, out vect1);
267            Vector2D.Subtract(ref point, ref c, out vect2);
268            Vector2D.ZCross(ref vect1, ref vect2, out temp);
269            if (temp < 0 ^ bClockwise) { return true; }
270            Vector2D.Subtract(ref a, ref c, out vect1);
271            Vector2D.Subtract(ref point, ref a, out vect2);
272            Vector2D.ZCross(ref vect1, ref vect2, out temp);
273            return temp < 0 ^ bClockwise;
274
275            /* bool bClockwise = (((b - a) ^ (point - b)) >= 0);
276             return !(((((c - b) ^ (point - c)) >= 0) ^ bClockwise) && ((((a - c) ^ (point - a)) >= 0) ^ bClockwise));*/
277        }
278        /// <summary>
279        ///             Converts degrees to radians.
280        /// </summary>
281        /// <param name="degrees"></param>
282        /// <returns></returns>
283        public static Scalar ToRadians(Scalar degrees)
284        {
285            return degrees * RadiansPerDegree;
286        }
287        /// <summary>
288        ///             Converts radians to degrees.
289        /// </summary>
290        /// <param name="radians"></param>
291        /// <returns></returns>
292        public static Scalar ToDegrees(Scalar radians)
293        {
294            return radians * DegreesPerRadian;
295        }
296
297        #region System.Math Methods
298        public static Scalar Acos(Scalar d) { return (Scalar)Math.Acos(d); }
299        public static Scalar Asin(Scalar d) { return (Scalar)Math.Asin(d); }
300        public static Scalar Atan(Scalar d) { return (Scalar)Math.Atan(d); }
301        public static Scalar Atan2(Scalar y, Scalar x) { return (Scalar)Math.Atan2(y, x); }
302        public static Scalar Ceiling(Scalar a) { return (Scalar)Math.Ceiling(a); }
303        public static Scalar Cos(Scalar d) { return (Scalar)Math.Cos(d); }
304        public static Scalar Cosh(Scalar value) { return (Scalar)Math.Cosh(value); }
305        public static Scalar Exp(Scalar d) { return (Scalar)Math.Exp(d); }
306        public static Scalar Floor(Scalar d) { return (Scalar)Math.Floor(d); }
307        public static Scalar IEEERemainder(Scalar x, Scalar y) { return (Scalar)Math.IEEERemainder(x, y); }
308        public static Scalar Log(Scalar d) { return (Scalar)Math.Log(d); }
309        public static Scalar Log10(Scalar d) { return (Scalar)Math.Log10(d); }
310        public static Scalar Pow(Scalar x, Scalar y) { return (Scalar)Math.Pow(x, y); }
311        public static Scalar Round(Scalar a) { return (Scalar)Math.Round(a); }
312        public static Scalar Round(Scalar value, int digits) { return (Scalar)Math.Round(value, digits); }
313        public static Scalar Sin(Scalar a) { return (Scalar)Math.Sin(a); }
314        public static Scalar Sinh(Scalar value) { return (Scalar)Math.Sinh(value); }
315        public static Scalar Sqrt(Scalar d) { return (Scalar)Math.Sqrt(d); }
316        public static Scalar Tan(Scalar a) { return (Scalar)Math.Tan(a); }
317        public static Scalar Tanh(Scalar value) { return (Scalar)Math.Tanh(value); }
318        #endregion
319
320
321        #endregion
322    }
323}
Note: See TracBrowser for help on using the repository browser.