From 64775a4626c3e53d254e388df20190fadc6f660b Mon Sep 17 00:00:00 2001 From: tomvanmele Date: Mon, 6 Nov 2023 23:03:40 +0100 Subject: [PATCH] merge brep updates (ongoing) --- docs/examples/brep_overlap.py | 1 - src/compas_occ/brep/brep.py | 292 +++++++++++----------- src/compas_occ/brep/brepedge.py | 12 +- src/compas_occ/brep/brepface.py | 8 +- src/compas_occ/conversions/__init__.py | 84 ++++--- src/compas_occ/conversions/geometry.py | 34 +++ src/compas_occ/geometry/curves/curve2d.py | 3 +- 7 files changed, 242 insertions(+), 192 deletions(-) diff --git a/docs/examples/brep_overlap.py b/docs/examples/brep_overlap.py index de0a0b942..ef5704826 100644 --- a/docs/examples/brep_overlap.py +++ b/docs/examples/brep_overlap.py @@ -2,7 +2,6 @@ from compas.geometry import Translation from compas.geometry import Box -from compas.geometry import Brep from compas.colors import Color from compas.brep import Brep from compas_view2.app import App diff --git a/src/compas_occ/brep/brep.py b/src/compas_occ/brep/brep.py index d3f647c82..a9e177bd0 100644 --- a/src/compas_occ/brep/brep.py +++ b/src/compas_occ/brep/brep.py @@ -1,7 +1,6 @@ from typing import List, Tuple, Union import compas.geometry -from compas.geometry import Brep as BrepPluggable import compas.datastructures @@ -15,59 +14,50 @@ from compas.datastructures import Mesh from compas.brep import Brep -from OCC.Extend.DataExchange import read_step_file - -from OCC.Core.gp import gp_Pnt -from OCC.Core.gp import gp_Dir -from OCC.Core.gp import gp_Ax2 - -from OCC.Core.TopoDS import TopoDS_Iterator -from OCC.Core.TopoDS import TopoDS_Shell -from OCC.Core.TopoDS import TopoDS_Shape -from OCC.Core.TopoDS import topods -from OCC.Core.TopExp import TopExp_Explorer -from OCC.Core.TopAbs import TopAbs_VERTEX -from OCC.Core.TopAbs import TopAbs_EDGE -from OCC.Core.TopAbs import TopAbs_WIRE -from OCC.Core.TopAbs import TopAbs_FACE -from OCC.Core.TopAbs import TopAbs_SHELL -from OCC.Core.TopAbs import TopAbs_SOLID -from OCC.Core.TopAbs import TopAbs_Orientation -from OCC.Core.TopAbs import TopAbs_ShapeEnum from OCC.Core.BRep import BRep_Builder from OCC.Core.BRep import BRep_Tool -from OCC.Core.BRepGProp import brepgprop_VolumeProperties -from OCC.Core.BRepGProp import brepgprop_SurfaceProperties +from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Common +from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Cut +from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Fuse +from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Section from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_NurbsConvert from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeSolid from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_Sewing from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_Transform from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_Copy +from OCC.Core.BRepCheck import BRepCheck_Shell +from OCC.Core.BRepCheck import BRepCheck_Status +from OCC.Core.BRepExtrema import BRepExtrema_ShapeProximity +from OCC.Core.BRepGProp import brepgprop_VolumeProperties +from OCC.Core.BRepGProp import brepgprop_SurfaceProperties +from OCC.Core.BRepMesh import BRepMesh_IncrementalMesh +from OCC.Core.BRepOffsetAPI import BRepOffsetAPI_MakePipe +from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakePrism from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeSphere from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeCylinder -from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Common -from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Cut -from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Fuse -from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Section from OCC.Core.BOPAlgo import BOPAlgo_Splitter -from OCC.Core.BRepCheck import BRepCheck_Shell -from OCC.Core.BRepCheck import BRepCheck_Status -from OCC.Core.BRepMesh import BRepMesh_IncrementalMesh -from OCC.Core.BRepExtrema import BRepExtrema_ShapeProximity -from OCC.Core.ShapeFix import ShapeFix_Shell +from OCC.Core.gp import gp_Pnt from OCC.Core.GProp import GProp_GProps +from OCC.Core.ShapeFix import ShapeFix_Shell +from OCC.Core.TopAbs import TopAbs_VERTEX +from OCC.Core.TopAbs import TopAbs_EDGE +from OCC.Core.TopAbs import TopAbs_WIRE +from OCC.Core.TopAbs import TopAbs_FACE +from OCC.Core.TopAbs import TopAbs_SHELL +from OCC.Core.TopAbs import TopAbs_SOLID +from OCC.Core.TopAbs import TopAbs_Orientation +from OCC.Core.TopAbs import TopAbs_ShapeEnum +from OCC.Core.TopExp import TopExp_Explorer +from OCC.Core.TopExp import topexp_MapShapesAndUniqueAncestors from OCC.Core.TopLoc import TopLoc_Location -from OCC.Core.STEPControl import STEPControl_Writer -from OCC.Core.STEPControl import STEPControl_AsIs -from OCC.Core.IFSelect import IFSelect_RetDone -from OCC.Core.Interface import Interface_Static - +from OCC.Core.TopoDS import TopoDS_Iterator +from OCC.Core.TopoDS import TopoDS_Shell +from OCC.Core.TopoDS import TopoDS_Shape +from OCC.Core.TopoDS import topods from OCC.Core.TopTools import TopTools_IndexedDataMapOfShapeListOfShape -from OCC.Core.TopTools import TopTools_ListIteratorOfListOfShape -from OCC.Core.TopExp import topexp_MapShapesAndUniqueAncestors -from OCC.Core.BRepOffsetAPI import BRepOffsetAPI_MakePipe -from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakePrism +from OCC.Core.TopTools import TopTools_ListIteratorOfListOfShape # type: ignore +from OCC.Extend.DataExchange import read_step_file # from OCC.Core.TopExp import topexp_MapShapesAndAncestors # from OCC.Core.TopExp import topexp_FirstVertex @@ -82,7 +72,8 @@ from compas_occ.conversions import compas_transformation_to_trsf from compas_occ.conversions import compas_point_from_occ_point from compas_occ.conversions import compas_vector_to_occ_vector -from compas_occ.conversions import compas_frame_from_location +from compas_occ.conversions import compas_frame_from_occ_location +from compas_occ.conversions import compas_frame_to_occ_ax2 from compas_occ.geometry import OCCNurbsCurve from compas_occ.geometry import OCCNurbsSurface @@ -114,15 +105,6 @@ class OCCBrep(Brep): volume : float, read-only The volume of the regions contained by the Brep. - Other Attributes - ---------------- - occ_shape : ``TopoDS_Shape`` - The underlying OCC shape of the Brep. - type : {TopAbs_COMPOUND, TopAbs_COMPSOLID, TopAbs_SOLID, TopAbs_SHELL, TopAbs_FACE, TopAbs_WIRE, TopAbs_EDGE, TopAbs_VERTEX, TopAbs_SHAPE}, read-only - The type of BRep shape. - orientation : {TopAbs_FORWARD, TopAbs_REVERSED, TopAbs_INTERNAL, TopAbs_EXTERNAL}, read-only - Orientation of the shape. - Examples -------- Constructors @@ -159,11 +141,10 @@ class OCCBrep(Brep): """ - __class__ = BrepPluggable + _occ_shape: TopoDS_Shape def __init__(self) -> None: super().__init__() - self._occ_shape = None self._vertices = None self._edges = None self._loops = None @@ -201,70 +182,70 @@ def copy(self, *args, **kwargs): Returns ------- - :class:`~compas_occ.brep.BRep` + :class:`~compas_occ.brep.OCCBrep` """ builder = BRepBuilderAPI_Copy(self.native_brep) builder.Perform(self.native_brep) - return BRep.from_native(builder.Shape()) + return OCCBrep.from_native(builder.Shape()) # ============================================================================== # Customization # ============================================================================== - def __deepcopy__(self, *args, **kwargs): - return self.copy() + # def __deepcopy__(self, *args, **kwargs): + # return self.copy() - def __add__(self, other): - """ - Compute the boolean union using the "+" operator of this BRep and another. + # def __add__(self, other): + # """ + # Compute the boolean union using the "+" operator of this BRep and another. - Parameters - ---------- - other : :class:`compas_occ.brep.Brep` - The BRep to add. + # Parameters + # ---------- + # other : :class:`compas_occ.brep.Brep` + # The BRep to add. - Returns - ------- - :class:`compas_occ.brep.Brep` - The resulting Brep. + # Returns + # ------- + # :class:`compas_occ.brep.Brep` + # The resulting Brep. - """ - return OCCBrep.from_boolean_union(self, other) + # """ + # return OCCBrep.from_boolean_union(self, other) - def __sub__(self, other): - """ - Compute the boolean difference using the "-" operator of this shape and another. + # def __sub__(self, other): + # """ + # Compute the boolean difference using the "-" operator of this shape and another. - Parameters - ---------- - other : :class:`compas_occ.brep.Brep` - The BRep to subtract. + # Parameters + # ---------- + # other : :class:`compas_occ.brep.Brep` + # The BRep to subtract. - Returns - ------- - :class:`compas_occ.brep.Brep` - The resulting Brep. + # Returns + # ------- + # :class:`compas_occ.brep.Brep` + # The resulting Brep. - """ - return OCCBrep.from_boolean_difference(self, other) + # """ + # return OCCBrep.from_boolean_difference(self, other) - def __and__(self, other): - """ - Compute the boolean intersection using the "&" operator of this shape and another. + # def __and__(self, other): + # """ + # Compute the boolean intersection using the "&" operator of this shape and another. - Parameters - ---------- - other : :class:`compas_occ.brep.Brep` - The Brep to intersect with. + # Parameters + # ---------- + # other : :class:`compas_occ.brep.Brep` + # The Brep to intersect with. - Returns - ------- - :class:`compas_occ.brep.Brep` - The resulting Brep. + # Returns + # ------- + # :class:`compas_occ.brep.Brep` + # The resulting Brep. - """ - return OCCBrep.from_boolean_intersection(self, other) + # """ + # return OCCBrep.from_boolean_intersection(self, other) # ============================================================================== # OCC Properties @@ -273,6 +254,8 @@ def __and__(self, other): @property def occ_shape(self) -> TopoDS_Shape: return self._occ_shape # type: ignore + + @property def native_brep(self) -> TopoDS_Shape: return self._occ_shape @@ -332,11 +315,11 @@ def is_convex(self) -> bool: @property def is_manifold(self) -> bool: - pass + return False @property def is_surface(self) -> bool: - pass + return False # ============================================================================== # Geometric Components @@ -423,7 +406,7 @@ def shells(self) -> List["OCCBrep"]: while explorer.More(): shell = explorer.Current() brep = Brep() - brep.occ_shape = shell + brep.native_brep = shell shells.append(brep) explorer.Next() self._shells = shells @@ -437,7 +420,7 @@ def solids(self) -> List["OCCBrep"]: while explorer.More(): solid = explorer.Current() brep = Brep() - brep.occ_shape = solid + brep.native_brep = solid solids.append(brep) explorer.Next() self._solids = solids @@ -450,7 +433,7 @@ def solids(self) -> List["OCCBrep"]: @property def frame(self) -> compas.geometry.Frame: location = self.native_brep.Location() - return compas_frame_from_location(location) + return compas_frame_from_occ_location(location) @property def area(self) -> float: @@ -491,6 +474,23 @@ def from_shape(cls, shape: TopoDS_Shape) -> "OCCBrep": brep.native_brep = shape return brep + @classmethod + def from_native(cls, shape: TopoDS_Shape) -> "OCCBrep": + """ + Construct a BRep from an OCC shape. + + Parameters + ---------- + shape : ``TopoDS_Shape`` + The OCC shape. + + Returns + ------- + :class:`~compas_occ.brep.OCCBrep` + + """ + return cls.from_shape(shape) + @classmethod def from_step(cls, filename: str) -> "OCCBrep": """ @@ -506,7 +506,7 @@ def from_step(cls, filename: str) -> "OCCBrep": """ shape = read_step_file(filename) - return cls.from_native(shape) + return cls.from_native(shape) # type: ignore @classmethod def from_polygons(cls, polygons: List[compas.geometry.Polygon]) -> "OCCBrep": @@ -571,7 +571,7 @@ def from_box(cls, box: compas.geometry.Box) -> "OCCBrep": yaxis = box.frame.yaxis.scaled(-0.5 * box.ysize) zaxis = box.frame.zaxis.scaled(-0.5 * box.zsize) frame = box.frame.transformed(Translation.from_vector(xaxis + yaxis + zaxis)) - ax2 = gp_Ax2(gp_Pnt(*frame.point), gp_Dir(*frame.zaxis), gp_Dir(*frame.xaxis)) + ax2 = compas_frame_to_occ_ax2(frame) # type: ignore shape = BRepPrimAPI_MakeBox(ax2, box.xsize, box.ysize, box.zsize).Shape() return cls.from_native(shape) @@ -611,7 +611,7 @@ def from_cylinder(cls, cylinder: compas.geometry.Cylinder) -> "OCCBrep": radius = cylinder.circle.radius frame = Frame.from_plane(plane) frame.transform(Translation.from_vector(frame.zaxis * (-0.5 * height))) - ax2 = gp_Ax2(gp_Pnt(*frame.point), gp_Dir(*frame.zaxis), gp_Dir(*frame.xaxis)) + ax2 = compas_frame_to_occ_ax2(frame) # type: ignore shape = BRepPrimAPI_MakeCylinder(ax2, radius, height).Shape() return cls.from_native(shape) @@ -660,7 +660,7 @@ def from_mesh( Returns ------- - :class:`BRep` + :class:`OCCBrep` """ shell = TopoDS_Shell() @@ -692,7 +692,7 @@ def from_brepfaces(cls, faces: List[OCCBrepFace]) -> "OCCBrep": Returns ------- - :class:`BRep` + :class:`OCCBrep` """ shell = TopoDS_Shell() @@ -763,7 +763,7 @@ def from_breps(cls, breps: List["OCCBrep"]) -> "OCCBrep": builder = BRep_Builder() builder.MakeCompound(compound) for brep in breps: - builder.Add(compound, brep.occ_shape) + builder.Add(compound, brep.native_brep) return cls.from_native(compound) # ============================================================================== @@ -846,22 +846,22 @@ def from_boolean_union(cls, A: "OCCBrep", B: "OCCBrep") -> "OCCBrep": # Converters # ============================================================================== - def to_json(self, filepath: str): - """ - Export the BRep to a JSON file. + # def to_json(self, filepath: str): + # """ + # Export the BRep to a JSON file. - Parameters - ---------- - filepath : str - Location of the file. + # Parameters + # ---------- + # filepath : str + # Location of the file. - Returns - ------- - None + # Returns + # ------- + # None - """ - with open(filepath, "w") as f: - self.native_brep.DumpJson(f) + # """ + # with open(filepath, "w") as f: + # self.native_brep.DumpJson(f) def to_step(self, filepath: str, schema: str = "AP203", unit: str = "MM") -> None: """ @@ -881,8 +881,12 @@ def to_step(self, filepath: str, schema: str = "AP203", unit: str = "MM") -> Non None """ + from OCC.Core.STEPControl import STEPControl_Writer + from OCC.Core.STEPControl import STEPControl_AsIs + from OCC.Core.IFSelect import IFSelect_RetDone + from OCC.Core.Interface import Interface_Static + step_writer = STEPControl_Writer() - # Interface_Static.SetCVal("write.step.schema", schema) Interface_Static.SetCVal("write.step.unit", unit) step_writer.Transfer(self.occ_shape, STEPControl_AsIs) status = step_writer.Write(filepath) @@ -942,7 +946,7 @@ def to_meshes(self, u=16, v=16): """ converter = BRepBuilderAPI_NurbsConvert(self.occ_shape, False) - brep = Brep.from_shape(converter.Shape()) + brep = OCCBrep.from_shape(converter.Shape()) meshes = [] for face in brep.faces: srf = OCCNurbsSurface.from_face(face.occ_face) @@ -1238,13 +1242,13 @@ def transformed(self, matrix: compas.geometry.Transformation) -> "OCCBrep": Returns ------- - :class:`BRep` + :class:`OCCBrep` """ trsf = compas_transformation_to_trsf(matrix) builder = BRepBuilderAPI_Transform(self.occ_shape, trsf, True) shape = builder.ModifiedShape(self.occ_shape) - return Brep.from_shape(shape) + return OCCBrep.from_shape(shape) def contours( self, planes: List[compas.geometry.Plane] @@ -1266,10 +1270,10 @@ def contours( raise NotImplementedError def slice(self, plane: compas.geometry.Plane) -> OCCBrepFace: - """ + """ """ if isinstance(plane, Frame): plane = Plane.from_frame(plane) - face = BRepFace.from_plane(plane).occ_face + face = OCCBrepFace.from_plane(plane).occ_face results = _split_shape(self.native_brep, face) # The order of solids in `results` does not depend on the orientation of the cutting plane but rather @@ -1278,7 +1282,7 @@ def slice(self, plane: compas.geometry.Plane) -> OCCBrepFace: for solid in results: centroid = _get_brep_centroid(solid) if not _is_point_in_pos_half_space(centroid, plane): - return BRep.from_native(solid) + return OCCBrep.from_native(solid) def trim(self, plane: Union[compas.geometry.Plane, compas.geometry.Frame]): """Trim a BRep with a plane. @@ -1295,7 +1299,7 @@ def trim(self, plane: Union[compas.geometry.Plane, compas.geometry.Frame]): if trimmed is not None: self.native_brep = trimmed.native_brep - def sliced(self, plane: compas.geometry.Plane) -> BRepFace: + def sliced(self, plane: compas.geometry.Plane) -> OCCBrepFace: """ Returns a new Brep which is a slice of this Brep and the given plane. @@ -1313,40 +1317,40 @@ def sliced(self, plane: compas.geometry.Plane) -> BRepFace: section = BRepAlgoAPI_Section(self.occ_shape, face.occ_face) section.Build() if section.IsDone(): - return Brep.from_shape(section.Shape()) + return OCCBrep.from_shape(section.Shape()) - def split(self, other: "OCCBrep") -> List["OCCBrep"]: - """ - Perform in-place slice of this Brep with the given plane. + # def split(self, other: "OCCBrep") -> List["OCCBrep"]: + # """ + # Perform in-place slice of this Brep with the given plane. - Parameters - ---------- - plane : :class:`~compas.geometry.Plane` - The slicing plane. + # Parameters + # ---------- + # plane : :class:`~compas.geometry.Plane` + # The slicing plane. - """ - sliced = self.sliced(plane) - if sliced: - self.native_brep = sliced.native_brep + # """ + # sliced = self.sliced(plane) + # if sliced: + # self.native_brep = sliced.native_brep - def split(self, other: "BRep") -> List["BRep"]: + def split(self, other: "OCCBrep") -> List["OCCBrep"]: """Split a BRep using another BRep as splitter. Parameters ---------- - other : :class:`BRep` + other : :class:`OCCBrep` Another b-rep. Returns ------- - List[:class:`~compas_occ.brep.BRep`] + List[:class:`~compas_occ.brep.OCCBrep`] """ splitter = BOPAlgo_Splitter() splitter.AddArgument(self.occ_shape) splitter.AddTool(other.occ_shape) splitter.Perform() - return Brep.from_shape(splitter.Shape()) + return OCCBrep.from_shape(splitter.Shape()) def overlap( self, other: "OCCBrep", deflection: float = 1e-3, tolerance: float = 0.0 @@ -1356,7 +1360,7 @@ def overlap( Parameters ---------- - other : :class:`BRep` + other : :class:`OCCBrep` The other b-rep. deflection : float, optional Allowable deflection for mesh generation used for proximity detection. diff --git a/src/compas_occ/brep/brepedge.py b/src/compas_occ/brep/brepedge.py index 96e0fc5c1..7e401bcd1 100644 --- a/src/compas_occ/brep/brepedge.py +++ b/src/compas_occ/brep/brepedge.py @@ -122,6 +122,10 @@ def from_data(cls, data): # OCC Properties # ============================================================================== + @property + def occ_shape(self) -> TopoDS_Edge: + return self._occ_edge # type: ignore + @property def occ_edge(self) -> TopoDS_Edge: return self._occ_edge # type: ignore @@ -146,15 +150,15 @@ def orientation(self) -> TopAbs_Orientation: @property def curve(self) -> OCCCurve: if not self._curve: - self._curve = OCCCurve() - self._curve.occ_curve = self.occ_adaptor.Curve() # type: ignore + occ_curve = self.occ_adaptor.Curve() + self._curve = OCCCurve(occ_curve) # type: ignore return self._curve @property def nurbscurve(self) -> OCCNurbsCurve: if not self._nurbscurve: - self._nurbscurve = OCCNurbsCurve() - self._nurbscurve.occ_curve = self.occ_adaptor.BSpline() # type: ignore + occ_curve = self.occ_adaptor.BSpline() + self._nurbscurve = OCCNurbsCurve(occ_curve) # type: ignore return self._nurbscurve # type: ignore (don't understand why this is necessary) # ============================================================================== diff --git a/src/compas_occ/brep/brepface.py b/src/compas_occ/brep/brepface.py index 3e0f0f6d4..f15267beb 100644 --- a/src/compas_occ/brep/brepface.py +++ b/src/compas_occ/brep/brepface.py @@ -143,15 +143,15 @@ def orientation(self) -> TopAbs_Orientation: @property def surface(self) -> OCCSurface: if not self._surface: - self._surface = OCCSurface() - self._surface.occ_surface = self.occ_adaptor.Surface().Surface() + occ_surface = self.occ_adaptor.Surface().Surface() + self._surface = OCCSurface(occ_surface) return self._surface @property def nurbssurface(self) -> OCCNurbsSurface: if not self._nurbssurface: - self._nurbssurface = OCCNurbsSurface() - self._nurbssurface.occ_surface = self.occ_adaptor.BSpline() + occ_surface = self.occ_adaptor.BSpline() + self._nurbssurface = OCCNurbsSurface(occ_surface) return self._nurbssurface # ============================================================================== diff --git a/src/compas_occ/conversions/__init__.py b/src/compas_occ/conversions/__init__.py index e57badc47..cc8d3c64b 100644 --- a/src/compas_occ/conversions/__init__.py +++ b/src/compas_occ/conversions/__init__.py @@ -1,43 +1,46 @@ -from .arrays import array1_from_integers1 # noqa: F401 -from .arrays import array1_from_floats1 # noqa: F401 -from .arrays import array2_from_floats2 # noqa: F401 -from .arrays import array1_from_points1 # noqa: F401 -from .arrays import harray1_from_points1 # noqa: F401 -from .arrays import array2_from_points2 # noqa: F401 -from .arrays import points1_from_array1 # noqa: F401 -from .arrays import points2_from_array2 # noqa: F401 -from .arrays import floats2_from_array2 # noqa: F401 +from .arrays import array1_from_integers1 +from .arrays import array1_from_floats1 +from .arrays import array2_from_floats2 +from .arrays import array1_from_points1 +from .arrays import harray1_from_points1 +from .arrays import array2_from_points2 +from .arrays import points1_from_array1 +from .arrays import points2_from_array2 +from .arrays import floats2_from_array2 -from .geometry import compas_point_to_occ_point # noqa: F401 -from .geometry import compas_vector_to_occ_vector # noqa: F401 -from .geometry import compas_vector_to_occ_direction # noqa: F401 -from .geometry import compas_line_to_occ_line # noqa: F401 -from .geometry import compas_plane_to_occ_plane # noqa: F401 -from .geometry import compas_plane_to_occ_ax2 # noqa: F401 -from .geometry import compas_plane_to_occ_ax3 # noqa: F401 -from .geometry import compas_frame_to_occ_ax2 # noqa: F401 -from .geometry import compas_frame_to_occ_ax3 # noqa: F401 -from .geometry import compas_circle_to_occ_circle # noqa: F401 -from .geometry import compas_sphere_to_occ_sphere # noqa: F401 -from .geometry import compas_cylinder_to_occ_cylinder # noqa: F401 -from .geometry import compas_cone_to_occ_cone # noqa: F401 -from .geometry import compas_torus_to_occ_torus # noqa: F401 +from .geometry import compas_axis_to_occ_axis +from .geometry import compas_circle_to_occ_circle +from .geometry import compas_cone_to_occ_cone +from .geometry import compas_cylinder_to_occ_cylinder +from .geometry import compas_frame_to_occ_ax2 +from .geometry import compas_frame_to_occ_ax3 +from .geometry import compas_line_to_occ_line +from .geometry import compas_plane_to_occ_plane +from .geometry import compas_plane_to_occ_ax2 +from .geometry import compas_plane_to_occ_ax3 +from .geometry import compas_point_to_occ_point +from .geometry import compas_sphere_to_occ_sphere +from .geometry import compas_torus_to_occ_torus +from .geometry import compas_vector_to_occ_vector +from .geometry import compas_vector_to_occ_direction -from .geometry import compas_point_from_occ_point # noqa: F401 -from .geometry import compas_point_from_occ_point2d # noqa: F401 -from .geometry import compas_vector_from_occ_axis # noqa: F401 -from .geometry import compas_vector_from_occ_direction # noqa: F401 -from .geometry import compas_vector_from_occ_vector # noqa: F401 -from .geometry import compas_vector_from_occ_vector2d # noqa: F401 -from .geometry import compas_line_from_occ_line # noqa: F401 -from .geometry import compas_plane_from_occ_plane # noqa: F401 -from .geometry import compas_circle_from_occ_circle # noqa: F401 -from .geometry import compas_ellipse_from_occ_ellipse # noqa: F401 -from .geometry import compas_frame_from_occ_ax2 # noqa: F401 -from .geometry import compas_frame_from_occ_ax3 # noqa: F401 -from .geometry import compas_cylinder_from_occ_cylinder # noqa: F401 +from .geometry import compas_axis_from_occ_axis +from .geometry import compas_circle_from_occ_circle +from .geometry import compas_cylinder_from_occ_cylinder +from .geometry import compas_ellipse_from_occ_ellipse +from .geometry import compas_frame_from_occ_ax2 +from .geometry import compas_frame_from_occ_ax3 +from .geometry import compas_frame_from_occ_location +from .geometry import compas_line_from_occ_line +from .geometry import compas_plane_from_occ_plane +from .geometry import compas_point_from_occ_point +from .geometry import compas_point_from_occ_point2d +from .geometry import compas_vector_from_occ_axis +from .geometry import compas_vector_from_occ_direction +from .geometry import compas_vector_from_occ_vector +from .geometry import compas_vector_from_occ_vector2d -from .transformations import compas_transformation_to_trsf # noqa: F401 +from .transformations import compas_transformation_to_trsf from .meshes import compas_mesh_to_occ_shell from .meshes import compas_quadmesh_to_occ_shell @@ -59,8 +62,12 @@ "compas_cone_to_occ_cone", "compas_cylinder_from_occ_cylinder", "compas_cylinder_to_occ_cylinder", - "compas_frame_from_location", + "compas_ellipse_from_occ_ellipse", + "compas_frame_from_occ_ax2", "compas_frame_from_occ_ax3", + "compas_frame_from_occ_location", + "compas_frame_to_occ_ax2", + "compas_frame_to_occ_ax3", "compas_line_from_occ_line", "compas_line_to_occ_line", "compas_plane_from_occ_plane", @@ -76,6 +83,7 @@ "compas_vector_to_occ_direction", "compas_vector_to_occ_vector", "compas_vector_from_occ_axis", + "compas_vector_from_occ_direction", "compas_vector_from_occ_vector", "compas_vector_from_occ_vector2d", "compas_mesh_to_occ_shell", diff --git a/src/compas_occ/conversions/geometry.py b/src/compas_occ/conversions/geometry.py index 0c02258e1..64c933dae 100644 --- a/src/compas_occ/conversions/geometry.py +++ b/src/compas_occ/conversions/geometry.py @@ -13,6 +13,7 @@ from compas.geometry import Cylinder from compas.geometry import Cone from compas.geometry import Torus +from compas.geometry import Transformation from OCC.Core.gp import gp_Ax1 from OCC.Core.gp import gp_Ax2 @@ -30,6 +31,7 @@ from OCC.Core.gp import gp_Cylinder from OCC.Core.gp import gp_Cone from OCC.Core.gp import gp_Torus +from OCC.Core.TopLoc import TopLoc_Location # ============================================================================= @@ -932,6 +934,38 @@ def compas_frame_from_occ_ax3( ) +def compas_frame_from_occ_location(location: TopLoc_Location) -> Frame: + """Construct a COMPAS frame from an OCC location. + + Parameters + ---------- + location : ``TopLoc_Location`` + The OCC location. + + Returns + ------- + :class:`~compas.geometry.Frame` + + Examples + -------- + >>> from OCC.Core.TopLoc import TopLoc_Location + >>> from compas_occ.conversions import compas_frame_from_occ_location + >>> location = TopLoc_Location() + >>> compas_frame_from_occ_location(location) + Frame(Point(0.000, 0.000, 0.000), Vector(1.000, 0.000, 0.000), Vector(0.000, 1.000, 0.000)) + + """ + t = location.Transformation() + + # transformation.Value is a 1-based 3x4 matrix + rows, columns = 3, 4 + matrix = [ + [t.Value(i, j) for j in range(1, columns + 1)] for i in range(1, rows + 1) + ] + matrix.append([0.0, 0.0, 0.0, 1.0]) # COMPAS wants a 4x4 matrix + return Frame.from_transformation(Transformation(matrix)) + + def compas_circle_from_occ_circle( circ: gp_Circ, cls: Optional[Type[Circle]] = None, diff --git a/src/compas_occ/geometry/curves/curve2d.py b/src/compas_occ/geometry/curves/curve2d.py index 2ca727468..57374a90c 100644 --- a/src/compas_occ/geometry/curves/curve2d.py +++ b/src/compas_occ/geometry/curves/curve2d.py @@ -43,10 +43,11 @@ class OCCCurve2d(Curve): """ + _occ_curve: Geom2d_Curve + def __init__(self, occ_curve: Geom2d_Curve, name=None): super().__init__(name=name) self._dimension = 2 - self._occ_curve = Geom2d_Curve() self.occ_curve = occ_curve def __eq__(self, other: "OCCCurve2d") -> bool: