tool extends Chart class_name RadarChart """ [RadarChart] - General purpose node for Radar Charts A radar chart is a graphical method of displaying multivariate data in the form of a two-dimensional chart of three or more quantitative variables represented on axes starting from the same point. The relative position and angle of the axes is typically uninformative, but various heuristics, such as algorithms that plot data as the maximal total area, can be applied to sort the variables (axes) into relative positions that reveal distinct correlations, trade-offs, and a multitude of other comparative measures. / source : Wikipedia / """ func _get_property_list(): return [ # Chart Properties { "hint": PROPERTY_HINT_NONE, "usage": PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, "name": "Chart_Properties/are_values_columns", "type": TYPE_BOOL }, { "hint": PROPERTY_HINT_RANGE, "hint_string": "-1,100,1", "usage": PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, "name": "Chart_Properties/labels_index", "type": TYPE_INT }, { "hint": PROPERTY_HINT_RANGE, "hint_string": "-1,100,1", "usage": PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, "name": "Chart_Properties/function_names_index", "type": TYPE_INT }, { "hint": PROPERTY_HINT_NONE, "usage": PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, "name": "Chart_Properties/use_height_as_radius", "type": TYPE_BOOL }, { "hint": PROPERTY_HINT_RANGE, "hint_string": "0,2000", "usage": PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, "name": "Chart_Properties/radius", "type": TYPE_REAL }, # Chart Display { "hint": PROPERTY_HINT_RANGE, "hint_string": "0.1,100", "usage": PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, "name": "Chart_Display/full_scale", "type": TYPE_REAL }, # Chart Style { "hint": 24, "hint_string": "%d/%d:%s"%[TYPE_INT, PROPERTY_HINT_ENUM, PoolStringArray(PointShapes.keys()).join(",")], "name": "Chart_Style/points_shape", "type": TYPE_ARRAY, "usage": PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE }, { "hint": PROPERTY_HINT_NONE, "usage": PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, "name": "Chart_Style/function_colors", "type": TYPE_COLOR_ARRAY }, { "hint": PROPERTY_HINT_NONE, "usage": PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, "name": "Chart_Style/outline_color", "type": TYPE_COLOR }, { "hint": PROPERTY_HINT_NONE, "usage": PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, "name": "Chart_Style/grid_color", "type": TYPE_COLOR }, { "class_name": "Font", "hint": PROPERTY_HINT_RESOURCE_TYPE, "hint_string": "Font", "usage": PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, "name": "Chart_Style/font", "type": TYPE_OBJECT }, { "class_name": "Font", "hint": PROPERTY_HINT_RESOURCE_TYPE, "hint_string": "Font", "usage": PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, "name": "Chart_Style/bold_font", "type": TYPE_OBJECT }, { "hint": PROPERTY_HINT_NONE, "usage": PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, "name": "Chart_Style/font_color", "type": TYPE_COLOR }, { "hint": PROPERTY_HINT_ENUM, "hint_string": PoolStringArray(Utilities.templates.keys()).join(","), "usage": PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, "name": "Chart_Style/template", "type": TYPE_INT }, { "hint": PROPERTY_HINT_RANGE, "hint_string": "0,360", "usage": PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, "name": "Chart_Modifiers/rotation", "type": TYPE_REAL }, ] func structure_datas(database : Array): # @x_values_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 are_values_columns = invert_chart != are_values_columns match are_values_columns: true: for row in database.size(): var t_row : Array = [] for column in database[row].size(): if row == labels_index: if column == function_names_index: pass else: x_labels.append(database[row][column]) else: if column == function_names_index: y_labels.append(database[row][column]) else: if typeof(database[row][column]) == TYPE_INT or typeof(database[row][column]) == TYPE_REAL: t_row.append(database[row][column] as float) else: t_row.append(database[row][column].replace(",", ".") as float) if not t_row.empty(): x_datas.append(t_row) false: for row in database.size(): if row == function_names_index: y_labels = database[row] as PoolStringArray var x_temp_datas : PoolRealArray = [] for column in database[row].size(): if column == labels_index: x_labels.append(database[row][column] as String) else: x_temp_datas.append(database[row][column] as float) x_datas.append(x_temp_datas) if labels_index == -1 : for data in x_datas[0].size(): x_labels.append("Element %s" % data) if function_names_index == -1 : for data in x_datas.size(): y_labels.append("Function %s" % data) func build_chart(): SIZE = get_size() origin = OFFSET + SIZE/2 var radar_polygon : Array func calculate_pass() : var ordered_max : Array for data in x_datas : var ordered_data : Array = data.duplicate() ordered_data.sort() ordered_max.append(ordered_data.pop_back()) ordered_max.sort() var max_value : float = ordered_max.pop_back() var dist = full_scale * pow(10.0,str(max_value).length()-2) var multi = 0 var value = dist * multi x_chors.append(value as String) while value < max_value: multi+=1 value = dist * multi x_chors.append(value as String) func calculate_coordinates(): for chor in x_chors.size(): var inner_polyline : PoolVector2Array var scalar_factor : float = (x_chors[chor] as float/x_chors.back() as float) for function in functions: var angle : float = ((2 * PI * function) / functions) - PI /2 + deg2rad(rotation) var x_coordinate : float = (radius if (not use_height_as_radius and radius