Improved render previews

This commit is contained in:
bklronin
2026-07-18 23:06:42 +02:00
parent 742d06d242
commit d6e829c23d
9 changed files with 2195 additions and 1553 deletions
+54 -15
View File
@@ -54,6 +54,7 @@ class OCGeometryKernel(GeometryKernel):
def create_point(self, x: float, y: float) -> GeometryObject:
"""Create a 2D point."""
from OCP.gp import gp_Pnt
return OCCGeometryObject(gp_Pnt(x, y, 0))
def create_line(self, start: Point2D, end: Point2D) -> GeometryObject:
@@ -61,9 +62,7 @@ class OCGeometryKernel(GeometryKernel):
from OCP.gp import gp_Pnt
from OCP.BRepBuilderAPI import BRepBuilderAPI_MakeEdge
edge = BRepBuilderAPI_MakeEdge(
gp_Pnt(start.x, start.y, 0), gp_Pnt(end.x, end.y, 0)
).Edge()
edge = BRepBuilderAPI_MakeEdge(gp_Pnt(start.x, start.y, 0), gp_Pnt(end.x, end.y, 0)).Edge()
return OCCGeometryObject(edge, {"type": "line"})
def create_circle(self, center: Point2D, radius: float) -> GeometryObject:
@@ -71,9 +70,7 @@ class OCGeometryKernel(GeometryKernel):
from OCP.gp import gp_Pnt, gp_Dir, gp_Ax2, gp_Circ
from OCP.BRepBuilderAPI import BRepBuilderAPI_MakeEdge
circ = gp_Circ(
gp_Ax2(gp_Pnt(center.x, center.y, 0), gp_Dir(0, 0, 1)), radius
)
circ = gp_Circ(gp_Ax2(gp_Pnt(center.x, center.y, 0), gp_Dir(0, 0, 1)), radius)
edge = BRepBuilderAPI_MakeEdge(circ).Edge()
return OCCGeometryObject(edge, {"type": "circle"})
@@ -88,9 +85,7 @@ class OCGeometryKernel(GeometryKernel):
start_rad = math.radians(start_angle)
end_rad = math.radians(end_angle)
circ = gp_Circ(
gp_Ax2(gp_Pnt(center.x, center.y, 0), gp_Dir(0, 0, 1)), radius
)
circ = gp_Circ(gp_Ax2(gp_Pnt(center.x, center.y, 0), gp_Dir(0, 0, 1)), radius)
edge = BRepBuilderAPI_MakeEdge(circ, start_rad, end_rad).Edge()
return OCCGeometryObject(edge, {"type": "arc"})
@@ -159,8 +154,7 @@ class OCGeometryKernel(GeometryKernel):
face = self._get_shape(sketch)
if face is None:
raise ValueError(
"Cannot extrude: sketch has no geometry. "
"Draw a closed profile before extruding."
"Cannot extrude: sketch has no geometry. Draw a closed profile before extruding."
)
# If the wrapper class itself leaked through somehow, surface a
# clear error instead of letting BRepPrimAPI_MakePrism raise an
@@ -204,6 +198,7 @@ class OCGeometryKernel(GeometryKernel):
def _sketch_normal(obj: GeometryObject) -> Tuple[float, float, float]:
"""Return the normal stored on a sketch-derived geometry object, else +Z."""
import numpy as np
meta = getattr(obj, "metadata", None) or {}
n = meta.get("normal")
if n is None:
@@ -453,7 +448,6 @@ class OCGeometryKernel(GeometryKernel):
origin: Tuple[float, float, float] = (0, 0, 0),
) -> GeometryObject:
"""Rotate a body around an axis."""
import math
shape = self._get_shape(body)
from OCP.BRepBuilderAPI import BRepBuilderAPI_Transform
from OCP.gp import gp_Trsf, gp_Ax1, gp_Pnt, gp_Dir
@@ -562,6 +556,52 @@ class OCGeometryKernel(GeometryKernel):
shape = reader.OneShape()
return OCCGeometryObject(shape, {"type": "imported_step"})
def import_step_components(self, filepath: str) -> list:
"""Import a STEP file and return each solid as a separate ``(name, shape)`` pair.
The STEP reader transfers the entire root shape, then we iterate
over individual ``TopAbs_SOLID`` entities so that each solid gets
its own ``OCCGeometryObject``. If the file contains only a single
solid the list will have one entry.
Returns a list of ``(name, OCCGeometryObject)`` tuples.
"""
from OCP.STEPControl import STEPControl_Reader
from OCP.IFSelect import IFSelect_RetDone
from OCP.TopExp import TopExp_Explorer
from OCP.TopAbs import TopAbs_SOLID
from OCP.TopoDS import TopoDS
reader = STEPControl_Reader()
status = reader.ReadFile(filepath)
if status != IFSelect_RetDone:
raise ValueError(f"Failed to read STEP file: {filepath}")
reader.TransferRoots()
shape = reader.OneShape()
# Extract individual solids
solids: list = []
explorer = TopExp_Explorer(shape, TopAbs_SOLID)
idx = 0
while explorer.More():
solid = TopoDS.Solid_s(explorer.Current())
idx += 1
solids.append(
(
f"Part {idx}",
OCCGeometryObject(solid, {"type": "imported_step"}),
)
)
explorer.Next()
# Fallback: no individual solids found — return the whole shape
if not solids:
solids = [("Imported", OCCGeometryObject(shape, {"type": "imported_step"}))]
return solids
def import_iges(self, filepath: str) -> GeometryObject:
"""Import from IGES format."""
from OCP.IGESControl import IGESControl_Reader
@@ -643,10 +683,8 @@ class OCGeometryKernel(GeometryKernel):
from OCP.TopExp import TopExp_Explorer
from OCP.TopAbs import TopAbs_EDGE
from OCP.BRep import BRep_Tool
from OCP.TopLoc import TopLoc_Location
from OCP.BRepAdaptor import BRepAdaptor_Curve
from OCP.GeomAbs import GeomAbs_Line, GeomAbs_Circle, GeomAbs_Ellipse, GeomAbs_BSplineCurve
from OCP.GeomAbs import GeomAbs_Line
vertices_list: List[List[float]] = []
edges_list: List[List[int]] = []
@@ -678,6 +716,7 @@ class OCGeometryKernel(GeometryKernel):
explorer = TopExp_Explorer(shape, TopAbs_EDGE)
while explorer.More():
from OCP.TopoDS import TopoDS
edge = TopoDS.Edge_s(explorer.Current())
edge_points = discretize_edge(edge)