diff --git a/bin/getexdraw.bat b/bin/getexdraw.bat index 2e12910..aede7ce 100644 --- a/bin/getexdraw.bat +++ b/bin/getexdraw.bat @@ -1,4 +1,4 @@ -REM @echo off +@echo off if [%1]==[] goto usage for /F %%i in ("%1") do set FILENAME=%%~ni diff --git a/bin/routing.bat b/bin/routing.bat index 6347351..75c211f 100644 --- a/bin/routing.bat +++ b/bin/routing.bat @@ -1,4 +1,4 @@ @echo off CALL manage_interpreter.bat activate_interpreter -python %PROJECT_LIB%\routing.py %* +python -m cProfile -o file.prof %PROJECT_LIB%\routing.py %* CALL manage_interpreter.bat deactivate_interpreter diff --git a/bin/setenv.bat b/bin/setenv.bat index ae38e00..2e539ec 100644 --- a/bin/setenv.bat +++ b/bin/setenv.bat @@ -10,10 +10,12 @@ set PROJECT_DATA=%PROJECT%\data set PROJECT_WORK=%PROJECT%\work set PROJECT_LOG=%PROJECT%\log set PROJECT_TEST=%PROJECT%\testdata +set PROJECT_HOT=%PROJECT%\hotfolder if not exist %PROJECT%\work mkdir %PROJECT%\work if not exist %PROJECT%\log mkdir %PROJECT%\log if not exist %PROJECT%\data mkdir %PROJECT%\data +if not exist %PROJECT%\hotfolder mkdir %PROJECT%\hotfolder popd goto :eof diff --git a/lib/plant.py b/lib/plant.py index 4ccf7f5..7baea85 100644 --- a/lib/plant.py +++ b/lib/plant.py @@ -110,7 +110,7 @@ class NodeIDs(): def show(self): return self._id2cord class RackIDs(): - def __init__(self, tol_snap = 200): + def __init__(self, tol_snap = 200.0): self._point2rack = dict() self._rack2begend = dict() # Toleranzen zur Rack anbindung aneinander (Rack Snap) @@ -267,7 +267,7 @@ class Anlage(): """ - def __init__(self, tol_snap=200, snap_step=10, tol_connect=1000, tol_connect_step=50): + def __init__(self, tol_snap=200.0, snap_step=10.0, tol_connect=1000.0, tol_connect_step=50.0): # Container für alle Racks self._racks = RackIDs(tol_snap=tol_snap) # zuordnung zwischen KnotenID und Punkt @@ -288,6 +288,8 @@ class Anlage(): self._connect_step = tol_connect_step # Infos zum zeichnen des Graphen self._node_positions = dict() + # falls man die rack zu den Sensorpunkten abfragen möchte, ist ein STR Baum nötig + self._rack_tree = None def set_racks(self, racks:dict[str, list[Point]]): r""" @@ -362,21 +364,6 @@ class Anlage(): die Rückgabe enthält ein Tuple, welche Sensoren keinem Rack zugeordnet werden konnten ''' return self.connect_equipment_to_racks(self._sensors, self._sensor_onpoints) - ''' - errors = list() - for sname, pos in self._sensors.items(): - rack_borders = self._racks.get_racks_borders() - onpoint, rack_name = self.find_nearest_rack_from_point(self._tol_connect, self._connect_step, pos, rack_borders) - if onpoint == None or rack_name == None: - errors.append((sname, pos)) - continue - self._sensor_onpoints[sname] = (onpoint, rack_name) - self.add_point_to_rack(onpoint, rack_name) - # Füge "virtuelle Racks" von Sensor zu Aufpunkt von Sensor auf Rack hinzu. - vrackname = f"v-{sname}-{rack_name}" - self._racks.add_rack(pos, onpoint, vrackname) - return errors - ''' def add_distributor(self, dname: str, pos:Point): self._distributors[dname] = pos @@ -393,21 +380,6 @@ class Anlage(): die Rückage enthält ein Tuple, welche Unterverteiler keinem Rack zugeordnet werden konnten ''' return self.connect_equipment_to_racks(self._distributors, self._distributors_onpoints) - ''' - errors = list() - for dname, pos in self._distributors.items(): - rack_borders = self._racks.get_racks_borders() - onpoint, rack_name = self.find_nearest_rack_from_point(self._tol_connect, self._connect_step, pos, rack_borders) - if onpoint == None or rack_name == None: - errors.append((dname, pos)) - continue - self._distributors_onpoints[dname] = (onpoint, rack_name) - self.add_point_to_rack(onpoint, rack_name) - # Füge "virtuelle Racks" von Sensor zu Aufpunkt von Sensor auf Rack hinzu. - drackname = f"d-{dname}-{rack_name}" - self._racks.add_rack(pos, onpoint, drackname) - return errors - ''' def join_racks(self): self._racks.join_racks() @@ -420,40 +392,20 @@ class Anlage(): self._rack_lines.append(line) self._rack_map[line] = r_name self._rack_tree = STRtree(self._rack_lines) - - def find_nearest_rack_from_point_tree(self, max_dist, sensor:Point) -> tuple[Point, str]: - if not hasattr(self, "_rack_tree"): - self._build_rack_strtree() - - result = self._rack_tree.query_nearest(sensor, return_distance=True) - if result == None: - return None, None - - index_array, dist_array = result - nearest_index = index_array[0] - distance = dist_array[0] - - #nearest_line, distance = result - if distance > max_dist: - return None, None - - nearest_line = self._rack_lines[nearest_index] - rack_name = self._rack_map[nearest_line] - nearest_point = nearest_line.interpolate(nearest_line.project(sensor)) - return(nearest_point, rack_name) - + def find_nearest_rack_from_point_STR_bbox(self, max_dist, sensor:Point) -> tuple[Point, str]: - if not hasattr(self, "_rack_tree"): + if self._rack_tree is None: self._build_rack_strtree() minx, miny, maxx, maxy = sensor.x - max_dist, sensor.y - max_dist, sensor.x + max_dist, sensor.y + max_dist bbox = box(minx, miny, maxx, maxy) - candidates = self._rack_tree.query(box) - - if not candidates: - return None, None + candidates = self._rack_tree.query(bbox) + if len(candidates) == 0: + raise LookupError("no candidates in box found") + candidates = [self._rack_lines[idx] for idx in candidates] + best_dist = max_dist for line in candidates: dist = sensor.distance(line) if dist < best_dist: @@ -461,7 +413,7 @@ class Anlage(): best_line = line if best_dist > max_dist: - return None, None + raise LookupError("no line in correct distance found") rack_name = self._rack_map[best_line] nearest_point = best_line.interpolate(best_line.project(sensor)) @@ -475,11 +427,12 @@ class Anlage(): ''' errors = [] for name, pos in equipment.items(): - onpoint, rackname = self.find_nearest_rack_from_point_STR_bbox(self._tol_connect, pos) - if onpoint == None or rackname == None: + try: + onpoint, rackname = self.find_nearest_rack_from_point_STR_bbox(self._tol_connect, pos) + onpoints[name] = (onpoint, rackname) + except LookupError: errors.append((name, pos)) continue - onpoints[name] = (onpoint, rackname) self.add_point_to_rack(onpoint, rackname) virtual_rackname = f"v-{name}-{rackname}" @@ -487,76 +440,6 @@ class Anlage(): return errors - def connect_equipment_batch(self, equipment:dict, onpoints:dict) -> list: - if not hasattr(self, "_rack_tree"): - self._build_rack_strtree() - - devices = list(equipment.items()) - device_names = [name for name, _ in devices] - device_points = [pos for _, pos in devices] - - idx_rack, distances = self._rack_tree.query_nearest(device_points, return_distance=True, all_matches=False) - # !!! Problem !!!: query gibt mehrere Ergebnisse zurück -> kann dann nicht zugeordnet werden - # Greifen des ersten ergebnisses nicht zielführend, da nicht das näheste - - errors = [] - for i, (rack_idxs, dist) in enumerate(zip(idx_rack, distances)): - # Nehme ersten Treffer - rack_idx = int(rack_idxs[0]) - dist = float(dist) - - if dist > self._tol_connect: - errors.append(devices[i]) - continue - - eqname, eqpos = devices[i] - nearest_line = self._rack_lines[rack_idx] - rackname = self._rack_map[nearest_line] - onpoint = nearest_line.interpolate(nearest_line.project(eqpos)) - - onpoints[eqname] = (onpoint, rackname) - self.add_point_to_rack(onpoint, rackname) - - virtual_rackname = f"v-{eqname}-{rackname}" - self._racks.add_rack(eqpos, onpoint, virtual_rackname) - - return errors - - - def find_nearest_rack_from_point(self, max_dist, coarse_step, sensor:Point, racks:dict) -> tuple[Point, str]: - # 1. grobe Kandidatensuche - candidate_lines = [] - radius = coarse_step - rack_lines = dict() - while radius <= max_dist: - circle = sensor.buffer(radius) - for r_name, pts in racks.items(): - line = LineString([pts[0], pts[-1]]) #Linestring aus erstem und letzten Eintrag in Rack dict erzeugen - if circle.intersects(line): - candidate_lines.append((r_name, line)) - if candidate_lines: - break - radius += coarse_step - - if not candidate_lines: - return None, None - - # 2. Feinbestimmung über Distanz - candidates_distance = [ - (r_name, line, line.distance(sensor)) - for r_name, line in candidate_lines - ] - - # Sortieren nach Abstand - candidates_distance.sort(key=lambda x: x[2]) - '''# Theoretisch könnten mehrere ähnlich naheliegende Racks zurückgegeben werden.''' - r_best, line_best, _ = candidates_distance[0] # Hier wird nur das tatsächlich dem Senso nächste Rack gegriffen - - # Aufpunkt bestimmen - nearest_point = line_best.interpolate(line_best.project(sensor)) - - return (nearest_point, r_best) - def search_connections(self, rack_segments, segment_endpoints, tol, tol_step): ''' Aus Rack Segmenten und Endpunkten der Racks wird unter Berücksichtigung von Toleranz naheliegende Endpunkte gefunden. Zuerst echte Schnittpunkte und im Anschluss via Kreissuche neheliegende Punkte und deren gepinnte Berührpunkte @@ -736,132 +619,122 @@ class Anlage(): def show_node_ids(self): return self._nodeids.show() - - - -class TestLinesweep(unittest.TestCase): +class TestPlant(unittest.TestCase): - # def test_duplicate_points(self): - # ''' Testet das Nicht-Hinzufügen von doppelten Punkten''' - # # Initialisiere die Liste an Knoten - # nodeids = NodeIDs() + 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)) + # Setze gleichen Knoten doppelt + nodeids.add_point(Point(1,1)) + nodeids.add_point(Point(1,1)) - # self.assertEqual(nodeids.size_of(), 1) + self.assertEqual(nodeids.size_of(), 1) - - # def test_cut_rack_in_segments(self): - # ''' Teilt Rack aus Polyline in mehrere Segmente automatisch auf.''' - # racks_data = { - # 'Rack_1': [Point(0, 0), Point(0, 10), Point (10, 10)], - # 'Rack_2': [Point(-5, 5), Point(5, 5)] - # } + def test_cut_rack_in_segments(self): + ''' Teilt Rack aus Polyline in mehrere Segmente automatisch auf.''' + 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) + # 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']) + 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. ''' + 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)], - # } + 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 Schnittpunkten und füge Schnittpunkte (exakt & beinahe) zu jeweiligem Rack hinzu - # rack.join_racks() + # 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 Schnittpunkten 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)]) + self.assertEqual(rack.get_points_from_rack("Rack_1-1"), [Point(0, 0), Point(0, 5), Point (0, 10)]) - - # def test_snap_segments(self): - # ''' Verlängert Anfangs und Endpunkte von Racks, sodass sie auf naheliegenden Racks liegen''' - # racks_data = { - # 'Rack_1': [Point(0, 0), Point(0, 10)], - # 'Rack_2': [Point(1, 5), Point(5, 5)], - # 'Rack_3': [Point(1.5, 7.5), Point(5, 7.5)] - # } + def test_snap_segments(self): + ''' Verlängert Anfangs und Endpunkte von Racks, sodass sie auf naheliegenden Racks liegen''' + racks_data = { + 'Rack_1': [Point(0, 0), Point(0, 10)], + 'Rack_2': [Point(1, 5), Point(5, 5)], + 'Rack_3': [Point(1.5, 7.5), Point(5, 7.5)] + } - # # Initialisiere Racks - # rack = RackIDs(tol_snap=1) - # # 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 Schnittpunkten und füge Schnittpunkte (exakt & beinahe) zu jeweiligem Rack hinzu - # rack.join_racks() + # Initialisiere Racks + rack = RackIDs(tol_snap=1) + # 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 Schnittpunkten und füge Schnittpunkte (exakt & beinahe) zu jeweiligem Rack hinzu + rack.join_racks() - # #Rack 2 wird verlängert auf SP mit Rack 1. Rack 3 ausserhalb der Toleranz - # self.assertEqual(rack.get_points_from_rack("Rack_1"), [Point(0, 0), Point(0, 5), Point (0, 10)]) + #Rack 2 wird verlängert auf SP mit Rack 1. Rack 3 ausserhalb der Toleranz + 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() - # point2rack.add_racks(res_rack_seg) + point2rack = RackIDs() + point2rack.add_racks(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)]) - - - # def test_add_point_interim(self): - # ''' Testet das hinzufügen und einsortieren eines Zwischenpunktes zwischen Rack-Anfang und Rack-Ende''' + 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 hinzufügen und einsortieren eines Zwischenpunktes zwischen Rack-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() - # point2rack.add_racks(res_rack_seg) - # point2rack.add_point_to_rack(Point(1,4), "Rack_2-0") + point2rack = RackIDs() + point2rack.add_racks(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_add_equipment_w_tree(self): @@ -876,7 +749,7 @@ class TestLinesweep(unittest.TestCase): distributors = {'Dist_1': Point(-1, 9), 'Dist_2': Point(11, 0)} - an = Anlage(tol_snap=1.5) + an = Anlage(tol_snap=1.5, tol_connect=1.5) an.set_racks(racks) an.join_racks() @@ -891,193 +764,191 @@ class TestLinesweep(unittest.TestCase): self.assertEqual(plist1, [Point(0, 0), Point(0, 1), Point(0, 3), Point(0, 9), Point(0, 10)]) self.assertEqual(plist2, [Point(10, -2), Point(10, 0), Point(10, 2), Point(10, 3), Point(10, 5)]) + + def test_wegsuche_str_tree(self): + + # Beispiel-Daten + points = [Point(x, y) for x, y in [(1, 2), (3, 4), (5, 5), (7, 8)]] + lines = [LineString([(0, 1), (2, 3)]), LineString([(4, 4), (6, 6)]), LineString([(8, 8), (10, 10)])] + # STRtree erstellen mit tatsächlichen LineStrings + tree = STRtree(lines) - # def test_add_equipment_w_tree_batch(self): + # Zuordnung + nearest_line_for_point = {} + for point in points: + candidates = tree.query(point) # Gibt direkt LineStrings zurück + if not candidates: + continue + candidates = [lines[idx] for idx in candidates] + nearest_line = min(candidates, key=lambda line: line.distance(point)) + nearest_line_for_point[point] = nearest_line + + # Ausgabe + for point, line in nearest_line_for_point.items(): + print(f"Punkt {point} liegt am nächsten zu Linie {line}") + + def test_wegsuche_w_tree(self): + racks = {'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)]} - # racks = {'Rack_1': [Point(0, 0), Point(0, 10)], - # 'Rack_2': [Point(10, -2), Point(10, 5)], - # 'Rack_3': [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']} - # an = Anlage(tol_snap=1) - # an.set_racks(racks) - # an.join_racks() + an = Anlage(tol_snap=1) + an.set_racks(racks) + an.join_racks() - # an.add_sensors(sensors) - # an.add_distributors(distributors) - # an.connect_equipment_batch(an._sensors, an._sensor_onpoints) - # an.connect_equipment_batch(an._distributors, an._distributors_onpoints) + an.add_sensors(sensors) + an.add_distributors(distributors) + an.connect_equipment_to_racks(an._sensors, an._sensor_onpoints) + an.connect_equipment_to_racks(an._distributors, an._distributors_onpoints) - # plist1 = an.get_points_from_rack("Rack_1") - # plist2 = an.get_points_from_rack("Rack_2") + an.map_distributors_to_sensors(mapping) - # G1 = nx.Graph() - # pos = an.generate_graph(G1) - # nx.draw(G1, pos, with_labels=False, node_size=10, font_size=8) - # plt.show() + G = nx.Graph() + #Fülle eben erstellten Graphen mit Daten + pos = an.generate_graph(G) + #Extrahiere Farb-Informationen der Kanten + edge_colors = [G[u][v].get('color', 'black') for u, v in G.edges()] + #Zeiche Graphen und zeige in + nx.draw(G, 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(G) + + paths_by_id = {p['id']: p for p in paths["kabel"]} - # self.assertEqual(plist1, [Point(0, 0), Point(0, 1), Point(0, 3), Point(0, 9), Point(0, 10)]) - # self.assertEqual(plist2, [Point(10, -2), Point(10, 0), Point(10, 2), Point(10, 3), Point(10, 5)]) + self.assertEqual(paths_by_id['Dist_1-Sens_1']["coords"], [{'x': -1.0, 'y': 9.0}, {'x': 0.0, 'y': 9.0}, {'x': 0.0, 'y': 3.0}, {'x': 0.0, 'y': 1.0}, {'x': 1.0, 'y': 1.0}]) + self.assertEqual(paths_by_id['Dist_1-Sens_2']["coords"], [{'x': -1.0, 'y': 9.0}, {'x': 0.0, 'y': 9.0}, {'x': 0.0, 'y': 3.0}, {'x': 2.0, 'y': 3.0}, {'x': 2.0, 'y': 4.0}]) + self.assertEqual(paths_by_id['Dist_2-Sens_3']["coords"], [{'x': 11.0, 'y': 0.0}, {'x': 10.0, 'y': 0.0}, {'x': 10.0, 'y': 2.0}, {'x': 9.0, 'y': 2.0}]) + + self.assertEqual(paths_by_id['Dist_1-Sens_1']["length"], 10) + self.assertEqual(paths_by_id['Dist_1-Sens_2']["length"], 10) + self.assertEqual(paths_by_id['Dist_2-Sens_3']["length"], 4) - - - # def test_wegsuche_w_tree(self): - # racks = {'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 Ausbaustufen (nur Racks, Racks+Sensoren, Racks+Sensoren+Unterverteiler)''' - # sensors = {'Sens_1': Point(1, 1), - # 'Sens_2': Point(2, 4), - # 'Sens_3': Point(9, 2)} + 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)]} - # distributors = {'Dist_1': Point(-1, 9), - # 'Dist_2': Point(11, 0)} + sensors = {'Sens_1': Point(1, 1), + 'Sens_2': Point(2, 4), + 'Sens_3': Point(9, 2)} - # mapping = {'Dist_1': ['Sens_1', 'Sens_2'], - # 'Dist_2': ['Sens_3']} + distributors = {'Dist_1': Point(-1, 9), + 'Dist_2': Point(11, 0)} + + 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() + + an.add_sensors(sensors) + an.connect_sensors_to_racks() + 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() + + an.add_distributors(distributors) + an.connect_distributor_to_racks() + G3 = nx.Graph() + pos = an.generate_graph(G3) + 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() + + def test_Wegsuche(self): + ''' Erstellt Graphen mit Racks, Sensoren und Unterverteilern und sucht kürzeste Wege von Unterverteiler zu zugehörigen Sensoren''' - # an = Anlage(tol_snap=1) - # an.set_racks(racks) - # an.join_racks() - - # an.add_sensors(sensors) - # an.add_distributors(distributors) - # an.connect_equipment_to_racks(an._sensors, an._sensor_onpoints) - # an.connect_equipment_to_racks(an._distributors, an._distributors_onpoints) - - # an.map_distributors_to_sensors(mapping) - - # G = nx.Graph() - # Fülle eben erstellten Graphen mit Daten - # pos = an.generate_graph(G) - # Extrahiere Farb-Informationen der Kanten - # edge_colors = [G[u][v].get('color', 'black') for u, v in G.edges()] - # Zeiche Graphen und zeige in - # nx.draw(G, 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(G) - - # paths_by_id = {p['id']: p for p in paths["kabel"]} - - - # self.assertEqual(paths_by_id['Dist_1-Sens_1']["coords"], [{'x': -1.0, 'y': 9.0}, {'x': 0.0, 'y': 9.0}, {'x': 0.0, 'y': 3.0}, {'x': 0.0, 'y': 1.0}, {'x': 1.0, 'y': 1.0}]) - # self.assertEqual(paths_by_id['Dist_1-Sens_2']["coords"], [{'x': -1.0, 'y': 9.0}, {'x': 0.0, 'y': 9.0}, {'x': 0.0, 'y': 3.0}, {'x': 2.0, 'y': 3.0}, {'x': 2.0, 'y': 4.0}]) - # self.assertEqual(paths_by_id['Dist_2-Sens_3']["coords"], [{'x': 11.0, 'y': 0.0}, {'x': 10.0, 'y': 0.0}, {'x': 10.0, 'y': 2.0}, {'x': 9.0, 'y': 2.0}]) - - # self.assertEqual(paths_by_id['Dist_1-Sens_1']["length"], 10) - # self.assertEqual(paths_by_id['Dist_1-Sens_2']["length"], 10) - # self.assertEqual(paths_by_id['Dist_2-Sens_3']["length"], 4) - - - # def test_generate_graph(self): - # '''Generiert einen Graphen in 3 unterschiedlichen Ausbaustufen (nur Racks, Racks+Sensoren, Racks+Sensoren+Unterverteiler)''' + rack_segs = {'Rack_1': [Point(0, 0), Point(0, 10)], + 'Rack_2': [Point(10, -2), Point(10, 5)], + 'Rack_3': [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)} + 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']} - # 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() - - # an.add_sensors(sensors) - # an.connect_sensors_to_racks() - # 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() - - # an.add_distributors(distributors) - # an.connect_distributor_to_racks() - # G3 = nx.Graph() - # pos = an.generate_graph(G3) - # 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() + #Erstelle Anlage + an = Anlage(tol_snap=1) + #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() - # 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': [Point(0, 0), Point(0, 10)], - # 'Rack_2': [Point(10, -2), Point(10, 5)], - # 'Rack_3': [Point(0, 3), Point(10, 3)]} - - # 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)} - - # mapping = {'Dist_1': ['Sens_1', 'Sens_2'], - # 'Dist_2': ['Sens_3']} + #Ermittle kürzeste Wege von Unterverteilern zu zugehörigen Sensoren + paths = an.create_cable_paths(G3) - # Erstelle Anlage - # an = Anlage(tol_snap=1) - # 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() - - # Ermittle kürzeste Wege von Unterverteilern zu zugehörigen Sensoren - # paths = an.create_cable_paths(G3) - - # paths_by_id = {p['id']: p for p in paths["kabel"]} + paths_by_id = {p['id']: p for p in paths["kabel"]} - # self.assertEqual(paths_by_id['Dist_1-Sens_1']["coords"], [{'x': -1.0, 'y': 9.0}, {'x': 0.0, 'y': 9.0}, {'x': 0.0, 'y': 3.0}, {'x': 0.0, 'y': 1.0}, {'x': 1.0, 'y': 1.0}]) - # self.assertEqual(paths_by_id['Dist_1-Sens_2']["coords"], [{'x': -1.0, 'y': 9.0}, {'x': 0.0, 'y': 9.0}, {'x': 0.0, 'y': 3.0}, {'x': 2.0, 'y': 3.0}, {'x': 2.0, 'y': 4.0}]) - # self.assertEqual(paths_by_id['Dist_2-Sens_3']["coords"], [{'x': 11.0, 'y': 0.0}, {'x': 10.0, 'y': 0.0}, {'x': 10.0, 'y': 2.0}, {'x': 9.0, 'y': 2.0}]) - - # self.assertEqual(paths_by_id['Dist_1-Sens_1']["length"], 10) - # self.assertEqual(paths_by_id['Dist_1-Sens_2']["length"], 10) - # self.assertEqual(paths_by_id['Dist_2-Sens_3']["length"], 4) - + self.assertEqual(paths_by_id['Dist_1-Sens_1']["coords"], [{'x': -1.0, 'y': 9.0}, {'x': 0.0, 'y': 9.0}, {'x': 0.0, 'y': 3.0}, {'x': 0.0, 'y': 1.0}, {'x': 1.0, 'y': 1.0}]) + self.assertEqual(paths_by_id['Dist_1-Sens_2']["coords"], [{'x': -1.0, 'y': 9.0}, {'x': 0.0, 'y': 9.0}, {'x': 0.0, 'y': 3.0}, {'x': 2.0, 'y': 3.0}, {'x': 2.0, 'y': 4.0}]) + self.assertEqual(paths_by_id['Dist_2-Sens_3']["coords"], [{'x': 11.0, 'y': 0.0}, {'x': 10.0, 'y': 0.0}, {'x': 10.0, 'y': 2.0}, {'x': 9.0, 'y': 2.0}]) + self.assertEqual(paths_by_id['Dist_1-Sens_1']["length"], 10) + self.assertEqual(paths_by_id['Dist_1-Sens_2']["length"], 10) + self.assertEqual(paths_by_id['Dist_2-Sens_3']["length"], 4) if __name__ == '__main__': - unittest.main() \ No newline at end of file + suite = unittest.TestSuite() + suite.addTest(TestPlant('test_duplicate_points')) + suite.addTest(TestPlant('test_cut_rack_in_segments')) + suite.addTest(TestPlant('test_intersect_segments')) + suite.addTest(TestPlant('test_snap_segments')) + suite.addTest(TestPlant('test_ids_to_point')) + suite.addTest(TestPlant('test_add_point_interim')) + suite.addTest(TestPlant('test_add_sensor')) + suite.addTest(TestPlant('test_add_equipment_w_tree')) + suite.addTest(TestPlant('test_add_equipment_w_tree_batch')) + suite.addTest(TestPlant('test_wegsuche_str_tree')) + suite.addTest(TestPlant('test_wegsuche_w_tree')) + suite.addTest(TestPlant('test_generate_graph')) + suite.addTest(TestPlant('test_Wegsuche')) + runner = unittest.TextTestRunner() + runner.run(suite) + #unittest.main() diff --git a/lib/requirements.txt b/lib/requirements.txt index a0c89b3..452a0e0 100644 --- a/lib/requirements.txt +++ b/lib/requirements.txt @@ -20,9 +20,6 @@ pip-tools==7.4.1 PyMuPDF==1.25.5 pyparsing==3.2.3 pyproject_hooks==1.2.0 -PySide6==6.9.0 -PySide6_Addons==6.9.0 -PySide6_Essentials==6.9.0 python-dateutil==2.8.2 pytz==2023.3.post1 setuptools==80.0.0