From 5b97c528feb66e18d5742e841b7aa958c48be1fc Mon Sep 17 00:00:00 2001 From: Jorge <63685920+JFerrerBeired@users.noreply.github.com> Date: Thu, 25 Feb 2021 21:57:05 +0100 Subject: [PATCH] Refactor so it works with the new data format. Restructured some functions in smaller pieces and changed it so they can work with data in the new format. Main way to use it will be with the new plot_function but old functions support is requiered through structure_datas (WIP) --- .../Utilities/Scripts/scatter_chart_base.gd | 158 ++++++++++-------- 1 file changed, 87 insertions(+), 71 deletions(-) diff --git a/addons/easy_charts/Utilities/Scripts/scatter_chart_base.gd b/addons/easy_charts/Utilities/Scripts/scatter_chart_base.gd index 074037f..0d4a79c 100644 --- a/addons/easy_charts/Utilities/Scripts/scatter_chart_base.gd +++ b/addons/easy_charts/Utilities/Scripts/scatter_chart_base.gd @@ -6,6 +6,15 @@ class_name ScatterChartBase # of points in a two-variable space. It handles basic data structure and grid # layout and leaves to child classes the more specific behaviour. +var identifiers : Array + +#Stored in the form of [[min_func1, min_func2, min_func3, ...], [max_func1, max_func2, ...]] +var x_domain := [[], []] +var y_domain := [[], []] + +var x_range +var y_range + var property_list = [ # Chart Properties { @@ -142,6 +151,22 @@ var property_list = [ ] +func plot_function(x:Array, y:Array, id=""): + pass + + +func update_function(x:Array, y:Array, id=""): + pass + + +func delete_function(id): + pass + + +func generate_identifier(): + return "f%d" % (identifiers.size() + 1) + + func structure_datas(database : Array): # @labels_index can be either a column or a row relative to x values # @y_values can be either a column or a row relative to y values @@ -181,18 +206,27 @@ func structure_datas(database : Array): for value in data.size(): data[value] = data[value] as float - # draw y labels - var to_order : Array - var to_order_min : Array - for cluster in y_datas.size(): - # define x_chors and y_chors - var margin_max = y_datas[cluster].max() - var margin_min = y_datas[cluster].min() - to_order.append(margin_max) - to_order_min.append(margin_min) - var y_margin_max = to_order.max() - y_margin_min = to_order_min.min() if not origin_at_zero else 0 +func calculate_range(id): + # Calculate the domain of the given function in the x and y axis + # and updates the range value + + var function = identifiers.find(id) + + y_domain[0][function] = y_datas[function].min() + y_domain[1][function] = y_datas[function].max() + + x_domain[0][function] = x_datas[function].min() + x_domain[1][function] = x_datas[function].max() + + # Chose the min/max from each function + y_range = [y_domain[0].min() if not origin_at_zero else 0, y_domain[1].max()] + x_range = [x_domain[0].min() if not origin_at_zero else 0, x_domain[1].max()] + + +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 @@ -202,11 +236,8 @@ func structure_datas(database : Array): p = (v_dist * multi) + y_margin_min y_chors.append(p as String) - # draw x_labels - to_order.clear() - to_order = x_datas - var x_margin_max = to_order.max() - x_margin_min = to_order.min() if not origin_at_zero else 0 + 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 @@ -216,87 +247,72 @@ func structure_datas(database : Array): multi += 1 p = (h_dist * multi) + x_margin_min x_labels.append(p as String) - - OFFSET.x = str(y_margin_max).length() * font_size - OFFSET.y = font_size * 2 + + if not show_x_values_as_labels: + x_chors = x_labels + else: + for function in identifiers.size(): + for value in x_datas[function]: + if not x_chors.has(value as String): #Don't append repeated values + x_chors.append(value as String) func build_chart(): SIZE = get_size() - Vector2(OFFSET.x, 0) origin = Vector2(OFFSET.x, SIZE.y - OFFSET.y) + + OFFSET.x = str(y_range[1]).length() * font_size + OFFSET.y = font_size * 2 func calculate_pass(): - if show_x_values_as_labels: - x_chors = x_datas.duplicate(true) as PoolStringArray - else: - x_chors = x_labels - - # calculate distance in pixel between 2 consecutive values/datas + # 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) func calculate_coordinates(): - x_coordinates.clear() - y_coordinates.clear() point_values.clear() point_positions.clear() + point_values.resize(identifiers.size()) + point_positions.resize(identifiers.size()) - for cluster in y_datas: - var single_coordinates : Array - for value in cluster.size(): - single_coordinates.append((cluster[value] - y_margin_min) * y_pass / v_dist) - y_coordinates.append(single_coordinates) + for function in identifiers.size(): + for val in function.size(): + var value_x = (x_datas[function][val] - x_margin_min) * x_pass / h_dist + var value_y = (y_datas[function][val] - y_margin_min) * y_pass / v_dist - if show_x_values_as_labels: - for x in x_datas.size(): - x_coordinates.append(x_pass * x) - else: - for x in x_datas.size(): - x_coordinates.append((x_datas[x] - x_margin_min) * x_pass / h_dist) - - for f in functions: - point_values.append([]) - point_positions.append([]) - - for cluster in y_coordinates.size(): - for y in y_coordinates[cluster].size(): - if are_values_columns: - point_values[y].append([x_datas[cluster], y_datas[cluster][y]]) - point_positions[y].append(Vector2(x_coordinates[cluster] + origin.x, - origin.y - y_coordinates[cluster][y])) - else: - point_values[cluster].append([x_datas[y], y_datas[cluster][y]]) - point_positions[cluster].append(Vector2(x_coordinates[y] + origin.x, - origin.y - y_coordinates[cluster][y])) + point_values[function].append([x_datas[function][val], y_datas[function][val]]) + point_positions[function].append(Vector2(value_x + origin.x, origin.y - value_y)) func draw_grid(): # ascisse for p in x_chors.size(): - var point : Vector2 = origin+Vector2((p)*x_pass,0) + var point : Vector2 = origin + Vector2(p * x_pass, 0) # v grid - draw_line(point,point-Vector2(0,SIZE.y-OFFSET.y),v_lines_color,0.2,true) + draw_line(point, -Vector2(0, SIZE.y - OFFSET.y), v_lines_color, 0.2, true) # ascisse - draw_line(point-Vector2(0,5),point,v_lines_color,1,true) - draw_string(font,point+Vector2(-const_width/2*x_chors[p].length(),font_size+const_height),x_chors[p],font_color) + draw_line(point - Vector2(0, 5), point, v_lines_color, 1, true) + draw_string(font, point + Vector2(-const_width/2 * x_chors[p].length(), + font_size + const_height), x_chors[p], font_color) # ordinate for p in y_chors.size(): - var point : Vector2 = origin-Vector2(0,(p)*y_pass) + var point : Vector2 = origin - Vector2(0, p * y_pass) # h grid - draw_line(point,point+Vector2(SIZE.x-OFFSET.x,0),h_lines_color,0.2,true) + draw_line(point, point + Vector2(SIZE.x - OFFSET.x, 0), h_lines_color, 0.2, true) # ordinate - draw_line(point,point+Vector2(5,0),h_lines_color,1,true) - draw_string(font,point-Vector2(y_chors[p].length()*const_width+font_size,-const_height),y_chors[p],font_color) + draw_line(point, point + Vector2(5, 0), h_lines_color, 1, true) + draw_string(font, point - Vector2(y_chors[p].length() * const_width + + font_size, -const_height), y_chors[p], font_color) func draw_chart_outlines(): - draw_line(origin,SIZE-Vector2(0,OFFSET.y),box_color,1,true) - draw_line(origin,Vector2(OFFSET.x,0),box_color,1,true) - draw_line(Vector2(OFFSET.x,0),Vector2(SIZE.x,0),box_color,1,true) - draw_line(Vector2(SIZE.x,0),SIZE-Vector2(0,OFFSET.y),box_color,1,true) + draw_line(origin, SIZE-Vector2(0, OFFSET.y), box_color, 1, true) + draw_line(origin, Vector2(OFFSET.x, 0), box_color, 1, true) + draw_line(Vector2(OFFSET.x, 0), Vector2(SIZE.x, 0), box_color, 1, true) + draw_line(Vector2(SIZE.x, 0), SIZE - Vector2(0, OFFSET.y), box_color, 1, true) func draw_points(): @@ -304,20 +320,20 @@ func draw_points(): if function_colors.size(): defined_colors = true - for _function in point_values.size(): + for function in point_values.size(): var PointContainer : Control = Control.new() Points.add_child(PointContainer) - for function_point in point_values[_function].size(): + for function_point in point_values[function].size(): var point : Point = point_node.instance() point.connect("_point_pressed",self,"point_pressed") point.connect("_mouse_entered",self,"show_data") point.connect("_mouse_exited",self,"hide_data") - point.create_point(points_shape[_function], function_colors[_function], - Color.white, point_positions[_function][function_point], - point.format_value(point_values[_function][function_point], false, false), - y_labels[_function] as String) + point.create_point(points_shape[function], function_colors[function], + Color.white, point_positions[function][function_point], + point.format_value(point_values[function][function_point], false, false), + y_labels[function] as String) PointContainer.add_child(point)