diff --git a/lib/linesweep_circle.py b/lib/linesweep_circle.py index 9bc7a94..ab8d47f 100644 --- a/lib/linesweep_circle.py +++ b/lib/linesweep_circle.py @@ -152,8 +152,6 @@ class RackIDs(): def get_rack_names(self) -> list: return list(self._rack2begend.keys()) - - def add_point_to_rack(self, point:Point, name:str): if point in self._point2rack: self._point2rack[point].append(name) @@ -199,12 +197,10 @@ class RackIDs(): last = Point(l2.coords[1]) if l1.distance(first) <= self._tol_snap: snap_point = l1.interpolate(l1.project(first)) + self.add_point_to_rack(snap_point, rnames[l1]) if l1.distance(last) <= self._tol_snap: snap_point = l1.interpolate(l1.project(last)) - - self.add_point_to_rack(snap_point, rnames[l1]) - - + self.add_point_to_rack(snap_point, rnames[l1]) def rack_is_horizontal(self, name): [pa, pe] = self._rack2begend[name] @@ -216,39 +212,52 @@ class RackIDs(): class Anlage(): r""" Baut eine Anlage besteend aus Kabeltrassen (Racks), Sensoren und Unterverteilern auf. - Ermöglicht die Berechnung der günstigsten kabelwege und gibt die Kabellängen von jedem Sensor zum zugehörigen Unterverteiler aus. + Ermöglicht die Berechnung der günstigsten Kabelwege und gibt die Kabellängen von jedem Sensor zum zugehörigen Unterverteiler aus. Parameters ---------- - G : NetworkX graph - - weight : string or function - If this is a string, then edge weights will be accessed via the - edge attribute with this key (that is, the weight of the edge - joining `u` to `v` will be ``G.edges[u, v][weight]``). If no - such edge attribute exists, the weight of the edge is assumed to - be one. - - If this is a function, the weight of an edge is the value - returned by the function. The function must accept exactly three - positional arguments: the two endpoints of an edge and the - dictionary of edge attributes for that edge. The function must - return a number. Returns ------- - distance : dictionary - Dictionary, keyed by source and target, of shortest paths. Examples -------- - >>> graph = nx.DiGraph() - >>> graph.add_weighted_edges_from( - ... [("0", "3", 3), ("0", "1", -5), ("0", "2", 2), ("1", "2", 4), ("2", "3", 1)] - ... ) - >>> paths = nx.johnson(graph, weight="weight") - >>> paths["0"]["2"] - ['0', '1', '2'] + >>> # Erstelle Anlage + >>> an = Anlage() + >>> # Füge racks aus Daten hinzu + >>> an.set_racks(rack_segs) + >>> # Verbinde Racks miteinander (ggf. verlängere ungenaue Racks) + >>> an.join_racks() + >>> # Füge Sensoren als Knoten hinzu + >>> an.add_sensors(sensors) + >>> # Verbinde Sensoren mit deren naheliegendsten Racks + >>> an.connect_sensors_to_racks() + >>> # Füge UV hinzu + >>> an.add_distributors(distributors) + >>> # Verbinde UV mit deren naheliegendsten Racks + >>> an.connect_distributor_to_racks() + >>> # Verknüpfe Sensoren mit zugehörigem UV + >>> an.map_distributors_to_sensors(mapping) + >>> + >>> # Initialisiere Graph + >>> G3 = nx.Graph() + >>> # Fülle eben erstellten Graphen mit Daten + >>> pos = an.generate_graph(G3) + + >>> # Ermittle kürzeste Wege von Unterverteilern zu zugehörigen Sensoren + >>> paths = an.create_cable_paths(G3) + + + >>> print(paths['Dist_1-Sens_1']["path_coords"]) + ... [Point(-1, 9), Point(0, 9), Point(0, 3), Point(0, 1), Point(1, 1)] + >>> print(paths['Dist_1-Sens_2']["path_coords"]) + ... [Point(-1, 9), Point(0, 9), Point(0, 3), Point(2, 3), Point(2, 4)] + >>> print(paths['Dist_2-Sens_3']["path_coords"]) + ... [Point(11, 0), Point(10, 0), Point(10, 2), Point(9, 2)] + + >>> print(paths['Dist_1-Sens_1']["path_length"]) + ... 10 + """ def __init__(self, tol_snap=200, snap_step=10, tol_connect=2, tol_connect_step=0.5): @@ -273,15 +282,39 @@ class Anlage(): def set_racks(self, racks:dict[str, list[Point]]): + r""" + Fügt racks aus eingelsener Datei zu Anlage hinzu. + + Parameters + ---------- + racks - dict{"Rack_1-1": [Point(1, 0), Point(2,0), ...]} + """ return self._racks.add_racks(racks) def get_racks(self) -> dict: + r""" + Gibt in Anlage enthaltene Racks zurück. + + Returns + ---------- + dict{Point(0,0): ["Rack_1", "Rack_2", ...]} + """ return self._racks._point2rack def add_point_to_rack(self, point:Point, rname:str): + r""" + Fügt einen Punkt zu einem angegebenen Rack hinzu. + """ return self._racks.add_point_to_rack(point, rname) def get_all_rack_points(self): + r""" + Gibt einer Liste von allen Punkten allen Racks zurück. + + Returns + ---------- + [Point(0,0), Point(1,5), Point(2,6)] + """ ret = list() for rname in self._racks.get_rack_names(): ret.extend(self.get_points_from_rack(rname)) @@ -367,6 +400,9 @@ class Anlage(): return(segment_endpoints) + def join_racks(self): + self._racks.join_racks() + def increase_circle(self, tol, tol_step, line, pt, rack_id, idx, other_rack_id, other_idx, verbindungen, endpoint_pinned): ''' vergrößere Kreis bis Schnittpunkt mit Rack entsteht. @@ -604,7 +640,12 @@ class Anlage(): pfade = dict() for sname, dname in self._sensor2dist.items(): pfad_nodes, pfad_length = self.create_cable_path(G, sname, dname) - pfade[f"{dname}-{sname}"] = {"pfad": pfad_nodes, "laenge": pfad_length} + pfad_coords = self._nodeids.get_points(pfad_nodes) + pfade[f"{dname}-{sname}"] = {"path_nodes": pfad_nodes, + "path_coords": pfad_coords, + "path_length": pfad_length} + + return pfade def show_node_ids(self): return self._nodeids.show() @@ -617,8 +658,11 @@ class Anlage(): class TestLinesweep(unittest.TestCase): def test_duplicate_points(self): + ''' Testet das Nicht-Hinzufügen von doppelten Punkten''' + # Initialisiere die Liste an Knoten nodeids = NodeIDs() + # Setze gleichen Knoten doppelt nodeids.add_point(Point(1,1)) nodeids.add_point(Point(1,1)) @@ -676,23 +720,27 @@ class TestLinesweep(unittest.TestCase): 'Rack_2': [Point(-5, 5), Point(5, 5)] } + # Initialisiere Racks rack = RackIDs() + # Füge Racks aus gegebenen Daten hinzu und teile Rack_1 bestehend aus 3 Punkten in 2 Racks auf rack.add_racks(racks_data) self.assertEqual(rack.get_rack_names(), ['Rack_1-1', 'Rack_1-2', 'Rack_2']) - - def test_intersect_segments(self): ''' Stellt Schnittpunkte zwischen Racks fest und fügt Schnittpunkt zu Rack hinzu. ''' + racks_data = { 'Rack_1': [Point(0, 0), Point(0, 10), Point (10, 10)], 'Rack_2': [Point(-5, 5), Point(5, 5)], } + # Initialisiere Racks rack = RackIDs() + # Füge Racks aus gegebenen Daten hinzu und teile Rack_1 bestehend aus 3 Punkten in 2 Racks auf rack.add_racks(racks_data) + # Verknüpfe Racks mit echten Schniuttpunkten und füge Schnittpunkte (exakt & beinahe) zu jeweiligem Rack hinzu rack.join_racks() self.assertEqual(rack.get_points_from_rack("Rack_1-1"), [Point(0, 0), Point(0, 5), Point (0, 10)]) @@ -704,156 +752,167 @@ class TestLinesweep(unittest.TestCase): 'Rack_2': [Point(1, 5), Point(5, 5)], 'Rack_3': [Point(1.5, 7.5), Point(5,7.5)] } - + # Initialisiere Racks rack = RackIDs() + # Füge Racks aus gegebenen Daten hinzu und teile Rack_1 bestehend aus 3 Punkten in 2 Racks auf rack.add_racks(racks_data) + # Verknüpfe Racks mit echten Schniuttpunkten und füge Schnittpunkte (exakt & beinahe) zu jeweiligem Rack hinzu rack.join_racks() self.assertEqual(rack.get_points_from_rack("Rack_1"), [Point(0, 0), Point(0, 5), Point (0, 10)]) - # def test_ids_to_point(self): - # ''' Testet, ob gefragter Punkt auf Racks a, b, c liegt''' + def test_ids_to_point(self): + ''' Testet, ob gefragter Punkt auf Racks a, b, c liegt''' - # res_rack_seg = {'Rack_1-0': [Point(1, 0), Point(5, 6)], - # 'Rack_2-0': [Point(1, 8), Point(1, 0)], - # 'Rack_2-1': [Point(0, 10), Point(5, 10)]} + res_rack_seg = {'Rack_1-0': [Point(1, 0), Point(5, 6)], + 'Rack_2-0': [Point(1, 8), Point(1, 0)], + 'Rack_2-1': [Point(0, 10), Point(5, 10)]} - # point2rack = RackIDs(res_rack_seg) + point2rack = RackIDs(res_rack_seg) - # self.assertEqual(point2rack.get_racks_from_point(Point(1, 0)), ["Rack_1-0", "Rack_2-0"]) - # self.assertEqual(point2rack.get_racks_from_point(Point(5, 6)), ["Rack_1-0"]) - # self.assertEqual(point2rack.get_points_from_rack("Rack_2-0"), [Point(1, 0), Point(1, 8)]) + self.assertEqual(point2rack.get_racks_from_point(Point(1, 0)), ["Rack_1-0", "Rack_2-0"]) + self.assertEqual(point2rack.get_racks_from_point(Point(5, 6)), ["Rack_1-0"]) + self.assertEqual(point2rack.get_points_from_rack("Rack_2-0"), [Point(1, 0), Point(1, 8)]) - # def test_add_point_interim(self): - # ''' Testet das inzufügen und einsortieren eines Zwischenpunktes zwische nRack-Anfang und Rack-Ende''' + def test_add_point_interim(self): + ''' Testet das inzufügen und einsortieren eines Zwischenpunktes zwische nRack-Anfang und Rack-Ende''' - # res_rack_seg = {'Rack_1-0': [Point(1, 0), Point(5, 6)], - # 'Rack_2-0': [Point(1, 8), Point(1, 0)], - # 'Rack_2-1': [Point(0, 10), Point(5, 10)]} + res_rack_seg = {'Rack_1-0': [Point(1, 0), Point(5, 6)], + 'Rack_2-0': [Point(1, 8), Point(1, 0)], + 'Rack_2-1': [Point(0, 10), Point(5, 10)]} - # point2rack = RackIDs(res_rack_seg) - # point2rack.add_point_to_rack(Point(1,4), "Rack_2-0") + point2rack = RackIDs(res_rack_seg) + point2rack.add_point_to_rack(Point(1,4), "Rack_2-0") - # self.assertEqual(point2rack.get_points_from_rack("Rack_2-0"), [Point(1, 0), Point(1,4), Point(1, 8)]) + self.assertEqual(point2rack.get_points_from_rack("Rack_2-0"), [Point(1, 0), Point(1,4), Point(1, 8)]) - # def test_add_sensor(self): - # ''' Erzeugt Aufpunkt an dem Sensor nähesten Rack und fügt diesen auf Rack ein (sortiert).''' + def test_add_sensor(self): + ''' Erzeugt Aufpunkt an dem Sensor nähesten Rack und fügt diesen auf Rack ein (sortiert).''' - - # rack_segs = {'Rack_1-0': [Point(0, 0), Point(0, 10)], - # 'Rack_2-0': [Point(10, -2), Point(10, 5)], - # 'Rack_2-1': [Point(0, 3), Point(10, 3)]} + rack_segs = {'Rack_1-0': [Point(0, 0), Point(0, 10)], + 'Rack_2-0': [Point(10, -2), Point(10, 5)], + 'Rack_2-1': [Point(0, 3), Point(10, 3)]} - # sensors = {'Sens_1': Point(1, 1), - # 'Sens_2': Point(2, 4), - # 'Sens_3': Point(9, 2)} + sensors = {'Sens_1': Point(1, 1), + 'Sens_2': Point(2, 4), + 'Sens_3': Point(9, 2)} - # an = Anlage() - # point2rack = an.set_racks(rack_segs) - # an.add_sensors(sensors) + an = Anlage() + point2rack = an.set_racks(rack_segs) + an.add_sensors(sensors) - # plist1 = an.get_points_from_rack("Rack_1-0") + plist1 = an.get_points_from_rack("Rack_1-0") - # an.connect_sensors_to_racks() - # plist2 = an.get_points_from_rack("Rack_1-0") + an.connect_sensors_to_racks() + plist2 = an.get_points_from_rack("Rack_1-0") - # self.assertEqual(plist1, [Point(0, 0), Point(0, 10)]) - # self.assertEqual(plist2, [Point(0, 0), Point(0,1), Point(0, 10)]) + self.assertEqual(plist1, [Point(0, 0), Point(0, 10)]) + self.assertEqual(plist2, [Point(0, 0), Point(0,1), Point(0, 10)]) - # def test_generate_graph(self): - - # rack_segs = {'Rack_1-0': [Point(0, 0), Point(0, 10)], - # 'Rack_2-0': [Point(10, -2), Point(10, 5)], - # 'Rack_2-1': [Point(0, 3), Point(10, 3)]} + def test_generate_graph(self): + '''Generiert einen Graphen in 3 unterschiedlichen Ausbauestufen (nur Racks, Racks+Sensoren, Racks+Sensoren+Unterverteiler)''' + rack_segs = {'Rack_1-0': [Point(0, 0), Point(0, 10)], + 'Rack_2-0': [Point(10, -2), Point(10, 5)], + 'Rack_2-1': [Point(0, 3), Point(10, 3)]} - # sensors = {'Sens_1': Point(1, 1), - # 'Sens_2': Point(2, 4), - # 'Sens_3': Point(9, 2)} + sensors = {'Sens_1': Point(1, 1), + 'Sens_2': Point(2, 4), + 'Sens_3': Point(9, 2)} - # distributors = {'Dist_1': Point(-1, 9), - # 'Dist_2': Point(11, 0)} + distributors = {'Dist_1': Point(-1, 9), + 'Dist_2': Point(11, 0)} - # an = Anlage() - # an.set_racks(rack_segs) + an = Anlage() + an.set_racks(rack_segs) + an.join_racks - # G1 = nx.Graph() - # pos = an.generate_graph(G1) - # nx.draw(G1, pos, with_labels=False, node_size=10, font_size=8) - # plt.show() + G1 = nx.Graph() + pos = an.generate_graph(G1) + nx.draw(G1, pos, with_labels=False, node_size=10, font_size=8) + plt.show() - # an.add_sensors(sensors) - # an.connect_sensors_to_racks() + an.add_sensors(sensors) + an.connect_sensors_to_racks() - # G2 = nx.Graph() - # pos = an.generate_graph(G2) + G2 = nx.Graph() + pos = an.generate_graph(G2) - # edge_colors = [G2[u][v].get('color', 'black') for u, v in G2.edges()] - # nx.draw(G2, pos, with_labels=False, node_size=10, font_size=8, edge_color=edge_colors) - # plt.show() + edge_colors = [G2[u][v].get('color', 'black') for u, v in G2.edges()] + nx.draw(G2, pos, with_labels=False, node_size=10, font_size=8, edge_color=edge_colors) + plt.show() - # an.add_distributors(distributors) - # an.connect_distributor_to_racks() + an.add_distributors(distributors) + an.connect_distributor_to_racks() - # G3 = nx.Graph() - # pos = an.generate_graph(G3) + G3 = nx.Graph() + pos = an.generate_graph(G3) - # edge_colors = [G3[u][v].get('color', 'black') for u, v in G3.edges()] + edge_colors = [G3[u][v].get('color', 'black') for u, v in G3.edges()] - # nx.draw(G3, pos, with_labels=False, node_size=10, font_size=8, edge_color=edge_colors) - # plt.show() + nx.draw(G3, pos, with_labels=False, node_size=10, font_size=8, edge_color=edge_colors) + plt.show() - # def test_Wegsuche(self): - - # rack_segs = {'Rack_1-0': [Point(0, 0), Point(0, 10)], - # 'Rack_2-0': [Point(10, -2), Point(10, 5)], - # 'Rack_2-1': [Point(0, 3), Point(10, 3)]} + def test_Wegsuche(self): + ''' Erstellt Graphen mit Racks, Sensoren und Unterverteilern und sucht kürzeste Wege von Unterverteiler zu zugehörigen Sensoren''' + rack_segs = {'Rack_1-0': [Point(0, 0), Point(0, 10)], + 'Rack_2-0': [Point(10, -2), Point(10, 5)], + 'Rack_2-1': [Point(0, 3), Point(10, 3)]} - # sensors = {'Sens_1': Point(1, 1), - # 'Sens_2': Point(2, 4), - # 'Sens_3': Point(9, 2)} + sensors = {'Sens_1': Point(1, 1), + 'Sens_2': Point(2, 4), + 'Sens_3': Point(9, 2)} - # distributors = {'Dist_1': Point(-1, 9), - # 'Dist_2': Point(11, 0)} + distributors = {'Dist_1': Point(-1, 9), + 'Dist_2': Point(11, 0)} - # mapping = {'Dist_1': ['Sens_1', 'Sens_2'], - # 'Dist_2': ['Sens_3']} + mapping = {'Dist_1': ['Sens_1', 'Sens_2'], + 'Dist_2': ['Sens_3']} - # an = Anlage() - # an.set_racks(rack_segs) - # an.add_sensors(sensors) - # an.connect_sensors_to_racks() - # an.add_distributors(distributors) - # an.connect_distributor_to_racks() - # an.map_distributors_to_sensors(mapping) + # Erstelle Anlage + an = Anlage() + # Füge racks aus Daten hinzu + an.set_racks(rack_segs) + # Verbinde Racks miteinander (ggf. verlängere ungenaue Racks) + an.join_racks() + # Füge Sensoren als Knoten hinzu + an.add_sensors(sensors) + # Verbinde Sensoren mit deren naheliegendsten Racks + an.connect_sensors_to_racks() + # Füge UV hinzu + an.add_distributors(distributors) + # Verbinde UV mit deren naheliegendsten Racks + an.connect_distributor_to_racks() + # Verknüpfe Sensoren mit zugehörigem UV + an.map_distributors_to_sensors(mapping) + # Initialisiere Graph + G3 = nx.Graph() + # Fülle eben erstellten Graphen mit Daten + pos = an.generate_graph(G3) + # Extrahiere Farb-Informationen der Kanten + edge_colors = [G3[u][v].get('color', 'black') for u, v in G3.edges()] + # Zeiche Graphen und zeige in + nx.draw(G3, pos, with_labels=False, node_size=10, font_size=8, edge_color=edge_colors) + plt.show() - # G3 = nx.Graph() - # pos = an.generate_graph(G3) - # print(G3.nodes) - # print(G3.edges) - # print([(n, nbrdict) for n, nbrdict in G3.adjacency()]) - # print(an.show_node_ids()) - - - - # edge_colors = [G3[u][v].get('color', 'black') for u, v in G3.edges()] - - # nx.draw(G3, pos, with_labels=False, node_size=10, font_size=8, edge_color=edge_colors) - # plt.show() - - + # Ermittle kürzeste Wege von Unterverteilern zu zugehörigen Sensoren + paths = an.create_cable_paths(G3) - # paths = an.create_cable_paths(G3) - # self.assertEqual(paths, "") + self.assertEqual(paths['Dist_1-Sens_1']["path_coords"], [Point(-1, 9), Point(0, 9), Point(0, 3), Point(0, 1), Point(1, 1)]) + self.assertEqual(paths['Dist_1-Sens_2']["path_coords"], [Point(-1, 9), Point(0, 9), Point(0, 3), Point(2, 3), Point(2, 4)]) + self.assertEqual(paths['Dist_2-Sens_3']["path_coords"], [Point(11, 0), Point(10, 0), Point(10, 2), Point(9, 2)]) + self.assertEqual(paths['Dist_1-Sens_1']["path_length"], 10) + self.assertEqual(paths['Dist_1-Sens_2']["path_length"], 10) + self.assertEqual(paths['Dist_2-Sens_3']["path_length"], 4)