I wonder if anyone can spot where I’m going wrong here? I’m just trying to get the left and right edges of apertures using the
geometry3d.face.Face3D.get_left_right_vertical_edges() method, but I am getting inconsistent results for some reason?
Sometimes the left is the left, but sometimes the left is the right? And if use the
Rhino.RhinoDoc.ModelAbsoluteTolerance, then left is the bottom or the top.
Is there a better technique for getting the left and right vertical edges that can be used? Or is this method supposed to be used in a different way perhaps?
any help is appreciated as always! Example file attached for reference.
left_right_edges_test.gh (24.3 KB)
In case anyone finds this thread and has a similar issue, I was able to use an alternative method to get the aperture edges consistently. This method seems to work even with horizontal skylights, and other non-perpendicular apertures as well.
from Rhino.RhinoDoc import ModelAbsoluteTolerance
import ghpythonlib.components as ghc
from ladybug_geometry.geometry3d import LineSegment3D, Plane
from ladybug_rhino.fromgeometry import from_face3d, from_linesegment3d, from_point3d, from_plane
from honeybee.aperture import Aperture
TOLERANCE = ModelAbsoluteTolerance
def calc_edge_angle_about_origin(_edge, _center_pt, _pl, _tol=0.0001):
# type: (LineSegment3D, Point3d, Plane, float) -> float
"""Calculate the angle of an edge's midpoint about the origin-point of its parent plane."""
# -- Get the edge's mid-point
rh_edge = from_linesegment3d(_edge)
edge_midpoint = ghc.CurveMiddle(rh_edge)
# -- Find the angle from the aperture's center-point, to the edges' midpoint
# -- Use the local y-axis so that if the aperture is moved or
# -- rotated or slanted (skylights) it will still work as expected
_, _, local_y_axis, _ = ghc.DeconstructPlane(_pl)
v = ghc.Vector2Pt(_center_pt, edge_midpoint, False).vector
angle = math.degrees(ghc.Angle(local_y_axis, v, _pl).angle)
angle = round(angle, 2)
# -- Ensure that floating-point errors (359.999999999998) won't mess up the order
if abs(angle - 360.0) <= _tol:
angle = 0.0
def get_ap_edges(_aperture, _tol=0.0001):
# type: (Aperture, float) -> List[LineSegment3D]
"""Sort the edges of the aperture based on their angle about the aperture's center point."""
aperture_face = from_face3d(_aperture.geometry)
aperture_local_plane = from_plane(_aperture.geometry.plane)
apeture_center_point = ghc.Area(aperture_face).centroid
# -- Get the edges in clockwise order (top, right, bottom, left)
edges_sorted = sorted(
key=lambda e: calc_edge_angle_about_origin(
e, apeture_center_point, aperture_local_plane, _tol
left_edges_, right_edges_ = , 
for aperture in _aps:
top, right, bottom, left= get_ap_edges(aperture, _tol=TOLERANCE)
left_right_edges_test.gh (30.0 KB)