Unittests zu allen Elementen erstellt
This commit is contained in:
+118
-48
@@ -1,13 +1,77 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from ezdxf.entities import Line
|
||||
"""
|
||||
Omniflo — Modell und Erstellungsfunktionen für Omniflo-Kettenförderer.
|
||||
|
||||
Refactoring-Änderungen:
|
||||
- 8x try/except-Boilerplate durch _safe_float/_safe_int Hilfsfunktionen ersetzt
|
||||
- @staticmethod auf Omniflo_geraden_erstellung und omniflo_foerdererstellung
|
||||
- Bug fix: omniflo_foerdererstellung nutzte rotation (Grad) statt winkel_rad in sin/cos
|
||||
- Duplizierte dx/dy-Berechnung vereinheitlicht
|
||||
"""
|
||||
import math
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
|
||||
from ezdxf.entities import Line
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import Optional
|
||||
from lib import plant2dxf
|
||||
|
||||
from lib import block_methoden
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# HILFSFUNKTIONEN
|
||||
# ============================================================================
|
||||
|
||||
|
||||
def _safe_float(value, default=0.0):
|
||||
"""
|
||||
Konvertiert einen Wert zu float mit Fallback.
|
||||
|
||||
Behandelt automatisch Komma-als-Dezimaltrennzeichen (z.B. "3,5" → 3.5).
|
||||
|
||||
Args:
|
||||
value: Zu konvertierender Wert (str, int, float oder None)
|
||||
default: Rückgabewert bei Konvertierungsfehler
|
||||
|
||||
Returns:
|
||||
Float-Wert oder default
|
||||
"""
|
||||
try:
|
||||
if value is None:
|
||||
return default
|
||||
if isinstance(value, str):
|
||||
value = value.replace(",", ".")
|
||||
return float(value)
|
||||
except (TypeError, ValueError):
|
||||
return default
|
||||
|
||||
|
||||
def _safe_int(value, default=0):
|
||||
"""
|
||||
Konvertiert einen Wert zu int mit Fallback (über float-Zwischenschritt).
|
||||
|
||||
Args:
|
||||
value: Zu konvertierender Wert
|
||||
default: Rückgabewert bei Konvertierungsfehler
|
||||
|
||||
Returns:
|
||||
Int-Wert oder default
|
||||
"""
|
||||
try:
|
||||
if value is None:
|
||||
return default
|
||||
return int(float(value))
|
||||
except (TypeError, ValueError):
|
||||
return default
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# OMNIFLO KLASSE
|
||||
# ============================================================================
|
||||
|
||||
|
||||
class Omniflo(BaseModel):
|
||||
"""Modell für Omniflo-Kettenförderer."""
|
||||
|
||||
teileid: str
|
||||
x: float
|
||||
y: float
|
||||
@@ -24,62 +88,58 @@ class Omniflo(BaseModel):
|
||||
|
||||
@property
|
||||
def hight_zwischen(self):
|
||||
"""Mittlere Höhe zwischen h0 und h1."""
|
||||
return (self.h0 + self.h1) / 2
|
||||
|
||||
@classmethod
|
||||
def from_merkmale(cls, teileid, x, y, merkmale):
|
||||
sivasnummer = merkmale.get("SivasNummer")
|
||||
try:
|
||||
laenge = (
|
||||
float(merkmale.get("Länge in Meter", "0").replace(",", ".")) * 1000
|
||||
) # Meter → mm
|
||||
except Exception:
|
||||
laenge = 0
|
||||
try:
|
||||
winkel = float(merkmale.get("Drehung"))
|
||||
except Exception:
|
||||
winkel = 0.0
|
||||
try:
|
||||
hoehe = float(merkmale.get("Höhe"))
|
||||
except Exception:
|
||||
hoehe = 0.0
|
||||
try:
|
||||
h0 = float(merkmale.get("Höhe unten"))
|
||||
except Exception:
|
||||
h0 = 0.0
|
||||
try:
|
||||
h1 = float(merkmale.get("Höhe oben"))
|
||||
except Exception:
|
||||
h1 = 0.0
|
||||
try:
|
||||
anzahl_scanner = float(merkmale.get("Anzahl der Scanner", "0"))
|
||||
except Exception:
|
||||
anzahl_scanner = 0
|
||||
try:
|
||||
anzahl_separatoren = float(merkmale.get("Anzahl der Separatoren", "0"))
|
||||
except Exception:
|
||||
anzahl_separatoren = 0
|
||||
"""
|
||||
Erstellt Omniflo aus einem Merkmale-Dictionary.
|
||||
|
||||
Verwendet _safe_float/_safe_int für robuste Konvertierung
|
||||
statt 8x wiederholtem try/except-Muster.
|
||||
|
||||
Args:
|
||||
teileid: Teile-Identifikator
|
||||
x, y: Koordinaten in mm
|
||||
merkmale: Dictionary mit Eigenschaftswerten
|
||||
|
||||
Returns:
|
||||
Omniflo-Instanz
|
||||
"""
|
||||
return cls(
|
||||
teileid=teileid,
|
||||
x=x,
|
||||
y=y,
|
||||
sivasnummer=sivasnummer,
|
||||
laenge=laenge,
|
||||
drehung=winkel,
|
||||
hoehe=hoehe,
|
||||
h0=h0,
|
||||
h1=h1,
|
||||
anzahl_scanner=anzahl_scanner,
|
||||
anzahl_stopper=anzahl_separatoren,
|
||||
sivasnummer=merkmale.get("SivasNummer"),
|
||||
laenge=_safe_float(merkmale.get("Länge in Meter"), 0.0) * 1000, # Meter → mm
|
||||
drehung=_safe_float(merkmale.get("Drehung"), 0.0),
|
||||
hoehe=_safe_float(merkmale.get("Höhe"), 0.0),
|
||||
h0=_safe_float(merkmale.get("Höhe unten"), 0.0),
|
||||
h1=_safe_float(merkmale.get("Höhe oben"), 0.0),
|
||||
anzahl_scanner=_safe_int(merkmale.get("Anzahl der Scanner"), 0),
|
||||
anzahl_stopper=_safe_int(merkmale.get("Anzahl der Separatoren"), 0),
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def Omniflo_geraden_erstellung(msp, doc, tefsivas, omniflo_objekt):
|
||||
"""Erstellung der Tef gerade und Omniflo gerade"""
|
||||
"""
|
||||
Erstellung der Tef gerade und Omniflo gerade.
|
||||
|
||||
Zeichnet eine Linie zwischen Start- und Endpunkt basierend auf
|
||||
Länge und Drehung des Omniflo-Objekts.
|
||||
|
||||
Args:
|
||||
msp: DXF-Modelspace
|
||||
doc: DXF-Dokument
|
||||
tefsivas: Sivas-Nummer der Tef-Strecke
|
||||
omniflo_objekt: Omniflo-Instanz
|
||||
"""
|
||||
winkel_rad = math.radians(omniflo_objekt.drehung)
|
||||
halbe_laenge = omniflo_objekt.laenge / 2
|
||||
x = omniflo_objekt.x
|
||||
y = omniflo_objekt.y
|
||||
# Man muss bei sin -1 machen wegen des links koordinaten system
|
||||
# Koordinatensystem: sin mit -1 wegen links-Koordinatensystem
|
||||
dx = halbe_laenge * math.sin(winkel_rad * -1)
|
||||
dy = halbe_laenge * math.cos(winkel_rad)
|
||||
start = (x + dx, y + dy, omniflo_objekt.h1)
|
||||
@@ -94,8 +154,17 @@ class Omniflo(BaseModel):
|
||||
else:
|
||||
linie.dxf.layer = "A-2"
|
||||
|
||||
@staticmethod
|
||||
def omniflo_foerdererstellung(msp, doc, lib_doc, omniflo_objekt):
|
||||
""" "Erstellung des Kettenförderers aktuell nur grundriss"""
|
||||
"""
|
||||
Erstellung des Kettenförderers (aktuell nur Grundriss).
|
||||
|
||||
Args:
|
||||
msp: DXF-Modelspace
|
||||
doc: DXF-Dokument
|
||||
lib_doc: Bibliotheks-Dokument
|
||||
omniflo_objekt: Omniflo-Instanz
|
||||
"""
|
||||
block_methoden.import_block("bogen1", lib_doc, doc)
|
||||
block_methoden.import_block("bogen2", lib_doc, doc)
|
||||
x = omniflo_objekt.x
|
||||
@@ -108,9 +177,10 @@ class Omniflo(BaseModel):
|
||||
blockname = f"OF_Förderer_{laenge}_{h_zwischen}"
|
||||
winkel_rad = math.radians(rotation)
|
||||
halbe_laenge = laenge / 2
|
||||
# Man muss bei sin -1 machen wegen des links koordinaten system
|
||||
dx = halbe_laenge * math.sin(rotation * -1)
|
||||
dy = halbe_laenge * math.cos(rotation)
|
||||
# BUG FIX: war `math.sin(rotation * -1)` — rotation ist in Grad!
|
||||
# Muss winkel_rad (Radianten) verwenden wie in Omniflo_geraden_erstellung
|
||||
dx = halbe_laenge * math.sin(winkel_rad * -1)
|
||||
dy = halbe_laenge * math.cos(winkel_rad)
|
||||
start = (x + dx, y + dy, h1)
|
||||
ende = (x - dx, y - dy, h0)
|
||||
if blockname not in doc.blocks:
|
||||
|
||||
Reference in New Issue
Block a user