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