-
Notifications
You must be signed in to change notification settings - Fork 244
Expand file tree
/
Copy pathkosMath.cs
More file actions
173 lines (154 loc) · 6.78 KB
/
Copy pathkosMath.cs
File metadata and controls
173 lines (154 loc) · 6.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
using System;
using System.Collections.Generic;
namespace kOS.Safe.Utilities
{
public static class KOSMath
{
public static float Clamp(float input, float low, float high)
{
return (input > high ? high : (input < low ? low : input));
}
public static double Clamp(double input, double low, double high)
{
return (input > high ? high : (input < low ? low : input));
}
public static double? Clamp(double? input, double low, double high)
{
if (!input.HasValue)
{
return null;
}
return Clamp(input.Value, low, high);
}
public static float? Clamp(float? input, float low, float high)
{
if (!input.HasValue)
{
return null;
}
return Clamp(input.Value, low, high);
}
/// <summary>
/// Round the value to the nearest allowed value.
/// if the slider starts at min, ends at max, and has detents every inc.
/// </summary>
/// <param name="val">value to round</param>
/// <param name="min">minimum allowed value</param>
/// <param name="max">maximum allowed value</param>
/// <param name="increment">increment of the detents</param>
/// <returns></returns>
public static double ClampToIndent(double val, double min, double max, double increment)
{
// First clamp the value to within min/max:
double outVal = System.Math.Max(min, System.Math.Min(val, max));
// How many discrete increments up the slider gets us to the nearest detent less than or equal to the value:
var numIncs = (int)System.Math.Floor((outVal-min)/increment);
// get detent values just below and above the value:
double nearUnder = min + (numIncs*increment);
double nearOver = min + ((numIncs+1)*increment);
// pick which one to round to:
double remainder = outVal - nearUnder;
if (remainder >= (increment/2f) && nearOver <= max)
outVal = nearOver;
else
outVal = nearUnder;
return outVal;
}
/// <summary>
/// Round the value to the nearest allowed value.
/// if the slider starts at min, ends at max, and has detents every inc.
/// </summary>
/// <param name="val">value to round</param>
/// <param name="min">minimum allowed value</param>
/// <param name="max">maximum allowed value</param>
/// <param name="increment">increment of the detents</param>
/// <returns></returns>
public static float ClampToIndent(float val, float min, float max, float increment)
{
// First clamp the value to within min/max:
float outVal = System.Math.Max(min, System.Math.Min(val, max));
// How many discrete increments up the slider gets us to the nearest detent less than or equal to the value:
var numIncs = (long)System.Math.Floor((outVal-min)/increment);
// get detent values just below and above the value:
float nearUnder = min + (numIncs*increment);
float nearOver = min + ((numIncs+1)*increment);
// pick which one to round to:
float remainder = outVal - nearUnder;
if (remainder >= (increment/2f) && nearOver <= max)
outVal = nearOver;
else
outVal = nearUnder;
return outVal;
}
/// <summary>
/// Fix the strange too-large or too-small angle degrees that are sometimes
/// returned by KSP, normalizing them into a constrained 360 degree range.
/// </summary>
/// <param name="inAngle">input angle in degrees</param>
/// <param name="rangeStart">
/// Bottom of 360 degree range to normalize to.
/// ( 0 means the range [0..360]), while -180 means [-180,180] )
/// </param>
/// <returns>the same angle, normalized to the range given.</returns>
public static double DegreeFix(double inAngle, double rangeStart)
{
double rangeEnd = rangeStart + 360.0;
double outAngle = inAngle;
while (outAngle > rangeEnd)
outAngle -= 360.0;
while (outAngle < rangeStart)
outAngle += 360.0;
return outAngle;
}
private static Dictionary<string, System.Random> randomizers = null;
/// <summary>
/// Begin a new random number sequence from an integer seed, giving it
/// a string key to refer to later in GetRandom.
/// </summary>
/// <param name="key"></param>
/// <param name="seed">If null, no seed is given and it does the default seed</param>
public static void StartRandomFromSeed(string key, int? seed)
{
if (randomizers == null)
randomizers = new Dictionary<string, Random>(StringComparer.OrdinalIgnoreCase);
if (!randomizers.ContainsKey(key))
randomizers.Add(key, null);
randomizers[key] = (seed == null ? new Random() : new System.Random(seed.Value));
}
/// <summary>
/// Get the next number from a random number sequence given its string key
/// you gave it in StartRandomFromSeed()
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static double GetRandom(string key)
{
if (randomizers == null)
randomizers = new Dictionary<string, Random>(StringComparer.OrdinalIgnoreCase);
if (!randomizers.ContainsKey(key))
randomizers.Add(key, new Random());
return randomizers[key].NextDouble();
}
/// <summary>
/// Get the number of decimal digits in a number. i.e. if input = 33333, return a 5.
/// </summary>
/// <param name="val"></param>
/// <returns></returns>
public static int DecimalDigitsIn(int val)
{
int absVal = val < 0 ? -val : val;
// Believe it or not, a basic hardcoded if-else chain is actually the fastest performance
// when you know the numbers aren't allowed to be large (have to fit in int32):
if (absVal < 10) return 1;
if (absVal < 100) return 2;
if (absVal < 1000) return 3;
if (absVal < 10000) return 4;
if (absVal < 100000) return 5;
if (absVal < 1000000) return 6;
if (absVal < 10000000) return 7;
if (absVal < 100000000) return 8;
if (absVal < 1000000000) return 9;
return 10;
}
}
}