Skip to content

Conversation

@chenkasirer
Copy link
Member

@chenkasirer chenkasirer commented Dec 6, 2022

Updated RhinoBrep serialization format and reconstruction procedure to fix invalid reconstruction on more complex shapes. Highlights are:

  • Changed serialization format to eliminate duplicate elements.

  • Serializing to/from primitives instead of NURBS where possible

  • Moved brep reconstruction logic from RhinoBrep over to a the new brep/builder.py module.

  • Added representation for trims with BrepTrim.

  • Added RhinoNurbsSurface.from_frame

  • Bug fix in a backwards-compatible manner.

  • New feature in a backwards-compatible manner.

  • Breaking change: bug fix or new feature that involve incompatible API changes.

  • Other (e.g. doc update, configuration, etc)

image

Checklist

  • I added a line to the CHANGELOG.md file in the Unreleased section under the most fitting heading (e.g. Added, Changed, Removed).
  • I ran all tests on my computer and it's all green (i.e. invoke test).
  • I ran lint on my computer and there are no errors (i.e. invoke lint).
  • I added new functions/classes and made them available on a second-level import, e.g. compas.datastructures.Mesh.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have added necessary documentation (if appropriate)

@chenkasirer chenkasirer mentioned this pull request Dec 6, 2022
10 tasks
@chenkasirer chenkasirer requested review from gonzalocasas and tomvanmele and removed request for tomvanmele December 6, 2022 12:08
Copy link
Member

@gonzalocasas gonzalocasas left a comment

Choose a reason for hiding this comment

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

I find it hard to judge if the brep parts are correct, but it LGTM!

Comment on lines 10 to 13
West = 3
South = 4
East = 5
North = 6
Copy link
Member

Choose a reason for hiding this comment

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

should these be uppercased?

Copy link
Member Author

Choose a reason for hiding this comment

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

yup!

def _make_surface_from_data(surface_type, surface_data, uv_domain):
if surface_type == "plane":
frame = Frame.from_data(surface_data)
surface = RhinoNurbsSurface.from_frame(frame, uv_domain[0], uv_domain[1], (1, 1), (2, 2))
Copy link
Member

Choose a reason for hiding this comment

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

what's the meaning of (1, 1), (2, 2)? does it need a comment?

Copy link
Member Author

Choose a reason for hiding this comment

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

These are the required constant to create a simple planar NURBS surface with first degree and 2 control point in each direction (4 corners). Agreed with @brgcode these will be moved as default kwargs to the signature of from_frame since these will normally be used.

def _get_curve_geometry(self):
curve = self._edge.EdgeCurve
if self.is_line:
type_ = "line"
Copy link
Member

Choose a reason for hiding this comment

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

what's the meaning of the trailing underscore?

Copy link
Member Author

Choose a reason for hiding this comment

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

sometimes I insist on naming a var type so this is to avoid shadowing the builtin. It's apparently PEP8:

single_trailing_underscore_: used by convention to avoid conflicts with Python keyword, e.g.:

Copy link
Member

Choose a reason for hiding this comment

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

ahhh thanks!

@tomvanmele
Copy link
Member

would it not make more sense to add stuff to the builder instead of adding the builder to each of the from_data functions?

Copy link
Member

@tomvanmele tomvanmele left a comment

Choose a reason for hiding this comment

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

can we a short meeting about the code?
have the feeling it would be more meaningful than writing a thousand comments...

CHANGELOG.md Outdated
### Added

* Added conversion function `frame_to_rhino_plane` to `compas_rhino.conversions`.
* Added `RhinoSuface.from_frame` to `compas_rhino.geometry`.
Copy link
Member

Choose a reason for hiding this comment

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

not important but there is an "r" missing in Surface

Comment on lines +82 to +89
builder = RhinoBrepBuilder()
for v_data in data["vertices"]:
RhinoBrepVertex.from_data(v_data, builder)
for e_data in data["edges"]:
RhinoBrepEdge.from_data(e_data, builder)
for f_data in data["faces"]:
RhinoBrepFace.from_data(f_data, builder)
self._brep = builder.result
Copy link
Member

Choose a reason for hiding this comment

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

would it not make more sense to add stuff to the builder rather than to modify the signature of all the constructors to send the builder around?

Copy link
Member Author

@chenkasirer chenkasirer Dec 6, 2022

Choose a reason for hiding this comment

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

The builder serves:

  • keeps the reconstruction logic in a single place
  • keeps the reconstruction logic separate from the de-serialization
  • makes the reconstruction context (i.e. Brep) available to each of the components while avoiding global state
  • enables the de-serialized elements to hold the native Rhino.Geometry type immediately after de-serialization.

BrepBuilder is the main context, it essentially wraps around the newly created Rhino.Geometry.Brep and holds it until it's properly built.

Since Face, Loop and Trim are nested in each other:

BrepFaceBuilder wraps around Rhino.Geometry.BrepFace and handed over to the loops so that they can add themselves to the face.
BrepLoopBuilder wraps around Rhino.Geometry.BrepLoop and handed over to the trims so that they can add themselves to the loop.

The result property of the builders gives access to the newly built native element once it's ready. BrepLoopBuilder.result returns the Rhino.Geometry.BrepLoop after all the trims have been added to it. BrepFaceBuilder.result returns the Rhino.Geometry.BrepFace after all the loops have been added to it. BrepBuilder.result returns the Rhino.Geometry.Brep after all the vertices, edges and faces have been added to it.

Comment on lines 53 to 54
def result(self):
return self.loop
Copy link
Member

Choose a reason for hiding this comment

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

is this loop somehow updated in the add_trim method

Copy link
Member

Choose a reason for hiding this comment

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

actually, how/when/where is this result attribute actually used (in any of the builder classes)?

"""

def __init__(self, loop=None, instance=None):
Copy link
Member

Choose a reason for hiding this comment

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

could you add the types of these parameters in the docstring above because it is not very clear to me what they are supposed to be

Copy link
Member Author

Choose a reason for hiding this comment

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

renamed and added to docstrings to maybe make some more sense


@classmethod
def from_frame(cls, frame, u_interval, v_interval, uv_degrees, uv_point_counts):
def from_frame(cls, frame, u_interval, v_interval, uv_degrees=(1, 1), uv_point_counts=(2, 2)):
Copy link
Member

Choose a reason for hiding this comment

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

would it not make more sense to do u_degree=1, v_degree=1, u_count=2, v_count=2? since this is how it is done for the intervals as well...

Copy link
Member Author

Choose a reason for hiding this comment

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

agree. done.

@chenkasirer chenkasirer merged commit 257e8b4 into main Dec 7, 2022
@chenkasirer chenkasirer deleted the rhino_brep branch December 7, 2022 19:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants