Source code for honeybee_plus.hbsurface

from ._hbanalysissurface import HBAnalysisSurface
from .hbfensurface import HBFenSurface
from .surfaceproperties import SurfaceProperties, SurfaceState
from .vectormath.euclid import Vector3, Point3
import honeybee_plus.utilcol as util
import honeybee_plus
try:
    import plus
except ImportError as e:
    if honeybee_plus.isplus:
        raise ImportError(e)
import sys
if (sys.version_info >= (3, 0)):
    xrange = range
    basestring = str


[docs]class HBSurface(HBAnalysisSurface): """Base class for Honeybee surface. Attributes: name: A unique string for surface name sorted_points: A list of 3 points or more as tuple or list with three items (x, y, z). Points should be sorted. This class won't sort the points. If surfaces has multiple subsurfaces you can pass lists of point lists to this function (e.g. ((0, 0, 0), (10, 0, 0), (0, 10, 0))). surface_type: Optional input for surface type. You can use any of the surface types available from surfacetype libraries or use a float number to indicate the type. If not indicated it will be assigned based on normal angle of the surface which will be calculated from surface points. 0.0: Wall 0.5: UndergroundWall 1.0: Roof 1.5: UndergroundCeiling 2.0: Floor 2.25: UndergroundSlab 2.5: SlabOnGrade 2.75: ExposedFloor 3.0: Ceiling 4.0: AirWall 6.0: Context is_name_set_by_user: If you want the name to be changed by honeybee any case set is_name_set_by_user to True. Default is set to False which let Honeybee to rename the surface in cases like creating a newHBZone. rad_properties: Radiance properties for this surface. If empty default RADProperties will be assigned to surface by Honeybee. ep_properties: EnergyPlus properties for this surface. If empty default ep_properties will be assigned to surface by Honeybee. Usage: pts = ((0, 0, 0), (10, 0, 0), (0, 0, 10)) hbsrf = HBSurface("001", pts, surface_type=None, is_name_set_by_user=True, is_type_set_by_user=True) print(hbsrf.to_rad_string(include_materials=True)) > void plastic generic_wall > 0 > 0 > 5 0.500 0.500 0.500 0.000 0.000 > generic_wall polygon 001 > 0 > 0 > 9 > 0 0 0 > 10 0 0 > 0 10 10 """ def __init__(self, name, sorted_points=[], surface_type=None, is_name_set_by_user=False, is_type_set_by_user=False, rad_properties=None, ep_properties=None, states=None): """Init honeybee surface.""" states = states or () HBAnalysisSurface.__init__(self, name, sorted_points, surface_type, is_name_set_by_user, is_type_set_by_user) sp = SurfaceProperties(self.surface_type, rad_properties, ep_properties) self._states[0] = SurfaceState('default', sp) for state in states: self.add_surface_state(state) self._parent = None self._child_surfaces = [] self._is_created_from_geo = False # TODO: Parse EnergyPlus properties
[docs] @classmethod def from_ep_string(cls, ep_string): """Init Honeybee surface from an ep_string. Args: ep_string: The full ep_string for an EnergyPlus surface. """ types = {'Wall': 0, 'Roof': 1, 'Floor': 2, 'Ceiling': 3} # clean input ep_string - split based on comma segments = ep_string.replace("\t", "") \ .replace(" ", "").replace(";", "").split(",") name = segments[1] srf_type = types[segments[2].capitalize()] pts = range((len(segments) - 11) / 3) # create points for count, i in enumerate(xrange(11, len(segments), 3)): try: pts[count] = [float(c) for c in segments[i: i + 3]] except ValueError: raise ValueError( "%s is an invalid value for points." % segments[i: i + 3] ) # create the surfaceString return cls(name, pts, srf_type, is_name_set_by_user=True, is_type_set_by_user=True)
[docs] @classmethod def from_geometry(cls, name, geometry, surface_type=None, is_name_set_by_user=False, is_type_set_by_user=False, rad_properties=None, ep_properties=None, states=None, group=False): """Create honeybee surface[s] from a Grasshopper geometry. If group is False it will return a list of HBSurfaces. """ assert honeybee_plus.isplus, \ '"fromGeometries" method can only be used in [+] libraries.' name = name or util.random_name() if isinstance(name, basestring): names = (name,) elif not hasattr(name, '__iter__'): names = (name,) else: names = name namescount = len(names) - 1 srf_data = plus.extract_geometry_points(geometry) cls._is_created_from_geo = True if not group: if ep_properties: print('ep_properties.duplicate must be implemented to honeybee surface.') hbsrfs = [] # create a separate surface for each geometry. for gcount, srf in enumerate(srf_data): for scount, (geo, pts) in enumerate(srf): try: _name = '%s_%d_%d' % (names[gcount], gcount, scount) except IndexError: _name = '%s_%d_%d' % (names[-1], gcount, scount) if rad_properties: _srf = cls(_name, pts, surface_type, is_name_set_by_user, is_type_set_by_user, rad_properties.duplicate(), ep_properties, states) else: _srf = cls(_name, pts, surface_type, is_name_set_by_user, is_type_set_by_user, rad_properties, ep_properties, states) _srf.geometry = geo hbsrfs.append(_srf) # check naming and fix it if it's only single geometry if (gcount == 0 or gcount <= namescount) and scount == 0: # this is just a single geometry. remove counter for hbsrf in hbsrfs: hbsrf.name = '_'.join(hbsrf.name.split('_')[:-2]) elif gcount == 0 or gcount == namescount: # this is a single geometry with multiple sub surfaces like a polysurface for hbs in hbsrfs: bname = hbs.name.split('_') hbs.name = '%s_%s' % ('_'.join(bname[:-2]), bname[-1]) return hbsrfs else: _geos = [] _pts = [] # collect all the points in a single list for srf in srf_data: for geo, pts in srf: _pts.extend(pts) _geos.append(geo) _srf = cls(names[0], _pts, surface_type, is_name_set_by_user, is_type_set_by_user, rad_properties, ep_properties, states) _srf.geometry = _geos return _srf
@property def is_created_from_geometry(self): """Return True if the surface is created from a geometry not points.""" return self._isCeatedFromGeo @property def isHBSurface(self): """Return True for HBSurface.""" return True @property def is_child_surface(self): """Return False for HBSurface.""" return False @property def has_child_surfaces(self): """Return True if Honeybee surface has Fenestration surrfaces.""" return len(self._child_surfaces) != 0 @property def parent(self): """Get or set parent zone.""" return self._parent @property def children_surfaces(self): """Get children surfaces.""" return self._child_surfaces @property def geometry(self): """Return geometry.""" assert honeybee_plus.isplus, \ '"geometry" property can only be used in [+] libraries.' if self.is_created_from_geometry: return self._geometry else: return self.profile @geometry.setter def geometry(self, geo): """Set geometry.""" assert honeybee_plus.isplus, \ '"geometry" property can only be used in [+] libraries.' self._geometry = geo @property def profile(self): """Get profile curve of this surface.""" assert honeybee_plus.isplus, \ '"profile" property can only be used in [+] libraries.' return plus.polygon( tuple(plus.xyz_to_geometrical_points(self.absolute_points)) )
[docs] def add_fenestration_surface_by_size(self, name, width, height, sill_height=1, radiance_material=None): """Add rectangular fenestration surface to surface. Args: width: Opening width. Opening will be centered in HBSurface. height: Opening height. sill_height: Sill height (default: 1). radiance_material: Optional radiance material for this fenestration. """ for pts in self.points: assert len(pts) == 4, 'Length of points should be 4.' pt0 = Point3(*pts[0]) pt1 = Point3(*pts[1]) pt3 = Point3(*pts[-1]) x_axis = Vector3(*(pt1 - pt0)).normalized() y_axis = Vector3(*(pt3 - pt0)).normalized() srf_width = pt0.distance(pt1) srf_height = pt0.distance(pt3) assert srf_width > width, \ 'Opening width [{}] should be smaller than ' \ 'HBSurface width [{}].'.format(srf_width, width) assert srf_height > height + sill_height, \ 'Opening height plus sill height [{}] should be smaller than ' \ 'HBSurface height [{}].'.format(srf_height + sill_height, height) # create fenestration surface x_gap = (srf_width - width) / 2.0 glz_pt0 = pt0 + (x_gap * x_axis) + (sill_height * y_axis) glz_pt1 = pt0 + ((x_gap + width) * x_axis) + (sill_height * y_axis) glz_pt2 = pt0 + ((x_gap + width) * x_axis) + \ ((sill_height + height) * y_axis) glz_pt3 = pt0 + (x_gap * x_axis) + ((sill_height + height) * y_axis) glzsrf = HBFenSurface(name, [glz_pt0, glz_pt1, glz_pt2, glz_pt3]) if radiance_material: glzsrf.radiance_material = radiance_material self.add_fenestration_surface(glzsrf)
[docs] def add_fenestration_surface(self, fenestration_surface): """Add a fenestration surface to HB surface.""" assert hasattr(fenestration_surface, 'isHBFenSurface'), \ '{} is not a HBFenSurfaces'.format(type(fenestration_surface)) self._child_surfaces.append(fenestration_surface) # set up parent object if it's not set fenestration_surface._parent = self