Source code for honeybee_ph_utils.polygon2d_tools

# -*- coding: utf-8 -*-
# -*- Python Version: 2.7 -*-

"""Tools for working with Ladybug.geometry2d.Polygon2D objects."""

import math
from copy import copy

try:
    from typing import List
except ImportError:
    pass  # Python 2.7

try:
    from ladybug_geometry.geometry2d.pointvector import Point2D, Vector2D
    from ladybug_geometry.geometry2d.polygon import Polygon2D
    from ladybug_geometry.geometry3d.face import Face3D
    from ladybug_geometry.geometry3d.plane import Plane
except ImportError as e:
    raise ImportError("Failed to import ladybug_geometry: " + str(e))

try:
    from honeybee_ph_utils import vector3d_tools
except ImportError as e:
    raise ImportError("Failed to import honeybee_ph_utils: " + str(e))


[docs] def counterclockwise_angle_between_2_Planes(_plane1, _plane2, _tolerance): # type: (Plane, Plane, float) -> float """Return the counterclockwise angle (in radians) between two Plane's X-Axes.""" if not vector3d_tools.vector_equal(_plane1.n, _plane2.n, _tolerance): msg = ( "Error: Cannot calculate the angle between planes with different normal vectors ." "Normal vector: {} is not equal to: {}".format(_plane1.n, _plane2.n) ) raise Exception(msg) angle_in_radians = vector3d_tools.angle_between_2D_vectors(_plane1.x, _plane2.x) # Convert radians to degrees angle_degrees = math.degrees(angle_in_radians) # Determine the sign of the angle using the cross product cross_prod = vector3d_tools.cross_product(_plane1.x, _plane2.x) if vector3d_tools.dot_product(cross_prod, _plane1.n) < 0: angle_degrees = 360 - angle_degrees return math.radians(angle_degrees)
[docs] def move_vector_between_two_points(_point1, _point2): # type: (Point2D, Point2D) -> Vector2D """Return a Vector2D from _point1 to _point2.""" mv_x = _point1.x - _point2.x mv_y = _point1.y - _point2.y move_vec = Vector2D(mv_x, mv_y) # type: ignore return move_vec
[docs] def translate_polygon2D(_polygon2D, _starting_plane, _target_plane, _tolerance): # type: (Polygon2D, Plane, Plane, float) -> Polygon2D """Translate (move, rotate) one Polygon2D from its own Plane into another.""" # ------------------------------------------------------------------------ # -- Create a Vector2D from the Polygon2D's origin to the _new_plane's # -- origin within the new-plane's space. target_plane_origin_pt = copy(_target_plane.xyz_to_xy(_target_plane.o)) polygon2D_origin_pt_in_target_plane_space = copy(_target_plane.xyz_to_xy(_starting_plane.o)) # ------------------------------------------------------------------------ # -- Move the starting Polygon2D into the _new_plane's space move_vec = move_vector_between_two_points(polygon2D_origin_pt_in_target_plane_space, target_plane_origin_pt) moved_polygon2D = _polygon2D.move(move_vec) # ------------------------------------------------------------------------ # -- Rotate the moved Polygon2D to align with the _new_plane's space angle_in_radians = counterclockwise_angle_between_2_Planes( _target_plane, _starting_plane, _tolerance, ) rotated_polygon = moved_polygon2D.rotate(angle=angle_in_radians, origin=polygon2D_origin_pt_in_target_plane_space) return rotated_polygon
[docs] def get_lbt_Face3D_polygon2Ds(_lbt_face3Ds): # type: (List[Face3D]) -> List[Polygon2D] """Return the LBT-Face3D Polygon2Ds.""" return [copy(f.polygon2d) for f in _lbt_face3Ds]
[docs] def get_lbt_Face3D_planes(_lbt_face3Ds): # type: (List[Face3D]) -> List[Plane] """Return the LBT-Face3D Planes.""" return [copy(f.plane) for f in _lbt_face3Ds]
[docs] def merge_polygon_2ds(_lbt_polygon_2ds, _tolerance): # type: (List[Polygon2D], float) -> List[Polygon2D] """Merge together a list of Polygon2Ds.""" try: merged_polygon2Ds = Polygon2D.boolean_union_all(_lbt_polygon_2ds, _tolerance) except Exception: merged_polygon2Ds = _lbt_polygon_2ds return merged_polygon2Ds
[docs] def merge_lbt_face_polygons(_lbt_face3Ds, _tolerance): # type: (List[Face3D], float) -> List[Polygon2D] """Merge together the Polygon2Ds of a list of LBT-Face3Ds.""" lbt_face3D_polygon2Ds = get_lbt_Face3D_polygon2Ds(_lbt_face3Ds) lbt_face3D_planes = get_lbt_Face3D_planes(_lbt_face3Ds) reference_plane = _lbt_face3Ds[0].plane try: # --------------------------------------------------------------------- # -- Get all the LBT-Face3D Polygon2Ds in the same Plane-space translated_polygon2Ds = [] # type: List[Polygon2D] for face3D_poly_2D, face3D_plane in zip(lbt_face3D_polygon2Ds, lbt_face3D_planes): translated_polygon2Ds.append(translate_polygon2D(face3D_poly_2D, face3D_plane, reference_plane, _tolerance)) # --------------------------------------------------------------------- # -- Try and merge all the new Polygon2Ds together into a single one. merged_polygon2Ds = Polygon2D.boolean_union_all(translated_polygon2Ds, _tolerance) except Exception: merged_polygon2Ds = list(lbt_face3D_polygon2Ds) return merged_polygon2Ds