def draw_psych_chart(psy_chart): """Draw a given psychrometric chart object into Rhino geometry. This will NOT translate any colored meshes or data points. """ # output all of the lines/polylines for the various axes title_i = [from_polyline2d(psy_chart.chart_border, z)] temp_lines_i = [ from_linesegment2d(tl, z) for tl in psy_chart.temperature_lines ] rh_lines_i = [from_polyline2d(rhl, z) for rhl in psy_chart.rh_lines] hr_lines_i = [from_linesegment2d(hrl, z) for hrl in psy_chart.hr_lines] # add the text to the various lines title_i.append( text_objects(psy_chart.x_axis_text, plane_from_point(psy_chart.x_axis_location), psy_chart.legend_parameters.text_height * 1.5, psy_chart.legend_parameters.font, 0, 0)) title_i.append( text_objects( psy_chart.y_axis_text, plane_from_point(psy_chart.y_axis_location, Vector3D(0, 1)), psy_chart.legend_parameters.text_height * 1.5, psy_chart.legend_parameters.font, 2, 0)) temp_lines_i = temp_lines_i + small_labels( psy_chart, psy_chart.temperature_labels, psy_chart.temperature_label_points, 1, 0) rh_lines_i = rh_lines_i + small_labels(psy_chart, psy_chart.rh_labels[:-1], psy_chart.rh_label_points[:-1], 2, 3, 0.8) hr_lines_i = hr_lines_i + small_labels(psy_chart, psy_chart.hr_labels, psy_chart.hr_label_points, 0, 3) # add enthalpy or wet bulb lines if plot_wet_bulb_: enth_wb_lines_i = [ from_linesegment2d(el, z) for el in psy_chart.wb_lines ] enth_wb_lines_i = enth_wb_lines_i + small_labels( psy_chart, psy_chart.wb_labels, psy_chart.wb_label_points, 2, 3) else: enth_wb_lines_i = [ from_linesegment2d(el, z) for el in psy_chart.enthalpy_lines ] enth_wb_lines_i = enth_wb_lines_i + small_labels( psy_chart, psy_chart.enthalpy_labels, psy_chart.enthalpy_label_points, 2, 3) # add all of the objects to the bse list title.append(title_i) temp_lines.append(temp_lines_i) rh_lines.append(rh_lines_i) hr_lines.append(hr_lines_i) enth_wb_lines.append(enth_wb_lines_i)
def translate_compass(compass, z=0, font='Arial'): """Translate a Ladybug Compass object into Grasshopper geometry. Args: compass: A Ladybug Compass object to be converted to Rhino geometry. z: A number for the Z-coordinate to be used in translation. (Default: 0) font: Optional text for the font to be used in creating the text. (Default: 'Arial') Returns: A list of Rhino geometries in the following order. - all_boundary_circles -- Three Circle objects for the compass boundary. - major_azimuth_ticks -- Line objects for the major azimuth labels. - major_azimuth_text -- Bake-able text objects for the major azimuth labels. """ # set default variables based on the compass properties maj_txt = compass.radius / 2.5 xaxis = Vector3D(1, 0, 0).rotate_xy(math.radians(compass.north_angle)) result = [] # list to hold all of the returned objects # create the boundary circles for circle in compass.all_boundary_circles: result.append(from_arc2d(circle, z)) # generate the labels and tick marks for the azimuths for line in compass.major_azimuth_ticks: result.append(from_linesegment2d(line, z)) for txt, pt in zip(compass.MAJOR_TEXT, compass.major_azimuth_points): result.append( text_objects(txt, Plane(o=Point3D(pt.x, pt.y, z), x=xaxis), maj_txt, font, 1, 3)) return result
def create_graphic_container(_season, _data, _study_mesh, _legend_par): """Creates the Ladybug 'Graphic' Object from the result data Copied from Ladybug 'IncidentRadiation' Component Arguments: _season: (str) 'Winter' or 'Summer'. Used in the title. _data: (list: float:) A list of the result data to use to color / style the output _study_mesh: (ladybug_geometry.geometry3d.Mesh3D) The joined Mesh used in the analysis _legend_par: Ladybug Legend Parameters Returns: (tuple) graphic: (ladybug.graphic.GraphicContainer) The Ladybug Graphic Object title: The text title """ graphic = GraphicContainer(_data, _study_mesh.min, _study_mesh.max, _legend_par) graphic.legend_parameters.title = 'kWh' title = text_objects('{} Incident Radiation'.format(_season), graphic.lower_title_location, graphic.legend_parameters.text_height * 1.5, graphic.legend_parameters.font) return graphic, title
def label_face(face, _attribute_, _font_, label_text, base_pts, labels, wire_frame): """Generate labels for a face or sub-face and add it to a list.""" face_prop = get_attr_nested(face, _attribute_) # get a base plane and text height for the text label cent_pt = face.geometry.center # base point for the text base_plane = Plane(face.normal, cent_pt) if base_plane.y.z < 0: # base plane pointing downwards; rotate it base_plane = base_plane.rotate(base_plane.n, math.pi, base_plane.o) if _txt_height_ is None: # auto-calculate default text height txt_len = len(face_prop) if len(face_prop) > 10 else 10 largest_dim = max((face.geometry.max.x - face.geometry.min.x), (face.geometry.max.y - face.geometry.min.y)) txt_h = largest_dim / (txt_len * 2) else: txt_h = _txt_height_ # move base plane origin a little to avoid overlaps of adjacent labels if base_plane.n.x != 0: m_vec = base_plane.y if base_plane.n.x < 0 else -base_plane.y else: m_vec = base_plane.y if base_plane.n.z < 0 else -base_plane.y base_plane = base_plane.move(m_vec * txt_h) # create the text label label = text_objects(face_prop, base_plane, txt_h, font=_font_, horizontal_alignment=1, vertical_alignment=3) # append everything to the lists label_text.append(face_prop) base_pts.append(from_plane(base_plane)) labels.append(label) wire_frame.extend(from_face3d_to_wireframe(face.geometry))
def small_labels(psy_chart, labels, points, x_align, y_align, factor=1.0): """Translate a list of psych chart text labels into the Rhino scene.""" return [ text_objects(txt, Plane(o=Point3D(pt.x, pt.y, z)), psy_chart.legend_parameters.text_height * factor, psy_chart.legend_parameters.font, x_align, y_align) for txt, pt in zip(labels, points) ]
windrose._zero_count / len(windrose.analysis_values) * 100.0, 2), windrose._zero_count) windrose.base_point = Point2D(center_pt_2d.x, center_pt_2d.y) # Make the mesh mesh = from_mesh2d(windrose.colored_mesh, _center_pt_.z) # Make the graphic outputs legend = legend_objects(windrose.legend) freq_per = windrose._frequency_hours / \ len([b for a in windrose.histogram_data for b in a]) freq_text = '\nEach closed polyline shows frequency of {}% = {} hours.'.format( round(freq_per * 100, 1), windrose._frequency_hours) title = text_objects( title_text(speed_data) + calm_text + freq_text, windrose.container.lower_title_location, windrose.legend_parameters.text_height, windrose.legend_parameters.font) compass = compass_objects(windrose.compass, _center_pt_.z, None) orient_line = [ from_linesegment2d(seg, _center_pt_.z) for seg in windrose.orientation_lines ] freq_line = [from_polygon2d(poly) for poly in windrose.frequency_lines] windrose_lines = [ from_polygon2d(poly) for poly in windrose.windrose_lines ] fac = (i + 1) * windrose.compass_radius * 3 center_pt_2d = Point2D(_center_pt_.x + fac, _center_pt_.y) # Add histogram
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] # create the mesh and legend outputs graphic = GraphicContainer(results, study_mesh.min, study_mesh.max, legend_par_) graphic.legend_parameters.title = 'hours' if legend_par_ is None or legend_par_.are_colors_default: graphic.legend_parameters.colors = Colorset.ecotect() title = text_objects('Direct Sun Hours', graphic.lower_title_location, graphic.legend_parameters.text_height * 1.5, graphic.legend_parameters.font) # create all of the visual outputs study_mesh.colors = graphic.value_colors mesh = from_mesh3d(study_mesh) legend = legend_objects(graphic.legend)
d_meshes = month_chart.data_meshes if d_meshes is not None: data_mesh = [from_mesh2d(msh, z_val_tol) for msh in d_meshes] d_lines = month_chart.data_polylines if d_lines is not None: data_lines = [from_polyline2d(lin, z_val_tol) for lin in d_lines] borders = [from_polyline2d(month_chart.chart_border, z_val)] + \ [from_linesegment2d(line, z_val) for line in month_chart.y_axis_lines] + \ [from_linesegment2d(line, z_val_tol) for line in month_chart.month_lines] legend = legend_objects(month_chart.legend) # process all of the text-related outputs title_txt = month_chart.title_text if global_title_ is None else global_title_ txt_hgt = month_chart.legend_parameters.text_height font = month_chart.legend_parameters.font title = text_objects(title_txt, month_chart.lower_title_location, txt_hgt, font) # process the first y axis y1_txt = month_chart.y_axis_title_text1 if len( y_axis_title_) == 0 else y_axis_title_[0] y_title = text_objects(y1_txt, month_chart.y_axis_title_location1, txt_hgt, font) label1 = [ text_objects(txt, Plane(o=Point3D(pt.x, pt.y, z_val)), txt_hgt, font, 1, 0) for txt, pt in zip(month_chart.month_labels, month_chart.month_label_points) ] label2 = [ text_objects(txt, Plane(o=Point3D(pt.x, pt.y, z_val)), txt_hgt, font, 2, 3) for txt, pt in zip(month_chart.y_axis_labels1, month_chart.y_axis_label_points1)
# create the ladybug compass object lb_compass = Compass(radius, center_pt_i, north_) # create a graphic container to generate colors and legends n_data = data.filter_by_moys( moys) # filter data collection by sun-up hours graphic = GraphicContainer(n_data.values, lb_compass.min_point3d(z), lb_compass.max_point3d(z), lpar, n_data.header.data_type, n_data.header.unit) all_legends.append(legend_objects(graphic.legend)) title.append( text_objects(title_text(n_data), graphic.lower_title_location, graphic.legend_parameters.text_height, graphic.legend_parameters.font)) # create points, analemmas, daily arcs, and compass geometry sun_pts_init = draw_sun_positions(suns, radius, center_pt3d_i) analemma_i, daily_i = draw_analemma_and_arcs( sp, datetimes, radius, center_pt3d_i) compass_i = compass_objects(lb_compass, z, None, projection_, graphic.legend_parameters.font) all_analemma.append(analemma_i) all_daily.append(daily_i) all_compass.append(compass_i) # produce a visualization of colored points cols = [color_to_color(col) for col in graphic.value_colors] col_pts = []
def draw_dome(dome_data, center, dome_name, legend_par): """Draw the dome mesh, compass, legend, and title for a sky dome. Args: dome_data: List of radiation values for the dome data center: Point3D for the center of the sun path. dome_name: Text for the dome name, which will appear in the title. legend_par: Legend parameters to be used for the dome Returns: dome_mesh: A colored mesh for the dome based on dome_data. dome_compass: A compass for the dome. dome_legend: A leend for the colored dome mesh. dome_title: A title for the dome. values: A list of radiation values that align with the dome_mesh faces. """ # create the dome mesh and ensure patch values align with mesh faces if len(dome_data) == 145: # tregenza sky lb_mesh = view_sphere.tregenza_dome_mesh_high_res.scale(radius) values = [] # high res dome has 3 x 3 faces per patch; we must convert tot_i = 0 # track the total number of patches converted for patch_i in view_sphere.TREGENZA_PATCHES_PER_ROW: row_vals = [] for val in dome_data[tot_i:tot_i + patch_i]: row_vals.extend([val] * 3) for i in range(3): values.extend(row_vals) tot_i += patch_i values = values + [dome_data[-1] ] * 18 # last patch has triangular faces else: #reinhart sky lb_mesh = view_sphere.reinhart_dome_mesh.scale(radius) values = dome_data + [dome_data[-1] ] * 11 # last patch has triangular faces # move and/or rotate the mesh as needed if north != 0: lb_mesh = lb_mesh.rotate_xy(math.radians(north), Point3D()) if center != Point3D(): lb_mesh = lb_mesh.move(Vector3D(center.x, center.y, center.z)) # project the mesh if requested if projection_ is not None: if projection_.title() == 'Orthographic': pts = (Compass.point3d_to_orthographic(pt) for pt in lb_mesh.vertices) elif projection_.title() == 'Stereographic': pts = (Compass.point3d_to_stereographic(pt, radius, center) for pt in lb_mesh.vertices) else: raise ValueError( 'Projection type "{}" is not recognized.'.format(projection_)) pts3d = tuple(Point3D(pt.x, pt.y, z) for pt in pts) lb_mesh = Mesh3D(pts3d, lb_mesh.faces) # output the dome visualization, including legend and compass move_fac = radius * 0.15 min_pt = lb_mesh.min.move(Vector3D(-move_fac, -move_fac, 0)) max_pt = lb_mesh.max.move(Vector3D(move_fac, move_fac, 0)) graphic = GraphicContainer(values, min_pt, max_pt, legend_par) graphic.legend_parameters.title = 'kWh/m2' lb_mesh.colors = graphic.value_colors dome_mesh = from_mesh3d(lb_mesh) dome_legend = legend_objects(graphic.legend) dome_compass = compass_objects( Compass(radius, Point2D(center.x, center.y), north), z, None, projection_, graphic.legend_parameters.font) # construct a title from the metadata st, end = metadata[2], metadata[3] time_str = '{} - {}'.format(st, end) if st != end else st title_txt = '{} Radiation\n{}\n{}'.format( dome_name, time_str, '\n'.join([dat for dat in metadata[4:]])) dome_title = text_objects(title_txt, graphic.lower_title_location, graphic.legend_parameters.text_height, graphic.legend_parameters.font) return dome_mesh, dome_compass, dome_legend, dome_title, values
lpar = None if len(legend_par_) == 0 else legend_par_[-1] # create the hourly plot object and get the main pieces of geometry hour_plot = HourlyPlot(data_coll, lpar, _base_pt_, _x_dim_, _y_dim_, _z_dim_, reverse_y_) msh = from_mesh2d(hour_plot.colored_mesh2d, _base_pt_.z) if _z_dim_ == 0 else \ from_mesh3d(hour_plot.colored_mesh3d) mesh.append(msh) border = [from_polyline2d(hour_plot.chart_border2d, _base_pt_.z)] + \ [from_linesegment2d(line, _base_pt_.z) for line in hour_plot.hour_lines2d] + \ [from_linesegment2d(line, _base_pt_.z) for line in hour_plot.month_lines2d] all_borders.append(border) legnd = legend_objects(hour_plot.legend) all_legends.append(legnd) tit_txt = text_objects(hour_plot.title_text, hour_plot.lower_title_location, hour_plot.legend_parameters.text_height, hour_plot.legend_parameters.font) title.append(tit_txt) # create the text label objects label1 = [ text_objects(txt, Plane(o=Point3D(pt.x, pt.y, _base_pt_.z)), hour_plot.legend_parameters.text_height, hour_plot.legend_parameters.font, 2, 3) for txt, pt in zip(hour_plot.hour_labels, hour_plot.hour_label_points2d) ] label2 = [ text_objects(txt, Plane(o=Point3D(pt.x, pt.y, _base_pt_.z)), hour_plot.legend_parameters.text_height, hour_plot.legend_parameters.font, 1, 0) for txt, pt in zip(hour_plot.month_labels, hour_plot.month_label_points2d)
y_dim, t_min, t_max, use_ip=use_ip) psy_chart.z = z psy_chart.original_temperature = original_temperature draw_psych_chart(psy_chart) if isinstance(all_data[-2], BaseCollection): meta_i = all_data[-2].header.metadata.items() title_items = ['Time [hr]' ] + ['{}: {}'.format(k, v) for k, v in meta_i] else: title_items = ['Psychrometric Chart'] title[j + j * len(data_)].append( text_objects('\n'.join(title_items), psy_chart.container.upper_title_location, psy_chart.legend_parameters.text_height * 1.5, psy_chart.legend_parameters.font, 0, 0)) psych_chart.append(psy_chart) # plot the data on the chart lb_points = psy_chart.data_points points.append([from_point2d(pt) for pt in lb_points]) if len(lb_points) != 1: # hide the points and just display the mesh hide_output(ghenv.Component, 8) mesh.append(from_mesh2d(psy_chart.colored_mesh, z)) legend.append(legend_objects(psy_chart.legend)) else: # show the single point on the chart show_output(ghenv.Component, 8) # process any of the connected data into a legend and colors if len(data_) != 0:
max_dist_, parallel=parallel_) # compute the results int_mtx = objectify_output('Visibility Intersection Matrix', int_matrix) vec_count = len(_view_points) if pt_weights_: # weight intersections by the input point weights tot_wght = sum(pt_weights_) / vec_count adj_weights = [wght / tot_wght for wght in pt_weights_] results = [] for int_vals in int_matrix: w_res = [ival * wght for ival, wght in zip(int_vals, adj_weights)] results.append(sum(w_res) * 100 / vec_count) else: # no need to wieght results results = [sum(int_list) * 100 / vec_count for int_list in int_matrix] # create the mesh and legend outputs graphic = GraphicContainer(results, study_mesh.min, study_mesh.max, legend_par_) graphic.legend_parameters.title = '%' if legend_par_ is None or legend_par_.are_colors_default: graphic.legend_parameters.colors = Colorset.view_study() title = text_objects('Visibility Percent', graphic.lower_title_location, graphic.legend_parameters.text_height * 1.5, graphic.legend_parameters.font) # create all of the visual outputs study_mesh.colors = graphic.value_colors mesh = from_mesh3d(study_mesh) legend = legend_objects(graphic.legend)
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) rad_result = sum(r * w for r, w in zip(pt_rel, all_rad)) results.append(rad_result) # output the intersection matrix and compute total radiation int_mtx = objectify_output('Geometry/Sky Intersection Matrix', int_matrix) unit_conv = conversion_to_meters()**2 total = 0 for rad, area in zip(results, study_mesh.face_areas): total += rad * area * unit_conv # create the mesh and legend outputs graphic = GraphicContainer(results, study_mesh.min, study_mesh.max, legend_par_) graphic.legend_parameters.title = 'kWh/m2' title = text_objects('Incident Radiation', graphic.lower_title_location, graphic.legend_parameters.text_height * 1.5, graphic.legend_parameters.font) # create all of the visual outputs study_mesh.colors = graphic.value_colors mesh = from_mesh3d(study_mesh) legend = legend_objects(graphic.legend)
elif isinstance(hb_obj, Room): faces.extend(hb_obj.faces) else: faces.append(hb_obj) # apply analysis period to the data if connected if period_ is not None: _data = [coll.filter_by_analysis_period(period_) for coll in _data] # set default norm_by_floor value normalize_ = True if normalize_ is None else normalize_ # create the ColorFace visualization object and output geometry color_obj = ColorFace(_data, faces, legend_par_, sim_step_, normalize_, units_abbreviation()) graphic = color_obj.graphic_container mesh = [ from_face3ds_to_colored_mesh([fc], col) for fc, col in zip( color_obj.matched_flat_geometry, graphic.value_colors) ] wire_frame = [] for face in color_obj.matched_flat_faces: wire_frame.append(from_face3d_to_wireframe(face.geometry)) legend = legend_objects(graphic.legend) title = text_objects(color_obj.title_text, graphic.lower_title_location, graphic.legend_parameters.text_height, graphic.legend_parameters.font) faces = color_obj.matched_flat_faces colors = [color_to_color(col, 125) for col in graphic.value_colors] values = graphic.values
for ival, ang in zip(int_vals, angles)) weight_result = sum(r * w for r, w in zip(w_res, patch_wghts)) results.append(weight_result * 100 / vec_count) else: if patch_wghts: for int_list in int_matrix: weight_result = sum(r * w for r, w in zip(int_list, patch_wghts)) results.append(weight_result * 100 / vec_count) else: results = [ sum(int_list) * 100 / vec_count for int_list in int_matrix ] # create the mesh and legend outputs graphic = GraphicContainer(results, study_mesh.min, study_mesh.max, legend_par_) graphic.legend_parameters.title = '%' if legend_par_ is None or legend_par_.are_colors_default: graphic.legend_parameters.colors = Colorset.view_study() title_txt = vt_str if vt_str in ('Sky Exposure', 'Sky View') else \ '{} View'.format(vt_str) title = text_objects(title_txt, graphic.lower_title_location, graphic.legend_parameters.text_height * 1.5, graphic.legend_parameters.font) # create all of the visual outputs study_mesh.colors = graphic.value_colors mesh = from_mesh3d(study_mesh) legend = legend_objects(graphic.legend)
# extract any rooms from input Models rooms = [] for hb_obj in _rooms_model: if isinstance(hb_obj, Model): rooms.extend(hb_obj.rooms) else: rooms.append(hb_obj) for room in rooms: room_prop = get_attr_nested(room, _attribute_) # create the text label cent_pt = room.geometry.center # base point for the text base_plane = Plane(Vector3D(0, 0, 1), cent_pt) if _txt_height_ is None: # auto-calculate default text height txt_len = len(room_prop) if len(room_prop) > 10 else 10 txt_h = (room.geometry.max.x - room.geometry.min.x) / txt_len else: txt_h = _txt_height_ label = text_objects(room_prop, base_plane, txt_h, font=_font_, horizontal_alignment=1, vertical_alignment=3) # append everything to the lists label_text.append(room_prop) base_pts.append(from_plane(base_plane)) labels.append(label) wire_frame.extend(from_polyface3d_to_wireframe(room.geometry))