Koordinaten der Unterverteiler, Sensoren und Kabelpritsche aus .dxf Datei festgestellt. Bisher Ausgabe nur in Konsole.
This commit is contained in:
Vendored
+18
-3
@@ -21,7 +21,22 @@
|
||||
"justMyCode": true
|
||||
},
|
||||
{
|
||||
"name": "use filename and default",
|
||||
"name": "use easy.dwg",
|
||||
"type": "debugpy",
|
||||
"request": "launch",
|
||||
"program": "${file}",
|
||||
"console": "integratedTerminal",
|
||||
"justMyCode": true,
|
||||
"args": [
|
||||
"--filename",
|
||||
"easy.dxf",
|
||||
"-s",
|
||||
"-d",
|
||||
"-r"
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "use Steuerungstestlayout",
|
||||
"type": "debugpy",
|
||||
"request": "launch",
|
||||
"program": "${file}",
|
||||
@@ -30,8 +45,8 @@
|
||||
"args": [
|
||||
"--filename",
|
||||
"ST_6300_Steuerungstestlayout1_neueBloecke.dxf",
|
||||
"-i",
|
||||
"-o",
|
||||
"-s",
|
||||
"-d",
|
||||
"-r"
|
||||
],
|
||||
}
|
||||
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"python.languageServer": "Pylance",
|
||||
"cSpell.words": [
|
||||
"ezdxf"
|
||||
]
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
@echo off
|
||||
CALL manage_interpreter.bat activate_interpreter
|
||||
python %PROJECT_LIB%\getpositions.py
|
||||
python %PROJECT_LIB%\getpositions.py %*
|
||||
CALL manage_interpreter.bat deactivate_interpreter
|
||||
|
||||
+106
-56
@@ -1,9 +1,14 @@
|
||||
import argparse
|
||||
import configparser
|
||||
import ezdxf
|
||||
#import ezdxf
|
||||
import ezdxf.document
|
||||
from ezdxf.math import Matrix44
|
||||
import os
|
||||
import sys
|
||||
import math
|
||||
import json
|
||||
import re
|
||||
|
||||
|
||||
"""
|
||||
Dieses Programm:
|
||||
@@ -49,53 +54,71 @@ def get_world_position_of_attribute(insert, attrib):
|
||||
# Transformation aufbauen: Skalierung -> Rotation -> Translation
|
||||
m = (
|
||||
Matrix44.scale(xscale, yscale, 1) @
|
||||
Matrix44.z_rotate(rotation_deg * 3.141592653589793 / 180) @
|
||||
Matrix44.z_rotate(rotation_deg * math.pi / 180) @
|
||||
Matrix44.translate(block_pos.x, block_pos.y, block_pos.z)
|
||||
)
|
||||
|
||||
# Lokale Position transformieren
|
||||
return m.transform(local_pos)
|
||||
|
||||
def get_input_positions(doc):
|
||||
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
|
||||
"""
|
||||
msp = doc.modelspace()
|
||||
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:
|
||||
# Position des Blocks ist attrib.dxf.insert
|
||||
print(f"Attribut Name: {attrib.dxf.tag}, Wert: {attrib.dxf.text}")
|
||||
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 --: {attrib.dxf.insert}")
|
||||
if attrib.dxf.tag == "B" and "MB" in attrib.dxf.text:
|
||||
print(f"-- coord --: {attrib.dxf.insert}")
|
||||
if attrib.dxf.tag == "B" and "BG" in attrib.dxf.text:
|
||||
print(f"-- coord --: {attrib.dxf.insert}")
|
||||
# attrib.layer
|
||||
#print(f"-- coord real --: {attrib.dxf.insert}")
|
||||
world_pos = get_world_position_of_attribute(insert, attrib)
|
||||
#print(f"-- world --: {world_pos}")
|
||||
ld["block_pos"] = attrib.dxf.insert
|
||||
ld["world_pos"] = world_pos
|
||||
|
||||
# # Attribute abrufen (als Liste von ATTRIB-Objekten)
|
||||
# attribs = {attrib.dxf.tag: attrib.dxf.text for attrib in insert.attribs}
|
||||
|
||||
# # Hier z.B. filtern: Blocke, die ein "NAME"-Attribut haben
|
||||
# if "NAME" in attribs:
|
||||
# print(f"Blockname: {insert.dxf.name}")
|
||||
# print(f"NAME-Attribut: {attribs['NAME']}")
|
||||
|
||||
# # Zugriff auf weitere Attribute
|
||||
# # z.B. "ID", "TYP" usw.
|
||||
# if "ID" in attribs:
|
||||
# print(f"ID: {attribs['ID']}")
|
||||
if not id == "":
|
||||
if not id in allIds:
|
||||
allIds[id] = ld
|
||||
else:
|
||||
allIds[id] = merge_two_dicts(allIds[id], ld)
|
||||
return allIds
|
||||
|
||||
|
||||
# msp = doc.modelspace()
|
||||
def get_subdistributor_positions(msp):
|
||||
"""hole alle Positionen der Unterverteiler
|
||||
"""
|
||||
# # Über alle Texte laufen
|
||||
# for text in msp.query('TEXT'):
|
||||
# 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)
|
||||
@@ -104,37 +127,53 @@ def get_input_positions(doc):
|
||||
# # print("Handle:", text.dxf.handle)
|
||||
# print("---")
|
||||
|
||||
|
||||
|
||||
def get_output_positions(doc):
|
||||
"""hole alle Positionen der Ausgänge
|
||||
"""
|
||||
pass
|
||||
ret = dict()
|
||||
# Alle Texte auf Layer "xy"
|
||||
for text in msp.query('TEXT[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_entity(e):
|
||||
def print_line(e):
|
||||
print("LINE on layer: %s\n" % e.dxf.layer)
|
||||
print("points: %s\n" % repr(e.dxf.points()))
|
||||
#print("y point: %s\n" % e.dxf.y)
|
||||
print("points: %s\n" % repr(e.dxf))
|
||||
|
||||
def get_rack_positions(doc):
|
||||
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
|
||||
msp = doc.modelspace()
|
||||
# for e in msp:
|
||||
# if e.dxftype() == "LINE":
|
||||
# print_line(e)
|
||||
# if e.dxftype() == "LWPOLYLINE":
|
||||
# print_entity(e)
|
||||
|
||||
# # entity query for all LINE entities in modelspace
|
||||
# for e in msp.query("LWPOLYLINE"):
|
||||
# print_entity(e)
|
||||
|
||||
|
||||
|
||||
|
||||
# print_polyline(e)
|
||||
return ret
|
||||
|
||||
def to_json(d, pretty: bool = True) -> str:
|
||||
return json.dumps(d, indent=2 if pretty else None, default=str)
|
||||
|
||||
def get_dxf_file(filepath):
|
||||
"""hole das dxf file
|
||||
@@ -152,9 +191,10 @@ def get_dxf_file(filepath):
|
||||
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('-i', '--input', action='store_true', help='fetch all position of inputs')
|
||||
parser.add_argument('-o', '--output', action='store_true', help='fetch all positions of outputs')
|
||||
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()
|
||||
|
||||
@@ -162,15 +202,25 @@ if __name__ == '__main__':
|
||||
work_dir = os.environ.get('PROJECT_WORK')
|
||||
filename = args.filename
|
||||
|
||||
doc = get_dxf_file(os.path.join(work_dir, filename))
|
||||
doc = get_dxf_file(os.path.join(work_dir, filename)) # type: ignore
|
||||
msp = doc.modelspace()
|
||||
|
||||
res = dict()
|
||||
if args.input:
|
||||
res = get_input_positions(doc)
|
||||
if args.output:
|
||||
get_output_positions(doc)
|
||||
if args.rack:
|
||||
get_rack_positions(doc)
|
||||
res_pos = dict()
|
||||
res_dist = dict()
|
||||
res_rac = dict()
|
||||
if args.sensors or args.dists or args.rack:
|
||||
if args.sensors:
|
||||
res_pos = get_input_positions(msp)
|
||||
if args.console:
|
||||
print(to_json(res_pos))
|
||||
if args.dists:
|
||||
res_dist = get_subdistributor_positions(msp)
|
||||
if args.console:
|
||||
print(to_json(res_dist))
|
||||
if args.rack:
|
||||
res_rac = get_rack_positions(msp)
|
||||
if args.console:
|
||||
print(to_json(res_rac))
|
||||
|
||||
else:
|
||||
parser.print_help()
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
from dataclasses import dataclass, asdict, fields
|
||||
from dacite import from_dict
|
||||
from typing import List
|
||||
import json
|
||||
|
||||
|
||||
@dataclass
|
||||
class Sensor:
|
||||
id: str
|
||||
x: float
|
||||
y: float
|
||||
|
||||
@dataclass
|
||||
class Aktor:
|
||||
id: str
|
||||
x: float
|
||||
y: float
|
||||
|
||||
@dataclass
|
||||
class Pritsche:
|
||||
id: str
|
||||
x: float
|
||||
y: float
|
||||
|
||||
@dataclass
|
||||
class Anlage:
|
||||
name: str
|
||||
sensoren: List[Sensor]
|
||||
aktoren: List[Aktor]
|
||||
kabelpritschen: List[Pritsche]
|
||||
|
||||
def to_json(self, pretty: bool = True) -> str:
|
||||
d = self.to_dict()
|
||||
return json.dumps(d, indent=2 if pretty else None, default=str)
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
"""Konvertiert das Objekt in ein dict – datetime wird als ISO-String dargestellt."""
|
||||
result = asdict(self)
|
||||
# hier um irgendwas ergänzen
|
||||
# result["startdatum"] = self.startdatum.isoformat()
|
||||
return result
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
json_string = '''{
|
||||
"name": "H&M",
|
||||
"sensoren": [
|
||||
{"id": "AP4321", "x": 14, "y": 50},
|
||||
{"id": "AP4322", "x": 22, "y": 100}
|
||||
],
|
||||
"aktoren": [
|
||||
{"id": "AP4321", "x": 14, "y": 50},
|
||||
{"id": "AP4322", "x": 22, "y": 100}
|
||||
],
|
||||
"kabelpritschen": [
|
||||
{"id": "p1", "x": 1, "y": 0},
|
||||
{"id": "p2", "x": 22, "y": 10}
|
||||
]
|
||||
}
|
||||
'''
|
||||
data = json.loads(json_string)
|
||||
anlage = from_dict(
|
||||
data_class=Anlage,
|
||||
data=data
|
||||
)
|
||||
print(anlage)
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"typeCheckingMode": "basic",
|
||||
"reportMissingTypeStubs": true,
|
||||
"useLibraryCodeForTypes": true
|
||||
}
|
||||
Reference in New Issue
Block a user