Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(polyskel): Remove segments that lie outside boundary #232

Merged
merged 1 commit into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 3 additions & 1 deletion ladybug_geometry_polyskel/polygraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
from ladybug_geometry.geometry2d import LineSegment2D, Polygon2D
from ladybug_geometry.intersection2d import intersect_line2d_infinite

from .polyskel import skeleton_as_edge_list, _intersect_skeleton_segments
from .polyskel import skeleton_as_edge_list, _intersect_skeleton_segments, \
_remove_segments_outside_boundary


def _vector2hash(vector, tol):
Expand Down Expand Up @@ -640,6 +641,7 @@ def skeleton_as_directed_graph(boundary, holes=None, tolerance=1e-5):
# get the segments representing the straight skeleton
skeleton = skeleton_as_edge_list(boundary, holes, tolerance)
skeleton, is_intersect_topology = _intersect_skeleton_segments(skeleton, tolerance)
skeleton = _remove_segments_outside_boundary(skeleton, boundary, tolerance)

# ensure the boundary and holes are oriented correctly for the graph
if boundary.is_clockwise:
Expand Down
32 changes: 32 additions & 0 deletions ladybug_geometry_polyskel/polyskel.py
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,37 @@ def _intersect_skeleton_segments(skeleton, tolerance=1e-5):
return split_skeleton, is_intersect_topology


def _remove_segments_outside_boundary(skeleton, boundary, tolerance=1e-5):
"""Remove LineSegment2D that are outside the boundary of the parent shape.

This can be used to clean up the result after intersection of segments
since the skeleton routines can sometimes fail to produce a result that
is completely within the parent shape.

Args:
skeleton: A list of ladybug-geometry LineSegment2D for the segments
of the straight skeleton.
boundary: A Polygon2D for the boundary of the shape. Segments that lie
outside of this boundary beyond the tolerance will be removed from
the result.
tolerance: The tolerance for distinguishing whether skeleton points lie
outside the boundary.

Returns:
A tuple with two items.

* clean_skeleton -- A list of LineSegment2D objects with segments removed
that outside of the boundary.
"""
clean_skeleton = []
for seg in skeleton:
p1, p2 = seg.p1, seg.p2
if boundary.point_relationship(p2, tolerance) >= 0 and \
boundary.point_relationship(p1, tolerance) >= 0:
clean_skeleton.append(seg)
return clean_skeleton


def skeleton_as_subtree_list(boundary, holes=None, tolerance=1e-5):
"""Get a straight skeleton as a list of Subtree source and sink points.

Expand Down Expand Up @@ -817,4 +848,5 @@ def skeleton_as_edge_list(boundary, holes=None, tolerance=1e-5, intersect=False)

if intersect: # intersect skeleton segments to split them
skeleton, _ = _intersect_skeleton_segments(skeleton, tolerance)
skeleton = _remove_segments_outside_boundary(skeleton, boundary, tolerance)
return skeleton
Loading