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 private static Dictionary<LogLevel, (ConsoleColor, ConsoleColor)> mappings = new Dictionary<LogLevel, (ConsoleColor, ConsoleColor)>
52 private static Dictionary<LogLevel, (ConsoleColor, ConsoleColor)> mappings = new Dictionary<LogLevel, (ConsoleColor, ConsoleColor)>
53 {
53 {
54 {LogLevel.Critical, (ConsoleColor.White, ConsoleColor.Red)},
54 {LogLevel.Critical, (ConsoleColor.White, ConsoleColor.Red)},
55 {LogLevel.Error, (ConsoleColor.Red, ConsoleColor.Black)},
55 {LogLevel.Error, (ConsoleColor.Black, ConsoleColor.Red)},
56 {LogLevel.Warning, (ConsoleColor.Yellow, ConsoleColor.Black)},
56 {LogLevel.Warning, (ConsoleColor.Black, ConsoleColor.Yellow)},
57 {LogLevel.Success, (ConsoleColor.Green, ConsoleColor.Black)},
57 {LogLevel.Success, (ConsoleColor.White, ConsoleColor.Green)},
58 {LogLevel.Info, (ConsoleColor.Blue, ConsoleColor.Black)},
58 {LogLevel.Info, (ConsoleColor.White, ConsoleColor.Blue)},
59 {LogLevel.Debug, (ConsoleColor.White, ConsoleColor.Cyan)},
59 {LogLevel.Debug, (ConsoleColor.Blue, ConsoleColor.Black)},
60 {LogLevel.Trace, (ConsoleColor.White, ConsoleColor.Yellow)},
60 {LogLevel.Trace, (ConsoleColor.Magenta, ConsoleColor.Black)},
61 {LogLevel.Spy, (ConsoleColor.Black, ConsoleColor.White)},
61 {LogLevel.Spy, (ConsoleColor.Black, ConsoleColor.White)},
62
62
63 };
63 };
@@ -27,6 +27,7
27 public static bool show_upkeep = false;
27 public static bool show_upkeep = false;
28
28
29 public static bool always_show_zero = false;
29 public static bool always_show_zero = false;
30 public static bool logarithmic = false;
30
31
31 private static string[] money_series = {"Total Funds",
32 private static string[] money_series = {"Total Funds",
32 "Subsidies", "Upkeep", "Contracts", "Cashflow", "Misc"};
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 public static void DrawLine(ImDrawListPtr draw_list, Num.Vector2 c, Num.Vector2[] points, ImGuiColor col) {
139 public static void DrawLine(ImDrawListPtr draw_list, Num.Vector2 c, Num.Vector2[] points, ImGuiColor col) {
107 var p = Num.Vector2.Zero;
140 var p = Num.Vector2.Zero;
108
141
@@ -125,6 +158,29
125 return (int) (((num - domain.X) / domain_span) * range_span + range.X);
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 public static Num.Vector2 adjust_domain(int domain_min, int domain_max)
184 public static Num.Vector2 adjust_domain(int domain_min, int domain_max)
129 {
185 {
130 if (domain_max == int.MinValue) {
186 if (domain_max == int.MinValue) {
@@ -139,6 +195,8
139 var domain_max_rounded = Math.Ceiling(domain_max / 50.0) * 50;
195 var domain_max_rounded = Math.Ceiling(domain_max / 50.0) * 50;
140 var domain_min_rounded = Math.Floor(domain_min / 50.0) * 50;
196 var domain_min_rounded = Math.Floor(domain_min / 50.0) * 50;
141
197
198 Logging.Info("Standard rounding.");
199
142 //Throw out rounding if result is too close together:
200 //Throw out rounding if result is too close together:
143 if (domain_min_rounded != domain_max_rounded) {
201 if (domain_min_rounded != domain_max_rounded) {
144 return new Num.Vector2((float)domain_min_rounded, (float)domain_max_rounded);
202 return new Num.Vector2((float)domain_min_rounded, (float)domain_max_rounded);
@@ -147,11 +205,14
147 return new Num.Vector2(domain_min, domain_max);
205 return new Num.Vector2(domain_min, domain_max);
148 }
206 }
149
207
208
150 }
209 }
151 else {
210 else {
152 var lower = MathUtils.Clamp(domain_min, 0, 100);
211 var lower = MathUtils.Clamp(domain_min, 0, 100);
153 var upper = MathUtils.Clamp(domain_min, 10, 100);
212 var upper = MathUtils.Clamp(domain_min, 10, 100);
154
213
214 Logging.Info("Clamped rounding.");
215
155 return new Num.Vector2(domain_min-lower, domain_max+upper);
216 return new Num.Vector2(domain_min-lower, domain_max+upper);
156 }
217 }
157 }
218 }
@@ -243,8 +304,8
243 var range = new Num.Vector2(200 - padding, 0 + padding);
304 var range = new Num.Vector2(200 - padding, 0 + padding);
244
305
245 //Zero
306 //Zero
246 var zero_point = Scale(domain, range, 0);
307 var zero_point = logarithmic ? ScaleLogarithmic(domain, range, 0) : Scale(domain, range, 0);
247 Logging.Spy(new {zero_point = zero_point});
308 // Logging.Spy(new {zero_point = zero_point});
248 draw_list.AddLine(Num.Vector2.Add(new Num.Vector2(padding, zero_point), c),
309 draw_list.AddLine(Num.Vector2.Add(new Num.Vector2(padding, zero_point), c),
249 Num.Vector2.Add(new Num.Vector2(350, zero_point), c),
310 Num.Vector2.Add(new Num.Vector2(350, zero_point), c),
250 (uint)ImGuiColor.LIGHTGREY, 1.0f);
311 (uint)ImGuiColor.LIGHTGREY, 1.0f);
@@ -261,7 +322,7
261
322
262 if (data.Count() > 0 && show)
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 var data_array2 = data_array.Select((p, i) => new Num.Vector2(Scale(x_domain, x_range, i), p)).ToArray();
326 var data_array2 = data_array.Select((p, i) => new Num.Vector2(Scale(x_domain, x_range, i), p)).ToArray();
266
327
267 DrawLine(draw_list, c, data_array2, color);
328 DrawLine(draw_list, c, data_array2, color);
@@ -270,7 +331,12
270 }
331 }
271
332
272 DrawLinearAxis(draw_list, range /*new Num.Vector2(0, 200)*/, true, 11, Num.Vector2.Add(c, new Num.Vector2(padding, padding)));
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 DrawLinearAxis(draw_list, new Num.Vector2(0, 350), false, 12, Num.Vector2.Add(c, new Num.Vector2(padding, 200 - padding)));
340 DrawLinearAxis(draw_list, new Num.Vector2(0, 350), false, 12, Num.Vector2.Add(c, new Num.Vector2(padding, 200 - padding)));
275
341
276 ImGui.Dummy(new Num.Vector2(350, 200));
342 ImGui.Dummy(new Num.Vector2(350, 200));
@@ -314,6 +380,12
314 ImGui.Text("Always show zero:");
380 ImGui.Text("Always show zero:");
315 ImGui.SameLine();
381 ImGui.SameLine();
316 ImGui.Checkbox("##AlwaysShowZero", ref always_show_zero);
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 #if DEBUG
391 #if DEBUG
@@ -185,5 +185,13
185 throw new EmptyArrayException("Array must not be empty");
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