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)