def setSurface(self): # Crea i valori immagine per la superficie, calcolando su ogni punto della plotTriangulation il valore della superficie di Bezier triangolare sul triangolo PS al quale il punto appartiene. # Raffinamento uniforme della triangolazione Powell_Sabin ai fini del plottaggio. refiner = UniformTriRefiner(self.domain.PowellSabinTr) self.plotTriangulation, self.TrIndex = refiner.refine_triangulation( return_tri_index=True, subdiv=4) # Salvo i punti della triangolazione iniziale in un solo array. self.plotPoints = np.array( list(zip(self.plotTriangulation.x, self.plotTriangulation.y))) # Inizializzo l'array delle ordinate. plotHeights = [] for point_index in range(len(self.plotPoints)): point = self.plotPoints[point_index] # Ricerco il triangolo PS al quale appartiene il punto. m = self.TrIndex[point_index] triangle = self.domain.PS_triangles[m] tr_vertexes = np.array( [self.domain.PS_points[i] for i in triangle]) # Ricavo le coordinate baricentriche bc del punto rispetto al triangolo PS. bc = self.getBarycentricCoords(tr_vertexes, point) # Calcolo l'ordinata associata al punto. plotHeights.append(self.triDeCasteljau(m, (0, 0, 0), bc, 3)) # Salvo array delle ordinate. self.plotHeights = np.array(plotHeights)
def plot_simplex(self, num_contours: int = 100, num_sub_div: int = 8, color_map: str = 'viridis', border: bool = True, ax: Optional[Axes] = None, **kwargs) -> Axes: """ Plot a 3-dimensional functions as a simplex heat-map. :param num_contours: The number of levels of contours to plot. :param num_sub_div: Number of recursive subdivisions to create. :param color_map: Optional colormap for the plot. :param border: Whether to plot a border around the simplex heat-map. :param ax: Optional matplotlib axes to plot on. :param kwargs: Additional arguments for tricontourf method. """ corners = array([[0, 0], [1, 0], [0.5, 0.75 ** 0.5]]) triangle = Triangulation(corners[:, 0], corners[:, 1]) mid_points = [ (corners[(i + 1) % 3] + corners[(i + 2) % 3]) / 2 for i in range(3) ] def to_barycentric(cartesian): """ Converts 2D Cartesian to barycentric coordinates. :param cartesian: A length-2 sequence containing the x and y value. """ s = [(corners[i] - mid_points[i]).dot( cartesian - mid_points[i] ) / 0.75 for i in range(3)] s_clipped = clip(a=s, a_min=0, a_max=1) return s_clipped / norm(s_clipped, ord=1) refiner = UniformTriRefiner(triangle) tri_mesh = refiner.refine_triangulation(subdiv=num_sub_div) f = [self._method(to_barycentric(xy)) for xy in zip(tri_mesh.x, tri_mesh.y)] ax = ax or new_axes() ax.tricontourf(tri_mesh, f, num_contours, cmap=color_map, **kwargs) ax.set_aspect('equal') ax.set_xlim(0, 1) ax.set_ylim(0, 0.75 ** 0.5) ax.set_axis_off() if border: ax.triplot(triangle, linewidth=1) return ax
def _two_dimension_triangle_func_val(function, num_sample_points): """Calculate the triangulation and function values for a given 2D function :arg function: 2D function :arg num_sample_points: Number of sampling points. This is not obeyed exactly, but a linear triangulation is created which matches it reasonably well. """ from math import log try: from matplotlib.tri import Triangulation, UniformTriRefiner except ImportError: raise RuntimeError("Matplotlib not importable, is it installed?") if function.function_space().mesh().ufl_cell() == Cell('triangle'): x = np.array([0, 0, 1]) y = np.array([0, 1, 0]) elif function.function_space().mesh().ufl_cell() == Cell('quadrilateral'): x = np.array([0, 0, 1, 1]) y = np.array([0, 1, 0, 1]) else: raise RuntimeError("Unsupported Functionality") base_tri = Triangulation(x, y) refiner = UniformTriRefiner(base_tri) sub_triangles = int(log(num_sample_points, 4)) tri = refiner.refine_triangulation(False, sub_triangles) triangles = tri.get_masked_triangles() x_ref = tri.x y_ref = tri.y num_verts = triangles.max() + 1 num_cells = function.function_space().cell_node_list.shape[0] ref_points = np.dstack([x_ref, y_ref]).reshape(-1, 2) z_vals = _calculate_values(function, ref_points, 2) coords_vals = _calculate_values(function.function_space(). mesh().coordinates, ref_points, 2) Z = z_vals.reshape(-1) X = coords_vals.reshape(-1, 2).T[0] Y = coords_vals.reshape(-1, 2).T[1] add_idx = np.arange(num_cells).reshape(-1, 1, 1) * num_verts all_triangles = (triangles + add_idx).reshape(-1, 3) triangulation = Triangulation(X, Y, triangles=all_triangles) return triangulation, Z
def _two_dimension_triangle_func_val(function, num_sample_points): """Calculate the triangulation and function values for a given 2D function :arg function: 2D function :arg num_sample_points: Number of sampling points. This is not obeyed exactly, but a linear triangulation is created which matches it reasonably well. """ from math import log try: from matplotlib.tri import Triangulation, UniformTriRefiner except ImportError: raise RuntimeError("Matplotlib not importable, is it installed?") if function.function_space().mesh().ufl_cell() == Cell('triangle'): x = np.array([0, 0, 1]) y = np.array([0, 1, 0]) elif function.function_space().mesh().ufl_cell() == Cell('quadrilateral'): x = np.array([0, 0, 1, 1]) y = np.array([0, 1, 0, 1]) else: raise RuntimeError("Unsupported Functionality") base_tri = Triangulation(x, y) refiner = UniformTriRefiner(base_tri) sub_triangles = int(log(num_sample_points, 4)) tri = refiner.refine_triangulation(False, sub_triangles) triangles = tri.get_masked_triangles() x_ref = tri.x y_ref = tri.y num_verts = triangles.max() + 1 num_cells = function.function_space().cell_node_list.shape[0] ref_points = np.dstack([x_ref, y_ref]).reshape(-1, 2) z_vals = _calculate_values(function, ref_points, 2) coords_vals = _calculate_values(function.function_space(). mesh().coordinates, ref_points, 2) Z = z_vals.reshape(-1) X = coords_vals.reshape(-1, 2).T[0] Y = coords_vals.reshape(-1, 2).T[1] add_idx = np.arange(num_cells).reshape(-1, 1, 1) * num_verts all_triangles = (triangles + add_idx).reshape(-1, 3) triangulation = Triangulation(X, Y, triangles=all_triangles) return triangulation, Z