"""Prueba de concepto: DXF 2D -> modelo 3D (STEP y STL) por extrusion. Uso: python conversion.py placa.dxf 10 (DXF y espesor en mm) """ import sys import cadquery as cq import ezdxf def area(puntos): """Area de un poligono con la formula del area de Gauss (shoelace).""" s = 0.0 for (x1, y1), (x2, y2) in zip(puntos, puntos[1:] + puntos[:1]): s += x1 * y2 - x2 * y1 return abs(s) / 2 def leer_perfiles(ruta): """Devuelve las polilineas cerradas y los circulos del DXF.""" doc = ezdxf.readfile(ruta) msp = doc.modelspace() poligonos = [] for e in msp.query("LWPOLYLINE"): if e.closed: poligonos.append([(p[0], p[1]) for p in e.get_points()]) circulos = [(c.dxf.center.x, c.dxf.center.y, c.dxf.radius) for c in msp.query("CIRCLE")] return poligonos, circulos def construir_solido(poligonos, circulos, altura): """El perfil de mayor area es el exterior; el resto se restan como agujeros.""" if not poligonos: raise ValueError("El DXF no contiene ningun perfil cerrado") exterior = max(poligonos, key=area) solido = cq.Workplane("XY").polyline(exterior).close().extrude(altura) for p in poligonos: if p is not exterior: hueco = cq.Workplane("XY").polyline(p).close().extrude(altura) solido = solido.cut(hueco) for x, y, r in circulos: taladro = cq.Workplane("XY").center(x, y).circle(r).extrude(altura) solido = solido.cut(taladro) return solido def main(): ruta, altura = sys.argv[1], float(sys.argv[2]) poligonos, circulos = leer_perfiles(ruta) print(f"Perfiles cerrados: {len(poligonos)} ยท Circulos: {len(circulos)}") solido = construir_solido(poligonos, circulos, altura) cq.exporters.export(solido, "resultado.step") cq.exporters.export(solido, "resultado.stl") print("Generados resultado.step y resultado.stl") if __name__ == "__main__": main()