Fix representation of negative values

Using negative numbers should now work on both axis. For this I created two new methods calcualte_interval_tics and calculate_number_integer_digits to avoid code repetition.

I'd like to work more on this, since now the representation is correct but can look very weird for some values with a lot of empty space on the chart.
This commit is contained in:
Jorge 2021-03-17 00:05:36 +01:00
parent dde7c16989
commit e298e88231
2 changed files with 63 additions and 26 deletions

View File

@ -62,8 +62,8 @@ var x_label : String
var x_labels : Array
var y_labels : Array
var x_margin_min : int = 0
var y_margin_min : int = 0
var x_margin_min : float = 0
var y_margin_min : float = 0
# actual values of point, from the database
var point_values : Array
@ -78,9 +78,9 @@ export (String) var chart_name : String = "" setget set_chart_name
export (String, FILE, "*.txt, *.csv") var source : String = "" setget set_source
export (String) var delimiter : String = ";" setget set_delimiter
var origin_at_zero : bool = true setget set_origin_at_zero#, get_origin_at_zero
var origin_at_zero : bool = false setget set_origin_at_zero#, get_origin_at_zero
var are_values_columns : bool = false setget set_are_values_columns#, get_are_values_columns
var show_x_values_as_labels : bool = true setget set_show_x_values_as_labels#, get_show_x_values_as_labels
var show_x_values_as_labels : bool = false setget set_show_x_values_as_labels#, get_show_x_values_as_labels
var labels_index : int = 0 setget set_labels_index#, get_labels_index
var function_names_index : int = 0 setget set_function_names_index#, get_function_names_index
@ -94,7 +94,7 @@ var column_gap : float = 2 setget set_column_gap
# Calculations of decim and its relation with number of tics: https://www.desmos.com/calculator/jeiceaswiy
var full_scale : float = 1.0 setget set_full_scale
var x_decim : float = 5.0 setget set_x_decim
var x_decim : float = 1.0 setget set_x_decim
var y_decim : float = 1.0 setget set_y_decim
var points_shape : Array = [PointShapes.Dot] setget set_points_shape

View File

@ -454,7 +454,7 @@ func calculate_range(id):
x_domain[0][function] = x_datas[function].min()
x_domain[1][function] = x_datas[function].max()
func calculate_tics():
y_chors.clear()
@ -469,28 +469,37 @@ func calculate_tics():
y_margin_min = y_range[0]
var y_margin_max = y_range[1]
v_dist = y_decim * pow(10.0, str(y_margin_max).split(".")[0].length() - 1)
var multi = 0
var p = (v_dist * multi) + y_margin_min
y_chors.append(p as String)
while p < y_margin_max:
multi += 1
p = (v_dist * multi) + y_margin_min
y_chors.append(p as String)
v_dist = y_decim * pow(10.0, calculate_number_integer_digits(max(abs(y_margin_max), abs(y_margin_min))) - 1)
# There are three cases of min/max:
# For +/+ and -/- we just do the usual and draw tics from min to max
# But for the -/+ we do in two times to force the 0 to appear so it is
# easier to read. Then we draw the negative from 0 to min and the positives
# from 0 to max without drawing the 0 again
if y_margin_min < 0 and y_margin_max >= 0:
calculate_interval_tics(0, y_margin_min, -v_dist, y_chors) #Negative tics
calculate_interval_tics(0, y_margin_max, v_dist, y_chors, false) #Positive tics
y_chors.sort()
y_margin_min = min(y_margin_min, y_chors[0])
else:
calculate_interval_tics(y_margin_min, y_margin_max, v_dist, y_chors)
for i in y_chors.size():
y_chors[i] = String(y_chors[i]) #Can't cast directly on calculate_interval_tics because it mess up with the sorting
x_margin_min = x_range[0]
var x_margin_max = x_range[1]
if not show_x_values_as_labels:
h_dist = x_decim * pow(10.0, str(x_margin_max).split(".")[0].length() - 1)
multi = 0
p = (h_dist * multi) + x_margin_min
x_labels.append(p as String)
while p < x_margin_max:
multi += 1
p = (h_dist * multi) + x_margin_min
x_labels.append(p as String)
if not show_x_values_as_labels:
h_dist = x_decim * pow(10.0, calculate_number_integer_digits(max(abs(x_margin_max), abs(x_margin_min))) - 1)
if x_margin_min < 0 and x_margin_max >= 0:
calculate_interval_tics(0, x_margin_min, -h_dist, x_labels) #Negative tics
calculate_interval_tics(0, x_margin_max, h_dist, x_labels, false) #Positive tics
x_labels.sort()
x_margin_min = min(x_margin_min, x_labels[0])
else:
calculate_interval_tics(x_margin_min, x_margin_max, h_dist, x_labels)
for i in x_labels.size():
x_labels[i] = String(x_labels[i])
x_chors = x_labels
else:
for function in y_labels.size():
@ -500,7 +509,8 @@ func calculate_tics():
func build_chart():
OFFSET.x = str(y_range[1]).length() * font_size
#TODO: Still needs improving (for example 0.000001 vS 10 should pick the former)
OFFSET.x = str(max(abs(y_range[0]), abs(y_range[1]))).length() * font_size
OFFSET.y = font_size * 2
SIZE = get_size() - Vector2(OFFSET.x, 0)
@ -514,7 +524,7 @@ func count_functions():
func calculate_pass():
# Calculate distance in pixel between 2 consecutive values/datas
x_pass = (SIZE.x - OFFSET.x) / (x_chors.size() - 1 if x_chors.size() > 1 else x_chors.size())
y_pass = (origin.y - ChartName.get_rect().size.y * 2) / (y_chors.size() - 1)
y_pass = (origin.y - ChartName.get_rect().size.y * 2) / (y_chors.size() - 1 if y_chors.size() > 1 else y_chors.size())
func calculate_coordinates():
@ -593,3 +603,30 @@ func draw_treshold():
draw_line(Vector2(origin.x, treshold_draw.y), Vector2(SIZE.x, treshold_draw.y), Color.red, 0.4, true)
if treshold.x != 0:
draw_line(Vector2(treshold_draw.x, 0), Vector2(treshold_draw.x, SIZE.y - OFFSET.y), Color.red, 0.4, true)
func calculate_number_integer_digits(number):
var digits = str(number).split(".")[0].length()
if number < 0: #the '-' char doesn't count as digit
digits -= 1
return digits
func calculate_interval_tics(v_from:float, v_to:float, dist:float, chords:Array, include_first := true):
# Appends to array chords the tics calculated between v_from and v_to with
# a given distance between tics.
#include_first is used to tell if v_from should be appended or ignored
var multi = 0
var p = (dist * multi) + v_from
var missing_tics = p < v_to if dist > 0 else p > v_to
if include_first:
chords.append(p)
while missing_tics:
multi += 1
p = (dist * multi) + v_from
missing_tics = p < v_to if dist > 0 else p > v_to
chords.append(p)