def test_mesh2d_init_from_polygon_triangulated_incorrect(): """Test the initalization of Mesh2D from_polygon_triangulated.""" verts = (Point2D(0, 0), Point2D(2, 0), Point2D(2, 1), Point2D(1, 1), Point2D(1, 2), Point2D(2, 0)) polygon = Polygon2D(verts) with pytest.raises(ValueError): Mesh2D.from_polygon_triangulated(polygon)
def test_mesh2d_init_concave(): """Test the initalization of Mesh2D objects with a concave quad face.""" pts = (Point2D(0, 0), Point2D(0, 2), Point2D(1, 1), Point2D(2, 0)) mesh = Mesh2D(pts, [(0, 1, 2, 3)]) assert len(mesh.vertices) == 4 assert len(mesh.faces) == 1 assert mesh[0] == Point2D(0, 0) assert mesh[1] == Point2D(0, 2) assert mesh[2] == Point2D(1, 1) assert mesh[3] == Point2D(2, 0) assert mesh.area == 2 assert mesh.min == Point2D(0, 0) assert mesh.max == Point2D(2, 2) assert mesh.center == Point2D(1, 1) assert mesh.centroid.x == pytest.approx(0.667, rel=1e-2) assert mesh.centroid.y == pytest.approx(0.667, rel=1e-2) assert len(mesh.face_areas) == 1 assert mesh.face_areas[0] == 2 assert len(mesh.face_centroids) == 1 mesh = Mesh2D(pts, [(3, 2, 1, 0)]) assert len(mesh.vertices) == 4 assert len(mesh.faces) == 1 assert mesh.area == 2
def _segment_mesh_2d(self, base_pt=Point2D(0, 0)): """Mesh2D for the segments in the 2D space of the legend.""" # get general properties _l_par = self.legend_parameters n_seg = self.segment_length # create the 2D mesh of the legend if _l_par.vertical: mesh2d = Mesh2D.from_grid(base_pt, 1, n_seg, _l_par.segment_width, _l_par.segment_height) else: _base_pt = Point2D(base_pt.x - _l_par.segment_width * n_seg, base_pt.y) mesh2d = Mesh2D.from_grid(_base_pt, n_seg, 1, _l_par.segment_width, _l_par.segment_height) # add colors to the mesh _seg_colors = self.segment_colors if not _l_par.continuous_legend: mesh2d.colors = _seg_colors else: if _l_par.vertical: mesh2d.colors = _seg_colors + _seg_colors else: mesh2d.colors = tuple(col for col in _seg_colors for i in (0, 1)) return mesh2d
def test_mesh2d_init_from_face_vertices(): """Test the initialization of Mesh2D from_face_vertices.""" face_1 = (Point2D(0, 0), Point2D(0, 2), Point2D(2, 2), Point2D(2, 0)) face_2 = (Point2D(2, 2), Point2D(2, 0), Point2D(4, 0)) mesh_1 = Mesh2D.from_face_vertices([face_1, face_2]) mesh_2 = Mesh2D.from_face_vertices([face_1, face_2], False) assert len(mesh_1.vertices) == 5 assert len(mesh_2.vertices) == 7 assert len(mesh_1.faces) == len(mesh_2.faces) == 2 assert mesh_1.area == mesh_2.area == 6 assert mesh_1.min == mesh_2.min == Point2D(0, 0) assert mesh_1.max == mesh_2.max == Point2D(4, 2) assert mesh_1.center == mesh_2.center == Point2D(2, 1) assert mesh_1.centroid.x == mesh_2.centroid.x == pytest.approx(1.56, rel=1e-2) assert mesh_1.centroid.y == mesh_2.centroid.y == pytest.approx(0.89, rel=1e-2) assert len(mesh_1.face_areas) == len(mesh_2.face_areas) == 2 assert mesh_1.face_areas[0] == mesh_2.face_areas[0] == 4 assert mesh_1.face_areas[1] == mesh_2.face_areas[1] == 2 assert len(mesh_1.face_centroids) == len(mesh_2.face_centroids) == 2 assert mesh_1.face_centroids[0] == mesh_2.face_centroids[0] == Point2D( 1, 1) assert mesh_1.face_centroids[1].x == mesh_2.face_centroids[ 1].x == pytest.approx(2.67, rel=1e-2) assert mesh_1.face_centroids[1].y == mesh_2.face_centroids[ 1].y == pytest.approx(0.67, rel=1e-2) assert mesh_1._is_color_by_face is mesh_1._is_color_by_face is False assert mesh_1.colors is mesh_1.colors is None
def test_mesh2d_to_from_dict(): """Test the to/from dict of Mesh2D objects.""" pts = (Point2D(0, 0), Point2D(0, 2), Point2D(2, 2), Point2D(2, 0)) mesh = Mesh2D(pts, [(0, 1, 2, 3)]) mesh_dict = mesh.to_dict() new_mesh = Mesh2D.from_dict(mesh_dict) assert isinstance(new_mesh, Mesh2D) assert new_mesh.to_dict() == mesh_dict
def test_mesh2d_incorrect(): """Test the initalization of Mesh2D objects with incorrect values.""" pts = (Point2D(0, 0), Point2D(0, 2), Point2D(2, 2), Point2D(2, 0), Point2D(4, 0)) with pytest.raises(AssertionError): Mesh2D(pts, [(0, 1, 2, 3, 5)]) # too many vertices in a face with pytest.raises(AssertionError): Mesh2D(pts, []) # we need at least one face with pytest.raises(AssertionError): Mesh2D(pts, (0, 1, 2, 3)) # incorrect input type for face with pytest.raises(IndexError): Mesh2D(pts, [(0, 1, 2, 6)]) # incorrect index used by face with pytest.raises(TypeError): Mesh2D(pts, [(0.0, 1, 2, 6)]) # incorrect use of floats for face index
def test_equality(): """Test the equality of Polygon2D objects.""" pts = (Point2D(0, 0), Point2D(0, 2), Point2D(2, 2), Point2D(2, 0)) pts_2 = (Point2D(0, 0), Point2D(0, 2), Point2D(2, 2), Point2D(2, 0.1)) mesh = Mesh2D(pts, [(0, 1, 2, 3)]) mesh_dup = mesh.duplicate() mesh_alt = Mesh2D(pts_2, [(0, 1, 2, 3)]) assert mesh is mesh assert mesh is not mesh_dup assert mesh == mesh_dup assert hash(mesh) == hash(mesh_dup) assert mesh != mesh_alt assert hash(mesh) != hash(mesh_alt)
def test_join_meshes(): """Test the join_meshes method.""" pts1 = (Point2D(0, 0), Point2D(0, 2), Point2D(2, 2), Point2D(2, 0)) pts2 = (Point2D(2, 2), Point2D(2, 4), Point2D(4, 4), Point2D(4, 2)) mesh1 = Mesh2D(pts1, [(0, 1, 2, 3)]) mesh2 = Mesh2D(pts2, [(0, 1, 2, 3)]) mesh1.face_centroids mesh2.face_centroids joined_mesh = Mesh2D.join_meshes([mesh1, mesh2]) assert isinstance(joined_mesh, Mesh2D) assert len(joined_mesh.faces) == 2 assert len(joined_mesh.vertices) == 8 assert joined_mesh._face_centroids is not None
def test_reflect(): """Test the Mesh2D reflect method.""" pts = (Point2D(1, 1), Point2D(1, 2), Point2D(2, 2), Point2D(2, 1), Point2D(3, 1)) mesh = Mesh2D(pts, [(0, 1, 2, 3), (2, 3, 4)]) origin_1 = Point2D(1, 0) normal_1 = Vector2D(1, 0) normal_2 = Vector2D(-1, -1).normalize() test_1 = mesh.reflect(normal_1, origin_1) assert test_1[0].x == pytest.approx(1, rel=1e-3) assert test_1[0].y == pytest.approx(1, rel=1e-3) assert test_1[2].x == pytest.approx(0, rel=1e-3) assert test_1[2].y == pytest.approx(2, rel=1e-3) assert mesh.area == test_1.area assert len(mesh.vertices) == len(test_1.vertices) assert len(mesh.faces) == len(test_1.faces) test_1 = mesh.reflect(normal_2, Point2D(0, 0)) assert test_1[0].x == pytest.approx(-1, rel=1e-3) assert test_1[0].y == pytest.approx(-1, rel=1e-3) assert test_1[2].x == pytest.approx(-2, rel=1e-3) assert test_1[2].y == pytest.approx(-2, rel=1e-3) assert mesh.area == test_1.area assert len(mesh.vertices) == len(test_1.vertices) assert len(mesh.faces) == len(test_1.faces) test_2 = mesh.reflect(normal_2, origin_1) assert test_2[0].x == pytest.approx(0, rel=1e-3) assert test_2[0].y == pytest.approx(0, rel=1e-3) assert test_2[2].x == pytest.approx(-1, rel=1e-3) assert test_2[2].y == pytest.approx(-1, rel=1e-3) assert mesh.area == test_2.area assert len(mesh.vertices) == len(test_2.vertices) assert len(mesh.faces) == len(test_2.faces)
def _generate_mesh(self): """Get the colored mesh from this object's hour values.""" # global properties used in the generation of the mesh prs = self.average_pressure t_per_row = [self._min_temperature] + self._t_category x_per_row = [self.t_x_value(t) for t in t_per_row] temp_in_c = self.TEMP_TYPE.to_unit(t_per_row, 'C', 'F') \ if self.use_ip else t_per_row # loop through RH rows and create mesh vertices and faces vertices = [Point2D(x, self._base_point.y) for x in x_per_row] faces, vert_count, row_len = [], 0, len(t_per_row) for rh in self._rh_category: vert_count += row_len y1 = self.hr_y_value(humid_ratio_from_db_rh(temp_in_c[0], rh, prs)) vertices.append(Point2D(x_per_row[0], y1)) for i, t in enumerate(temp_in_c[1:]): y = self.hr_y_value(humid_ratio_from_db_rh(t, rh, prs)) vertices.append(Point2D(x_per_row[i + 1], y)) v1 = vert_count - row_len + i v2 = v1 + 1 v3 = vert_count + i + 1 v4 = v3 - 1 faces.append((v1, v2, v3, v4)) # create the Mesh2D, remove unused faces, and assign the colors mesh = Mesh2D(vertices, faces) mesh = mesh.remove_faces_only(self._remove_pattern) mesh.colors = self._container.value_colors return mesh
def _compute_colored_mesh2d(self): """Compute a colored mesh from this object's data collection.""" # generate the base mesh as a stanadard grid _colored_mesh2d = Mesh2D.from_grid(self.base_point, self._num_x, self._num_y, self.x_dim, self.y_dim) # remove any faces in the base mesh that do not represent the data if not isinstance(self.data_collection, HourlyContinuousCollection): # get a pattern of booleans for whether mesh faces should be included data_coll_moys = [dt.moy for dt in self.data_collection.datetimes] data_coll_moys.append( 527100) # extra value for the end of the list found_i = 0 mesh_pattern = [] for moy in self.analysis_period.moys: if moy == data_coll_moys[found_i]: mesh_pattern.append(True) found_i += 1 else: mesh_pattern.append(False) if self._reverse_y: hr_diff = (self.analysis_period.end_hour - self.analysis_period.st_hour) t_step = self.analysis_period.timestep t_diff = t_step * hr_diff + 1 if t_step == 1 or hr_diff != 23 else \ t_step * (hr_diff + 1) mesh_pat_rev = [] for i in range(0, len(mesh_pattern), t_diff): mesh_pat_rev.extend(reversed(mesh_pattern[i:i + t_diff])) mesh_pattern = mesh_pat_rev _colored_mesh2d = _colored_mesh2d.remove_faces_only(mesh_pattern) # assign the colors to the mesh _colored_mesh2d.colors = self.colors return _colored_mesh2d
def test_rotate(): """Test the Mesh2D rotate method.""" pts = (Point2D(0, 0), Point2D(0, 2), Point2D(2, 2), Point2D(2, 0), Point2D(4, 0)) mesh = Mesh2D(pts, [(0, 1, 2, 3), (2, 3, 4)]) origin_1 = Point2D(1, 1) test_1 = mesh.rotate(math.pi, origin_1) assert test_1[0].x == pytest.approx(2, rel=1e-3) assert test_1[0].y == pytest.approx(2, rel=1e-3) assert test_1[2].x == pytest.approx(0, rel=1e-3) assert test_1[2].y == pytest.approx(0, rel=1e-3) assert mesh.area == test_1.area assert len(mesh.vertices) == len(test_1.vertices) assert len(mesh.faces) == len(test_1.faces) test_2 = mesh.rotate(math.pi / 2, origin_1) assert test_2[0].x == pytest.approx(2, rel=1e-3) assert test_2[0].y == pytest.approx(0, rel=1e-3) assert test_2[2].x == pytest.approx(0, rel=1e-3) assert test_2[2].y == pytest.approx(2, rel=1e-3) assert mesh.area == test_2.area assert len(mesh.vertices) == len(test_2.vertices) assert len(mesh.faces) == len(test_2.faces)
def test_remove_faces(): """Test the Mesh3D remove_faces method.""" mesh_2d = Mesh2D.from_grid(Point2D(1, 1), 8, 2, 0.25, 1) mesh = Mesh3D.from_mesh2d(mesh_2d) assert len(mesh.vertices) == 27 assert len(mesh.faces) == 16 assert mesh.area == 4 pattern_1 = [] for i in range(4): pattern_1.extend([True, False, False, False]) mesh_1, vert_pattern = mesh.remove_faces(pattern_1) assert len(mesh_1.vertices) == 16 assert len(mesh_1.faces) == 4 assert mesh_1.area == 1 for face in mesh_1.faces: for i in face: mesh_1[i] # make sure all face indices reference current vertices pattern_2 = [] for i in range(8): pattern_2.extend([True, False]) mesh_2, vert_pattern = mesh.remove_faces(pattern_2) assert len(mesh_2.vertices) == 18 assert len(mesh_2.faces) == 8 assert mesh_2.area == 2 for face in mesh_2.faces: for i in face: mesh_2[i] # make sure all face indices reference current vertices
def test_mesh2d_init_from_polygon_grid_concave(): """Test the initalization of Mesh2D from_polygon_grid.""" verts = (Point2D(0, 0), Point2D(2, 0), Point2D(2, 1), Point2D(1, 1), Point2D(1, 2), Point2D(0, 2)) polygon = Polygon2D(verts) mesh = Mesh2D.from_polygon_grid(polygon, 0.5, 0.5, False) assert len(mesh.vertices) == 21 assert len(mesh.faces) == 12 assert mesh.area == 3 assert mesh.min.x == 0 assert mesh.min.y == 0 assert mesh.max.x == 2 assert mesh.max.y == 2 assert mesh.center.x == 1 assert mesh.center.y == 1 assert mesh.centroid.x == pytest.approx(0.83, rel=1e-2) assert mesh.centroid.y == pytest.approx(0.83, rel=1e-2) assert len(mesh.face_areas) == 12 assert mesh.face_areas[0] == 0.25 assert len(mesh.face_centroids) == 12 assert mesh._is_color_by_face is False assert mesh.colors is None
def test_mesh2d_init(): """Test the initalization of Mesh2D objects and basic properties.""" pts = (Point2D(0, 0), Point2D(0, 2), Point2D(2, 2), Point2D(2, 0)) mesh = Mesh2D(pts, [(0, 1, 2, 3)]) str(mesh) # test the string representation of the object assert len(mesh.vertices) == 4 assert len(mesh.faces) == 1 assert mesh[0] == Point2D(0, 0) assert mesh[1] == Point2D(0, 2) assert mesh[2] == Point2D(2, 2) assert mesh[3] == Point2D(2, 0) assert mesh.area == 4 assert mesh.min == Point2D(0, 0) assert mesh.max == Point2D(2, 2) assert mesh.center == Point2D(1, 1) assert mesh.centroid == Point2D(1, 1) assert len(mesh.face_areas) == 1 assert mesh.face_areas[0] == 4 assert len(mesh.face_centroids) == 1 assert mesh.face_centroids[0] == Point2D(1, 1) assert mesh._is_color_by_face is False assert mesh.colors is None assert len(mesh.vertex_connected_faces) == 4 for vf in mesh.vertex_connected_faces: assert len(vf) == 1
def test_mesh2d_init_two_faces(): """Test the initalization of Mesh2D objects with two faces.""" pts = (Point2D(0, 0), Point2D(0, 2), Point2D(2, 2), Point2D(2, 0), Point2D(4, 0)) mesh = Mesh2D(pts, [(0, 1, 2, 3), (2, 3, 4)]) assert len(mesh.vertices) == 5 assert len(mesh.faces) == 2 assert mesh[0] == Point2D(0, 0) assert mesh[1] == Point2D(0, 2) assert mesh[2] == Point2D(2, 2) assert mesh[3] == Point2D(2, 0) assert mesh[4] == Point2D(4, 0) assert mesh.area == 6 assert mesh.min == Point2D(0, 0) assert mesh.max == Point2D(4, 2) assert mesh.center == Point2D(2, 1) assert mesh.centroid.x == pytest.approx(1.56, rel=1e-2) assert mesh.centroid.y == pytest.approx(0.89, rel=1e-2) assert len(mesh.face_areas) == 2 assert mesh.face_areas[0] == 4 assert mesh.face_areas[1] == 2 assert len(mesh.face_centroids) == 2 assert mesh.face_centroids[0] == Point2D(1, 1) assert mesh.face_centroids[1].x == pytest.approx(2.67, rel=1e-2) assert mesh.face_centroids[1].y == pytest.approx(0.67, rel=1e-2) assert mesh._is_color_by_face is False assert mesh.colors is None
def _compute_colored_mesh2d(self): """Compute a colored mesh from this object's data collection.""" # generate the base mesh as a stanadard grid _colored_mesh2d = Mesh2D.from_grid(self.base_point, self._num_x, self._num_y, self.x_dim, self.y_dim) # remove any faces in the base mesh that do not represent the data if not isinstance(self.data_collection, HourlyContinuousCollection): # get a pattern of booleans for whether mesh faces should be included data_coll_moys = [dt.moy for dt in self.data_collection.datetimes] data_coll_moys.append( 527100) # extra value for the end of the list found_i = 0 mesh_pattern = [] for moy in self.analysis_period.moys: if moy == data_coll_moys[found_i]: mesh_pattern.append(True) found_i += 1 else: mesh_pattern.append(False) _colored_mesh2d = _colored_mesh2d.remove_faces_only(mesh_pattern) # assign the colors to the mesh _colored_mesh2d.colors = self.colors return _colored_mesh2d
def test_init_graphic_con(): """Test the initialization of GraphicContainer objects.""" mesh2d = Mesh2D.from_grid(num_x=2, num_y=2) mesh3d = Mesh3D.from_mesh2d(mesh2d) data = [0, 1, 2, 3] graphic_con = GraphicContainer(data, mesh3d.min, mesh3d.max) str(graphic_con) # Test the GraphicContainer representation assert len(graphic_con) == 4 assert graphic_con[0] == 0 assert graphic_con[-1] == 3 for item in graphic_con: assert isinstance(item, (float, int)) assert len(graphic_con.values) == 4 assert isinstance(graphic_con.legend, Legend) assert graphic_con.value_colors == graphic_con.legend.value_colors assert graphic_con.legend_parameters.is_base_plane_default is False assert graphic_con.legend_parameters.is_segment_height_default is False assert graphic_con.legend_parameters.is_segment_width_default is True assert graphic_con.legend_parameters.is_text_height_default is True assert graphic_con.legend_parameters.base_plane != Plane() assert isinstance(graphic_con.lower_title_location, Plane) assert isinstance(graphic_con.upper_title_location, Plane) assert graphic_con.lower_title_location != Plane() assert graphic_con.upper_title_location != Plane()
def _compute_monthly_bars(self): """Compute a list of bar colored meshes from this object's input data.""" # get values used across all bars meshes = [] colors = self.colors bar_count = 0 bar_width = self._x_dim / (self._horizontal_bar_count() + 1) spacer_width = bar_width / 2 # loop through each data set and build the bar meshes for j, (t, data_arr) in enumerate( zip(self._data_types, self._grouped_data)): d_range = self._maximums[j] - self._minimums[j] d_range = 1 if d_range == 0 else d_range # catch case of all same values min_val = self._minimums[j] zero_val = self._y_dim * (min_val / d_range) base_y = self._base_point.y - zero_val if self._is_cumulative(t) \ else self._base_point.y bar_y_low = [base_y] * len( data_arr[0]) # track the bar cumulative heights bar_y_up = [base_y] * len( data_arr[0]) # track the bar cumulative heights for i, data in enumerate(data_arr): verts = [] faces = [] vert_count = 0 for m_i, val in enumerate(data): # iterate through values # compute critical dimensions of each bar start_x = self._base_point.x + m_i * self._x_dim + \ spacer_width + bar_count * bar_width if self._is_cumulative(t): bar_hgt = (self._y_dim * ((val - min_val) / d_range)) + zero_val if bar_hgt >= 0: start_y = bar_y_up[m_i] if self._stack: # shift the baseline up for next bar bar_y_up[m_i] += bar_hgt else: start_y = bar_y_low[m_i] if self._stack: # shift the baseline down for next bar bar_y_low[m_i] += bar_hgt else: # always plot the value from the bottom bar_hgt = self._y_dim * ((val - min_val) / d_range) start_y = base_y end_y = start_y + bar_hgt # create the bar mesh face verts.extend( self._bar_pts(start_x, start_y, bar_width, end_y)) faces.append(tuple(x + vert_count for x in (0, 1, 2, 3))) vert_count += 4 # create the final colored mesh mesh_col = [colors[self._color_map[j][i]]] * len(faces) meshes.append(Mesh2D(verts, faces, mesh_col)) if not self._stack or not self._is_cumulative( t): # shift bar in x dir bar_count += 1 if self._stack and self._is_cumulative(t): bar_count += 1 return meshes
def test_from_mesh3d(): mesh_2d = Mesh2D.from_grid(Point2D(1, 1), 8, 2, 0.25, 1) mesh = Mesh3D.from_mesh2d(mesh_2d) sg = SensorGrid.from_mesh3d('sg_1', mesh) assert len(sg.sensors) == 16 assert len(sg.mesh.vertices) == 27 assert len(sg.mesh.faces) == 16 assert mesh.area == 4
def colored_mesh(self): """Get the colored Mesh2D for this graphic. Returns: A Mesh2D of the wind rose plot. """ assert self._number_of_directions > 2, 'The number of directions must be ' \ 'greater then three to plot the wind rose. Currently the ' \ 'number_of_directions parameter is: {}'.format(self._number_of_directions) # Reset computed graphics to account for changes to cached viz properties self._compass = None self._container = None max_bar_radius = self.mesh_radius min_bar_radius = self._zero_mesh_radius zero_mesh_array, zero_color_array = [], [] if self.show_zeros: # Compute the array for calm rose zero_data = [[0] for _ in self.histogram_data] zero_data_stacked = [[0] for _ in self.histogram_data] zero_mesh_array, zero_color_array = WindRose._compute_colored_mesh_array( zero_data, zero_data_stacked, self.bin_vectors, 0, min_bar_radius, show_freq=False) # Calculate regular mesh if self.show_freq: histogram_data_stacked = WindRose._histogram_data_nested( self.histogram_data, self.frequency_hours) else: histogram_data_stacked = [[sum(h) / len(h)] if len(h) > 0 else [0] for h in self.histogram_data] # Don't round radius since there are no frequency intervals. max_bar_radius = self.real_freq_max / self.frequency_hours max_bar_radius *= self.frequency_spacing_distance max_bar_radius += self._zero_mesh_radius mesh_array, color_array = WindRose._compute_colored_mesh_array( self.histogram_data, histogram_data_stacked, self.bin_vectors, min_bar_radius, max_bar_radius, self.show_freq) mesh_array += zero_mesh_array color_array += zero_color_array mesh = Mesh2D.from_face_vertices(mesh_array, purge=True) # Assign colors _color_range = self.color_range mesh.colors = tuple(_color_range.color(val) for val in color_array) # Scale up unit circle to windrose radius (and other transforms) return self._transform(mesh)
def test_init_graphic_con_invalid(self): """Test the initialization of GraphicContainer objects with invalid inputs.""" mesh2d = Mesh2D.from_grid(num_x=2, num_y=2) mesh3d = Mesh3D.from_mesh2d(mesh2d) data = [0, 1, 2, 3, 4] with pytest.raises(Exception): GraphicContainer(data, mesh3d.min, mesh3d.max, data_type=Temperature(), unit='NotAUnit')
def test_to_from_dict(): """Test the to/from dict methods.""" mesh2d = Mesh2D.from_grid(num_x=2, num_y=2) mesh3d = Mesh3D.from_mesh2d(mesh2d) data = [0, 1, 2, 3] graphic_con = GraphicContainer(data, mesh3d.min, mesh3d.max) graphic_con_dict = graphic_con.to_dict() new_graphic_con = GraphicContainer.from_dict(graphic_con_dict) assert new_graphic_con.to_dict() == graphic_con_dict
def colored_mesh(self): """Get a colored Mesh2D for this graphic. """ max_bar_radius = 1.0 min_bar_radius = 0.0 zero_mesh_array, zero_color_array = [], [] # Calculate ytick nums for the wind mesh ytick_num = self.legend.legend_parameters.segment_count # total max_bar_num = self.real_freq_max ytick_num_mesh = ytick_num # default if self.show_zeros: # Calculate radius of zero rose max_bar_num += self.zeros_per_bin min_bar_radius = self.zeros_per_bin / max_bar_num * max_bar_radius ytick_num_mesh = max_bar_num / self.frequency_maximum * ytick_num # Update yticks zero_ytick_num_mesh = self._ytick_zero_inc() ytick_num_mesh -= zero_ytick_num_mesh # Compute the array for calm rose zero_data = [[0] for _ in self.histogram_data] zero_data_stacked = [[0] for _ in self.histogram_data] zero_mesh_array, zero_color_array = WindRose._compute_colored_mesh_array( zero_data, zero_data_stacked, self.bin_vectors, zero_ytick_num_mesh, 0, min_bar_radius, show_stack=False) # Calculate regular mesh if self.show_stack: histogram_data_stacked = WindRose._histogram_data_stacked( self.histogram_data, ytick_num) else: histogram_data_stacked = [[sum(h) / len(h)] if len(h) > 0 else [0] for h in self.histogram_data] mesh_array, color_array = WindRose._compute_colored_mesh_array( self.histogram_data, histogram_data_stacked, self.bin_vectors, ytick_num_mesh, min_bar_radius, max_bar_radius, self.show_stack) mesh_array += zero_mesh_array color_array += zero_color_array mesh = Mesh2D.from_face_vertices(mesh_array, purge=True) mesh.colors = color_array return mesh.scale(self.wind_radius).move(self.base_point)
def test_mesh2d_init_from_polygon_triangulated_concave(): """Test Mesh2D from_polygon_triangulated with a concave polygon.""" verts = (Point2D(0, 0), Point2D(2, 0), Point2D(2, 1), Point2D(1, 1), Point2D(1, 2), Point2D(0, 2)) polygon = Polygon2D(verts) mesh_1 = Mesh2D.from_polygon_triangulated(polygon) mesh_2 = Mesh2D.from_polygon_triangulated(polygon, False) assert len(mesh_1.vertices) == 6 assert len(mesh_2.vertices) == 12 assert len(mesh_1.faces) == len(mesh_2.faces) == 4 assert mesh_1.area == mesh_2.area == 3 assert mesh_1.min == mesh_2.min == Point2D(0, 0) assert mesh_1.max == mesh_2.max == Point2D(2, 2) assert mesh_1.center == mesh_2.center == Point2D(1, 1) assert mesh_1.centroid.x == mesh_2.centroid.x == pytest.approx(0.8333, rel=1e-2) assert mesh_1.centroid.y == mesh_2.centroid.y == pytest.approx(0.8333, rel=1e-2) assert len(mesh_1.face_areas) == len(mesh_2.face_areas) == 4 assert len(mesh_1.face_centroids) == len(mesh_2.face_centroids) == 4
def test_scale_world_origin(): """Test the Mesh2D scale method with None origin.""" pts = (Point2D(0, 0), Point2D(0, 2), Point2D(2, 2), Point2D(2, 0), Point2D(4, 0)) mesh = Mesh2D(pts, [(0, 1, 2, 3), (2, 3, 4)]) new_mesh_1 = mesh.scale(2) assert new_mesh_1[0] == Point2D(0, 0) assert new_mesh_1[1] == Point2D(0, 4) assert new_mesh_1[2] == Point2D(4, 4) assert new_mesh_1[3] == Point2D(4, 0) assert new_mesh_1[4] == Point2D(8, 0) assert new_mesh_1.area == 24 assert len(mesh.vertices) == len(new_mesh_1.vertices) assert len(mesh.faces) == len(new_mesh_1.faces)
def test_mesh2d_init_from_polygon_triangulated_colinear(): """Test Mesh2D from_polygon_triangulated with some colinear vertices.""" verts = (Point2D(0, 0), Point2D(0, 2), Point2D(2, 2), Point2D(4, 0), Point2D(2, 0)) polygon = Polygon2D(verts) mesh = Mesh2D.from_polygon_triangulated(polygon) assert len(mesh.vertices) == 5 assert len(mesh.faces) == 3 assert mesh.area == 6 assert mesh.min == Point2D(0, 0) assert mesh.max == Point2D(4, 2) assert mesh.center == Point2D(2, 1) assert mesh.centroid.x == pytest.approx(1.56, rel=1e-2) assert mesh.centroid.y == pytest.approx(0.89, rel=1e-2)
def test_triangualted(): """Test the Mesh2D triangualted method.""" pts = (Point2D(0, 0), Point2D(0, 2), Point2D(2, 2), Point2D(2, 0), Point2D(4, 0)) mesh = Mesh2D(pts, [(0, 1, 2, 3), (2, 3, 4)], ['red', 'green']) assert len(mesh.vertices) == 5 assert len(mesh.faces) == 2 assert len(mesh.colors) == 2 assert mesh.area == 6 tri_mesh = mesh.triangulated() assert len(tri_mesh.vertices) == 5 assert len(tri_mesh.faces) == 3 assert len(tri_mesh.colors) == 3 assert tri_mesh.area == 6
def test_scale(): """Test the Mesh2D scale method.""" pts = (Point2D(0, 0), Point2D(0, 2), Point2D(2, 2), Point2D(2, 0), Point2D(4, 0)) mesh = Mesh2D(pts, [(0, 1, 2, 3), (2, 3, 4)]) origin_1 = Point2D(2, 0) new_mesh_1 = mesh.scale(2, origin_1) assert new_mesh_1[0] == Point2D(-2, 0) assert new_mesh_1[1] == Point2D(-2, 4) assert new_mesh_1[2] == Point2D(2, 4) assert new_mesh_1[3] == Point2D(2, 0) assert new_mesh_1[4] == Point2D(6, 0) assert new_mesh_1.area == 24 assert len(mesh.vertices) == len(new_mesh_1.vertices) assert len(mesh.faces) == len(new_mesh_1.faces)
def test_init_graphic_con_vertex_based(): """Test the initialization of ResultMesh objects with vertex-based input.""" mesh2d = Mesh2D.from_grid(num_x=2, num_y=2) mesh3d = Mesh3D.from_mesh2d(mesh2d) data = [0, 1, 2, 3, 4, 5, 6, 7, 8] graphic_con = GraphicContainer(data, mesh3d.min, mesh3d.max) assert len(graphic_con) == 9 assert graphic_con[0] == 0 assert graphic_con[-1] == 8 assert len(graphic_con.values) == 9 assert isinstance(graphic_con.legend_parameters, LegendParameters) assert isinstance(graphic_con.legend, Legend) assert graphic_con.value_colors == graphic_con.legend.value_colors