22from typing import Optional
33from typing import Union
44
5+ from OCC .Core import APIHeaderSection
56from OCC .Core import Bnd
67from OCC .Core import BOPAlgo
78from OCC .Core import BRep
1516from OCC .Core import BRepMesh
1617from OCC .Core import BRepOffsetAPI
1718from OCC .Core import BRepPrimAPI
19+ from OCC .Core import BRepTools
1820from OCC .Core import GProp
1921from OCC .Core import IFSelect
2022from OCC .Core import IGESControl
2325from OCC .Core import ShapeUpgrade
2426from OCC .Core import STEPControl
2527from OCC .Core import StlAPI
28+ from OCC .Core import TCollection
2629from OCC .Core import TopAbs
2730from OCC .Core import TopExp
2831from OCC .Core import TopLoc
@@ -97,8 +100,8 @@ class OCCBrep(Brep):
97100 @property
98101 def __data__ (self ) -> dict :
99102 return {
100- # "vertices": [vertex.__data__ for vertex in self.vertices],
101- # "edges": [edge.__data__ for edge in self.edges],
103+ "vertices" : [vertex .__data__ for vertex in self .vertices ],
104+ "edges" : [edge .__data__ for edge in self .edges ],
102105 "faces" : [face .__data__ for face in self .faces ],
103106 }
104107
@@ -131,6 +134,12 @@ def __init__(self) -> None:
131134 self ._shells = None
132135 self ._solids = None
133136
137+ self ._aabb = None
138+ self ._obb = None
139+ self ._area = None
140+ self ._volume = None
141+ self ._centroid = None
142+
134143 def copy (self ) -> "OCCBrep" :
135144 """Deep-copy this BRep using the native OCC copying mechanism.
136145
@@ -232,11 +241,11 @@ def is_surface(self) -> bool:
232241 @property
233242 def points (self ) -> list [Point ]:
234243 points = []
235- seen = []
244+ # seen = []
236245 for vertex in self .vertices :
237- if any (vertex .is_same (test ) for test in seen ):
238- continue
239- seen .append (vertex )
246+ # if any(vertex.is_same(test) for test in seen):
247+ # continue
248+ # seen.append(vertex)
240249 points .append (vertex .point )
241250 return points
242251
@@ -346,22 +355,28 @@ def frame(self) -> Frame:
346355
347356 @property
348357 def area (self ) -> float :
358+ # if self._area is None:
349359 props = GProp .GProp_GProps ()
350360 BRepGProp .brepgprop .SurfaceProperties (self .native_brep , props )
351- return props .Mass ()
361+ self ._area = props .Mass ()
362+ return self ._area
352363
353364 @property
354365 def volume (self ) -> float :
366+ # if self._volume is None:
355367 props = GProp .GProp_GProps ()
356368 BRepGProp .brepgprop .VolumeProperties (self .occ_shape , props )
357- return props .Mass ()
369+ self ._volume = props .Mass ()
370+ return self ._volume
358371
359372 @property
360373 def centroid (self ) -> Point :
374+ # if self._centroid is None:
361375 props = GProp .GProp_GProps ()
362376 BRepGProp .brepgprop .VolumeProperties (self .occ_shape , props )
363377 pnt = props .CentreOfMass ()
364- return point_to_compas (pnt )
378+ self ._centroid = point_to_compas (pnt )
379+ return self ._centroid
365380
366381 @property
367382 def aabb (self ) -> Box :
@@ -384,7 +399,7 @@ def convex_hull(self) -> Mesh:
384399 # ==============================================================================
385400
386401 @classmethod
387- def from_step (cls , filename : Union [str , pathlib .Path ], solid : bool = True ) -> "OCCBrep" :
402+ def from_step (cls , filename : Union [str , pathlib .Path ], heal : bool = False , solid : bool = False ) -> "OCCBrep" :
388403 """
389404 Conctruct a BRep from the data contained in a STEP file.
390405
@@ -400,9 +415,10 @@ def from_step(cls, filename: Union[str, pathlib.Path], solid: bool = True) -> "O
400415 :class:`compas_occ.brep.OCCBrep`
401416
402417 """
403- shape = DataExchange .read_step_file (str (filename ))
418+ shape = DataExchange .read_step_file (str (filename ), verbosity = False )
404419 brep = cls .from_native (shape ) # type: ignore
405- brep .heal ()
420+ if heal :
421+ brep .heal ()
406422 if solid :
407423 brep .make_solid ()
408424 return brep
@@ -431,7 +447,35 @@ def from_iges(cls, filename: Union[str, pathlib.Path], solid: bool = True) -> "O
431447 brep .make_solid ()
432448 return brep
433449
434- def to_step (self , filepath : Union [str , pathlib .Path ], schema : str = "AP203" , unit : str = "MM" ) -> None :
450+ def to_brep (
451+ self ,
452+ filepath : Union [str , pathlib .Path ],
453+ ) -> None :
454+ """
455+ Write the BRep shape to a BREP file.
456+
457+ Parameters
458+ ----------
459+ filepath : str | pathlib.Path
460+ Location of the file.
461+
462+ Returns
463+ -------
464+ None
465+
466+ """
467+ BRepTools .breptools .Write (self .native_brep , str (filepath ))
468+
469+ def to_step (
470+ self ,
471+ filepath : Union [str , pathlib .Path ],
472+ schema : str = "AP203" ,
473+ unit : str = "MM" ,
474+ author : Optional [str ] = None ,
475+ name : Optional [str ] = None ,
476+ description : Optional [str ] = None ,
477+ organization : Optional [str ] = None ,
478+ ) -> None :
435479 """
436480 Write the BRep shape to a STEP file.
437481
@@ -449,10 +493,33 @@ def to_step(self, filepath: Union[str, pathlib.Path], schema: str = "AP203", uni
449493 None
450494
451495 """
452- step_writer = STEPControl .STEPControl_Writer ()
496+ writer = STEPControl .STEPControl_Writer ()
497+ Interface .Interface_Static .SetCVal ("write.step.schema" , schema )
453498 Interface .Interface_Static .SetCVal ("write.step.unit" , unit )
454- step_writer .Transfer (self .occ_shape , STEPControl .STEPControl_StepModelType .STEPControl_AsIs ) # type: ignore
455- status = step_writer .Write (str (filepath ))
499+ Interface .Interface_Static .SetCVal ("write.step.product.name" , name or self .name )
500+
501+ writer .Transfer (self .occ_shape , STEPControl .STEPControl_StepModelType .STEPControl_AsIs ) # type: ignore
502+
503+ if author or description or organization :
504+ model = writer .Model ()
505+ model .ClearHeader ()
506+
507+ header = APIHeaderSection .APIHeaderSection_MakeHeader ()
508+
509+ if author :
510+ header .SetAuthorValue (1 , TCollection .TCollection_HAsciiString (author ))
511+ if organization :
512+ org = Interface .Interface_HArray1OfHAsciiString (1 , 1 )
513+ org .SetValue (1 , TCollection .TCollection_HAsciiString (organization ))
514+ if description :
515+ desc = Interface .Interface_HArray1OfHAsciiString (1 , 1 )
516+ desc .SetValue (1 , TCollection .TCollection_HAsciiString (description ))
517+
518+ model .AddHeaderEntity (header .FnValue ())
519+ model .AddHeaderEntity (header .FsValue ())
520+ model .AddHeaderEntity (header .FdValue ())
521+
522+ status = writer .Write (str (filepath ))
456523 assert status == IFSelect .IFSelect_RetDone , status
457524
458525 def to_stl (
@@ -651,7 +718,12 @@ def from_extrusion(
651718 return brep
652719
653720 @classmethod
654- def from_loft (cls , curves : list [OCCCurve ], start : Optional [Point ] = None , end : Optional [Point ] = None ) -> "OCCBrep" :
721+ def from_loft (
722+ cls ,
723+ curves : list [OCCCurve ],
724+ start : Optional [Point ] = None ,
725+ end : Optional [Point ] = None ,
726+ ) -> "OCCBrep" :
655727 """Construct a Brep by lofing through a sequence of curves.
656728
657729 Parameters
@@ -1101,7 +1173,7 @@ def from_boolean_union(
11011173 # Converters
11021174 # ==============================================================================
11031175
1104- def to_tesselation (self , linear_deflection : float = 1 , angular_deflection : float = 0.1 ) -> tuple [Mesh , list [Polyline ]]:
1176+ def to_tesselation (self , linear_deflection : Optional [ float ] = None , angular_deflection : Optional [ float ] = None ) -> tuple [Mesh , list [Polyline ]]:
11051177 """
11061178 Create a tesselation of the shape for visualisation.
11071179
@@ -1117,6 +1189,9 @@ def to_tesselation(self, linear_deflection: float = 1, angular_deflection: float
11171189 tuple[:class:`compas.datastructures.Mesh`, list[:class:`compas.geometry.Polyline`]]
11181190
11191191 """
1192+ linear_deflection = linear_deflection or TOL .lineardeflection
1193+ angular_deflection = angular_deflection or TOL .angulardeflection
1194+
11201195 BRepMesh .BRepMesh_IncrementalMesh (self .occ_shape , linear_deflection , False , angular_deflection , True )
11211196 bt = BRep .BRep_Tool ()
11221197 mesh = Mesh ()
@@ -1156,6 +1231,7 @@ def to_tesselation(self, linear_deflection: float = 1, angular_deflection: float
11561231 node = nodes .Value (i )
11571232 points .append (vertices [node - 1 ])
11581233 polylines .append (Polyline (points ))
1234+ # This might not be necssary
11591235 lines = []
11601236 for edge in self .edges :
11611237 if any (edge .is_same (e ) for e in seen ):
@@ -1954,3 +2030,20 @@ def trimmed(self, plane: compas.geometry.Plane) -> "OCCBrep":
19542030 brep = self .copy ()
19552031 brep .trim (plane )
19562032 return brep
2033+
2034+ def offset (self , distance : float ) -> "OCCBrep" :
2035+ """Construct a thickened copy of the brep.
2036+
2037+ Parameters
2038+ ----------
2039+ distance : float
2040+ The thickness in the form of an offset distance.
2041+
2042+ Returns
2043+ -------
2044+ :class:`OCCBrep`
2045+
2046+ """
2047+ offset = BRepOffsetAPI .BRepOffsetAPI_MakeThickSolid ()
2048+ offset .MakeThickSolidBySimple (self .native_brep , distance )
2049+ return Brep .from_native (offset .Shape ())
0 commit comments