def test_init_compass(): """Test the initialization of Compass and basic properties.""" compass = Compass() str(compass) # test the string representation hash(compass) # test to be sure the compass is hash-able assert compass.radius == 100 assert compass.center == Point2D() assert compass.north_angle == 0 assert compass.north_vector == Vector2D(0, 1) assert compass.spacing_factor == 0.15 assert compass.min_point.is_equivalent(Point2D(-115.0, -115.0), 0.01) assert compass.max_point.is_equivalent(Point2D(115.0, 115.0), 0.01) assert isinstance(compass.inner_boundary_circle, Arc2D) assert len(compass.all_boundary_circles) == 3 for circ in compass.all_boundary_circles: assert isinstance(circ, Arc2D) assert len(compass.major_azimuth_points) == len(compass.MAJOR_AZIMUTHS) for pt in compass.major_azimuth_points: assert isinstance(pt, Point2D) assert len(compass.major_azimuth_ticks) == len(compass.MAJOR_AZIMUTHS) for lin in compass.major_azimuth_ticks: assert isinstance(lin, LineSegment2D) assert len(compass.minor_azimuth_points) == len(compass.MINOR_AZIMUTHS) for pt in compass.minor_azimuth_points: assert isinstance(pt, Point2D) assert len(compass.minor_azimuth_ticks) == len(compass.MINOR_AZIMUTHS) for lin in compass.minor_azimuth_ticks: assert isinstance(lin, LineSegment2D) assert isinstance(compass.min_point3d(), Point3D) assert isinstance(compass.max_point3d(), Point3D)
def test_equality(): """Test the equality and duplicatiion of of Compass objects.""" compass = Compass(radius=100) compass_dup = compass.duplicate() compass_alt = Compass(radius=200) assert compass is compass assert compass is not compass_dup assert compass == compass_dup assert compass != compass_alt
def test_label_points_from_angles(): """Test the label_points_from_angles method.""" compass = Compass() angles = list(range(0, 360, 30)) pts = compass.label_points_from_angles(angles) assert len(pts) == len(angles) for pt in pts: assert isinstance(pt, Point2D) lines = compass.ticks_from_angles(angles) assert len(lines) == len(angles) for lin in lines: assert isinstance(lin, LineSegment2D)
def test_compass_orthographic(): """Test the orthographic properties of the Compass.""" compass = Compass() assert len(compass.orthographic_altitude_points) == len(compass.ALTITUDES) for pt in compass.orthographic_altitude_points: assert isinstance(pt, Point2D) assert len(compass.orthographic_altitude_circles) == len(compass.ALTITUDES) for lin in compass.orthographic_altitude_circles: assert isinstance(lin, Arc2D)
def test_set_properties(): """Test the initialization of Compass and basic properties.""" compass = Compass() compass.radius = 200 assert compass.radius == 200 compass.center = Point2D(200, 0) assert compass.center == Point2D(200, 0) compass.north_angle = 10 assert compass.north_angle == 10 assert compass.north_vector != Vector2D(0, 1) compass.spacing_factor = 0.2 assert compass.spacing_factor == 0.2 assert compass.min_point.is_equivalent(Point2D(-40.0, -240.0), 0.01) assert compass.max_point.is_equivalent(Point2D(440.0, 240.0), 0.01)
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) center_pt3d_i = Point3D(center_pt3d.x + fac, center_pt3d.y, center_pt3d.z) # 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))
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 # set defaults for all of the if _north_ is not None: # process the _north_ try: _north_ = math.degrees( to_vector2d(_north_).angle_clockwise(Vector2D(0, 1))) except AttributeError: # north angle instead of vector _north_ = float(_north_) else: _north_ = 0 if _center_ is not None: # process the center point into a Point2D center_pt, z = to_point2d(_center_), to_point3d(_center_).z else: center_pt, z = Point2D(), 0 _scale_ = 1 if _scale_ is None else _scale_ # process the scale into a radius radius = (10 * _scale_) / conversion_to_meters() # create the compass compass = translate_compass(Compass(radius, center_pt, _north_, 1), z)
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
title = [] all_sun_pts = [] all_analemma = [] all_daily = [] all_compass = [] all_colors = [] all_col_pts = [] all_legends = [] for i, data in enumerate(data_): # 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) center_pt3d_i = Point3D(center_pt3d.x + fac, center_pt3d.y, center_pt3d.z) # 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), legend_par_, 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)
ori_dict = {'north': 0, 'east': 90, 'south': 180, 'west': 270} try: # first check if it's text for the direction orientation_ = ori_dict[orientation_.lower()] except KeyError: # it's a number for the orientation orientation_ = float(orientation_) direction = Vector3D(0, 1, 0).rotate_xy(-math.radians(orientation_)) # create the dome mesh of the sky and position/project it correctly sky_mask, view_vecs = view_sphere.dome_radial_patches(az_count, alt_count) sky_mask = sky_mask.scale(radius) if center_pt3d != Point3D(): m_vec = Vector3D(center_pt3d.x, center_pt3d.y, center_pt3d.z) sky_mask = sky_mask.move(m_vec) if projection_ is not None: if projection_.title() == 'Orthographic': pts = (Compass.point3d_to_orthographic(pt) for pt in sky_mask.vertices) elif projection_.title() == 'Stereographic': pts = (Compass.point3d_to_stereographic(pt, radius, center_pt3d) for pt in sky_mask.vertices) else: raise ValueError( 'Projection type "{}" is not recognized.'.format(projection_)) pts3d = tuple(Point3D(pt.x, pt.y, center_pt3d.z) for pt in pts) sky_mask = Mesh3D(pts3d, sky_mask.faces) sky_pattern = [True] * len( view_vecs) # pattern to be adjusted by the various masks # account for the orientation and any of the projection strategies orient_pattern, strategy_pattern = None, None if direction is not None: orient_pattern, dir_angles = view_sphere.orientation_pattern(