Files
kabellaengen/lib/getpositions.py
T

207 lines
7.6 KiB
Python

import argparse
import configparser
import ezdxf.document
from ezdxf.math import Matrix44
import os
import sys
import math
import json
import re
"""
Dieses Programm:
- liest die dxf Datei und holt sich von den Layern der dxf Datei die Positionen
+ der Motoren, Sensoren und Aktoren
+ der Unterverteiler
+ der Polylinien der Kabelpritschen
- erzeugt daraus eine .json Datei im Work Ordner
"""
def write_results(jsnResults, outdir, filename):
""" write results to a json file
"""
print("writing results to a json file ...")
outfile = os.path.join(outdir, filename)
with open(outfile, 'w', encoding='utf-8') as fh:
fh.write(jsnResults)
print("done")
def merge_two_dicts(x, y):
z = x.copy()
z.update(y)
return z
def get_input_positions(msp: ezdxf.document.Drawing.modelspace):
"""hole alle Positionen der Eingänge
"""
allIds = dict()
SpecialKeys = ["MB", # Separator
"MA", # Motor
"BG", # Stausensor
"FC" # Motorschutzschalter
]
# Über alle Blockreferenzen (INSERT) im Modelspace laufen
for insert in msp.query('INSERT'):
if len(insert.attribs) == 0:
continue # Überspringe Blöcke ohne Attribute
id = ""
ld = dict()
for attrib in insert.attribs:
if len(insert.attribs) == 0:
continue # Überspringe Blöcke ohne Attribute
#print(f"Attribut Name: {attrib.dxf.tag}, Wert: {attrib.dxf.text}")
ld[attrib.dxf.tag] = attrib.dxf.text
if attrib.dxf.tag == "IO":
id = attrib.dxf.text
# print(f"-- coord io {id}--: {attrib.dxf.insert}") # position des Blocks
if attrib.dxf.tag == "B":
for spec in SpecialKeys:
if spec in attrib.dxf.text:
id = attrib.dxf.text
#print(f"-- coord {attrib.dxf.text} --: {attrib.dxf.insert}")
if attrib.dxf.tag == "REALE_POSITION" and attrib.dxf.text == "x":
#print(f"-- coord real --: {attrib.dxf.insert}")
pos = attrib.dxf.insert #Position Ecke unten links von "x"-Marker auslesen
# Hoehe und Breite von "x" addieren, um Mittelpunkt zu finden
breite_marker = config.getfloat("Sensor_Marker", "Breite")
hoehe_marker = config.getfloat("Sensor_Marker", "Hoehe")
pos_midx = pos.x + breite_marker*0.5
pos_midy = pos.y + hoehe_marker*0.5
ld["pos"] = (pos_midx, pos_midy)
# Nur wenn eine ID vorhanden ist, und eine gültige Position existiert
if id and "pos" in ld and isinstance(ld["pos"], tuple) and len(ld["pos"]) == 2:
if id in allIds:
allIds[id] = merge_two_dicts(allIds[id], ld) #Kombiniert alle infos aus dxf und "pos"
else:
allIds[id] = ld
return allIds
def get_subdistributor_positions(msp):
"""hole alle Positionen der Unterverteiler
"""
# # Über alle Texte laufen
# for text in msp.query('MTEXT'):
# print(f"Inhalt: {text.dxf.text}")
# print(f"Layer: {text.dxf.layer}")
# print(f"Einfügepunkt: {text.dxf.insert}")
# print(f"Breite: {text.dxf.width}")
# # print("Farbe:", text.dxf.color) # Achtung: 256 = "ByLayer"
# # print("Höhe (height):", text.dxf.height)
# # print("Rotation (degrees):", text.dxf.rotation)
# # print("Breitenfaktor (width factor):", text.dxf.width)
# # print("Style (Schriftart):", text.dxf.style)
# # print("Handle:", text.dxf.handle)
# print("---")
ret = dict()
# Alle Texte auf Layer "xy"
for text in msp.query('MTEXT[layer=="Busverteiler-Kennzeichnung"]'):
print(f"Text auf Layer 'Busverteiler-Kennzeichnung': {text.dxf.text}")
match = re.search(r"UC\w+", text.dxf.text)
if match:
nameUC = match.group(0)
ret[nameUC] = text.dxf.insert
return ret
# helper function
def print_line(e):
print("LINE on layer: %s\n" % e.dxf.layer)
print("points: %s\n" % repr(e.dxf))
def print_polyline(e):
print("POLYLINE on layer: %s\n" % e.dxf.layer)
#print("points: %s\n" % repr(e.dxf))
#print("y point: %s\n" % e.dxf.y)
for x, y, start_width, end_width, bulge in e.get_points(): # Gibt Tuple (x, y, start_width, end_width, bulge)
print(f" Punkt: ({x}, {y}), Startbreite: ({start_width}, Endbreite: {end_width})")
if e.is_closed:
print("Diese Polyline ist geschlossen.")
def get_rack_positions(msp):
"""hole alle Positionen aller Kabelpritschen
"""
ret = list()
for e in msp.query('LWPOLYLINE[layer=="PRITSCHE_200-60"]'):
#print_polyline(e)
poly = list()
for x, y, start_width, end_width, bulge in e.get_points(): # Gibt Tuple (x, y, start_width, end_width, bulge)
point = (x,y)
poly.append(point)
ret.append(poly)
# iterate over all entities in modelspace
# for e in msp:
# if e.dxftype() == "LINE":
# print_line(e)
# if e.dxftype() == "LWPOLYLINE":
# print_polyline(e)
return ret
def to_json(d, pretty: bool = True) -> str:
return json.dumps(d, indent=2 if pretty else None, ensure_ascii=False, default=str) #ensure_ascii false für darstellung von "ue"
def get_dxf_file(filepath):
"""hole das dxf file
"""
try:
doc = ezdxf.readfile(filepath)
except IOError:
print(f"Not a DXF file or a generic I/O error.")
sys.exit(1)
except ezdxf.DXFStructureError:
print(f"Invalid or corrupted DXF file.")
sys.exit(2)
return doc
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='fetches the x/y positions from a dxf file', prog='getpositions')
parser.add_argument('-f', '--filename', action='store', required=True, default="ST_6300_Steuerungstestlayout1_neueBloecke.dwg", help='which file should be fetched', metavar='myfile.dwg')
parser.add_argument('-s', '--sensors', action='store_true', help='fetch all position of sensors, motors, actors')
parser.add_argument('-d', '--dists', action='store_true', help='fetch all positions of all subdistributors')
parser.add_argument('-r', '--rack', action='store_true', help='fetch all positions of all cable racks')
parser.add_argument('-c', '--console', action='store_true', help='print results to output')
args = parser.parse_args()
out_dir = os.environ.get('PROJECT_DATA')
work_dir = os.environ.get('PROJECT_WORK')
config_dir = os.environ.get("PROJECT_CFG")
filename = args.filename
doc = get_dxf_file(os.path.join(work_dir, filename)) # type: ignore
msp = doc.modelspace()
res_pos = dict()
res_dist = dict()
res_rac = dict()
if args.sensors or args.dists or args.rack:
config = configparser.ConfigParser(allow_no_value=True)
config.read(os.path.join(config_dir, "getpositions.cfg"))
if args.sensors:
res_pos = get_input_positions(msp)
if args.console:
print(to_json(res_pos))
write_results(to_json(res_pos), work_dir, "sensors.json")
if args.dists:
res_dist = get_subdistributor_positions(msp)
if args.console:
print(to_json(res_dist))
write_results(to_json(res_dist), work_dir, "subdistributors.json")
if args.rack:
res_rac = get_rack_positions(msp)
if args.console:
print(to_json(res_rac))
write_results(to_json(res_rac), work_dir, "racks.json")
else:
parser.print_help()