Skip to content

Commit

Permalink
feat(create): Add component to offset (and optionally repair) Apertures
Browse files Browse the repository at this point in the history
  • Loading branch information
chriswmackey authored and Chris Mackey committed Apr 12, 2024
1 parent ed5b4fc commit 9855252
Show file tree
Hide file tree
Showing 10 changed files with 158 additions and 8 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions honeybee_grasshopper_core/json/HB_Label_Faces.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "1.8.0",
"version": "1.8.1",
"nickname": "LableFaces",
"outputs": [
[
Expand Down Expand Up @@ -71,7 +71,7 @@
}
],
"subcategory": "1 :: Visualize",
"code": "\nimport math\n\ntry: # import the ladybug_geometry dependencies\n from ladybug_geometry.geometry3d.plane import Plane\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_geometry:\\n\\t{}'.format(e))\n\ntry: # import the core honeybee dependencies\n from honeybee.model import Model\n from honeybee.room import Room\n from honeybee.face import Face\n from honeybee.aperture import Aperture\n from honeybee.door import Door\n from honeybee.search import get_attr_nested\n from honeybee.units import parse_distance_string\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee:\\n\\t{}'.format(e))\n\ntry: # import the ladybug_{{cad}} dependencies\n from ladybug_{{cad}}.fromgeometry import from_face3d_to_wireframe, from_plane\n from ladybug_{{cad}}.text import text_objects\n from ladybug_{{cad}}.config import tolerance, conversion_to_meters, units_system\n from ladybug_{{cad}}.{{plugin}} import all_required_inputs\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_{{cad}}:\\n\\t{}'.format(e))\n\n\n# hide the base_pts output from the scene\nghenv.Component.Params.Output[1].Hidden = True\n# maximum text height in meters - converted to model units\nmax_txt_h = 0.25 / conversion_to_meters()\n# tolerance for computing the pole of inaccessibility\nunits = units_system()\np_tol = parse_distance_string('0.01m', units)\n# dictionary of unit-sensitive propperties to be handled specially\nUNIT_SENSITIVE = {\n 'properties.energy.r_factor': 'R Factor',\n 'properties.energy.u_factor': 'U Factor',\n 'properties.energy.shgc': 'SHGC'\n}\n\n\ndef label_face(face, _attribute_, _font_, label_text, base_pts, labels, wire_frame):\n \"\"\"Generate labels for a face or sub-face and add it to a list.\"\"\"\n if _attribute_ in UNIT_SENSITIVE:\n obj_method = get_attr_nested(face, _attribute_, cast_to_str=False)\n face_prop = str(obj_method(units))\n else:\n face_prop = get_attr_nested(face, _attribute_)\n\n # get a base plane and text height for the text label\n f_geo = face.geometry\n cent_pt = f_geo.center if f_geo.is_convex else f_geo.pole_of_inaccessibility(p_tol)\n base_plane = Plane(f_geo.normal, cent_pt)\n if base_plane.y.z < 0: # base plane pointing downwards; rotate it\n base_plane = base_plane.rotate(base_plane.n, math.pi, base_plane.o)\n if _txt_height_ is None: # auto-calculate default text height\n txt_len = len(face_prop) if len(face_prop) > 10 else 10\n dims = [\n (f_geo.max.x - f_geo.min.x),\n (f_geo.max.y - f_geo.min.y),\n (f_geo.max.z - f_geo.min.z)]\n dims.sort()\n txt_h = dims[1] / txt_len\n else:\n txt_h = _txt_height_\n if txt_h < tolerance:\n return\n txt_h = max_txt_h if txt_h > max_txt_h else txt_h\n if base_plane.y.z < 0: # base plane pointing downwards; rotate it\n base_plane = base_plane.rotate(base_plane.n, math.pi, base_plane.o)\n\n # move base plane origin a little to avoid overlaps of adjacent labels\n if base_plane.n.x != 0:\n m_vec = base_plane.y if base_plane.n.x < 0 else -base_plane.y\n else:\n m_vec = base_plane.y if base_plane.n.z < 0 else -base_plane.y\n base_plane = base_plane.move(m_vec * txt_h)\n\n # create the text label\n label = text_objects(face_prop, base_plane, txt_h, font=_font_,\n horizontal_alignment=1, vertical_alignment=3)\n\n # append everything to the lists\n label_text.append(face_prop)\n base_pts.append(from_plane(base_plane))\n labels.append(label)\n wire_frame.extend(from_face3d_to_wireframe(face.geometry))\n\n\nif all_required_inputs(ghenv.Component):\n # lists of {{cad}} geometry to be filled with content\n label_text = []\n base_pts = []\n labels = []\n wire_frame = []\n \n # set the default attribute and font\n if _attribute_ is None:\n _attribute_ = 'display_name'\n if _font_ is None:\n _font_ = 'Arial'\n \n # generate the labels\n if not sub_faces_:\n for obj in _hb_objs:\n if isinstance(obj, Room):\n for face in obj.faces:\n label_face(face, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n elif isinstance(obj, Face):\n label_face(obj, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n elif isinstance(obj, Model):\n for room in obj.rooms:\n for face in room.faces:\n label_face(face, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n for face in obj.orphaned_faces:\n label_face(face, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n else:\n for obj in _hb_objs:\n if isinstance(obj, Room):\n for face in obj.faces:\n for ap in face.apertures:\n label_face(ap, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n for dr in face.doors:\n label_face(dr, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n elif isinstance(obj, Face):\n for ap in obj.apertures:\n label_face(ap, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n for dr in obj.doors:\n label_face(dr, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n elif isinstance(obj, (Aperture, Door)):\n label_face(obj, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n elif isinstance(obj, Model):\n for room in obj.rooms:\n for face in room.faces:\n for ap in face.apertures:\n label_face(ap, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n for dr in face.doors:\n label_face(dr, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n for face in obj.orphaned_faces:\n for ap in face.apertures:\n label_face(ap, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n for dr in face.doors:\n label_face(dr, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n for ap in obj.orphaned_apertures:\n label_face(ap, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n for dr in obj.orphaned_doors:\n label_face(dr, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)",
"code": "\nimport math\n\ntry: # import the ladybug_geometry dependencies\n from ladybug_geometry.geometry3d.plane import Plane\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_geometry:\\n\\t{}'.format(e))\n\ntry: # import the core honeybee dependencies\n from honeybee.model import Model\n from honeybee.room import Room\n from honeybee.face import Face\n from honeybee.aperture import Aperture\n from honeybee.door import Door\n from honeybee.search import get_attr_nested\n from honeybee.units import parse_distance_string\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee:\\n\\t{}'.format(e))\n\ntry: # import the ladybug_{{cad}} dependencies\n from ladybug_{{cad}}.fromgeometry import from_face3d_to_wireframe, from_plane\n from ladybug_{{cad}}.text import text_objects\n from ladybug_{{cad}}.config import tolerance, conversion_to_meters, units_system\n from ladybug_{{cad}}.{{plugin}} import all_required_inputs\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_{{cad}}:\\n\\t{}'.format(e))\n\n\n# hide the base_pts output from the scene\nghenv.Component.Params.Output[1].Hidden = True\n# maximum text height in meters - converted to model units\nmax_txt_h = 0.25 / conversion_to_meters()\n# tolerance for computing the pole of inaccessibility\nunits = units_system()\np_tol = parse_distance_string('0.01m', units)\n# dictionary of unit-sensitive propperties to be handled specially\nUNIT_SENSITIVE = {\n 'properties.energy.r_factor': 'R Factor',\n 'properties.energy.u_factor': 'U Factor',\n 'properties.energy.shgc': 'SHGC'\n}\n\n\ndef label_face(face, _attribute_, _font_, label_text, base_pts, labels, wire_frame):\n \"\"\"Generate labels for a face or sub-face and add it to a list.\"\"\"\n if _attribute_ in UNIT_SENSITIVE:\n obj_method = get_attr_nested(face, _attribute_, cast_to_str=False)\n face_prop = str(obj_method(units))\n else:\n face_prop = str(get_attr_nested(face, _attribute_, 5))\n\n # get a base plane and text height for the text label\n f_geo = face.geometry\n cent_pt = f_geo.center if f_geo.is_convex else f_geo.pole_of_inaccessibility(p_tol)\n base_plane = Plane(f_geo.normal, cent_pt)\n if base_plane.y.z < 0: # base plane pointing downwards; rotate it\n base_plane = base_plane.rotate(base_plane.n, math.pi, base_plane.o)\n if _txt_height_ is None: # auto-calculate default text height\n txt_len = len(face_prop) if len(face_prop) > 10 else 10\n dims = [\n (f_geo.max.x - f_geo.min.x),\n (f_geo.max.y - f_geo.min.y),\n (f_geo.max.z - f_geo.min.z)]\n dims.sort()\n txt_h = dims[1] / txt_len\n else:\n txt_h = _txt_height_\n if txt_h < tolerance:\n return\n txt_h = max_txt_h if txt_h > max_txt_h else txt_h\n if base_plane.y.z < 0: # base plane pointing downwards; rotate it\n base_plane = base_plane.rotate(base_plane.n, math.pi, base_plane.o)\n\n # move base plane origin a little to avoid overlaps of adjacent labels\n if base_plane.n.x != 0:\n m_vec = base_plane.y if base_plane.n.x < 0 else -base_plane.y\n else:\n m_vec = base_plane.y if base_plane.n.z < 0 else -base_plane.y\n base_plane = base_plane.move(m_vec * txt_h)\n\n # create the text label\n label = text_objects(face_prop, base_plane, txt_h, font=_font_,\n horizontal_alignment=1, vertical_alignment=3)\n\n # append everything to the lists\n label_text.append(face_prop)\n base_pts.append(from_plane(base_plane))\n labels.append(label)\n wire_frame.extend(from_face3d_to_wireframe(face.geometry))\n\n\nif all_required_inputs(ghenv.Component):\n # lists of {{cad}} geometry to be filled with content\n label_text = []\n base_pts = []\n labels = []\n wire_frame = []\n \n # set the default attribute and font\n if _attribute_ is None:\n _attribute_ = 'display_name'\n if _font_ is None:\n _font_ = 'Arial'\n \n # generate the labels\n if not sub_faces_:\n for obj in _hb_objs:\n if isinstance(obj, Room):\n for face in obj.faces:\n label_face(face, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n elif isinstance(obj, Face):\n label_face(obj, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n elif isinstance(obj, Model):\n for room in obj.rooms:\n for face in room.faces:\n label_face(face, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n for face in obj.orphaned_faces:\n label_face(face, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n else:\n for obj in _hb_objs:\n if isinstance(obj, Room):\n for face in obj.faces:\n for ap in face.apertures:\n label_face(ap, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n for dr in face.doors:\n label_face(dr, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n elif isinstance(obj, Face):\n for ap in obj.apertures:\n label_face(ap, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n for dr in obj.doors:\n label_face(dr, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n elif isinstance(obj, (Aperture, Door)):\n label_face(obj, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n elif isinstance(obj, Model):\n for room in obj.rooms:\n for face in room.faces:\n for ap in face.apertures:\n label_face(ap, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n for dr in face.doors:\n label_face(dr, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n for face in obj.orphaned_faces:\n for ap in face.apertures:\n label_face(ap, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n for dr in face.doors:\n label_face(dr, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n for ap in obj.orphaned_apertures:\n label_face(ap, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)\n for dr in obj.orphaned_doors:\n label_face(dr, _attribute_, _font_, label_text, base_pts,\n labels, wire_frame)",
"category": "Honeybee",
"name": "HB Label Faces",
"description": "Lablel Honeybee faces and sub-faces with their attributes in the Rhino scene.\n_\nThis can be used as a means to check that correct properties are assigned to\ndifferent faces and sub-faces.\n-"
Expand Down
Loading

0 comments on commit 9855252

Please sign in to comment.