alles neu mit black formatiert. handler_context.py impl. um weniger Übergabeparameter zu haben

This commit is contained in:
2026-01-27 16:09:52 +01:00
parent 4d09aee02b
commit 19282888ee
16 changed files with 4228 additions and 1682 deletions
+23 -18
View File
@@ -1,15 +1,17 @@
from pydantic import BaseModel, Field, field_validator from pydantic import BaseModel, Field, field_validator
class Angetriebene_Kurve(BaseModel): class Angetriebene_Kurve(BaseModel):
teileid: str teileid: str
x: float x: float
y:float y: float
drehung: float = Field(default=0.0,description="Rotation der Kurve") drehung: float = Field(default=0.0, description="Rotation der Kurve")
hoehe0: float = Field(default=0.0,description="Hoehe Anfang der Kurve") hoehe0: float = Field(default=0.0, description="Hoehe Anfang der Kurve")
hoehe1: float = Field(default=0.0,description="Hoehe Ende der Kurve") hoehe1: float = Field(default=0.0, description="Hoehe Ende der Kurve")
kurvenrichtung: str = Field(description="Kurvenrichtung der Kurve") kurvenrichtung: str = Field(description="Kurvenrichtung der Kurve")
antriebNebenStrecke: str =Field(description="wo die Angetriebene Strecke ist abhängig von der kurvenrichtung") antriebNebenStrecke: str = Field(
description="wo die Angetriebene Strecke ist abhängig von der kurvenrichtung"
)
winkel: int = Field(description="Der Winkel der Kurve") winkel: int = Field(description="Der Winkel der Kurve")
@property @property
@@ -19,11 +21,15 @@ class Angetriebene_Kurve(BaseModel):
elif self.antriebNebenStrecke == "Innen": elif self.antriebNebenStrecke == "Innen":
self.antriebNebenStrecke = "innen" self.antriebNebenStrecke = "innen"
return self.antriebNebenStrecke return self.antriebNebenStrecke
@property @property
def hight_zwischen(self): def hight_zwischen(self):
return ((self.hoehe0 + self.hoehe1) /2) return (self.hoehe0 + self.hoehe1) / 2
@classmethod @classmethod
def from_merkmale(cls, teileid: str, x: float, y: float, merkmale: dict) -> 'Angetriebene_Kurve': def from_merkmale(
cls, teileid: str, x: float, y: float, merkmale: dict
) -> "Angetriebene_Kurve":
hoehe0 = float(merkmale.get("Höhe Anfang")) * 1000 hoehe0 = float(merkmale.get("Höhe Anfang")) * 1000
hoehe1 = float(merkmale.get("Höhe Ende")) * 1000 hoehe1 = float(merkmale.get("Höhe Ende")) * 1000
winkel = int(merkmale.get("Kurvenwinkel")) winkel = int(merkmale.get("Kurvenwinkel"))
@@ -35,14 +41,13 @@ class Angetriebene_Kurve(BaseModel):
drehung = 0.0 drehung = 0.0
return cls( return cls(
teileid = teileid, teileid=teileid,
x = x, x=x,
y = y, y=y,
drehung = drehung, drehung=drehung,
hoehe0 = hoehe0, hoehe0=hoehe0,
hoehe1 = hoehe1, hoehe1=hoehe1,
kurvenrichtung = kurvenrichtung, kurvenrichtung=kurvenrichtung,
antriebNebenStrecke = antriebNebenstrecke, antriebNebenStrecke=antriebNebenstrecke,
winkel = winkel winkel=winkel,
) )
+8 -10
View File
@@ -1,14 +1,18 @@
from pydantic import BaseModel, Field, field_validator from pydantic import BaseModel, Field, field_validator
from typing import Optional from typing import Optional
class Bt_element(BaseModel): class Bt_element(BaseModel):
"""Das sind beide BTMT Elemente""" """Das sind beide BTMT Elemente"""
teileid: str teileid: str
drehung: Optional [float] = Field(default=0.0,description="Rotation des Elements") drehung: Optional[float] = Field(default=0.0, description="Rotation des Elements")
hoehe: Optional [float] = Field(default=0.0,description="Hoehe des Elements") hoehe: Optional[float] = Field(default=0.0, description="Hoehe des Elements")
@classmethod @classmethod
def from_merkmale(cls, teileid: str, x: float, y: float, merkmale: dict) -> 'Bt_element': def from_merkmale(
cls, teileid: str, x: float, y: float, merkmale: dict
) -> "Bt_element":
try: try:
hoehe = float(merkmale.get("Höhe in Meter")) hoehe = float(merkmale.get("Höhe in Meter"))
except Exception as e: except Exception as e:
@@ -18,10 +22,4 @@ class Bt_element(BaseModel):
except Exception as e: except Exception as e:
drehung = 0.0 drehung = 0.0
return cls( return cls(teileid=teileid, x=x, y=y, hoehe=hoehe, drehung=drehung)
teileid = teileid,
x = x,
y = y,
hoehe = hoehe,
drehung = drehung
)
+29 -23
View File
@@ -1,15 +1,22 @@
from pydantic import BaseModel, Field, field_validator from pydantic import BaseModel, Field, field_validator
from typing import Optional from typing import Optional
import block_methoden import block_methoden
RADIUS = 400 RADIUS = 400
class Eckrad(BaseModel): class Eckrad(BaseModel):
teileid: str teileid: str
drehung: Optional [float] = Field(default=0.0,description="Rotation des Elements") drehung: Optional[float] = Field(default=0.0, description="Rotation des Elements")
hoehe: Optional [float] = Field(default=0.0,description="Hoehe des Elements") hoehe: Optional[float] = Field(default=0.0, description="Hoehe des Elements")
drehrichtung: Optional [str] =Field(default=None,description="Richtung des Eckrads") drehrichtung: Optional[str] = Field(
default=None, description="Richtung des Eckrads"
)
@classmethod @classmethod
def from_merkmale(cls, teileid: str, x: float, y: float, merkmale: dict) -> 'Eckrad': def from_merkmale(
cls, teileid: str, x: float, y: float, merkmale: dict
) -> "Eckrad":
try: try:
hoehe = float(merkmale.get("Höhe in Meter")) * 1000 hoehe = float(merkmale.get("Höhe in Meter")) * 1000
except Exception as e: except Exception as e:
@@ -22,27 +29,26 @@ class Eckrad(BaseModel):
drehrichtung = merkmale.get("Drehrichtung") drehrichtung = merkmale.get("Drehrichtung")
except Exception as e: except Exception as e:
drehrichtung = None drehrichtung = None
return cls( return cls(teileid=teileid, x=x, y=y, hoehe=hoehe, drehrichtung=drehrichtung)
teileid = teileid,
x = x,
y = y,
hoehe = hoehe,
drehrichtung = drehrichtung
)
def erstellung_eckrad_richtung(merkmale, doc, lib_doc): def erstellung_eckrad_richtung(merkmale, doc, lib_doc):
block_methoden.import_block("AN8",lib_doc,doc) block_methoden.import_block("AN8", lib_doc, doc)
block_methoden.import_block("Richtungspfeil",lib_doc,doc) block_methoden.import_block("Richtungspfeil", lib_doc, doc)
eckrad_rechts = "eckrad_UZS" eckrad_rechts = "eckrad_UZS"
eckrad_links = "eckrad_GUZS" eckrad_links = "eckrad_GUZS"
hight = float(merkmale.get("Höhe in m")) * 1000 hight = float(merkmale.get("Höhe in m")) * 1000
# Erstellung der Richtungung Blöcke der Eckrads # Erstellung der Richtungung Blöcke der Eckrads
if eckrad_rechts not in doc.blocks: if eckrad_rechts not in doc.blocks:
block_rechts = doc.blocks.new(name= eckrad_rechts,base_point=(0,0,0)) block_rechts = doc.blocks.new(name=eckrad_rechts, base_point=(0, 0, 0))
block_links = doc.blocks.new(name= eckrad_links,base_point=(0,0,0)) block_links = doc.blocks.new(name=eckrad_links, base_point=(0, 0, 0))
block_rechts.add_blockref("AN8",(0,0,0)) block_rechts.add_blockref("AN8", (0, 0, 0))
block_links.add_blockref("AN8",(0,0,0)) block_links.add_blockref("AN8", (0, 0, 0))
block_rechts.add_blockref("Richtungspfeil",(0+200,0+ RADIUS,0)) block_rechts.add_blockref("Richtungspfeil", (0 + 200, 0 + RADIUS, 0))
block_rechts.add_blockref("Richtungspfeil",(0-200,0- RADIUS,0),dxfattribs={"rotation": 180}) block_rechts.add_blockref(
block_links.add_blockref("Richtungspfeil",(0+200,0- RADIUS,0)) "Richtungspfeil", (0 - 200, 0 - RADIUS, 0), dxfattribs={"rotation": 180}
block_links.add_blockref("Richtungspfeil",(0-200,0+ RADIUS,0),dxfattribs={"rotation": 180}) )
return eckrad_rechts,eckrad_links,hight block_links.add_blockref("Richtungspfeil", (0 + 200, 0 - RADIUS, 0))
block_links.add_blockref(
"Richtungspfeil", (0 - 200, 0 + RADIUS, 0), dxfattribs={"rotation": 180}
)
return eckrad_rechts, eckrad_links, hight
+26 -26
View File
@@ -38,11 +38,11 @@ class Gefaellestrecke(BaseModel):
anzahl_scanner = int(merkmale.get("Anzahl der Scanner")), anzahl_scanner = int(merkmale.get("Anzahl der Scanner")),
anzahl_separatoren = int(merkmale.get("Anzahl der Separatoren")) anzahl_separatoren = int(merkmale.get("Anzahl der Separatoren"))
) )
def erstehlung_von_gefalle_ohne_aussnahmen(msp, x, y, upper_hoehe_gefaehlle, lower_hoehe_gefaehlle, halbe_laenge, winkel): def erstehlung_von_gefalle_ohne_aussnahmen(msp, x, y, upper_hoehe_gefaelle, lower_hoehe_gefaelle, halbe_laenge, winkel):
dx = halbe_laenge *math.sin(winkel * -1) dx = halbe_laenge *math.sin(winkel * -1)
dy = halbe_laenge * math.cos(winkel) dy = halbe_laenge * math.cos(winkel)
start = x +dx, y + dy,upper_hoehe_gefaehlle start = x +dx, y + dy,upper_hoehe_gefaelle
ende = x -dx, y - dy,lower_hoehe_gefaehlle ende = x -dx, y - dy,lower_hoehe_gefaelle
line =msp.add_line(start,ende) line =msp.add_line(start,ende)
line.dxf.layer = "6-SP" line.dxf.layer = "6-SP"
def rotation_mit_zwei_verbunden(gefaellestrecke_nachbarn,richtung2, richtung0, am_kreisel, kreisel_verbunden, hight_position): def rotation_mit_zwei_verbunden(gefaellestrecke_nachbarn,richtung2, richtung0, am_kreisel, kreisel_verbunden, hight_position):
@@ -137,7 +137,7 @@ class Gefaellestrecke(BaseModel):
elif gefaelle == "rechts" : elif gefaelle == "rechts" :
rotation = 270 rotation = 270
return rotation,drehung0,drehung1,hight_position return rotation,drehung0,drehung1,hight_position
def ein_motor_oder_eine_umlenk(x, y,start,ende, doc, lib_doc, hoehe_gefaehlle, block_Vario_Umlenkstation_500mm, block_Vario_Motorstation_500mm, blockname_motor_links, blockname_umlenk_links, hat_motor_0, hat_umlenk_0, tefkurve_0, block,umlenk_gerade,motor_gerade): def ein_motor_oder_eine_umlenk(x, y,start,ende, doc, lib_doc, hoehe_gefaelle, block_Vario_Umlenkstation_500mm, block_Vario_Motorstation_500mm, blockname_motor_links, blockname_umlenk_links, hat_motor_0, hat_umlenk_0, tefkurve_0, block,umlenk_gerade,motor_gerade):
block_Vario_Bogen_auf = (f"Vario_Bogen_auf_3°") block_Vario_Bogen_auf = (f"Vario_Bogen_auf_3°")
block_Vario_Bogen_ab = (f"Vario_Bogen_ab_3°") block_Vario_Bogen_ab = (f"Vario_Bogen_ab_3°")
@@ -165,48 +165,48 @@ class Gefaellestrecke(BaseModel):
if hat_motor_0 == True: if hat_motor_0 == True:
if tefkurve_0 == "links": if tefkurve_0 == "links":
if motor_gerade == False: if motor_gerade == False:
block.add_blockref(block_Vario_Bogen_ab_links,(start[0]-x,start[1]-Vario_Bogen_ab_Delta_SP_0[0]-y,start[2]- Vario_Bogen_ab_Delta_SP_0[2]-hoehe_gefaehlle),dxfattribs={"rotation": 270}) block.add_blockref(block_Vario_Bogen_ab_links,(start[0]-x,start[1]-Vario_Bogen_ab_Delta_SP_0[0]-y,start[2]- Vario_Bogen_ab_Delta_SP_0[2]-hoehe_gefaelle),dxfattribs={"rotation": 270})
start = [start[0],start[1]-Vario_Bogen_ab_Delta_SP_0[0]- Vario_Bogen_ab_Delta_SP_1[0],start[2]-Vario_Bogen_ab_Delta_SP_0[2]- Vario_Bogen_ab_Delta_SP_1[2]] start = [start[0],start[1]-Vario_Bogen_ab_Delta_SP_0[0]- Vario_Bogen_ab_Delta_SP_1[0],start[2]-Vario_Bogen_ab_Delta_SP_0[2]- Vario_Bogen_ab_Delta_SP_1[2]]
block.add_blockref(blockname_motor_links, (start[0]-x,start[1] - 250* math.cos(math.radians(3))-y,start[2] - 250* math.sin(math.radians(3))-hoehe_gefaehlle),dxfattribs={"rotation": 270}) block.add_blockref(blockname_motor_links, (start[0]-x,start[1] - 250* math.cos(math.radians(3))-y,start[2] - 250* math.sin(math.radians(3))-hoehe_gefaelle),dxfattribs={"rotation": 270})
start[1]= start[1] - 500* math.cos(math.radians(3)) start[1]= start[1] - 500* math.cos(math.radians(3))
start[2] = start[2] - 500* math.sin(math.radians(3)) start[2] = start[2] - 500* math.sin(math.radians(3))
else: else:
block.add_blockref("Vario_Motorstation_500mm_links", (start[0]-x,start[1] -250 -y,start[2] -hoehe_gefaehlle),dxfattribs={"rotation": 270}) block.add_blockref("Vario_Motorstation_500mm_links", (start[0]-x,start[1] -250 -y,start[2] -hoehe_gefaelle),dxfattribs={"rotation": 270})
start[1]= start[1] - 500 start[1]= start[1] - 500
else: else:
if motor_gerade == False: if motor_gerade == False:
block.add_blockref(block_Vario_Bogen_ab,(start[0]-x,start[1]-Vario_Bogen_ab_Delta_SP_0[0]-y,start[2]- Vario_Bogen_ab_Delta_SP_0[2]-hoehe_gefaehlle),dxfattribs={"rotation": 270}) block.add_blockref(block_Vario_Bogen_ab,(start[0]-x,start[1]-Vario_Bogen_ab_Delta_SP_0[0]-y,start[2]- Vario_Bogen_ab_Delta_SP_0[2]-hoehe_gefaelle),dxfattribs={"rotation": 270})
start = [start[0],start[1]-Vario_Bogen_ab_Delta_SP_0[0]- Vario_Bogen_ab_Delta_SP_1[0],start[2]-Vario_Bogen_ab_Delta_SP_0[2]- Vario_Bogen_ab_Delta_SP_1[2]] start = [start[0],start[1]-Vario_Bogen_ab_Delta_SP_0[0]- Vario_Bogen_ab_Delta_SP_1[0],start[2]-Vario_Bogen_ab_Delta_SP_0[2]- Vario_Bogen_ab_Delta_SP_1[2]]
block.add_blockref(block_Vario_Motorstation_500mm, (start[0]-x,start[1] - 250* math.cos(math.radians(3))-y,start[2] - 250* math.sin(math.radians(3))-hoehe_gefaehlle),dxfattribs={"rotation": 270}) block.add_blockref(block_Vario_Motorstation_500mm, (start[0]-x,start[1] - 250* math.cos(math.radians(3))-y,start[2] - 250* math.sin(math.radians(3))-hoehe_gefaelle),dxfattribs={"rotation": 270})
start[1]= start[1] - 500* math.cos(math.radians(3)) start[1]= start[1] - 500* math.cos(math.radians(3))
start[2] = start[2] - 500* math.sin(math.radians(3)) start[2] = start[2] - 500* math.sin(math.radians(3))
else: else:
block.add_blockref("Vario_Motorstation_500mm", (start[0]-x,start[1]- 250 -y,start[2] -hoehe_gefaehlle),dxfattribs={"rotation": 270}) block.add_blockref("Vario_Motorstation_500mm", (start[0]-x,start[1]- 250 -y,start[2] -hoehe_gefaelle),dxfattribs={"rotation": 270})
start[1]= start[1] - 500 start[1]= start[1] - 500
if hat_umlenk_0 == True: if hat_umlenk_0 == True:
if tefkurve_0 == "links": if tefkurve_0 == "links":
if umlenk_gerade == False: if umlenk_gerade == False:
block.add_blockref(block_Vario_Bogen_auf,(ende[0]-x,ende[1]+Vario_Bogen_auf_Delta_SP_0[0]-y,ende[2] + Vario_Bogen_auf_Delta_SP_0[2]-hoehe_gefaehlle),dxfattribs={"rotation": 90}) block.add_blockref(block_Vario_Bogen_auf,(ende[0]-x,ende[1]+Vario_Bogen_auf_Delta_SP_0[0]-y,ende[2] + Vario_Bogen_auf_Delta_SP_0[2]-hoehe_gefaelle),dxfattribs={"rotation": 90})
ende = [ende[0],ende[1]+ Vario_Bogen_auf_Delta_SP_0[0]+ Vario_Bogen_auf_Delta_SP_1[0],ende[2]+Vario_Bogen_auf_Delta_SP_0[2]+ Vario_Bogen_auf_Delta_SP_1[2]] ende = [ende[0],ende[1]+ Vario_Bogen_auf_Delta_SP_0[0]+ Vario_Bogen_auf_Delta_SP_1[0],ende[2]+Vario_Bogen_auf_Delta_SP_0[2]+ Vario_Bogen_auf_Delta_SP_1[2]]
block.add_blockref(blockname_umlenk_links, (ende[0]-x,ende[1] + 250* math.cos(math.radians(3))-y,ende[2] + 250* math.sin(math.radians(3))-hoehe_gefaehlle),dxfattribs={"rotation": 270}) block.add_blockref(blockname_umlenk_links, (ende[0]-x,ende[1] + 250* math.cos(math.radians(3))-y,ende[2] + 250* math.sin(math.radians(3))-hoehe_gefaelle),dxfattribs={"rotation": 270})
ende [1]= ende[1] + 500* math.cos(math.radians(3)) ende [1]= ende[1] + 500* math.cos(math.radians(3))
ende[2] = ende[2] + 500* math.sin(math.radians(3)) ende[2] = ende[2] + 500* math.sin(math.radians(3))
else: else:
block.add_blockref("Vario_Umlenkstation_500mm_links", (ende[0]-x,ende[1] + 250-y,ende[2] -hoehe_gefaehlle),dxfattribs={"rotation": 270}) block.add_blockref("Vario_Umlenkstation_500mm_links", (ende[0]-x,ende[1] + 250-y,ende[2] -hoehe_gefaelle),dxfattribs={"rotation": 270})
ende [1]= ende[1] + 500 ende [1]= ende[1] + 500
else: else:
if umlenk_gerade == False: if umlenk_gerade == False:
block.add_blockref(block_Vario_Bogen_auf_links,(ende[0]-x,ende[1]+Vario_Bogen_auf_Delta_SP_0[0]-y,ende[2] + Vario_Bogen_auf_Delta_SP_0[2]-hoehe_gefaehlle),dxfattribs={"rotation": 90}) block.add_blockref(block_Vario_Bogen_auf_links,(ende[0]-x,ende[1]+Vario_Bogen_auf_Delta_SP_0[0]-y,ende[2] + Vario_Bogen_auf_Delta_SP_0[2]-hoehe_gefaelle),dxfattribs={"rotation": 90})
ende = [ende[0],ende[1]+ Vario_Bogen_auf_Delta_SP_0[0]+ Vario_Bogen_auf_Delta_SP_1[0],ende[2]+Vario_Bogen_auf_Delta_SP_0[2]+ Vario_Bogen_auf_Delta_SP_1[2]] ende = [ende[0],ende[1]+ Vario_Bogen_auf_Delta_SP_0[0]+ Vario_Bogen_auf_Delta_SP_1[0],ende[2]+Vario_Bogen_auf_Delta_SP_0[2]+ Vario_Bogen_auf_Delta_SP_1[2]]
block.add_blockref(block_Vario_Umlenkstation_500mm, (ende[0]-x,ende[1] + 250* math.cos(math.radians(3))-y,ende[2] + 250* math.sin(math.radians(3))-hoehe_gefaehlle),dxfattribs={"rotation": 270}) block.add_blockref(block_Vario_Umlenkstation_500mm, (ende[0]-x,ende[1] + 250* math.cos(math.radians(3))-y,ende[2] + 250* math.sin(math.radians(3))-hoehe_gefaelle),dxfattribs={"rotation": 270})
ende [1]= ende[1] + 500* math.cos(math.radians(3)) ende [1]= ende[1] + 500* math.cos(math.radians(3))
ende[2] = ende[2] + 500* math.sin(math.radians(3)) ende[2] = ende[2] + 500* math.sin(math.radians(3))
else: else:
block.add_blockref("Vario_Umlenkstation_500mm", (ende[0]-x,ende[1] + 250-y,ende[2] -hoehe_gefaehlle),dxfattribs={"rotation": 270}) block.add_blockref("Vario_Umlenkstation_500mm", (ende[0]-x,ende[1] + 250-y,ende[2] -hoehe_gefaelle),dxfattribs={"rotation": 270})
ende [1]= ende[1] + 500 ende [1]= ende[1] + 500
return start,ende return start,ende
def hat_motor_umlenk_station (gefaelle_objekt, gefaellestrecke_nachbarn): def hat_motor_umlenk_station (gefaelle_objekt, gefaellestrecke_nachbarn):
@@ -218,8 +218,8 @@ class Gefaellestrecke(BaseModel):
tefkurve_1 = None tefkurve_1 = None
umlenk_gerade = False umlenk_gerade = False
motor_gerade = False motor_gerade = False
upper_hoehe_gefaehlle = gefaelle_objekt.h1 upper_hoehe_gefaelle = gefaelle_objekt.h1
lower_hoehe_gefaehlle = gefaelle_objekt.h0 lower_hoehe_gefaelle = gefaelle_objekt.h0
rotation = gefaelle_objekt.drehung rotation = gefaelle_objekt.drehung
x = gefaelle_objekt.x x = gefaelle_objekt.x
y = gefaelle_objekt.y y = gefaelle_objekt.y
@@ -238,13 +238,13 @@ class Gefaellestrecke(BaseModel):
else: else:
tefkurve_0 = "links" tefkurve_0 = "links"
if upper_hoehe_gefaehlle > lower_hoehe_gefaehlle: if upper_hoehe_gefaelle > lower_hoehe_gefaelle:
if vario_hoehe_0 == upper_hoehe_gefaehlle or vario_hoehe_1 == upper_hoehe_gefaehlle: if vario_hoehe_0 == upper_hoehe_gefaelle or vario_hoehe_1 == upper_hoehe_gefaelle:
hat_motor_0 = True hat_motor_0 = True
else: else:
hat_umlenk_0 = True hat_umlenk_0 = True
elif upper_hoehe_gefaehlle < lower_hoehe_gefaehlle: elif upper_hoehe_gefaelle < lower_hoehe_gefaelle:
if vario_hoehe_0 == lower_hoehe_gefaehlle or vario_hoehe_1 == lower_hoehe_gefaehlle: if vario_hoehe_0 == lower_hoehe_gefaelle or vario_hoehe_1 == lower_hoehe_gefaelle:
hat_motor_0 = True hat_motor_0 = True
else: else:
hat_umlenk_0 = True hat_umlenk_0 = True
@@ -270,13 +270,13 @@ class Gefaellestrecke(BaseModel):
tefkurve_1 = "rechts" tefkurve_1 = "rechts"
else: else:
tefkurve_1 = "links" tefkurve_1 = "links"
if upper_hoehe_gefaehlle > lower_hoehe_gefaehlle: if upper_hoehe_gefaelle > lower_hoehe_gefaelle:
if vario_hoehe_0_1 == upper_hoehe_gefaehlle or vario_hoehe_1_1 == upper_hoehe_gefaehlle: if vario_hoehe_0_1 == upper_hoehe_gefaelle or vario_hoehe_1_1 == upper_hoehe_gefaelle:
hat_motor_1 = True hat_motor_1 = True
else: else:
hat_umlenk_1 = True hat_umlenk_1 = True
elif upper_hoehe_gefaehlle < lower_hoehe_gefaehlle: elif upper_hoehe_gefaelle < lower_hoehe_gefaelle:
if vario_hoehe_0_1 == lower_hoehe_gefaehlle or vario_hoehe_1_1 == lower_hoehe_gefaehlle: if vario_hoehe_0_1 == lower_hoehe_gefaelle or vario_hoehe_1_1 == lower_hoehe_gefaelle:
hat_motor_1 = True hat_motor_1 = True
else: else:
hat_umlenk_1 = True hat_umlenk_1 = True
+94 -45
View File
@@ -1,4 +1,3 @@
from ezdxf.entities import Line from ezdxf.entities import Line
import math import math
from pydantic import BaseModel, Field, field_validator from pydantic import BaseModel, Field, field_validator
@@ -7,23 +6,31 @@ import plant2dxf
import block_methoden import block_methoden
ATTR_TAG = "TeileId" # Attributtag im Block ATTR_TAG = "TeileId" # Attributtag im Block
RADIUS = 400 # Radius der Kreiselkreise (mm) RADIUS = 400 # Radius der Kreiselkreise (mm)
class Kreisel(BaseModel): class Kreisel(BaseModel):
"""Pydantic-Modell für Kreisel-Komponenten.""" """Pydantic-Modell für Kreisel-Komponenten."""
teileid: str teileid: str
x: float = Field(description="X-Koordinate des Kreisel-Zentrums") x: float = Field(description="X-Koordinate des Kreisel-Zentrums")
y: float = Field(description="Y-Koordinate des Kreisel-Zentrums") y: float = Field(description="Y-Koordinate des Kreisel-Zentrums")
hoehe: float = Field(description="Höhe in mm") hoehe: float = Field(description="Höhe in mm")
drehung: float = Field(default=0.0, description="Drehung/Winkel in Grad") drehung: float = Field(default=0.0, description="Drehung/Winkel in Grad")
drehrichtung: Optional[str] = Field(default=None, description="Drehrichtung: UZS oder GUZS") drehrichtung: Optional[str] = Field(
abstand: float = Field(default=20000.0, description="Abstand zwischen Kreiselachsen in mm") default=None, description="Drehrichtung: UZS oder GUZS"
kreiselart: Optional[str] = Field(default=None, description="Kreiselart, z.B. 'Pin'") )
abstand: float = Field(
default=20000.0, description="Abstand zwischen Kreiselachsen in mm"
)
kreiselart: Optional[str] = Field(
default=None, description="Kreiselart, z.B. 'Pin'"
)
anzahl_scanner: float = Field(default=0.0, description="Anzahl der Scanner") anzahl_scanner: float = Field(default=0.0, description="Anzahl der Scanner")
anzahl_separatoren: float = Field(default=0.0, description="Anzahl der Separatoren") anzahl_separatoren: float = Field(default=0.0, description="Anzahl der Separatoren")
@field_validator('abstand') @field_validator("abstand")
@classmethod @classmethod
def validate_abstand(cls, v): def validate_abstand(cls, v):
"""Konvertiert Abstand von Meter zu mm, falls nötig.""" """Konvertiert Abstand von Meter zu mm, falls nötig."""
@@ -35,7 +42,7 @@ class Kreisel(BaseModel):
v = 10000.0 # Fallback 10 m v = 10000.0 # Fallback 10 m
return v return v
@field_validator('hoehe') @field_validator("hoehe")
@classmethod @classmethod
def validate_hoehe(cls, v): def validate_hoehe(cls, v):
"""Konvertiert Höhe von Meter zu mm, falls nötig.""" """Konvertiert Höhe von Meter zu mm, falls nötig."""
@@ -86,7 +93,9 @@ class Kreisel(BaseModel):
return self.hoehe return self.hoehe
@classmethod @classmethod
def from_merkmale(cls, teileid: str, x: float, y: float, merkmale: dict) -> 'Kreisel': def from_merkmale(
cls, teileid: str, x: float, y: float, merkmale: dict
) -> "Kreisel":
"""Erstellt ein Kreisel-Objekt aus einem merkmale-Dictionary.""" """Erstellt ein Kreisel-Objekt aus einem merkmale-Dictionary."""
hoehe_m = merkmale.get("Höhe in m", "0").replace(",", ".") hoehe_m = merkmale.get("Höhe in m", "0").replace(",", ".")
try: try:
@@ -94,7 +103,9 @@ class Kreisel(BaseModel):
except (ValueError, TypeError): except (ValueError, TypeError):
hoehe = 0.0 hoehe = 0.0
abstand_m = merkmale.get("Abstand (Kreiselachse A - Kreiselachse) in Meter", "20").replace(",", ".") abstand_m = merkmale.get(
"Abstand (Kreiselachse A - Kreiselachse) in Meter", "20"
).replace(",", ".")
try: try:
abstand = float(abstand_m) * 1000 abstand = float(abstand_m) * 1000
except (ValueError, TypeError): except (ValueError, TypeError):
@@ -125,7 +136,7 @@ class Kreisel(BaseModel):
abstand=abstand, abstand=abstand,
kreiselart=merkmale.get("Kreiselart"), kreiselart=merkmale.get("Kreiselart"),
anzahl_scanner=anzahl_scanner, anzahl_scanner=anzahl_scanner,
anzahl_separatoren=anzahl_separatoren anzahl_separatoren=anzahl_separatoren,
) )
def draw_kreisel_lines(msp, pos1, pos2, kreisel): def draw_kreisel_lines(msp, pos1, pos2, kreisel):
@@ -145,45 +156,61 @@ class Kreisel(BaseModel):
nx = -dy / length * RADIUS nx = -dy / length * RADIUS
ny = dx / length * RADIUS ny = dx / length * RADIUS
# Tangentialpunkte # Tangentialpunkte
p1a = (x1 + nx, y1 + ny,z1) p1a = (x1 + nx, y1 + ny, z1)
p1b = (x1 - nx, y1 - ny,z1) p1b = (x1 - nx, y1 - ny, z1)
p2a = (x2 + nx, y2 + ny,z1) p2a = (x2 + nx, y2 + ny, z1)
p2b = (x2 - nx, y2 - ny,z1) p2b = (x2 - nx, y2 - ny, z1)
if kreisel.kreiselart == "Pin": if kreisel.kreiselart == "Pin":
if rotation == 0.0: if rotation == 0.0:
p1a2 = p1a[0] - RADIUS - 50, p1a[1] + 50, z1 p1a2 = p1a[0] - RADIUS - 50, p1a[1] + 50, z1
p1b2 = p1b[0] - RADIUS - 50, p1b[1] - 50, z1 p1b2 = p1b[0] - RADIUS - 50, p1b[1] - 50, z1
p2a2 = p2a[0] + RADIUS + 50, p2a[1] + 50, z1 p2a2 = p2a[0] + RADIUS + 50, p2a[1] + 50, z1
p2b2 = p2b[0] + RADIUS + 50, p2b[1] - 50, z1 p2b2 = p2b[0] + RADIUS + 50, p2b[1] - 50, z1
Line1 = Line.new(dxfattribs={"start": p1a2,"end": p2a2,"layer": "Pinbereich"}) Line1 = Line.new(
Line2 = Line.new(dxfattribs={"start": p1b2,"end": p2b2,"layer": "Pinbereich"}) dxfattribs={"start": p1a2, "end": p2a2, "layer": "Pinbereich"}
)
Line2 = Line.new(
dxfattribs={"start": p1b2, "end": p2b2, "layer": "Pinbereich"}
)
msp.add_entity(Line1) msp.add_entity(Line1)
msp.add_entity(Line2) msp.add_entity(Line2)
elif rotation == 180.0: elif rotation == 180.0:
p1a2 = p1a[0] + RADIUS + 50, p1a[1] - 50, z1 p1a2 = p1a[0] + RADIUS + 50, p1a[1] - 50, z1
p1b2 = p1b[0] + RADIUS + 50, p1b[1] + 50, z1 p1b2 = p1b[0] + RADIUS + 50, p1b[1] + 50, z1
p2a2 = p2a[0] - RADIUS - 50, p2a[1] - 50, z1 p2a2 = p2a[0] - RADIUS - 50, p2a[1] - 50, z1
p2b2 = p2b[0] - RADIUS - 50, p2b[1] + 50, z1 p2b2 = p2b[0] - RADIUS - 50, p2b[1] + 50, z1
Line1 = Line.new(dxfattribs={"start": p1a2,"end": p2a2,"layer": "Pinbereich"}) Line1 = Line.new(
Line2 = Line.new(dxfattribs={"start": p1b2,"end": p2b2,"layer": "Pinbereich"}) dxfattribs={"start": p1a2, "end": p2a2, "layer": "Pinbereich"}
)
Line2 = Line.new(
dxfattribs={"start": p1b2, "end": p2b2, "layer": "Pinbereich"}
)
msp.add_entity(Line1) msp.add_entity(Line1)
msp.add_entity(Line2) msp.add_entity(Line2)
elif rotation == 90.0: elif rotation == 90.0:
p1a2 = p1a[0] + 50, p1a[1] - 50 + RADIUS , z1 p1a2 = p1a[0] + 50, p1a[1] - 50 + RADIUS, z1
p1b2 = p1b[0] - 50, p1b[1] - 50 + RADIUS, z1 p1b2 = p1b[0] - 50, p1b[1] - 50 + RADIUS, z1
p2a2 = p2a[0] + 50, p2a[1] + 50 - RADIUS, z1 p2a2 = p2a[0] + 50, p2a[1] + 50 - RADIUS, z1
p2b2 = p2b[0] - 50, p2b[1] + 50 - RADIUS, z1 p2b2 = p2b[0] - 50, p2b[1] + 50 - RADIUS, z1
Line1 = Line.new(dxfattribs={"start": p1a2,"end": p2a2,"layer": "Pinbereich"}) Line1 = Line.new(
Line2 = Line.new(dxfattribs={"start": p1b2,"end": p2b2,"layer": "Pinbereich"}) dxfattribs={"start": p1a2, "end": p2a2, "layer": "Pinbereich"}
)
Line2 = Line.new(
dxfattribs={"start": p1b2, "end": p2b2, "layer": "Pinbereich"}
)
msp.add_entity(Line1) msp.add_entity(Line1)
msp.add_entity(Line2) msp.add_entity(Line2)
elif rotation == 270.0: elif rotation == 270.0:
p1a2 = p1a[0] - 50, p1a[1] + 50 - RADIUS , z1 p1a2 = p1a[0] - 50, p1a[1] + 50 - RADIUS, z1
p1b2 = p1b[0] + 50, p1b[1] + 50 - RADIUS, z1 p1b2 = p1b[0] + 50, p1b[1] + 50 - RADIUS, z1
p2a2 = p2a[0] - 50, p2a[1] - 50 + RADIUS, z1 p2a2 = p2a[0] - 50, p2a[1] - 50 + RADIUS, z1
p2b2 = p2b[0] + 50, p2b[1] - 50 + RADIUS, z1 p2b2 = p2b[0] + 50, p2b[1] - 50 + RADIUS, z1
Line1 = Line.new(dxfattribs={"start": p1a2,"end": p2a2,"layer": "Pinbereich"}) Line1 = Line.new(
Line2 = Line.new(dxfattribs={"start": p1b2,"end": p2b2,"layer": "Pinbereich"}) dxfattribs={"start": p1a2, "end": p2a2, "layer": "Pinbereich"}
)
Line2 = Line.new(
dxfattribs={"start": p1b2, "end": p2b2, "layer": "Pinbereich"}
)
msp.add_entity(Line1) msp.add_entity(Line1)
msp.add_entity(Line2) msp.add_entity(Line2)
@@ -191,12 +218,14 @@ class Kreisel(BaseModel):
msp.add_line(p1a, p2a) msp.add_line(p1a, p2a)
msp.add_line(p1b, p2b) msp.add_line(p1b, p2b)
def draw_kreisel_drehrichtung_markierung(msp, pos1, pos2, kreisel, lib_doc, doc, verbose): def draw_kreisel_drehrichtung_markierung(
msp, pos1, pos2, kreisel, lib_doc, doc, verbose
):
drehrichtung = (kreisel.drehrichtung or "").upper() drehrichtung = (kreisel.drehrichtung or "").upper()
if drehrichtung not in ("UZS", "GUZS"): if drehrichtung not in ("UZS", "GUZS"):
return return
x1, y1,z1= pos1 x1, y1, z1 = pos1
x2, y2,z2 = pos2 x2, y2, z2 = pos2
dx = x2 - x1 dx = x2 - x1
dy = y2 - y1 dy = y2 - y1
length = math.hypot(dx, dy) length = math.hypot(dx, dy)
@@ -216,24 +245,44 @@ class Kreisel(BaseModel):
t = i / 4 # 1/4, 2/4, 3/4 t = i / 4 # 1/4, 2/4, 3/4
px = p1_oben[0] + t * (p2_oben[0] - p1_oben[0]) px = p1_oben[0] + t * (p2_oben[0] - p1_oben[0])
py = p1_oben[1] + t * (p2_oben[1] - p1_oben[1]) py = p1_oben[1] + t * (p2_oben[1] - p1_oben[1])
rotation = math.degrees(math.atan2(p2_oben[1] - p1_oben[1], p2_oben[0] - p1_oben[0])) rotation = math.degrees(
math.atan2(p2_oben[1] - p1_oben[1], p2_oben[0] - p1_oben[0])
)
if drehrichtung == "GUZS": if drehrichtung == "GUZS":
rotation += 180 rotation += 180
block_methoden.import_block("Richtungspfeil", lib_doc, doc) block_methoden.import_block("Richtungspfeil", lib_doc, doc)
blockref_layer, color = block_methoden.get_insert_color_layer(lib_doc, "Richtungspfeil") blockref_layer, color = block_methoden.get_insert_color_layer(
bref = msp.add_blockref("Richtungspfeil", (px, py,z1), dxfattribs={"rotation": rotation,"layer": blockref_layer}) lib_doc, "Richtungspfeil"
)
bref = msp.add_blockref(
"Richtungspfeil",
(px, py, z1),
dxfattribs={"rotation": rotation, "layer": blockref_layer},
)
if verbose: if verbose:
print(f"[INFO] Drehrichtung '{drehrichtung}': Richtungspfeil oben bei ({px:.1f}, {py:.1f}), rot={rotation:.1f}") print(
f"[INFO] Drehrichtung '{drehrichtung}': Richtungspfeil oben bei ({px:.1f}, {py:.1f}), rot={rotation:.1f}"
)
# S-LP auf unterer Linie (Drehrichtung invertiert) # S-LP auf unterer Linie (Drehrichtung invertiert)
for i in range(1, 4): for i in range(1, 4):
t = i / 4 t = i / 4
px = p1_unten[0] + t * (p2_unten[0] - p1_unten[0]) px = p1_unten[0] + t * (p2_unten[0] - p1_unten[0])
py = p1_unten[1] + t * (p2_unten[1] - p1_unten[1]) py = p1_unten[1] + t * (p2_unten[1] - p1_unten[1])
rotation = math.degrees(math.atan2(p2_unten[1] - p1_unten[1], p2_unten[0] - p1_unten[0])) rotation = math.degrees(
math.atan2(p2_unten[1] - p1_unten[1], p2_unten[0] - p1_unten[0])
)
if drehrichtung == "UZS": if drehrichtung == "UZS":
rotation += 180 rotation += 180
block_methoden.import_block("Richtungspfeil", lib_doc, doc) block_methoden.import_block("Richtungspfeil", lib_doc, doc)
blockref_layer, color = block_methoden.get_insert_color_layer( lib_doc, "Richtungspfeil") blockref_layer, color = block_methoden.get_insert_color_layer(
bref = msp.add_blockref("Richtungspfeil", (px, py, z1), dxfattribs={"rotation": rotation , "layer": blockref_layer}) lib_doc, "Richtungspfeil"
)
bref = msp.add_blockref(
"Richtungspfeil",
(px, py, z1),
dxfattribs={"rotation": rotation, "layer": blockref_layer},
)
if verbose: if verbose:
print(f"[INFO] Drehrichtung '{drehrichtung}':Richtungspfeil unten bei ({px:.1f}, {py:.1f}), rot={rotation:.1f}") print(
f"[INFO] Drehrichtung '{drehrichtung}':Richtungspfeil unten bei ({px:.1f}, {py:.1f}), rot={rotation:.1f}"
)
+50 -41
View File
@@ -1,31 +1,37 @@
from ezdxf.entities import Line from ezdxf.entities import Line
import math import math
from pydantic import BaseModel, Field, field_validator from pydantic import BaseModel, Field, field_validator
from typing import Optional from typing import Optional
import plant2dxf import plant2dxf
import block_methoden import block_methoden
class Omniflo(BaseModel): class Omniflo(BaseModel):
teileid:str teileid: str
x:float x: float
y:float y: float
sivasnummer:str sivasnummer: str
laenge: Optional [float] laenge: Optional[float]
drehung: float drehung: float
hoehe : Optional[float] hoehe: Optional[float]
h0: Optional[float] = Field(default = 0.0,description="Höhe unten im CSV") h0: Optional[float] = Field(default=0.0, description="Höhe unten im CSV")
h1: Optional[float] = Field(default = 0.0, description="Höhe Oben im CSV") h1: Optional[float] = Field(default=0.0, description="Höhe Oben im CSV")
anzahl_scanner: Optional [int] = Field(default=0, description="Anzahl der Scanner") anzahl_scanner: Optional[int] = Field(default=0, description="Anzahl der Scanner")
anzahl_stopper: Optional [int] = Field(default=0, description="Anzahl der Separatoren") anzahl_stopper: Optional[int] = Field(
default=0, description="Anzahl der Separatoren"
)
@property @property
def hight_zwischen(self): def hight_zwischen(self):
return ((self.h0 + self.h1) /2) return (self.h0 + self.h1) / 2
@classmethod @classmethod
def from_merkmale(cls, teileid,x,y, merkmale): def from_merkmale(cls, teileid, x, y, merkmale):
sivasnummer = merkmale.get("SivasNummer") sivasnummer = merkmale.get("SivasNummer")
try: try:
laenge = float(merkmale.get("Länge in Meter", "0").replace(",", ".")) * 1000 # Meter → mm laenge = (
float(merkmale.get("Länge in Meter", "0").replace(",", ".")) * 1000
) # Meter → mm
except Exception: except Exception:
laenge = 0 laenge = 0
try: try:
@@ -53,18 +59,19 @@ class Omniflo(BaseModel):
except Exception: except Exception:
anzahl_separatoren = 0 anzahl_separatoren = 0
return cls( return cls(
teileid= teileid, teileid=teileid,
x=x, x=x,
y=y, y=y,
sivasnummer = sivasnummer, sivasnummer=sivasnummer,
laenge = laenge, laenge=laenge,
drehung = winkel, drehung=winkel,
hoehe = hoehe, hoehe=hoehe,
h0 = h0, h0=h0,
h1 = h1, h1=h1,
anzahl_scanner = anzahl_scanner, anzahl_scanner=anzahl_scanner,
anzahl_stopper = anzahl_separatoren anzahl_stopper=anzahl_separatoren,
) )
def Omniflo_geraden_erstellung(msp, doc, tefsivas, omniflo_objekt): def Omniflo_geraden_erstellung(msp, doc, tefsivas, omniflo_objekt):
"""Erstellung der Tef gerade und Omniflo gerade""" """Erstellung der Tef gerade und Omniflo gerade"""
winkel_rad = math.radians(omniflo_objekt.drehung) winkel_rad = math.radians(omniflo_objekt.drehung)
@@ -74,21 +81,22 @@ class Omniflo(BaseModel):
# Man muss bei sin -1 machen wegen des links koordinaten system # Man muss bei sin -1 machen wegen des links koordinaten system
dx = halbe_laenge * math.sin(winkel_rad * -1) dx = halbe_laenge * math.sin(winkel_rad * -1)
dy = halbe_laenge * math.cos(winkel_rad) dy = halbe_laenge * math.cos(winkel_rad)
start = (x + dx, y + dy, omniflo_objekt.h1 ) start = (x + dx, y + dy, omniflo_objekt.h1)
ende = (x - dx, y - dy, omniflo_objekt.h0) ende = (x - dx, y - dy, omniflo_objekt.h0)
if "A-2" not in doc.layers: if "A-2" not in doc.layers:
doc.layers.add(name="A-2", color=2) doc.layers.add(name="A-2", color=2)
if "F-1" not in doc.layers: if "F-1" not in doc.layers:
doc.layers.add(name="F-1", color =1) doc.layers.add(name="F-1", color=1)
linie=msp.add_line(start, ende) linie = msp.add_line(start, ende)
if omniflo_objekt.sivasnummer == tefsivas: if omniflo_objekt.sivasnummer == tefsivas:
linie.dxf.layer = "F-1" linie.dxf.layer = "F-1"
else: else:
linie.dxf.layer = "A-2" linie.dxf.layer = "A-2"
def omniflo_foerdererstellung(msp, doc, lib_doc, omniflo_objekt): def omniflo_foerdererstellung(msp, doc, lib_doc, omniflo_objekt):
""""Erstellung des Kettenförderers aktuell nur grundriss""" """ "Erstellung des Kettenförderers aktuell nur grundriss"""
block_methoden.import_block("bogen1",lib_doc,doc) block_methoden.import_block("bogen1", lib_doc, doc)
block_methoden.import_block("bogen2",lib_doc,doc) block_methoden.import_block("bogen2", lib_doc, doc)
x = omniflo_objekt.x x = omniflo_objekt.x
y = omniflo_objekt.y y = omniflo_objekt.y
rotation = omniflo_objekt.drehung rotation = omniflo_objekt.drehung
@@ -96,21 +104,22 @@ class Omniflo(BaseModel):
h0 = omniflo_objekt.h0 h0 = omniflo_objekt.h0
h1 = omniflo_objekt.h1 h1 = omniflo_objekt.h1
h_zwischen = omniflo_objekt.hight_zwischen h_zwischen = omniflo_objekt.hight_zwischen
blockname = (f"OF_Förderer_{laenge}_{h_zwischen}") blockname = f"OF_Förderer_{laenge}_{h_zwischen}"
winkel_rad = math.radians(rotation) winkel_rad = math.radians(rotation)
halbe_laenge = laenge / 2 halbe_laenge = laenge / 2
# Man muss bei sin -1 machen wegen des links koordinaten system # Man muss bei sin -1 machen wegen des links koordinaten system
dx = halbe_laenge * math.sin(rotation * -1) dx = halbe_laenge * math.sin(rotation * -1)
dy = halbe_laenge * math.cos(rotation) dy = halbe_laenge * math.cos(rotation)
start = (x + dx, y + dy, h1 ) start = (x + dx, y + dy, h1)
ende = (x - dx, y - dy, h0) ende = (x - dx, y - dy, h0)
if blockname not in doc.blocks: if blockname not in doc.blocks:
block = doc.blocks.new(blockname, base_point=(0,0,0)) block = doc.blocks.new(blockname, base_point=(0, 0, 0))
block.add_blockref("bogen1",start) block.add_blockref("bogen1", start)
block.add_blockref("bogen2",ende) block.add_blockref("bogen2", ende)
line = Line.new(dxfattribs={"start": start,"end":ende}) line = Line.new(dxfattribs={"start": start, "end": ende})
copy = line.copy() copy = line.copy()
copy.translate(-x,-y,-h_zwischen) copy.translate(-x, -y, -h_zwischen)
block.add_entity(copy) block.add_entity(copy)
msp.add_blockref(blockname,(x,y,h_zwischen),dxfattribs={"rotation": rotation}) msp.add_blockref(
blockname, (x, y, h_zwischen), dxfattribs={"rotation": rotation}
)
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -6,7 +6,7 @@ import re
import configparser import configparser
from pathlib import Path from pathlib import Path
from utils import check_environment_var, setup_logger from utils import check_environment_var, setup_logger
from Elemente import Kreisel, VarioFoerderer,Gefaehllestrecke,Angetriebene_Kurve,Bt_element,Omniflo, Eckrad from Elemente import Kreisel, VarioFoerderer,Gefaellestrecke,Angetriebene_Kurve,Bt_element,Omniflo, Eckrad
# --------------------------------------------------------- CFG-Leser für shapes.cfg # --------------------------------------------------------- CFG-Leser für shapes.cfg
def get_shape_cfg(teileart, cfg_path, logger=None): def get_shape_cfg(teileart, cfg_path, logger=None):
parser = configparser.ConfigParser() parser = configparser.ConfigParser()
+710 -302
View File
File diff suppressed because it is too large Load Diff
+83 -41
View File
@@ -3,22 +3,32 @@ import plant2dxf
from ezdxf import units from ezdxf import units
from ezdxf.entities import Line from ezdxf.entities import Line
from ezdxf.addons import importer from ezdxf.addons import importer
from ezdxf.math import Matrix44, X_AXIS,Y_AXIS,Z_AXIS from ezdxf.math import Matrix44, X_AXIS, Y_AXIS, Z_AXIS
def dreh_block(block_name: str, to_doc,lib_doc, winkel) :
"""Nimmt ein schon importierten Block und erstellt einen neuen der an der y_axis oder x_axis gedreht wird
""" def dreh_block(block_name: str, to_doc, lib_doc, winkel):
dreh_block_name = block_name +f"_{math.degrees(winkel)}" """Nimmt ein schon importierten Block und erstellt einen neuen der an der y_axis oder x_axis gedreht wird"""
layer, color = get_insert_color_layer(lib_doc,block_name) dreh_block_name = block_name + f"_{math.degrees(winkel)}"
if (dreh_block_name in to_doc.blocks): layer, color = get_insert_color_layer(lib_doc, block_name)
return dreh_block_name if dreh_block_name in to_doc.blocks:
block_zwischen = to_doc.blocks.new(name=block_name + f"zwischenschrit_{winkel}", base_point=(0,0,0)) return dreh_block_name
block = to_doc.blocks.new(name=dreh_block_name, base_point=(0,0,0)) block_zwischen = to_doc.blocks.new(
if block_name == "200000146_ES-Element_90_rechts" or block_name =="400102632_ES-Element_90_links" or block_name =="200000241_AS-Element_90_rechts" or block_name =="200000217_AS-Element_90_links": name=block_name + f"zwischenschrit_{winkel}", base_point=(0, 0, 0)
)
block = to_doc.blocks.new(name=dreh_block_name, base_point=(0, 0, 0))
if (
block_name == "200000146_ES-Element_90_rechts"
or block_name == "400102632_ES-Element_90_links"
or block_name == "200000241_AS-Element_90_rechts"
or block_name == "200000217_AS-Element_90_links"
):
rotation_matrix = Matrix44.axis_rotate(X_AXIS, winkel) rotation_matrix = Matrix44.axis_rotate(X_AXIS, winkel)
else: else:
rotation_matrix = Matrix44.axis_rotate(Y_AXIS, winkel) rotation_matrix = Matrix44.axis_rotate(Y_AXIS, winkel)
block_zwischen.add_blockref(block_name,(0,0,0),dxfattribs={"layer":layer,"color": color}) block_zwischen.add_blockref(
block_name, (0, 0, 0), dxfattribs={"layer": layer, "color": color}
)
for e in block_zwischen: for e in block_zwischen:
copy = e.copy() copy = e.copy()
copy.transform(rotation_matrix) copy.transform(rotation_matrix)
@@ -26,7 +36,7 @@ def dreh_block(block_name: str, to_doc,lib_doc, winkel) :
return dreh_block_name return dreh_block_name
def import_block(block_name: str, from_doc, to_doc, winkel = None) -> None: def import_block(block_name: str, from_doc, to_doc, winkel=None) -> None:
"""Importiert Blockdefinition block_name von from_doc nach to_doc. """Importiert Blockdefinition block_name von from_doc nach to_doc.
- Kopiert alle Entities des Blocks - Kopiert alle Entities des Blocks
@@ -41,16 +51,16 @@ def import_block(block_name: str, from_doc, to_doc, winkel = None) -> None:
# Alle Linientypen importieren # Alle Linientypen importieren
imp.import_table("linetypes") imp.import_table("linetypes")
if ((block_name in to_doc.blocks)): if block_name in to_doc.blocks:
# speichern der attdef elemente in eine Liste falks diese verhanden sind und gibt diese zurück # speichern der attdef elemente in eine Liste falks diese verhanden sind und gibt diese zurück
for ent in src: for ent in src:
copy = ent.copy() copy = ent.copy()
if ent.dxftype() == "ATTDEF": if ent.dxftype() == "ATTDEF":
att_def[ent.dxf.tag] =ent.dxf.text att_def[ent.dxf.tag] = ent.dxf.text
if ent.dxftype() == "INSERT": if ent.dxftype() == "INSERT":
import_block(ent.dxf.name,from_doc, to_doc,None) import_block(ent.dxf.name, from_doc, to_doc, None)
if att_def != {}: if att_def != {}:
return att_def return att_def
@@ -92,14 +102,15 @@ def import_block(block_name: str, from_doc, to_doc, winkel = None) -> None:
copy = ent.copy() copy = ent.copy()
if ent.dxftype() == "ATTDEF": if ent.dxftype() == "ATTDEF":
att_def[ent.dxf.tag] =ent.dxf.text att_def[ent.dxf.tag] = ent.dxf.text
if ent.dxftype() == "INSERT": if ent.dxftype() == "INSERT":
import_block(ent.dxf.name,from_doc, to_doc,None) import_block(ent.dxf.name, from_doc, to_doc, None)
tgt.add_entity(copy) tgt.add_entity(copy)
if att_def != {}: if att_def != {}:
return att_def return att_def
def get_insert_color_layer(lib_doc, blockname): def get_insert_color_layer(lib_doc, blockname):
"""Gibt den Layer und die Color für den Jeweiligen block in der Libary datei zurück""" """Gibt den Layer und die Color für den Jeweiligen block in der Libary datei zurück"""
msp_lib = lib_doc.modelspace() msp_lib = lib_doc.modelspace()
@@ -111,34 +122,65 @@ def get_insert_color_layer(lib_doc, blockname):
layer = insert.dxf.layer layer = insert.dxf.layer
return layer, color return layer, color
def rotatate_and_left_motor_umlenk(doc, lib_doc,config):
motor_rotation = float(config.get("Ils 2.0 core winkel","winkel_motor")) def rotatate_and_left_motor_umlenk(doc, lib_doc, config):
umlenk_rotation = float(config.get("Ils 2.0 core winkel","winkel_umlenk")) motor_rotation = float(config.get("Ils 2.0 core winkel", "winkel_motor"))
block_Vario_Umlenkstation_500mm ="Vario_Umlenkstation_500mm" umlenk_rotation = float(config.get("Ils 2.0 core winkel", "winkel_umlenk"))
block_Vario_Umlenkstation_500mm = "Vario_Umlenkstation_500mm"
block_Vario_Motorstation_500mm = "Vario_Motorstation_500mm" block_Vario_Motorstation_500mm = "Vario_Motorstation_500mm"
blockname_motor_links = block_Vario_Motorstation_500mm +"_links" blockname_motor_links = block_Vario_Motorstation_500mm + "_links"
blockname_umlenk_links = block_Vario_Umlenkstation_500mm + "_links" blockname_umlenk_links = block_Vario_Umlenkstation_500mm + "_links"
import_block(block_Vario_Umlenkstation_500mm,lib_doc,doc) import_block(block_Vario_Umlenkstation_500mm, lib_doc, doc)
import_block(block_Vario_Motorstation_500mm,lib_doc,doc) import_block(block_Vario_Motorstation_500mm, lib_doc, doc)
turn_two_blocks_left(doc, block_Vario_Umlenkstation_500mm, block_Vario_Motorstation_500mm, blockname_motor_links, blockname_umlenk_links) turn_two_blocks_left(
doc,
block_Vario_Umlenkstation_500mm,
block_Vario_Motorstation_500mm,
blockname_motor_links,
blockname_umlenk_links,
)
block_Vario_Umlenkstation_500mm =dreh_block(block_Vario_Umlenkstation_500mm,doc,lib_doc,math.radians(umlenk_rotation)) block_Vario_Umlenkstation_500mm = dreh_block(
block_Vario_Motorstation_500mm =dreh_block(block_Vario_Motorstation_500mm,doc,lib_doc,math.radians(motor_rotation)) block_Vario_Umlenkstation_500mm, doc, lib_doc, math.radians(umlenk_rotation)
blockname_motor_links =dreh_block(blockname_motor_links,doc,lib_doc,math.radians(umlenk_rotation)) )
blockname_umlenk_links =dreh_block(blockname_umlenk_links,doc,lib_doc,math.radians(motor_rotation)) block_Vario_Motorstation_500mm = dreh_block(
return block_Vario_Umlenkstation_500mm,block_Vario_Motorstation_500mm,blockname_motor_links,blockname_umlenk_links block_Vario_Motorstation_500mm, doc, lib_doc, math.radians(motor_rotation)
)
blockname_motor_links = dreh_block(
blockname_motor_links, doc, lib_doc, math.radians(umlenk_rotation)
)
blockname_umlenk_links = dreh_block(
blockname_umlenk_links, doc, lib_doc, math.radians(motor_rotation)
)
return (
block_Vario_Umlenkstation_500mm,
block_Vario_Motorstation_500mm,
blockname_motor_links,
blockname_umlenk_links,
)
def turn_two_blocks_left(doc, block_1_name_zwischen, block_2_name_zwischen, block_2_left_name, block_1_left_name):
def turn_two_blocks_left(
doc,
block_1_name_zwischen,
block_2_name_zwischen,
block_2_left_name,
block_1_left_name,
):
blockname1 = block_1_name_zwischen blockname1 = block_1_name_zwischen
blockname2 = block_2_name_zwischen blockname2 = block_2_name_zwischen
if block_2_left_name not in doc.blocks: if block_2_left_name not in doc.blocks:
matrix = Matrix44.scale(1,-1,1) matrix = Matrix44.scale(1, -1, 1)
block1_zwischen = doc.blocks.new(name=block_1_name_zwischen + "zwischenschrit", base_point=(0,0,0)) block1_zwischen = doc.blocks.new(
block2_zwischen = doc.blocks.new(name=block_2_name_zwischen + "zwischenschrit", base_point=(0,0,0)) name=block_1_name_zwischen + "zwischenschrit", base_point=(0, 0, 0)
block_2 = doc.blocks.new(name=block_2_left_name,base_point=(0,0,0)) )
block_1_left_name = doc.blocks.new(name=block_1_left_name,base_point=(0,0,0)) block2_zwischen = doc.blocks.new(
block1_zwischen.add_blockref(blockname1,(0,0,0)) name=block_2_name_zwischen + "zwischenschrit", base_point=(0, 0, 0)
block2_zwischen.add_blockref(blockname2,(0,0,0)) )
block_2 = doc.blocks.new(name=block_2_left_name, base_point=(0, 0, 0))
block_1_left_name = doc.blocks.new(name=block_1_left_name, base_point=(0, 0, 0))
block1_zwischen.add_blockref(blockname1, (0, 0, 0))
block2_zwischen.add_blockref(blockname2, (0, 0, 0))
for e in block2_zwischen: for e in block2_zwischen:
copy = e.copy() copy = e.copy()
copy.transform(matrix) copy.transform(matrix)
@@ -149,8 +191,8 @@ def turn_two_blocks_left(doc, block_1_name_zwischen, block_2_name_zwischen, bloc
copy.transform(matrix) copy.transform(matrix)
block_1_left_name.add_entity(copy) block_1_left_name.add_entity(copy)
def add_attributes_to_block(block, attributes):
def add_attributes_to_block(block, attributes):
""" """
Fügt einem bestehenden ezdxf-Block Attribut-Definitionen hinzu. Fügt einem bestehenden ezdxf-Block Attribut-Definitionen hinzu.
@@ -161,7 +203,7 @@ def add_attributes_to_block(block, attributes):
for tag, value in attributes.items(): for tag, value in attributes.items():
tag = tag tag = tag
value = value value = value
a =block.add_attrib( a = block.add_attrib(
tag=tag, tag=tag,
text=value, text=value,
) )
+178 -104
View File
@@ -4,12 +4,12 @@ from ezdxf.math import Matrix44, Vec3, BoundingBox, Vec2
import math import math
import argparse import argparse
import sys import sys
import shutil
import configparser import configparser
from utils import check_environment_var, setup_logger from utils import check_environment_var, setup_logger
from pathlib import Path from pathlib import Path
import logging import logging
def create_block_library(input_dir, output_file, config, logger=None): def create_block_library(input_dir, output_file, config, logger=None):
""" """
Erstellt eine DXF-Block-Bibliothek aus einzelnen DXF-Dateien. Erstellt eine DXF-Block-Bibliothek aus einzelnen DXF-Dateien.
@@ -79,22 +79,21 @@ def create_block_library(input_dir, output_file, config, logger=None):
"REGION", "REGION",
} }
filtered_entities = [] filtered_entities = []
att_def= {} att_def = {}
for insert in src_msp.query("INSERT"): for insert in src_msp.query("INSERT"):
for attrib in insert.attribs: for attrib in insert.attribs:
att_def[attrib.dxf.tag] = attrib.dxf.text att_def[attrib.dxf.tag] = attrib.dxf.text
for e in entities: for e in entities:
if e.dxftype() in allowed_types: if e.dxftype() in allowed_types:
filtered_entities.append(e) filtered_entities.append(e)
else: else:
logger.info(f"{e.dxftype()} is nicht in der erlaubten Liste. Diese befindet sich in {filename}") logger.info(
f"{e.dxftype()} is nicht in der erlaubten Liste. Diese befindet sich in {filename}"
)
entities = filtered_entities entities = filtered_entities
except Exception as e: except Exception as e:
error_msg = f"Fehler beim Lesen von {filename}: {e}" error_msg = f"Fehler beim Lesen von {filename}: {e}"
if logger: if logger:
@@ -106,7 +105,9 @@ def create_block_library(input_dir, output_file, config, logger=None):
# Sicherstellen, dass die im Quell-DXF verwendeten Layer im Zieldokument existieren # Sicherstellen, dass die im Quell-DXF verwendeten Layer im Zieldokument existieren
try: try:
used_layer_names = {e.dxf.layer for e in entities if hasattr(e.dxf, "layer")} used_layer_names = {
e.dxf.layer for e in entities if hasattr(e.dxf, "layer")
}
for layer_name in used_layer_names: for layer_name in used_layer_names:
if layer_name and layer_name not in doc.layers: if layer_name and layer_name not in doc.layers:
try: try:
@@ -123,7 +124,9 @@ def create_block_library(input_dir, output_file, config, logger=None):
except Exception: except Exception:
pass pass
boundingbox, ausdehnung, center = calculate_block_bounding_box(filtered_entities, doc,src_doc, filename,config) boundingbox, ausdehnung, center = calculate_block_bounding_box(
filtered_entities, doc, src_doc, filename, config
)
if center is None: if center is None:
error_msg = f"Keine gültige Geometrie in {filename}" error_msg = f"Keine gültige Geometrie in {filename}"
if logger: if logger:
@@ -136,7 +139,7 @@ def create_block_library(input_dir, output_file, config, logger=None):
if name in doc.blocks: if name in doc.blocks:
doc.blocks.delete_block(name) doc.blocks.delete_block(name)
blk = doc.blocks.new(name=name, base_point=(0,0)) blk = doc.blocks.new(name=name, base_point=(0, 0))
for e in entities: for e in entities:
cp = copy_entity(logger, error_files, filename, e, center) cp = copy_entity(logger, error_files, filename, e, center)
@@ -146,11 +149,10 @@ def create_block_library(input_dir, output_file, config, logger=None):
# Platzierung in Reihen und Spalten # Platzierung in Reihen und Spalten
# Attribut-Definition (ATTDEF) hinzufügen # Attribut-Definition (ATTDEF) hinzufügen
# Blockreferenz-Layer bestimmen
# Blockreferenz-Layer bestimmen
blockref_layer = None blockref_layer = None
try: try:
#Konfiguration erlaubt expliziten Layernamen # Konfiguration erlaubt expliziten Layernamen
cfg_layer = None cfg_layer = None
try: try:
cfg_layer = config.get("dxf2lib", "blockref_layer") cfg_layer = config.get("dxf2lib", "blockref_layer")
@@ -186,40 +188,57 @@ def create_block_library(input_dir, output_file, config, logger=None):
blockref_layer = None blockref_layer = None
section = "dxf2lib" section = "dxf2lib"
text_height = get_cfg_value(section, "text_height", DEFAULTS["text_height"]) text_height = get_cfg_value(section, "text_height", DEFAULTS["text_height"])
extra_block_space_x = get_cfg_value(section, "extra_block_space_x", DEFAULTS["extra_block_space_x"]) extra_block_space_x = get_cfg_value(
blocks_per_row = get_cfg_value(section, "blocks_per_row", DEFAULTS["blocks_per_row"]) section, "extra_block_space_x", DEFAULTS["extra_block_space_x"]
extra_text_space_y = get_cfg_value(section, "extra_text_space_y", DEFAULTS["extra_text_space_y"]) )
blocks_per_row = get_cfg_value(
section, "blocks_per_row", DEFAULTS["blocks_per_row"]
)
extra_text_space_y = get_cfg_value(
section, "extra_text_space_y", DEFAULTS["extra_text_space_y"]
)
ausdehnung_x, ausdehung_y = ausdehnung[0], ausdehnung[1] ausdehnung_x, ausdehung_y = ausdehnung[0], ausdehnung[1]
block_spacing_y = ausdehung_y + 400 block_spacing_y = ausdehung_y + 400
block_spacing_x = ausdehnung_x + extra_block_space_x block_spacing_x = ausdehnung_x + extra_block_space_x
max_blockspacing_x = max(max_blockspacing_x, block_spacing_x) max_blockspacing_x = max(max_blockspacing_x, block_spacing_x)
max_blockspacing_y = max(max_blockspacing_y, block_spacing_y) max_blockspacing_y = max(max_blockspacing_y, block_spacing_y)
x_offset += max_blockspacing_x x_offset += max_blockspacing_x
# Blockreferenz mit optionalem Layer einfügen (Entity-Layer bleiben erhalten) # Blockreferenz mit optionalem Layer einfügen (Entity-Layer bleiben erhalten)
if blockref_layer: if blockref_layer:
test =msp.add_blockref(name, insert=(x_offset, y_offset), dxfattribs={"layer": blockref_layer}) test = msp.add_blockref(
name, insert=(x_offset, y_offset), dxfattribs={"layer": blockref_layer}
)
else: else:
test =msp.add_blockref(name, insert=(x_offset, y_offset)) test = msp.add_blockref(name, insert=(x_offset, y_offset))
# Text mit Blocknamen über dem Block # Text mit Blocknamen über dem Block
if name == "a" or name == "b": if name == "a" or name == "b":
for tag, value in att_def.items(): for tag, value in att_def.items():
tag = tag tag = tag
value = value value = value
a =test.add_attrib( a = test.add_attrib(
tag=tag, tag=tag,
text=value, text=value,
) )
a.is_invisible = True a.is_invisible = True
# Werte aus Config holen (Block: [dxf2lib]) # Werte aus Config holen (Block: [dxf2lib])
msp.add_text(name, dxfattribs={'height': text_height, 'insert': (x_offset -ausdehnung_x/2 , y_offset + ausdehung_y/2 + extra_text_space_y)}) msp.add_text(
name,
dxfattribs={
"height": text_height,
"insert": (
x_offset - ausdehnung_x / 2,
y_offset + ausdehung_y / 2 + extra_text_space_y,
),
},
)
processed_files.append(filename) processed_files.append(filename)
blocks_in_row += 1 blocks_in_row += 1
# Abstand zwischen Blöcken in einer Reihe # Abstand zwischen Blöcken in einer Reihe
if blocks_in_row == blocks_per_row: if blocks_in_row == blocks_per_row:
blocks_in_row = 0 blocks_in_row = 0
@@ -234,7 +253,9 @@ def create_block_library(input_dir, output_file, config, logger=None):
logger.info(f"Fehlerhafte Dateien: {len(error_files)}") logger.info(f"Fehlerhafte Dateien: {len(error_files)}")
if error_files: if error_files:
logger.warning(f"{len(error_files)} Dateien konnten nicht verarbeitet werden:") logger.warning(
f"{len(error_files)} Dateien konnten nicht verarbeitet werden:"
)
for filename, error_msg in error_files: for filename, error_msg in error_files:
logger.error(f"{filename}: {error_msg}") logger.error(f"{filename}: {error_msg}")
else: else:
@@ -245,7 +266,9 @@ def create_block_library(input_dir, output_file, config, logger=None):
print(f"Fehlerhafte Dateien: {len(error_files)}") print(f"Fehlerhafte Dateien: {len(error_files)}")
if error_files: if error_files:
print(f"Warnung: {len(error_files)} Dateien konnten nicht verarbeitet werden.") print(
f"Warnung: {len(error_files)} Dateien konnten nicht verarbeitet werden."
)
output_dir = output_file.parent output_dir = output_file.parent
if not output_dir.exists(): if not output_dir.exists():
@@ -267,7 +290,9 @@ def copy_entity(logger, error_files, filename, e, center):
return cp return cp
except Exception as err: except Exception as err:
error_msg = f"Fehler beim Verarbeiten von Entity {e.dxftype()} in {filename}: {err}" error_msg = (
f"Fehler beim Verarbeiten von Entity {e.dxftype()} in {filename}: {err}"
)
if logger: if logger:
logger.error(error_msg) logger.error(error_msg)
else: else:
@@ -276,15 +301,15 @@ def copy_entity(logger, error_files, filename, e, center):
return None return None
# Standardwerte (falls nicht in der Config) # Standardwerte (falls nicht in der Config)
DEFAULTS = { DEFAULTS = {
"text_height": 20, # Schriftgröße des Texts (in DXF-Einheiten) "text_height": 20, # Schriftgröße des Texts (in DXF-Einheiten)
"blocks_per_row": 20, # Anzahl Blöcke pro Zeile im Raster "blocks_per_row": 20, # Anzahl Blöcke pro Zeile im Raster
"extra_block_space_x" : 50, # Extra Platz damit sich Blöcke nicht überlappen "extra_block_space_x": 50, # Extra Platz damit sich Blöcke nicht überlappen
"extra_text_space_y" : 50 # Abstand der Überschrift über dem Symbol "extra_text_space_y": 50, # Abstand der Überschrift über dem Symbol
} }
def get_cfg_value(section, key, fallback): def get_cfg_value(section, key, fallback):
try: try:
return int(config.get(section, key)) return int(config.get(section, key))
@@ -292,9 +317,9 @@ def get_cfg_value(section, key, fallback):
return fallback return fallback
def convert_dxf_to_block_with_inserts(
input_filename, output_filename, block_name="CONVERTED_BLOCK"
def convert_dxf_to_block_with_inserts(input_filename, output_filename, block_name="CONVERTED_BLOCK"): ):
""" """
Konvertiert alle Entities einer DXF-Datei in einen neuen Block Konvertiert alle Entities einer DXF-Datei in einen neuen Block
INSERTs werden als Referenzen beibehalten (nicht explodiert) INSERTs werden als Referenzen beibehalten (nicht explodiert)
@@ -305,8 +330,8 @@ def convert_dxf_to_block_with_inserts(input_filename, output_filename, block_nam
print(f"Lade DXF-Datei: {input_filename}") print(f"Lade DXF-Datei: {input_filename}")
# Neue Ausgabe-DXF erstellen # Neue Ausgabe-DXF erstellen
output_doc = ezdxf.new('R2010') output_doc = ezdxf.new("R2010")
output_doc.header['$INSUNITS'] = 4 # Millimeter output_doc.header["$INSUNITS"] = 4 # Millimeter
# Zuerst alle Block-Definitionen kopieren # Zuerst alle Block-Definitionen kopieren
copied_blocks = copy_block_definitions(input_doc, output_doc) copied_blocks = copy_block_definitions(input_doc, output_doc)
@@ -322,7 +347,7 @@ def convert_dxf_to_block_with_inserts(input_filename, output_filename, block_nam
insert_count = 0 insert_count = 0
for entity in msp: for entity in msp:
if entity.dxftype() == 'INSERT': if entity.dxftype() == "INSERT":
# INSERT direkt kopieren (nicht explodieren) # INSERT direkt kopieren (nicht explodieren)
copy_entity_to_block(entity, new_block) copy_entity_to_block(entity, new_block)
insert_count += 1 insert_count += 1
@@ -373,7 +398,7 @@ def copy_block_definitions(source_doc, target_doc):
for block_name in source_doc.blocks: for block_name in source_doc.blocks:
# Standard-Blöcke (MODEL_SPACE, PAPER_SPACE) überspringen # Standard-Blöcke (MODEL_SPACE, PAPER_SPACE) überspringen
if block_name.startswith('*'): if block_name.startswith("*"):
continue continue
source_block = source_doc.blocks[block_name] source_block = source_doc.blocks[block_name]
@@ -395,7 +420,7 @@ def copy_block_definitions(source_doc, target_doc):
return copied_blocks return copied_blocks
def calculate_block_bounding_box(block, doc, src_doc, filename,config): def calculate_block_bounding_box(block, doc, src_doc, filename, config):
""" """
Berechnet die Bounding Box eines Blocks inklusive aller INSERTs Berechnet die Bounding Box eines Blocks inklusive aller INSERTs
""" """
@@ -403,15 +428,20 @@ def calculate_block_bounding_box(block, doc, src_doc, filename,config):
bbox = BoundingBox() bbox = BoundingBox()
for entity in block: for entity in block:
entity_bbox = get_entity_bounding_box(entity, doc,src_doc,filename,config) entity_bbox = get_entity_bounding_box(entity, doc, src_doc, filename, config)
if entity_bbox and entity_bbox.has_data: if entity_bbox and entity_bbox.has_data:
bbox.extend(entity_bbox) bbox.extend(entity_bbox)
return (
return bbox, (bbox.extmax.x - bbox.extmin.x, bbox.extmax.y - bbox.extmin.y), bbox.center bbox,
(bbox.extmax.x - bbox.extmin.x, bbox.extmax.y - bbox.extmin.y),
bbox.center,
)
def _bbox_from_virtual_entities(entity, doc, src_doc, filename, config, transform_matrix=None): def _bbox_from_virtual_entities(
entity, doc, src_doc, filename, config, transform_matrix=None
):
""" """
Nutzt virtual_entities(), um komplexe Objekte (z.B. SURFACE) in Nutzt virtual_entities(), um komplexe Objekte (z.B. SURFACE) in
auswertbare Geometrie zu zerlegen und darauf eine Bounding Box zu auswertbare Geometrie zu zerlegen und darauf eine Bounding Box zu
@@ -432,7 +462,7 @@ def _bbox_from_virtual_entities(entity, doc, src_doc, filename, config, transfor
return v_bbox return v_bbox
def get_entity_bounding_box(e, doc,src_doc,filename,config, transform_matrix=None): def get_entity_bounding_box(e, doc, src_doc, filename, config, transform_matrix=None):
""" """
Berechnet die Bounding Box einer einzelnen Entity Berechnet die Bounding Box einer einzelnen Entity
Berücksichtigt INSERTs mit ihren Block-Inhalten Berücksichtigt INSERTs mit ihren Block-Inhalten
@@ -440,7 +470,7 @@ def get_entity_bounding_box(e, doc,src_doc,filename,config, transform_matrix=Non
bbox = BoundingBox() bbox = BoundingBox()
try: try:
if e.dxftype() == 'LINE': if e.dxftype() == "LINE":
start = Vec3(e.dxf.start) start = Vec3(e.dxf.start)
end = Vec3(e.dxf.end) end = Vec3(e.dxf.end)
if transform_matrix: if transform_matrix:
@@ -449,7 +479,7 @@ def get_entity_bounding_box(e, doc,src_doc,filename,config, transform_matrix=Non
bbox.extend([start]) bbox.extend([start])
bbox.extend([end]) bbox.extend([end])
elif e.dxftype() == 'CIRCLE': elif e.dxftype() == "CIRCLE":
# Kreis durch Punktabtastung (robust bei Transformationen) # Kreis durch Punktabtastung (robust bei Transformationen)
center = Vec3(e.dxf.center) center = Vec3(e.dxf.center)
radius = float(e.dxf.radius) radius = float(e.dxf.radius)
@@ -465,7 +495,7 @@ def get_entity_bounding_box(e, doc,src_doc,filename,config, transform_matrix=Non
if points: if points:
bbox.extend(points) bbox.extend(points)
elif e.dxftype() == 'ARC': elif e.dxftype() == "ARC":
# Bogen durch Punktabtastung zwischen Start- und Endwinkel # Bogen durch Punktabtastung zwischen Start- und Endwinkel
center = Vec3(e.dxf.center) center = Vec3(e.dxf.center)
radius = float(e.dxf.radius) radius = float(e.dxf.radius)
@@ -496,7 +526,7 @@ def get_entity_bounding_box(e, doc,src_doc,filename,config, transform_matrix=Non
if points: if points:
bbox.extend(points) bbox.extend(points)
elif e.dxftype() == 'LWPOLYLINE': elif e.dxftype() == "LWPOLYLINE":
# Nutze virtuelle Entities (Linien/Bögen), inkl. Bulge-Unterstützung # Nutze virtuelle Entities (Linien/Bögen), inkl. Bulge-Unterstützung
ve_bbox = _bbox_from_virtual_entities( ve_bbox = _bbox_from_virtual_entities(
e, doc, src_doc, filename, config, transform_matrix e, doc, src_doc, filename, config, transform_matrix
@@ -504,7 +534,7 @@ def get_entity_bounding_box(e, doc,src_doc,filename,config, transform_matrix=Non
if ve_bbox.has_data: if ve_bbox.has_data:
bbox.extend(ve_bbox) bbox.extend(ve_bbox)
elif e.dxftype() == 'POLYLINE': elif e.dxftype() == "POLYLINE":
# 2D/3D Polylines ebenfalls über virtuelle Entities # 2D/3D Polylines ebenfalls über virtuelle Entities
ve_bbox = _bbox_from_virtual_entities( ve_bbox = _bbox_from_virtual_entities(
e, doc, src_doc, filename, config, transform_matrix e, doc, src_doc, filename, config, transform_matrix
@@ -512,7 +542,7 @@ def get_entity_bounding_box(e, doc,src_doc,filename,config, transform_matrix=Non
if ve_bbox.has_data: if ve_bbox.has_data:
bbox.extend(ve_bbox) bbox.extend(ve_bbox)
elif e.dxftype() == '3DFACE': elif e.dxftype() == "3DFACE":
# 3DFace: direkte Eckpunkte verwenden # 3DFace: direkte Eckpunkte verwenden
pts = [] pts = []
try: try:
@@ -527,7 +557,7 @@ def get_entity_bounding_box(e, doc,src_doc,filename,config, transform_matrix=Non
if pts: if pts:
bbox.extend(pts) bbox.extend(pts)
elif e.dxftype() in {'MESH', 'POLYFACE', 'POLYFACEMESH'}: elif e.dxftype() in {"MESH", "POLYFACE", "POLYFACEMESH"}:
# Mesh/Polyface über virtuelle Geometrie auswerten # Mesh/Polyface über virtuelle Geometrie auswerten
ve_bbox = _bbox_from_virtual_entities( ve_bbox = _bbox_from_virtual_entities(
e, doc, src_doc, filename, config, transform_matrix e, doc, src_doc, filename, config, transform_matrix
@@ -535,7 +565,7 @@ def get_entity_bounding_box(e, doc,src_doc,filename,config, transform_matrix=Non
if ve_bbox.has_data: if ve_bbox.has_data:
bbox.extend(ve_bbox) bbox.extend(ve_bbox)
elif e.dxftype() == 'SPLINE': elif e.dxftype() == "SPLINE":
# Approximation der Spline-Kurve # Approximation der Spline-Kurve
try: try:
pts = list(e.approximate(60)) pts = list(e.approximate(60))
@@ -557,18 +587,20 @@ def get_entity_bounding_box(e, doc,src_doc,filename,config, transform_matrix=Non
if sampled: if sampled:
bbox.extend(sampled) bbox.extend(sampled)
elif e.dxftype() == 'ATTDEF': elif e.dxftype() == "ATTDEF":
insert_point = Vec3(e.dxf.insert) insert_point = Vec3(e.dxf.insert)
if transform_matrix: if transform_matrix:
insert_point = transform_matrix.transform(insert_point) insert_point = transform_matrix.transform(insert_point)
elif e.dxftype() == 'TEXT': elif e.dxftype() == "TEXT":
insert_point = Vec3(e.dxf.insert) insert_point = Vec3(e.dxf.insert)
height = float(getattr(e.dxf, "height", 1.0)) height = float(getattr(e.dxf, "height", 1.0))
width_factor = float(getattr(e.dxf, "width", 1.0)) width_factor = float(getattr(e.dxf, "width", 1.0))
rotation = math.radians(getattr(e.dxf, "rotation", 0.0)) rotation = math.radians(getattr(e.dxf, "rotation", 0.0))
text_content = getattr(e.dxf, "text", "") or "" text_content = getattr(e.dxf, "text", "") or ""
est_width = max(len(text_content) * height * 0.6 * width_factor, height * 0.5) est_width = max(
len(text_content) * height * 0.6 * width_factor, height * 0.5
)
corners = [ corners = [
insert_point, insert_point,
insert_point + Vec3(est_width, 0, 0), insert_point + Vec3(est_width, 0, 0),
@@ -590,7 +622,7 @@ def get_entity_bounding_box(e, doc,src_doc,filename,config, transform_matrix=Non
pt = transform_matrix.transform(pt) pt = transform_matrix.transform(pt)
bbox.extend([pt]) bbox.extend([pt])
elif e.dxftype() == 'MTEXT': elif e.dxftype() == "MTEXT":
insert_point = Vec3(e.dxf.insert) insert_point = Vec3(e.dxf.insert)
char_height = float(getattr(e.dxf, "char_height", 1.0)) char_height = float(getattr(e.dxf, "char_height", 1.0))
width = float(getattr(e.dxf, "width", 0.0)) width = float(getattr(e.dxf, "width", 0.0))
@@ -610,7 +642,7 @@ def get_entity_bounding_box(e, doc,src_doc,filename,config, transform_matrix=Non
pt = transform_matrix.transform(pt) pt = transform_matrix.transform(pt)
bbox.extend([pt]) bbox.extend([pt])
elif e.dxftype() == 'REGION': elif e.dxftype() == "REGION":
# Region: Begrenzungsgeometrie über virtual_entities() # Region: Begrenzungsgeometrie über virtual_entities()
ve_bbox = _bbox_from_virtual_entities( ve_bbox = _bbox_from_virtual_entities(
e, doc, src_doc, filename, config, transform_matrix e, doc, src_doc, filename, config, transform_matrix
@@ -618,7 +650,7 @@ def get_entity_bounding_box(e, doc,src_doc,filename,config, transform_matrix=Non
if ve_bbox.has_data: if ve_bbox.has_data:
bbox.extend(ve_bbox) bbox.extend(ve_bbox)
elif e.dxftype().endswith('SURFACE'): elif e.dxftype().endswith("SURFACE"):
# Viele Surface-Typen liefern ihre Proxy-Geometrie über virtual_entities() # Viele Surface-Typen liefern ihre Proxy-Geometrie über virtual_entities()
ve_bbox = _bbox_from_virtual_entities( ve_bbox = _bbox_from_virtual_entities(
e, doc, src_doc, filename, config, transform_matrix e, doc, src_doc, filename, config, transform_matrix
@@ -626,30 +658,42 @@ def get_entity_bounding_box(e, doc,src_doc,filename,config, transform_matrix=Non
if ve_bbox.has_data: if ve_bbox.has_data:
bbox.extend(ve_bbox) bbox.extend(ve_bbox)
elif e.dxftype() == 'INSERT': elif e.dxftype() == "INSERT":
# INSERT: Block-Inhalt mit Transformation berücksichtigen # INSERT: Block-Inhalt mit Transformation berücksichtigen
insert_bbox = calculate_insert_bounding_box(e, doc,src_doc,filename,config, transform_matrix) insert_bbox = calculate_insert_bounding_box(
if insert_bbox and insert_bbox.has_data and e.dxf.layer not in config.get("dxf2lib","automation_layer"): e, doc, src_doc, filename, config, transform_matrix
)
if (
insert_bbox
and insert_bbox.has_data
and e.dxf.layer not in config.get("dxf2lib", "automation_layer")
):
bbox.extend(insert_bbox) bbox.extend(insert_bbox)
except Exception as e: except Exception as e:
print(f"Fehler bei Bounding Box Berechnung für {e.dxftype()}: {e}") print(f"Fehler bei Bounding Box Berechnung für {e.dxftype()}: {e}")
return bbox return bbox
def extract_scaling(matrix):
sx = math.sqrt(matrix[0, 0]**2 + matrix[0, 1]**2 + matrix[0, 2]**2)
sy = math.sqrt(matrix[1, 0]**2 + matrix[1, 1]**2 + matrix[1, 2]**2)
return sx, sy,
def calculate_insert_bounding_box(insert_entity, doc,src_doc,filename,config,parent_transform=None): def extract_scaling(matrix):
sx = math.sqrt(matrix[0, 0] ** 2 + matrix[0, 1] ** 2 + matrix[0, 2] ** 2)
sy = math.sqrt(matrix[1, 0] ** 2 + matrix[1, 1] ** 2 + matrix[1, 2] ** 2)
return (
sx,
sy,
)
def calculate_insert_bounding_box(
insert_entity, doc, src_doc, filename, config, parent_transform=None
):
""" """
Berechnet die Bounding Box eines INSERTs inklusive Block-Inhalt Berechnet die Bounding Box eines INSERTs inklusive Block-Inhalt
""" """
try: try:
# Block-Definition finden # Block-Definition finden
block_name = insert_entity.dxf.name block_name = insert_entity.dxf.name
src_blk = src_doc.blocks[block_name] src_blk = src_doc.blocks[block_name]
@@ -667,7 +711,6 @@ def calculate_insert_bounding_box(insert_entity, doc,src_doc,filename,config,par
block_def = src_blk block_def = src_blk
# Transformation der INSERT-Entity berechnen # Transformation der INSERT-Entity berechnen
insert_transform = get_insert_transform_matrix(insert_entity) insert_transform = get_insert_transform_matrix(insert_entity)
@@ -682,11 +725,13 @@ def calculate_insert_bounding_box(insert_entity, doc,src_doc,filename,config,par
for block_entity in block_def: for block_entity in block_def:
entity_bbox= get_entity_bounding_box(block_entity, doc,src_doc,filename, config,combined_transform) entity_bbox = get_entity_bounding_box(
if entity_bbox and entity_bbox.has_data: block_entity, doc, src_doc, filename, config, combined_transform
if new_insert: )
dst_blk.add_entity(block_entity.copy()) if entity_bbox and entity_bbox.has_data:
block_bbox.extend(entity_bbox) if new_insert:
dst_blk.add_entity(block_entity.copy())
block_bbox.extend(entity_bbox)
return block_bbox return block_bbox
@@ -703,18 +748,18 @@ def get_insert_transform_matrix(insert_entity):
insert_point = Vec3(insert_entity.dxf.insert) insert_point = Vec3(insert_entity.dxf.insert)
# Skalierung # Skalierung
xscale = getattr(insert_entity.dxf, 'xscale', 1.0) xscale = getattr(insert_entity.dxf, "xscale", 1.0)
yscale = getattr(insert_entity.dxf, 'yscale', 1.0) yscale = getattr(insert_entity.dxf, "yscale", 1.0)
zscale = getattr(insert_entity.dxf, 'zscale', 1.0) zscale = getattr(insert_entity.dxf, "zscale", 1.0)
# Rotation (in Radiant umwandeln) # Rotation (in Radiant umwandeln)
rotation = math.radians(getattr(insert_entity.dxf, 'rotation', 0.0)) rotation = math.radians(getattr(insert_entity.dxf, "rotation", 0.0))
# Transformationsmatrix erstellen # Transformationsmatrix erstellen
matrix = Matrix44.chain( matrix = Matrix44.chain(
Matrix44.scale(xscale, yscale, zscale), Matrix44.scale(xscale, yscale, zscale),
Matrix44.z_rotate(rotation), Matrix44.z_rotate(rotation),
Matrix44.translate(insert_point.x, insert_point.y, insert_point.z) Matrix44.translate(insert_point.x, insert_point.y, insert_point.z),
) )
return matrix return matrix
@@ -759,11 +804,14 @@ def add_bounding_box_to_modelspace(msp, bbox, centered=False):
(right, bottom), (right, bottom),
(right, top), (right, top),
(left, top), (left, top),
(left, bottom) (left, bottom),
] ]
# Roter Punkt in der Mitte # Roter Punkt in der Mitte
msp.add_circle(center=(0.0, 0.0), radius=max(0.5, min(width, height) * 0.01), msp.add_circle(
dxfattribs={"layer": "BOUNDING_BOX", "color": 1}) center=(0.0, 0.0),
radius=max(0.5, min(width, height) * 0.01),
dxfattribs={"layer": "BOUNDING_BOX", "color": 1},
)
else: else:
# Ursprüngliche, nicht-zentrierte Bounding Box # Ursprüngliche, nicht-zentrierte Bounding Box
bbox_points = [ bbox_points = [
@@ -771,7 +819,7 @@ def add_bounding_box_to_modelspace(msp, bbox, centered=False):
(max_pt.x, min_pt.y), (max_pt.x, min_pt.y),
(max_pt.x, max_pt.y), (max_pt.x, max_pt.y),
(min_pt.x, max_pt.y), (min_pt.x, max_pt.y),
(min_pt.x, min_pt.y) (min_pt.x, min_pt.y),
] ]
bbox_poly = msp.add_lwpolyline(bbox_points) bbox_poly = msp.add_lwpolyline(bbox_points)
@@ -779,13 +827,23 @@ def add_bounding_box_to_modelspace(msp, bbox, centered=False):
bbox_poly.dxf.color = 1 # Rot bbox_poly.dxf.color = 1 # Rot
# Text mit Abmessungen # Text mit Abmessungen
text_pos = Vec3(bbox_points[0][0], (bbox_points[2][1] if centered else max_pt.y) + 5, 0) text_pos = Vec3(
msp.add_text(f"Breite: {width:.2f} mm", height=3, bbox_points[0][0], (bbox_points[2][1] if centered else max_pt.y) + 5, 0
dxfattribs={'insert': text_pos, 'layer': "BOUNDING_BOX", 'color': 1}) )
msp.add_text(
f"Breite: {width:.2f} mm",
height=3,
dxfattribs={"insert": text_pos, "layer": "BOUNDING_BOX", "color": 1},
)
text_pos2 = Vec3(bbox_points[0][0], (bbox_points[2][1] if centered else max_pt.y) + 10, 0) text_pos2 = Vec3(
msp.add_text(f"Höhe: {height:.2f} mm", height=3, bbox_points[0][0], (bbox_points[2][1] if centered else max_pt.y) + 10, 0
dxfattribs={'insert': text_pos2, 'layer': "BOUNDING_BOX", 'color': 1}) )
msp.add_text(
f"Höhe: {height:.2f} mm",
height=3,
dxfattribs={"insert": text_pos2, "layer": "BOUNDING_BOX", "color": 1},
)
def format_bounding_box(bbox): def format_bounding_box(bbox):
@@ -801,9 +859,11 @@ def format_bounding_box(bbox):
height = max_pt.y - min_pt.y height = max_pt.y - min_pt.y
depth = max_pt.z - min_pt.z depth = max_pt.z - min_pt.z
return (f"Min: ({min_pt.x:.2f}, {min_pt.y:.2f}, {min_pt.z:.2f}) " return (
f"Max: ({max_pt.x:.2f}, {max_pt.y:.2f}, {max_pt.z:.2f}) " f"Min: ({min_pt.x:.2f}, {min_pt.y:.2f}, {min_pt.z:.2f}) "
f"Größe: {width:.2f} × {height:.2f} × {depth:.2f} mm") f"Max: ({max_pt.x:.2f}, {max_pt.y:.2f}, {max_pt.z:.2f}) "
f"Größe: {width:.2f} × {height:.2f} × {depth:.2f} mm"
)
def analyze_source_dxf_with_blocks(filename): def analyze_source_dxf_with_blocks(filename):
@@ -824,16 +884,16 @@ def analyze_source_dxf_with_blocks(filename):
entity_type = entity.dxftype() entity_type = entity.dxftype()
entity_types[entity_type] = entity_types.get(entity_type, 0) + 1 entity_types[entity_type] = entity_types.get(entity_type, 0) + 1
layer = getattr(entity.dxf, 'layer', '0') layer = getattr(entity.dxf, "layer", "0")
layer_count[layer] = layer_count.get(layer, 0) + 1 layer_count[layer] = layer_count.get(layer, 0) + 1
if entity_type == 'INSERT': if entity_type == "INSERT":
block_name = entity.dxf.name block_name = entity.dxf.name
insert_blocks[block_name] = insert_blocks.get(block_name, 0) + 1 insert_blocks[block_name] = insert_blocks.get(block_name, 0) + 1
# Block-Definitionen analysieren # Block-Definitionen analysieren
for block_name in doc.blocks: for block_name in doc.blocks:
if not block_name.startswith('*'): # Keine Standard-Blöcke if not block_name.startswith("*"): # Keine Standard-Blöcke
block_def = doc.blocks[block_name] block_def = doc.blocks[block_name]
entity_count = len(list(block_def)) entity_count = len(list(block_def))
block_definitions[block_name] = entity_count block_definitions[block_name] = entity_count
@@ -864,11 +924,21 @@ def analyze_source_dxf_with_blocks(filename):
print(f"Fehler bei der Analyse: {e}") print(f"Fehler bei der Analyse: {e}")
return {}, {}, {}, {} return {}, {}, {}, {}
if __name__ == "__main__": if __name__ == "__main__":
# Argumentparser für Kommandozeilenoptionen # Argumentparser für Kommandozeilenoptionen
parser = argparse.ArgumentParser(description="SVG/XML zu DXF Konverter") parser = argparse.ArgumentParser(description="SVG/XML zu DXF Konverter")
parser.add_argument('-i', '--input', type=str, help='Input-Verzeichnis mit SVG/XML-Dateien') parser.add_argument(
parser.add_argument('-n', '--name', required=False, type=str, help='Name der zu erzeugenden Bibliothek (optional, wird sonst abgefragt)', default="test") "-i", "--input", type=str, help="Input-Verzeichnis mit SVG/XML-Dateien"
)
parser.add_argument(
"-n",
"--name",
required=False,
type=str,
help="Name der zu erzeugenden Bibliothek (optional, wird sonst abgefragt)",
default="test",
)
if len(sys.argv) == 2 and sys.argv[1] in ("-h", "--help"): if len(sys.argv) == 2 and sys.argv[1] in ("-h", "--help"):
parser.print_help() parser.print_help()
@@ -877,12 +947,14 @@ if __name__ == "__main__":
args = parser.parse_args() args = parser.parse_args()
if not args.name: if not args.name:
args.name = input("Bitte Namen der zu erzeugenden Bibliothek eingeben: ").strip() args.name = input(
"Bitte Namen der zu erzeugenden Bibliothek eingeben: "
).strip()
if not args.name: if not args.name:
print("Fehler: Kein Name angegeben. Beende.") print("Fehler: Kein Name angegeben. Beende.")
sys.exit(1) sys.exit(1)
# Verzeichnisse über Umgebungsvariablen oder Fallback # Verzeichnisse über Umgebungsvariablen oder Fallback
if args.input: if args.input:
INPUT_DIR = Path(args.input) INPUT_DIR = Path(args.input)
print(f"Verwende Input-Verzeichnis: {INPUT_DIR} \n") print(f"Verwende Input-Verzeichnis: {INPUT_DIR} \n")
@@ -890,7 +962,9 @@ if __name__ == "__main__":
INPUT_DIR = check_environment_var("PROJECT_DATA") / "omniflo" INPUT_DIR = check_environment_var("PROJECT_DATA") / "omniflo"
print(f"Kein Input-Verzeichnis angegeben, verwende Standard: {INPUT_DIR} \n") print(f"Kein Input-Verzeichnis angegeben, verwende Standard: {INPUT_DIR} \n")
OUTPUT_FILE = check_environment_var("PROJECT_DATA") / "block_libraries" / f"{args.name}.dxf" OUTPUT_FILE = (
check_environment_var("PROJECT_DATA") / "block_libraries" / f"{args.name}.dxf"
)
# Prüfe und erstelle log-Verzeichnis falls nötig # Prüfe und erstelle log-Verzeichnis falls nötig
log_dir = check_environment_var("PROJECT_LOG") log_dir = check_environment_var("PROJECT_LOG")
@@ -899,9 +973,9 @@ if __name__ == "__main__":
print(f"Log-Verzeichnis erstellt: {log_dir}") print(f"Log-Verzeichnis erstellt: {log_dir}")
# Logger Setup # Logger Setup
log_file = Path(os.environ['PROJECT_LOG']) / 'dxf2lib.log' log_file = Path(os.environ["PROJECT_LOG"]) / "dxf2lib.log"
file_handler = logging.FileHandler(str(log_file), 'a', 'utf-8') file_handler = logging.FileHandler(str(log_file), "a", "utf-8")
logger = setup_logger(log_dir, name='dxf2lib') logger = setup_logger(log_dir, name="dxf2lib")
logger.info("=== DXF2LIB Verarbeitung gestartet ===") logger.info("=== DXF2LIB Verarbeitung gestartet ===")
logger.info(f"Input-Verzeichnis: {INPUT_DIR}") logger.info(f"Input-Verzeichnis: {INPUT_DIR}")
logger.info(f"Output-Datei: {OUTPUT_FILE}") logger.info(f"Output-Datei: {OUTPUT_FILE}")
+214
View File
@@ -0,0 +1,214 @@
"""
Handler Context für DXF-Elementgenerierung.
Vereinfacht die Aufrufe der handle-Funktionen und bietet Debug-Unterstützung.
"""
class HandlerContext:
"""
Kontextobjekt für Handler-Funktionsaufrufe.
Speichert alle Parameter für handle-Funktionen und bietet:
- Vereinfachte Aufrufe
- Schöne String-Repräsentation für Debugging
- Einfachen Zugriff auf alle Parameter
"""
def __init__(
self,
msp,
teileid,
merkmale,
x,
y,
doc,
lib_doc,
verbose=False,
symbols=None,
strecken_nachbarn=None,
config=None,
config_allgemein=None,
):
self.msp = msp
self.teileid = teileid
self.merkmale = merkmale if merkmale is not None else {}
self.x = x
self.y = y
self.doc = doc
self.lib_doc = lib_doc
self.verbose = verbose
self.symbols = symbols if symbols is not None else []
self.strecken_nachbarn = (
strecken_nachbarn if strecken_nachbarn is not None else []
)
self.config = config
self.config_allgemein = config_allgemein
def call(self, handler_func):
"""
Ruft eine Handler-Funktion mit allen gespeicherten Parametern auf.
Args:
handler_func: Die Handler-Funktion (z.B. handle_ils_2_0_kreisel)
Returns:
Rückgabewert der Handler-Funktion
"""
return handler_func(
self.msp,
self.teileid,
self.merkmale,
self.x,
self.y,
self.doc,
self.lib_doc,
self.verbose,
self.symbols,
self.strecken_nachbarn,
self.config,
self.config_allgemein,
)
def __str__(self):
"""String-Repräsentation für Debugging."""
lines = [
"=" * 80,
"HandlerContext:",
"=" * 80,
f"TeileId: {self.teileid}",
f"Position: x={self.x:.2f}, y={self.y:.2f}",
f"Verbose: {self.verbose}",
"-" * 80,
"Merkmale:",
]
if self.merkmale:
for key, value in self.merkmale.items():
lines.append(f" {key:20s}: {value}")
else:
lines.append(" (keine)")
lines.append("-" * 80)
lines.append(f"Symbols: {len(self.symbols)} Einträge")
if self.symbols:
for i, sym in enumerate(self.symbols, 1):
lines.append(f" [{i}] {sym}")
lines.append("-" * 80)
lines.append(f"Nachbarn: {len(self.strecken_nachbarn)} Einträge")
lines.append("-" * 80)
lines.append(f"doc: {type(self.doc).__name__}")
lines.append(
f"lib_doc: {type(self.lib_doc).__name__ if self.lib_doc else 'None'}"
)
lines.append(f"msp: {type(self.msp).__name__}")
lines.append(f"config: {'vorhanden' if self.config else 'None'}")
lines.append(f"config_allg: {'vorhanden' if self.config_allgemein else 'None'}")
lines.append("=" * 80)
return "\n".join(lines)
def __repr__(self):
"""Kurze Repräsentation."""
return (
f"HandlerContext(teileid={self.teileid!r}, "
f"x={self.x:.2f}, y={self.y:.2f}, "
f"merkmale={len(self.merkmale)} items)"
)
def to_dict(self):
"""
Gibt alle Parameter als Dictionary zurück (ohne Objekt-Referenzen).
Nützlich für Logging oder Serialisierung.
"""
return {
"teileid": self.teileid,
"x": self.x,
"y": self.y,
"verbose": self.verbose,
"merkmale": self.merkmale.copy(),
"symbols_count": len(self.symbols),
"symbols": self.symbols,
"nachbarn_count": len(self.strecken_nachbarn),
"has_config": self.config is not None,
"has_config_allgemein": self.config_allgemein is not None,
"has_lib_doc": self.lib_doc is not None,
}
@property
def position(self):
"""Gibt Position als Tuple zurück."""
return (self.x, self.y)
@property
def has_library(self):
"""Prüft, ob eine Bibliothek verfügbar ist."""
return self.lib_doc is not None
def get_merkmal(self, key, default=None):
"""
Holt ein Merkmal mit Fallback-Wert.
Args:
key: Merkmal-Schlüssel
default: Standardwert, falls Merkmal nicht existiert
Returns:
Merkmalwert oder default
"""
return self.merkmale.get(key, default)
def create_context_from_row(
row,
msp,
doc,
lib_doc,
strecken_nachbarn,
config,
config_allgemein,
symbols=None,
verbose=False,
):
"""
Factory-Funktion: Erstellt HandlerContext aus einer CSV-Zeile.
Args:
row: Dictionary mit CSV-Daten
msp: Modelspace
doc: DXF-Dokument
lib_doc: Bibliotheks-Dokument
strecken_nachbarn: Liste der Nachbarn
config: Config-Parser
config_allgemein: Allgemeine Config
symbols: Symbol-Liste (optional)
verbose: Debug-Modus (optional)
Returns:
HandlerContext-Instanz
"""
from arbeiten_mit_csv import parse_merkmale, extract_coords
bezeichner = row["Bezeichnung"].strip()
teileid = row["TeileId"].strip()
planquadrat = row["Planquadrat"]
merkmale = parse_merkmale(row.get("Merkmale", ""))
merkmale["bezeichner"] = bezeichner
x, y = extract_coords(planquadrat)
return HandlerContext(
msp=msp,
teileid=teileid,
merkmale=merkmale,
x=x,
y=y,
doc=doc,
lib_doc=lib_doc,
verbose=verbose,
symbols=symbols if symbols is not None else [],
strecken_nachbarn=strecken_nachbarn,
config=config,
config_allgemein=config_allgemein,
)
+1 -1
View File
@@ -7,7 +7,7 @@ def inspect_blocks(dxf_path):
print(f"Datei: {dxf_path}") print(f"Datei: {dxf_path}")
print("Gefundene Blöcke und Attribute:\n") print("Gefundene Blöcke und Attribute:\n")
for block in doc.blocks: for block in doc.blocks:
if block.name.startswith('*'): # Überspringe anonyme/Standardblöcke if block.name.startswith("*"): # Überspringe anonyme/Standardblöcke
continue continue
print(f"Block: {block.name}") print(f"Block: {block.name}")
attribs = [e for e in block if e.dxftype() == "ATTDEF"] attribs = [e for e in block if e.dxftype() == "ATTDEF"]
+1140 -406
View File
File diff suppressed because it is too large Load Diff
+212 -67
View File
@@ -4,6 +4,7 @@ import difflib
from utils import check_environment_var, setup_logger from utils import check_environment_var, setup_logger
import plant2dxf import plant2dxf
class TestDXFGeometry(unittest.TestCase): class TestDXFGeometry(unittest.TestCase):
testordner_path = Path(check_environment_var("PROJECT_TEST")) testordner_path = Path(check_environment_var("PROJECT_TEST"))
lib_path = Path(check_environment_var("PROJECT_DATA")) lib_path = Path(check_environment_var("PROJECT_DATA"))
@@ -13,7 +14,25 @@ class TestDXFGeometry(unittest.TestCase):
cfg_path = config_dir / "shapes.cfg" cfg_path = config_dir / "shapes.cfg"
allgemein_cfg_path = config_dir / "allgemein.cfg" allgemein_cfg_path = config_dir / "allgemein.cfg"
GEOM_CODES = {"0", "8", "10", "20", "30", "11", "21", "31", "41", "42", "43", "70", "71", "72", "73", "74", "75"} GEOM_CODES = {
"0",
"8",
"10",
"20",
"30",
"11",
"21",
"31",
"41",
"42",
"43",
"70",
"71",
"72",
"73",
"74",
"75",
}
def extract_geometry_lines(self, file_path): def extract_geometry_lines(self, file_path):
""" """
@@ -39,125 +58,251 @@ class TestDXFGeometry(unittest.TestCase):
geom1 = self.extract_geometry_lines(file1) geom1 = self.extract_geometry_lines(file1)
geom2 = self.extract_geometry_lines(file2) geom2 = self.extract_geometry_lines(file2)
if geom1 != geom2: if geom1 != geom2:
diff = "".join(difflib.unified_diff(geom1, geom2, fromfile=str(file1), tofile=str(file2))) diff = "".join(
difflib.unified_diff(
geom1, geom2, fromfile=str(file1), tofile=str(file2)
)
)
raise AssertionError(f"Geometrische Daten unterscheiden sich:\n{diff}") raise AssertionError(f"Geometrische Daten unterscheiden sich:\n{diff}")
def test_omniflobogen_dxf_file(self): def test_omniflobogen_dxf_file(self):
omniflo_bogen = "omniflo_bogen" omniflo_bogen = "omniflo_bogen"
omniflo_bogen_csv = self.testordner_path / f"{omniflo_bogen}.csv" omniflo_bogen_csv = self.testordner_path / f"{omniflo_bogen}.csv"
omniflo_bogen_dxf = f"{omniflo_bogen}.dxf" omniflo_bogen_dxf = f"{omniflo_bogen}.dxf"
omniflo_bogen_jason = self.work_dir / f"{omniflo_bogen}.jason" omniflo_bogen_json = self.work_dir / f"{omniflo_bogen}.json"
omniflo_bogen_output = self.work_dir / omniflo_bogen_dxf omniflo_bogen_output = self.work_dir / omniflo_bogen_dxf
omniflo_bogen_reference = self.testordner_path / omniflo_bogen_dxf omniflo_bogen_reference = self.testordner_path / omniflo_bogen_dxf
plant2dxf.main(omniflo_bogen_csv , self.default_lib_path, self.cfg_path, self.allgemein_cfg_path, omniflo_bogen_output,omniflo_bogen_jason) plant2dxf.main(
omniflo_bogen_csv,
self.default_lib_path,
self.cfg_path,
self.allgemein_cfg_path,
omniflo_bogen_output,
omniflo_bogen_json,
)
self.assert_dxf_geometry_equal(omniflo_bogen_output, omniflo_bogen_reference) self.assert_dxf_geometry_equal(omniflo_bogen_output, omniflo_bogen_reference)
def test_weiche_90_dxf_file(self): def test_weiche_90_dxf_file(self):
weiche_90= "weiche_90" weiche_90 = "weiche_90"
weiche_90_csv = self.testordner_path / f"{weiche_90}.csv" weiche_90_csv = self.testordner_path / f"{weiche_90}.csv"
weiche_90_dxf = f"{weiche_90}.dxf" weiche_90_dxf = f"{weiche_90}.dxf"
weiche_90_jason = self.work_dir /f"{weiche_90}.jason" weiche_90_json = self.work_dir / f"{weiche_90}.json"
weiche_90_output = self.work_dir / weiche_90_dxf weiche_90_output = self.work_dir / weiche_90_dxf
weiche_90_reference = self.testordner_path / weiche_90_dxf weiche_90_reference = self.testordner_path / weiche_90_dxf
plant2dxf.main(weiche_90_csv , self.default_lib_path, self.cfg_path, self.allgemein_cfg_path, weiche_90_output,weiche_90_jason) plant2dxf.main(
weiche_90_csv,
self.default_lib_path,
self.cfg_path,
self.allgemein_cfg_path,
weiche_90_output,
weiche_90_json,
)
self.assert_dxf_geometry_equal(weiche_90_output, weiche_90_reference) self.assert_dxf_geometry_equal(weiche_90_output, weiche_90_reference)
def test_weiche_45_simple_dxf_file(self): def test_weiche_45_simple_dxf_file(self):
weiche_45_simple= "weiche_45_simple" weiche_45_simple = "weiche_45_simple"
weiche_45_simple_csv = self.testordner_path / f"{weiche_45_simple}.csv" weiche_45_simple_csv = self.testordner_path / f"{weiche_45_simple}.csv"
weiche_45_simple_dxf = f"{weiche_45_simple}.dxf" weiche_45_simple_dxf = f"{weiche_45_simple}.dxf"
weiche_45_simple_jason = self.work_dir/ f"{weiche_45_simple}.jason" weiche_45_simple_json = self.work_dir / f"{weiche_45_simple}.json"
weiche_45_simple_output = self.work_dir / weiche_45_simple_dxf weiche_45_simple_output = self.work_dir / weiche_45_simple_dxf
weiche_45_simple_reference = self.testordner_path / weiche_45_simple_dxf weiche_45_simple_reference = self.testordner_path / weiche_45_simple_dxf
plant2dxf.main(weiche_45_simple_csv , self.default_lib_path, self.cfg_path, self.allgemein_cfg_path, weiche_45_simple_output,weiche_45_simple_jason) plant2dxf.main(
self.assert_dxf_geometry_equal(weiche_45_simple_output, weiche_45_simple_reference) weiche_45_simple_csv,
self.default_lib_path,
self.cfg_path,
self.allgemein_cfg_path,
weiche_45_simple_output,
weiche_45_simple_json,
)
self.assert_dxf_geometry_equal(
weiche_45_simple_output, weiche_45_simple_reference
)
def test_weiche_45_doppel_dxf_file(self): def test_weiche_45_doppel_dxf_file(self):
weiche_45_doppel= "weiche_45_doppel" weiche_45_doppel = "weiche_45_doppel"
weiche_45_doppel_csv = self.testordner_path / f"{weiche_45_doppel}.csv" weiche_45_doppel_csv = self.testordner_path / f"{weiche_45_doppel}.csv"
weiche_45_doppel_dxf = f"{weiche_45_doppel}.dxf" weiche_45_doppel_dxf = f"{weiche_45_doppel}.dxf"
weiche_45_doppel_jason = self.work_dir /f"{weiche_45_doppel}.jason" weiche_45_doppel_json = self.work_dir / f"{weiche_45_doppel}.json"
weiche_45_doppel_output = self.work_dir / weiche_45_doppel_dxf weiche_45_doppel_output = self.work_dir / weiche_45_doppel_dxf
weiche_45_doppel_reference = self.testordner_path / weiche_45_doppel_dxf weiche_45_doppel_reference = self.testordner_path / weiche_45_doppel_dxf
plant2dxf.main(weiche_45_doppel_csv , self.default_lib_path, self.cfg_path, self.allgemein_cfg_path, weiche_45_doppel_output,weiche_45_doppel_jason) plant2dxf.main(
self.assert_dxf_geometry_equal(weiche_45_doppel_output, weiche_45_doppel_reference) weiche_45_doppel_csv,
self.default_lib_path,
self.cfg_path,
self.allgemein_cfg_path,
weiche_45_doppel_output,
weiche_45_doppel_json,
)
self.assert_dxf_geometry_equal(
weiche_45_doppel_output, weiche_45_doppel_reference
)
def test_weiche_45_dreiwege_dxf_file(self): def test_weiche_45_dreiwege_dxf_file(self):
weiche_45_dreiwege= "weiche_45_dreiwege" weiche_45_dreiwege = "weiche_45_dreiwege"
weiche_45_dreiwege_csv = self.testordner_path / f"{weiche_45_dreiwege}.csv" weiche_45_dreiwege_csv = self.testordner_path / f"{weiche_45_dreiwege}.csv"
weiche_45_dreiwege_dxf = f"{weiche_45_dreiwege}.dxf" weiche_45_dreiwege_dxf = f"{weiche_45_dreiwege}.dxf"
weiche_45_dreiwege_jason = self.work_dir /f"{weiche_45_dreiwege}.jason" weiche_45_dreiwege_json = self.work_dir / f"{weiche_45_dreiwege}.json"
weiche_45_dreiwege_output = self.work_dir / weiche_45_dreiwege_dxf weiche_45_dreiwege_output = self.work_dir / weiche_45_dreiwege_dxf
weiche_45_dreiwege_reference = self.testordner_path / weiche_45_dreiwege_dxf weiche_45_dreiwege_reference = self.testordner_path / weiche_45_dreiwege_dxf
plant2dxf.main(weiche_45_dreiwege_csv , self.default_lib_path, self.cfg_path, self.allgemein_cfg_path, weiche_45_dreiwege_output,weiche_45_dreiwege_jason) plant2dxf.main(
self.assert_dxf_geometry_equal(weiche_45_dreiwege_output, weiche_45_dreiwege_reference) weiche_45_dreiwege_csv,
self.default_lib_path,
self.cfg_path,
self.allgemein_cfg_path,
weiche_45_dreiwege_output,
weiche_45_dreiwege_json,
)
self.assert_dxf_geometry_equal(
weiche_45_dreiwege_output, weiche_45_dreiwege_reference
)
def test_weichenkoerper_dxf_file(self): def test_weichenkoerper_dxf_file(self):
weichenkoerper= "weichenkoerper" weichenkoerper = "weichenkoerper"
weichenkoerper_csv = self.testordner_path / f"{weichenkoerper}.csv" weichenkoerper_csv = self.testordner_path / f"{weichenkoerper}.csv"
weichenkoerper_dxf = f"{weichenkoerper}.dxf" weichenkoerper_dxf = f"{weichenkoerper}.dxf"
weichenkoerper_jason = self.work_dir /f"{weichenkoerper}.jason" weichenkoerper_json = self.work_dir / f"{weichenkoerper}.json"
weichenkoerper_output = self.work_dir / weichenkoerper_dxf weichenkoerper_output = self.work_dir / weichenkoerper_dxf
weichenkoerper_reference = self.testordner_path / weichenkoerper_dxf weichenkoerper_reference = self.testordner_path / weichenkoerper_dxf
plant2dxf.main(weichenkoerper_csv , self.default_lib_path, self.cfg_path, self.allgemein_cfg_path, weichenkoerper_output,weichenkoerper_jason) plant2dxf.main(
weichenkoerper_csv,
self.default_lib_path,
self.cfg_path,
self.allgemein_cfg_path,
weichenkoerper_output,
weichenkoerper_json,
)
self.assert_dxf_geometry_equal(weichenkoerper_output, weichenkoerper_reference) self.assert_dxf_geometry_equal(weichenkoerper_output, weichenkoerper_reference)
def test_weichenkombination_dxf_file(self): def test_weichenkombination_dxf_file(self):
weichenkombination= "weichenkombination" weichenkombination = "weichenkombination"
weichenkombination_csv = self.testordner_path / f"{weichenkombination}.csv" weichenkombination_csv = self.testordner_path / f"{weichenkombination}.csv"
weichenkombination_dxf = f"{weichenkombination}.dxf" weichenkombination_dxf = f"{weichenkombination}.dxf"
weichenkombination_jason = self.work_dir /f"{weichenkombination}.jason" weichenkombination_json = self.work_dir / f"{weichenkombination}.json"
weichenkombination_output = self.work_dir / weichenkombination_dxf weichenkombination_output = self.work_dir / weichenkombination_dxf
weichenkombination_reference = self.testordner_path / weichenkombination_dxf weichenkombination_reference = self.testordner_path / weichenkombination_dxf
plant2dxf.main(weichenkombination_csv , self.default_lib_path, self.cfg_path, self.allgemein_cfg_path, weichenkombination_output,weichenkombination_jason) plant2dxf.main(
self.assert_dxf_geometry_equal(weichenkombination_output, weichenkombination_reference) weichenkombination_csv,
self.default_lib_path,
self.cfg_path,
self.allgemein_cfg_path,
weichenkombination_output,
weichenkombination_json,
)
self.assert_dxf_geometry_equal(
weichenkombination_output, weichenkombination_reference
)
def test_gefaelle_dxf_file(self): def test_gefaelle_dxf_file(self):
gefaelle= "gefaelle" gefaelle = "gefaelle"
gefaelle_csv = self.testordner_path / f"{gefaelle}.csv" gefaelle_csv = self.testordner_path / f"{gefaelle}.csv"
gefaelle_dxf = f"{gefaelle}.dxf" gefaelle_dxf = f"{gefaelle}.dxf"
gefaelle_jason = self.work_dir /f"{gefaelle}.jason" gefaelle_json = self.work_dir / f"{gefaelle}.json"
weichenkombination_output = self.work_dir / gefaelle_dxf weichenkombination_output = self.work_dir / gefaelle_dxf
weichenkombination_reference = self.testordner_path / gefaelle_dxf weichenkombination_reference = self.testordner_path / gefaelle_dxf
plant2dxf.main(gefaelle_csv , self.default_lib_path, self.cfg_path, self.allgemein_cfg_path, weichenkombination_output,gefaelle_jason) plant2dxf.main(
self.assert_dxf_geometry_equal(weichenkombination_output, weichenkombination_reference) gefaelle_csv,
self.default_lib_path,
self.cfg_path,
self.allgemein_cfg_path,
weichenkombination_output,
gefaelle_json,
)
self.assert_dxf_geometry_equal(
weichenkombination_output, weichenkombination_reference
)
def test_gefaelle_ausnahme_gleiche_orientierung_dxf_file(self): def test_gefaelle_ausnahme_gleiche_orientierung_dxf_file(self):
gefaelle_ausnahme_gleiche_orientierung= "gefaelle_ausnahme_gleiche_orientierung" gefaelle_ausnahme_gleiche_orientierung = (
gefaelle_ausnahme_gleiche_orientierung_csv = self.testordner_path / f"{gefaelle_ausnahme_gleiche_orientierung}.csv" "gefaelle_ausnahme_gleiche_orientierung"
gefaelle_ausnahme_gleiche_orientierung_dxf = f"{gefaelle_ausnahme_gleiche_orientierung}.dxf" )
gefaelle_ausnahme_gleiche_orientierung_jason = self.work_dir /f"{gefaelle_ausnahme_gleiche_orientierung}.jason" gefaelle_ausnahme_gleiche_orientierung_csv = (
gefaelle_ausnahme_gleiche_orientierung_output = self.work_dir / gefaelle_ausnahme_gleiche_orientierung_dxf self.testordner_path / f"{gefaelle_ausnahme_gleiche_orientierung}.csv"
gefaelle_ausnahme_gleiche_orientierung_reference = self.testordner_path / gefaelle_ausnahme_gleiche_orientierung_dxf )
plant2dxf.main(gefaelle_ausnahme_gleiche_orientierung_csv , self.default_lib_path, self.cfg_path, self.allgemein_cfg_path, gefaelle_ausnahme_gleiche_orientierung_output,gefaelle_ausnahme_gleiche_orientierung_jason) gefaelle_ausnahme_gleiche_orientierung_dxf = (
self.assert_dxf_geometry_equal(gefaelle_ausnahme_gleiche_orientierung_output, gefaelle_ausnahme_gleiche_orientierung_reference) f"{gefaelle_ausnahme_gleiche_orientierung}.dxf"
)
gefaelle_ausnahme_gleiche_orientierung_json = (
self.work_dir / f"{gefaelle_ausnahme_gleiche_orientierung}.json"
)
gefaelle_ausnahme_gleiche_orientierung_output = (
self.work_dir / gefaelle_ausnahme_gleiche_orientierung_dxf
)
gefaelle_ausnahme_gleiche_orientierung_reference = (
self.testordner_path / gefaelle_ausnahme_gleiche_orientierung_dxf
)
plant2dxf.main(
gefaelle_ausnahme_gleiche_orientierung_csv,
self.default_lib_path,
self.cfg_path,
self.allgemein_cfg_path,
gefaelle_ausnahme_gleiche_orientierung_output,
gefaelle_ausnahme_gleiche_orientierung_json,
)
self.assert_dxf_geometry_equal(
gefaelle_ausnahme_gleiche_orientierung_output,
gefaelle_ausnahme_gleiche_orientierung_reference,
)
def test_gefaelle_ausnahme_unterschiedlich_orientierung_dxf_file(self): def test_gefaelle_ausnahme_unterschiedlich_orientierung_dxf_file(self):
gefaelle_ausnahme_unterschiedlich_orientierung= "gefaelle_ausnahme_unterschiedlich_orientierung" gefaelle_ausnahme_unterschiedlich_orientierung = (
gefaelle_ausnahme_unterschiedlich_orientierung_csv = self.testordner_path / f"{gefaelle_ausnahme_unterschiedlich_orientierung}.csv" "gefaelle_ausnahme_unterschiedlich_orientierung"
gefaelle_ausnahme_unterschiedlich_orientierung_dxf = f"{gefaelle_ausnahme_unterschiedlich_orientierung}.dxf" )
gefaelle_ausnahme_unterschiedlich_orientierung_jason = self.work_dir /f"{gefaelle_ausnahme_unterschiedlich_orientierung}.jason" gefaelle_ausnahme_unterschiedlich_orientierung_csv = (
gefaelle_ausnahme_unterschiedlich_orientierung_output = self.work_dir / gefaelle_ausnahme_unterschiedlich_orientierung_dxf self.testordner_path
gefaelle_ausnahme_unterschiedlich_orientierung_reference = self.testordner_path / gefaelle_ausnahme_unterschiedlich_orientierung_dxf / f"{gefaelle_ausnahme_unterschiedlich_orientierung}.csv"
plant2dxf.main(gefaelle_ausnahme_unterschiedlich_orientierung_csv , self.default_lib_path, self.cfg_path, self.allgemein_cfg_path, gefaelle_ausnahme_unterschiedlich_orientierung_output,gefaelle_ausnahme_unterschiedlich_orientierung_jason) )
self.assert_dxf_geometry_equal(gefaelle_ausnahme_unterschiedlich_orientierung_output, gefaelle_ausnahme_unterschiedlich_orientierung_reference) gefaelle_ausnahme_unterschiedlich_orientierung_dxf = (
f"{gefaelle_ausnahme_unterschiedlich_orientierung}.dxf"
)
gefaelle_ausnahme_unterschiedlich_orientierung_json = (
self.work_dir / f"{gefaelle_ausnahme_unterschiedlich_orientierung}.json"
)
gefaelle_ausnahme_unterschiedlich_orientierung_output = (
self.work_dir / gefaelle_ausnahme_unterschiedlich_orientierung_dxf
)
gefaelle_ausnahme_unterschiedlich_orientierung_reference = (
self.testordner_path / gefaelle_ausnahme_unterschiedlich_orientierung_dxf
)
plant2dxf.main(
gefaelle_ausnahme_unterschiedlich_orientierung_csv,
self.default_lib_path,
self.cfg_path,
self.allgemein_cfg_path,
gefaelle_ausnahme_unterschiedlich_orientierung_output,
gefaelle_ausnahme_unterschiedlich_orientierung_json,
)
self.assert_dxf_geometry_equal(
gefaelle_ausnahme_unterschiedlich_orientierung_output,
gefaelle_ausnahme_unterschiedlich_orientierung_reference,
)
def test_gefaelle_einzeln_verbunden_dxf_file(self): def test_gefaelle_einzeln_verbunden_dxf_file(self):
gefaelle_einzeln_verbunden= "gefaelle_einzeln_verbunden" gefaelle_einzeln_verbunden = "gefaelle_einzeln_verbunden"
gefaelle_einzeln_verbunden_csv = self.testordner_path / f"{gefaelle_einzeln_verbunden}.csv" gefaelle_einzeln_verbunden_csv = (
self.testordner_path / f"{gefaelle_einzeln_verbunden}.csv"
)
gefaelle_einzeln_verbunden_dxf = f"{gefaelle_einzeln_verbunden}.dxf" gefaelle_einzeln_verbunden_dxf = f"{gefaelle_einzeln_verbunden}.dxf"
gefaelle_einzeln_verbunden_jason = self.work_dir /f"{gefaelle_einzeln_verbunden}.jason" gefaelle_einzeln_verbunden_json = (
gefaelle_einzeln_verbunden_output = self.work_dir / gefaelle_einzeln_verbunden_dxf self.work_dir / f"{gefaelle_einzeln_verbunden}.json"
gefaelle_einzeln_verbunden_reference = self.testordner_path / gefaelle_einzeln_verbunden_dxf )
plant2dxf.main(gefaelle_einzeln_verbunden_csv , self.default_lib_path, self.cfg_path, self.allgemein_cfg_path, gefaelle_einzeln_verbunden_output,gefaelle_einzeln_verbunden_jason) gefaelle_einzeln_verbunden_output = (
self.assert_dxf_geometry_equal(gefaelle_einzeln_verbunden_output, gefaelle_einzeln_verbunden_reference) self.work_dir / gefaelle_einzeln_verbunden_dxf
)
gefaelle_einzeln_verbunden_reference = (
self.testordner_path / gefaelle_einzeln_verbunden_dxf
)
plant2dxf.main(
gefaelle_einzeln_verbunden_csv,
self.default_lib_path,
self.cfg_path,
self.allgemein_cfg_path,
gefaelle_einzeln_verbunden_output,
gefaelle_einzeln_verbunden_json,
)
self.assert_dxf_geometry_equal(
gefaelle_einzeln_verbunden_output, gefaelle_einzeln_verbunden_reference
)
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()
+4 -3
View File
@@ -14,7 +14,7 @@ def check_environment_var(env_str: str) -> Path:
sys.exit(1) sys.exit(1)
def setup_logger(log_dir: Path, name: str = 'app') -> logging.Logger: def setup_logger(log_dir: Path, name: str = "app") -> logging.Logger:
""" """
Erstellt und konfiguriert einen Logger, der sowohl in eine Datei als auch auf die Konsole schreibt. Erstellt und konfiguriert einen Logger, der sowohl in eine Datei als auch auf die Konsole schreibt.
Die Logdatei erhält einen Zeitstempel im Namen und ist UTF-8 kodiert. Die Logdatei erhält einen Zeitstempel im Namen und ist UTF-8 kodiert.
@@ -26,6 +26,7 @@ def setup_logger(log_dir: Path, name: str = 'app') -> logging.Logger:
logging.Logger: Konfigurierter Logger logging.Logger: Konfigurierter Logger
""" """
from datetime import datetime from datetime import datetime
logger = logging.getLogger(name) logger = logging.getLogger(name)
logger.setLevel(logging.INFO) logger.setLevel(logging.INFO)
@@ -38,7 +39,7 @@ def setup_logger(log_dir: Path, name: str = 'app') -> logging.Logger:
# Logdatei mit Zeitstempel im Namen erzeugen # Logdatei mit Zeitstempel im Namen erzeugen
log_file = log_dir / f"{name}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log" log_file = log_dir / f"{name}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log"
file_handler = logging.FileHandler(log_file, encoding='utf-8') file_handler = logging.FileHandler(log_file, encoding="utf-8")
file_handler.setLevel(logging.INFO) file_handler.setLevel(logging.INFO)
# Handler für die Konsole # Handler für die Konsole
@@ -46,7 +47,7 @@ def setup_logger(log_dir: Path, name: str = 'app') -> logging.Logger:
console_handler.setLevel(logging.INFO) console_handler.setLevel(logging.INFO)
# Einheitliches Log-Format definieren # Einheitliches Log-Format definieren
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
file_handler.setFormatter(formatter) file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter) console_handler.setFormatter(formatter)