diff --git a/mysite/plots/avl_tree.py b/mysite/plots/avl_tree.py index d44d7e4fa39a859e8c508c059982b10eebb7287d..9073387455a3de6b77700011d095017105a4339e 100644 --- a/mysite/plots/avl_tree.py +++ b/mysite/plots/avl_tree.py @@ -8,6 +8,7 @@ import sys # Create a tree node class TreeNode(object): + def __init__(self, key, vertice, vertice_neighbour): self.key = key self.vertice = vertice @@ -184,4 +185,15 @@ class AVLTree(object): indent += "| " print(currPtr.key) self.printHelper(currPtr.left, indent, False) - self.printHelper(currPtr.right, indent, True) \ No newline at end of file + self.printHelper(currPtr.right, indent, True) + +# myTree = AVLTree() +# root = None +# nums = [33, 13, 52, 9, 21, 61, 8, 11] +# for num in nums: +# root = myTree.insert_node(root, num) +# myTree.printHelper(root, "", True) +# key = 13 +# root = myTree.delete_node(root, key) +# print("After Deletion: ") +# myTree.printHelper(root, "", True) \ No newline at end of file diff --git a/mysite/plots/dataset_creator.py b/mysite/plots/dataset_creator.py new file mode 100644 index 0000000000000000000000000000000000000000..98d1c7d8555c490e3a00ad20922f8b69f8bccfcb --- /dev/null +++ b/mysite/plots/dataset_creator.py @@ -0,0 +1,173 @@ +# import pandas as pd +# from .packing_algo import ConvexPolygon, pack_polygons, truncate, End_Container, plot_containers, ConvexContainer +# from .polygon_creator import voronoi_polygons_wrapper, rectangle_cutter +# +# +# # def build_aprox_factors(): +# +# +# def build_dataset_with_rectangle_cutter(rect_width: float, rect_height, repetition, angle_steps=90, cut_min=1, +# cut_max=1, cut_steps=1, intervals=[0, 0.01, 0.05, 1], weights=[0, 0, 0.5, 1]): +# if cut_min > cut_max: +# cut_max = cut_min +# data_dict_list = [] +# for cut_count in range(cut_min, cut_max + cut_steps, cut_steps): +# cutted_polygons_lists = [] +# for n in range(0, repetition): +# cutted_polygons = rectangle_cutter(rect_width, rect_height, cut_count, intervals=intervals, weights=weights) +# cutted_polygons_lists.append(cutted_polygons) +# dict_data = collect_rect_containers_data(rect_width, rect_height, cutted_polygons_lists, angle_steps) +# data_dict_list.append(dict_data) +# return data_dict_list +# +# +# def build_dataset_with_voronoi(rect_width, rect_height, repetition, cut_min=5, cut_max=5, cut_steps=1, angle_steps=90): +# if cut_min > cut_max: +# cut_max = cut_min +# data_dict_list = [] +# for cut_count in range(cut_min, cut_max + cut_steps, cut_steps): +# cutted_polygons_lists = [] +# for n in range(0, repetition): +# cutted_polygons = voronoi_polygons_wrapper(rect_width, rect_height, cut_count) +# cutted_polygons_lists.append(cutted_polygons) +# dict_data = collect_rect_containers_data(rect_width, rect_height, cutted_polygons_lists, angle_steps) +# data_dict_list.append(dict_data) +# return data_dict_list +# +# +# def collect_rect_containers_data(rect_width: float, rect_height: float, cutted_polygons_lists: [[ConvexPolygon]], +# angle_steps=90) -> {str, list}: +# opt_area = rect_width * rect_height +# opt_area_list = [] +# area_list = [] +# area_div_list = [] +# angle_0_area_div_list = [] +# angle_0_not_clipped_area_div_list = [] +# not_clipped_area_list = [] +# not_clipped_area_div_list = [] +# polygon_count_list = [] +# end_container_list = [] +# mini_container_count_list = [] +# for polygons in cutted_polygons_lists: +# cc = ConvexContainer(polygons, steps=angle_steps) +# end_container = cc.smallest_end_container +# end_container_angle_0 = cc.angle_0_end_container +# +# c_area = end_container.container_area +# c_not_opt_area = end_container.container_not_clipped_area +# c_not_r_area = end_container_angle_0.container_area +# c_not_r_not_opt_area = end_container_angle_0.container_not_clipped_area +# area_list.append(truncate(c_area, 1)) +# area_div_list.append(truncate(c_area / opt_area, 1)) +# not_clipped_area_list.append(truncate(c_not_opt_area, 1)) +# not_clipped_area_div_list.append(truncate(c_not_opt_area / opt_area, 1)) +# +# angle_0_area_div_list.append(truncate(c_not_r_area / opt_area, 1)) +# angle_0_not_clipped_area_div_list.append(truncate(c_not_r_not_opt_area / opt_area, 1)) +# opt_area_list.append(opt_area) +# polygon_count_list.append(len(polygons)) +# mini_container_count_list.append(len(end_container.mini_containers)) +# end_container_list.append(cc) +# rect_containers_data_dict = {'area': area_list, 'area/opt_area': area_div_list, +# 'not_clipped_area': not_clipped_area_list, +# 'not_clipped_area/opt_area': not_clipped_area_div_list, +# 'angle_0_area/opt_area': angle_0_area_div_list, +# 'angle_0_not_clipped_area/opt_area': angle_0_not_clipped_area_div_list, +# 'opt-area': opt_area_list, 'polygon count': polygon_count_list, +# 'mini-container count': mini_container_count_list, 'end-container': end_container_list} +# return rect_containers_data_dict +# +# +# # need to update like rectangle_cutter with deviation +# def find_repition_factor_rectangle_voronoi(cut, rep_high, rep_low=1, rep_steps=1, display_flag=True, +# intervals=[0, 0.01, 0.05, 1], weights=[0, 0, 0.5, 1]): +# average_list = [] +# if rep_low < 1 or rep_high < 1: +# raise ValueError("the value of rep_high and rep_low need to bigger then 0") +# for rep in range(rep_low, rep_high + rep_steps, rep_steps): +# data = build_dataset_with_voronoi(1000, 1000, rep, cut_min=cut, cut_max=cut, cut_steps=1) +# df = pd.DataFrame(data[0]) +# if display_flag: +# display(df.sort_values(by="area", ascending=False)) +# list_optimal_areas = df["area/opt_area"].tolist() +# average = sum(list_optimal_areas) / len(list_optimal_areas) +# average_list.append((rep, average)) +# return average_list +# +# +# # deviation=0.05, accept=10 +# def find_repition_factor_rectangle_cutter(cut, rep_high, deviation=0.05, accept_number=10, rep_low=1, rep_steps=1, +# display_flag=True, intervals=[0, 0.01, 0.05, 1], weights=[0, 0, 0.5, 1]): +# average_list = [] +# if rep_low < 1 or rep_high < 1: +# raise ValueError("the value of rep_high and rep_low need to bigger then 0") +# average_canidate = 0 +# accept_counter = accept_number +# average_top_bound = average_canidate + average_canidate * deviation +# average_bot_bound = average_canidate - average_canidate * deviation +# for rep in range(rep_low, rep_high + rep_steps, rep_steps): +# +# data = build_dataset_with_rectangle_cutter(1000, 1000, rep, cut_min=cut, cut_max=cut, cut_steps=1, +# intervals=[0, 0.01, 0.05, 1], weights=[0, 0, 0.5, 1]) +# df = pd.DataFrame(data[0]) +# if display_flag: +# display(df.sort_values(by="area", ascending=False)) +# +# list_optimal_areas = df["area/opt_area"].tolist() +# average = sum(list_optimal_areas) / len(list_optimal_areas) +# +# if average_bot_bound <= average <= average_top_bound: +# accept_counter -= 1 +# else: +# average_canidate = average +# accept_counter = accept_number +# average_top_bound = average_canidate + average_canidate * deviation +# average_bot_bound = average_canidate - average_canidate * deviation +# if accept_counter <= 0: +# print(rep) +# return average_list +# average_list.append((rep, average)) +# return average_list +# +# +# def dict_list_to_ordered_panda_list(dictionary_list: [dict], ordered_by_area=True) -> [pd.DataFrame]: +# data_frame_list = [] +# for dic in dictionary_list: +# df = pd.DataFrame(dic) +# if ordered_by_area: +# data_frame_list.append(df.sort_values(by="area", ascending=False)) +# else: +# data_frame_list.append(df.sort_values(by="not_clipped_area", ascending=False)) +# return data_frame_list +# +# +# def display_panda_df_list(df_list: [pd.DataFrame]) -> None: +# for df in df_list: +# display(df) +# +# +# def build_aprox_values(panda_data): +# mean_opt = 0 +# mean_not_clipped = 0 +# mean_angle_0 = 0 +# mean_angle_0_not_clipped = 0 +# counter = 0 +# mean_best = 0 +# mean_worst = 0 +# for data in panda_data: +# mean_opt += data["area/opt_area"].mean(axis=0) +# mean_best += data["area/opt_area"].iloc[-1] +# mean_worst += data["area/opt_area"].iloc[0] +# mean_not_clipped += data["not_clipped_area/opt_area"].mean(axis=0) +# mean_angle_0 += data["angle_0_area/opt_area"].mean(axis=0) +# mean_angle_0_not_clipped += data["angle_0_not_clipped_area/opt_area"].mean(axis=0) +# counter += 1 +# mean_opt = mean_opt / counter +# mean_best = mean_best / counter +# mean_worst = mean_worst / counter +# mean_not_clipped = mean_not_clipped / counter +# mean_angle_0 = mean_angle_0 / counter +# mean_angle_0_not_clipped = mean_angle_0_not_clipped / counter +# aprox_dict = dict(aprox=mean_opt, aprox_best=mean_best, aprox_worst=mean_worst, aprox_not_clipped=mean_not_clipped, +# aprox_angle_0=mean_angle_0, aprox_angle_0_not_clipped=mean_angle_0_not_clipped) +# return aprox_dict \ No newline at end of file diff --git a/mysite/plots/packing_algo.py b/mysite/plots/packing_algo.py new file mode 100644 index 0000000000000000000000000000000000000000..34351764c9f3498653f649120de6f6bfdb3fdc55 --- /dev/null +++ b/mysite/plots/packing_algo.py @@ -0,0 +1,1115 @@ +import sys, path +import copy +import numpy +import math +import random +from collections import defaultdict +import itertools +# from typing import NewType +# for JupyterLab +#import import_ipynb + +# tree datastructure +from . import avl_tree + +# shapely/polygon packages +from shapely.geometry import MultiPolygon, Polygon, LineString, LinearRing, Point +from shapely.geometry.base import BaseGeometry, geos_geom_from_py +from shapely import affinity + +# plotting packages +import mpld3 +import bokeh +from bokeh.plotting import figure, Figure +from bokeh.io import output_notebook, show +from bokeh.layouts import gridplot, row, layout, column, Column +from bokeh.models import Div +from bokeh.models import Legend +from bokeh.models import BoxAnnotation +from bokeh.models.widgets import Tabs, Panel +from bokeh.models import ColumnDataSource, Label, LabelSet, Range1d +from bokeh.palettes import Dark2_5 as palette +from bokeh.plotting import output_file + + +# for analysing the data +import pandas as pd + +# Type aliases for the type hints +Point_xy = (float, float) + + +class ConvexPolygon(object): + + def __init__(self, shell: [Point_xy]) -> None: + self.__shell, self.__area = self.convex_hull_and_area(shell) + self.__x_values = [vertex[0] for vertex in self.shell] + self.__y_values = [vertex[1] for vertex in self.shell] + self.__min_x = min(self.__x_values) + self.__max_x = max(self.__x_values) + self.__min_y = min(self.__y_values) + self.__max_y = max(self.__y_values) + self.__height = self.__max_y - self.__min_y + self.__width = self.__max_x - self.__min_x + self.__spine = self.set_spine() + self.__vertices_left_visible, self.__vertices_right_visible = self.splitter() + self.__slope = self.set_slope() + self.plot_fill = False + + @property + def area(self): + return self.__area + + @property + def shell(self): + return self.__shell + + @property + def min_x(self): + return self.__min_x + + @property + def max_x(self): + return self.__max_x + + @property + def min_y(self): + return self.__min_y + + @property + def max_y(self): + return self.__max_y + + @property + def x_values(self): + return self.__x_values + + @property + def y_values(self): + return self.__y_values + + @property + def height(self): + return self.__height + + @property + def width(self): + return self.__width + + @property + def spine(self): + return self.__spine + + @property + def vertices_left_visible(self): + return self.__vertices_left_visible + + @property + def vertices_right_visible(self): + return self.__vertices_right_visible + + @property + def slope(self): + return self.__slope + + # @property + # def plot_fill(self): + # return self.__plot_fill + + def convex_hull_and_area(self, shell: [Point_xy]) -> [Point_xy]: + # the Polygon points will be ordered clockweise and the start and end point are connected + if shell == None: + raise ValueError("a convex polygon can't intialized with None") + elif shell == [] or len(shell) < 3: + raise ValueError("a convex polygon needs at least 3 points") + shapely_polygon = Polygon(shell) + convex_polygon = shapely_polygon.convex_hull + if type(convex_polygon) is not Polygon: + raise ValueError( + "couldn't create the convex Polygon, to less points after using the convex hull on the input points") + shell = list(convex_polygon.exterior.coords) + area = convex_polygon.area + return (shell, area) + + def translation(self, x: float, y: float) -> None: + self.__shell = [(point[0] + x, point[1] + y) for point in self.__shell] + self.__spine = ( + (self.__spine[0][0] + x, self.__spine[0][1] + y), (self.__spine[1][0] + x, self.__spine[1][1] + y)) + self.__vertices_left_visible = [(point[0] + x, point[1] + y) for point in self.__vertices_left_visible] + self.__vertices_right_visible = [(point[0] + x, point[1] + y) for point in self.__vertices_right_visible] + self.__min_x = self.__min_x + x + self.__max_x = self.__max_x + x + self.__min_y = self.__min_y + y + self.__max_y = self.__max_y + y + self.__x_values = [vertex + x for vertex in self.__x_values] + self.__y_values = [vertex + y for vertex in self.__y_values] + + def set_spine(self) -> (Point_xy, + Point_xy): # für den spine spielt es keine Rolle in welche Rolle das Polygon aufgebaut ist ob im Uhrzeigersinn oder dagegen + y_sorted_p_p = sorted(self.__shell, key=lambda k: k[ + 1]) # Parser schreibt oder davon ausgeht das konvexe Polygone übergeben werden + if y_sorted_p_p[0][1] == y_sorted_p_p[1][ + 1]: # falls der niedrige Puntk eine wagerechte ist nehme die linke Ecke + if y_sorted_p_p[0][0] < y_sorted_p_p[1][0]: + spine_bottom = y_sorted_p_p[0] + else: + spine_bottom = y_sorted_p_p[1] + else: + spine_bottom = y_sorted_p_p[0] + if y_sorted_p_p[-2][1] == y_sorted_p_p[-1][ + 1]: # falls der höchste Punkt eine wagerechte ist nehme die rechte Ecke + if y_sorted_p_p[-2][0] < y_sorted_p_p[-1][0]: + spine_top = y_sorted_p_p[-1] + else: + spine_top = y_sorted_p_p[-2] + else: + spine_top = y_sorted_p_p[-1] + return (spine_bottom, spine_top) + + def set_slope(self) -> float: + spine = self.__spine + if spine[0][0] == spine[1][0]: # Sonderfall für eine senkrechte + slope = math.inf + else: + slope = (spine[1][1] - spine[0][1]) / (spine[1][0] - spine[0][ + 0]) # m = y2-y1/x2-x1 Formel für die Geradensteigung mithilfe aus zwei verschiedenen Punkten der Geraden + return slope + + def plot_polygon(self, title="", plot_width=400, plot_height=300, color="#1F77B4", render=True) -> Figure: + """Plotting a Polygon with bokeh""" + legend_items = [] + height = (int(self.__height * 10)) / 10 + if self.__slope == math.inf: + slope = math.inf + else: + slope = truncate(self.__slope, 1) + x_data = self.__x_values + y_data = self.__y_values + TOOLTIPS = [("index", "$index"), ("(x,y)", "($x{0.0}, $y{0.0})"), ] + if title == "": + title = 'height: {} slope: {}'.format(height, slope) + else: + title = '{} height: {} slope: {}'.format(title, height, slope) + fig = figure(title=title, x_axis_label='x', y_axis_label='y', width=plot_width, height=plot_height, + tooltips=TOOLTIPS, ) + if self.plot_fill: + poly_fig = fig.patch(x_data, y_data, line_width=1, color=color, alpha=0.9, line_alpha=1, muted_alpha=0.05) + else: + poly_fig = fig.patch(x_data, y_data, line_width=1, alpha=0.1, color=color, line_alpha=1, muted_alpha=0.05) + fig_points = fig.circle(x_data, y_data, color=color, line_width=1, muted_alpha=0.02, size=4) + legend_items.append(("shell-lines", [poly_fig])) + legend_items.append(("vertices", [fig_points])) + spine_x_values = [x[0] for x in self.__spine] + spine_y_values = [x[1] for x in self.__spine] + fig_spine = fig.line(spine_x_values, spine_y_values, line_color="red", line_width=1, muted_alpha=0.2, + muted_color="red") + legend_items.append(("spine", [fig_spine])) + legend = Legend(items=legend_items) + legend.click_policy = "mute" + fig.add_layout(legend, 'right') + if render: + show(fig) + return fig + + def splitter(self) -> ([Point_xy], [Point_xy]): + left = [] + right = [] + spine_bottom = self.__spine[0] + spine_top = self.__spine[1] + help_array = self.__shell[:] + if help_array[0] == help_array[-1]: # falls letztes element doppelt + help_array = help_array[0:-1] + spine_bottom_found = False + spine_top_found = False + spine_bottom_not_horizontal = False + while spine_bottom_found == False: # Phase 1 der Funktion sie sucht den bottom spine, dabei werden die Ecken die nicht der Spine Bottom sind ans Ende der Liste geschoben + if help_array[0] == spine_bottom: + if spine_bottom[1] != help_array[-1][ + 1]: # checkt ob Spine bottom ein horizontalen Nachbar hat falls ja wird ein Flag gesetzt damit Spine bottomt später nicht in die Rechte mitgenommen wird + spine_bottom_not_horizontal = True + spine_bottom_found = True + left.append(help_array.pop(0)) + else: + help_array.append(help_array.pop(0)) + while spine_top_found == False: # iterieren die Liste erneut durch bis wir spine top finden, falls spine top gefunden wurde wird auch geschaut ob spine top ein horizontalen linken + if help_array[0] == spine_top: # Nachbar hat falls ja wird spine top nicht in die Linke Liste miteingefügt + spine_top_found = True + if spine_top[1] != left[-1][1]: + left.append(spine_top) + else: + left.append(help_array.pop(0)) + right = help_array.copy() + if spine_bottom_not_horizontal: + right.append(spine_bottom) + return (left, right) + + +class HighClass(object): + def __init__(self, i: int, alpha: float, h_max_polygon: float, w_max_polygon: float) -> None: + self.i = i + self.alpha = alpha + self.h_max_polygon = h_max_polygon + self.w_max_polygon = w_max_polygon + self.min_border = alpha ** (i + 1) * h_max_polygon + self.max_border = alpha ** (i) * h_max_polygon + self.polygons = [] + self.spine_ordered_polygons = [] + + def set_polygons(self, polygons: [ConvexPolygon]) -> None: + self.polygons = polygons + spine_ordered_polygons = sorted(self.polygons, key=lambda polygon: polygon.slope) + self.spine_ordered_polygons = spine_ordered_polygons + + def plot_hc(self, ordered=False, render=True, plot_width=300, plot_height=300) -> Column: + plots = [] + if ordered: + polygon_list = self.spine_ordered_polygons + else: + polygon_list = self.polygons + for counter, polygon in enumerate(polygon_list): + title = "Polygon {}".format(counter) + plots.append(polygon.plot_polygon(title=title, render=False)) + grid = gridplot(plots, ncols=4, plot_width=plot_width, plot_height=plot_height, toolbar_location="left") + grid_title = Div(text="<b>Hc_{} height: {}-{} alpha: {}<b>".format(self.i, truncate( + self.min_border, 1), truncate(self.max_border, 1), self.alpha)) + grid_layout = column(grid_title, grid) + if render: + show(grid_layout) + return grid_layout + + +class Container(object): + def __init__(self, hc: HighClass) -> None: + self.hc = hc # am ende nur zuweiseung ohne copy + self.y_boundary = self.hc.max_border + self.x_boundary = 0 + self.Tree = avl_tree.AVLTree() + self.root = None + self.sigma, self.plot_steps = self.packing_container(self.hc.spine_ordered_polygons) + + def distance(self, edge_points: (Point_xy, Point_xy), point: Point_xy) -> float: + # y = m*x+n + # (y-n)/m=x + # n = y-m*x + edge_p1 = edge_points[0] + edge_p2 = edge_points[1] + if edge_p1[0] == edge_p2[0]: # Sonderfall für eine senkrechte + distance = math.sqrt((edge_p1[0] - point[ + 0]) ** 2) # da der edge_points eine senkrechte ist -> der eintreffpunkt hat den gleichen y wert wie der punkt, in der Abstand formel fällt dieser wert weg + elif edge_p1[1] == point[1]: + distance = math.sqrt((edge_p1[0] - point[0]) ** 2 + (edge_p1[1] - point[1]) ** 2) + else: + slope = (edge_p2[1] - edge_p1[1]) / (edge_p2[0] - edge_p1[ + 0]) # m = y2-y1/x2-x1 Formel für die Geradensteigung mithilfe aus zwei verschiedenen Punkten der Geraden + n = edge_p1[1] - (slope * edge_p1[0]) + intersection_point_x = (point[1] - n) / slope # x=(y-n)/m + intersection_point = (intersection_point_x, point[1]) + distance = math.sqrt((intersection_point[0] - point[0]) ** 2 + (intersection_point[1] - point[1]) ** 2) + return distance + + def find_successor(self, vertex: Point_xy, vertices_visible_left: [Point_xy]) -> (Point_xy, Point_xy): + for counter, top_edge_vertex in enumerate(vertices_visible_left): + if top_edge_vertex[1] >= vertex[1]: + bottom_edge_vertex = vertices_visible_left[counter - 1] + return (bottom_edge_vertex, top_edge_vertex) + + def packing_container(self, hc_spine_ordered_polygons: [ConvexPolygon]) -> ([ConvexPolygon], [Figure]): + hc_polygons = copy.deepcopy(hc_spine_ordered_polygons) # n + sigma_plot_helper = [] # holds the Polygons before their translation to next polygon in sigma + step_counter = 0 + sigma = [] + plot_steps = [] + for polygon in hc_polygons: + sigma_plot_helper.append(polygon) + if sigma == []: + transform_x = -polygon.min_x + transform_y = -polygon.min_y + polygon.translation(transform_x, transform_y) + polygon_vertices = len(polygon.vertices_right_visible) + # filling the tree with all vertices visible form right of the first polygon + for count in range(0, polygon_vertices - 1): + vertice = polygon.vertices_right_visible[count] + vertice_neighbour = polygon.vertices_right_visible[count + 1] + self.root = self.Tree.insert_node(self.root, vertice[1], vertice, vertice_neighbour) + sigma.append(polygon) + self.x_boundary += polygon.width + plot_steps.append( + self.plot_container(sigma_plot_helper, render=False, title="Step {}".format(step_counter))) + step_counter += 1 + else: + transform_x = (self.x_boundary + abs(polygon.min_x)) + 10 + transform_y = -polygon.min_y + polygon.translation(transform_x, transform_y) + min_horizontal_distance = math.inf + distance_rl_plot_helper = [] + # distanzen von rechts nach links + for vertex in polygon.vertices_left_visible: + vertex_y = vertex[1] + successor_vertex = self.Tree.find_edges(self.root, vertex_y, self.root) + corresponding_edge_points = (successor_vertex.vertice, successor_vertex.vertice_neighbour) + distance = self.distance(corresponding_edge_points, vertex) + if distance <= min_horizontal_distance: + min_horizontal_distance = distance + distance_rl_plot_helper.append((vertex, distance)) + key = polygon.spine[1][1] + tree_array = self.Tree.preOrder_array((self.root), [], + key) # alle Ecken bis zum höchsten Punkt von dem neuen Polygon + distance_lr_plot_helper = [] + # distanzen von links nach rechts + for vertex in tree_array: + successor = self.find_successor(vertex, polygon.vertices_left_visible) + distance = self.distance(successor, vertex) + if distance <= min_horizontal_distance: + min_horizontal_distance = distance + self.root = self.Tree.delete_node(self.root, vertex[1]) # deleting vertices from B + distance_lr_plot_helper.append((vertex, distance)) + plot_steps.append( + self.plot_container(sigma_plot_helper, distance_rl_plot_helper, distance_lr_plot_helper, + min_horizontal_distance, render=False, title="Step {}".format(step_counter))) + step_counter += 1 + polygon.translation(-(min_horizontal_distance), 0) + for counter, vertex in enumerate(polygon.vertices_right_visible[0:-1]): + self.root = self.Tree.insert_node(self.root, vertex[1], vertex, + (polygon.vertices_right_visible[counter + 1])) + x_boundary = max([vertex[0] for vertex in polygon.vertices_right_visible] + [self.x_boundary]) + self.x_boundary = x_boundary + sigma.append(polygon) + plot_steps.append(self.plot_container(sigma, render=False, title="Finished Container")) + return (sigma, plot_steps) + + def plot_container(self, sigma=None, r_l_distances=None, l_r_distances=None, min_distance=None, render=True, + title="", box_boundarys_x_values_colors_tuple=None) -> Figure: + # sigma als argument statt self.sigma dient dazu auch zwischen schritte plotten zu lassen + legend_items = [] + legend_polygons = [] + legend_spine = [] + legend_lr = [] + legend_rl = [] + legend_vertices = [] + if sigma == None: + sigma = self.sigma + TOOLTIPS = [("index", "$index"), ("(x,y)", "($x{0.0}, $y{0.0})"), ] + fig = figure(title=title, x_axis_label='x', y_axis_label='y', tooltips=TOOLTIPS, toolbar_location="left") + for counter, polygon in enumerate(sigma): + x_values = polygon.x_values + y_values = polygon.y_values + poly_fig = fig.patch(x_values, y_values, line_width=1, alpha=0.1, muted_alpha=0.05, line_alpha=1) + circle_fig = fig.circle(x_values, y_values, line_width=1, muted_alpha=0.01) + legend_label = "Polygon{}".format(counter) + legend_polygons.append((legend_label, [poly_fig])) + legend_vertices.append(circle_fig) + x_spine = [x[0] for x in polygon.spine] + y_spine = [y[1] for y in polygon.spine] + spine_fig = fig.line(x_spine, y_spine, line_color="red", line_width=1, alpha=0.01, muted_color="red", + muted_alpha=1) + legend_spine.append(spine_fig) + if box_boundarys_x_values_colors_tuple != None: + box_boundarys_x_values = box_boundarys_x_values_colors_tuple[0] + background_c_list = box_boundarys_x_values_colors_tuple[1] + for counter, boundary in enumerate(box_boundarys_x_values[0:-1]): + next_boundary = box_boundarys_x_values[counter + 1] + color_box = BoxAnnotation(bottom=0, top=self.y_boundary, left=box_boundarys_x_values[counter], + right=next_boundary, fill_color=background_c_list[counter], fill_alpha=0.1) + fig.add_layout(color_box) + fig.line([next_boundary, next_boundary], [0, self.y_boundary], line_dash="dotted") + fig.title.text = 'Hc-Container{} height: {} -> Mini Containers'.format(self.hc.i, + truncate(self.y_boundary, 1)) + if title == "": + fig.title.text = 'Hc-Container{} height: {} '.format(self.hc.i, truncate(self.y_boundary, 1)) + if r_l_distances != None: + for vertex_distance_tuple in r_l_distances: + vertex_r = vertex_distance_tuple[0] + distance = vertex_distance_tuple[1] + x = vertex_r[0] + corresponding_point_x = x - distance + y = vertex_r[1] + text_point_x, text_point_y = (x - distance / 2, y) + distance_int = int(distance) + color = "blue" + if distance_int == int(min_distance): + line_dash = "solid" + else: + line_dash = "dotted" + fig_rl = fig.line([vertex_r[0], corresponding_point_x], [y, y], line_color=color, line_width=1, + muted_alpha=0.2, line_dash=line_dash) + source = ColumnDataSource(data=dict(x=[vertex_r[0] - (distance / 2)], y=[y], names=[distance_int])) + labels = LabelSet(x='x', y='y', text='names', level='glyph', x_offset=0, y_offset=0, source=source, + render_mode='canvas') + fig.add_layout(labels) + legend_rl.append(fig_rl) + if l_r_distances != None: + for vertex_distance_tuple in l_r_distances: + vertex_l = vertex_distance_tuple[0] + distance = vertex_distance_tuple[1] + x = vertex_l[0] + corresponding_point_x = x + distance + y = vertex_l[1] + text_point_x, text_point_y = (x + distance / 2, y) + distance_int = int(distance) + color = "green" + if distance_int == int(min_distance): + line_dash = 'solid' + else: + line_dash = "dotted" + fig_lr = fig.line([vertex_l[0], corresponding_point_x], [y, y], line_color=color, line_width=1, + muted_alpha=0.2, line_dash=line_dash) + source = ColumnDataSource(data=dict(x=[vertex_l[0] + (distance / 2)], y=[y], names=[distance_int])) + labels = LabelSet(x='x', y='y', text='names', level='glyph', x_offset=0, y_offset=0, source=source, + render_mode='canvas') + fig.add_layout(labels) + legend_lr.append(fig_lr) + # building the custom legend + fig_boundary = fig.line([0, self.x_boundary, self.x_boundary, 0, 0], + [0, 0, self.y_boundary, self.y_boundary, 0], line_color="black", alpha=0.7, + line_width=1, muted_alpha=0.2, ) + legend_items.append(("spine", legend_spine)) + if l_r_distances != None: + legend_items.append(("distance-lr", legend_lr)) + if r_l_distances != None: + legend_items.append(("distance-rl", legend_rl)) + legend_items.append(("boundary", [fig_boundary])) + legend_items.append(("vertices", legend_vertices)) + legend_items = legend_items + legend_polygons + legend = Legend(items=legend_items) + legend.click_policy = "mute" + fig.add_layout(legend, 'right') + if render: + show(fig) + return fig + + def plot_container_steps(self, render=True, colums=2, plot_width=600, plot_height=600) -> Column: + grid = gridplot(self.plot_steps, ncols=colums, plot_width=plot_width, plot_height=plot_height, + toolbar_location="left") + min_border = (int(self.hc.min_border * 10)) / 10 + max_border = (int(self.hc.max_border * 10)) / 10 + # text="<b>Hc_{} height: {}-{} alpha: {}<b> + title = Div( + text="<b>Highclass Container {}, Polygon height: {}-{} <b>".format(self.hc.i, min_border, + max_border)) + grid_layout = column(title, grid) + if render: + show(grid_layout) + return grid_layout + + +class Mini_Container(object): + def __init__(self, max_width: float, max_height: float, max_polygon_width: float, hc_i: int, c=2.214) -> None: + self.max_polygon_width = max_polygon_width + self.current_right_boundary = 0 + self.height = 0 + self.hc_i = hc_i + self.hc_height = max_height + self.max_width = max_width + self.c = c + self.polygons = [] + self.y_offset = 0 + self.plot_steps = [] + + def plot_container(self, render=True, title="", background_c=None) -> Figure: + y_offset = self.y_offset + legend_polygons = [] + legend_spine = [] + legend_lr = [] + legend_rl = [] + legend_vertices = [] + TOOLTIPS = [("index", "$index"), ("(x,y)", "($x{0.0}, $y{0.0})"), ] + fig = figure(title=title, x_axis_label='x', y_axis_label='y', tooltips=TOOLTIPS, toolbar_location="left") + if background_c != None: + color_box = BoxAnnotation(left=0, right=self.max_width, bottom=y_offset, + top=y_offset + self.height, fill_color=background_c, + fill_alpha=0.1) + fig.add_layout(color_box) + for counter, polygon in enumerate(self.polygons): + x_values = polygon.x_values + y_values = polygon.y_values + poly_fig = fig.patch(x_values, y_values, line_width=1, alpha=0.1, line_alpha=1, muted_alpha=0.05) + circle_fig = fig.circle(x_values, y_values, line_width=1, muted_alpha=0.01) + legend_label = "Polygon{}".format(counter) + legend_polygons.append((legend_label, [poly_fig])) + legend_vertices.append(circle_fig) + x_spine = [x[0] for x in polygon.spine] + y_spine = [y[1] for y in polygon.spine] + spine_fig = fig.line(x_spine, y_spine, line_color="red", line_width=1, alpha=0.1, muted_alpha=1, + muted_color="red") + legend_spine.append(spine_fig) + # building the custom legend + fig_boundary = fig.line([0, self.max_width, self.max_width, 0, 0], + [0 + y_offset, 0 + y_offset, self.height + y_offset, self.height + y_offset, + 0 + y_offset] + , line_color="black", alpha=0.7, line_width=1, muted_alpha=0.2, ) + fig_polygon_boundary = fig.line([self.current_right_boundary, self.current_right_boundary], + [0 + y_offset, self.height + y_offset] + , line_color="black", line_dash="dotted", alpha=0.7, line_width=1, + muted_alpha=0.2, ) + items = legend_polygons + [("spine", legend_spine)] + items.append(("container-boundary", [fig_boundary])) + items.append(("last polygon-boundary", [fig_polygon_boundary])) + items.append(("vertices", legend_vertices)) + legend = Legend(items=items) + legend.click_policy = "mute" + fig.add_layout(legend, 'right') + if render: + show(fig) + return fig + + +class End_Container(object): + def __init__(self, mini_container_array: [Mini_Container], angle=0) -> None: + self.mini_containers = copy.deepcopy(mini_container_array) + self.initial_mini_containers = mini_container_array + self.polygons, self.max_width, self.max_height, self.container_not_clipped_area = self.pack_container() + self.x_values_border = [0, 0, self.max_width, self.max_width, 0] + self.y_values_border = [0, self.max_height, self.max_height, 0, 0] + self.container_area = self.max_width * self.max_height + self.angle = angle + self.plot_steps_all = None + + def pack_container(self) -> ([ConvexPolygon], float, float): + y_offset = 0 + end_c_polygons = [] + container_polygon_boundary_width = 0 + container_not_clipped_area = 0 + for mini_container in self.mini_containers: + container_not_clipped_area += mini_container.max_width * mini_container.hc_height + for polygon in mini_container.polygons: + polygon.translation(0, y_offset) + mini_container.y_offset = y_offset + y_offset += mini_container.height + end_c_polygons = end_c_polygons + mini_container.polygons + if container_polygon_boundary_width < mini_container.current_right_boundary: + container_polygon_boundary_width = mini_container.current_right_boundary + return (end_c_polygons, container_polygon_boundary_width, y_offset, container_not_clipped_area) + + def plot_polygons(self, title="", plot_width=500, plot_height=500, render=True) -> Figure: + if title == "": + title = 'End-Container area: {} not-clipped-area: {} angle:{}'.format(truncate(self.container_area, 1), + truncate( + self.container_not_clipped_area, + 1), self.angle) + fig = plot_polygons_in_single_plot(self.polygons, title=title, plot_width=plot_width, plot_height=plot_height, + render=render, border=(self.x_values_border, self.y_values_border)) + return fig + + def plot_steps(self, render=True): + if render: + show(self.plot_steps_all) + return self.plot_steps_all + + def plot_container(self, title="", plot_width=600, plot_height=600, solo_box_border=False, render=True, + reverse_legend=True) -> Figure: + legend_mini_containers = [] + legend_spine = [] + legend_lr = [] + legend_rl = [] + legend_items = [] + legend_vertices = [] + TOOLTIPS = [("index", "$index"), ("(x,y)", "($x{0.0}, $y{0.0})"), ] + if title == "": + title = 'End-Container area: {} not-clipped-area: {} angle:{}'.format( + truncate(self.container_area, 1), truncate(self.container_not_clipped_area, 1), self.angle) + fig = figure(title=title, x_axis_label='x', y_axis_label='y', width=plot_width, height=plot_height, + toolbar_location="left", tooltips=TOOLTIPS) + y_offset = 0 + colors = itertools.cycle(palette) + for counter, mini_container in enumerate(self.mini_containers): + color = next(colors) + legend_polygons = [] + for polygon in mini_container.polygons: + source = ColumnDataSource(data=dict(x=polygon.x_values, y=polygon.y_values)) + fig_polygon = fig.patch(x="x", y="y", line_width=1, color=color, line_color=color, muted_color=color, + alpha=0.1, muted_alpha=0.05, line_alpha=1, source=source) + fig_circle = fig.circle(x="x", y="y", line_width=1, color=color, fill_color=color, muted_color=color, + muted_alpha=0.01, size=4, + source=source) + spine_x_values = [x[0] for x in polygon.spine] + spine_y_values = [x[1] for x in polygon.spine] + fig_spine = fig.line(spine_x_values, spine_y_values, line_color="red", line_width=1, alpha=0.01, + muted_color="red", + muted_alpha=1) + legend_spine.append(fig_spine) + legend_polygons = legend_polygons + [fig_polygon] + legend_vertices.append(fig_circle) + if solo_box_border: + mini_box_border = mini_container.current_right_boundary + fig.title.text = 'End-Container mini-containers with solo boundarys' + else: + mini_box_border = self.max_width + color_box = BoxAnnotation(left=0, right=mini_box_border, bottom=mini_container.y_offset, + top=mini_container.y_offset + mini_container.height, fill_color=color, + fill_alpha=0.1) + fig.add_layout(color_box) + fig_border = fig.line([0, mini_box_border, mini_box_border, 0, 0], + [0 + y_offset, 0 + y_offset, mini_container.height + y_offset, + mini_container.height + y_offset, + 0 + y_offset], line_color=color, muted_alpha=0.2) + y_offset += mini_container.height + legend_label = "MC{} height:{} (hc{})".format(counter, int(mini_container.height), mini_container.hc_i) + legend_polygons.append(fig_border) + legend_mini_containers.append((legend_label, legend_polygons)) + spine_legend = [("spine", legend_spine)] + vertices_legend = [("vertices", legend_vertices)] + legend_items = legend_items + legend_mini_containers + spine_legend + vertices_legend + if reverse_legend: + legend_items.reverse() + legend = Legend(items=legend_items) + fig.add_layout(legend, 'right') + fig.legend.click_policy = "mute" + if render: + show(fig) + return fig + + +class ConvexContainer(object): + def __init__(self, polygons: [ConvexPolygon], steps=90, build_plots=True) -> None: + self.angle_0_end_container = pack_polygons(polygons) + self.angle_0_end_container_polygons = self.angle_0_end_container.polygons + self.rotate_center = (self.angle_0_end_container.max_width / 2, self.angle_0_end_container.max_height / 2) + self.rotated_end_container_list = [] # Liste aller Endcontainer + self.rotated_container_plots = [] + self.back_rotated_polygons_plots = [] + self.smallest_end_container, self.polygons, self.angle, self.area = self.find_convex_container(steps, + build_plots) + self.width = self.smallest_end_container.max_width + self.height = self.smallest_end_container.max_height + self.boundarys_x_values, self.boundarys_y_values = self.set_boundarys() + self.plot_steps_all = self.build_plot_steps() + + def build_plot_steps(self): + convex_c_panels = [] + smallest_c = self.plot_container(render=False, plot_width=800, plot_height=700) + smallest_c_tab = Panel(child=smallest_c, title="Smallest-Convex-Container") + convex_c_panels.append(smallest_c_tab) + + rotated_c = self.plot_rotated_containers(render=False, plot_width=800, plot_height=700) + rotated_c_tab = Panel(child=rotated_c, title="Rotated-End-Containers") + convex_c_panels.append(rotated_c_tab) + + back_rotated_c = self.plot_back_rotated_polygons(render=False, plot_width=800, plot_height=700) + back_rotated_c_tab = Panel(child=back_rotated_c, title="Convex-Containers (back rotated)") + convex_c_panels.append(back_rotated_c_tab) + + tabs = Tabs(tabs=convex_c_panels) + t_header = Panel(child=tabs, title="Convex-Container") # + tab_header = self.smallest_end_container.plot_steps(render=False) + tab_header.tabs.append(t_header) + return tab_header + + def plot_steps(self, render=True): + if render: + show(self.plot_steps_all) + return self.plot_steps_all + + def find_convex_container(self, steps: int, build_plots=True) -> (End_Container, [ConvexPolygon], int, float): + list_of_area = [] + polygons = [] + for angle in range(0, 360, steps): + polygons = rotate_polygons(self.angle_0_end_container_polygons, -angle, origin=self.rotate_center) + rotated_end_container = pack_polygons(polygons, -angle) + # rotated_end_container.angle=angle + self.rotated_end_container_list.append(rotated_end_container) + list_of_area.append(rotated_end_container) + if build_plots: # das Flag ist aus Performance gründen da sonst wird jeder End Container zurück rotiert + title = 'End-Container area: {} not-clipped-area: {} angle: {}'.format( + truncate(rotated_end_container.container_area, 1), + truncate(rotated_end_container.container_not_clipped_area, 1), rotated_end_container.angle) + self.rotated_container_plots.append(rotated_end_container.plot_container(render=False, title=title)) + back_rotated_polygons = rotate_polygons(rotated_end_container.polygons, angle, + origin=self.rotate_center) # kreiert neue Polygone + box_x_v = rotated_end_container.x_values_border + box_y_v = rotated_end_container.y_values_border + boundarys = list(zip(box_x_v, box_y_v)) + rotated_x_values, rotated_y_values = rotate_points_and_split(boundarys, angle, + origin=self.rotate_center) + title2 = 'Convex-Container area: {} not-clipped-area: {} angle: {}'.format( + truncate(rotated_end_container.container_area, 1), + truncate(rotated_end_container.container_not_clipped_area, 1), -rotated_end_container.angle) + back_rotated_polygon_plot = plot_polygons_in_single_plot(back_rotated_polygons, render=False, + border=(rotated_x_values, rotated_y_values), + title=title2) + self.back_rotated_polygons_plots.append(back_rotated_polygon_plot) + sorted_container = sorted(list_of_area, key=lambda k: k.container_area) + smallest_container = sorted_container[0] + angle = smallest_container.angle + smallest_container_polygons = sorted_container[0].polygons + smallest_back_rotated_polygons = rotate_polygons(smallest_container_polygons, angle, origin=self.rotate_center) + smallest_area = smallest_container.container_area + return (smallest_container, smallest_back_rotated_polygons, abs(angle), smallest_area) + + def set_boundarys(self) -> ([Point_xy], [Point_xy]): + container = self.smallest_end_container + boundarys_x_values = [0, 0, self.width, self.width, 0] + boundarys_y_values = [0, self.height, self.height, 0, 0] + boundarys = list(zip(boundarys_x_values, boundarys_y_values)) + rotated_x_values, rotated_y_values = rotate_points_and_split(boundarys, container.angle, + origin=self.rotate_center) + return (rotated_x_values, rotated_y_values) + + def plot_rotated_containers(self, render=True, colums=9, plot_width=600, plot_height=600) -> Column: + grid = gridplot(self.rotated_container_plots, ncols=colums, plot_width=plot_width, plot_height=plot_height, + toolbar_location="left") + if render: + show(grid) + return grid + + def plot_back_rotated_polygons(self, render=True, colums=9, plot_width=700, plot_height=600) -> Column: + grid = gridplot(self.back_rotated_polygons_plots, ncols=colums, plot_width=plot_width, plot_height=plot_height, + toolbar_location="left") + if render: + show(grid) + return grid + + def plot_container(self, title="", plot_width=600, plot_height=600, render=True, reverse_legend=True) -> Figure: + if title == "": + title = 'Convex Container area: {} not-clipped-area: {} angle: {}'.format( + truncate(self.smallest_end_container.container_area, 1), + truncate(self.smallest_end_container.container_not_clipped_area, 1), self.angle) + fig = plot_polygons_in_single_plot(self.polygons, title=title, plot_width=plot_width, plot_height=plot_height, + render=render, border=(self.boundarys_x_values, self.boundarys_y_values)) + return fig + + +def rotate_points_and_split(point_list: [Point_xy], angle, origin=(0, 0)) -> ([float], [float]): + poly_wrapper = Polygon(point_list) + poly_wrapper_rotated = affinity.rotate(poly_wrapper, angle, origin=origin) + return poly_wrapper_rotated.exterior.xy + + +def rotate_and_create_new_convex_polygon(polygon: ConvexPolygon, angle: int, origin=(0, 0)) -> ConvexPolygon: + poly_wrapper = Polygon(polygon.shell) + poly_wrapper_rotated = affinity.rotate(poly_wrapper, angle, origin=origin) + rotated_convex_polygon = ConvexPolygon(poly_wrapper_rotated.exterior.coords) + return rotated_convex_polygon + + +def rotate_polygons(polygons: [ConvexPolygon], angle: int, origin=(0, 0)) -> [ConvexPolygon]: + rotated_polygons = [] + for polygon in polygons: + rotated_polygon = rotate_and_create_new_convex_polygon(polygon, angle, origin) + rotated_polygons.append(rotated_polygon) + return rotated_polygons + + +def build_mini_containers_and_plots(container_array: [Container], c=2.214) -> ([Mini_Container], [[Figure]]): + mini_container_array = [] + mini_container_plots_list = [] + colors = itertools.cycle(palette) + background_color_list = [next(colors)] + for container in container_array: + container_sigma = copy.deepcopy(container.sigma) + container_and_mini_container_plots = [] + box_width = c * container.hc.w_max_polygon + box_width_helper = 0 + box_counter = 1 # hilft dabei wie oft der Container in Mini-Container geteilt wird + box_boundarys_x_values = [] + # für den plot die grenzen der miniboxen herauszufinden + while box_width_helper < container.x_boundary: + box_boundarys_x_values.append(box_width_helper) + box_width_helper += box_width + background_color_list.append(next(colors)) + box_boundarys_x_values_colors_tuple = (box_boundarys_x_values, background_color_list) + container_and_mini_container_plots.append(container.plot_container(container_sigma, render=False, + box_boundarys_x_values_colors_tuple=box_boundarys_x_values_colors_tuple)) # will added to the plots + max_width_mini_container = box_width + container.hc.w_max_polygon + background_counter = 0 + # wichtig zu kucken ob der container noch Polygone enthält da die linkesten Punkte noch in der anderen Box liegen können und eine Box leer sein kann + # while len(container_sigma) > 0 and (box_width * box_counter) < (container.x_boundary): + while len(container_sigma) > 0: + mini_container = Mini_Container(max_width_mini_container, (container.y_boundary), + container.hc.w_max_polygon, container.hc.i) + translation = box_width * (box_counter - 1) + min_translation = math.inf + mini_container_y_border = 0 + mini_container_x_border = 0 + # new + pop_list = [] # enthält die counter der Polygone die zur box gehören + for counter, polygon in enumerate(container_sigma): + if polygon.min_x < (box_width * box_counter): + pop_list.append(counter) + if polygon.min_x < min_translation: + min_translation = polygon.min_x + # selbst wenn man das 0 Element poped gibt es keine Probleme + pop_helper = 0 + if pop_list != []: + for counter in pop_list: + container_sigma[counter - pop_helper].translation(-min_translation, 0) # new + if mini_container_y_border < container_sigma[counter - pop_helper].max_y: + mini_container_y_border = container_sigma[counter - pop_helper].max_y + if mini_container_x_border < container_sigma[counter - pop_helper].max_x: + mini_container_x_border = container_sigma[counter - pop_helper].max_x + mini_container.polygons.append(container_sigma.pop(counter - pop_helper)) + pop_helper += 1 + # mini_container.plot_container() + mini_container.height = mini_container_y_border + mini_container.current_right_boundary = mini_container_x_border + mini_container_array.append(mini_container) + if (box_width * box_counter) < (container.x_boundary): + title = "Mini-Container{} height: {} (hc_{})".format(box_counter, truncate(mini_container.height, 1), + container.hc.i) + b_color = background_color_list[background_counter] # ---- + container_and_mini_container_plots.append( + mini_container.plot_container(title=title, render=False, background_c=b_color)) + box_counter += 1 + background_counter += 1 + # für die kürzere box + else: + title = "Mini-Container{} height: {} (hc_{})".format(box_counter, truncate(mini_container.height, 1), + container.hc.i) + # mini_container.plot_container(title)- + container_and_mini_container_plots.append(mini_container.plot_container(title=title, render=False)) + mini_container_plots_list.append(container_and_mini_container_plots) + return (mini_container_array, mini_container_plots_list) + + +def plot_mini_containers(plot_steps: [[Figure]], render=True, colums=3, plot_width=600, plot_height=600) -> Column: + plots = [] + for plot in plot_steps: + grid = gridplot(plot, ncols=colums, plot_width=plot_width, plot_height=plot_height, toolbar_location="left") + plots.append(grid) + if render: + show(layout(plots)) + return layout(plots) + + +def create_multiple_convex_polygons(number: int, max_ngon: int, max_rand=1000) -> [ConvexPolygon]: + polygon_list = [] + for count in range(0, number): + polygon_list.append(create_convex_polygon(max_ngon, max_rand)) + return polygon_list + + +def create_convex_polygon(max_ngon: int, + max_rand=1000) -> ConvexPolygon: # die erste Koordinate der konvexen Polygone wird dupliziert zum schließen des Polygons + ngon = numpy.random.randint(3, max_ngon + 1) + # polygon_points=[] + convex_polygon = None + while type(convex_polygon) is not Polygon: # da bei der Convexen Hülle ein Punkt oder String rauskommen kann + polygon_points = [] + while len(polygon_points) < ngon: + x = numpy.random.randint(0, max_rand + 1) + y = numpy.random.randint(0, max_rand + 1) + while (x, y) in polygon_points: + x = numpy.random.randint(0, max_rand + 1) + y = numpy.random.randint(0, max_rand + 1) + polygon_points.append((x, y)) + convex_polygon = Polygon(polygon_points).convex_hull + c_polygon = ConvexPolygon(list(convex_polygon.exterior.coords)) + return c_polygon + + +def plot_polygons(polygon_list: [ConvexPolygon], render=True, plot_width=450, plot_height=450, ncols=4) -> Column: + plots = [] + colors = itertools.cycle(palette) + for counter, polygon in enumerate(polygon_list): + color = next(colors) + title = "Polygon {}".format(counter) + plots.append(polygon.plot_polygon(title=title, color=color, render=False)) + grid = gridplot(plots, ncols=ncols, plot_width=plot_width, plot_height=plot_height, toolbar_location="left") + if render: + show(grid) + return grid + + +def plot_figures_as_grid(plot_list: [Figure], render=True, plot_width=600, plot_height=500, ncols=4) -> Column: + grid = gridplot(plot_list, ncols=ncols, plot_width=plot_width, plot_height=plot_height, toolbar_location="left") + if render: + show(grid) + return grid + + +def plot_polygons_in_single_plot(polygon_list: [ConvexPolygon], title="", plot_width=750, plot_height=500, render=True, + border=None, reverse_legend=False) -> Figure: + polygon_number = len(polygon_list) + + TOOLTIPS = [("index", "$index"), ("(x,y)", "($x{0.0}, $y{0.0})"), ] + fig = figure(title=title, x_axis_label='x', y_axis_label='y', width=plot_width, height=plot_height, + tooltips=TOOLTIPS, toolbar_location="left") + colors = itertools.cycle(palette) + legend_items = [] + legend_polygons = [] + legend_all_polygons = [] + legend_vertices = [] + for counter, polygon in enumerate(polygon_list): + color = next(colors) + x = polygon.x_values + y = polygon.y_values + if polygon.plot_fill: + legend_label = "polygon {} filled".format(counter) + poly_fig = fig.patch(x, y, color=color, line_width=1, alpha=0.9, line_alpha=1, muted_alpha=0.05) + else: + legend_label = "polygon {}".format(counter) + poly_fig = fig.patch(x, y, color=color, line_width=1, alpha=0.1, line_alpha=1, muted_alpha=0.05) + circle_fig = fig.circle(x, y, color=color, line_width=1, muted_alpha=0.01, size=4) + legend_polygons.append((legend_label, [poly_fig])) + legend_vertices.append(circle_fig) + legend_all_polygons = legend_all_polygons + [poly_fig] + if border != None: + fig_border = fig.line(border[0], border[1], line_color="red", line_width=1, muted_alpha=0.2) + legend_items.append(("border", [fig_border])) + + legend_items.append(("vertices", legend_vertices)) + legend_items.append(("all polygons", legend_all_polygons)) + legend_items = legend_items + legend_polygons + if reverse_legend: + legend_items.reverse() + legend = Legend(items=legend_items) + legend.label_text_font_size = "10px" + legend.click_policy = "mute" + fig.add_layout(legend, 'right') + if render: + show(fig) + return fig + + +def build_height_classes(polygon_list: [ConvexPolygon]) -> [HighClass]: + ordered_polygons = sorted(polygon_list, key=lambda polygon: polygon.height, reverse=True) + h_max_polygon = ordered_polygons[0].height + w_max_polygon = max([polygon.width for polygon in polygon_list]) + alpha = 0.407 + i = 0 + height_classes = [] + polygon_count = len(ordered_polygons) + while polygon_count > 0: + hc = HighClass(i, alpha, h_max_polygon, w_max_polygon) + hc_polygons = [] + while polygon_count > 0 and hc.min_border < ordered_polygons[0].height and ordered_polygons[ + 0].height <= hc.max_border: + hc_polygons.append(ordered_polygons.pop(0)) + polygon_count -= 1 + hc.set_polygons(hc_polygons) + if len(hc.polygons) > 0: + height_classes.append(hc) # will man höhen Klassen ohne Polygone drinne ? + i += 1 + return height_classes + + +def building_containers(height_classes: [HighClass]) -> [Container]: + containers = [] + for height_class in height_classes: + container = Container(height_class) + containers.append(container) + return containers + + +def pack_polygons(polygons: [ConvexPolygon], angle=0) -> End_Container: + # building the endcontainer + list_hc = build_height_classes(polygons) + list_containers = building_containers(list_hc) + list_mini_containers, mini_container_plot_steps = build_mini_containers_and_plots(list_containers) + end_container = End_Container(list_mini_containers, angle) + + # plots + p_tab = polygons_to_tab_plot(polygons) + p_header_tab = Panel(child=p_tab, title="Polygons") + hc_tab = hc_to_tab_plot(list_hc) + hc_header_tab = Panel(child=hc_tab, title="Height-Classes") + c_tab = containers_to_tab_plot(list_containers) + c_header_tab = Panel(child=c_tab, title="Containers") + mc_tab = mini_container_plots_to_tab_plot(mini_container_plot_steps) + mc_header_tab = Panel(child=mc_tab, title="Mini-Containers") + ec_tab = end_container_to_tab_plot(end_container) + ec_header_tab = Panel(child=ec_tab, title="End-Container") + all_tabs_with_header = Tabs(tabs=[p_header_tab, hc_header_tab, c_header_tab, mc_header_tab, ec_header_tab]) + + end_container.plot_steps_all = all_tabs_with_header + return end_container + + +def polygons_to_tab_plot(polygons: [ConvexPolygon], tab_poly_count=9, ncols=3, plot_width=450, plot_height=450) -> Tabs: + polygon_tab_list = [] + polygons_in_one_tab = [] + colors = itertools.cycle(palette) + for counter, polygon in enumerate(polygons): + color = next(colors) + polygon_title = "Polygon{}".format(counter) + polygon_plot = polygon.plot_polygon(title=polygon_title, color=color, render=False) + polygons_in_one_tab.append(polygon_plot) + if len(polygons_in_one_tab) >= tab_poly_count or (counter + 1 == len(polygons)): + # tab_layout= ([polygons_in_one_tab]) + if counter + 1 - tab_poly_count < 0: + title = "Polygons {}-{}".format(0, counter) + else: + title = "Polygons {}-{}".format(counter + 1 - len(polygons_in_one_tab), counter) + grid_title = Div(text="<b>{}<b>".format(title)) + polygons_grid = gridplot(polygons_in_one_tab, ncols=ncols, plot_width=plot_width, plot_height=plot_height, + toolbar_location="left") + tab_layout = layout(grid_title, polygons_grid) + tab = Panel(child=tab_layout, title=title) + polygon_tab_list.append(tab) + polygons_in_one_tab = [] + polygon_tabs = Tabs(tabs=polygon_tab_list) + return polygon_tabs + + +def hc_to_tab_plot(list_hc: [HighClass], plot_width=450, plot_height=450) -> Tabs: + hc_tab_list = [] + for counter, hc in enumerate(list_hc): + hc_plot = hc.plot_hc(render=False, plot_width=plot_width, plot_height=plot_height) + tab = Panel(child=hc_plot, title="High-Class {}".format(counter)) + hc_tab_list.append(tab) + hc_tabs = Tabs(tabs=hc_tab_list) + return hc_tabs + + +def containers_to_tab_plot(list_containers: [Container], plot_width=700, plot_height=700) -> Tabs: + container_tab_list = [] + for counter, container in enumerate(list_containers): + container_plot = container.plot_container_steps(plot_width=plot_width, colums=3, plot_height=plot_height, + render=False) + tab = Panel(child=container_plot, title="Container {}".format(counter, counter)) + container_tab_list.append(tab) + container_tabs = Tabs(tabs=container_tab_list) + return container_tabs + + +def mini_container_plots_to_tab_plot(mini_container_plot_steps: [Figure], plot_width=700, plot_height=700, + ncols=3) -> Tabs: + mini_plots_tabs = [] + for counter, m_plot in enumerate(mini_container_plot_steps): + m_plot_grid = gridplot(m_plot, ncols=3, plot_width=plot_width, plot_height=plot_height, toolbar_location="left") + grid_title = Div(text="<b>Hc{} to Mini-Containers<b>".format(counter)) + mc_layout = layout(grid_title, m_plot_grid) + tab = Panel(child=mc_layout, title="Hc{} Mini-Containers".format(counter)) + mini_plots_tabs.append(tab) + mini_tabs = Tabs(tabs=mini_plots_tabs) + return mini_tabs + + +def end_container_to_tab_plot(end_container: End_Container, plot_width=800, plot_height=800) -> Tabs: + end_container_tabs = [] + polygons_plot = end_container.plot_polygons(render=False, plot_width=plot_width, plot_height=plot_height) + tab = Panel(child=polygons_plot, title="End-Container") + end_container_tabs.append(tab) + container_plot = end_container.plot_container(render=False, plot_width=plot_width, plot_height=plot_height) + tab = Panel(child=container_plot, title="Show Mini-Containers") + end_container_tabs.append(tab) + end_tabs = Tabs(tabs=end_container_tabs) + return end_tabs + + +def plot_containers(container_list: [Container], render=True, colums=3, plot_width=500, plot_height=500) -> Column: + container_plots = [] + for container in container_list: + container_plots.append(container.plot_container(render=False)) + grid = gridplot(container_plots, ncols=colums, plot_width=plot_width, plot_height=plot_height, + toolbar_location="left") + if render: + show(grid) + return grid + + +# https://kodify.net/python/math/truncate-decimals/ +# Python.org (n.d.). math — Mathematical functions. Retrieved on October 22, 2019, from https://docs.python.org/3.8/library/math.html +def truncate(number: float, decimals=0) -> float: + """ + Returns a value truncated to a specific number of decimal places. + """ + if not isinstance(decimals, int): + raise TypeError("decimal places must be an integer.") + elif decimals < 0: + raise ValueError("decimal places has to be 0 or more.") + elif decimals == 0: + return math.trunc(number) + factor = 10.0 ** decimals + return math.trunc(number * factor) / factor + +# output_notebook() # for using Bokeh in Jupyter Lab \ No newline at end of file diff --git a/mysite/plots/plot_helpers.py b/mysite/plots/plot_helpers.py index 4793d656479b7f38fdd06aa526c6161d2d8a7233..9dcf768dfb683ed5bf247ee8ec8b1f5907324411 100644 --- a/mysite/plots/plot_helpers.py +++ b/mysite/plots/plot_helpers.py @@ -1,92 +1,92 @@ -import math -from django.shortcuts import render -from plotly.offline import plot -import plots.polygon as poly -from django.http import JsonResponse -from plotly.graph_objs import Scatter -import plotly.graph_objects as go -from django.http import HttpResponse -import pdb; pdb.set_trace -from plotly.subplots import make_subplots -import math - -def polygon_plot(polygons): - plot_polygon_list = [] - - polygon_count = len(polygons) - cols = 4 - rows = math.ceil(polygon_count / cols) - number = 0 - sub_plot_titles = ['{} height:{} slope:{}'.format(number, - (int(polygons[number].height * 10)) / 10, - (int(polygons[number].slope * 10)) / 10) - for number in range(0, polygon_count)] - - fig = make_subplots(rows=rows, cols=cols, subplot_titles=sub_plot_titles) - fig.update_layout(title="Convex Polygons") - counter = 0 - for polygon in polygons: - x_data = polygon.x_values - y_data = polygon.y_values - scatter = go.Scatter(x=x_data, y=y_data, - mode='lines', name='{}'.format(counter), - opacity=0.8, marker_color='green') - - spine_x_values = [x[0] for x in polygon.spine] - spine_y_values = [x[1] for x in polygon.spine] - scatter_spine = go.Scatter(x=spine_x_values, y=spine_y_values, - mode='lines', name='{} Spine'.format(counter), - opacity=0.8, marker_color='red') - row = math.ceil((counter + 1) / cols) - col = (counter % cols) + 1 - fig.add_trace(scatter, row=row, col=col) - fig.add_trace(scatter_spine, row=row, col=col) - counter += 1 - plot_polygons_div = plot(fig, output_type='div') - return plot_polygons_div - -def high_class_plot(high_classes): - plot_high_class_list = [] - polygon_number = 0 - polygon_title_number = 0 - for hc in high_classes: - polygon_count = len(hc.polygons) - cols = 4 - rows = math.ceil(polygon_count / cols) - - # sub_plot_titles = ['{} height:{} slope:{}'.format(number, - # (int(hc.spine_ordered_polygons[number].height * 10)) / 10, - # (int(hc.spine_ordered_polygons[number].slope * 10)) / 10) - # for number in range(0, polygon_count)] - sub_plot_titles=[] - for polygon in hc.spine_ordered_polygons: - - sub_plot_titles.append('{} height:{} slope:{}'.format(polygon_title_number, (int(polygon.height*10))/10,(int(polygon.slope * 10)) / 10)) - polygon_title_number += 1 - fig = make_subplots(rows=rows, cols=cols, subplot_titles=sub_plot_titles) - fig.update_layout(title="Highclass {} heights: {}-{}".format(hc.i, int(hc.min_border), int(hc.max_border))) - counter = 0 - - for polygon in hc.spine_ordered_polygons: - x_data = polygon.x_values - y_data = polygon.y_values - scatter = go.Scatter(x=x_data, y=y_data, - mode='lines', name='{}'.format(polygon_number), - opacity=0.8, marker_color='green') - - spine_x_values = [x[0] for x in polygon.spine] - spine_y_values = [x[1] for x in polygon.spine] - scatter_spine = go.Scatter(x=spine_x_values, y=spine_y_values, - mode='lines', name='{} Spine'.format(polygon_number), - opacity=0.8, marker_color='red') - row = math.ceil((counter + 1) / cols) - col = (counter % cols) + 1 - fig.add_trace(scatter, row=row, col=col) - fig.add_trace(scatter_spine, row=row, col=col) - counter += 1 - polygon_number += 1 - plt_div = plot(fig, output_type='div') - plot_high_class_list.append(plt_div) - return plot_high_class_list - - +# import math +# from django.shortcuts import render +# from plotly.offline import plot +# import plots.polygon as poly +# from django.http import JsonResponse +# from plotly.graph_objs import Scatter +# import plotly.graph_objects as go +# from django.http import HttpResponse +# import pdb; pdb.set_trace +# from plotly.subplots import make_subplots +# import math +# +# def polygon_plot(polygons): +# plot_polygon_list = [] +# +# polygon_count = len(polygons) +# cols = 4 +# rows = math.ceil(polygon_count / cols) +# number = 0 +# sub_plot_titles = ['{} height:{} slope:{}'.format(number, +# (int(polygons[number].height * 10)) / 10, +# (int(polygons[number].slope * 10)) / 10) +# for number in range(0, polygon_count)] +# +# fig = make_subplots(rows=rows, cols=cols, subplot_titles=sub_plot_titles) +# fig.update_layout(title="Convex Polygons") +# counter = 0 +# for polygon in polygons: +# x_data = polygon.x_values +# y_data = polygon.y_values +# scatter = go.Scatter(x=x_data, y=y_data, +# mode='lines', name='{}'.format(counter), +# opacity=0.8, marker_color='green') +# +# spine_x_values = [x[0] for x in polygon.spine] +# spine_y_values = [x[1] for x in polygon.spine] +# scatter_spine = go.Scatter(x=spine_x_values, y=spine_y_values, +# mode='lines', name='{} Spine'.format(counter), +# opacity=0.8, marker_color='red') +# row = math.ceil((counter + 1) / cols) +# col = (counter % cols) + 1 +# fig.add_trace(scatter, row=row, col=col) +# fig.add_trace(scatter_spine, row=row, col=col) +# counter += 1 +# plot_polygons_div = plot(fig, output_type='div') +# return plot_polygons_div +# +# def high_class_plot(high_classes): +# plot_high_class_list = [] +# polygon_number = 0 +# polygon_title_number = 0 +# for hc in high_classes: +# polygon_count = len(hc.polygons) +# cols = 4 +# rows = math.ceil(polygon_count / cols) +# +# # sub_plot_titles = ['{} height:{} slope:{}'.format(number, +# # (int(hc.spine_ordered_polygons[number].height * 10)) / 10, +# # (int(hc.spine_ordered_polygons[number].slope * 10)) / 10) +# # for number in range(0, polygon_count)] +# sub_plot_titles=[] +# for polygon in hc.spine_ordered_polygons: +# +# sub_plot_titles.append('{} height:{} slope:{}'.format(polygon_title_number, (int(polygon.height*10))/10,(int(polygon.slope * 10)) / 10)) +# polygon_title_number += 1 +# fig = make_subplots(rows=rows, cols=cols, subplot_titles=sub_plot_titles) +# fig.update_layout(title="Highclass {} heights: {}-{}".format(hc.i, int(hc.min_border), int(hc.max_border))) +# counter = 0 +# +# for polygon in hc.spine_ordered_polygons: +# x_data = polygon.x_values +# y_data = polygon.y_values +# scatter = go.Scatter(x=x_data, y=y_data, +# mode='lines', name='{}'.format(polygon_number), +# opacity=0.8, marker_color='green') +# +# spine_x_values = [x[0] for x in polygon.spine] +# spine_y_values = [x[1] for x in polygon.spine] +# scatter_spine = go.Scatter(x=spine_x_values, y=spine_y_values, +# mode='lines', name='{} Spine'.format(polygon_number), +# opacity=0.8, marker_color='red') +# row = math.ceil((counter + 1) / cols) +# col = (counter % cols) + 1 +# fig.add_trace(scatter, row=row, col=col) +# fig.add_trace(scatter_spine, row=row, col=col) +# counter += 1 +# polygon_number += 1 +# plt_div = plot(fig, output_type='div') +# plot_high_class_list.append(plt_div) +# return plot_high_class_list +# +# diff --git a/mysite/plots/polygon.py b/mysite/plots/polygon.py deleted file mode 100644 index eaee6603f2c53982f8f610f5f82a1b2975f3c5b5..0000000000000000000000000000000000000000 --- a/mysite/plots/polygon.py +++ /dev/null @@ -1,1434 +0,0 @@ -import sys, path -import mpld3 -#import import_ipynb -from plots import avl_tree -import pandas as pd -from matplotlib import pyplot as plt -from shapely.geometry import Point, Polygon, LineString -from shapely.geometry.base import BaseGeometry, geos_geom_from_py -from shapely import affinity -import numpy -import numpy as np -import math -import mplcursors -from fractions import Fraction -import random -from copy import deepcopy -from plotly.subplots import make_subplots -import plotly.graph_objects as go -from plotly.offline import plot -from bokeh.plotting import figure -from bokeh.io import output_notebook, show -from bokeh.layouts import gridplot, row, layout -from bokeh.models import Legend -from bokeh.models import Arrow, NormalHead, OpenHead, VeeHead -from bokeh.core.properties import Enum -from bokeh.layouts import column -from bokeh.models import Div, BoxAnnotation -from bokeh.models import ColumnDataSource, Label, LabelSet, Range1d -from bokeh.palettes import Dark2_5 as palette -from bokeh.palettes import Viridis256 -from bokeh.models import CustomJS -import itertools - -a = 0.407 - - -class Polygon2(object): - - def __init__(self, shell=None, holes=None): - # super().__init__(shell=None, holes=None) - self.shell = shell - self.x_values = [vertex[0] for vertex in shell] - self.y_values = [vertex[1] for vertex in shell] - self.min_x, self.max_x = self.min_x_max_x(shell) - self.min_y, self.max_y = self.min_y_max_y(shell) - self.height = self.height(shell) - self.width = self.width(shell) - self.spine = self.spine(self.shell) - self.left, self.right = self.splitter() - self.slope = self.slope(self.spine) - - def min_x_max_x(self, shell): - x_values = [point[0] for point in shell] - return (min(x_values), max(x_values)) - - def min_y_max_y(self, shell): - y_values = [point[1] for point in shell] - return (min(y_values), max(y_values)) - - def height(self, coord): - height = self.max_y - self.min_y - return height - - def width(self, coord): - width = self.max_x - self.min_x - return width - - def translation(self, x, y): - self.shell = [(point[0] + x, point[1] + y) for point in self.shell] - self.spine = ((self.spine[0][0] + x, self.spine[0][1] + y), (self.spine[1][0] + x, self.spine[1][1] + y)) - self.left = [(point[0] + x, point[1] + y) for point in self.left] - self.right = [(point[0] + x, point[1] + y) for point in self.right] - self.min_x = self.min_x + x - self.max_x = self.max_x + x - self.min_y = self.min_y + y - self.max_y = self.max_y + y - self.x_values = [vertex + x for vertex in self.x_values] - self.y_values = [vertex + y for vertex in self.y_values] - return self.shell - - def spine(self, shell): - y_sorted_p_p = sorted(shell, key=lambda k: k[ - 1]) # Parser schreibt oder davon ausgeht das konvexe Polygone übergeben werden - if y_sorted_p_p[0][1] == y_sorted_p_p[1][1]: - if y_sorted_p_p[0][0] < y_sorted_p_p[1][0]: - spine_bottom = y_sorted_p_p[0] - else: - spine_bottom = y_sorted_p_p[1] - else: - spine_bottom = y_sorted_p_p[0] - if y_sorted_p_p[-2][1] == y_sorted_p_p[-1][1]: - if y_sorted_p_p[-2][0] < y_sorted_p_p[-1][0]: - spine_top = y_sorted_p_p[-1] - else: - spine_top = y_sorted_p_p[-2] - else: - spine_top = y_sorted_p_p[-1] - return (spine_bottom, spine_top) - - def slope(self, spine): - if spine[0][0] == spine[1][0]: # Sonderfall für eine senkrechte - slope = math.inf - else: - slope = (spine[1][1] - spine[0][1]) / (spine[1][0] - spine[0][ - 0]) # m = y2-y1/x2-x1 Formel für die Geradensteigung mithilfe aus zwei verschiedenen Punkten der Geraden - return slope - - def plot_polygon(self, title="", render=True): - """Plotting a Polygon with bokeh""" - height = (int(self.height * 10)) / 10 - if self.slope == math.inf: - slope = math.inf - else: - slope = (int(self.slope * 10)) / 10 - x_data = self.x_values - y_data = self.y_values - TOOLTIPS = [("index", "$index"), ("(x,y)", "($x, $y)"), ] - if title == "": - title = 'height:{} slope:{}'.format(height, slope) - else: - title = '{} height:{} slope:{}'.format(title, height, slope) - fig = figure(title=title, x_axis_label='x', y_axis_label='y', tooltips=TOOLTIPS, ) - fig.line(x_data, y_data, legend_label="Shell", line_width=2, muted_alpha=0.2) - fig.circle(x_data, y_data, legend_label="Shell", line_width=2, muted_alpha=0.2, size=8) - spine_x_values = [x[0] for x in self.spine] - spine_y_values = [x[1] for x in self.spine] - fig.line(spine_x_values, spine_y_values, line_color="red", legend_label="Spine", line_width=2, muted_alpha=0.2) - fig.legend.click_policy = "mute" - if render: - return show(fig) - else: - return fig - - def splitter(self): - left = [] - right = [] - spine_bottom = self.spine[0] - spine_top = self.spine[1] - help_array = self.shell.copy() - if help_array[0] == help_array[-1]: # falls letztes element doppelt - help_array = help_array[0:-1] - spine_bottom_found = False - spine_top_found = False - spine_bottom_not_horizontal = False - while spine_bottom_found == False: # Phase 1 der Funktion sie sucht den bottom spine, dabei werden die Ecken die nicht der Spine Bottom sind ans Ende der Liste geschoben - if help_array[0] == spine_bottom: - if spine_bottom[1] != help_array[-1][ - 1]: # checkt ob Spine bottom ein horizontalen Nachbar hat falls ja wird ein Flag gesetzt damit Spine bottomt später nicht in die Rechte mitgenommen wird - spine_bottom_not_horizontal = True - spine_bottom_found = True - left.append(help_array.pop(0)) - else: - help_array.append(help_array.pop(0)) - while spine_top_found == False: # iterieren die Liste erneut durch bis wir spine top finden, falls spine top gefunden wurde wird auch geschaut ob spine top ein horizontalen linken - if help_array[0] == spine_top: # Nachbar hat falls ja wird spine top nicht in die Linke Liste miteingefügt - spine_top_found = True - if spine_top[1] != left[-1][1]: - left.append(spine_top) - else: - left.append(help_array.pop(0)) - right = help_array.copy() - if spine_bottom_not_horizontal: - right.append(spine_bottom) - return (left, right) - - -class HighClass(object): - def __init__(self, i, alpha, h_max, w_max): - self.i = i - self.alpha = alpha - self.h_max = h_max - self.w_max = w_max - self.min_border = alpha ** (i + 1) * h_max - self.max_border = alpha ** (i) * h_max - self.polygons = [] - self.spine_ordered_polygons = [] - - def spine_order_polygons(self): - spine_ordered_polygons = sorted(self.polygons, key=lambda polygon: polygon.slope) - self.spine_ordered_polygons = spine_ordered_polygons - return spine_ordered_polygons - - def plot_hc(self, ordered=False, render=True, plot_width=250, plot_height=250): - plots = [] - if ordered: - polygon_list = self.spine_ordered_polygons - else: - polygon_list = self.polygons - for counter, polygon in enumerate(polygon_list): - title = "Polygon {}".format(counter) - plots.append(polygon.plot_polygon(title=title, render=False)) - grid = gridplot(plots, ncols=4, plot_width=plot_width, plot_height=plot_height) - if render: - return show(grid) - else: - return grid - - -def height_classes(polygon_list): - ordered_polygons = sorted(polygon_list, key=lambda polygon: polygon.height, reverse=True) - h_max = ordered_polygons[0].height - # max([polygon.height for polygon in polygon_list]) - w_max = max([polygon.width for polygon in polygon_list]) - alpha = 0.407 - i = 0 - # h_i = height_max - height_classes = [] - response = [] - polygon_count = len(ordered_polygons) - while polygon_count > 0: - hc = HighClass(i, alpha, h_max, w_max) - # polygon_count= len(ordered_polygons) - while polygon_count > 0 and hc.min_border < ordered_polygons[0].height and ordered_polygons[ - 0].height <= hc.max_border: - # print (alpha**(i+1)*h_max, ordered_polygons[0].height,alpha**(i)*h_max) # print - hc.polygons.append(ordered_polygons.pop(0)) - polygon_count -= 1 - hc.spine_order_polygons() - if len(hc.polygons) > 0: - height_classes.append(hc) # will man höhen Klassen ohne Polygone drinne ? - # response.append([polygon.height for polygon in hc.polygons]) # print - i += 1 - # print(Hresponse) - # print([y.polygons for y in height_classes]) - return height_classes - - -def create_multiple_convex_polygons(number, max_ngon): - polygon_list = [] - for count in range(0, number): - polygon_list.append(create_convex_polygon(max_ngon)) - return polygon_list - - -def create_convex_polygon( - max_ngon): # die erste Koordinate der konvexen Polygone wird dupliziert zum schließen des Polygons - convex = False - ngon = numpy.random.randint(3, max_ngon + 1) - # ries=0 - max_rand = 1000 - - # tries=tries+1 - polygon_points = [] - while len(polygon_points) < ngon: - - x = numpy.random.randint(1, max_rand) - y = numpy.random.randint(1, max_rand) - # x = numpy.random.random() - # y = numpy.random.random() - while (x, y) in polygon_points: - # x = numpy.random.random() - # y = numpy.random.random() - x = numpy.random.randint(1, max_rand) - y = numpy.random.randint(1, max_rand) - polygon_points.append((x, y)) - - polygon = Polygon(polygon_points) - polygon_parent_class = polygon.convex_hull - polygon2 = Polygon2(list(polygon_parent_class.exterior.coords)) - # randomint = numpy.random.randint(minvert,maxvert) - # response= numpy.random.rand(randomint,2) - return polygon2 - - -def plot_polygons(polygon_list, render=True, plot_width=250, plot_height=250): - plots = [] - for counter, polygon in enumerate(polygon_list): - title = "Polygon {}".format(counter) - plots.append(polygon.plot_polygon(title=title, render=False)) - grid = gridplot(plots, ncols=4, plot_width=plot_width, plot_height=plot_height) - if render: - return show(grid) - else: - return grid - - -def plot_polygons_in_single_plot(polygon_list, title="", render=True, border=None): - polygon_number = len(polygon_list) - # x_data = self.x_values - # y_data = self.y_values - TOOLTIPS = [("index", "$index"), ("(x,y)", "($x, $y)"), ] - # if title=="": - # title= 'height:{} slope:{}'.format(height,slope) - # else: - # title= '{} height:{} slope:{}'.format(title,height,slope) - fig = figure(title=title, x_axis_label='x', y_axis_label='y', tooltips=TOOLTIPS, toolbar_location="below") - colors = itertools.cycle(palette) - legend_items = [] - legend_polygons = [] - for counter, polygon in enumerate(polygon_list): - color = next(colors) - x = polygon.x_values - y = polygon.y_values - legend_label = "Polygon {}".format(counter) - poly_fig = fig.line(x, y, color=color, line_width=2, muted_alpha=0.2) - circle_fig = fig.circle(x, y, color=color, line_width=2, muted_alpha=0.2, size=8) - legend_polygons.append((legend_label, [poly_fig, circle_fig])) - # spine_x_values = [x[0] for x in self.spine] - # spine_y_values = [x[1] for x in self.spine] - if border != None: - fig_border = fig.line(border[0], border[1], line_color="red", line_width=2, muted_alpha=0.2) - legend_items.append(("border", [fig_border])) - legend_items = legend_items + legend_polygons - legend = Legend(items=legend_items) - legend.click_policy = "mute" - fig.add_layout(legend, 'right') - fig.legend.click_policy = "mute" - if render: - return show(fig) - else: - return fig - - -def pack_polygons(polygons): - copy_polygons = deepcopy(polygons) - list_hc = height_classes(copy_polygons) - list_containers = building_containers(list_hc) - list_mini_containers = pack_mini_containers(list_containers) - end_container = End_Container(list_mini_containers) - return end_container - - -# https://kodify.net/python/math/truncate-decimals/ -def truncate(number, decimals=0): - """ - Returns a value truncated to a specific number of decimal places. - """ - if not isinstance(decimals, int): - raise TypeError("decimal places must be an integer.") - elif decimals < 0: - raise ValueError("decimal places has to be 0 or more.") - elif decimals == 0: - return math.trunc(number) - - factor = 10.0 ** decimals - return math.trunc(number * factor) / factor - - - -class Container(object): - def __init__(self, hc): - self.hc = hc - self.hc_copy = deepcopy(hc) - self.y_boundary = hc.max_border - self.x_boundary = 0 - self.sigma = [] - self.Tree = avl_tree.AVLTree() - self.root = None - self.box_boundarys_x_values = [] - self.plot_steps = [] - - def plot_container(self, sigma=None, r_l_distances=None, l_r_distances=None, min_distance=None, render=True, - title="", background_c_list=None): - legend_polygons = [] - legend_spine = [] - legend_lr = [] - legend_rl = [] - if sigma == None: - sigma = self.sigma - TOOLTIPS = [("index", "$index"), ("(x,y)", "($x, $y)"), ] - # if title: - # title=title - # else: - # title="" - fig = figure(title=title, x_axis_label='x', y_axis_label='y', tooltips=TOOLTIPS, toolbar_location="below") - for counter, polygon in enumerate(sigma): - x_values = [] - y_values = [] - for x, y in polygon.shell: - x_values.append(x) - y_values.append(y) - poly_fig = fig.line(x_values, y_values, line_width=2, muted_alpha=0.2) - circle_fig = fig.circle(x_values, y_values, line_width=2, muted_alpha=0.2) - legend_label = "Polygon{}".format(counter) - legend_polygons.append((legend_label, [poly_fig, circle_fig])) - x_spine = [x[0] for x in polygon.spine] - y_spine = [y[1] for y in polygon.spine] - - spine_fig = fig.line(x_spine, y_spine, line_color="red", line_width=2, muted_alpha=0.2) - legend_spine.append(spine_fig) - # mini-Container helper - if self.box_boundarys_x_values != []: - # print("self.box_boundarys_x_values",self.box_boundarys_x_values) - for counter, boundary in enumerate(self.box_boundarys_x_values[0:-1]): - next_boundary = self.box_boundarys_x_values[counter + 1] - if background_c_list != None: - color_box = BoxAnnotation(bottom=0, top=self.y_boundary, left=self.box_boundarys_x_values[counter], - right=next_boundary, fill_color=background_c_list[counter], - fill_alpha=0.1) - fig.add_layout(color_box) - fig.line([next_boundary, next_boundary], [0, self.y_boundary], line_dash="dotted") - fig.title.text = 'hc_{} Container -> Mini Containers'.format(self.hc.i) - if title == "": - fig.title.text = 'hc_{} Container'.format(self.hc.i) - if r_l_distances != None: - for tuple in r_l_distances: - x = tuple[0][0] - corresponding_point_x = x - tuple[1] - y = tuple[0][1] - text_point_x, text_point_y = (x - tuple[1] / 2, y) - distance = int(tuple[1]) - color = "blue" - if distance == int(min_distance): - line_dash = "solid" - else: - line_dash = "dotted" - fig_rl = fig.line([tuple[0][0], corresponding_point_x], [y, y], line_color=color, line_width=2, - muted_alpha=0.2, line_dash=line_dash) - source = ColumnDataSource(data=dict(x=[tuple[0][0] - (tuple[1] / 2)], y=[y], names=[distance])) - labels = LabelSet(x='x', y='y', text='names', level='glyph', x_offset=0, y_offset=0, source=source, - render_mode='canvas') - fig.add_layout(labels) - # fig_triangle_rl=fig.triangle([tuple[0][0],corresponding_point_x],[y,y],line_color=color,line_width=2, muted_alpha=0.2,angle=-90,angle_units="deg",size=6,fill_color=color) - # fig_triangle_rl=fig.triangle([tuple[0][0]-(tuple[1]/2)],[y],line_color=color,line_width=2, muted_alpha=0.2,angle=-90,angle_units="deg",size=6,fill_color=color) - legend_rl.append(fig_rl) - # legend_rl.append(fig_triangle_rl) - if l_r_distances != None: - for tuple in l_r_distances: - x = tuple[0][0] - corresponding_point_x = x + tuple[1] - y = tuple[0][1] - text_point_x, text_point_y = (x + tuple[1] / 2, y) - distance = int(tuple[1]) - color = "green" - if distance == int(min_distance): - line_dash = 'solid' - else: - line_dash = "dotted" - fig_lr = fig.line([tuple[0][0], corresponding_point_x], [y, y], line_color=color, line_width=2, - muted_alpha=0.2, line_dash=line_dash) - # fig_triangle_lr=fig.triangle([tuple[0][0],corresponding_point_x],[y,y],line_color=color,line_width=2, muted_alpha=0.2,angle=90,angle_units="deg",size=6,fill_color=color) - source = ColumnDataSource(data=dict(x=[tuple[0][0] + (tuple[1] / 2)], y=[y], names=[distance])) - labels = LabelSet(x='x', y='y', text='names', level='glyph', x_offset=0, y_offset=0, source=source, - render_mode='canvas') - fig.add_layout(labels) - legend_lr.append(fig_lr) - # legend_lr.append(fig_triangle_lr) - # building the custom legend - fig_boundary = fig.line([0, self.x_boundary, self.x_boundary, 0, 0], - [0, 0, self.y_boundary, self.y_boundary, 0], line_color="black", line_width=2, - muted_alpha=0.2, ) - items = legend_polygons + [("spine", legend_spine)] - if l_r_distances != None: - items.append(("distance-lr", legend_lr)) - if r_l_distances != None: - items.append(("distance-rl", legend_rl)) - items.append(("boundary", [fig_boundary])) - legend = Legend(items=items) - legend.click_policy = "mute" - fig.add_layout(legend, 'right') - if render: - return show(fig) - else: - return fig - - def plot_container_steps(self, render=True, colums=2, plot_width=600, plot_height=600): - grid = gridplot(self.plot_steps, ncols=colums, plot_width=plot_width, plot_height=plot_height) - min_border = (int(self.hc.min_border * 10)) / 10 - max_border = (int(self.hc.max_border * 10)) / 10 - # title = Div(text="<h1>Highclass Container {}, Polygon height: {}-{} </h1>".format(self.hc.i,min_border,max_border)) - # r = column(title, grid) - if render: - return show(grid) - else: - return grid - - # if render: - # return show(grid) - # else: - # return grid - - # def plot_container(self, sigma=None, r_l_distances=None,l_r_distances=None,min_distance=None): - # fig, ax = plt.subplots(facecolor='w', edgecolor='k', figsize=(20,12), dpi=90) - # #x,y= self.exterior.xy - # if sigma==None: - # sigma=self.sigma - # for polygon in sigma: - # x=[] - # y=[] - # for x_text, y_text in polygon.shell : - # x.append(x_text) - # y.append(y_text) - # #ax.text(x_text, y_text, '({}, {})'.format(int(x_text*10)/10, int(y_text*10)/10)) - # #print(x,y) - # ax.plot(x, y) - # ax.scatter(x, y, s=60) - # x1 = [x[0]for x in polygon.spine] - # y1= [x[1]for x in polygon.spine] - # ax.plot(x1,y1, linewidth=2,color='black') - # if self.box_boundarys_x_values!=[]: - # for boundary in self.box_boundarys_x_values: - # ax.plot([self.box_boundarys_x_values,self.box_boundarys_x_values],[0,self.y_boundary],linestyle='--') - # ax.set_title('hc_{} Container -> Mini Containers'.format(self.hc.i)) - # else: - # ax.set_title('hc_{} Container'.format(self.hc.i)) - # if r_l_distances!= None: - # for tuple in r_l_distances: - # x = tuple[0][0] - # corresponding_point_x = x-tuple[1] - # y = tuple[0][1] - # text_point_x,text_point_y = (x-tuple[1]/2,y) - # distance = int(tuple[1]) - # ax.text(text_point_x, text_point_y, '{}'.format(distance)) - # if distance==int(min_distance): - # ax.plot([tuple[0][0],corresponding_point_x],[y,y],linestyle='--',marker='<',color='green') - # else: - # ax.plot([tuple[0][0],corresponding_point_x],[y,y],linestyle='--',marker='<',color='red') - # if l_r_distances!= None: - # for tuple in l_r_distances: - # x = tuple[0][0] - # corresponding_point_x = x+tuple[1] - # y = tuple[0][1] - # text_point_x,text_point_y = (x+tuple[1]/2,y) - # distance = int(tuple[1]) - # ax.text(text_point_x, text_point_y, '{}'.format(distance)) - # if distance==int(min_distance): - # ax.plot([tuple[0][0],corresponding_point_x],[y,y],linestyle='--',marker='>',color='green') - # else: - # ax.plot([tuple[0][0],corresponding_point_x],[y,y],linestyle='--',marker='>',color='blue') - # mplcursors.cursor() - # ax.plot([0,self.x_boundary,self.x_boundary,0,0],[0,0,self.y_boundary,self.y_boundary,0]) - # return plt.show() - - def slope3(self, spine, point1): - # y = m*x+n - # (y-n)/m=x - # n = y-m*x - if spine[0][0] == spine[1][0]: # Sonderfall für eine senkrechte - distance = math.sqrt((spine[0][0] - point1[ - 0]) ** 2) # da der spine eine senkrechte ist -> der eintreffpunkt hat den gleichen y wert wie der punkt, in der Abstand formel fällt dieser wert weg - elif spine[0][1] == point1[1]: - distance = math.sqrt((spine[0][0] - point1[0]) ** 2 + (spine[0][1] - point1[1]) ** 2) - else: - slope = (spine[1][1] - spine[0][1]) / (spine[1][0] - spine[0][ - 0]) # m = y2-y1/x2-x1 Formel für die Geradensteigung mithilfe aus zwei verschiedenen Punkten der Geraden - # print("steigung", slope) - # print(point1[1]) - n = spine[0][1] - (slope * spine[0][0]) - # print("y-achsenabnschnitt",n) - point0_x = (point1[1] - n) / slope # x=(y-n)/m - # print("x-wert vom punkt",point0_x) - point0 = (point0_x, point1[1]) - distance = math.sqrt((point0[0] - point1[0]) ** 2 + (point0[1] - point1[1]) ** 2) - return distance - - def find_successor(self, vertex, array): - for counter, top_edge_point in enumerate(array): - if top_edge_point[1] >= vertex[1]: - return (array[counter - 1], top_edge_point) - - def packing_container(self, hc_polygons): - tree = self.Tree - p = [] - l = [] - r = [] - b = [] - sigma_helper = [] # vi - step_counter = 0 - for polygon in hc_polygons: - sigma_helper.append(polygon) - if self.sigma == []: - transform_x = -polygon.min_x - transform_y = -polygon.min_y - # polygon.plot_polygon("before translation") - polygon.translation(transform_x, transform_y) - - # polygon.plot_polygon("after translation") - polygon_vertices = len(polygon.right) - for count in range(0, polygon_vertices - 1): - vertice = polygon.right[count] - vertice_neighbour = polygon.right[count + 1] - self.root = self.Tree.insert_node(self.root, vertice[1], vertice, vertice_neighbour) - self.sigma.append(polygon) - self.x_boundary += polygon.width - t = deepcopy(self.sigma) # vi - # t.append(polygon) # vi - # self.plot_container(t) # vi - - self.plot_steps.append( - self.plot_container(sigma_helper, render=False, title="Step {}".format(step_counter))) - step_counter += 1 - else: - # print("self.x boundary",self.x_boundary)#p - # if polygon.min_x < self.x_boundary: - transform_x = (self.x_boundary + abs(polygon.min_x)) + 10 - # print("x_boundary:",self.x_boundary,"polygon min x abs",abs(polygon.min_x))#p - # print("transform x:",transform_x)#p - # print("polygon min x",polygon.min_x)#p - # else: - # transform_x=0 - transform_y = -polygon.min_y - polygon.translation(transform_x, transform_y) - # print(self.sigma) # vi - min_horizontal_distance = math.inf - # print("tree/n",tree.printHelper(self.root, "", True))#p - helper_0 = [] - for vertex in polygon.left: - vertex_y = vertex[1] - successor_vertex = self.Tree.find_edges(self.root, vertex_y, self.root) - corresponding_edge_points = (successor_vertex.vertice, successor_vertex.vertice_neighbour) - # print("corresponding edge points",corresponding_edge_points,"for vertex",vertex)#p - distance = self.slope3(corresponding_edge_points, vertex) - if distance <= min_horizontal_distance: - min_horizontal_distance = distance - helper_0.append((vertex, distance)) - # print("min_horizontal distance right to left",min_horizontal_distance)#p - # print("helper_0",helper_0)#p - key = polygon.spine[1][1] - # print("key to order tree array", key)#p - tree_array = self.Tree.preOrder_array((self.root), [], key) - # print("tree_array in order ",tree_array)#p - helper_1 = [] - for vertex in tree_array: - # print("vertex",vertex)#p - # print("polygon left vertices",polygon.left)#p - successor = self.find_successor(vertex, polygon.left) - # print(successor)#p - distance = self.slope3(successor, vertex) - # print("distance",distance) #p - if distance <= min_horizontal_distance: - min_horizontal_distance = distance - self.root = self.Tree.delete_node(self.root, vertex[1]) # deleting vertices from B - helper_1.append((vertex, distance)) # ------- - # for count in range(0,polygon_vertices-1): - # vertice = polygon.translated_right[count] - # vertice_neighbour = polygon.translated_right[count+1] - # self.root = self.Tree.insert_node(self.root,vertice[1],vertice,vertice_neighbour) - # print("min_horizontal distance left to right ",min_horizontal_distance) #p - # self.plot_container(sigma_helper,helper_0,helper_1,min_horizontal_distance) #--------------------- - self.plot_steps.append( - self.plot_container(sigma_helper, helper_0, helper_1, min_horizontal_distance, render=False, - title="Step {}".format(step_counter))) - step_counter += 1 - polygon.translation(-(min_horizontal_distance), 0) - # print(polygon.right)# p - for counter, vertex in enumerate(polygon.right[0:-1]): - self.root = self.Tree.insert_node(self.root, vertex[1], vertex, (polygon.right[counter + 1])) - x_boundary = max([vertex[0] for vertex in polygon.right] + [self.x_boundary]) - self.x_boundary = x_boundary - self.sigma.append(polygon) - self.plot_steps.append(self.plot_container(self.sigma, render=False, title="Finished Container")) - return self.sigma - - -def building_containers(height_classes, plot=None): - containers = [] - for height_class in height_classes: - container = Container(height_class) - if plot == True: - container.packing_container(container.hc.spine_ordered_polygons) - else: - container.packing_container(container.hc.spine_ordered_polygons) - containers.append(container) - return containers - - -class Mini_Container(object): - def __init__(self, max_width, max_height, max_polygon_width, hc_i): - self.max_polygon_width = max_polygon_width - self.current_right_boundary = 0 - self.height = 0 - self.hc_i = hc_i - self.hc_height = max_height - self.max_width = max_width - - self.c = 2.214 - self.polygons = [] - self.y_offset = 0 - self.plot_steps = [] - - def plot_container(self, render=True, title="", background_c=None): - legend_polygons = [] - legend_spine = [] - legend_lr = [] - legend_rl = [] - TOOLTIPS = [("index", "$index"), ("(x,y)", "($x, $y)"), ] - fig = figure(title=title, x_axis_label='x', y_axis_label='y', tooltips=TOOLTIPS, toolbar_location="below") - if background_c != None: - # fig.background_fill_color = background_c - # fig.background_fill_alpha = 0.1 - color_box = BoxAnnotation(left=0, right=self.max_width, bottom=self.y_offset, - top=self.y_offset + self.height, fill_color=background_c, - fill_alpha=0.1) - fig.add_layout(color_box) - for counter, polygon in enumerate(self.polygons): - x_values = [] - y_values = [] - for x, y in polygon.shell: - x_values.append(x) - y_values.append(y) - poly_fig = fig.line(x_values, y_values, line_width=2, muted_alpha=0.2) - circle_fig = fig.circle(x_values, y_values, line_width=2, muted_alpha=0.2) - legend_label = "Polygon{}".format(counter) - legend_polygons.append((legend_label, [poly_fig, circle_fig])) - x_spine = [x[0] for x in polygon.spine] - y_spine = [y[1] for y in polygon.spine] - - spine_fig = fig.line(x_spine, y_spine, line_color="red", line_width=2, muted_alpha=0.2) - legend_spine.append(spine_fig) - # mini-Container helper - # old split line - - # building the custom legend - fig_boundary = fig.line([0, self.max_width, self.max_width, 0, 0], - [0 + self.y_offset, 0 + self.y_offset, self.height + self.y_offset, - self.height + self.y_offset, 0 + self.y_offset] - , line_color="black", line_width=2, muted_alpha=0.2, ) - fig_polygon_boundary = fig.line([self.current_right_boundary, self.current_right_boundary], - [0 + self.y_offset, self.height + self.y_offset] - , line_color="black", line_dash="dotted", line_width=2, muted_alpha=0.2, ) - items = legend_polygons + [("spine", legend_spine)] - items.append(("container-boundary", [fig_boundary])) - items.append(("last polygon-boundary", [fig_polygon_boundary])) - legend = Legend(items=items) - legend.click_policy = "mute" - fig.add_layout(legend, 'right') - if render: - return show(fig) - else: - return fig - - -# def plot_container(self,title=None): -# #fig, ax = plt.subplots(facecolor='w', edgecolor='k', figsize=(20,12), dpi=90) -# #x,y= self.exterior.xy - -# for polygon in self.polygons: -# x=[] -# y=[] -# for x_text, y_text in polygon.shell : -# x.append(x_text) -# y.append(y_text) -# ax.text(x_text, y_text-(y_text*0.1), '({}, {})'.format(int(x_text*10)/10, int(y_text*10)/10),) -# #print(x,y) -# ax.plot(x, y) -# ax.scatter(x, y, s=60) -# if title==None: -# ax.set_title('Mini-Container') -# else: -# ax.set_title(title) -# x1 = [x[0]for x in polygon.spine] -# y1= [x[1]for x in polygon.spine] -# ax.plot(x1,y1, linewidth=2,color='black') -# mplcursors.cursor() -# ax.plot([0,self.max_width,self.max_width,0,0],[0+self.y_offset,0+self.y_offset,self.height+self.y_offset,self.height+self.y_offset,0+self.y_offset]) -# return plt.show() - -def pack_mini_containers(container_array, plot_steps=False): - mini_container_array = [] - plot_steps_helper_tuples = [] - colors = itertools.cycle(palette) - background_color_list = [next(colors)] - for container in container_array: - mini_container_plot = [] - box_width = 2.214 * container.hc.w_max - box_width_helper = 0 - box_counter = 1 # hilft dabei wie oft der Container in Mini-Container geteilt wird - while box_width_helper < container.x_boundary: - container.box_boundarys_x_values.append(box_width_helper) - box_width_helper += box_width - background_color_list.append(next(colors)) - container_plot = container.plot_container(container.sigma, render=False, - background_c_list=background_color_list) # will added to the plots - max_width_mini_container = box_width + container.hc.w_max - background_counter = 0 - # wichtig zu kucken ob der container noch Polygone enthält da die linkesten Punkte noch in der anderen Box liegen können und eine Box leer sein kann - while len(container.sigma) > 0 and (box_width * box_counter) < (container.x_boundary): - - # print("max_with,y_boundary",max_width_mini_container,(copy_container.y_boundary)) - b_color = background_color_list[background_counter] - mini_container = Mini_Container(max_width_mini_container, (container.y_boundary), - container.hc.w_max, container.hc.i) - translation_flag = True - mini_container_y_border = 0 - mini_container_x_border = 0 - # while len(container.sigma) > 0 and (container.sigma[0].min_x) < (box_width * box_counter): - pop_list = [] # enthält die counter der Polygone die zur box gehören - for counter, polygon in enumerate(container.sigma): - if polygon.min_x < (box_width * box_counter): - if translation_flag: - translation = container.sigma[counter].min_x - translation_flag = False - container.sigma[counter].translation(-translation, 0) - pop_list.append(counter) - if mini_container_y_border < container.sigma[counter].max_y: - mini_container_y_border = container.sigma[counter].max_y - if mini_container_x_border < container.sigma[counter].max_x: - mini_container_x_border = container.sigma[counter].max_x - # selbst wenn man das 0 Element poped gibt es keine Probleme - pop_helper = 0 - if pop_list != []: - for counter in pop_list: - mini_container.polygons.append(container.sigma.pop(counter - pop_helper)) - pop_helper += 1 - # mini_container.plot_container() - mini_container.height = mini_container_y_border - mini_container.current_right_boundary = mini_container_x_border - mini_container_array.append(mini_container) - title = "Mini-Container {} heigth:{} (hc_{})".format(box_counter, mini_container.height, container.hc.i) - mini_container_plot.append(mini_container.plot_container(title=title, render=False, background_c=b_color)) - box_counter += 1 - background_counter += 1 - if len(container.sigma) > 0: # für die letzte box die eventuell kürzer ist - mini_container_y_border = 0 - mini_container_x_border = 0 - mini_container = Mini_Container(max_width_mini_container, container.y_boundary, - container.hc.w_max, container.hc.i) - translation_flag = True - pop_list2 = [] - for counter, polygon in enumerate(container.sigma): - if polygon.min_x < (box_width * box_counter): - if translation_flag: - translation = container.sigma[counter].min_x - translation_flag = False - container.sigma[counter].translation(-translation, 0) - pop_list2.append(counter) - if mini_container_y_border < container.sigma[counter].max_y: - mini_container_y_border = container.sigma[counter].max_y - if mini_container_x_border < container.sigma[counter].max_x: - mini_container_x_border = container.sigma[counter].max_x - - if pop_list2 != []: - pop_helper2 = 0 - for counter in pop_list2: - mini_container.polygons.append(container.sigma.pop(counter - pop_helper2)) - pop_helper2 += 1 - mini_container.height = mini_container_y_border - mini_container.current_right_boundary = mini_container_x_border - mini_container_array.append(mini_container) - title = "Mini-Container {} (hc_{})".format(box_counter, container.hc.i) - # mini_container.plot_container(title) - mini_container_plot.append(mini_container.plot_container(title=title, render=False)) - plot_steps_helper_tuples.append((container_plot, mini_container_plot)) - if plot_steps == True: - return (mini_container_array, plot_steps_helper_tuples) - else: - return mini_container_array - - -# def pack_mini_containers2(container_array, plot_steps=False): -# mini_container_array = [] -# plot_steps_helper_tuples = [] - -# colors = itertools.cycle(palette) -# background_color_list = [next(colors)] -# for container in container_array: -# mini_container_plot = [] -# copy_container = container # nochmal schauen ob der Schritt nötig ist bzw. ob nur ein Pointer kopiert wird statt eine deepcopy -# box_width = 2.214 * copy_container.hc.w_max -# box_width_helper = 0 - -# box_counter = 1 -# # print("container boundarys",copy_container.x_boundary) -# while box_width_helper < copy_container.x_boundary: -# container.box_boundarys_x_values.append(box_width_helper) # füllen den Container mit Box Grenzen (wichtig fürs Ploten des Containers) -# box_width_helper += box_width -# background_color_list.append(next(colors)) -# container_plot = copy_container.plot_container(copy_container.sigma, render=False, -# background_c_list=background_color_list) # will added to the plots -# max_width_mini_container = box_width + copy_container.hc.w_max # maximale breite der Mini-Container (c+1)*w_max -# background_counter = 0 - -# # Boxen -> Miniboxen -# while len(copy_container.sigma) > 0 and (box_width * box_counter) < (copy_container.x_boundary): -# b_color = background_color_list[background_counter] -# mini_container = Mini_Container(max_width_mini_container, (copy_container.y_boundary), -# copy_container.hc.w_max, copy_container.hc.i) -# translation_flag = True -# mini_container_y_border=0 -# mini_container_x_border=0 -# while len(copy_container.sigma) > 0 and (copy_container.sigma[0].min_x) < (box_width * box_counter): -# if translation_flag: -# translation = copy_container.sigma[0].min_x -# translation_flag = False -# copy_container.sigma[0].translation(-translation, 0) -# if mini_container_y_border < copy_container.sigma[0].max_y: -# mini_container_y_border = copy_container.sigma[0].max_y -# if mini_container_x_border < copy_container.sigma[0].max_x: -# mini_container_x_border = copy_container.sigma[0].max_x -# mini_container.polygons.append(copy_container.sigma.pop(0)) -# # mini_container.plot_container() -# mini_container.height = mini_container_y_border -# mini_container.current_right_boundary = mini_container_x_border -# mini_container_array.append(mini_container) -# # if plot==True: -# # title = "Mini-Container {} (hc_{})".format(box_counter, container.hc.i) -# # mini_container.plot_container(title) -# title = "Mini-Container {} heigth:{} (hc_{})".format(box_counter,mini_container.height, container.hc.i) -# mini_container_plot.append(mini_container.plot_container(title=title, render=False, background_c=b_color)) -# box_counter += 1 -# background_counter += 1 -# if len(copy_container.sigma) > 0: -# mini_container_y_border=0 -# mini_container_x_border=0 -# mini_container = Mini_Container(max_width_mini_container, copy_container.y_boundary, -# copy_container.hc.w_max, copy_container.hc.i) -# translation_flag = True -# while len(copy_container.sigma) > 0 and copy_container.sigma[0].min_x < box_width * box_counter: -# if translation_flag: -# translation = copy_container.sigma[0].min_x -# translation_flag = False -# copy_container.sigma[0].translation(-translation, 0) -# if mini_container_y_border < copy_container.sigma[0].max_y: -# mini_container_y_border = copy_container.sigma[0].max_y -# if mini_container_x_border < copy_container.sigma[0].max_x: -# mini_container_x_border = copy_container.sigma[0].max_x -# mini_container.polygons.append(copy_container.sigma.pop(0)) -# # mini_container.plot_container() -# mini_container.height = mini_container_y_border -# mini_container.current_right_boundary = mini_container_x_border -# mini_container_array.append(mini_container) -# # if plot==True: -# title = "Mini-Container {} (hc_{})".format(box_counter, container.hc.i) -# # mini_container.plot_container(title) -# mini_container_plot.append(mini_container.plot_container(title=title, render=False)) -# plot_steps_helper_tuples.append((container_plot, mini_container_plot)) -# if plot_steps == True: -# return (mini_container_array, plot_steps_helper_tuples) -# else: -# return mini_container_array - - -def plot_mini_containers(plot_steps, render=True, plot_width=600, plot_height=600): - plots = [] - - # hc_container =plot_steps[0] - for plot_container in plot_steps: - plot_hc = [plot_container[0]] + plot_container[1] - grid = gridplot(plot_hc, ncols=len(plot_container[1]) + 1, plot_width=plot_width, plot_height=plot_height) - # # show(plot1) - # show(grid) - - # plots.append(grid) - # grid=row(plot_container[1]) - plots.append(grid) - # plots.append(grid) - if render: - return show(layout(plots)) - else: - return plots - - -class End_Container(object): - def __init__(self, mini_container_array, angle=0): - self.mini_containers = mini_container_array - self.polygons, self.max_width, self.max_height = self.pack_mini_containers() - self.x_values_border, self.y_values_border = [0, 0, self.max_width, self.max_width, 0], [0, self.max_height, - self.max_height, 0, 0] - self.container_area = self.max_width * self.max_height - self.container_not_opt_area = self.container_not_opt_area(self.mini_containers) - self.angle = angle - - def pack_mini_containers(self): - # y_offset = self.mini_containers[0].height - # polygons=self.mini_containers[0].polygons - y_offset = 0 - polygons = [] - container_polygon_boundary_width = 0 - for mini_container in self.mini_containers: - for polygon in mini_container.polygons: - polygon.translation(0, y_offset) - mini_container.y_offset = y_offset - y_offset += mini_container.height - polygons = polygons + mini_container.polygons - # print(mini_container.current_right_boundary) - if container_polygon_boundary_width < mini_container.current_right_boundary: - container_polygon_boundary_width = mini_container.current_right_boundary - border_points = [(0, 0), (0, y_offset), (container_polygon_boundary_width, y_offset), - (container_polygon_boundary_width, 0)] - return (polygons, container_polygon_boundary_width, y_offset,) - - # def pack_mini_containers(self): - # y_offset = self.mini_containers[0].height - # polygons=self.mini_containers[0].polygons - # container_polygon_boundary_width =self.mini_containers[0].current_right_boundary - # for mini_container in self.mini_containers[1:]: - # for polygon in mini_container.polygons: - # polygon.translation(0, y_offset) - # mini_container.y_offset = y_offset - # y_offset += mini_container.height - # polygons= polygons+mini_container.polygons - # print(mini_container.current_right_boundary) - # if container_polygon_boundary_width < mini_container.current_right_boundary: - # container_polygon_boundary_width = mini_container.current_right_boundary - # border_points = [(0,0),(0,y_offset),(container_polygon_boundary_width,y_offset),(container_polygon_boundary_width,0)] - # return (polygons,container_polygon_boundary_width,y_offset,) - - def container_not_opt_area(self, mini_containers): - container_not_opt_area = 0 - for mini_container in mini_containers: - container_not_opt_area += mini_container.max_width * mini_container.hc_height - return container_not_opt_area - - def plot_polygons(self, title=""): - polygon_number = len(self.polygons) - # x_data = self.x_values - # y_data = self.y_values - TOOLTIPS = [("index", "$index"), ("(x,y)", "($x, $y)"), ] - if title == "": - title = 'End-Container-Polygons area: {} not-optimal-area: {}'.format( - (int(self.container_area / 10)) * 10, (int(self.container_not_opt_area / 10)) * 10) - fig = figure(title=title, x_axis_label='x', y_axis_label='y', tooltips=TOOLTIPS, toolbar_location="below") - colors = itertools.cycle(palette) - legend_items = [] - legend_polygons = [] - for counter, polygon in enumerate(self.polygons): - color = next(colors) - x = polygon.x_values - y = polygon.y_values - legend_label = "Polygon {}".format(counter) - poly_fig = fig.line(x, y, color=color, line_width=2, muted_alpha=0.2) - circle_fig = fig.circle(x, y, color=color, line_width=2, muted_alpha=0.2, size=8) - legend_polygons.append((legend_label, [poly_fig, circle_fig])) - # spine_x_values = [x[0] for x in self.spine] - # spine_y_values = [x[1] for x in self.spine] - fig_border = fig.line(self.x_values_border, self.y_values_border, line_color="red", line_width=2, - muted_alpha=0.2) - - legend_items = legend_polygons - legend_items.append(("border", [fig_border])) - legend = Legend(items=legend_items) - - fig.add_layout(legend, 'right') - fig.legend.click_policy = "mute" - # if render: - # return show(fig) - # else: - return show(fig) - - def plot_container(self, title="", plot_width=850, plot_height=700, solo_box_border=False, render=True): - - legend_mini_containers = [] - legend_spine = [] - legend_lr = [] - legend_rl = [] - legend_items = [] - # fig = plt.subplots(facecolor='w', edgecolor='k', figsize=(20,12), dpi=90) - TOOLTIPS = [("index", "$index"), ("(x,y)", "($x, $y)"), ] - if title == "": - title = 'End-Container area: {} not-optimal-area: {}'.format((int(self.container_area / 10)) * 10, ( - int(self.container_not_opt_area / 10)) * 10) - fig = figure(title=title, x_axis_label='x', y_axis_label='y', width=plot_width, height=plot_height, - toolbar_location="below", tooltips=TOOLTIPS) - y_offset = 0 - colors = itertools.cycle(palette) - for counter, mini_container in enumerate(self.mini_containers): - color = next(colors) - legend_polygons = [] - for polygon in mini_container.polygons: - # mapper = linear_cmap(field_name='x', palette=Viridis256 ,low=min(x) ,high=max(x)) - source = ColumnDataSource(data=dict(x=polygon.x_values, y=polygon.y_values)) - spine_x_values = [x[0] for x in polygon.spine] - spine_y_values = [x[1] for x in polygon.spine] - - # legend_label = "Mini-Container {} height:{} (hc{})".format(counter,int(mini_container.height), mini_container.hc_i) - fig_polygon = fig.line(x="x", y="y", line_width=2, line_color=color, muted_alpha=0.2, source=source) - # fig.circle(x="x",y="y",fill_color=linear_cmap(field_name='y', palette= 'Viridis256'),source=source, line_width=2, muted_alpha=0.2,size=8) - fig_circle = fig.circle(x="x", y="y", line_width=2, color=color, fill_color=color, muted_alpha=0.2, - size=8, - source=source) - # ax.scatter(x, y, s=60) - fig_spine = fig.line(spine_x_values, spine_y_values, line_color="red", line_width=2, - muted_alpha=0.2) - legend_spine.append(fig_spine) - legend_polygons = legend_polygons + [fig_polygon, fig_circle] - - if solo_box_border: - mini_box_border = mini_container.current_right_boundary - fig.title.text = 'End-Container mini-containers with solo boundarys' - else: - mini_box_border = self.max_width - color_box = BoxAnnotation(left=0, right=mini_box_border, bottom=mini_container.y_offset, - top=mini_container.y_offset + mini_container.height, fill_color=color, - fill_alpha=0.1) - fig.add_layout(color_box) - fig_border = fig.line([0, mini_box_border, mini_box_border, 0, 0], - [0 + y_offset, 0 + y_offset, mini_container.height + y_offset, - mini_container.height + y_offset, - 0 + y_offset], line_color=color, muted_alpha=0.2) - y_offset += mini_container.height - legend_label = "Mini-Container {} height:{} (hc{})".format(counter, int(mini_container.height), - mini_container.hc_i) - legend_polygons.append(fig_border) - legend_mini_containers.append((legend_label, legend_polygons)) - spine_legend = [("spine", legend_spine)] - legend_items = legend_items + legend_mini_containers + spine_legend - legend = Legend(items=legend_items) - - fig.add_layout(legend, 'right') - fig.legend.click_policy = "mute" - # mplcursors.cursor() - if render: - return show(fig) - else: - return fig - - -class Convex_Container(object): - def __init__(self, end_container, plots=False): - self.angle_0_end_container = deepcopy(end_container) - self.end_container_list = [] # Liste aller Endcontainer - self.end_container_polygons = deepcopy(end_container.polygons) # die Polygone des endcontainers unrotiert - self.back_rotated_polygons_plots = [] - self.container_plots = [] - self.smallest_end_container, self.polygons, self.angle, self.area = self.find_convex_container(plots) - self.width = self.smallest_end_container.max_width - self.height = self.smallest_end_container.max_height - self.box_boundarys_x_values, self.box_boundarys_y_values = self.set_boundarys() - - def find_convex_container(self, plot=False): - list_of_area = [] - polygons = [] - - for angle in range(0, 360, 10): - polygons = self.rotate_polygons(self.end_container_polygons, -angle) - qs = height_classes(polygons) - containers = building_containers(qs) - mini_containers = pack_mini_containers(containers) - end_container = End_Container(mini_containers) - end_container.angle = angle - self.end_container_list.append(end_container) - list_of_area.append(end_container) - # if plot==True: - - if plot: - title = 'End-Container area: {} not-optimal-area: {} angle: {}'.format( - truncate(end_container.container_area, 1), truncate(end_container.container_not_opt_area, 1), - -end_container.angle) - self.container_plots.append(end_container.plot_container(render=False, title=title)) - - scp = end_container.polygons - back_rotated_polygons = self.rotate_polygons(scp, angle) - box_x_v = end_container.x_values_border - box_y_v = end_container.y_values_border - boundarys = list(zip(box_x_v, box_y_v)) - x_values, y_values = self.rotate_points(boundarys, angle, split_x_y=True) - title2 = 'Convex-Container area: {} not-optimal-area: {} angle: {}'.format( - truncate(end_container.container_area, 1), truncate(end_container.container_not_opt_area, 1), - -end_container.angle) - back_rotated_polygon_plot = plot_polygons_in_single_plot(back_rotated_polygons, render=False, - border=(x_values, y_values), title=title2) - self.back_rotated_polygons_plots.append(back_rotated_polygon_plot) - # - # area = end_container.container_area - - sorted_container = sorted(list_of_area, key=lambda k: k.container_area) - smallest_container = sorted_container[0] - angle = smallest_container.angle - print("smallest poylgon", angle) - smallest_container_polygons = deepcopy(sorted_container[0].polygons) - back_rotated_polygons = self.rotate_polygons(smallest_container_polygons, angle) - return (smallest_container, back_rotated_polygons, angle, smallest_container.container_area) - - def set_boundarys(self): - container = self.smallest_end_container - box_boundarys_x_values = [0, 0, self.width, self.width, 0] - box_boundarys_y_values = [0, self.height, self.height, 0, 0] - boundarys = list(zip(box_boundarys_x_values, box_boundarys_y_values)) - x_values, y_values = self.rotate_points(boundarys, container.angle, split_x_y=True) - return (x_values, y_values) - - # def smallest_convex_container(self,convex_container_list): - # sorted_container = sorted(convex_container_list,key=lambda k:k.container_area) - # smallest_container=sorted_container[0] - # return smallest_container - - def rotate_polygons(self, polygons, angle): - rotated_polygons = [] - for polygon in polygons: - rotated_polygons.append(self.create_rotated_polygon(polygon, angle)) - return rotated_polygons - - def rotate_points(self, point_list, angle, split_x_y=False): - x_values = [] - y_values = [] - angle = angle * math.pi / 180.0 - cosp = math.cos(angle) - sinp = math.sin(angle) - if abs(cosp) < 2.5e-16: - cosp = 0.0 - if abs(sinp) < 2.5e-16: - sinp = 0.0 - for point in point_list: - point_x = (cosp * point[0]) - (sinp * point[1]) - point_y = (sinp * point[0]) + (cosp * point[1]) - x_values.append(point_x) - y_values.append(point_y) - if split_x_y: - return (x_values, y_values) - else: - return list(zip(x_values, y_values)) - - def create_rotated_polygon(self, polygon, angle): - # https://github.com/Toblerity/Shapely/blob/master/shapely/affinity.py hilfe aus zeile 160 - rotated_shell = [] - angle = angle * math.pi / 180.0 - cosp = math.cos(angle) - sinp = math.sin(angle) - if abs(cosp) < 2.5e-16: - cosp = 0.0 - if abs(sinp) < 2.5e-16: - sinp = 0.0 - for vertex in polygon.shell: - vertex_x = (cosp * vertex[0]) - (sinp * vertex[1]) - vertex_y = (sinp * vertex[0]) + (cosp * vertex[1]) - rotated_shell.append((vertex_x, vertex_y)) - return Polygon2(rotated_shell) - - def plot_finding_cc_steps(self, render=True, colums=9, plot_width=500, plot_height=500): - grid = gridplot(self.container_plots, ncols=colums, plot_width=plot_width, plot_height=plot_height) - if render: - return show(grid) - else: - return grid - - def plot_all_cc(self, render=True, colums=9, plot_width=500, plot_height=500): - grid = gridplot(self.back_rotated_polygons_plots, ncols=colums, plot_width=plot_width, plot_height=plot_height) - if render: - return show(grid) - else: - return grid - - def plot_polygons(self, render=True, title=""): - polygon_number = len(self.polygons) - # x_data = self.x_values - # y_data = self.y_values - TOOLTIPS = [("index", "$index"), ("(x,y)", "($x, $y)"), ] - if title == "": - title = 'Convex Container area: {} angle: {}'.format(int(self.smallest_end_container.container_area), - self.angle) - fig = figure(title=title, x_axis_label='x', y_axis_label='y', tooltips=TOOLTIPS, toolbar_location="below") - colors = itertools.cycle(palette) - legend_items = [] - legend_polygons = [] - for counter, polygon in enumerate(self.polygons): - color = next(colors) - x = polygon.x_values - y = polygon.y_values - legend_label = "Polygon {}".format(counter) - poly_fig = fig.line(x, y, color=color, line_width=2, muted_alpha=0.2) - circle_fig = fig.circle(x, y, color=color, line_width=2, muted_alpha=0.2, size=8) - legend_polygons.append((legend_label, [poly_fig, circle_fig])) - # spine_x_values = [x[0] for x in self.spine] - # spine_y_values = [x[1] for x in self.spine] - fig_border = fig.line(self.box_boundarys_x_values, self.box_boundarys_y_values, line_color="red", line_width=2, - muted_alpha=0.2) - - legend_items = legend_polygons - legend_items.append(("border", [fig_border])) - legend = Legend(items=legend_items) - fig.add_layout(legend, 'right') - fig.legend.click_policy = "mute" - if render: - return show(fig) - else: - return fig - - # x' = cos α * x - sin α * y - - -# y' = sin α * x + cos α * y -def rotate_polygons2(polygons, angle): - rotated_polygons = [] - for polygon in polygons: - rotated_polygons.append(create_rotated_polygon2(polygon, angle)) - return rotated_polygons - - -def create_rotated_polygon2(polygon, angle): - # https://github.com/Toblerity/Shapely/blob/master/shapely/affinity.py hilfe aus zeile 160 - rotated_shell = [] - angle = angle * math.pi / 180.0 - cosp = math.cos(angle) - sinp = math.sin(angle) - if abs(cosp) < 2.5e-16: - cosp = 0.0 - if abs(sinp) < 2.5e-16: - sinp = 0.0 - for vertex in polygon.shell: - vertex_x = (cosp * vertex[0]) - (sinp * vertex[1]) - vertex_y = (sinp * vertex[0]) + (cosp * vertex[1]) - rotated_shell.append((vertex_x, vertex_y)) - return Polygon2(rotated_shell) - - -# Zerlegen des Polygons - -def cut_polygon_into_polygons(polygon, number, plot=None): - list_polygons = [polygon] - plots = [] - while number > 0: - list_helper = [] - for polygon in list_polygons: - if plot == True: - cutted_polygons, polygon_plot = cut_polygon(polygon, True) - plots.append(polygon_plot) - else: - cutted_polygons = cut_polygon(polygon) - # print(cutted_polygons) - list_helper = list_helper + cutted_polygons - list_polygons = list_helper - number = number - 1 - if plot == True: - return (list_polygons, plots) - else: - return list_polygons - - -def cut_polygon(polygon, plot=None): - polygon = polygon.shell # polyog - number_vertices = len(polygon) - if number_vertices < 3: - raise ("Polygon has not enough vertices") - first_edge = numpy.random.randint(1, number_vertices) - second_edge = numpy.random.randint(1, number_vertices) - while first_edge == second_edge: - second_edge = numpy.random.randint(1, number_vertices) - # print(first_edge,second_edge) - if first_edge > second_edge: - first_edge, second_edge = second_edge, first_edge - vertex_1 = polygon[first_edge - 1] - vertex_2 = polygon[first_edge] - # if second_edge == number_vertices: - # vertex_3 = polygon[0] - # vertex_4 = polygon[-1] - # else: - vertex_3 = polygon[second_edge - 1] - vertex_4 = polygon[second_edge] - - def helper(vertex_1, vertex_2): - new_vertex = (0, 0) - if vertex_1[0] == vertex_2[0]: - low, high = vertex_1[1], vertex_2[1] - if low > high: - low, high = high, low - rand_number = numpy.random.uniform(low, high) - new_vertex = (vertex_1[0], rand_number) - elif vertex_1[1] == vertex_2[1]: - low, high = vertex_1[0], vertex_2[0] - if low > high: - low, high = high, low - rand_number = numpy.random.uniform(low, high) - new_vertex = (rand_number, vertex_1[1]) - else: - # y = m*x+n - # n = y-m*x - slope = (vertex_1[1] - vertex_2[1]) / (vertex_1[0] - vertex_2[ - 0]) # m = y2-y1/x2-x1 Formel für die Geradensteigung mithilfe aus zwei verschiedenen Punkten der Geraden - n = vertex_1[1] - (slope * vertex_1[0]) - low, high = vertex_1[1], vertex_2[1] - if low > high: - low, high = high, low - rand_number = numpy.random.uniform(low, high) - new_vertex_x = (rand_number - n) / slope # x=(y-n)/m - new_vertex = (new_vertex_x, rand_number) - return new_vertex - - new_vertex_1 = helper(vertex_1, vertex_2) - new_vertex_2 = helper(vertex_3, vertex_4) - polygon_1 = polygon[:first_edge] + [new_vertex_1] + [new_vertex_2] + polygon[second_edge:] - polygon_2 = [new_vertex_1] + polygon[first_edge:second_edge] + [new_vertex_2] + [new_vertex_1] - # s = [1,2,5,6,7] ,s[6:] => []; daher können wir für den spezial Fall second_edge== vertices_number so vorgehen - if plot == True: - plot_fig = plot_polygons_in_single_plot([Polygon2(polygon_1), Polygon2(polygon_2)], render=False) - return ([Polygon2(polygon_1), Polygon2(polygon_2)], plot_fig) - else: - return [Polygon2(polygon_1), Polygon2(polygon_2)] - -# def plot_polygons2(polygon_list,title="",render=True, border=None): -# polygon_number = len(polygon_list) -# # x_data = self.x_values -# # y_data = self.y_values -# TOOLTIPS= [("index", "$index"),("(x,y)", "($x, $y)"),] -# # if title=="": -# # title= 'height:{} slope:{}'.format(height,slope) -# # else: -# # title= '{} height:{} slope:{}'.format(title,height,slope) -# fig = figure(title=title, x_axis_label='x', y_axis_label='y', tooltips=TOOLTIPS, toolbar_location="below") -# colors = itertools.cycle(palette) -# legend_items=[] -# legend_polygons=[] -# for counter,polygon in enumerate(polygon_list): -# color = next(colors) -# x= polygon.x_values -# y= polygon.y_values -# legend_label="Polygon {}".format(counter) -# poly_fig = fig.line(x,y,color=color,line_width=2, muted_alpha=0.2) -# circle_fig = fig.circle(x,y,color=color, line_width=2, muted_alpha=0.2,size=8) -# legend_polygons.append((legend_label, [poly_fig, circle_fig])) -# # spine_x_values = [x[0] for x in self.spine] -# # spine_y_values = [x[1] for x in self.spine] -# if border !=None: -# fig.line(border[0],border[1], line_color="red",legend_label="Border", line_width=2,muted_alpha=0.2) - -# legend_items=legend_polygons -# legend = Legend(items=legend_items) -# legend.click_policy="mute" -# fig.add_layout(legend, 'right') -# fig.legend.click_policy="mute" -# if render: -# return show(fig) -# else: -# return fig -# def plot_polygons2(polygon_list): -# polygon_number = len(polygon_list) -# fig, ax = plt.subplots(1,figsize=(9, 8), dpi= 80, facecolor='w', edgecolor='k') -# plt.tight_layout(pad=10, w_pad=10, h_pad=3) - -# for polygon in polygon_list: -# x= polygon.x_values -# y= polygon.y_values -# for x_text, y_text in polygon.shell : -# ax.text(x_text, y_text-(y_text*0.2), '({}, {})'.format(int(x_text*10)/10, int(y_text*10)/10),) -# ax.plot(x, y) -# ax.scatter(x, y, s=60) -# ax.set_title('A single plot') -# ngon = numpy.random.randint(3,max_ngon+1) -# #ries=0 -# max_rand= 1000 - -# #tries=tries+1 -# polygon_points=[] -# while len(polygon_points)<ngon: - - -# x = numpy.random.randint(1,max_rand) -# y = numpy.random.randint(1,max_rand) -# # x = numpy.random.random() -# # y = numpy.random.random() -# while (x,y) in polygon_points: -# # x = numpy.random.random() -# # y = numpy.random.random() -# x = numpy.random.randint(1,max_rand) -# y = numpy.random.randint(1,max_rand) \ No newline at end of file diff --git a/mysite/plots/polygon_creator.py b/mysite/plots/polygon_creator.py new file mode 100644 index 0000000000000000000000000000000000000000..00d5518aaa0ba73a8cd667f823328c847a62c60b --- /dev/null +++ b/mysite/plots/polygon_creator.py @@ -0,0 +1,145 @@ +# Zerlegen des Polygons +#import import_ipynb + +# Voronoi diagramm +import scipy.spatial as spatial +from collections import defaultdict +import random +import numpy +from shapely.geometry import Polygon, MultiPolygon +from .packing_algo import ConvexPolygon, Point_xy, plot_polygons_in_single_plot + + +def rectangle_cutter(rect_width: float, rect_height: float, cut_count: int, intervals=[0, 0.01, 0.05, 1], + weights=[0, 0, 0.5, 1], render=False, + plot_width=700, plot_height=700) -> [ConvexPolygon]: + if len(intervals) != len(weights): + raise ValueError("the number of values from weights and intervals need to be the same") + rectangle_polygon = ConvexPolygon([(0, 0), (0, rect_height), (rect_width, rect_height), (rect_width, 0), (0, 0)]) + max_area = rect_width * rect_height + small_area_polygons = [] + polygons_to_cut = [rectangle_polygon] + if cut_count < 0: + raise ValueError("the cut cut_count need to be positive to cut the polygon") + while cut_count > 0 and len(polygons_to_cut) > 0: + cutted_polygons = [] + for polygon in polygons_to_cut: + related_area = polygon.area / max_area + weight = find_weight(related_area, intervals, weights) + rand = random.random() + if rand <= weight: + cutted_polygons = cutted_polygons + cut_polygon(polygon) + else: + polygon.plot_fill = True + small_area_polygons.append(polygon) + polygons_to_cut = cutted_polygons + cut_count = cut_count - 1 + if render: + current_polygons = polygons_to_cut + small_area_polygons + title = "Rectangle to Polygons=P. cut_count: {} P. count: {} P. to cut: {} P. stopped cutting: {}".format( + cut_count, len(current_polygons), len(polygons_to_cut), len(small_area_polygons)) + fig = plot_polygons_in_single_plot(current_polygons, title=title, plot_width=plot_width, + plot_height=plot_height) + all_polygons = polygons_to_cut + small_area_polygons + if render: + for polygon in all_polygons: + polygon.plot_fill = False + return all_polygons + + +def find_weight(x, intervals, weights): + for index in range(0, len(intervals)): + if x <= intervals[index]: + return weights[index] + + +def cut_polygon(polygon: ConvexPolygon) -> [ConvexPolygon]: + polygon = polygon.shell # polyog + number_vertices = len(polygon) + if number_vertices < 3: + raise ValueError("Polygon has not enough vertices") + first_edge = numpy.random.randint(1, number_vertices) + second_edge = numpy.random.randint(1, number_vertices) + while first_edge == second_edge: + second_edge = numpy.random.randint(1, number_vertices) + if first_edge > second_edge: + first_edge, second_edge = second_edge, first_edge + vertex_1_first_edge = polygon[first_edge - 1] + vertex_2_first_edge = polygon[first_edge] + vertex_1_second_edge = polygon[second_edge - 1] + vertex_2_second_edge = polygon[second_edge] + + new_vertex_1 = random_point_between_edge(vertex_1_first_edge, vertex_2_first_edge) + new_vertex_2 = random_point_between_edge(vertex_1_second_edge, vertex_2_second_edge) + polygon_1 = polygon[:first_edge] + [new_vertex_1] + [new_vertex_2] + polygon[second_edge:] + polygon_2 = [new_vertex_1] + polygon[first_edge:second_edge] + [new_vertex_2] + [new_vertex_1] + # s = [1,2,5,6,7] ,s[6:] => []; daher können wir für den spezial Fall second_edge== vertices_number so vorgehen + return [ConvexPolygon(polygon_1), ConvexPolygon(polygon_2)] + + +def random_point_between_edge(vertex_1: Point_xy, vertex_2: Point_xy) -> Point_xy: + new_vertex = (0, 0) + if vertex_1[0] == vertex_2[0]: + low, high = vertex_1[1], vertex_2[1] + if low > high: + low, high = high, low + rand_number = numpy.random.uniform(low, high) + new_vertex = (vertex_1[0], rand_number) + elif vertex_1[1] == vertex_2[1]: + low, high = vertex_1[0], vertex_2[0] + if low > high: + low, high = high, low + rand_number = numpy.random.uniform(low, high) + new_vertex = (rand_number, vertex_1[1]) + else: + # y = m*x+n + # n = y-m*x + slope = (vertex_1[1] - vertex_2[1]) / (vertex_1[0] - vertex_2[ + 0]) # m = y2-y1/x2-x1 Formel für die Geradensteigung mithilfe aus zwei verschiedenen Punkten der Geraden + n = vertex_1[1] - (slope * vertex_1[0]) + low, high = vertex_1[1], vertex_2[1] + if low > high: + low, high = high, low + rand_number = numpy.random.uniform(low, high) + new_vertex_x = (rand_number - n) / slope # x=(y-n)/m + new_vertex = (new_vertex_x, rand_number) + return new_vertex + + +# https://gist.github.com/pv/8036995 +# https://stackoverflow.com/questions/20515554/colorize-voronoi-diagram/20678647#20678647 +def voronoi_polygons_wrapper(rect_width, rect_height, point_count): + boundary = numpy.array([[0, 0], [0, rect_height], [rect_width, rect_height], [rect_width, 0], [0, 0]]) + boundary_polygon = Polygon(boundary) + + x_values = numpy.random.uniform(low=0 + 1, high=rect_width - 1, size=(point_count,)) + y_values = numpy.random.uniform(low=0 + 1, high=rect_height - 1, size=(point_count,)) + points = list(zip(x_values, y_values)) + bigger = max(rect_width, rect_height) + pre_number = pre_decimal_finder(bigger) + 3 + border_point = int(str(9) * pre_number) + help_border = [[border_point, border_point], [-border_point, border_point], [border_point, -border_point], + [-border_point, -border_point]] + points = numpy.append(points, help_border, axis=0) + # compute Voronoi tesselation + vor = spatial.Voronoi(points) + polygon_list = [] + for region in vor.regions: + if not -1 in region: + polygon = [vor.vertices[i] for i in region] + if len(polygon) > 2: + # Clipping polygon + poly = Polygon(polygon) + clipped_poly = poly.intersection(boundary_polygon) + polygon_list.append(ConvexPolygon(clipped_poly.exterior.coords)) + return polygon_list + + +def pre_decimal_finder(i: float) -> int: + if i < 0: + i = abs(i) + counter = 0 + while i != 0: + i = i // 10 + counter += 1 + return counter diff --git a/mysite/plots/templates/plots/index0.html b/mysite/plots/templates/plots/index0.html index 0fba171dc66ce14f252bb1fc8d63e5b85ec79d28..8c6895bb698ca009d532b6a5240cf31fcea7c690 100644 --- a/mysite/plots/templates/plots/index0.html +++ b/mysite/plots/templates/plots/index0.html @@ -9,7 +9,7 @@ <div> {% autoescape off %} -<h1>Polygons</h1> +<h1>Packed Polygons Steps</h1> {{polygons_plot}} {{polygons_plot.}} <hr> diff --git a/mysite/plots/templates/plots/index_new.html b/mysite/plots/templates/plots/index_new.html new file mode 100644 index 0000000000000000000000000000000000000000..f495949bda7218599140638e14ccb201414e6f2a --- /dev/null +++ b/mysite/plots/templates/plots/index_new.html @@ -0,0 +1,17 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title>test</title> +</head> +<body> +<div> +{% autoescape off %} + +<h1>Polygons</h1> +{{plot_steps}} +{% endautoescape %} +</div> +</body> +</html> \ No newline at end of file diff --git a/mysite/plots/templates/plots/tab.html b/mysite/plots/templates/plots/tab.html deleted file mode 100644 index e86a81bdb176ca03228a37aa0de7b02f44dbcf1c..0000000000000000000000000000000000000000 --- a/mysite/plots/templates/plots/tab.html +++ /dev/null @@ -1,89 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta name="viewport" content="width=device-width, initial-scale=1"> -<style> -body {font-family: Arial;} - -/* Style the tab */ -.tab { - overflow: hidden; - border: 1px solid #ccc; - background-color: #f1f1f1; -} - -/* Style the buttons inside the tab */ -.tab button { - background-color: inherit; - float: left; - border: none; - outline: none; - cursor: pointer; - padding: 14px 16px; - transition: 0.3s; - font-size: 17px; -} - -/* Change background color of buttons on hover */ -.tab button:hover { - background-color: #ddd; -} - -/* Create an active/current tablink class */ -.tab button.active { - background-color: #ccc; -} - -/* Style the tab content */ -.tabcontent { - display: none; - padding: 6px 12px; - border: 1px solid #ccc; - border-top: none; -} -</style> -</head> -<body> - -<h2>Tabs</h2> -<p>Click on the buttons inside the tabbed menu:</p> - -<div class="tab"> - <button class="tablinks" onclick="openCity(event, 'London')">London</button> - <button class="tablinks" onclick="openCity(event, 'Paris')">Paris</button> - <button class="tablinks" onclick="openCity(event, 'Tokyo')">Tokyo</button> -</div> - -<div id="London" class="tabcontent"> - <h3>London</h3> - <p>London is the capital city of England.</p> -</div> - -<div id="Paris" class="tabcontent"> - <h3>Paris</h3> - <p>Paris is the capital of France.</p> -</div> - -<div id="Tokyo" class="tabcontent"> - <h3>Tokyo</h3> - <p>Tokyo is the capital of Japan.</p> -</div> - -<script> -function openCity(evt, cityName) { - var i, tabcontent, tablinks; - tabcontent = document.getElementsByClassName("tabcontent"); - for (i = 0; i < tabcontent.length; i++) { - tabcontent[i].style.display = "none"; - } - tablinks = document.getElementsByClassName("tablinks"); - for (i = 0; i < tablinks.length; i++) { - tablinks[i].className = tablinks[i].className.replace(" active", ""); - } - document.getElementById(cityName).style.display = "block"; - evt.currentTarget.className += " active"; -} -</script> - -</body> -</html> diff --git a/mysite/plots/templates/plots/test.html b/mysite/plots/templates/plots/test.html index 974e89d26ea2a538906bff37c5e1923f499804b0..53e3d53a06700b8011bbde15b66d341b53a95aef 100644 --- a/mysite/plots/templates/plots/test.html +++ b/mysite/plots/templates/plots/test.html @@ -3,25 +3,12 @@ <head> <meta charset="utf-8"> <title></title> - - <style> - html { - width: 100%; - height: 100%; - } - body { - width: 90%; - height: 100%; - margin: auto; - } - </style> - <script> - function change_ds_value(name, idx, value) { - var ds = Bokeh.documents[0].get_model_by_name('my-data-source'); - ds.data[name][idx] = value; - ds.change.emit(); - } - </script> + <script src="https://cdn.bokeh.org/bokeh/release/bokeh-2.2.3.min.js" + crossorigin="anonymous"></script> + <script src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.2.3.min.js" + crossorigin="anonymous"></script> + <script src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.2.3.min.js" + crossorigin="anonymous"></script> </head> <body> @@ -29,22 +16,53 @@ <div> {{ response|safe }} <form action="/test/" method="post"> - {% csrf_token %} - <label for="your_name"></label> - <input id="your_name" type="hidden" name="your_name" value="test"> - <input type="submit" onclick="myFunction()" value="Load Polygons"> - </form> - <!--{{response4|safe}}--> + {% csrf_token %} + <label for="your_name">Load the input Polygons</label> + <input id="your_name" type="hidden" name="your_name" value="test"> + <input type="submit" onclick="myFunction()" value="load"> + </form> </div> - + <div> + <form action="/packing_rect_container/" target="_blank" method="get"> + {% csrf_token %} + <label for="pack_rect_container">Packing Rectengular Container</label> + <input id="pack_rect_container" type="hidden" name="pack_polygon" value="test"> + <input type="submit" onclick="packPolygons()" value="pack"> + </form> + </div> + <div> + <form action="/packing_rotated_rect_container/" target="_blank" method="get"> + {% csrf_token %} + <label for="pack_rotated_rect_container">Packing Rotated Rectengular Container</label> + <input id="pack_rotated_rect_container" type="hidden" name="pack_polygon" value="test"> + <input type="submit" onclick="packPolygons()" value="pack"> + </form> + </div> + <div> + <form action="/packing_convex_container/" target="_blank" method="post"> + {% csrf_token %} + <label for="pack_convex_container">Packing Convex Container (degree between 1-360)</label> + <input id="pack_convex_container" type="number" min="1" max="360" name="angle" value=10> + <input type="submit" value="pack"> + </form> + </div> + <div> + {% autoescape off %} + <h1>Convex Polygons</h1> {{polygons_plot|safe}} + <h1>Convex Polygons in one Plot</h1> {{polygons_single_plot|safe}} + + + {% endautoescape %} + </div> + + </body> -<script type="text/javascript"> -var element = document.getElementById("your_name"); -element.value = "{{response}}"; -</script> + + + <script> function myFunction() { var ds = Bokeh.documents[0].get_model_by_name('my-data-source'); diff --git a/mysite/plots/urls.py b/mysite/plots/urls.py index 5314b36e09801d20578d8c506a0219e54f8429e4..9e65f3b94d79553c97763dd03e0d609187755110 100644 --- a/mysite/plots/urls.py +++ b/mysite/plots/urls.py @@ -1,11 +1,14 @@ from django.urls import path -from plots.views import PolygonEditView +from plots.views import PolygonEditView, PackingRectContainer, PackingRotatedRectContainer, PackingConvexContainer from . import views urlpatterns = [ path('plot/', views.index, name='index'), - path('json/', views.get_json_view, name='index2'), + #path('json/', views.get_json_view, name='index2'), #path('test/', views.test, name='index3'), - path('hello/', views.hello, name='index4'), + #path('hello/', views.hello, name='index4'), path('test/', PolygonEditView.as_view(), name='index4'), + path('packing_rect_container/', PackingRectContainer.as_view(), name='rect_container'), + path('packing_rotated_rect_container/', PackingRotatedRectContainer.as_view(), name='rotated_rect_container'), + path('packing_convex_container/', PackingConvexContainer.as_view(), name='convex_container'), ] \ No newline at end of file diff --git a/mysite/plots/views.py b/mysite/plots/views.py index c0427ebb845084b3593acab5855e0632e8741579..a1f76aa4ca93305e6be16a843c0e861457335716 100644 --- a/mysite/plots/views.py +++ b/mysite/plots/views.py @@ -6,21 +6,20 @@ import json from django.shortcuts import render from django.views import View -from plotly.offline import plot + from django.http import HttpResponseRedirect -import plots.polygon as poly +import plots.packing_algo as poly from bokeh.embed import file_html from bokeh.models import BoxZoomTool from django.views.generic import TemplateView import matplotlib from django.http import JsonResponse -from plotly.graph_objs import Scatter -import plotly.graph_objects as go + from django.http import HttpResponse import pdb;pdb.set_trace import matplotlib.pyplot as plt import mpld3 -from plotly.subplots import make_subplots + import math from plots import plot_helpers from bokeh.plotting import figure, output_file, show @@ -43,246 +42,53 @@ from bokeh.models.callbacks import CustomJS from bokeh.embed import json_item import json -def index(request): - - convex_polygons = poly.create_multiple_convex_polygons(50,9) - - polygons_plot= poly.plot_polygons(convex_polygons,plot_width=300,plot_height=300,render=False) - html_polygons = file_html(polygons_plot, CDN, "my plot") - - high_classes = poly.height_classes(convex_polygons) - - hc_tab_list = [] - - # building highclass plots - for counter,hc in enumerate(high_classes): - hc_plot = hc.plot_hc(render=False,plot_width=300,plot_height=300) - tab = Panel(child=hc_plot, title="High-Class {}".format(counter)) - hc_tab_list.append(tab) - hc_tabs = Tabs(tabs=hc_tab_list) - hc_plot_helper = file_html(hc_tabs, CDN, "my plot") - - list_containers = poly.building_containers(high_classes) - container_tab_list=[] - - #building container plots - for counter,container in enumerate(list_containers): - container_plot = container.plot_container_steps(plot_width=500,colums=3,plot_height=500,render=False) - tab = Panel(child=container_plot, title="High-Class {} -> Container {}".format(counter, counter)) - container_tab_list.append(tab) - tabs = Tabs(tabs=container_tab_list) - container_plot_helper= file_html(tabs, CDN, "my plot") - - - mini_containers_tuple = poly.pack_mini_containers(list_containers,plot_steps=True) - list_mini_containers = mini_containers_tuple[0] - mini_container_plots = mini_containers_tuple[1] - mini_plot = poly.plot_mini_containers(mini_container_plots,render=False) +def index(request): - # building mini container plots - mini_plots_tabs=[] - for counter,m_plot in enumerate(mini_plot): - tab = Panel(child=m_plot, title="Container {} -> Mini-Containers".format(counter)) - mini_plots_tabs.append(tab) - mini_tabs = Tabs(tabs=mini_plots_tabs) - mini_html_plots = file_html(mini_tabs, CDN, "my plot") + convex_polygons = poly.create_multiple_convex_polygons(10,9) + cc = poly.ConvexContainer(convex_polygons) + plot_steps = cc.plot_steps(render=False) + plot_steps_html = file_html(plot_steps, CDN, "my plot2") - # end container plot - end_container = poly.End_Container(list_mini_containers) - end_container_plot= end_container.plot_container(render=False) - end_container_html =file_html(end_container_plot, CDN, "my plot2") - return render(request, 'plots/index0.html', context={'polygons_plot': html_polygons,'hc_plot': hc_plot_helper,'container_plot': container_plot_helper, - 'mini_container_plot': mini_html_plots, 'end_container_plot':end_container_html}) + return render(request, 'plots/index_new.html', context={"plot_steps":plot_steps_html}) # 'high_classes': plot_high_class_list,}) # 'hc_container': hc_container}) +class PackingRectContainer(View): + def get(self, request, *args, **kwargs): + cc = poly.pack_polygons( PolygonEditView.polygons) + plot_steps = cc.plot_steps(render=False) + plot_steps_html = file_html(plot_steps, CDN, "my plot23") + #PackingPolygons.context["packed_polygons"]=plot_steps_html + return render(request, 'plots/index_new.html', context={"plot_steps": plot_steps_html}) +class PackingRotatedRectContainer(View): + def get(self, request, *args, **kwargs): + cc = poly.ConvexContainer(PolygonEditView.polygons,steps=90) + plot_steps = cc.plot_steps(render=False) + plot_steps_html = file_html(plot_steps, CDN, "my plot23") + # PackingPolygons.context["packed_polygons"]=plot_steps_html + return render(request, 'plots/index_new.html', context={"plot_steps": plot_steps_html}) -def get_json_view(request): - convex_polygons = poly.create_multiple_convex_polygons(14, 3) - #polygons_plot = poly.plot_polygons(convex_polygons, plot_width=300, plot_height=300, render=False) - #html_polygons = file_html(polygons_plot, CDN, "my plot") - list_hc = poly.height_classes(convex_polygons) - list_containers = poly.building_containers(list_hc) - - tab_list=[] - counter=0 - for container in list_containers: - container_plot = container.plot_container_steps(plot_width=500, colums=3, plot_height=500, render=False) - #tab1 = Panel(child=container_plot, title="High-Class {} -> Container {}".format(counter,counter)) - tab_list.append(file_html(container_plot, CDN, "my plot")) - counter +=1 - #html_container = file_html(tab_list, CDN, "my plot") - - #container_plot_helper.append(html_container) - #tabs = Tabs(tabs=tab_list) - response = tab_list - - mini_containers_tuple = poly.pack_mini_containers(list_containers, plot_steps=True) - list_mini_containers = mini_containers_tuple[0] - mini_container_plots = mini_containers_tuple[1] - - mini_plot = poly.plot_mini_containers(mini_container_plots, render=False) - - mini_plots = [] - tabs = [] - for counter, m_plot in enumerate(mini_plot): - - mini_plots.append(file_html(m_plot, CDN, "my plot")) - # tabs.append(Panel(child=m_plot, title="circle {}".format(counter))) - # tab =Tabs(tabs=tabs) - mini_html_plots = mini_plots - - # fig1 = figure() - # fig1.circle([0, 1, 2], [1, 3, 2]) - # fig2 = figure() - # fig2.circle([0, 0, 2], [4, -1, 1]) - # fig3 = figure() - # fig3.circle([0, 4, 3], [1, 2, 0]) - # - # l1 = layout([[fig1, fig2]]) - # l2 = layout([[fig3]]) - # - # tab1 = Panel(child=fig1, title="This is Tab 1") - # tab2 = Panel(child=fig2, title="This is Tab 2") - # tabs = Tabs(tabs=[tab1, tab2]) - # response =file_html(tabs, CDN, "my plot") - #show(tabs) - return render(request, 'plots/get.html', context={'containers': response,'containers2':mini_plots}) - - - - - -def test(request): - # source = ColumnDataSource(data=dict(x=[1, 2, 3], - # y=[3, 2, 1]), - # name='my-data-source') - # - # p = figure() - # l1 = p.line("x", "y", source=source) - # response = file_html(p, CDN, "my plot") - # list =[1,2,3,4] - if request.method == "POST": - context={} - print(request.POST) - test = request.POST["your_name"] - dict_poly = json.loads(test) - print(dict_poly["x"]) - print(dict_poly["y"]) - polygon_list=[] - polygons_x_y_tuple = list(zip(dict_poly["x"],dict_poly["y"])) - # polygon_x_list = [] - # polygon_y_list = [] - for x,y in polygons_x_y_tuple: - polygon_list.append(list(zip(x,y))) - # for x,y in polygons_x_y_tuple: - # polygon_x_list.append(x) - # polygon_y_list.append(y) - print(polygon_list) - real_polygons=[] - for polygon in polygon_list: - - if len(polygon)<3: - continue - if polygon[0]!= polygon[-1]: - polygon.append(polygon[0]) - - - polygon2 = poly.Polygon(polygon) - print("konkav",list(polygon2.exterior.coords)) - polygon_parent_class = polygon2.convex_hull - polygon2 = poly.Polygon2(list(polygon_parent_class.exterior.coords)) - print("convex",polygon2.shell) - real_polygons.append(polygon2) - # print(polygon_list) - # q = map(list, zip(*polygon_list)) - # s= json.loads(test) - # x = s["x"] - # y = s["y"] - # source = ColumnDataSource(data=dict(x=polygon_x_list, y=polygon_y_list),name='my-data-source') - # print(test) - plot = poly.plot_polygons_in_single_plot(real_polygons,render=False) - # plot = poly.plot_polygons(real_polygons,render=False) - # print(type(test)) - # p = figure() - # p.multi_line("x", "y", source=source) - response2 = file_html(plot, CDN, "my plot") - context["response3"]=response2 - return HttpResponseRedirect('/test/') - TOOLTIPS = [("index", "$index"), ("(x,y)", "($x{1.1}, $y{1.1})"), ] - source = ColumnDataSource(data=dict(x=[], - y=[]), - name='my-data-source') - - p = figure(x_range=(0, 10), y_range=(0, 10), width=400, height=400, - title='Poly Edit Tool',tooltips=TOOLTIPS) - - p1 = p.patches("x", "y", fill_alpha=0.4,source=source, fill_color="red") - - c1 = p.circle([],[], size=10, color='red', ) - - draw_tool = PolyDrawTool(renderers=[p1]) - edit_tool = PolyEditTool(renderers=[p1], vertex_renderer=c1) - p.add_tools(draw_tool, edit_tool) - p.toolbar.active_drag = edit_tool - response = file_html(p, CDN, "my plot") - return render(request, 'plots/test.html', context={"response":response, "list":list}) - - -def hello(request): - if request.method == 'POST': - test = request.POST["your_name"] - dict_poly = json.loads(test) - print(dict_poly["x"]) - print(dict_poly["y"]) - polygon_list=[] - polygons_x_y_tuple = list(zip(dict_poly["x"],dict_poly["y"])) - # polygon_x_list = [] - # polygon_y_list = [] - for x,y in polygons_x_y_tuple: - polygon_list.append(list(zip(x,y))) - # for x,y in polygons_x_y_tuple: - # polygon_x_list.append(x) - # polygon_y_list.append(y) - print(polygon_list) - real_polygons=[] - for polygon in polygon_list: - - if len(polygon)<3: - continue - if polygon[0]!= polygon[-1]: - polygon.append(polygon[0]) - +class PackingConvexContainer(View): + # context = {} + def get(self, request, *args, **kwargs): + cc = poly.ConvexContainer(PolygonEditView.polygons, steps=1) + plot_steps = cc.plot_steps(render=False) + plot_steps_html = file_html(plot_steps, CDN, "my plot23") + # PackingPolygons.context["packed_polygons"]=plot_steps_html + return render(request, 'plots/index_new.html', context={"plot_steps": plot_steps_html}) + def post(self, request, *args, **kwargs): + angle = int(request.POST["angle"]) + cc = poly.ConvexContainer(PolygonEditView.polygons, steps=angle) + plot_steps = cc.plot_steps(render=False) + plot_steps_html = file_html(plot_steps, CDN, "my plot23") + return render(request, 'plots/index_new.html', context={"plot_steps": plot_steps_html}) - polygon2 = poly.Polygon(polygon) - print("konkav",list(polygon2.exterior.coords)) - polygon_parent_class = polygon2.convex_hull - polygon2 = poly.Polygon2(list(polygon_parent_class.exterior.coords)) - print("convex",polygon2.shell) - real_polygons.append(polygon2) - # print(polygon_list) - # q = map(list, zip(*polygon_list)) - # s= json.loads(test) - # x = s["x"] - # y = s["y"] - # source = ColumnDataSource(data=dict(x=polygon_x_list, y=polygon_y_list),name='my-data-source') - # print(test) - plot = poly.plot_polygons_in_single_plot(real_polygons,render=False) - # plot = poly.plot_polygons(real_polygons,render=False) - # print(type(test)) - # p = figure() - # p.multi_line("x", "y", source=source) - response = file_html(plot, CDN, "my plot") - # polygon = Polygon(polygon_points) - # polygon_parent_class = polygon.convex_hull - # polygon2 = Polygon2(list(polygon_parent_class.exterior.coords)) - return HttpResponse(response) class PolygonEditView(View): context={} @@ -291,15 +97,15 @@ class PolygonEditView(View): plot_max_x= 100 plot_min_y = 0 plot_max_y= 100 - colum_data_x=[[]] - colum_data_y=[[]] + colum_data_x=[] # wil be a list of lists + colum_data_y=[] def get(self, request, *args, **kwargs): TOOLTIPS = [("index", "$index"), ("(x,y)", "($x{1.1}, $y{1.1})"), ] source = ColumnDataSource(data=dict(x=PolygonEditView.colum_data_x, y=PolygonEditView.colum_data_y), name='my-data-source') - p = figure(x_range=(PolygonEditView.plot_min_x, PolygonEditView.plot_max_x), y_range=(PolygonEditView.plot_min_y, PolygonEditView.plot_max_y), width=750, height=750, + p = figure(x_range=(PolygonEditView.plot_min_x, PolygonEditView.plot_max_x), y_range=(PolygonEditView.plot_min_y, PolygonEditView.plot_max_y), width=1000, height=1000, title='Poly Edit Tool', tooltips=TOOLTIPS) p.aspect_ratio = 1 p1 = p.patches("x", "y", fill_alpha=0.4, source=source, fill_color="red") @@ -310,9 +116,11 @@ class PolygonEditView(View): edit_tool = PolyEditTool(renderers=[p1], vertex_renderer=c1) p.add_tools(draw_tool, edit_tool) - p.toolbar.active_drag = edit_tool + p.toolbar.active_drag = draw_tool response = file_html(p, CDN, "my plot") - PolygonEditView.context["response"]=response + PolygonEditView.context["response"] = response + + return render(request, 'plots/test.html', PolygonEditView.context) def post(self, request, *args, **kwargs): @@ -331,7 +139,7 @@ class PolygonEditView(View): polygon_list=[] - polygons_x_y_tuple = list(zip(dict_poly["x"],dict_poly["y"])) + polygons_x_y_tuple = list(zip(dict_poly["x"], dict_poly["y"])) # polygon_x_list = [] # polygon_y_list = [] for x,y in polygons_x_y_tuple: @@ -353,27 +161,24 @@ class PolygonEditView(View): polygon.append(polygon[0]) - polygon2 = poly.Polygon(polygon) - print("konkav",list(polygon2.exterior.coords)) - polygon_parent_class = polygon2.convex_hull - polygon2 = poly.Polygon2(list(polygon_parent_class.exterior.coords)) + polygon2 = poly.ConvexPolygon(polygon) + print("konkav",list(polygon2.shell)) + #polygon_parent_class = polygon2.convex_hull + #polygon2 = poly.Polygon2(list(polygon_parent_class.exterior.coords)) polygon_max_x_list.append(polygon2.max_x) polygon_min_x_list.append(polygon2.min_x) polygon_max_y_list.append(polygon2.max_y) polygon_min_y_list.append(polygon2.min_y) real_polygons.append(polygon2) + # for setting the plot PolygonEditView.polygons = real_polygons - PolygonEditView.plot_max_y = max(polygon_max_y_list) - PolygonEditView.plot_min_y = min(polygon_min_y_list) - PolygonEditView.plot_max_x = max(polygon_max_x_list) - PolygonEditView.plot_min_x = min(polygon_min_x_list) - polygons_single_plot = poly.plot_polygons_in_single_plot(real_polygons,render=False) + polygons_single_plot = poly.plot_polygons_in_single_plot(real_polygons,plot_height=1000, plot_width=2000,render=False) plot = poly.plot_polygons(real_polygons,render=False) # print(type(test)) # p = figure() @@ -383,5 +188,7 @@ class PolygonEditView(View): #self.polygons.append(response2) PolygonEditView.context["polygons_plot"]= polygons_plot_html PolygonEditView.context["polygons_single_plot"] = polygons_single_plot_html + + return HttpResponseRedirect('/test/') diff --git a/mysite/requirements/base.txt b/mysite/requirements/base.txt index ef327b2de60521deedc4372a770f55ade26f455e..802234c8e36f1f07d4f08749fdf2d201fcf84de8 100644 --- a/mysite/requirements/base.txt +++ b/mysite/requirements/base.txt @@ -1,10 +1,13 @@ -shapely==1.7.1 -matplotlib==3.3.2 -path==15.0.0 -numpy==1.19.2 -mplcursors==0.3 +django +matplotlib +path +numpy +mplcursors mpld3 bokeh django-jquery -django.js==0.8.1 -pandas ==1.1.3 \ No newline at end of file +django.js +pandas +scipy +ipython +shapely \ No newline at end of file