Skip to content

Commit

Permalink
various fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
tomvanmele committed Jan 20, 2025
1 parent 7ea3fbd commit 9d9284c
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 146 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

* Added implementation for `compas_rhino.geometry.RhinoBrep.from_step`.

### Changed

* Fixed bug in `compas.geometry.Polygon.points` setter by removing duplicate points if they exist.
* Fixed bug in `compas.geometry.Polygon.plane` by aligning the normal of the bestfit plane with the approximate normal of the polygon faces.
* Changed the order of face vertices in `compas.geometry.Surface.to_vertices_and_faces` to a counter clockwise cycling direction and outward facing normals for curved surfaces.

### Removed


Expand Down
27 changes: 23 additions & 4 deletions src/compas/geometry/polygon.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from compas.geometry import earclip_polygon
from compas.geometry import is_coplanar
from compas.geometry import is_polygon_convex
from compas.geometry import normal_triangle
from compas.geometry import transform_points
from compas.itertools import pairwise
from compas.tolerance import TOL
Expand Down Expand Up @@ -135,9 +136,15 @@ def points(self):

@points.setter
def points(self, points):
if points[-1] == points[0]:
points = points[:-1]
self._points = [Point(*xyz) for xyz in points]
previous = Point(*points[0])
self._points = [previous]
for xyz in points[1:]:
if previous == xyz:
continue
previous = Point(*xyz)
self._points.append(previous)
if self._points[0] == self._points[-1]:
del self._points[-1]
self._lines = None

@property
Expand Down Expand Up @@ -173,7 +180,19 @@ def normal(self):

@property
def plane(self):
return Plane.from_points(self.points)
# by just taking the bestfit plane,
# the normal might not be aligned with the winding direciton of the polygon
# this can be solved by comparing the plane normal with the normal of one of the triangles of the polygon
# for convex polygons this is always correct
# in the case of concave polygons it may not be
# to be entirely correct, the check should be done with one of the polygon ears after earclipping
# however, this is costly
# and even then it is only correct if we assume th polygon is plat enough to have a consistent direction
normal = normal_triangle([self.centroid] + self.points[:2])
plane = Plane.from_points(self.points)
if plane.normal.dot(normal) < 0:
plane.normal.flip()
return plane

@property
def frame(self):
Expand Down
2 changes: 1 addition & 1 deletion src/compas/geometry/shapes/sphere.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ def from_point_and_radius(cls, point, radius): # type: (...) -> Sphere
# Discretisation
# ==========================================================================

def compute_vertices(self): # type: () -> list[float]
def compute_vertices(self): # type: () -> list[list[float]]
"""Compute the vertices of the discrete representation of the sphere.
Returns
Expand Down
4 changes: 2 additions & 2 deletions src/compas/geometry/surfaces/surface.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,9 +252,9 @@ def to_vertices_and_faces(self, nu=16, nv=16, du=None, dv=None):
faces = [
[
i * (nv + 1) + j,
(i + 1) * (nv + 1) + j,
(i + 1) * (nv + 1) + j + 1,
i * (nv + 1) + j + 1,
(i + 1) * (nv + 1) + j + 1,
(i + 1) * (nv + 1) + j,
]
for i, j in product(range(nu), range(nv))
]
Expand Down
39 changes: 22 additions & 17 deletions src/compas_rhino/geometry/brep/__init__.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import Rhino # noqa: F401
import Rhino # type: ignore # noqa: F401

from compas.plugins import plugin

from .brep import RhinoBrep


@plugin(category="factories", requires=["Rhino"])
def new_brep(*args, **kwargs):
return object.__new__(RhinoBrep)
def from_boolean_difference(*args, **kwargs):
return RhinoBrep.from_boolean_difference(*args, **kwargs)


@plugin(category="factories", requires=["Rhino"])
def from_extrusion(*args, **kwargs):
return RhinoBrep.from_extrusion(*args, **kwargs)
def from_boolean_intersection(*args, **kwargs):
return RhinoBrep.from_boolean_intersection(*args, **kwargs)


@plugin(category="factories", requires=["Rhino"])
def from_native(*args, **kwargs):
return RhinoBrep.from_native(*args, **kwargs)
def from_boolean_union(*args, **kwargs):
return RhinoBrep.from_boolean_union(*args, **kwargs)


@plugin(category="factories", requires=["Rhino"])
Expand All @@ -31,8 +31,13 @@ def from_cylinder(*args, **kwargs):


@plugin(category="factories", requires=["Rhino"])
def from_sphere(*args, **kwargs):
return RhinoBrep.from_sphere(*args, **kwargs)
def from_extrusion(*args, **kwargs):
return RhinoBrep.from_extrusion(*args, **kwargs)


@plugin(category="factories", requires=["Rhino"])
def from_loft(*args, **kwargs):
return RhinoBrep.from_loft(*args, **kwargs)


@plugin(category="factories", requires=["Rhino"])
Expand All @@ -41,20 +46,20 @@ def from_mesh(*args, **kwargs):


@plugin(category="factories", requires=["Rhino"])
def from_loft(*args, **kwargs):
return RhinoBrep.from_loft(*args, **kwargs)
def from_native(*args, **kwargs):
return RhinoBrep.from_native(*args, **kwargs)


@plugin(category="factories", requires=["Rhino"])
def from_boolean_difference(*args, **kwargs):
return RhinoBrep.from_boolean_difference(*args, **kwargs)
def from_sphere(*args, **kwargs):
return RhinoBrep.from_sphere(*args, **kwargs)


@plugin(category="factories", requires=["Rhino"])
def from_boolean_intersection(*args, **kwargs):
return RhinoBrep.from_boolean_intersection(*args, **kwargs)
def from_step(*args, **kwargs):
return RhinoBrep.from_step(*args, **kwargs)


@plugin(category="factories", requires=["Rhino"])
def from_boolean_union(*args, **kwargs):
return RhinoBrep.from_boolean_union(*args, **kwargs)
def new_brep(*args, **kwargs):
return object.__new__(RhinoBrep)
Loading

0 comments on commit 9d9284c

Please sign in to comment.