plano3d/motor/simulado.py

46 lines
1.9 KiB
Python

"""Motor simulado: devuelve siempre la pieza de CUBE01 con sus avisos reales.
Sirve para desarrollar la aplicación (interfaz y visor) antes de que exista el motor real.
Las líneas del plano sí se leen del archivo recibido, para poder dibujarlas en 2D.
"""
from __future__ import annotations
from pathlib import Path
import cadquery as cq
import ezdxf
from motor.api import Aviso, Estado, Gravedad, Opciones, Referencia, Resultado, Segmento2D, Vista
RAIZ = Path(__file__).resolve().parent.parent
PIEZA_CUBE01 = RAIZ / "pruebas" / "catalogo" / "CUBE01" / "esperado.step"
def _leer_lineas(ruta: Path) -> list[Segmento2D]:
if ruta.suffix.lower() != ".dxf":
return []
doc = ezdxf.readfile(ruta)
segmentos = []
for e in doc.modelspace().query("LINE"):
tipo = e.dxf.get("linetype", "ByLayer")
if tipo.lower() == "bylayer":
tipo = doc.layers.get(e.dxf.layer).dxf.linetype
oculta = "HIDDEN" in tipo.upper() or "HIDDEN" in e.dxf.layer.upper()
segmentos.append(Segmento2D(e.dxf.start.x, e.dxf.start.y, e.dxf.end.x, e.dxf.end.y, oculta))
return segmentos
def procesar(ruta: Path, opciones: Opciones) -> Resultado:
solido = cq.importers.importStep(str(PIEZA_CUBE01)).val()
avisos = [
Aviso("ESCALA_DETECTADA", "Escala 1:2 leída del cajetín.", Gravedad.INFO),
Aviso("SIN_COTAS", "El plano no tiene cotas: las medidas se deducen de la geometría y la escala.",
Gravedad.AVISO),
Aviso("PROYECCION_MIXTA",
"Sistemas de proyección mezclados: la planta sigue el europeo (ISO-E) y el perfil el americano (ISO-A).",
Gravedad.AVISO, Referencia(vista="perfil")),
]
# Simulado: todas las líneas van en una sola "vista"; el motor real las separará en alzado, planta y perfil.
vistas = {"plano": Vista("plano", _leer_lineas(ruta))}
return Resultado(Estado.CON_AVISOS, solido, avisos, vistas, escala=opciones.escala or 2.0)