Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
tomvanmele committed Jul 29, 2024
2 parents e87aebd + bbc802c commit a307f44
Show file tree
Hide file tree
Showing 15 changed files with 518 additions and 5 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

* Added `compas_cgal.straight_skeleton_2.create_interior_straight_skeleton`.
* Added `compas_cgal.straight_skeleton_2.create_interior_straight_skeleton_with_holes`.
* Added `compas_cgal.straight_skeleton_2.create_offset_polygons_2_inner`.
* Added `compas_cgal.straight_skeleton_2.create_offset_polygons_2_outer`.
* Added `compas_cgal.straight_skeleton_2.create_weighted_offset_polygons_2_inner`.
* Added `compas_cgal.straight_skeleton_2.create_weighted_offset_polygons_2_outer`.

### Changed

Expand Down
1 change: 0 additions & 1 deletion docs/PLACEHOLDER

This file was deleted.

1 change: 0 additions & 1 deletion docs/_images/PLACEHOLDER

This file was deleted.

Binary file added docs/_images/cgal_straight_skeleton_2_holes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/api/compas_cgal.straight_skeleton_2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ compas_cgal.straight_skeleton_2
:nosignatures:

create_interior_straight_skeleton
create_interior_straight_skeleton_with_holes
27 changes: 27 additions & 0 deletions docs/examples/straight_skeleton_2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,30 @@

.. literalinclude:: straight_skeleton_2.py
:language: python


.. figure:: /_images/cgal_straight_skeleton_2_holes.png
:figclass: figure
:class: figure-img img-fluid


.. literalinclude:: straight_skeleton_2_holes.py
:language: python


.. figure:: /_images/cgal_straight_skeleton_2_offset.png
:figclass: figure
:class: figure-img img-fluid


.. literalinclude:: straight_skeleton_2_offset.py
:language: python


.. figure:: /_images/cgal_straight_skeleton_2_offset_weighted.png
:figclass: figure
:class: figure-img img-fluid


.. literalinclude:: straight_skeleton_2_offset_weighted.py
:language: python
42 changes: 42 additions & 0 deletions docs/examples/straight_skeleton_2_holes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from compas.datastructures import Graph
from compas.geometry import Polygon
from compas_viewer import Viewer

from compas_cgal.straight_skeleton_2 import create_interior_straight_skeleton_with_holes

points = [
(-1.91, 3.59, 0.0),
(-5.53, -5.22, 0.0),
(-0.39, -1.98, 0.0),
(2.98, -5.51, 0.0),
(4.83, -2.02, 0.0),
(9.70, -3.63, 0.0),
(12.23, 1.25, 0.0),
(3.42, 0.66, 0.0),
(2.92, 4.03, 0.0),
(-1.91, 3.59, 0.0),
]

holes = [
[(0.42, 0.88, 0.0), (1.1, -1.0, 0.0), (-1.97, -0.93, 0.0), (-1.25, 1.82, 0.0)],
[(4.25, -0.64, 0.0), (2.9, -3.03, 0.0), (2.12, -2.16, 0.0), (2.89, -0.36, 0.0)],
[(10.6, 0.29, 0.0), (9.48, -1.54, 0.0), (5.48, -1.26, 0.0), (5.98, -0.04, 0.0)],
]


polygon = Polygon(points)
holes = [Polygon(hole) for hole in holes]
lines = create_interior_straight_skeleton_with_holes(polygon, holes)
graph = Graph.from_lines(lines)

# ==============================================================================
# Viz
# ==============================================================================

viewer = Viewer(width=1600, height=900)
viewer.renderer_config.show_grid = False
viewer.scene.add(graph, edgecolor=(1.0, 0.0, 0.0))
viewer.scene.add(polygon)
for hole in holes:
viewer.scene.add(hole)
viewer.show()
37 changes: 37 additions & 0 deletions docs/examples/straight_skeleton_2_offset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from compas.geometry import Polygon
from compas_viewer import Viewer

from compas_cgal.straight_skeleton_2 import create_offset_polygons_2

points = [
(-1.91, 3.59, 0.0),
(-5.53, -5.22, 0.0),
(-0.39, -1.98, 0.0),
(2.98, -5.51, 0.0),
(4.83, -2.02, 0.0),
(9.70, -3.63, 0.0),
(12.23, 1.25, 0.0),
(3.42, 0.66, 0.0),
(2.92, 4.03, 0.0),
(-1.91, 3.59, 0.0),
]
polygon = Polygon(points)
offset = 1.5

offset_polygons_inner = create_offset_polygons_2(points, offset)
offset_polygons_outer = create_offset_polygons_2(points, -offset)

# ==============================================================================
# Viz
# ==============================================================================

viewer = Viewer(width=1600, height=900)
viewer.scene.add(polygon)
viewer.config.renderer.show_grid = False

for opolygon in offset_polygons_inner:
viewer.scene.add(opolygon, linecolor=(1.0, 0.0, 0.0), facecolor=(1.0, 1.0, 1.0, 0.0))
for opolygon in offset_polygons_outer:
viewer.scene.add(opolygon, linecolor=(0.0, 0.0, 1.0), facecolor=(1.0, 1.0, 1.0, 0.0))

viewer.show()
37 changes: 37 additions & 0 deletions docs/examples/straight_skeleton_2_offset_weighted.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from compas.geometry import Polygon
from compas_viewer import Viewer

from compas_cgal.straight_skeleton_2 import create_weighted_offset_polygons_2

points = [
(-1.91, 3.59, 0.0),
(-5.53, -5.22, 0.0),
(-0.39, -1.98, 0.0),
(2.98, -5.51, 0.0),
(4.83, -2.02, 0.0),
(9.70, -3.63, 0.0),
(12.23, 1.25, 0.0),
(3.42, 0.66, 0.0),
(2.92, 4.03, 0.0),
(-1.91, 3.59, 0.0),
]
polygon = Polygon(points)


distances = [0.1, 0.3, 0.6, 0.1, 0.7, 0.5, 0.2, 0.4, 0.8, 0.2]
weights = [1.0 / d for d in distances]
offset = 1.0
offset_polygons_outer = create_weighted_offset_polygons_2(points, -offset, weights)

# ==============================================================================
# Viz
# ==============================================================================

viewer = Viewer(width=1600, height=900)
viewer.scene.add(polygon)
viewer.config.renderer.show_grid = False

for opolygon in offset_polygons_outer:
viewer.scene.add(opolygon, linecolor=(0.0, 0.0, 1.0), facecolor=(1.0, 1.0, 1.0, 0.0))

viewer.show()
118 changes: 116 additions & 2 deletions src/compas_cgal/straight_skeleton_2.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import numpy as np
from compas.geometry import Polygon
from compas.geometry import normal_polygon
from compas.tolerance import TOL

Expand Down Expand Up @@ -26,7 +27,120 @@ def create_interior_straight_skeleton(points) -> PolylinesNumpy:
If the normal of the polygon is not [0, 0, 1].
"""
points = list(points)
if not TOL.is_allclose(normal_polygon(points, True), [0, 0, 1]):
raise ValueError("Please pass a polygon with a normal vector of [0, 0, 1].")
normal = normal_polygon(points, True)
if not TOL.is_allclose(normal, [0, 0, 1]):
raise ValueError("The normal of the polygon should be [0, 0, 1]. The normal of the provided polygon is {}".format(normal))
V = np.asarray(points, dtype=np.float64)
return straight_skeleton_2.create_interior_straight_skeleton(V)


def create_interior_straight_skeleton_with_holes(points, holes) -> PolylinesNumpy:
"""Compute the skeleton of a polygon with holes.
Parameters
----------
points : list of point coordinates or :class:`compas.geometry.Polygon`
The points of the polygon.
holes : list of list of point coordinates or list of :class:`compas.geometry.Polygon`
The holes of the polygon.
Returns
-------
:attr:`compas_cgal.types.PolylinesNumpy`
The skeleton of the polygon.
Raises
------
ValueError
If the normal of the polygon is not [0, 0, 1].
If the normal of a hole is not [0, 0, -1].
"""
points = list(points)
normal = normal_polygon(points, True)
if not TOL.is_allclose(normal, [0, 0, 1]):
raise ValueError("The normal of the polygon should be [0, 0, 1]. The normal of the provided polygon is {}".format(normal))
V = np.asarray(points, dtype=np.float64)

H = []
for i, hole in enumerate(holes):
points = list(hole)
normal_hole = normal_polygon(points, True)
if not TOL.is_allclose(normal_hole, [0, 0, -1]):
raise ValueError("The normal of the hole should be [0, 0, -1]. The normal of the provided {}-th hole is {}".format(i, normal_hole))
hole = np.asarray(points, dtype=np.float64)
H.append(hole)
return straight_skeleton_2.create_interior_straight_skeleton_with_holes(V, H)


def create_offset_polygons_2(points, offset) -> list[Polygon]:
"""Compute the polygon offset.
Parameters
----------
points : list of point coordinates or :class:`compas.geometry.Polygon`
The points of the polygon.
offset : float
The offset distance. If negative, the offset is outside the polygon, otherwise inside.
Returns
-------
list[:class:`Polygon`]
The offset polygon(s).
Raises
------
ValueError
If the normal of the polygon is not [0, 0, 1].
"""
points = list(points)
normal = normal_polygon(points, True)
if not TOL.is_allclose(normal, [0, 0, 1]):
raise ValueError("The normal of the polygon should be [0, 0, 1]. The normal of the provided polygon is {}".format(normal))
V = np.asarray(points, dtype=np.float64)
offset = float(offset)
if offset < 0: # outside
offset_polygons = straight_skeleton_2.create_offset_polygons_2_outer(V, abs(offset))[1:] # first one is box
else: # inside
offset_polygons = straight_skeleton_2.create_offset_polygons_2_inner(V, offset)
return [Polygon(points.tolist()) for points in offset_polygons]


def create_weighted_offset_polygons_2(points, offset, weights) -> list[Polygon]:
"""Compute the polygon offset with weights.
Parameters
----------
points : list of point coordinates or :class:`compas.geometry.Polygon`
The points of the polygon.
offset : float
The offset distance. If negative, the offset is outside the polygon, otherwise inside.
weights : list of float
The weights for each edge, starting with the edge between the last and the first point.
Returns
-------
list[:class:`Polygon`]
The offset polygon(s).
Raises
------
ValueError
If the normal of the polygon is not [0, 0, 1].
ValueError
If the number of weights does not match the number of points.
"""
points = list(points)
normal = normal_polygon(points, True)
if not TOL.is_allclose(normal, [0, 0, 1]):
raise ValueError("The normal of the polygon should be [0, 0, 1]. The normal of the provided polygon is {}".format(normal))

V = np.asarray(points, dtype=np.float64)
offset = float(offset)
W = np.asarray(weights, dtype=np.float64)
if W.shape[0] != V.shape[0]:
raise ValueError("The number of weights should be equal to the number of points %d != %d." % (W.shape[0], V.shape[0]))
if offset < 0:
offset_polygons = straight_skeleton_2.create_weighted_offset_polygons_2_outer(V, abs(offset), W)[1:]
else:
offset_polygons = straight_skeleton_2.create_weighted_offset_polygons_2_inner(V, offset, W)
return [Polygon(points.tolist()) for points in offset_polygons]
Loading

0 comments on commit a307f44

Please sign in to comment.