alles neu mit black formatiert. handler_context.py impl. um weniger Übergabeparameter zu haben
This commit is contained in:
+111
-62
@@ -1,29 +1,36 @@
|
||||
|
||||
from ezdxf.entities import Line
|
||||
import math
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
from typing import Optional
|
||||
import plant2dxf
|
||||
import plant2dxf
|
||||
import block_methoden
|
||||
|
||||
|
||||
ATTR_TAG = "TeileId" # Attributtag im Block
|
||||
RADIUS = 400 # Radius der Kreiselkreise (mm)
|
||||
ATTR_TAG = "TeileId" # Attributtag im Block
|
||||
RADIUS = 400 # Radius der Kreiselkreise (mm)
|
||||
|
||||
|
||||
class Kreisel(BaseModel):
|
||||
"""Pydantic-Modell für Kreisel-Komponenten."""
|
||||
|
||||
teileid: str
|
||||
x: float = Field(description="X-Koordinate des Kreisel-Zentrums")
|
||||
y: float = Field(description="Y-Koordinate des Kreisel-Zentrums")
|
||||
hoehe: float = Field(description="Höhe in mm")
|
||||
drehung: float = Field(default=0.0, description="Drehung/Winkel in Grad")
|
||||
drehrichtung: Optional[str] = Field(default=None, description="Drehrichtung: UZS oder GUZS")
|
||||
abstand: float = Field(default=20000.0, description="Abstand zwischen Kreiselachsen in mm")
|
||||
kreiselart: Optional[str] = Field(default=None, description="Kreiselart, z.B. 'Pin'")
|
||||
drehrichtung: Optional[str] = Field(
|
||||
default=None, description="Drehrichtung: UZS oder GUZS"
|
||||
)
|
||||
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_separatoren: float = Field(default=0.0, description="Anzahl der Separatoren")
|
||||
|
||||
@field_validator('abstand')
|
||||
|
||||
@field_validator("abstand")
|
||||
@classmethod
|
||||
def validate_abstand(cls, v):
|
||||
"""Konvertiert Abstand von Meter zu mm, falls nötig."""
|
||||
@@ -34,8 +41,8 @@ class Kreisel(BaseModel):
|
||||
except ValueError:
|
||||
v = 10000.0 # Fallback 10 m
|
||||
return v
|
||||
|
||||
@field_validator('hoehe')
|
||||
|
||||
@field_validator("hoehe")
|
||||
@classmethod
|
||||
def validate_hoehe(cls, v):
|
||||
"""Konvertiert Höhe von Meter zu mm, falls nötig."""
|
||||
@@ -46,12 +53,12 @@ class Kreisel(BaseModel):
|
||||
except ValueError:
|
||||
v = 0.0
|
||||
return v
|
||||
|
||||
|
||||
@property
|
||||
def halbabstand(self) -> float:
|
||||
"""Halbabstand zwischen den beiden Blöcken."""
|
||||
return self.abstand / 2
|
||||
|
||||
|
||||
@property
|
||||
def winkel_rad(self) -> float:
|
||||
"""Winkel in Radianten für Berechnungen."""
|
||||
@@ -59,62 +66,66 @@ class Kreisel(BaseModel):
|
||||
return math.radians(self.drehung)
|
||||
else:
|
||||
return math.radians(self.drehung - 180)
|
||||
|
||||
|
||||
@property
|
||||
def richtung_rad(self) -> float:
|
||||
"""Richtung in Radianten (für am_kreisel_direct_verbunden)."""
|
||||
# Wird aus drehung abgeleitet oder separat gesetzt
|
||||
return math.radians(self.drehung)
|
||||
|
||||
|
||||
@property
|
||||
def pos1(self) -> tuple[float, float, float]:
|
||||
"""Position des ersten Blocks (x, y, z)."""
|
||||
dx = self.halbabstand * math.cos(self.winkel_rad)
|
||||
dy = self.halbabstand * math.sin(self.winkel_rad)
|
||||
return (self.x - dx, self.y - dy, self.hoehe)
|
||||
|
||||
|
||||
@property
|
||||
def pos2(self) -> tuple[float, float, float]:
|
||||
"""Position des zweiten Blocks (x, y, z)."""
|
||||
dx = self.halbabstand * math.cos(self.winkel_rad)
|
||||
dy = self.halbabstand * math.sin(self.winkel_rad)
|
||||
return (self.x + dx, self.y + dy, self.hoehe)
|
||||
|
||||
|
||||
@property
|
||||
def z(self) -> float:
|
||||
"""Z-Koordinate (gleich der Höhe)."""
|
||||
return self.hoehe
|
||||
|
||||
|
||||
@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."""
|
||||
hoehe_m = merkmale.get("Höhe in m", "0").replace(",", ".")
|
||||
try:
|
||||
hoehe = float(hoehe_m) * 1000
|
||||
except (ValueError, TypeError):
|
||||
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:
|
||||
abstand = float(abstand_m) * 1000
|
||||
except (ValueError, TypeError):
|
||||
abstand = 10000.0
|
||||
|
||||
|
||||
try:
|
||||
drehung = float(merkmale.get("Drehung", "0"))
|
||||
except (ValueError, TypeError):
|
||||
drehung = 0.0
|
||||
|
||||
|
||||
try:
|
||||
anzahl_scanner = float(merkmale.get("Anzahl der Scanner", "0"))
|
||||
except (ValueError, TypeError):
|
||||
anzahl_scanner = 0.0
|
||||
|
||||
|
||||
try:
|
||||
anzahl_separatoren = float(merkmale.get("Anzahl der Separatoren", "0"))
|
||||
except (ValueError, TypeError):
|
||||
anzahl_separatoren = 0.0
|
||||
|
||||
|
||||
return cls(
|
||||
teileid=teileid,
|
||||
x=x,
|
||||
@@ -125,9 +136,9 @@ class Kreisel(BaseModel):
|
||||
abstand=abstand,
|
||||
kreiselart=merkmale.get("Kreiselart"),
|
||||
anzahl_scanner=anzahl_scanner,
|
||||
anzahl_separatoren=anzahl_separatoren
|
||||
anzahl_separatoren=anzahl_separatoren,
|
||||
)
|
||||
|
||||
|
||||
def draw_kreisel_lines(msp, pos1, pos2, kreisel):
|
||||
"""Zeichnet tangentiale Linien zwischen zwei Kreiselblöcken, unabhängig vom Winkel."""
|
||||
rotation = kreisel.drehung
|
||||
@@ -145,58 +156,76 @@ class Kreisel(BaseModel):
|
||||
nx = -dy / length * RADIUS
|
||||
ny = dx / length * RADIUS
|
||||
# Tangentialpunkte
|
||||
p1a = (x1 + nx, y1 + ny,z1)
|
||||
p1b = (x1 - nx, y1 - ny,z1)
|
||||
p2a = (x2 + nx, y2 + ny,z1)
|
||||
p2b = (x2 - nx, y2 - ny,z1)
|
||||
p1a = (x1 + nx, y1 + ny, z1)
|
||||
p1b = (x1 - nx, y1 - ny, z1)
|
||||
p2a = (x2 + nx, y2 + ny, z1)
|
||||
p2b = (x2 - nx, y2 - ny, z1)
|
||||
if kreisel.kreiselart == "Pin":
|
||||
if rotation == 0.0:
|
||||
p1a2 = p1a[0] - RADIUS - 50, p1a[1] + 50, z1
|
||||
p1b2 = p1b[0] - RADIUS - 50, p1b[1] - 50, z1
|
||||
p2a2 = p2a[0] + RADIUS + 50, p2a[1] + 50, z1
|
||||
p2b2 = p2b[0] + RADIUS + 50, p2b[1] - 50, z1
|
||||
Line1 = Line.new(dxfattribs={"start": p1a2,"end": p2a2,"layer": "Pinbereich"})
|
||||
Line2 = Line.new(dxfattribs={"start": p1b2,"end": p2b2,"layer": "Pinbereich"})
|
||||
Line1 = Line.new(
|
||||
dxfattribs={"start": p1a2, "end": p2a2, "layer": "Pinbereich"}
|
||||
)
|
||||
Line2 = Line.new(
|
||||
dxfattribs={"start": p1b2, "end": p2b2, "layer": "Pinbereich"}
|
||||
)
|
||||
msp.add_entity(Line1)
|
||||
msp.add_entity(Line2)
|
||||
elif rotation == 180.0:
|
||||
elif rotation == 180.0:
|
||||
p1a2 = p1a[0] + RADIUS + 50, p1a[1] - 50, z1
|
||||
p1b2 = p1b[0] + RADIUS + 50, p1b[1] + 50, z1
|
||||
p2a2 = p2a[0] - RADIUS - 50, p2a[1] - 50, z1
|
||||
p2b2 = p2b[0] - RADIUS - 50, p2b[1] + 50, z1
|
||||
Line1 = Line.new(dxfattribs={"start": p1a2,"end": p2a2,"layer": "Pinbereich"})
|
||||
Line2 = Line.new(dxfattribs={"start": p1b2,"end": p2b2,"layer": "Pinbereich"})
|
||||
Line1 = Line.new(
|
||||
dxfattribs={"start": p1a2, "end": p2a2, "layer": "Pinbereich"}
|
||||
)
|
||||
Line2 = Line.new(
|
||||
dxfattribs={"start": p1b2, "end": p2b2, "layer": "Pinbereich"}
|
||||
)
|
||||
msp.add_entity(Line1)
|
||||
msp.add_entity(Line2)
|
||||
elif rotation == 90.0:
|
||||
p1a2 = p1a[0] + 50, p1a[1] - 50 + RADIUS , z1
|
||||
p1b2 = p1b[0] - 50, p1b[1] - 50 + RADIUS, z1
|
||||
p2a2 = p2a[0] + 50, p2a[1] + 50 - RADIUS, z1
|
||||
p2b2 = p2b[0] - 50, p2b[1] + 50 - RADIUS, z1
|
||||
Line1 = Line.new(dxfattribs={"start": p1a2,"end": p2a2,"layer": "Pinbereich"})
|
||||
Line2 = Line.new(dxfattribs={"start": p1b2,"end": p2b2,"layer": "Pinbereich"})
|
||||
elif rotation == 90.0:
|
||||
p1a2 = p1a[0] + 50, p1a[1] - 50 + RADIUS, z1
|
||||
p1b2 = p1b[0] - 50, p1b[1] - 50 + RADIUS, z1
|
||||
p2a2 = p2a[0] + 50, p2a[1] + 50 - RADIUS, z1
|
||||
p2b2 = p2b[0] - 50, p2b[1] + 50 - RADIUS, z1
|
||||
Line1 = Line.new(
|
||||
dxfattribs={"start": p1a2, "end": p2a2, "layer": "Pinbereich"}
|
||||
)
|
||||
Line2 = Line.new(
|
||||
dxfattribs={"start": p1b2, "end": p2b2, "layer": "Pinbereich"}
|
||||
)
|
||||
msp.add_entity(Line1)
|
||||
msp.add_entity(Line2)
|
||||
elif rotation == 270.0:
|
||||
p1a2 = p1a[0] - 50, p1a[1] + 50 - RADIUS , z1
|
||||
p1b2 = p1b[0] + 50, p1b[1] + 50 - RADIUS, z1
|
||||
p2a2 = p2a[0] - 50, p2a[1] - 50 + RADIUS, z1
|
||||
p2b2 = p2b[0] + 50, p2b[1] - 50 + RADIUS, z1
|
||||
Line1 = Line.new(dxfattribs={"start": p1a2,"end": p2a2,"layer": "Pinbereich"})
|
||||
Line2 = Line.new(dxfattribs={"start": p1b2,"end": p2b2,"layer": "Pinbereich"})
|
||||
elif rotation == 270.0:
|
||||
p1a2 = p1a[0] - 50, p1a[1] + 50 - RADIUS, z1
|
||||
p1b2 = p1b[0] + 50, p1b[1] + 50 - RADIUS, z1
|
||||
p2a2 = p2a[0] - 50, p2a[1] - 50 + RADIUS, z1
|
||||
p2b2 = p2b[0] + 50, p2b[1] - 50 + RADIUS, z1
|
||||
Line1 = Line.new(
|
||||
dxfattribs={"start": p1a2, "end": p2a2, "layer": "Pinbereich"}
|
||||
)
|
||||
Line2 = Line.new(
|
||||
dxfattribs={"start": p1b2, "end": p2b2, "layer": "Pinbereich"}
|
||||
)
|
||||
msp.add_entity(Line1)
|
||||
msp.add_entity(Line2)
|
||||
|
||||
# Linien zeichnen
|
||||
msp.add_line(p1a, p2a)
|
||||
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()
|
||||
if drehrichtung not in ("UZS", "GUZS"):
|
||||
return
|
||||
x1, y1,z1= pos1
|
||||
x2, y2,z2 = pos2
|
||||
x1, y1, z1 = pos1
|
||||
x2, y2, z2 = pos2
|
||||
dx = x2 - x1
|
||||
dy = y2 - y1
|
||||
length = math.hypot(dx, dy)
|
||||
@@ -216,24 +245,44 @@ class Kreisel(BaseModel):
|
||||
t = i / 4 # 1/4, 2/4, 3/4
|
||||
px = p1_oben[0] + t * (p2_oben[0] - p1_oben[0])
|
||||
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":
|
||||
rotation += 180
|
||||
block_methoden.import_block("Richtungspfeil", lib_doc, doc)
|
||||
blockref_layer, color = block_methoden.get_insert_color_layer(lib_doc, "Richtungspfeil")
|
||||
bref = msp.add_blockref("Richtungspfeil", (px, py,z1), dxfattribs={"rotation": rotation,"layer": blockref_layer})
|
||||
blockref_layer, color = block_methoden.get_insert_color_layer(
|
||||
lib_doc, "Richtungspfeil"
|
||||
)
|
||||
bref = msp.add_blockref(
|
||||
"Richtungspfeil",
|
||||
(px, py, z1),
|
||||
dxfattribs={"rotation": rotation, "layer": blockref_layer},
|
||||
)
|
||||
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)
|
||||
for i in range(1, 4):
|
||||
t = i / 4
|
||||
px = p1_unten[0] + t * (p2_unten[0] - p1_unten[0])
|
||||
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":
|
||||
rotation += 180
|
||||
block_methoden.import_block("Richtungspfeil", lib_doc, doc)
|
||||
blockref_layer, color = block_methoden.get_insert_color_layer( lib_doc, "Richtungspfeil")
|
||||
bref = msp.add_blockref("Richtungspfeil", (px, py, z1), dxfattribs={"rotation": rotation , "layer": blockref_layer})
|
||||
blockref_layer, color = block_methoden.get_insert_color_layer(
|
||||
lib_doc, "Richtungspfeil"
|
||||
)
|
||||
bref = msp.add_blockref(
|
||||
"Richtungspfeil",
|
||||
(px, py, z1),
|
||||
dxfattribs={"rotation": rotation, "layer": blockref_layer},
|
||||
)
|
||||
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}"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user