Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b4149870f6 | |||
| b8b5db45eb |
Vendored
+27
-29
@@ -1,10 +1,13 @@
|
|||||||
{
|
{
|
||||||
// Verwendet IntelliSense zum Ermitteln möglicher Attribute.
|
|
||||||
// Zeigen Sie auf vorhandene Attribute, um die zugehörigen Beschreibungen anzuzeigen.
|
|
||||||
// Weitere Informationen finden Sie unter https://go.microsoft.com/fwlink/?linkid=830387
|
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Python Debugger: Current File",
|
||||||
|
"type": "debugpy",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${file}",
|
||||||
|
"console": "integratedTerminal"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Python-Debugger: Aktuelle Datei mit Argumenten",
|
"name": "Python-Debugger: Aktuelle Datei mit Argumenten",
|
||||||
"type": "debugpy",
|
"type": "debugpy",
|
||||||
@@ -18,24 +21,22 @@
|
|||||||
"type": "debugpy",
|
"type": "debugpy",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${file}",
|
"program": "${file}",
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal"
|
||||||
"justMyCode": true
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "use easy.dxf",
|
"name": "getpositions with easy.dxf",
|
||||||
"type": "debugpy",
|
"type": "debugpy",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${file}",
|
"program": "${file}",
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"justMyCode": true,
|
|
||||||
"args": [
|
"args": [
|
||||||
"--filename",
|
"--filename",
|
||||||
"easy.dxf",
|
"easy.dxf",
|
||||||
"-s",
|
"--sensors",
|
||||||
"-d",
|
"--dists",
|
||||||
"-r",
|
"--rack",
|
||||||
"-c",
|
"--console",
|
||||||
"-w"
|
"--write"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -44,12 +45,12 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${file}",
|
"program": "${file}",
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"justMyCode": true,
|
|
||||||
"args": [
|
"args": [
|
||||||
"--filename",
|
"--filename",
|
||||||
"easy.dxf",
|
"easy.dxf",
|
||||||
"-r",
|
"-r",
|
||||||
"-c"
|
"-c",
|
||||||
|
"-w"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -58,7 +59,6 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${file}",
|
"program": "${file}",
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"justMyCode": true,
|
|
||||||
"args": [
|
"args": [
|
||||||
"--filename",
|
"--filename",
|
||||||
"ST_6300_Steuerungstestlayout1_neueBloecke.dxf",
|
"ST_6300_Steuerungstestlayout1_neueBloecke.dxf",
|
||||||
@@ -67,31 +67,29 @@
|
|||||||
"-r"
|
"-r"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "run routing for easy",
|
|
||||||
"type": "debugpy",
|
|
||||||
"request": "launch",
|
|
||||||
"program": "${file}",
|
|
||||||
"console": "integratedTerminal",
|
|
||||||
"justMyCode": true,
|
|
||||||
"args": [
|
|
||||||
"--inputfile",
|
|
||||||
"easy_positions.json"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "draw cable dxf from easy.json",
|
"name": "draw cable dxf from easy.json",
|
||||||
"type": "debugpy",
|
"type": "debugpy",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${file}",
|
"program": "${file}",
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"justMyCode": true,
|
|
||||||
"args": [
|
"args": [
|
||||||
"--json",
|
"--json",
|
||||||
"easy.json",
|
"easy.json",
|
||||||
"--dxf",
|
"--dxf",
|
||||||
"easy.dxf"
|
"easy.dxf"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "routing for easy_positions.json",
|
||||||
|
"type": "debugpy",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${file}",
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"args": [
|
||||||
|
"--filename",
|
||||||
|
"easy_positions.json"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
@echo off
|
@echo off
|
||||||
CALL manage_interpreter.bat activate_interpreter
|
CALL manage_interpreter.bat activate_interpreter
|
||||||
python %PROJECT_LIB%\drawdxf.py
|
python %PROJECT_LIB%\drawdxf.py %*
|
||||||
CALL manage_interpreter.bat deactivate_interpreter
|
CALL manage_interpreter.bat deactivate_interpreter
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@echo off
|
||||||
|
CALL manage_interpreter.bat activate_interpreter
|
||||||
|
python %PROJECT_LIB%\routing.py %*
|
||||||
|
CALL manage_interpreter.bat deactivate_interpreter
|
||||||
+4
-6
@@ -7,6 +7,7 @@ import sys
|
|||||||
import math
|
import math
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
|
from shapely import Point
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@@ -132,13 +133,10 @@ def get_rack_positions(msp):
|
|||||||
for e in msp.query('LWPOLYLINE[layer=="PRITSCHE_200-60"]'):
|
for e in msp.query('LWPOLYLINE[layer=="PRITSCHE_200-60"]'):
|
||||||
#print_polyline(e)
|
#print_polyline(e)
|
||||||
rack_key = f"Rack_{rack_counter}"
|
rack_key = f"Rack_{rack_counter}"
|
||||||
ret[rack_key] = dict()
|
ret[rack_key] = list()
|
||||||
|
|
||||||
node_counter = 1
|
|
||||||
for x, y, start_width, end_width, bulge in e.get_points(): # Gibt Tuple (x, y, start_width, end_width, bulge)
|
for x, y, start_width, end_width, bulge in e.get_points(): # Gibt Tuple (x, y, start_width, end_width, bulge)
|
||||||
node_key = f"Node_{node_counter}"
|
p = [round(x,1), round(y,1)]
|
||||||
ret[rack_key][node_key] = [round(x,1), round(y,1)]
|
ret[rack_key].append(p)
|
||||||
node_counter +=1
|
|
||||||
rack_counter +=1
|
rack_counter +=1
|
||||||
# iterate over all entities in modelspace
|
# iterate over all entities in modelspace
|
||||||
# for e in msp:
|
# for e in msp:
|
||||||
|
|||||||
@@ -152,8 +152,6 @@ class RackIDs():
|
|||||||
def get_rack_names(self) -> list:
|
def get_rack_names(self) -> list:
|
||||||
return list(self._rack2begend.keys())
|
return list(self._rack2begend.keys())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def add_point_to_rack(self, point:Point, name:str):
|
def add_point_to_rack(self, point:Point, name:str):
|
||||||
if point in self._point2rack:
|
if point in self._point2rack:
|
||||||
self._point2rack[point].append(name)
|
self._point2rack[point].append(name)
|
||||||
@@ -199,12 +197,10 @@ class RackIDs():
|
|||||||
last = Point(l2.coords[1])
|
last = Point(l2.coords[1])
|
||||||
if l1.distance(first) <= self._tol_snap:
|
if l1.distance(first) <= self._tol_snap:
|
||||||
snap_point = l1.interpolate(l1.project(first))
|
snap_point = l1.interpolate(l1.project(first))
|
||||||
|
self.add_point_to_rack(snap_point, rnames[l1])
|
||||||
if l1.distance(last) <= self._tol_snap:
|
if l1.distance(last) <= self._tol_snap:
|
||||||
snap_point = l1.interpolate(l1.project(last))
|
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):
|
def rack_is_horizontal(self, name):
|
||||||
[pa, pe] = self._rack2begend[name]
|
[pa, pe] = self._rack2begend[name]
|
||||||
@@ -216,39 +212,52 @@ class RackIDs():
|
|||||||
class Anlage():
|
class Anlage():
|
||||||
r"""
|
r"""
|
||||||
Baut eine Anlage besteend aus Kabeltrassen (Racks), Sensoren und Unterverteilern auf.
|
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
|
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
|
Returns
|
||||||
-------
|
-------
|
||||||
distance : dictionary
|
|
||||||
Dictionary, keyed by source and target, of shortest paths.
|
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
>>> graph = nx.DiGraph()
|
>>> # Erstelle Anlage
|
||||||
>>> graph.add_weighted_edges_from(
|
>>> an = Anlage()
|
||||||
... [("0", "3", 3), ("0", "1", -5), ("0", "2", 2), ("1", "2", 4), ("2", "3", 1)]
|
>>> # Füge racks aus Daten hinzu
|
||||||
... )
|
>>> an.set_racks(rack_segs)
|
||||||
>>> paths = nx.johnson(graph, weight="weight")
|
>>> # Verbinde Racks miteinander (ggf. verlängere ungenaue Racks)
|
||||||
>>> paths["0"]["2"]
|
>>> an.join_racks()
|
||||||
['0', '1', '2']
|
>>> # 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):
|
def __init__(self, tol_snap=200, snap_step=10, tol_connect=2, tol_connect_step=0.5):
|
||||||
@@ -270,18 +279,44 @@ class Anlage():
|
|||||||
# Toleranzen zur Anbindung von Sensoren / Verteilern zu Racks
|
# Toleranzen zur Anbindung von Sensoren / Verteilern zu Racks
|
||||||
self._tol_connect = tol_connect
|
self._tol_connect = tol_connect
|
||||||
self._connect_step = tol_connect_step
|
self._connect_step = tol_connect_step
|
||||||
|
# Infos zum zeichnen des Graphen
|
||||||
|
self._node_positions = dict()
|
||||||
|
|
||||||
|
|
||||||
def set_racks(self, racks:dict[str, list[Point]]):
|
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)
|
return self._racks.add_racks(racks)
|
||||||
|
|
||||||
def get_racks(self) -> dict:
|
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
|
return self._racks._point2rack
|
||||||
|
|
||||||
def add_point_to_rack(self, point:Point, rname:str):
|
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)
|
return self._racks.add_point_to_rack(point, rname)
|
||||||
|
|
||||||
def get_all_rack_points(self):
|
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()
|
ret = list()
|
||||||
for rname in self._racks.get_rack_names():
|
for rname in self._racks.get_rack_names():
|
||||||
ret.extend(self.get_points_from_rack(rname))
|
ret.extend(self.get_points_from_rack(rname))
|
||||||
@@ -342,60 +377,8 @@ class Anlage():
|
|||||||
self._racks.add_rack(pos, onpoint, drackname)
|
self._racks.add_rack(pos, onpoint, drackname)
|
||||||
return self._distributors_onpoints
|
return self._distributors_onpoints
|
||||||
|
|
||||||
def rack_segmentation(self, racks:dict) -> list[tuple[str, int, LineString]]:
|
def join_racks(self):
|
||||||
''' Racks werden zu LineString konvertiert. Racks bestehend aus Polylinine werden in einzelne Segmente zerlegt und in Liste gesammelt.
|
self._racks.join_racks()
|
||||||
'''
|
|
||||||
rack_segments = []
|
|
||||||
for rack_id, nodes in racks.items():
|
|
||||||
# Sortiere Node_1, Node_2, ...
|
|
||||||
sorted_keys = sorted(nodes.keys(), key=lambda k: int(k.split("_")[1]))
|
|
||||||
coords = [tuple(nodes[k]) for k in sorted_keys]
|
|
||||||
|
|
||||||
for i in range(len(coords) - 1):
|
|
||||||
p1, p2 = coords[i], coords[i+1]
|
|
||||||
line = LineString([p1, p2])
|
|
||||||
rack_segments.append((rack_id, i, line))
|
|
||||||
|
|
||||||
return(rack_segments)
|
|
||||||
|
|
||||||
def find_rack_endpoints(self, rack_segments):
|
|
||||||
''' Endpunkte der Racks-Segmente werden in Points konvertiert und in Liste gesammelt'''
|
|
||||||
segment_endpoints = []
|
|
||||||
for rack_id, idx, line in rack_segments:
|
|
||||||
for pt in [line.coords[0], line.coords[1]]:
|
|
||||||
segment_endpoints.append((rack_id, idx, Point(pt)))
|
|
||||||
|
|
||||||
return(segment_endpoints)
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
Argumente:
|
|
||||||
tol, tol_step -- Toleranz und Schittweite
|
|
||||||
line -- linestring der entlang gelaufen wird
|
|
||||||
rack_id, idx -- Rack_id und index von dem linestring stammt
|
|
||||||
pt -- Punkt der Überprüft wird
|
|
||||||
other_rack_id, other_idx -- Rack zu welchem der zu untersuchende Punkt gehört
|
|
||||||
verbindungen -- Liste an die angefügt wird und die verbindungspunkte speichert
|
|
||||||
endpoint_pinned -- Liste, die Rack und index von dem untersuchten Punkt und den neuen angepinnten Punkt speichert
|
|
||||||
'''
|
|
||||||
radius = tol_step
|
|
||||||
while radius <= tol:
|
|
||||||
circle = pt.buffer(radius)
|
|
||||||
if circle.intersects(line):
|
|
||||||
contact = circle.intersection(line)
|
|
||||||
if contact.geom_type == "Point":
|
|
||||||
nearest = contact
|
|
||||||
else:
|
|
||||||
nearest = nearest_points(pt, contact)[1]
|
|
||||||
#print(f" 🟡 Kreisberührung bei {nearest} mit {rack_id}_{idx}")
|
|
||||||
verbindungen.append((rack_id, idx, other_rack_id, other_idx, nearest))
|
|
||||||
|
|
||||||
# Füge verschobenen Endpunkt zu Liste hinzu. [Punkt gehört zu Rack_Nr, alter Punkt, neuer Punkt, gepinnt an Target_Rack]
|
|
||||||
endpoint_pinned.append((other_rack_id, other_idx, pt, nearest, rack_id))
|
|
||||||
|
|
||||||
break
|
|
||||||
radius += tol_step
|
|
||||||
|
|
||||||
def find_nearest_rack_from_point(self, max_dist, coarse_step, sensor:Point, racks:dict) -> tuple[Point, str]:
|
def find_nearest_rack_from_point(self, max_dist, coarse_step, sensor:Point, racks:dict) -> tuple[Point, str]:
|
||||||
# 1. grobe Kandidatensuche
|
# 1. grobe Kandidatensuche
|
||||||
@@ -515,14 +498,10 @@ class Anlage():
|
|||||||
d_rack_to_points[key] = unique_points
|
d_rack_to_points[key] = unique_points
|
||||||
|
|
||||||
return rack_segments_pinned
|
return rack_segments_pinned
|
||||||
|
|
||||||
def generate_connected_racks(self, racks_json:dict[str, list[Point]]) -> dict:
|
def get_node_positions(self):
|
||||||
rack_segments = self.rack_segmentation(racks_json)
|
''' Daten werden durch generate_graph() befüllt'''
|
||||||
rack_endpoints = self.find_rack_endpoints(rack_segments) # könnte man hier auch get_racks_borders nehmen?
|
return self._node_positions
|
||||||
|
|
||||||
connected_racks = self.search_connections(rack_segments, rack_endpoints, self._tol_snap, self._snap_step) #Kann man diese Ausgabe jetzt nochmal in sowas wie add_Racks aufrufen um "eingelesene Racks" zu überscheiben?
|
|
||||||
self._racks.add_racks(connected_racks)
|
|
||||||
return connected_racks
|
|
||||||
|
|
||||||
def is_sensor(self, p:Point) -> bool:
|
def is_sensor(self, p:Point) -> bool:
|
||||||
if p in self._sensors.values():
|
if p in self._sensors.values():
|
||||||
@@ -538,11 +517,8 @@ class Anlage():
|
|||||||
|
|
||||||
def generate_graph(self, G:nx.Graph):
|
def generate_graph(self, G:nx.Graph):
|
||||||
points = list()
|
points = list()
|
||||||
|
|
||||||
points.extend(self.get_all_rack_points())
|
points.extend(self.get_all_rack_points())
|
||||||
|
points.extend(self.get_points_from_sensors())
|
||||||
points.extend(self.get_points_from_sensors())
|
|
||||||
|
|
||||||
self._nodeids.add_points(points)
|
self._nodeids.add_points(points)
|
||||||
|
|
||||||
for p in points:
|
for p in points:
|
||||||
@@ -555,10 +531,10 @@ class Anlage():
|
|||||||
nid = self._nodeids.get_id(p)
|
nid = self._nodeids.get_id(p)
|
||||||
G.add_node(nid, shape=shape) # Knoten für Startpunkt
|
G.add_node(nid, shape=shape) # Knoten für Startpunkt
|
||||||
|
|
||||||
pos = dict()
|
|
||||||
for node in G.nodes:
|
for node in G.nodes:
|
||||||
point = self._nodeids.get_point(node)
|
point = self._nodeids.get_point(node)
|
||||||
pos[node] = (point.x, point.y)
|
self._node_positions[node] = (point.x, point.y)
|
||||||
|
|
||||||
for rname in self.get_rack_names():
|
for rname in self.get_rack_names():
|
||||||
plist = self.get_points_from_rack(rname)
|
plist = self.get_points_from_rack(rname)
|
||||||
@@ -573,7 +549,7 @@ class Anlage():
|
|||||||
else:
|
else:
|
||||||
color = "black"
|
color = "black"
|
||||||
G.add_edge(nid_start, nid_end, color=color, weight=start.distance(end))
|
G.add_edge(nid_start, nid_end, color=color, weight=start.distance(end))
|
||||||
return pos
|
return self._node_positions
|
||||||
|
|
||||||
def map_distributor_to_sensors(self, dname:str, snamen:list[str]):
|
def map_distributor_to_sensors(self, dname:str, snamen:list[str]):
|
||||||
''' Gibt zu einem Distributor die zugehörigen Sensoren an, die später zugeordnet werden.
|
''' Gibt zu einem Distributor die zugehörigen Sensoren an, die später zugeordnet werden.
|
||||||
@@ -593,8 +569,6 @@ class Anlage():
|
|||||||
def create_cable_path(self, G, sname, dname):
|
def create_cable_path(self, G, sname, dname):
|
||||||
quelle = self._nodeids.get_id(self.get_distributor_point(dname))
|
quelle = self._nodeids.get_id(self.get_distributor_point(dname))
|
||||||
ziel = self._nodeids.get_id(self.get_sensor_point(sname))
|
ziel = self._nodeids.get_id(self.get_sensor_point(sname))
|
||||||
print(self.get_distributor_point(dname), dname, quelle)
|
|
||||||
print(self.get_sensor_point(sname), sname, ziel)
|
|
||||||
pfad_nodes = nx.shortest_path(G, source=quelle, target=ziel, weight='weight')
|
pfad_nodes = nx.shortest_path(G, source=quelle, target=ziel, weight='weight')
|
||||||
pfad_length = nx.shortest_path_length(G, source=quelle, target=ziel, weight='weight')
|
pfad_length = nx.shortest_path_length(G, source=quelle, target=ziel, weight='weight')
|
||||||
|
|
||||||
@@ -604,7 +578,12 @@ class Anlage():
|
|||||||
pfade = dict()
|
pfade = dict()
|
||||||
for sname, dname in self._sensor2dist.items():
|
for sname, dname in self._sensor2dist.items():
|
||||||
pfad_nodes, pfad_length = self.create_cable_path(G, sname, dname)
|
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):
|
def show_node_ids(self):
|
||||||
return self._nodeids.show()
|
return self._nodeids.show()
|
||||||
@@ -617,57 +596,16 @@ class Anlage():
|
|||||||
class TestLinesweep(unittest.TestCase):
|
class TestLinesweep(unittest.TestCase):
|
||||||
|
|
||||||
def test_duplicate_points(self):
|
def test_duplicate_points(self):
|
||||||
|
''' Testet das Nicht-Hinzufügen von doppelten Punkten'''
|
||||||
|
# Initialisiere die Liste an Knoten
|
||||||
nodeids = NodeIDs()
|
nodeids = NodeIDs()
|
||||||
|
|
||||||
|
# Setze gleichen Knoten doppelt
|
||||||
nodeids.add_point(Point(1,1))
|
nodeids.add_point(Point(1,1))
|
||||||
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_linesweep(self):
|
|
||||||
''' Prüft ob aus ungeanuen Endpunkten von Racks innerhalb einer Json ein neues Rack-Gerüst mit aufeinander Liegenden
|
|
||||||
Endpunkten auf Racks erzeugt wird.
|
|
||||||
'''
|
|
||||||
tol = 200
|
|
||||||
tol_step = 10
|
|
||||||
|
|
||||||
racks_json_str= '''{
|
|
||||||
"Rack_1": {
|
|
||||||
"Node_1": [ 4946.5, 15774.4 ],
|
|
||||||
"Node_2": [ 4946.5, 3879.4 ]
|
|
||||||
},
|
|
||||||
"Rack_2": {
|
|
||||||
"Node_1": [ 0.1, 57.6 ],
|
|
||||||
"Node_2": [ 0.1, 3777.6 ],
|
|
||||||
"Node_3": [ 14755.1, 3777.6 ]
|
|
||||||
},
|
|
||||||
"Rack_3": {
|
|
||||||
"Node_1": [ 185.1, 15865.5 ],
|
|
||||||
"Node_2": [ 12450.7, 15865.5 ] },
|
|
||||||
"Rack_4": {
|
|
||||||
"Node_1": [ 2866.6, 15774.4 ],
|
|
||||||
"Node_2": [ 2866.6, 3880.4 ]
|
|
||||||
},
|
|
||||||
"Rack_5": {
|
|
||||||
"Node_1": [ 8866.1, 15774.4 ],
|
|
||||||
"Node_2": [ 8866.1, 3878.4 ]
|
|
||||||
}}'''
|
|
||||||
|
|
||||||
racks_json = json.loads(racks_json_str)
|
|
||||||
|
|
||||||
an = Anlage()
|
|
||||||
|
|
||||||
connected_racks = an.generate_connected_racks(racks_json)
|
|
||||||
|
|
||||||
res_rack_seg = {'Rack_1-0': [Point(4946.5, 15865.5), Point(4946.5, 3777.6)],
|
|
||||||
'Rack_2-0': [Point(0.1, 57.6), Point(0.1, 3777.6)],
|
|
||||||
'Rack_2-1': [Point(0.1, 3777.6), Point(14755.1, 3777.6)],
|
|
||||||
'Rack_3-0': [Point(185.1, 15865.5), Point(12450.7, 15865.5)],
|
|
||||||
'Rack_4-0': [Point(2866.6, 15865.5), Point(2866.6, 3777.6)],
|
|
||||||
'Rack_5-0': [Point(8866.1, 15865.5), Point(8866.1, 3777.6)]
|
|
||||||
}
|
|
||||||
|
|
||||||
self.assertEqual(connected_racks, res_rack_seg)
|
|
||||||
|
|
||||||
def test_cut_rack_in_segments(self):
|
def test_cut_rack_in_segments(self):
|
||||||
''' Teilt Rack aus Polyline in mehrere Segmente automatisch auf.'''
|
''' Teilt Rack aus Polyline in mehrere Segmente automatisch auf.'''
|
||||||
@@ -676,23 +614,27 @@ class TestLinesweep(unittest.TestCase):
|
|||||||
'Rack_2': [Point(-5, 5), Point(5, 5)]
|
'Rack_2': [Point(-5, 5), Point(5, 5)]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Initialisiere Racks
|
||||||
rack = RackIDs()
|
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)
|
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):
|
def test_intersect_segments(self):
|
||||||
''' Stellt Schnittpunkte zwischen Racks fest und fügt Schnittpunkt zu Rack hinzu. '''
|
''' Stellt Schnittpunkte zwischen Racks fest und fügt Schnittpunkt zu Rack hinzu. '''
|
||||||
|
|
||||||
racks_data = {
|
racks_data = {
|
||||||
'Rack_1': [Point(0, 0), Point(0, 10), Point (10, 10)],
|
'Rack_1': [Point(0, 0), Point(0, 10), Point (10, 10)],
|
||||||
'Rack_2': [Point(-5, 5), Point(5, 5)],
|
'Rack_2': [Point(-5, 5), Point(5, 5)],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Initialisiere Racks
|
||||||
rack = RackIDs()
|
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)
|
rack.add_racks(racks_data)
|
||||||
|
# Verknüpfe Racks mit echten Schniuttpunkten und füge Schnittpunkte (exakt & beinahe) zu jeweiligem Rack hinzu
|
||||||
rack.join_racks()
|
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)])
|
||||||
@@ -704,156 +646,167 @@ class TestLinesweep(unittest.TestCase):
|
|||||||
'Rack_2': [Point(1, 5), Point(5, 5)],
|
'Rack_2': [Point(1, 5), Point(5, 5)],
|
||||||
'Rack_3': [Point(1.5, 7.5), Point(5,7.5)]
|
'Rack_3': [Point(1.5, 7.5), Point(5,7.5)]
|
||||||
}
|
}
|
||||||
|
# Initialisiere Racks
|
||||||
rack = RackIDs()
|
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)
|
rack.add_racks(racks_data)
|
||||||
|
# Verknüpfe Racks mit echten Schniuttpunkten und füge Schnittpunkte (exakt & beinahe) zu jeweiligem Rack hinzu
|
||||||
rack.join_racks()
|
rack.join_racks()
|
||||||
|
|
||||||
self.assertEqual(rack.get_points_from_rack("Rack_1"), [Point(0, 0), Point(0, 5), Point (0, 10)])
|
self.assertEqual(rack.get_points_from_rack("Rack_1"), [Point(0, 0), Point(0, 5), Point (0, 10)])
|
||||||
|
|
||||||
# def test_ids_to_point(self):
|
def test_ids_to_point(self):
|
||||||
# ''' Testet, ob gefragter Punkt auf Racks a, b, c liegt'''
|
''' Testet, ob gefragter Punkt auf Racks a, b, c liegt'''
|
||||||
|
|
||||||
# res_rack_seg = {'Rack_1-0': [Point(1, 0), Point(5, 6)],
|
res_rack_seg = {'Rack_1-0': [Point(1, 0), Point(5, 6)],
|
||||||
# 'Rack_2-0': [Point(1, 8), Point(1, 0)],
|
'Rack_2-0': [Point(1, 8), Point(1, 0)],
|
||||||
# 'Rack_2-1': [Point(0, 10), Point(5, 10)]}
|
'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(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_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_points_from_rack("Rack_2-0"), [Point(1, 0), Point(1, 8)])
|
||||||
|
|
||||||
|
|
||||||
# def test_add_point_interim(self):
|
def test_add_point_interim(self):
|
||||||
# ''' Testet das inzufügen und einsortieren eines Zwischenpunktes zwische nRack-Anfang und Rack-Ende'''
|
''' 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)],
|
res_rack_seg = {'Rack_1-0': [Point(1, 0), Point(5, 6)],
|
||||||
# 'Rack_2-0': [Point(1, 8), Point(1, 0)],
|
'Rack_2-0': [Point(1, 8), Point(1, 0)],
|
||||||
# 'Rack_2-1': [Point(0, 10), Point(5, 10)]}
|
'Rack_2-1': [Point(0, 10), Point(5, 10)]}
|
||||||
|
|
||||||
|
|
||||||
# point2rack = RackIDs(res_rack_seg)
|
point2rack = RackIDs(res_rack_seg)
|
||||||
# point2rack.add_point_to_rack(Point(1,4), "Rack_2-0")
|
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):
|
def test_add_sensor(self):
|
||||||
# ''' Erzeugt Aufpunkt an dem Sensor nähesten Rack und fügt diesen auf Rack ein (sortiert).'''
|
''' 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_segs = {'Rack_1-0': [Point(0, 0), Point(0, 10)],
|
'Rack_2-0': [Point(10, -2), Point(10, 5)],
|
||||||
# 'Rack_2-0': [Point(10, -2), Point(10, 5)],
|
'Rack_2-1': [Point(0, 3), Point(10, 3)]}
|
||||||
# 'Rack_2-1': [Point(0, 3), Point(10, 3)]}
|
|
||||||
|
|
||||||
# sensors = {'Sens_1': Point(1, 1),
|
sensors = {'Sens_1': Point(1, 1),
|
||||||
# 'Sens_2': Point(2, 4),
|
'Sens_2': Point(2, 4),
|
||||||
# 'Sens_3': Point(9, 2)}
|
'Sens_3': Point(9, 2)}
|
||||||
|
|
||||||
|
|
||||||
# an = Anlage()
|
an = Anlage()
|
||||||
# point2rack = an.set_racks(rack_segs)
|
point2rack = an.set_racks(rack_segs)
|
||||||
# an.add_sensors(sensors)
|
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()
|
an.connect_sensors_to_racks()
|
||||||
# plist2 = an.get_points_from_rack("Rack_1-0")
|
plist2 = an.get_points_from_rack("Rack_1-0")
|
||||||
|
|
||||||
# self.assertEqual(plist1, [Point(0, 0), Point(0, 10)])
|
self.assertEqual(plist1, [Point(0, 0), Point(0, 10)])
|
||||||
# self.assertEqual(plist2, [Point(0, 0), Point(0,1), Point(0, 10)])
|
self.assertEqual(plist2, [Point(0, 0), Point(0,1), Point(0, 10)])
|
||||||
|
|
||||||
|
|
||||||
# def test_generate_graph(self):
|
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_segs = {'Rack_1-0': [Point(0, 0), Point(0, 10)],
|
||||||
# 'Rack_2-0': [Point(10, -2), Point(10, 5)],
|
'Rack_2-0': [Point(10, -2), Point(10, 5)],
|
||||||
# 'Rack_2-1': [Point(0, 3), Point(10, 3)]}
|
'Rack_2-1': [Point(0, 3), Point(10, 3)]}
|
||||||
|
|
||||||
# sensors = {'Sens_1': Point(1, 1),
|
sensors = {'Sens_1': Point(1, 1),
|
||||||
# 'Sens_2': Point(2, 4),
|
'Sens_2': Point(2, 4),
|
||||||
# 'Sens_3': Point(9, 2)}
|
'Sens_3': Point(9, 2)}
|
||||||
|
|
||||||
# distributors = {'Dist_1': Point(-1, 9),
|
distributors = {'Dist_1': Point(-1, 9),
|
||||||
# 'Dist_2': Point(11, 0)}
|
'Dist_2': Point(11, 0)}
|
||||||
|
|
||||||
# an = Anlage()
|
an = Anlage()
|
||||||
# an.set_racks(rack_segs)
|
an.set_racks(rack_segs)
|
||||||
|
an.join_racks
|
||||||
|
|
||||||
# G1 = nx.Graph()
|
G1 = nx.Graph()
|
||||||
# pos = an.generate_graph(G1)
|
pos = an.generate_graph(G1)
|
||||||
# nx.draw(G1, pos, with_labels=False, node_size=10, font_size=8)
|
nx.draw(G1, pos, with_labels=False, node_size=10, font_size=8)
|
||||||
# plt.show()
|
plt.show()
|
||||||
|
|
||||||
# an.add_sensors(sensors)
|
an.add_sensors(sensors)
|
||||||
# an.connect_sensors_to_racks()
|
an.connect_sensors_to_racks()
|
||||||
|
|
||||||
# G2 = nx.Graph()
|
G2 = nx.Graph()
|
||||||
# pos = an.generate_graph(G2)
|
pos = an.generate_graph(G2)
|
||||||
|
|
||||||
# edge_colors = [G2[u][v].get('color', 'black') for u, v in G2.edges()]
|
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)
|
nx.draw(G2, pos, with_labels=False, node_size=10, font_size=8, edge_color=edge_colors)
|
||||||
# plt.show()
|
plt.show()
|
||||||
|
|
||||||
# an.add_distributors(distributors)
|
an.add_distributors(distributors)
|
||||||
# an.connect_distributor_to_racks()
|
an.connect_distributor_to_racks()
|
||||||
|
|
||||||
# G3 = nx.Graph()
|
G3 = nx.Graph()
|
||||||
# pos = an.generate_graph(G3)
|
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)
|
nx.draw(G3, pos, with_labels=False, node_size=10, font_size=8, edge_color=edge_colors)
|
||||||
# plt.show()
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
# def test_Wegsuche(self):
|
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_segs = {'Rack_1-0': [Point(0, 0), Point(0, 10)],
|
||||||
# 'Rack_2-0': [Point(10, -2), Point(10, 5)],
|
'Rack_2-0': [Point(10, -2), Point(10, 5)],
|
||||||
# 'Rack_2-1': [Point(0, 3), Point(10, 3)]}
|
'Rack_2-1': [Point(0, 3), Point(10, 3)]}
|
||||||
|
|
||||||
# sensors = {'Sens_1': Point(1, 1),
|
sensors = {'Sens_1': Point(1, 1),
|
||||||
# 'Sens_2': Point(2, 4),
|
'Sens_2': Point(2, 4),
|
||||||
# 'Sens_3': Point(9, 2)}
|
'Sens_3': Point(9, 2)}
|
||||||
|
|
||||||
# distributors = {'Dist_1': Point(-1, 9),
|
distributors = {'Dist_1': Point(-1, 9),
|
||||||
# 'Dist_2': Point(11, 0)}
|
'Dist_2': Point(11, 0)}
|
||||||
|
|
||||||
# mapping = {'Dist_1': ['Sens_1', 'Sens_2'],
|
mapping = {'Dist_1': ['Sens_1', 'Sens_2'],
|
||||||
# 'Dist_2': ['Sens_3']}
|
'Dist_2': ['Sens_3']}
|
||||||
|
|
||||||
# an = Anlage()
|
# Erstelle Anlage
|
||||||
# an.set_racks(rack_segs)
|
an = Anlage()
|
||||||
# an.add_sensors(sensors)
|
# Füge racks aus Daten hinzu
|
||||||
# an.connect_sensors_to_racks()
|
an.set_racks(rack_segs)
|
||||||
# an.add_distributors(distributors)
|
# Verbinde Racks miteinander (ggf. verlängere ungenaue Racks)
|
||||||
# an.connect_distributor_to_racks()
|
an.join_racks()
|
||||||
# an.map_distributors_to_sensors(mapping)
|
# 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()
|
# Ermittle kürzeste Wege von Unterverteilern zu zugehörigen Sensoren
|
||||||
# pos = an.generate_graph(G3)
|
paths = an.create_cable_paths(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()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# paths = an.create_cable_paths(G3)
|
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, "")
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
+80
-60
@@ -7,42 +7,92 @@ import matplotlib.pyplot as plt
|
|||||||
import networkx as nx
|
import networkx as nx
|
||||||
from shapely.geometry import LineString, Point
|
from shapely.geometry import LineString, Point
|
||||||
from shapely.ops import nearest_points
|
from shapely.ops import nearest_points
|
||||||
|
from plant import Anlage
|
||||||
|
|
||||||
# Funktionen
|
# Funktionen
|
||||||
|
def load_json(jsonfilename):
|
||||||
|
with open(jsonfilename, encoding='utf-8') as fh:
|
||||||
|
return json.load(fh)
|
||||||
|
|
||||||
def rack_segmentation(racks):
|
|
||||||
''' Racks werden zu LineString konvertiert. Racks bestehend aus Polylinine werden in einzelne Segmente zerlegt.'''
|
def create_plant(racks:dict, sensors:dict, distributors:dict, mapping:dict):
|
||||||
rack_segments = []
|
|
||||||
for rack_id, nodes in racks.items():
|
# racks = {'Rack_1-0': [Point(0, 0), Point(0, 10)],
|
||||||
# Sortiere Node_1, Node_2, ...
|
# 'Rack_2-0': [Point(10, -2), Point(10, 5)],
|
||||||
sorted_keys = sorted(nodes.keys(), key=lambda k: int(k.split("_")[1]))
|
# 'Rack_2-1': [Point(0, 3), Point(10, 3)]}
|
||||||
coords = [tuple(nodes[k]) for k in sorted_keys]
|
|
||||||
|
|
||||||
for i in range(len(coords) - 1):
|
# sensors = {'Sens_1': Point(1, 1),
|
||||||
p1, p2 = coords[i], coords[i+1]
|
# 'Sens_2': Point(2, 4),
|
||||||
line = LineString([p1, p2])
|
# 'Sens_3': Point(9, 2)}
|
||||||
rack_segments.append((rack_id, i, line))
|
|
||||||
|
|
||||||
return(rack_segments)
|
# distributors = {'Dist_1': Point(-1, 9),
|
||||||
|
# 'Dist_2': Point(11, 0)}
|
||||||
|
|
||||||
|
# mapping = {'Dist_1': ['Sens_1', 'Sens_2'],
|
||||||
|
# 'Dist_2': ['Sens_3']}
|
||||||
|
|
||||||
def rack_endpoints(rack_segments)
|
# "mapping": {
|
||||||
''' Endpunkte der Racks werden in Points konvertiert'''
|
# "UC0101": [
|
||||||
segment_endpoints = []
|
# "BG3241",
|
||||||
for rack_id, idx, line in rack_segments:
|
# "BG3240",
|
||||||
for pt in [line.coords[0], line.coords[1]]:
|
# "MA0062",
|
||||||
segment_endpoints.append((rack_id, idx, Point(pt)))
|
# "FC0062"
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
|
||||||
|
an = Anlage()
|
||||||
|
# Füge racks aus Daten hinzu
|
||||||
|
an.set_racks(racks)
|
||||||
|
# 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
|
||||||
|
G = nx.Graph()
|
||||||
|
# Fülle eben erstellten Graphen mit Daten
|
||||||
|
an.generate_graph(G)
|
||||||
|
|
||||||
|
# Ermittle kürzeste Wege von Unterverteilern zu zugehörigen Sensoren
|
||||||
|
paths = an.create_cable_paths(G)
|
||||||
|
if args.graph:
|
||||||
|
draw_graph(G,an)
|
||||||
|
|
||||||
return(segment_endpoints)
|
def draw_graph(G:nx.Graph, an:Anlage):
|
||||||
|
pos = an.get_node_positions()
|
||||||
def pin_rack_endpoints(rack_segments, segment_endpoints)
|
|
||||||
'''Erstellung eines Dicts, welches unter dem Key "Rack_id - Index" die Endpunkte der Racks speichert. Endpunkte von Racks innerhalb der Toleranz werden an nahegelegenes Rack gepinnt.'''
|
edge_colors = [G[u][v].get('color', 'black') for u, v in G.edges()]
|
||||||
|
|
||||||
|
nx.draw(G, pos, with_labels=False, node_size=10, font_size=8, edge_color=edge_colors)
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
def prepare_data(rawdata:dict):
|
||||||
|
sensors = data["sensors"]
|
||||||
|
subdists = data["distributors"]
|
||||||
|
racks = data["racks"]
|
||||||
|
mapping = data["mapping"]
|
||||||
|
dracks = dict()
|
||||||
|
for rname,lp in racks:
|
||||||
|
if rname not in dracks:
|
||||||
|
dracks[rname] = list()
|
||||||
|
dracks[rname].append(Point(lp))
|
||||||
|
|
||||||
|
return (sensors, subdists, dracks, mapping)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
parser = argparse.ArgumentParser(description='Berechne Wege von Sensoren zu Verteilern über Kabeltrassen')
|
parser = argparse.ArgumentParser(description='Berechne Wege von Sensoren zu Verteilern über Kabeltrassen')
|
||||||
parser.add_argument('-i', '--inputfile', action='store', required=True, default="easy_position.json", help='file with all informations about positions gathered from getpositions', metavar='my_positions.json')
|
parser.add_argument('-f', '--filename', action='store', required=True, default="easy_position.json", help='file with all informations about positions gathered from getpositions', metavar='my_positions.json')
|
||||||
parser.add_argument('-c', '--console', action='store_true', help='Ausgabe auf Konsole')
|
parser.add_argument('-c', '--console', action='store_true', help='Ausgabe auf Konsole')
|
||||||
|
parser.add_argument('-g', '--graph', action='store_true', help='Zeichnet den Graphen der Anlage')
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
@@ -51,50 +101,20 @@ if __name__ == "__main__":
|
|||||||
config_dir = os.environ.get("PROJECT_CFG")
|
config_dir = os.environ.get("PROJECT_CFG")
|
||||||
|
|
||||||
# Pfade zu JSON-Dateien
|
# Pfade zu JSON-Dateien
|
||||||
jsonfilename = args.inputfile
|
jsonfilename = args.filename
|
||||||
sensors_path = os.path.join(work_dir, jsonfilename)
|
sensors_path = os.path.join(work_dir, jsonfilename)
|
||||||
|
|
||||||
# Einlesen
|
# Einlesen
|
||||||
|
rawdata = load_json(sensors_path)
|
||||||
|
|
||||||
|
(racks, sensors, subdists, mapping) = prepare_data(rawdata)
|
||||||
|
|
||||||
data = load_json(sensors_path)
|
|
||||||
sensors = data["sensors"]
|
|
||||||
subdists = data["distributors"]
|
|
||||||
racks = data["racks"]
|
|
||||||
|
|
||||||
|
plant = create_plant(racks, sensors, subdists, mapping)
|
||||||
# 1. Alle Kreuzungspunkte der Racks ermitteln
|
|
||||||
''' Funktion linesweep_circle wird aufgerufen.
|
|
||||||
Eingabe für Funktion: Nummerierte Racks aus getpositions.py. Reine Liste aus Koordinaten [((Anfang), (Ende)), ((Anfang), (Ende)), ... ] wird in Funktion erstellt
|
|
||||||
Racks werden abgelaufen und tatsächliche Schnittpunkte sowie Nahezu-Schnitte erfasst.
|
|
||||||
Ausgabe von Linesweep Circle: Liste von Endpunkten der Racks aus .dxf & Liste von SP von Rack_a mit Rack_b
|
|
||||||
|
|
||||||
|
# Erstelle Anlage
|
||||||
|
|
||||||
|
|
||||||
'''
|
|
||||||
|
|
||||||
# 2. Graph aus Racks erstellen
|
|
||||||
''' Zunächst leeren Graph erstellen.
|
|
||||||
Endpunkte der Racks wie in .dxf als Knoten hinzufügen. Kanten zwischen den Knoten ebenso hinzufügen.
|
|
||||||
Mittels ausgabe von linesweep_cirle: weitere Knoten auf Kanten hinzufügen und graph vollständig verknüpfen
|
|
||||||
|
|
||||||
Frage: Problematisch, wenn Knoten sehr nahe beieinander liegen also teoretischen "Doppelt" sind? -> lieber Endpunkte von Racks, die über linesweep_circle gefunden werden überschreiben?
|
|
||||||
|
|
||||||
Zusätzlich: über shapely und distance funktion sämtliche Distanzen bestimmen und Graph gewichten
|
|
||||||
'''
|
|
||||||
|
|
||||||
# 3. Sensoren mit nächstgelegenen Racks verknüpfen
|
|
||||||
''' Für jeden Sensor: Sensor pos aus json zu Graph hinzufügen
|
|
||||||
Für jeden Sensor: shapely.distance aufrufen und distance zu allen Racks bzw. Edges ermitteln. (if distance(a) > distance(b) -> Circle_methode um Sensor und Schnittpunkt zu Rack_b ermitteln)
|
|
||||||
SP von Sensor mit Rack als Node hinzufügen und Connection zwischen Sensor, Node, Edge herstellen
|
|
||||||
'''
|
|
||||||
|
|
||||||
# 4. Unterverteiler mit nächstegelegenen Racks verknüpfen
|
|
||||||
''' siehe 3.
|
|
||||||
'''
|
|
||||||
|
|
||||||
# 5. Bestimmung des küzesten Wegs
|
|
||||||
''' über Graphen-Toolbox z.B. nx wird für jeden Knoten zu dessen zugehörigen Unterverteilung der kürzeste Weg gefunden.
|
|
||||||
Schreiben der Ergebnisse in eine seperate kabel.json z.B.
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user