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_{}&nbsp;&nbsp;height:&nbsp;{}-{}&nbsp;&nbsp;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_{}&nbsp;&nbsp;height:&nbsp;{}-{}&nbsp;&nbsp;alpha: {}<b>
+        title = Div(
+            text="<b>Highclass Container&nbsp{},&nbspPolygon&nbspheight:&nbsp{}-{} <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