Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
def triangle_contour(x_center, y_center, values, smoothing, ckwargs={}):
    """A helper funciton used to draw contorus with pl.tricontour"""
    # make Triangulation object using the centers of each of the hexbins
    triag = Triangulation(x_center, y_center)
    refiner = UniformTriRefiner(triag) # refines the mesh of triangle
    # returns refines triangle field of triangles and interpolated
    # contour values by dividing each triangle into 4**subdiv triangles
    tri_refi, c_refi = refiner.refine_field(values, subdiv=smoothing)
    T = pl.tricontour(tri_refi, c_refi, **ckwargs)
    return T
Exemplo n.º 3
0
    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
Exemplo n.º 4
0
    def plot_magnetic_field_contour(self, ax=None):
        if ax is None:
            fig, ax = plt.subplots()
        else:
            fig = plt.gcf()
        ax.set_aspect('equal')
        
        
        from matplotlib.tri import Triangulation, TriAnalyzer, UniformTriRefiner
        import matplotlib.cm as cm
            
        element_to_magnetic_field = self.magnetic_field_per_element()
        
        x = []
        y = []
        Z = []
        for group in self.mesh.elements_groups:
            for element in group.elements:
                x_center, y_center = element.center
                x.append(x_center)
                y.append(y_center)
                Z.append(element_to_magnetic_field[element].Norm())
        
        tri = Triangulation(x, y)
        
        
        #-----------------------------------------------------------------------------
        # Improving the triangulation before high-res plots: removing flat triangles
        #-----------------------------------------------------------------------------
        # masking badly shaped triangles at the border of the triangular mesh.
        min_circle_ratio = -1 
        mask = TriAnalyzer(tri).get_flat_tri_mask(min_circle_ratio)
        tri.set_mask(mask)
        
        # refining the data
        refiner = UniformTriRefiner(tri)
        subdiv = 3
        tri_refi, z_test_refi = refiner.refine_field(Z, subdiv=subdiv)
        
        levels = npy.arange(0., 1., 0.05)
        cmap = cm.get_cmap(name='Blues', lut=None)
        ax.tricontour(tri_refi, z_test_refi, levels=levels, #cmap=cmap,
                      linewidths=[2.0, 0.5, 1.0, 0.5])
#        ax.triplot(tri_refi, color='0.97')
#        ax.triplot(tri, color='0.7')
#        ax.tricontour(x, y, Z)
        return ax 
Exemplo n.º 5
0
def plot_samples(num):
    samples_hundred = BM_sampling_method(num)
    tri = Triangulation(samples_hundred[0], samples_hundred[1])
    random_gen = np.random.mtrand.RandomState(seed=127260)
    init_mask_frac = 0.0
    min_circle_ratio = .01
    subdiv = 3

    ntri = tri.triangles.shape[0]

    print 'hi'
    mask_init = np.zeros(ntri, dtype=np.bool)
    masked_tri = random_gen.randint(0, ntri, int(ntri * init_mask_frac))
    mask_init[masked_tri] = True
    tri.set_mask(mask_init)
    print 'hey'

    z_exp = experiment_res(tri.x, tri.y)
    print z_exp

    mask = TriAnalyzer(tri).get_flat_tri_mask(min_circle_ratio)
    tri.set_mask(mask)

    # refining the data
    refiner = UniformTriRefiner(tri)
    tri_refi, z_test_refi = refiner.refine_field(z_exp, subdiv=subdiv)

    # analytical 'results' for comparison
    z_expected = experiment_res(tri_refi.x, tri_refi.y)

    plt.tricontour(tri_refi,
                   z_expected,
                   levels=levels,
                   cmap=cmap,
                   linestyles='--')

    plt.show()
    x, y = np.mgrid[-1:1:0.001, -1:1:0.001]
    pos = np.empty(x.shape + (2, ))
    pos[:, :, 0] = x
    pos[:, :, 1] = y
    rv = multivariate_normal([0, 0], [[1.0, 0.0], [0.0, 1.0]])
    plt.contour(x, y, rv.pdf(pos))
Exemplo n.º 6
0
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
Exemplo n.º 7
0
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
Exemplo n.º 8
0
    def refine(self, z, subdiv=3, triinterpolator=None):
        r"""
        对三角形网格重新采样.

        Parameters
        ----------
        z : array_like, (N, )
        subdiv : int, optional
            采样深度, 将三角形单元分为 4**subdiv.
        triinterpolator : TriInterpolator, optional
            插值方法, 默认使用 CubicTriInterpolator.

        Returns
        -------

        """
        refiner = UniformTriRefiner(self.mtri)
        mtri_ref, z_ref = refiner.refine_field(z,
                                               subdiv=subdiv,
                                               triinterpolator=triinterpolator)
        return mtri_ref, z_ref
Exemplo n.º 9
0
# Some invalid data are masked out
mask_init = np.zeros(ntri, dtype=bool)
masked_tri = random_gen.randint(0, ntri, int(ntri * init_mask_frac))
mask_init[masked_tri] = True
tri.set_mask(mask_init)


#-----------------------------------------------------------------------------
# Improving the triangulation before high-res plots: removing flat triangles
#-----------------------------------------------------------------------------
# masking badly shaped triangles at the border of the triangular mesh.
mask = TriAnalyzer(tri).get_flat_tri_mask(min_circle_ratio)
tri.set_mask(mask)

# refining the data
refiner = UniformTriRefiner(tri)
tri_refi, z_test_refi = refiner.refine_field(z_test, subdiv=subdiv)

# analytical 'results' for comparison
z_expected = experiment_res(tri_refi.x, tri_refi.y)

# for the demo: loading the 'flat' triangles for plot
flat_tri = Triangulation(x_test, y_test)
flat_tri.set_mask(~mask)


#-----------------------------------------------------------------------------
# Now the plots
#-----------------------------------------------------------------------------
# User options for plots
plot_tri = True          # plot of base triangulation
# Some invalid data are masked out
mask_init = np.zeros(ntri, dtype=np.bool)
masked_tri = random_gen.randint(0, ntri, int(ntri*init_mask_frac))
mask_init[masked_tri] = True
tri.set_mask(mask_init)


#-----------------------------------------------------------------------------
# Improving the triangulation before high-res plots: removing flat triangles
#-----------------------------------------------------------------------------
# masking badly shaped triangles at the border of the triangular mesh.
mask = TriAnalyzer(tri).get_flat_tri_mask(min_circle_ratio)
tri.set_mask(mask)

# refining the data
refiner = UniformTriRefiner(tri)
tri_refi, z_test_refi = refiner.refine_field(z_test, subdiv=subdiv)

# analytical 'results' for comparison
z_expected = experiment_res(tri_refi.x, tri_refi.y)

# for the demo: loading the 'flat' triangles for plot
flat_tri = Triangulation(x_test, y_test)
flat_tri.set_mask(~mask)


#-----------------------------------------------------------------------------
# Now the plots
#-----------------------------------------------------------------------------
# User options for plots
plot_tri = True          # plot of the base triangulation
Exemplo n.º 11
0
y = (radii*np.sin(angles)).flatten()
V = dipole_potential(x, y)

# Create the Triangulation; no triangles specified so Delaunay triangulation
# created.
triang = Triangulation(x, y)

# Mask off unwanted triangles.
triang.set_mask(np.hypot(x[triang.triangles].mean(axis=1),
                         y[triang.triangles].mean(axis=1))
                < min_radius)

#-----------------------------------------------------------------------------
# Refine data - interpolates the electrical potential V
#-----------------------------------------------------------------------------
refiner = UniformTriRefiner(triang)
tri_refi, z_test_refi = refiner.refine_field(V, subdiv=3)

#-----------------------------------------------------------------------------
# Computes the electrical field (Ex, Ey) as gradient of electrical potential
#-----------------------------------------------------------------------------
tci = CubicTriInterpolator(triang, -V)
# Gradient requested here at the mesh nodes but could be anywhere else:
(Ex, Ey) = tci.gradient(triang.x, triang.y)
E_norm = np.sqrt(Ex**2 + Ey**2)

#-----------------------------------------------------------------------------
# Plot the triangulation, the potential iso-contours and the vector field
#-----------------------------------------------------------------------------
fig, ax = plt.subplots()
ax.set_aspect('equal')
Exemplo n.º 12
0
y = (radii * np.sin(angles)).flatten()
V = dipole_potential(x, y)

# Create the Triangulation; no triangles specified so Delaunay triangulation
# created.
triang = Triangulation(x, y)

# Mask off unwanted triangles.
triang.set_mask(
    np.hypot(x[triang.triangles].mean(axis=1), y[triang.triangles].mean(
        axis=1)) < min_radius)

#-----------------------------------------------------------------------------
# Refine data - interpolates the electrical potential V
#-----------------------------------------------------------------------------
refiner = UniformTriRefiner(triang)
tri_refi, z_test_refi = refiner.refine_field(V, subdiv=3)

#-----------------------------------------------------------------------------
# Computes the electrical field (Ex, Ey) as gradient of electrical potential
#-----------------------------------------------------------------------------
tci = CubicTriInterpolator(triang, -V)
# Gradient requested here at the mesh nodes but could be anywhere else:
(Ex, Ey) = tci.gradient(triang.x, triang.y)
E_norm = np.sqrt(Ex**2 + Ey**2)

#-----------------------------------------------------------------------------
# Plot the triangulation, the potential iso-contours and the vector field
#-----------------------------------------------------------------------------
fig, ax = plt.subplots()
ax.set_aspect('equal')
Exemplo n.º 13
0
        -f_axis.mean())/1e3
tri_z = rx_axis.ravel()
# {{{ this part is actually very important, and prevents the data from
# interpolating to 0 at the edges!
# --> in the future, note that nan is a good placeholder for "lack of data"
mask = tri_y == 0 # t=0 are not valid datapoints
tri_y = tri_y[~mask]
tri_x = tri_x[~mask]
tri_z = tri_z[~mask]
# }}}
tri = Triangulation(tri_x,
        tri_y)
# {{{ refining the data -- see https://matplotlib.org/3.1.0/gallery/images_contours_and_fields/tricontour_smooth_delaunay.html#sphx-glr-gallery-images-contours-and-fields-tricontour-smooth-delaunay-py
#     I don't see a difference in the refined (tri_refi) vs. unrefined (tri),
#     but I'm quite possibly missing something, or it's more helpful in other cases
refiner = UniformTriRefiner(tri)
subdiv = 3  # Number of recursive subdivisions of the initial mesh for smooth
            # plots. Values >3 might result in a very high number of triangles
            # for the refine mesh: new triangles numbering = (4**subdiv)*ntri
tri_refi, tri_z_refi = refiner.refine_field(tri_z, subdiv=subdiv)
mask = TriAnalyzer(tri_refi).get_flat_tri_mask(10)
tri_refi = tri_refi.set_mask(~mask)
# }}}
figure(figsize=(5,15),
        facecolor=(1,1,1,0))
if not presentation:
    plot(tri_x,tri_y,'o',
            color='k',alpha=0.3)
    triplot(tri,
            color='k',alpha=0.3)
tricontourf(tri,tri_z,
Exemplo n.º 14
0
 def trirefine(tri, q, subdiv=3):
     ref = UniformTriRefiner(tri)
     return ref.refine_field(q, subdiv=subdiv)
Exemplo n.º 15
0
    def __init__(self, **kwargs):
        super(ContourMap, self).__init__(**kwargs)

        n_test = 200  # Number of test data points, tested from 3 to 5000 for subdiv=3

        subdiv = 3  # Number of recursive subdivisions of the initial mesh for smooth
        # plots. Values >3 might result in a very high number of triangles
        # for the refine mesh: new triangles numbering = (4**subdiv)*ntri

        init_mask_frac = 0.0  # Float > 0. adjusting the proportion of
        # (invalid) initial triangles which will be masked
        # out. Enter 0 for no mask.

        min_circle_ratio = .01  # Minimum circle ratio - border triangles with circle
        # ratio below this will be masked if they touch a
        # border. Suggested value 0.01 ; Use -1 to keep
        # all triangles.

        # Random points
        random_gen = np.random.mtrand.RandomState(seed=127260)
        x_test = random_gen.uniform(-1., 1., size=n_test)
        y_test = random_gen.uniform(-1., 1., size=n_test)
        z_test = experiment_res(x_test, y_test)

        # meshing with Delaunay triangulation
        tri = Triangulation(x_test, y_test)
        ntri = tri.triangles.shape[0]

        # Some invalid data are masked out
        mask_init = np.zeros(ntri, dtype=np.bool)
        masked_tri = random_gen.randint(0, ntri, int(ntri * init_mask_frac))
        mask_init[masked_tri] = True
        tri.set_mask(mask_init)

        #-----------------------------------------------------------------------------
        # Improving the triangulation before high-res plots: removing flat triangles
        #-----------------------------------------------------------------------------
        # masking badly shaped triangles at the border of the triangular mesh.
        mask = TriAnalyzer(tri).get_flat_tri_mask(min_circle_ratio)
        tri.set_mask(mask)

        # refining the data
        refiner = UniformTriRefiner(tri)
        tri_refi, z_test_refi = refiner.refine_field(z_test, subdiv=subdiv)

        # analytical 'results' for comparison
        z_expected = experiment_res(tri_refi.x, tri_refi.y)

        # for the demo: loading the 'flat' triangles for plot
        flat_tri = Triangulation(x_test, y_test)
        flat_tri.set_mask(~mask)

        #-----------------------------------------------------------------------------
        # Now the plots
        #-----------------------------------------------------------------------------
        # User options for plots
        plot_tri = True  # plot of base triangulation
        plot_masked_tri = True  # plot of excessively flat excluded triangles
        plot_refi_tri = False  # plot of refined triangulation
        plot_expected = False  # plot of analytical function values for comparison

        # Graphical options for tricontouring
        levels = np.arange(0., 1., 0.025)
        cmap = cm.get_cmap(name='Blues', lut=None)

        plt.figure()
        plt.gca().set_aspect('equal')
        plt.title("Filtering a Delaunay mesh\n" +
                  "(application to high-resolution tricontouring)")

        # 1) plot of the refined (computed) data countours:
        plt.tricontour(tri_refi,
                       z_test_refi,
                       levels=levels,
                       cmap=cmap,
                       linewidths=[2.0, 0.5, 1.0, 0.5])
        # 2) plot of the expected (analytical) data countours (dashed):
        if plot_expected:
            plt.tricontour(tri_refi,
                           z_expected,
                           levels=levels,
                           cmap=cmap,
                           linestyles='--')
        # 3) plot of the fine mesh on which interpolation was done:
        if plot_refi_tri:
            plt.triplot(tri_refi, color='0.97')
        # 4) plot of the initial 'coarse' mesh:
        if plot_tri:
            plt.triplot(tri, color='0.7')
        # 4) plot of the unvalidated triangles from naive Delaunay Triangulation:
        if plot_masked_tri:
            plt.triplot(flat_tri, color='red')

        plt.show()
Exemplo n.º 16
0
def density(model, refinement=0):
    """
    Create a Voronoi mesh and calculate the local particle density on its vertices.

    The local density is calculated as follows:
    for each vertex, compute the density of each neighbour region as
    one over the area and assign the average of
    the neighbouring density to the vertex.

    Parameters
    ----------
    model : simulation.builder.Model
        the Model object containing
    refinement : int (defaults : 0)
        number of subdivision for refining the mesh (0 == None)
    Returns
    -------
    tri : matplotlib.tri.Triangulation
        the triangulation mesh (refined if set as)
    vert_density : numpy.array
        the array containing the local denstity associated with the tri mesh


    Example
    -------
    To plot the result using matplotlib use :

    .. code-block:: python

        import matplotlib.pyplot as plt
        tri, density = data_proc.density(model)
        plt.tricontour(tri, density) # to draw contours
        plt.tricontourf(tri, density) # ot draw filled contours
        plt.show()

    Note
    ----
    As of now, the numerical results may not be quantitatively accurate
    but should qualitatively represent the density.
    """
    vor = Voronoi(model.pos)
    vert_density = np.zeros(max(vor.vertices.shape))  # density vector
    reg_num = np.zeros(max(
        vor.vertices.shape))  # nbr of regions per vertex --> averaging
    for point_index, reg in enumerate(vor.point_region):
        vertices = vor.regions[reg]
        if vertices:
            if -1 not in vertices:
                area = ConvexHull(vor.vertices[vertices]).area  # gets the area
                vert_density[
                    vertices] += 1 / area  # makes it a density (sort-of)
                reg_num[vertices] += 1
    vert_density /= reg_num  # averaging

    # getting rid of really ugly border points
    new_vert, vert_density = (
        vor.vertices[vor.vertices[:, 0] >= np.min(model.pos[:, 0])],
        vert_density[vor.vertices[:, 0] >= np.min(model.pos[:, 0])])

    new_vert, vert_density = (
        new_vert[new_vert[:, 0] <= np.max(model.pos[:, 0])],
        vert_density[new_vert[:, 0] <= np.max(model.pos[:, 0])])

    new_vert, vert_density = (
        new_vert[new_vert[:, 1] >= np.min(model.pos[:, 1])],
        vert_density[new_vert[:, 1] >= np.min(model.pos[:, 1])])

    new_vert, vert_density = (
        new_vert[new_vert[:, 1] <= np.max(model.pos[:, 1])],
        vert_density[new_vert[:, 1] <= np.max(model.pos[:, 1])])

    # for triangulation refinement
    tri2 = Triangulation(*new_vert.T)
    if refinement:
        tri2.set_mask(TriAnalyzer(tri2).get_flat_tri_mask(0.1))
        refiner = UniformTriRefiner(tri2)
        print(len(tri2.neighbors), vert_density.shape)
        tri, vert_density = refiner.refine_field(vert_density,
                                                 subdiv=refinement)
    else:
        tri, vert_density = tri2, vert_density

    return tri, vert_density