Skip to content

Commit

Permalink
fix(vis-aperture): Add new GH Visualize Aperture Frames component
Browse files Browse the repository at this point in the history
  • Loading branch information
ed-p-may committed May 25, 2023
1 parent 94c23ee commit 597d4ee
Show file tree
Hide file tree
Showing 7 changed files with 210 additions and 5 deletions.
65 changes: 65 additions & 0 deletions honeybee_grasshopper_ph/src/HBPH - Visualize Aperture Frames.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#
# Honeybee-PH: A Plugin for adding Passive-House data to LadybugTools Honeybee-Energy Models
#
# This component is part of the PH-Tools toolkit <https://github.com/PH-Tools>.
#
# Copyright (c) 2022, PH-Tools and bldgtyp, llc <[email protected]>
# Honeybee-PH is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published
# by the Free Software Foundation; either version 3 of the License,
# or (at your option) any later version.
#
# Honeybee-PH is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# For a copy of the GNU General Public License
# see <https://github.com/PH-Tools/honeybee_ph/blob/main/LICENSE>.
#
# @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
#
"""
Pull out all the frame and glazing surfaces from a given list of HB-Apertures. This
will create Rhino geometry for each of the elements which can be visualized in the
scene and used to check the model construction.
-
EM May 24, 2023
Args:
_aperture: (List[Aperture]) The list of HB-Aperatures to get the frame and
glass geometry for.
Returns:
frame_surfaces_: The resulting frame element surfaces.
glazing_surfaces_: The resulting glazing surfaces.
"""

import scriptcontext as sc
import Rhino as rh
import rhinoscriptsyntax as rs
import ghpythonlib.components as ghc
import Grasshopper as gh

from honeybee_ph_rhino import gh_compo_io, gh_io

# ------------------------------------------------------------------------------
import honeybee_ph_rhino._component_info_
reload(honeybee_ph_rhino._component_info_)
ghenv.Component.Name = "HBPH - Visualize Aperture Frames"
DEV = honeybee_ph_rhino._component_info_.set_component_params(ghenv, dev=False)
if DEV:
from honeybee_ph_rhino.gh_compo_io import visualize_win_frames as gh_compo_io
reload(gh_compo_io)

# ------------------------------------------------------------------------------
# -- GH Interface
IGH = gh_io.IGH( ghdoc, ghenv, sc, rh, rs, ghc, gh )


# ------------------------------------------------------------------------------
gh_compo_interface = gh_compo_io.GHCompo_VisualizeWindowFrameElements(
IGH,
_apertures,
)
frame_surfaces_, glazing_surfaces_ = gh_compo_interface.run()
Binary file not shown.
12 changes: 9 additions & 3 deletions honeybee_ph_rhino/_component_info_.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
These are called when the component is instantiated within the Grasshopper canvas.
"""

RELEASE_VERSION = "Honeybee-PH v1.0.46"
RELEASE_VERSION = "Honeybee-PH v1.0.47"
CATEGORY = "HB-PH"
SUB_CATEGORIES = {
0: "00 | Utils",
Expand Down Expand Up @@ -316,14 +316,14 @@
"Message": RELEASE_VERSION,
"Category": CATEGORY,
"SubCategory": 1,
},
},
"HBPH - Set Monthly Shade Factor": {
"NickName": "Set Shade Factor",
"Message": RELEASE_VERSION,
"Category": CATEGORY,
"SubCategory": 1,
},
# -- Envelope
# -- Envelope
"HBPH - Create SD Constructions": {
"NickName": "Create SD Const.",
"Message": RELEASE_VERSION,
Expand Down Expand Up @@ -516,6 +516,12 @@
"Category": CATEGORY,
"SubCategory": 1,
},
"HBPH - Visualize Window Frames": {
"NickName": "Visualize Window Frames",
"Message": RELEASE_VERSION,
"Category": CATEGORY,
"SubCategory": 1,
},
# -- Organize
"HBPH - Organize Spaces": {
"NickName": "Organize HBPH Spaces",
Expand Down
3 changes: 3 additions & 0 deletions honeybee_ph_rhino/gh_compo_io/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@

# -- Visualize
from honeybee_ph_rhino.gh_compo_io.visualize_spaces import GHCompo_VisualizeSpaces
from honeybee_ph_rhino.gh_compo_io.visualize_win_frames import (
GHCompo_VisualizeWindowFrameElements,
)

# -- Organize
from honeybee_ph_rhino.gh_compo_io.organize_spaces import GHCompo_OrganizeSpaces
119 changes: 119 additions & 0 deletions honeybee_ph_rhino/gh_compo_io/visualize_win_frames.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# -*- coding: utf-8 -*-
# -*- Python Version: 2.7 -*-

"""GHCompo Interface: HBPH - Visualize Window Frames."""

try:
from typing import List, Iterable
except ImportError:
pass

try:
from itertools import izip # type: ignore
except ImportError:
izip = zip # Python 3

try:
from System import Object # type: ignore
from Grasshopper import DataTree # type: ignore
from Grasshopper.Kernel.Data import GH_Path # type: ignore
from Rhino.Geometry import Brep, Point3d # type: ignore
except ImportError:
pass # Outside Rhino

try:
from ladybug_geometry.geometry3d import LineSegment3D
except ImportError as e:
raise ImportError("\nFailed to import ladybug_geometry:\n\t{}".format(e))

try:
from ladybug_rhino.fromgeometry import from_face3d, from_linesegment3d, from_point3d
except ImportError as e:
raise ImportError("\nFailed to import ladybug_rhino:\n\t{}".format(e))

try:
from honeybee.aperture import Aperture
except ImportError as e:
raise ImportError("\nFailed to import honeybee:\n\t{}".format(e))

try:
from honeybee_ph_rhino import gh_io
except ImportError as e:
raise ImportError("\nFailed to import honeybee_ph_rhino:\n\t{}".format(e))


class GHCompo_VisualizeWindowFrameElements(object):
def __init__(self, _IGH, _apertures):
# type: (gh_io.IGH, List[Aperture]) -> None
self.IGH = _IGH
self.apertures = _apertures
self.tolerance = _IGH.sc.doc.ModelAbsoluteTolerance

def get_ap_edges(self, ap):
# type: (Aperture) -> tuple[LineSegment3D, LineSegment3D, LineSegment3D, LineSegment3D]
lr_edges = ap.geometry.get_left_right_vertical_edges(self.tolerance)
if not lr_edges:
raise Exception("Failed to get left and right edges of the aperture.")
ap_edge_l, ap_edge_r = lr_edges

bt_edges = ap.geometry.get_top_bottom_horizontal_edges(self.tolerance)
if not bt_edges:
raise Exception("Failed to get bottom and top edges of the aperture.")
ap_edge_b, ap_edge_t = bt_edges

return (ap_edge_t, ap_edge_r, ap_edge_b, ap_edge_l)

def create_frame_surface(self, _ap_edges, _ap_frame_elements, ap_ctr_pt):
# type: (Iterable, Iterable, Point3d) -> List[Brep]
frame_surfaces = []
for edge, frame in izip(_ap_edges, _ap_frame_elements):
edge_rh = from_linesegment3d(edge)
crv_mid_pt = from_point3d(edge.midpoint)
extrusion_vector = self.IGH.ghc.Vector2Pt(crv_mid_pt, ap_ctr_pt, True).vector
extrusion_vector = self.IGH.ghc.Amplitude(extrusion_vector, frame.width)
ext = self.IGH.ghc.Extrude(base=edge_rh, direction=extrusion_vector)
frame_surfaces.append(ext)

return frame_surfaces

def create_glazing_surface(self, _frame_surfaces, _ap_srfc, _ap_ctr_pt):
# type: (List[Brep], Brep, Point3d) -> Brep
joined_frames = self.IGH.ghc.BrepJoin(_frame_surfaces).breps
edges = self.IGH.ghc.DeconstructBrep(joined_frames).edges
win_srfcs = self.IGH.ghc.SurfaceSplit(_ap_srfc, edges)

# -- Figure out which of the split surfaces is the glazing surface
ct_pt_distances = []
for test_srfc in win_srfcs:
ct_pt_distances.append(
self.IGH.ghc.SurfaceClosestPoint(_ap_ctr_pt, test_srfc).distance
)
glazing_srfc = win_srfcs[ct_pt_distances.index(min(ct_pt_distances))]

return glazing_srfc

def run(self):
# type: () -> tuple[DataTree[Object], DataTree[Object]]
frame_surfaces_, glazing_surfaces_ = DataTree[Object](), DataTree[Object]()

for i, ap in enumerate(self.apertures):
# -- Pull out all the relevant Aperture data needed
ap_srfc_rh = from_face3d(ap.geometry)
ap_ctr_pt = self.IGH.ghc.Area(ap_srfc_rh).centroid
ap_edges = self.get_ap_edges(ap)
ap_const = ap.properties.energy.construction
ap_frame_elements = ap_const.properties.ph.ph_frame.elements

# --
frame_surfaces = self.create_frame_surface(
ap_edges, ap_frame_elements, ap_ctr_pt
)
frame_surfaces_.AddRange(frame_surfaces, GH_Path(i))

# --
glazing_surfaces_.Add(
self.create_glazing_surface(frame_surfaces, ap_srfc_rh, ap_ctr_pt),
GH_Path(i),
)

return frame_surfaces_, glazing_surfaces_
3 changes: 3 additions & 0 deletions honeybee_ph_rhino/gh_compo_io/win_create_geom.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ def __init__(self, _IGH, _win_baselines, _win_names, _win_collection):
self.win_names = _win_names

def check_input(self):
if not self.win_baselines or not self.win_names:
return

if len(self.win_baselines) != len(self.win_names):
msg = "The number of window-baselines and window-names must be the same."
raise Exception(msg)
Expand Down
13 changes: 11 additions & 2 deletions honeybee_ph_rhino/gh_compo_io/win_create_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ def y_vector(self):
def build_origin_plane(self, _base_curve):
# type: (LineCurve) -> Plane
start_pt, end_pt = self.IGH.ghc.EndPoints(_base_curve)
return self.IGH.ghc.ConstructPlane(start_pt, self.x_vector, self.y_vector)
pl = self.IGH.ghc.ConstructPlane(start_pt, self.x_vector, self.y_vector)
return pl

def build_srfc_base_crv(self, _width, _origin_plane):
# type: (float, Plane) -> LineCurve
Expand All @@ -126,7 +127,15 @@ def build(self, _base_curve):

# -- Walk through each column, and each row in each column
for col_element_lists in self.elements_by_column(self.elements):
# 2) Build the base-curve for the Column;s elements
if not origin_plane:
msg = (
"Error: Something went wrong building the origin planes for "
"the window geometry? Note this window builder ONLY works for vertical "
"planar windows. Skylights or windows on sloped surfaces are not supported"
)
raise Exception(msg)

# 2) Build the base-curve for the Column's elements
width = col_element_lists[0].width
base_curve = self.build_srfc_base_crv(width, origin_plane)

Expand Down

0 comments on commit 597d4ee

Please sign in to comment.