Skip to content

Commit

Permalink
is_equal, is_same
Browse files Browse the repository at this point in the history
  • Loading branch information
tomvanmele committed Nov 16, 2023
1 parent 03bb40e commit d95a6b1
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 75 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Added correct type info to `OCCBrepEdge.occ_edge`.
* Added correct type info to `OCCBrepLoop.occ_wire`.
* Added correct type info to `OCCBrepFace.occ_face`.
* Added `OCCBrepLoop.occ_shape`.
* Added `OCCBrep.from_iges`.
* Added `OCCBrep.to_stl`.
* Added `OCCBrep.to_iges`.
* Added `OCCBrepVertex.is_same` and `OCCBrepVertex.is_equal`.
* Added `OCCBrepEdge.is_same` and `OCCBrepEdge.is_equal`.
* Added `OCCBrepLoop.is_same` and `OCCBrepLoop.is_equal`.
* Added `OCCBrepFace.is_same` and `OCCBrepFace.is_equal`.

### Changed

Expand Down
2 changes: 1 addition & 1 deletion docs/examples/breps/brep_with_holes.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
loop2 = OCCBrepLoop.from_edges([OCCBrepEdge.from_circle(circle2)])
loop3 = OCCBrepLoop.from_edges([OCCBrepEdge.from_circle(circle3)])

face = OCCBrepFace.from_plane(Plane.worldXY(), udomain=(-5, 5), vdomain=(-5, 5))
face = OCCBrepFace.from_plane(Plane.worldXY(), domain_u=(-5, 5), domain_v=(-5, 5))
face.add_loops([loop1, loop2, loop3], reverse=True)

brep = Brep.from_brepfaces([face])
Expand Down
203 changes: 134 additions & 69 deletions src/compas_occ/brep/brep.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@
from OCC.Core.BRepCheck import BRepCheck_Status
from OCC.Core.BRepExtrema import BRepExtrema_ShapeProximity
from OCC.Core.BRepFilletAPI import BRepFilletAPI_MakeFillet
from OCC.Core.BRepGProp import brepgprop_VolumeProperties
from OCC.Core.BRepGProp import brepgprop_SurfaceProperties
from OCC.Core.BRepGProp import brepgprop
from OCC.Core.BRepMesh import BRepMesh_IncrementalMesh
from OCC.Core.BRepOffsetAPI import BRepOffsetAPI_MakePipe
from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakePrism
Expand Down Expand Up @@ -58,7 +57,6 @@
from OCC.Core.TopoDS import TopoDS_Compound
from OCC.Core.TopTools import TopTools_IndexedDataMapOfShapeListOfShape
from OCC.Core.TopTools import TopTools_ListIteratorOfListOfShape # type: ignore
from OCC.Extend.DataExchange import read_step_file

from compas_occ.conversions import triangle_to_face
from compas_occ.conversions import quad_to_face
Expand Down Expand Up @@ -348,47 +346,158 @@ def frame(self) -> Frame:
@property
def area(self) -> float:
props = GProp_GProps()
brepgprop_SurfaceProperties(self.occ_shape, props)
brepgprop.SurfaceProperties(self.occ_shape, props)
return props.Mass()

@property
def volume(self) -> float:
props = GProp_GProps()
brepgprop_VolumeProperties(self.occ_shape, props)
brepgprop.VolumeProperties(self.occ_shape, props)
return props.Mass()

@property
def centroid(self) -> Point:
props = GProp_GProps()
brepgprop_VolumeProperties(self.occ_shape, props)
brepgprop.VolumeProperties(self.occ_shape, props)
pnt = props.CentreOfMass()
return compas_point_from_occ_point(pnt)

# ==============================================================================
# Constructors
# Read/Write
# ==============================================================================

@classmethod
def from_shape(cls, shape: TopoDS_Shape) -> "OCCBrep":
def from_step(cls, filename: str) -> "OCCBrep":
"""
Construct a BRep from an OCC shape.
Conctruct a BRep from the data contained in a STEP file.
Parameters
----------
shape : ``TopoDS_Shape``
The OCC shape.
filename : str
Returns
-------
:class:`~compas_occ.brep.OCCBrep`
"""
brep = cls()
brep.native_brep = shape
return brep
from OCC.Extend.DataExchange import read_step_file

shape = read_step_file(filename)
return cls.from_native(shape) # type: ignore

@classmethod
def from_native(cls, shape: TopoDS_Shape) -> "OCCBrep":
def from_iges(cls, filename: str) -> "OCCBrep":
"""
Conctruct a BRep from the data contained in a IGES file.
Parameters
----------
filename : str
Returns
-------
:class:`~compas_occ.brep.OCCBrep`
"""
from OCC.Extend.DataExchange import read_iges_file

shape = read_iges_file(filename)
return cls.from_native(shape) # type: ignore

def to_step(self, filepath: str, schema: str = "AP203", unit: str = "MM") -> None:
"""
Write the BRep shape to a STEP file.
Parameters
----------
filepath : str
Location of the file.
schema : str, optional
STEP file format schema.
unit : str, optional
Base units for the geometry in the file.
Returns
-------
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.unit", unit)
step_writer.Transfer(self.occ_shape, STEPControl_AsIs)
status = step_writer.Write(filepath)
assert status == IFSelect_RetDone, status

def to_stl(
self,
filepath: str,
linear_deflection: float = 1e-3,
angular_deflection: float = 0.5,
) -> bool:
"""
Write the BRep shape to a STL file.
Parameters
----------
filepath : str
Location of the file.
linear_deflection : float, optional
Allowable deviation between curved geometry and mesh discretisation.
angular_deflection : float, optional
Maximum angle between two adjacent facets.
Returns
-------
None
"""
from OCC.Core.StlAPI import StlAPI_Writer

BRepMesh_IncrementalMesh(
self.occ_shape,
linear_deflection,
theAngDeflection=angular_deflection,
)

stl_writer = StlAPI_Writer()
stl_writer.SetASCIIMode(True)

return stl_writer.Write(self.occ_shape, filepath)

def to_iges(self, filepath: str) -> bool:
"""
Write the BRep shape to a IGES file.
Parameters
----------
filepath : str
Location of the file.
Returns
-------
None
"""
from OCC.Core.IGESControl import IGESControl_Writer

iges_writer = IGESControl_Writer()
if not iges_writer.AddShape(self.occ_shape):
raise Exception("Failed to add shape to IGES writer.")

iges_writer.ComputeModel()
return iges_writer.Write(filepath)

# ==============================================================================
# Constructors
# ==============================================================================

@classmethod
def from_shape(cls, shape: TopoDS_Shape) -> "OCCBrep":
"""
Construct a BRep from an OCC shape.
Expand All @@ -402,24 +511,26 @@ def from_native(cls, shape: TopoDS_Shape) -> "OCCBrep":
:class:`~compas_occ.brep.OCCBrep`
"""
return cls.from_shape(shape)
brep = cls()
brep.native_brep = shape
return brep

@classmethod
def from_step(cls, filename: str) -> "OCCBrep":
def from_native(cls, shape: TopoDS_Shape) -> "OCCBrep":
"""
Conctruct a BRep from the data contained in a STEP file.
Construct a BRep from an OCC shape.
Parameters
----------
filename : str
shape : ``TopoDS_Shape``
The OCC shape.
Returns
-------
:class:`~compas_occ.brep.OCCBrep`
"""
shape = read_step_file(filename)
return cls.from_native(shape) # type: ignore
return cls.from_shape(shape)

@classmethod
def from_polygons(cls, polygons: List[compas.geometry.Polygon]) -> "OCCBrep":
Expand Down Expand Up @@ -778,53 +889,7 @@ def from_boolean_union(cls, A: "OCCBrep", B: "OCCBrep") -> "OCCBrep":
# Converters
# ==============================================================================

# def to_json(self, filepath: str):
# """
# Export the BRep to a JSON file.

# Parameters
# ----------
# filepath : str
# Location of the file.

# Returns
# -------
# None

# """
# with open(filepath, "w") as f:
# self.occ_shape.DumpJson(f)

def to_step(self, filepath: str, schema: str = "AP203", unit: str = "MM") -> None:
"""
Write the BRep shape to a STEP file.
Parameters
----------
filepath : str
Location of the file.
schema : str, optional
STEP file format schema.
unit : str, optional
Base units for the geometry in the file.
Returns
-------
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.unit", unit)
step_writer.Transfer(self.occ_shape, STEPControl_AsIs)
status = step_writer.Write(filepath)
assert status == IFSelect_RetDone, status

def to_tesselation(self, linear_deflection: float = 1e-3) -> Mesh:
def to_tesselation(self, linear_deflection: float = 1) -> Mesh:
"""
Create a tesselation of the shape for visualisation.
Expand Down Expand Up @@ -897,7 +962,7 @@ def to_polygons(self):
polygons.append(Polygon(points))
return polygons

def to_viewmesh(self, linear_deflection=0.001):
def to_viewmesh(self, linear_deflection=1):
"""
Convert the BRep to a view mesh."""
lines = []
Expand Down
7 changes: 3 additions & 4 deletions src/compas_occ/brep/brepface.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
from OCC.Core.BRepAdaptor import BRepAdaptor_Surface
from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeFace
from OCC.Core.BRepAlgo import brepalgo_IsValid
from OCC.Core.BRepGProp import brepgprop_VolumeProperties
from OCC.Core.BRepGProp import brepgprop_SurfaceProperties
from OCC.Core.BRepGProp import brepgprop
from OCC.Core.ShapeFix import ShapeFix_Face
from OCC.Core.GProp import GProp_GProps
from OCC.Core.GeomConvert import GeomConvert_ApproxSurface
Expand Down Expand Up @@ -255,13 +254,13 @@ def loops(self) -> List[OCCBrepLoop]:
@property
def area(self) -> float:
props = GProp_GProps()
brepgprop_SurfaceProperties(self.occ_shape, props)
brepgprop.SurfaceProperties(self.occ_shape, props)
return props.Mass()

@property
def centroid(self) -> compas.geometry.Point:
props = GProp_GProps()
brepgprop_VolumeProperties(self.occ_shape, props)
brepgprop.VolumeProperties(self.occ_shape, props)
pnt = props.CentreOfMass()
return compas_point_from_occ_point(pnt)

Expand Down
5 changes: 4 additions & 1 deletion src/compas_occ/brep/breploop.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,16 @@ def from_data(cls, data):
# OCC Properties
# ==============================================================================

@property
def occ_shape(self) -> TopoDS_Wire:
return self.occ_wire

@property
def occ_wire(self) -> TopoDS_Wire:
return self._occ_wire

@occ_wire.setter
def occ_wire(self, loop: TopoDS_Wire) -> None:
# self._occ_wire = topods.Wire(loop)
self._occ_wire = loop

# ==============================================================================
Expand Down

0 comments on commit d95a6b1

Please sign in to comment.