Trouble getting left and right aperture edges?

Hi all,

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.

best,
@edpmay

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.

import math
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

    return angle

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(
        _aperture.geometry.boundary_segments,
        reverse=True,
        key=lambda e: calc_edge_angle_about_origin(
            e, apeture_center_point, aperture_local_plane, _tol
        ),
    )

    return edges_sorted

# -----
left_edges_, right_edges_ = [], []
for aperture in _aps:
    top, right, bottom, left= get_ap_edges(aperture, _tol=TOLERANCE)
    left_edges_.append(from_linesegment3d(left))
    right_edges_.append(from_linesegment3d(right))

best
@edpmay

left_right_edges_test.gh (30.0 KB)

3 Likes