165 lines
5.1 KiB
Python
165 lines
5.1 KiB
Python
import argparse
|
||
import ezdxf
|
||
import json
|
||
import os.path
|
||
from dataclasses import dataclass, asdict, fields
|
||
from dacite import from_dict
|
||
from typing import List
|
||
from datetime import datetime
|
||
from openpyxl import Workbook
|
||
import math
|
||
from collections import defaultdict
|
||
|
||
|
||
|
||
|
||
@dataclass
|
||
class Point:
|
||
x: float
|
||
y: float
|
||
|
||
@dataclass
|
||
class Polyline:
|
||
id: str
|
||
coords: List[Point]
|
||
length: float
|
||
|
||
def to_tuple(self):
|
||
ret = list()
|
||
for p in self.coords:
|
||
ret.append( (p.x,p.y) )
|
||
return ret
|
||
|
||
@dataclass
|
||
class Polylines:
|
||
kabel: List[Polyline]
|
||
|
||
|
||
def add_polyline(msp, points:Polyline, dxf_attribs):
|
||
pts = points.to_tuple()
|
||
pline = msp.add_lwpolyline(points=pts, dxfattribs=dxf_attribs)
|
||
pline.rgb = (255, 128, 0)
|
||
|
||
def new_dxf(json_file, out_path, dxf_file=False):
|
||
""" creates a new dxf file with a polyline inside which is created by the given json file
|
||
"""
|
||
print("creating dxf ..")
|
||
anlage = model_from_json(json_file)
|
||
|
||
if dxf_file:
|
||
# bestehende DXF-Datei laden
|
||
doc = ezdxf.readfile(dxf_file)
|
||
else:
|
||
# neue Zeichnung im DXF format of AutoCAD 2010
|
||
doc = ezdxf.new('R2018', setup=True)
|
||
|
||
# 2. Layer mit Zeitstempel erstellen (z. B. "Layer_2025-05-07_14-30")
|
||
timestamp = datetime.now().strftime("Kabel_%Y-%m-%d_%H-%M")
|
||
if timestamp not in doc.layers:
|
||
doc.layers.add(name=timestamp, color=7)
|
||
|
||
# add new entities to the modelspace
|
||
msp = doc.modelspace()
|
||
# # Beispiel für Text und Polyline
|
||
# add_text(msp)
|
||
dxfattribs={"layer": timestamp}
|
||
for pl in anlage.kabel:
|
||
add_polyline(msp, pl, dxfattribs)
|
||
|
||
doc.saveas(out_path)
|
||
print("done")
|
||
|
||
def model_from_json(json_file):
|
||
with open(json_file, encoding='utf-8') as fh:
|
||
data = json.load(fh)
|
||
|
||
anlage = from_dict(
|
||
data_class=Polylines,
|
||
data=data
|
||
)
|
||
return anlage
|
||
|
||
def export_excel(json_file, out_path):
|
||
# Hier für Excel Export
|
||
print("creating excel file ..")
|
||
anlage = model_from_json(json_file)
|
||
write_excel_from_json(anlage, out_path)
|
||
print("done")
|
||
|
||
|
||
def write_excel_from_json(anlage:Polylines, outpath:str):
|
||
wb = Workbook()
|
||
length_summary = defaultdict(int)
|
||
|
||
#Worksheet 1 - Kabellängen
|
||
ws1 = wb.active
|
||
ws1.title = "Kabellängen"
|
||
ws1.append(["Kabel-ID", "Länge aus Json (m)", "Gerundete Länge (m)"])
|
||
|
||
for pl in anlage.kabel:
|
||
length = pl.length /1000 # Umrechnung von mm in m
|
||
rounded_len = math.ceil(length/10)*10
|
||
length_summary[rounded_len] +=1
|
||
ws1.append([pl.id, length, int(rounded_len)])
|
||
|
||
# Worksheet 2 - Zusammengefasste Längen
|
||
ws2 = wb.create_sheet("Längenübersicht")
|
||
ws2.append(["Gerundete Länge (m)", "Anzahl Kabel"])
|
||
|
||
for rlength in sorted(length_summary):
|
||
ws2.append([int(rlength), length_summary[rlength]])
|
||
|
||
wb.save(outpath)
|
||
|
||
|
||
def check_file_in_work(work_dir, filename):
|
||
fexists = True
|
||
if not os.path.exists(filename):
|
||
mypath = os.path.join(work_dir, filename)
|
||
if not os.path.exists(mypath):
|
||
fexists = False
|
||
else:
|
||
mypath = filename
|
||
return (mypath, fexists)
|
||
|
||
|
||
if __name__ == '__main__':
|
||
parser = argparse.ArgumentParser(description='draws a dxf file with the given cable coordinates', prog='drawdxf')
|
||
parser.add_argument('-f', '--filename', action='store', required=True, help='this json file contains all cables and its coordinates which should be drawn. Saved with an unique timestamp', metavar='myfile.json')
|
||
parser.add_argument('-d', '--dxf', action='store', help='this dxf drawing will be copied and the new layer with the cables will be added', metavar='myfile.dxf')
|
||
parser.add_argument('-n', '--new', action='store', help='create a new dxf file with cables in it. Name is basename and a timestamp')
|
||
parser.add_argument('-x', '--excel', action='store', help='create a xlsx file with cables data', metavar='allCables.xls')
|
||
|
||
args = parser.parse_args()
|
||
|
||
work_dir = os.fspath(os.environ.get('PROJECT_WORK'))
|
||
jfile = args.filename
|
||
(json_path, jexists) = check_file_in_work(work_dir, jfile)
|
||
if not jexists:
|
||
print("file %s does not exit", jfile)
|
||
parser.print_help()
|
||
exit()
|
||
|
||
if args.dxf:
|
||
# falls ein neuer Layer hinzu gefügt werden soll
|
||
dxf_file = args.dxf
|
||
(dxf_path, dexists) = check_file_in_work(work_dir, dxf_file)
|
||
if not dexists:
|
||
print("file %s does not exit", dxf_file)
|
||
parser.print_help()
|
||
exit()
|
||
out_path = dxf_path
|
||
res_pos = new_dxf(json_path, out_path, dxf_file=dxf_path)
|
||
else:
|
||
# erzeuge eine neue dxf Datei mit aktuellen Zeitstempel im Namen
|
||
#basename = os.path.splitext(dxf_path)[0]
|
||
#timestamp = datetime.now().strftime(basename+"_%Y%m%d-%H%M%S.dxf")
|
||
#timestamp = datetime.now().strftime("%Y%m%d-%H%M%S.dxf")
|
||
out_path = os.path.join(work_dir, args.new)
|
||
res_pos = new_dxf(json_path, out_path)
|
||
|
||
if args.excel:
|
||
excel_path = os.path.join(work_dir, args.excel)
|
||
export_excel(json_path, excel_path)
|
||
|