1055 lines
41 KiB
Python
1055 lines
41 KiB
Python
import json
|
|
from shapely.geometry import LineString, Point
|
|
from shapely.ops import nearest_points
|
|
import unittest
|
|
from collections import defaultdict
|
|
import bisect
|
|
import networkx as nx
|
|
import matplotlib.pyplot as plt
|
|
from itertools import pairwise, combinations, permutations
|
|
import re
|
|
from shapely.strtree import STRtree
|
|
import shapely
|
|
|
|
class PointSorter:
|
|
def __init__(self):
|
|
self._points_by_x = [] # [(x, y)]
|
|
self._points_by_y = [] # [(y, x)]
|
|
|
|
def add_point(self, x, y):
|
|
bisect.insort(self._points_by_x, (x, y))
|
|
bisect.insort(self._points_by_y, (y, x))
|
|
|
|
def add_points(self, points:list[Point]):
|
|
for p in points:
|
|
self.add_point(p.x, p.y)
|
|
|
|
def query_box(self, x1, x2, y1, y2):
|
|
# Suche nach x-Grenzen
|
|
ix1 = bisect.bisect_left(self._points_by_x, (x1, -float('inf')))
|
|
ix2 = bisect.bisect_right(self._points_by_x, (x2, float('inf')))
|
|
candidates = self._points_by_x[ix1:ix2]
|
|
|
|
# Filtere nach y
|
|
ret = list()
|
|
for (x,y) in candidates:
|
|
if y1 <= y <= y2:
|
|
ret.append(Point(x,y))
|
|
return ret
|
|
|
|
def get_sorted_by_x(self):
|
|
# Sortiere nach x
|
|
ret = list()
|
|
for (x,y) in self._points_by_x:
|
|
ret.append(Point(x,y))
|
|
return ret
|
|
|
|
def get_sorted_by_y(self):
|
|
# Sortiere nach y
|
|
ret = list()
|
|
for (y,x) in self._points_by_y:
|
|
ret.append(Point(x,y))
|
|
return ret
|
|
|
|
def to_json(d, pretty: bool = True) -> str:
|
|
return json.dumps(d, indent=2 if pretty else None, default=str) #ensure_ascii false für darstellung von "ue"
|
|
|
|
class NodeIDs():
|
|
def __init__(self, points=[]):
|
|
self._counter = 0
|
|
self._cord2id = dict()
|
|
self._id2cord = dict()
|
|
self.add_points(points)
|
|
|
|
def add_point(self, point:Point):
|
|
if self.point_exists(point):
|
|
return True
|
|
self._counter += 1
|
|
self._cord2id[f"{point.x} {point.y}"] = self._counter
|
|
self._id2cord[self._counter] = point
|
|
|
|
def point_exists(self, point:Point) -> bool:
|
|
return f"{point.x} {point.y}" in self._cord2id
|
|
|
|
def nid_exists(self, nid:int) -> bool:
|
|
return nid in self._id2cord
|
|
|
|
|
|
def add_points(self, points:list[Point]):
|
|
for p in points:
|
|
self.add_point(p)
|
|
|
|
def get_id(self, point:Point) -> int:
|
|
if f"{point.x} {point.y}" not in self._cord2id:
|
|
raise Exception(f"Punkt nicht vorhanden!, {point.x},{point.y}")
|
|
return self._cord2id[f"{point.x} {point.y}"]
|
|
|
|
def get_point(self, nid:int) -> Point:
|
|
if nid not in self._id2cord:
|
|
raise Exception(f"NodeID nicht vorhanden! {nid}")
|
|
return self._id2cord[nid]
|
|
|
|
def get_ids(self, points:list[Point]) -> list[int]:
|
|
ret = list()
|
|
for p in points:
|
|
nid = self.get_id(p)
|
|
ret.append(nid)
|
|
return ret
|
|
|
|
def size_of(self):
|
|
return len(self._cord2id.keys())
|
|
|
|
|
|
def get_points(self, nids:list[int]) -> list[Point]:
|
|
ret = list()
|
|
for n in nids:
|
|
c = self.get_point(n)
|
|
ret.append(c)
|
|
return ret
|
|
|
|
def show(self):
|
|
return self._id2cord
|
|
class RackIDs():
|
|
def __init__(self, tol_snap = 200):
|
|
self._point2rack = dict()
|
|
self._rack2begend = dict()
|
|
# Toleranzen zur Rack anbindung aneinander (Rack Snap)
|
|
self._tol_snap = tol_snap
|
|
|
|
def add_rack(self, beg:Point, end:Point, name:str): #Hier wird Rack nur mit Anfang und Ende hinzugefügt -> wie macht man Zwischenpunkte?
|
|
if beg in self._point2rack:
|
|
self._point2rack[beg].append(name)
|
|
else:
|
|
self._point2rack[beg] = [name]
|
|
if end in self._point2rack:
|
|
self._point2rack[end].append(name)
|
|
else:
|
|
self._point2rack[end] = [name]
|
|
|
|
self._rack2begend[name] = (beg, end) # Anfangs und Endpunkte zu Rack Namen merken
|
|
|
|
def add_racks(self, racks:dict):
|
|
for name,v in racks.items():
|
|
if len(v) == 2:
|
|
self.add_rack(v[0], v[1], name)
|
|
else:
|
|
counter = 0
|
|
for start, end in pairwise(v):
|
|
counter +=1
|
|
self.add_rack(start, end, f"{name}-{counter}")
|
|
|
|
def get_racks_borders(self) -> dict:
|
|
''' Gibt Rack nur mit Anfangs und Endpunkt zurück.
|
|
{Rack_1_0: "Point(0, 0), Point(0,15)", ... }
|
|
'''
|
|
return self._rack2begend
|
|
|
|
def get_racks_from_all_points(self) -> dict:
|
|
''' Gibt zu einem Punkt, diejenigen Racks zurück, auf denen der Punkt liegt.
|
|
{Point(0, 0): ["Rack_1-0", "Rack_2-0", ...]}
|
|
'''
|
|
return self._point2rack
|
|
|
|
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)
|
|
else:
|
|
self._point2rack[point] = [name]
|
|
|
|
def get_racks_from_point(self, point:Point) -> list[str]:
|
|
return self._point2rack[point]
|
|
|
|
def get_points_from_rack(self, name:str) -> list[Point]:
|
|
''' Gibt zu Namen von Rack zugehörige Punkte aus und sortiert Punkte'''
|
|
ret = list()
|
|
pin = PointSorter()
|
|
for p, l_racks in self._point2rack.items():
|
|
if name in l_racks:
|
|
ret.append(p)
|
|
pin.add_points(ret)
|
|
ret_sorted = list()
|
|
#(pa, pe) = self._rack2begend[name]
|
|
if self.rack_is_horizontal(name):
|
|
ret_sorted = pin.get_sorted_by_x()
|
|
else:
|
|
ret_sorted = pin.get_sorted_by_y()
|
|
return ret_sorted
|
|
|
|
def join_racks(self):
|
|
allracks = list()
|
|
rnames = dict()
|
|
for rname, lpoints in self._rack2begend.items():
|
|
ls = LineString(lpoints)
|
|
allracks.append(ls)
|
|
rnames[ls] = rname
|
|
|
|
for (l1, l2) in combinations(allracks,2):
|
|
if l1.intersects(l2):
|
|
inter = l1.intersection(l2)
|
|
if inter.geom_type == "Point":
|
|
self.add_point_to_rack(inter, rnames[l1])
|
|
self.add_point_to_rack(inter, rnames[l2])
|
|
|
|
for (l1, l2) in permutations(allracks,2):
|
|
first = Point(l2.coords[0])
|
|
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])
|
|
# Füge zusätzliches Rack als Verbindung zwischen Endpunkt und snap_point ein
|
|
connrackname = f"c-{rnames[l2]}"
|
|
self.add_rack(first, snap_point, connrackname)
|
|
if l1.distance(last) <= self._tol_snap:
|
|
snap_point = l1.interpolate(l1.project(last))
|
|
self.add_point_to_rack(snap_point, rnames[l1])
|
|
# Füge zusätzliches Rack als Verbindung zwischen Endpunkt und snap_point ein
|
|
connrackname = f"c-{rnames[l2]}"
|
|
self.add_rack(last, snap_point, connrackname)
|
|
|
|
def rack_is_horizontal(self, name):
|
|
[pa, pe] = self._rack2begend[name]
|
|
if pa.y == pe.y:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
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.
|
|
|
|
Parameters
|
|
----------
|
|
|
|
Returns
|
|
-------
|
|
|
|
Examples
|
|
--------
|
|
>>> # 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=1000, tol_connect_step=50):
|
|
# Container für alle Racks
|
|
self._racks = RackIDs(tol_snap=tol_snap)
|
|
# zuordnung zwischen KnotenID und Punkt
|
|
self._nodeids = NodeIDs()
|
|
# Container für alle Sensoren
|
|
self._sensors = dict()
|
|
self._sensor_onpoints = dict()
|
|
# Container für alle Unterverteiler
|
|
self._distributors = dict()
|
|
self._distributors_onpoints = dict()
|
|
#Container für alle Wege
|
|
self._sensor2dist = dict()
|
|
# Toleranzen zur Rack anbindung aneinander (Rack Snap)
|
|
self._tol_snap = tol_snap
|
|
self._snap_step = snap_step
|
|
# Toleranzen zur Anbindung von Sensoren / Verteilern zu Racks
|
|
self._tol_connect = tol_connect
|
|
self._connect_step = tol_connect_step
|
|
# Infos zum zeichnen des Graphen
|
|
self._node_positions = dict()
|
|
|
|
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))
|
|
return list(set(ret))
|
|
|
|
def get_rack_names(self) -> list:
|
|
return self._racks.get_rack_names()
|
|
|
|
def get_points_from_rack(self, rname) -> list:
|
|
''' Gibt zu Namen von Rack zugehörige Punkte aus und sortiert Punkte'''
|
|
return self._racks.get_points_from_rack(rname)
|
|
|
|
def get_points_from_sensors(self):
|
|
'''gibt die Aufpunkte aller Sensoren auf den Racks zurück'''
|
|
return self._sensors.values()
|
|
|
|
def get_distributor_onpoints(self):
|
|
'''gibt die Aufpunkte aller Unterverteiler auf den Racks zurück'''
|
|
return self._distributors_onpoints.values()
|
|
|
|
def get_sensor_onpoints(self):
|
|
'''gibt die Aufpunkte aller Sensoren auf den Racks zurück'''
|
|
return self._sensor_onpoints.values()
|
|
|
|
def add_sensor(self, sname: str, pos:Point):
|
|
self._sensors[sname] = pos
|
|
|
|
def add_sensors(self, sensors:dict):
|
|
for sname,pos in sensors.items():
|
|
self.add_sensor(sname, pos)
|
|
|
|
def get_sensor_point(self, sname:str) -> Point:
|
|
return self._sensors[sname]
|
|
|
|
def connect_sensors_to_racks(self) -> list:
|
|
'''verbindet die Sensoren mit den Racks.
|
|
die Rückgabe enthält ein Tuple, welche Sensoren keinem Rack zugeordnet werden konnten
|
|
'''
|
|
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
|
|
|
|
def add_distributors(self, distributors:dict):
|
|
for dname,pos in distributors.items():
|
|
self.add_distributor(dname, pos)
|
|
|
|
def get_distributor_point(self, dname:str) -> Point:
|
|
return self._distributors[dname]
|
|
|
|
def connect_distributor_to_racks(self) -> list:
|
|
'''verbindet die Unterverteiler mit den Racks
|
|
die Rückage enthält ein Tuple, welche Unterverteiler keinem Rack zugeordnet werden konnten
|
|
'''
|
|
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()
|
|
|
|
def _build_rack_strtree(self):
|
|
self._rack_lines = []
|
|
self._rack_map = {}
|
|
for r_name, pts in self._racks.get_racks_borders().items():
|
|
line = LineString([pts[0], pts[-1]])
|
|
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 connect_equipment_to_racks(self, equipment: dict, onpoints: dict) -> list:
|
|
'''Verbindet Peripherie (Sensoren / Aktoren/ Unterverteiler) mit dem nächsten Rack.
|
|
Eingabe: Dict des Equipments (Sensoren o. Dists), Dict der Aufpunkte von Sensoren o. Dists
|
|
Rückgabe: Liste der nicht zugeordneten Geräte
|
|
'''
|
|
errors = []
|
|
for name, pos in equipment.items():
|
|
onpoint, rackname = self.find_nearest_rack_from_point_tree(self._tol_connect, pos)
|
|
if onpoint == None or rackname == None:
|
|
errors.append((name, pos))
|
|
continue
|
|
onpoints[name] = (onpoint, rackname)
|
|
self.add_point_to_rack(onpoint, rackname)
|
|
|
|
virtual_rackname = f"v-{name}-{rackname}"
|
|
self._racks.add_rack(pos, onpoint, virtual_rackname)
|
|
|
|
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=True)
|
|
# !!! 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
|
|
'''
|
|
verbindungen = []
|
|
endpoint_pinned = []
|
|
|
|
# === A: Echte Schnittpunkte zwischen Linien finden ===
|
|
''' Alle Segmente mit allen überprüfen, um echte SP zu finden'''
|
|
for i, (rack_id1, idx1, line1) in enumerate(rack_segments):
|
|
#print(f"\n=== Prüfe {rack_id1}_{idx1} auf echte Schnittpunkte")
|
|
for j, (rack_id2, idx2, line2) in enumerate(rack_segments):
|
|
if i >= j:
|
|
continue # keine Duplikate / sich selbst
|
|
|
|
if line1.intersects(line2):
|
|
inter = line1.intersection(line2)
|
|
if inter.geom_type == "Point":
|
|
#print(f"✅ Exakter Schnittpunkt {inter} zwischen {rack_id1}_{idx1} und {rack_id2}_{idx2}")
|
|
verbindungen.append((rack_id1, idx1, rack_id2, idx2, inter))
|
|
|
|
# === B: Näherungsweise Verbindung durch Toleranz-Kreise ===
|
|
''' Entlanglaufen der Racks und Scan nach Endpunkten im Toleranzbereich'''
|
|
for rack_id, idx, line in rack_segments:
|
|
#print(f"\n=== Prüfe {rack_id}_{idx1} auf Punkte im Toleranzbereich")
|
|
for other_rack_id, other_idx, pt in segment_endpoints:
|
|
if rack_id == other_rack_id:
|
|
continue # ignoriere eigene Endpunkte
|
|
|
|
# Exakte Schnittpunkte ignorieren
|
|
if line.intersects(pt):
|
|
continue
|
|
|
|
dist = line.distance(pt)
|
|
if dist < tol:
|
|
self.increase_circle(tol, tol_step, line, pt, rack_id, idx, other_rack_id, other_idx, verbindungen, endpoint_pinned)
|
|
#print(f"🔍 Punkt {pt} liegt {dist:.2f} von Linie {rack_id}_{idx} entfernt"
|
|
|
|
# === Endpunkte aktualisieren ===
|
|
# Dict erstellen, dass mit dem Key "Rack_id - index" dahinter die Koordinaten von Anfang und Endpunkt speichert
|
|
rack_segments_pinned = dict()
|
|
|
|
for rack_id, idx, linestring in rack_segments:
|
|
key = f"{rack_id}-{idx}"
|
|
rack_segments_pinned[key] = [Point(linestring.coords[0]), Point(linestring.coords[1])] #Alle Racks in ihrer eingelesenen Form zum Dict hinzufügen
|
|
|
|
for rack_id, idx, old_pt, new_pt, taget_rack in endpoint_pinned: #Durch verschobene Endpunkte laufen...
|
|
key = f"{rack_id}-{idx}"
|
|
coords = rack_segments_pinned.get(key)
|
|
|
|
if coords: #...und bei Übereinstimmung von Start oder Endkoordinate die ursprüngliche (eingelesene) mit der gepinnten überschreiben
|
|
# Vergleich mit Startpunkt
|
|
if Point(coords[0]).equals(old_pt):
|
|
coords[0] = Point(new_pt.x, new_pt.y) #.x bzw .y übergibt x bzw y Koordinate von Objekt POINT
|
|
# Vergleich mit Endpunkt
|
|
elif Point(coords[1]).equals(old_pt):
|
|
coords[1] = Point(new_pt.x, new_pt.y)
|
|
|
|
rack_segments_pinned[key] = coords # aktualisieren
|
|
|
|
#Dict erstellen, dass alle Punkte die an einem Rack anschließen speichert
|
|
d_rack_conn_points = dict()
|
|
|
|
for conn_to_rack, conn_to_idx, conn_from_rack, conn_from_idx, conn_point in verbindungen:
|
|
key = f"{conn_to_rack}-{conn_to_idx} + {conn_from_rack}-{conn_from_idx}"
|
|
d_rack_conn_points[key] = [conn_point]
|
|
|
|
|
|
d_rack_to_points = dict() #neues Dict für Rack_id - Idx: Alle Punkte auf dem Rack
|
|
|
|
for key, coords in rack_segments_pinned.items(): # Erst Anfangs und Endpunkt aus d_racks_segments holen
|
|
# coords = [start_point end_point]
|
|
d_rack_to_points[key] = coords.copy()
|
|
|
|
for key, point in d_rack_conn_points.items(): # Dann aus d_rack_conn_points alle verbindungspunkte holen und dazu speichern
|
|
to_rack = key.split(" + ")[0]
|
|
if to_rack in d_rack_to_points:
|
|
d_rack_to_points[to_rack].extend(point)
|
|
|
|
for key in d_rack_to_points:
|
|
unique_points = list({(pt.x, pt.y): pt for pt in d_rack_to_points[key]}.values())
|
|
d_rack_to_points[key] = unique_points
|
|
|
|
return rack_segments_pinned
|
|
|
|
def get_node_positions(self):
|
|
''' Daten werden durch generate_graph() befüllt'''
|
|
return self._node_positions
|
|
|
|
def is_sensor(self, p:Point) -> bool:
|
|
if p in self._sensors.values():
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def is_distributor(self, p:Point) -> bool:
|
|
if p in self._distributors.values():
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def generate_graph(self, G:nx.Graph):
|
|
points = list()
|
|
points.extend(self.get_all_rack_points())
|
|
points.extend(self.get_points_from_sensors())
|
|
self._nodeids.add_points(points)
|
|
|
|
for p in points:
|
|
if self.is_distributor(p):
|
|
shape = "s"
|
|
elif self.is_sensor(p):
|
|
shape = "^"
|
|
else:
|
|
shape = "o"
|
|
nid = self._nodeids.get_id(p)
|
|
G.add_node(nid, shape=shape) # Knoten für Startpunkt
|
|
|
|
|
|
for node in G.nodes:
|
|
point = self._nodeids.get_point(node)
|
|
self._node_positions[node] = (point.x, point.y)
|
|
|
|
for rname in self.get_rack_names():
|
|
plist = self.get_points_from_rack(rname)
|
|
for start, end in pairwise(plist):
|
|
nid_start = self._nodeids.get_id(start)
|
|
nid_end = self._nodeids.get_id(end)
|
|
|
|
if re.match("v-.*", rname):
|
|
color = "red"
|
|
elif re.match("d-.*", rname):
|
|
color = "blue"
|
|
else:
|
|
color = "black"
|
|
G.add_edge(nid_start, nid_end, color=color, weight=start.distance(end))
|
|
return self._node_positions
|
|
|
|
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.
|
|
Dist_1: ["Sens_3, Sens_5, ...]
|
|
'''
|
|
for sname in snamen:
|
|
self._sensor2dist[sname] = dname
|
|
|
|
def map_distributors_to_sensors(self, d2sensors:dict[str, list[str]]):
|
|
''' Gibt zu einem dict mit Distributors die jeweils zugehörigen Sensoren aus.
|
|
{Dist_1: ["Sens_3, Sens_5, ...]
|
|
Dist_2: ["Sens_1, Sens_8, ...]}
|
|
'''
|
|
for dname, listofsensors in d2sensors.items():
|
|
self.map_distributor_to_sensors(dname, listofsensors)
|
|
|
|
def create_cable_path(self, G, sname, dname) -> tuple:
|
|
quelle = self._nodeids.get_id(self.get_distributor_point(dname))
|
|
ziel = self._nodeids.get_id(self.get_sensor_point(sname))
|
|
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')
|
|
|
|
return pfad_nodes, pfad_length
|
|
|
|
def create_cable_paths(self, G) -> dict:
|
|
pfade = dict()
|
|
pfade["kabel"] = list()
|
|
for sname, dname in self._sensor2dist.items():
|
|
pfad_nodes, pfad_length = self.create_cable_path(G, sname, dname)
|
|
pfad_coords = self._nodeids.get_points(pfad_nodes)
|
|
tuplecoords = [(p.x, p.y) for p in pfad_coords]
|
|
ld = dict()
|
|
ld['id'] = f"{dname}-{sname}"
|
|
ld["coords"]= [{"x":round(p.x,1), "y":round(p.y,1)} for p in pfad_coords]
|
|
ld["length"]= round(pfad_length,1)
|
|
ld["nodes"]=pfad_nodes
|
|
pfade["kabel"].append(ld)
|
|
|
|
return pfade
|
|
|
|
def show_node_ids(self):
|
|
return self._nodeids.show()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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))
|
|
|
|
# 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)]
|
|
# }
|
|
|
|
# # 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 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)])
|
|
|
|
|
|
# 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()
|
|
|
|
# #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'''
|
|
|
|
# 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)
|
|
|
|
# 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)]}
|
|
|
|
|
|
# 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)])
|
|
|
|
|
|
# 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)]}
|
|
|
|
# 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)
|
|
|
|
# plist1 = 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)])
|
|
|
|
|
|
# def test_add_equipment_w_tree(self):
|
|
|
|
# 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)}
|
|
|
|
# distributors = {'Dist_1': Point(-1, 9),
|
|
# 'Dist_2': Point(11, 0)}
|
|
|
|
# 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)
|
|
|
|
# plist1 = an.get_points_from_rack("Rack_1")
|
|
# plist2 = an.get_points_from_rack("Rack_2")
|
|
|
|
|
|
# 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_add_equipment_w_tree_batch(self):
|
|
|
|
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)}
|
|
|
|
distributors = {'Dist_1': Point(-1, 9),
|
|
'Dist_2': Point(11, 0)}
|
|
|
|
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)
|
|
|
|
plist1 = an.get_points_from_rack("Rack_1")
|
|
plist2 = an.get_points_from_rack("Rack_2")
|
|
|
|
G1 = nx.Graph()
|
|
pos = an.generate_graph(G1)
|
|
nx.draw(G1, pos, with_labels=False, node_size=10, font_size=8)
|
|
plt.show()
|
|
|
|
|
|
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_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)]}
|
|
|
|
# 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']}
|
|
|
|
# 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-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)}
|
|
|
|
# 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'''
|
|
|
|
# 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']}
|
|
|
|
# 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"]}
|
|
|
|
|
|
# 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__':
|
|
print(shapely.__file__)
|
|
print(shapely.__version__)
|
|
unittest.main() |