Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
7e1d7e6
WIP: start of a compas.core.Brep implementation
Jul 12, 2022
a062549
added basic implementations for edge, face, vertex and loop
Jul 13, 2022
ab65dc7
formatted with black
Jul 13, 2022
9027829
BRep->Brep, fixed pluging signatures, fixed call to default constructor
Jul 18, 2022
f937532
added interfaces for Brep components in compas.geometry
Jul 18, 2022
96b0e1a
fixed serialization
Jul 18, 2022
19b5dd6
WIP: reconstructing brep
Jul 21, 2022
4075a41
solved invalid geometry
Jul 21, 2022
84d356b
valid brep reconstruction
Jul 21, 2022
c2b3724
tidying of brep reconstruction
Jul 22, 2022
ad9ccda
added error handling to brep reconstruction
Jul 22, 2022
82c53f5
added circle and nurbs curves to possible edge geometries
Jul 22, 2022
1d6dd82
cleanup, linting and formatting
Jul 22, 2022
c86095d
updated CHANGELOG
Jul 22, 2022
6536d35
fixed ambiguous variable names
Jul 22, 2022
86519a3
updated some comments
Jul 25, 2022
d67a810
implemented Geometry interface in Brep, removed None syntax error
Jul 25, 2022
cc3a022
added documentation, started Brep json schema
Jul 26, 2022
89d4d53
added trim operation to brep
Jul 26, 2022
62e9f1c
updated tutorial
Jul 27, 2022
81dc3cf
fixed indentation errors in tutorial
Jul 27, 2022
ddc6cb9
removed already implemented methods
Jul 27, 2022
f636dc8
added docstrings
Jul 27, 2022
64fa58b
fixed weird trimming bug on de-serialized brep
Jul 28, 2022
550099d
dtype hack for backend agnostic de-serialization of brep
Jul 28, 2022
713141b
added turorial screenshots
Jul 28, 2022
66c3335
removed unused import
chenkasirer Aug 9, 2022
0b92fdb
Merge branch 'main' into geometry_brep
chenkasirer Aug 10, 2022
a40516d
completed missing docstrings
chenkasirer Aug 15, 2022
c529ec1
formatted with black
chenkasirer Aug 15, 2022
877fed9
new classes inherit from object
chenkasirer Aug 23, 2022
a2e2fce
fixed brep docstrings
chenkasirer Aug 23, 2022
48d9a9e
standardized docstrings in brep modules
chenkasirer Aug 24, 2022
7879313
remove property docstrings
chenkasirer Aug 24, 2022
2042d25
standardized docstrings in compas_rhino
chenkasirer Aug 25, 2022
937da8e
small docstring corrections
chenkasirer Aug 25, 2022
b273650
removed unused module attribute
chenkasirer Aug 25, 2022
d2540f7
Brep.trim takes cutting plane also as Plane
chenkasirer Aug 25, 2022
0e62739
black formatting
chenkasirer Aug 25, 2022
84b8dfd
fixed typo in conf.py
chenkasirer Aug 25, 2022
4d5d249
minor docs fixes
chenkasirer Aug 26, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

* Added pluggable `Brep` support with `compas.geometry.brep`.
* Added Rhino `Brep` plugin in `compas_rhino.geometry.brep`.

### Changed

### Removed
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ def patched_parse(self):
self._sections["keys"] = self._parse_keys_section
self._sections["attributes"] = self._parse_attributes_section
self._sections["class attributes"] = self._parse_class_attributes_section
self._sections["others attributes"] = self._parse_other_attributes_section
self._sections["other attributes"] = self._parse_other_attributes_section
self._unpatched_parse()


Expand Down
1 change: 1 addition & 0 deletions docs/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Tutorial

tutorial/data
tutorial/geometry
tutorial/brep
tutorial/networks
tutorial/meshes
tutorial/volmeshes
Expand Down
150 changes: 150 additions & 0 deletions docs/tutorial/brep.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
***********************
Boundary Representation
***********************

.. rst-class:: lead

Boundary representation (Brep) support is realized in COMPAS using its `plugin` system.
The expected interface for Brep related classes is defined in the :mod:`compas.geometry.brep` module
whereas the actual implementation is context dependent and implemented using plugins.

.. currentmodule:: compas.geometry

.. highlight:: python

Brep Basics
===========
Brep is a data structure used to describe a shape by means of recording topological and geometrical information of the shape's boundaries.
Some topological properties are associated with an underlying geometry, while others are purely topological.

A Brep is comprised of the following:

.. rst-class:: table table-bordered

.. list-table::
:widths: auto
:header-rows: 1

* - Topology
- Geometry
- Description
* - Vertex
- 3D Point
- The most basic element of a Brep, geometrically described as a point in 3D space.
* - Edge
- 3D Curve
- An edge has a start vertex and an end vertex. The underlying 3D curve describes the geometry of the edge (Line, Circle etc.). Closed edges feature start_vertex == end_vertex.
* - Loop
- None
- A collection of trims which define the inner or outer boundary of a face.
* - Face
- Surface
- Defines the geometry of one of the shape's faces using a surface. Associated with at least one loop which describes the trimmed outer boundary of the surface. Inner loops are referred to as holes in the face.
* - Trim
- 2D Curve
- A 2D curve which trims a face. Trims are associated with a corresponding edge.


Getting Started with COMPAS Brep
================================

To create an empty `Brep`

.. code-block::

>>> from compas.geometry import Brep
>>> brep = Brep()


Notice that the type of the actual instance created by `Brep()` will differ depending on the currently available backend.
For example, when in Rhino

.. code-block::

>>> type(brep)
compas_rhino.geometry.RhinoBrep

Every backend is expected to implement some alternative constructors

.. code-block::

>>> from compas.geometry import Box
>>> from compas.geometry import Brep
>>> ...
>>> box = Box.from_width_height_depth(5., 5., 5.)
>>> brep_box = Brep.from_box(box)


`Brep` can also be instantiated from an instance of a backend native `Brep`

.. code-block::

>>> import Rhino
>>> from compas.geometry import Brep
>>> ...
>>> Brep.from_brep(Rhino.Geometry.Brep())

Brep operations
===============

Trimming a Brep in Grasshopper

.. code-block::

from compas.geometry import Frame
from compas.geometry import Point
from compas.geometry import Brep

box = Box.from_width_height_depth(5, 5, 10)

brep = Brep.from_box(box)
cutting_plane = Frame(Point(0, 2.5, 0), [1, 0, 0], [0, 1, 1.5])

brep.trim(cutting_plane)

|pic1| |pic2|

.. |pic1| image:: files/box_w_plane.png
:width: 48%

.. |pic2| image:: files/trimmed_box.png
:width: 48%


Implementing a new backend
==========================

If you wish to create an additional backend to `Brep` in your package, this can be done using the plugin system of COMPAS.

Create a Brep type in your package which inherits from :class:`compas.geometry.Brep` and override the `__new__` dundle as follows:

.. code-block::

from compas.geometry import Brep

class OccBrep(Brep):

def __new__(cls, *args, **kwargs):
# This breaks the endless recursion when calling `compas.geometry.Brep()` and allows
# having Brep here as the parent class. Otherwise OccBrep() calls Brep.__new__()
# which calls OccBrep() and so on...
return object.__new__(cls, *args, **kwargs)

Whenever instantiating `compas.geometry.Brep`, the actual instantiation is delegated to the available factory plugin

.. code-block::

@plugin(category="factories", requires=["OCC"])
def new_brep(*args, **kwargs):
# Note: this is called inside Brep.__new__, thus Brep.__init__ will be ran by the interpreter
# upon returning from __new__. This means any fully initialized instance returned here will be overwritten!
return object.__new__(OccBrep, *args, **kwargs)

Now, a call to `compas.geometry.Brep()` will result in an instance of `your.package.OccBrep`, given that the plugin is available and loaded.
`OccBrep` encapsulates the native Brep object available by the underlying implementation. If necessary, it can be accessed using `occ_brep_instance.native_brep`.

Implementing the `compas.data.Data` interface
---------------------------------------------
A powerful feature of this approach is to be able to serialize a Brep created in one backend and de-serialize it using another.
For that, it is required that `your.package.OccBrep` implements the :class:`compas.data.Data` interface and follows the unified serialization protocol.

Binary file added docs/tutorial/files/box_w_plane.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/tutorial/files/trimmed_box.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions src/compas/data/schemas/brep.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "brep.json",
"$compas": "1.16.0",
"type": "object",
"properties": {
"faces": {
"type": "array",
"minItems": 1,
"items": {}
}
}
}
49 changes: 48 additions & 1 deletion src/compas/geometry/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,25 @@
Torus
Polyhedron

Boundary Representation (Brep)
------------------------------

.. autosummary::
:toctree: generated/
:nosignatures:

Brep
BrepVertex
BrepEdge
BrepLoop
BrepFace

BrepType
BrepOrientation

BrepError
BrepInvalidError
BrepTrimmingError

Transformations
===============
Expand Down Expand Up @@ -897,6 +916,21 @@
NurbsSurface
)

from .brep import (
Brep,
BrepVertex,
BrepFace,
BrepLoop,
BrepEdge,

BrepType,
BrepOrientation,

BrepError,
BrepInvalidError,
BrepTrimmingError,
)

__all__ = [
'close',
'allclose',
Expand Down Expand Up @@ -1201,7 +1235,20 @@
'NurbsCurve',

'Surface',
'NurbsSurface'
'NurbsSurface',

"Brep",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will need to expose vertex, edge, loop, and face as well...

"BrepLoop",
"BrepEdge",
"BrepVertex",
"BrepFace",

"BrepType",
"BrepOrientation",

"BrepError",
"BrepInvalidError",
"BrepTrimmingError",
]

if not compas.IPY:
Expand Down
39 changes: 39 additions & 0 deletions src/compas/geometry/brep/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from .brep import Brep
from .brep import BrepOrientation
from .brep import BrepType
from .edge import BrepEdge
from .loop import BrepLoop
from .face import BrepFace
from .vertex import BrepVertex


class BrepError(Exception):
"""Represents a generic error in the Brep context"""

pass


class BrepInvalidError(BrepError):
"""Raised when the process of re-constructing a Brep has resulted in an invalid Brep"""

pass


class BrepTrimmingError(BrepError):
"""Raised when a trimming operation has failed or had not result"""

pass


__all__ = [
"Brep",
"BrepEdge",
"BrepLoop",
"BrepFace",
"BrepVertex",
"BrepOrientation",
"BrepType",
"BrepError",
"BrepInvalidError",
"BrepTrimmingError",
]
Loading