def add_door(door, points, vectors): """Add Door normals.""" points.append(from_point3d(door.center)) vectors.append(from_vector3d(door.normal)) for shd in door.shades: points.append(from_point3d(shd.center)) vectors.append(from_vector3d(shd.normal))
def add_aperture(aperture, points, vectors): """Add Aperture normals.""" points.append(from_point3d(aperture.center)) vectors.append(from_vector3d(aperture.normal)) for shd in aperture.shades: points.append(from_point3d(shd.center)) vectors.append(from_vector3d(shd.normal))
def add_face(face, points, vectors): """Add Face normals.""" points.append(from_point3d(face.center)) vectors.append(from_vector3d(face.normal)) for ap in face.apertures: add_aperture(ap, points, vectors) for dr in face.doors: add_door(ap, points, vectors) for shd in face.shades: points.append(from_point3d(shd.center)) vectors.append(from_vector3d(shd.normal))
def add_room(room, points, vectors): """Add Room normals.""" for face in room.faces: add_face(face, points, vectors) for shd in room.shades: points.append(from_point3d(shd.center)) vectors.append(from_vector3d(shd.normal))
def add_model(model, points, vectors): """Add Model normals.""" for room in model.rooms: add_room(room, points, vectors) for face in model.orphaned_faces: add_face(face, points, vectors) for ap in model.orphaned_apertures: add_aperture(ap, points, vectors) for dr in model.orphaned_doors: add_door(door, points, vectors) for shd in model.orphaned_shades: points.append(from_point3d(shd.center)) vectors.append(from_vector3d(shd.normal))
def build_window_meshes(_window_surface, _grid_size, _mesh_params): """Create the Ladybug Mesh3D grided mesh for the window being analysed Arguments: _window_surface: (Brep) A single window Brep from the scene _grid_size: (float) _mesh_params: (Rhino.Geometry.MeshingParameters) Returns: (tuple) points: (list: Ladybug Point3D) All the analysis points on the window normals: (list: Ladybug Normal) All the normals for the analysis points window_mesh: (ladybug_geometry.geometry3d.Mesh3D) The window window_back_mesh: (ladybug_geometry.geometry3d.Mesh3D) A copy of the window shifted 'back' just a little bit (0.1 units). Used when solving the 'unshaded' situation. """ # create the gridded mesh for the window surface #--------------------------------------------------------------------------- offset_dist = 0.001 window_mesh = to_joined_gridded_mesh3d([_window_surface], _grid_size, offset_dist) window_rh_mesh = from_mesh3d(window_mesh) points = [from_point3d(pt) for pt in window_mesh.face_centroids] # Create a 'back' for the window #--------------------------------------------------------------------------- # Mostly this is done so it can be passed to the ladybug_rhino.intersect.intersect_mesh_rays() # solver as a surfce which is certain to *not* shade the window at all window_back_mesh = None for sr in _window_surface.Surfaces: window_normal = sr.NormalAt(0.5, 0.5) window_normal.Unitize() window_normal = window_normal * -1 * 0.1 window_back = _window_surface.Duplicate() window_back.Translate(window_normal) window_back_mesh = Rhino.Geometry.Mesh.CreateFromBrep( window_back, _mesh_params)[0] normals = [from_vector3d(vec) for vec in window_mesh.face_normals] return points, normals, window_mesh, window_back_mesh, window_rh_mesh
def deconstruct_sky_matrix(_sky_mtx): """Copied from Ladybug 'IncidentRadiation' Component Arguments: _sky_mtx: A Ladybug Sky Matrix for the season Returns: (tuple) sky_vecs: (list: _ ) total_sky_rad: (list: _ ) """ mtx = de_objectify_output(_sky_mtx) total_sky_rad = [ dir_rad + dif_rad for dir_rad, dif_rad in izip(mtx[1], mtx[2]) ] lb_vecs = view_sphere.tregenza_dome_vectors if len(total_sky_rad) == 145 \ else view_sphere.reinhart_dome_vectors if mtx[0][0] != 0: # there is a north input for sky; rotate vectors north_angle = math.radians(mtx[0][0]) lb_vecs = [vec.rotate_xy(north_angle) for vec in lb_vecs] sky_vecs = [from_vector3d(vec) for vec in lb_vecs] return sky_vecs, total_sky_rad
_offset_dist_ = _offset_dist_ if _offset_dist_ is not None \ else 0.1 / conversion_to_meters() # create the gridded mesh from the geometry study_mesh = to_joined_gridded_mesh3d(_geometry, _grid_size) points = [ from_point3d(pt.move(vec * _offset_dist_)) for pt, vec in zip(study_mesh.face_centroids, study_mesh.face_normals) ] hide_output(ghenv.Component, 1) # mesh the geometry and context shade_mesh = join_geometry_to_mesh(_geometry + context_) # get the study points and reverse the sun vectors (for backward ray-tracting) rev_vec = [from_vector3d(to_vector3d(vec).reverse()) for vec in _vectors] normals = [from_vector3d(vec) for vec in study_mesh.face_normals] # intersect the rays with the mesh int_matrix, angles = intersect_mesh_rays(shade_mesh, points, rev_vec, normals, parallel=parallel_) # compute the results int_mtx = objectify_output('Sun Intersection Matrix', int_matrix) if _timestep_ and _timestep_ != 1: # divide by the timestep before output results = [sum(int_list) / _timestep_ for int_list in int_matrix] else: # no division required results = [sum(int_list) for int_list in int_matrix]
hide_output(ghenv.Component, 1) # mesh the geometry and context shade_mesh = join_geometry_to_mesh(_geometry + context_) # deconstruct the matrix and get the sky dome vectors mtx = de_objectify_output(_sky_mtx) total_sky_rad = [ dir_rad + dif_rad for dir_rad, dif_rad in zip(mtx[1], mtx[2]) ] lb_vecs = view_sphere.tregenza_dome_vectors if len(total_sky_rad) == 145 \ else view_sphere.reinhart_dome_vectors if mtx[0][0] != 0: # there is a north input for sky; rotate vectors north_angle = math.radians(mtx[0][0]) lb_vecs = [vec.rotate_xy(north_angle) for vec in lb_vecs] sky_vecs = [from_vector3d(vec) for vec in lb_vecs] # intersect the rays with the mesh normals = [from_vector3d(vec) for vec in study_mesh.face_normals] int_matrix_init, angles = intersect_mesh_rays(shade_mesh, points, sky_vecs, normals, parallel=parallel_) # compute the results results = [] int_matrix = [] for int_vals, angles in zip(int_matrix_init, angles): pt_rel = [ival * math.cos(ang) for ival, ang in zip(int_vals, angles)] int_matrix.append(pt_rel)
hoys_ = list(data_hoys.intersection(set(hoys_))) # initialize sunpath based on location sp = Sunpath.from_location(_location, north_, dl_saving_) # process all of the input hoys into altitudes, azimuths and vectors altitudes, azimuths, datetimes, moys, hoys, vectors, suns = [], [], [], [], [], [], [] for hoy in hoys_: sun = sp.calculate_sun_from_hoy(hoy, solar_time_) if sun.is_during_day: altitudes.append(sun.altitude) azimuths.append(sun.azimuth) datetimes.append(sun.datetime) moys.append(sun.datetime.moy) hoys.append(sun.datetime.hoy) vectors.append(from_vector3d(sun.sun_vector)) suns.append(sun) if len(data_) > 0 and len( hoys_) > 0: # build a sunpath for each data collection title, all_sun_pts, all_analemma, all_daily, all_compass, all_col_pts, all_legends = \ [], [], [], [], [], [], [] for i, data in enumerate(data_): try: # sense when several legend parameters are connected lpar = legend_par_[i] except IndexError: lpar = None if len(legend_par_) == 0 else legend_par_[-1] # move the center point so sun paths are not on top of one another fac = i * radius * 3 center_pt_i = Point2D(center_pt.x + fac, center_pt.y)
from ladybug_rhino.intersect import join_geometry_to_brep, bounding_box_extents, \ trace_ray, normal_at_point from ladybug_rhino.grasshopper import all_required_inputs, list_to_data_tree, \ hide_output except ImportError as e: raise ImportError('\nFailed to import ladybug_rhino:\n\t{}'.format(e)) if all_required_inputs(ghenv.Component): # check the _bounce_count_ _bounce_count_ = 0 if _bounce_count_ is None else _bounce_count_ - 1 assert _bounce_count_ >= 0, 'The input _bounce_count_ must be greater ' \ 'than zero. Got {}.'.format(_bounce_count_ + 1) # process the input sun vector lb_vec = to_vector3d(_vector).normalize() neg_lb_vec = -lb_vec vec = from_vector3d(lb_vec) # convert all of the _source_geo and contex into a single Brep for ray tracing rtrace_brep = join_geometry_to_brep(_source_geo + context_) # autocompute the first and last bounce length if it's unspecified if _first_length_ is None or _last_length_ is None: max_pt, min_pt = (to_point3d(p) for p in bounding_box_extents(rtrace_brep)) diag_dist = max_pt.distance_to_point(min_pt) _first_length_ = diag_dist if _first_length_ is None else _first_length_ _last_length_ = diag_dist if _last_length_ is None else _last_length_ # create the gridded mesh from the _source_geo and set up the starting rays study_mesh = to_joined_gridded_mesh3d(_source_geo, _grid_size) move_vec = neg_lb_vec * _first_length_
human_points.extend(hpts) human_line.append(hlin) if _run: # mesh the context for the intersection calculation shade_mesh = join_geometry_to_mesh(_context) # generate the sun vectors for each sun-up hour of the year sp = Sunpath.from_location(_location, north_) sun_vecs = [] day_pattern = [] for hoy in range(8760): sun = sp.calculate_sun_from_hoy(hoy) day_pattern.append(sun.is_during_day) if sun.is_during_day: sun_vecs.append(from_vector3d(sun.sun_vector_reversed)) # intersect the sun vectors with the context and compute fraction exposed sun_int_matrix, angles = intersect_mesh_rays(shade_mesh, human_points, sun_vecs, cpu_count=workers) fract_body_exp = [] for i in range(0, len(human_points), _pt_count_): fract_body_exp.append( fract_exposed_from_mtx(sun_int_matrix[i:i + _pt_count_], day_pattern)) # generate the vectors and weights for sky exposure sky_vecs = [ from_vector3d(vec) for vec in view_sphere.tregenza_dome_vectors
for dr in model.orphaned_doors: add_door(door, points, vectors) for shd in model.orphaned_shades: points.append(from_point3d(shd.center)) vectors.append(from_vector3d(shd.normal)) if all_required_inputs(ghenv.Component): # list of rhino geometry to be filled with content points = [] vectors = [] # loop through all objects and add them for hb_obj in _hb_objs: if isinstance(hb_obj, Room): add_room(hb_obj, points, vectors) elif isinstance(hb_obj, Face): add_face(hb_obj, points, vectors) elif isinstance(hb_obj, Aperture): add_aperture(hb_obj, points, vectors) elif isinstance(hb_obj, Door): add_door(hb_obj, points, vectors) elif isinstance(hb_obj, Shade): points.append(from_point3d(hb_obj.center)) vectors.append(from_vector3d(hb_obj.normal)) elif isinstance(hb_obj, Model): add_model(hb_obj, points, vectors) else: raise TypeError( 'Unrecognized honeybee object type: {}'.format(type(hb_obj)))
sky_type = 1 if len(direct) == 145 else 2 # i for tregenza; 2 for reinhart total = [dirr + difr for dirr, difr in zip(direct, diffuse)] # total radiation # override the legend default min and max to make sense for domes l_par = legend_par_.duplicate( ) if legend_par_ is not None else LegendParameters() if l_par.min is None: l_par.min = 0 if l_par.max is None: l_par.max = max(total) # output patch patch vectors patch_vecs_lb = view_sphere.tregenza_dome_vectors if len(total) == 145 \ else view_sphere.reinhart_dome_vectors patch_vecs = [from_vector3d(vec) for vec in patch_vecs_lb] # create the dome meshes if not show_comp_: # only create the total dome mesh mesh, compass, legend, title, mesh_values = \ draw_dome(total, center_pt3d, 'Total', l_par) patch_values = total else: # create domes for total, direct and diffuse # loop through the 3 radiation types and produce a dome mesh, compass, legend, title, mesh_values = [], [], [], [], [] rad_types = ('Total', 'Direct', 'Diffuse') rad_data = (total, direct, diffuse) for dome_i in range(3): cent_pt = Point3D(center_pt3d.x + radius * 3 * dome_i, center_pt3d.y, center_pt3d.z) dome_mesh, dome_compass, dome_legend, dome_title, dome_values = \
try: x_axis = to_vector3d(quad_only_) lb_faces = [ Face3D(f.boundary, Plane(f.normal, f[0], x_axis), f.holes) for f in lb_faces ] except AttributeError: pass # no plane connected; juse use default orientation lb_meshes = [ geo.mesh_grid(_grid_size, offset=_offset_dist_) for geo in lb_faces ] if len(lb_meshes) == 1: lb_mesh = lb_meshes[0] elif len(lb_meshes) > 1: lb_mesh = Mesh3D.join_meshes(lb_meshes) else: # use Rhino's default meshing try: # assume it's a Rhino Brep lb_mesh = to_gridded_mesh3d(_geometry, _grid_size, _offset_dist_) except TypeError: # assume it's a Rhino Mesh try: lb_mesh = to_mesh3d(_geometry) except TypeError: # unidientified geometry type raise TypeError( '_geometry must be a Brep or a Mesh. Got {}.'.format( type(_geometry))) # generate the test points, vectors, and areas. points = [from_point3d(pt) for pt in lb_mesh.face_centroids] vectors = [from_vector3d(vec) for vec in lb_mesh.face_normals] face_areas = lb_mesh.face_areas mesh = from_mesh3d(lb_mesh)
# deconstruct the matrix and get the sky dome vectors mtx = de_objectify_output(_sky_mtx) total_sky_rad = [ dir_rad + dif_rad for dir_rad, dif_rad in zip(mtx[1], mtx[2]) ] ground_rad = [(sum(total_sky_rad) / len(total_sky_rad)) * mtx[0][1] ] * len(total_sky_rad) all_rad = total_sky_rad + ground_rad lb_vecs = view_sphere.tregenza_dome_vectors if len(total_sky_rad) == 145 \ else view_sphere.reinhart_dome_vectors if mtx[0][0] != 0: # there is a north input for sky; rotate vectors north_angle = math.radians(mtx[0][0]) lb_vecs = tuple(vec.rotate_xy(north_angle) for vec in lb_vecs) lb_grnd_vecs = tuple(vec.reverse() for vec in lb_vecs) all_vecs = [from_vector3d(vec) for vec in lb_vecs + lb_grnd_vecs] # intersect the rays with the mesh normals = [from_vector3d(vec) for vec in study_mesh.face_normals] int_matrix_init, angles = intersect_mesh_rays(shade_mesh, points, all_vecs, normals, cpu_count=workers) # compute the results results = [] int_matrix = [] for int_vals, angles in zip(int_matrix_init, angles): pt_rel = [ival * math.cos(ang) for ival, ang in zip(int_vals, angles)] int_matrix.append(pt_rel)
# get the view vectors based on the view type patch_wghts = None if vt_str == 'Horizontal Radial': lb_vecs = view_sphere.horizontal_radial_vectors(30 * _resolution_) elif vt_str == 'Horizontal 30-Degree Offset': patch_mesh, lb_vecs = view_sphere.horizontal_radial_patches( 30, _resolution_) patch_wghts = view_sphere.horizontal_radial_patch_weights( 30, _resolution_) elif vt_str == 'Spherical': patch_mesh, lb_vecs = view_sphere.sphere_patches(_resolution_) patch_wghts = view_sphere.sphere_patch_weights(_resolution_) else: patch_mesh, lb_vecs = view_sphere.dome_patches(_resolution_) patch_wghts = view_sphere.dome_patch_weights(_resolution_) view_vecs = [from_vector3d(pt) for pt in lb_vecs] # mesh the geometry and context shade_mesh = join_geometry_to_mesh(_geometry + context_) if _geo_block_ \ else join_geometry_to_mesh(context_) # intersect the rays with the mesh if vt_str == 'Sky View': # account for the normals of the surface normals = [from_vector3d(vec) for vec in study_mesh.face_normals] int_matrix, angles = intersect_mesh_rays(shade_mesh, points, view_vecs, normals, parallel=parallel_) else: int_matrix, angles = intersect_mesh_rays(shade_mesh,
apply_mask_to_base_mask(strategy_pattern, over_pattern, orient_pattern) apply_mask_to_sky(sky_pattern, over_pattern) if left_fin_proj_ or right_fin_proj_: f_pattern = view_sphere.fin_pattern(direction, left_fin_proj_, right_fin_proj_, view_vecs) apply_mask_to_base_mask(strategy_pattern, f_pattern, orient_pattern) apply_mask_to_sky(sky_pattern, f_pattern) # account for any input context context_pattern = None if len(context_) != 0: shade_mesh = join_geometry_to_mesh(context_) # mesh the context points = [from_point3d(center_pt3d)] view_vecs = [from_vector3d(pt) for pt in view_vecs] int_matrix, angles = intersect_mesh_rays(shade_mesh, points, view_vecs) context_pattern = [val == 0 for val in int_matrix[0]] apply_mask_to_sky(sky_pattern, context_pattern) # get the weights for each patch to be used in view factor calculation weights = view_sphere.dome_radial_patch_weights(az_count, alt_count) if direction is not None: weights = [ wgt * abs(math.cos(ang)) * 2 for wgt, ang in zip(weights, dir_angles) ] # create meshes for the masks and compute any necessary view factors gray, black = Color(230, 230, 230), Color(0, 0, 0) context_view, orient_view, strategy_view = 0, 0, 0 if context_pattern is not None: