Description:
Add logarithmic scale. Imperfect but does mostly work so I think it's worth merging this work from the past few weeks.
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r650:0598c83ca364 -

@@ -52,12 +52,12
52 52 private static Dictionary<LogLevel, (ConsoleColor, ConsoleColor)> mappings = new Dictionary<LogLevel, (ConsoleColor, ConsoleColor)>
53 53 {
54 54 {LogLevel.Critical, (ConsoleColor.White, ConsoleColor.Red)},
55 {LogLevel.Error, (ConsoleColor.Red, ConsoleColor.Black)},
56 {LogLevel.Warning, (ConsoleColor.Yellow, ConsoleColor.Black)},
57 {LogLevel.Success, (ConsoleColor.Green, ConsoleColor.Black)},
58 {LogLevel.Info, (ConsoleColor.Blue, ConsoleColor.Black)},
59 {LogLevel.Debug, (ConsoleColor.White, ConsoleColor.Cyan)},
60 {LogLevel.Trace, (ConsoleColor.White, ConsoleColor.Yellow)},
55 {LogLevel.Error, (ConsoleColor.Black, ConsoleColor.Red)},
56 {LogLevel.Warning, (ConsoleColor.Black, ConsoleColor.Yellow)},
57 {LogLevel.Success, (ConsoleColor.White, ConsoleColor.Green)},
58 {LogLevel.Info, (ConsoleColor.White, ConsoleColor.Blue)},
59 {LogLevel.Debug, (ConsoleColor.Blue, ConsoleColor.Black)},
60 {LogLevel.Trace, (ConsoleColor.Magenta, ConsoleColor.Black)},
61 61 {LogLevel.Spy, (ConsoleColor.Black, ConsoleColor.White)},
62 62
63 63 };
@@ -27,6 +27,7
27 27 public static bool show_upkeep = false;
28 28
29 29 public static bool always_show_zero = false;
30 public static bool logarithmic = false;
30 31
31 32 private static string[] money_series = {"Total Funds",
32 33 "Subsidies", "Upkeep", "Contracts", "Cashflow", "Misc"};
@@ -103,6 +104,38
103 104 }
104 105 }
105 106
107 public static void DrawLogrithmicLabels(ImFontPtr font, ImDrawListPtr draw_list, Num.Vector2 domain, Num.Vector2 range, bool vertical, int labels, Num.Vector2 starting_position) {
108 //We need to increment by one in order to cover the entire range.
109 //For example, if our range is 0 - 100, and we want 11 ticks, 100 / 10 gives us a spacing o 10
110 //So our 11 labels become 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100.
111 var tick_spacing = (int)Math.Abs((range.Y - range.X) / (labels - 1));
112 var tick_length = 5;
113 var tick_adjust = vertical ? new Num.Vector2(tick_length, 0) : new Num.Vector2(0, tick_length);
114
115 var tick_position = new Num.Vector2(0, range.Y);
116 var tick_absolute_position = Num.Vector2.Add(starting_position, tick_position);
117
118 for(int i = 0; i < labels; i++) {
119 var value = ScaleLogarithmic(range, domain, (int)(vertical ? tick_position.Y : tick_position.X));
120 var label = String.Format("{0}", value);
121 var height_adjust = ImGui.CalcTextSize(label).Y / 2;
122 var adjusted_position = Num.Vector2.Add(tick_absolute_position,
123 new Num.Vector2(0, -height_adjust));
124
125 draw_list.AddText(font, 11.0f, adjusted_position, (uint)ImGuiColor.BLACK, label);
126 //Logging.Info(String.Format("Drawing {0:} at {1} ({2})", label, tick_absolute_position, tick_position));
127
128 if (vertical) {
129 tick_position = new Num.Vector2(0, range.Y + ((i + 1) * tick_spacing));
130 }
131 else {
132 tick_position = new Num.Vector2(range.X + ((i + 1) * tick_spacing), 0);
133 }
134
135 tick_absolute_position = Num.Vector2.Add(starting_position, tick_position);
136 }
137 }
138
106 139 public static void DrawLine(ImDrawListPtr draw_list, Num.Vector2 c, Num.Vector2[] points, ImGuiColor col) {
107 140 var p = Num.Vector2.Zero;
108 141
@@ -125,6 +158,29
125 158 return (int) (((num - domain.X) / domain_span) * range_span + range.X);
126 159 }
127 160
161 public static float Scale(Num.Vector2 domain, Num.Vector2 range, float num) {
162 //https://stats.stackexchange.com/a/281164
163
164 if (!float.IsNaN(domain.Y - domain.X)) {
165 var domain_span = Math.Sign(domain.Y - domain.X) * Math.Max(1, Math.Abs(domain.Y - domain.X));
166 var range_span = range.Y - range.X;
167
168 var start = range.X - domain.X;
169
170 return (((num - domain.X) / domain_span) * range_span + range.X);
171 }
172 else {
173 return float.NaN;
174 }
175 }
176
177 public static float ScaleLogarithmic(Num.Vector2 domain, Num.Vector2 range, float num) {
178 var scaled_domain = new Num.Vector2((float)MathUtils.SymmetricLog10(domain.X), (float)MathUtils.SymmetricLog10(domain.Y));
179 float scaled_num = num == 0 ? 0.0f : (float)MathUtils.SymmetricLog10(num);
180
181 return Scale(scaled_domain, range, scaled_num);
182 }
183
128 184 public static Num.Vector2 adjust_domain(int domain_min, int domain_max)
129 185 {
130 186 if (domain_max == int.MinValue) {
@@ -139,6 +195,8
139 195 var domain_max_rounded = Math.Ceiling(domain_max / 50.0) * 50;
140 196 var domain_min_rounded = Math.Floor(domain_min / 50.0) * 50;
141 197
198 Logging.Info("Standard rounding.");
199
142 200 //Throw out rounding if result is too close together:
143 201 if (domain_min_rounded != domain_max_rounded) {
144 202 return new Num.Vector2((float)domain_min_rounded, (float)domain_max_rounded);
@@ -147,11 +205,14
147 205 return new Num.Vector2(domain_min, domain_max);
148 206 }
149 207
208
150 209 }
151 210 else {
152 211 var lower = MathUtils.Clamp(domain_min, 0, 100);
153 212 var upper = MathUtils.Clamp(domain_min, 10, 100);
154 213
214 Logging.Info("Clamped rounding.");
215
155 216 return new Num.Vector2(domain_min-lower, domain_max+upper);
156 217 }
157 218 }
@@ -243,8 +304,8
243 304 var range = new Num.Vector2(200 - padding, 0 + padding);
244 305
245 306 //Zero
246 var zero_point = Scale(domain, range, 0);
247 Logging.Spy(new {zero_point = zero_point});
307 var zero_point = logarithmic ? ScaleLogarithmic(domain, range, 0) : Scale(domain, range, 0);
308 // Logging.Spy(new {zero_point = zero_point});
248 309 draw_list.AddLine(Num.Vector2.Add(new Num.Vector2(padding, zero_point), c),
249 310 Num.Vector2.Add(new Num.Vector2(350, zero_point), c),
250 311 (uint)ImGuiColor.LIGHTGREY, 1.0f);
@@ -261,7 +322,7
261 322
262 323 if (data.Count() > 0 && show)
263 324 {
264 IEnumerable<int> data_array = data_sets[key].Select((p) => Scale(domain, range, (int)p));
325 IEnumerable<float> data_array = data_sets[key].Select((p) => (logarithmic ? ScaleLogarithmic(domain, range, (float)p): Scale(domain, range, (float)p)));
265 326 var data_array2 = data_array.Select((p, i) => new Num.Vector2(Scale(x_domain, x_range, i), p)).ToArray();
266 327
267 328 DrawLine(draw_list, c, data_array2, color);
@@ -270,7 +331,12
270 331 }
271 332
272 333 DrawLinearAxis(draw_list, range /*new Num.Vector2(0, 200)*/, true, 11, Num.Vector2.Add(c, new Num.Vector2(padding, padding)));
273 DrawLinearLabels(font, draw_list, domain, range /*new Num.Vector2(0, 200)*/, true, 11, c);
334 if (logarithmic) {
335 DrawLogrithmicLabels(font, draw_list, domain, range, true, 11, c);
336 }
337 else {
338 DrawLinearLabels(font, draw_list, domain, range, true, 11, c);
339 }
274 340 DrawLinearAxis(draw_list, new Num.Vector2(0, 350), false, 12, Num.Vector2.Add(c, new Num.Vector2(padding, 200 - padding)));
275 341
276 342 ImGui.Dummy(new Num.Vector2(350, 200));
@@ -314,6 +380,12
314 380 ImGui.Text("Always show zero:");
315 381 ImGui.SameLine();
316 382 ImGui.Checkbox("##AlwaysShowZero", ref always_show_zero);
383 #if DEBUG
384 ImGui.SameLine();
385 ImGui.Text("Logarithmic: ");
386 ImGui.SameLine();
387 ImGui.Checkbox("##Logarithmic", ref logarithmic);
388 #endif
317 389
318 390
319 391 #if DEBUG
@@ -185,5 +185,13
185 185 throw new EmptyArrayException("Array must not be empty");
186 186 }
187 187 }
188
189 public static float SymmetricLog10(float num) {
190 return num > 0.0f ? (float)Math.Log10(num) : -(float)Math.Log10(-num);
191 }
192
193 public static double SymmetricLog10(double num) {
194 return num > 0.0f ? Math.Log10(num) : -Math.Log10(-num);
195 }
188 196 }
189 197 }
You need to be logged in to leave comments. Login now