Плохая триангуляция Делоне для набора данных 3D с использованием matplotlib - PullRequest
0 голосов
/ 20 апреля 2019

enter image description here

У меня есть набор данных с координатами x, y, z, которые должны представлять поверхность.Данные происходят из трехмерной конечно-элементной сетки.Теперь я хотел бы построить только эту поверхность с помощью matplotlib.Используя приведенный ниже код, я смог успешно построить несколько поверхностей.Однако поверхность, соответствующая добавленному набору данных, не дает удовлетворительного результата, как вы можете видеть на этом изображении:

Поверхности, лежащие вдоль оси Y, и поверхность, которая не отображается правильно, нанесены с использованием отдельных наборов данных.

@staticmethod
    def plot_vector(*args, surfaces=[], **kwargs):
        '''
        *args = vectors that have to be plotted
        **surfaces = tuple of all surfaces that have to be plotted
        **vector_surface = surface on which the vectors have to be plotted,
        the vector_surface should also be included in the surfaces tuple
        **intersect = np.ndarray containing intersection points between the weld and plate
        The vectors will not be plotted on the centerpoint but along the edge of the weld
        Either vector_surface or intersect have to be entered,
        kwarg intersect has priority over kwarg vector_surface
        **colors = tuple containting colors for the quivers. len(colors) should be equal to
        the number of vector arguments given
        **vector_length = array_like of shape (3,) or a scalar value which allowing scaling
        of vector lengths
        **trisurf if trisurf kwarg = true then a trisurf plot instead of a scatter plot is made
        '''
        # Create figure and axes objects
        fig = plt.figure()
        ax = fig.add_subplot(111, projection='3d')

        # Check if atleast one of the manadatory kwargs is entered
        b = ['vector_surface', 'intersect']
        a = kwargs.keys()
        check = lambda a, b: any(i in b for i in a)
        if check is False:
            raise ValueError(''Expected either a vector_surface or intersect arg'')

        # Get the max and min number along each axis for each surface
        # Used to determine vector length and axis limits
        max_x = max([np.amax(surf[:, 0]) for surf in surfaces])
        max_y = max([np.amax(surf[:, 1]) for surf in surfaces])
        max_z = max([np.amax(surf[:, 2]) for surf in surfaces])

        min_x = min([np.amin(surf[:, 0]) for surf in surfaces])
        min_y = min([np.amin(surf[:, 1]) for surf in surfaces])
        min_z = min([np.amin(surf[:, 2]) for surf in surfaces])

        #Iterate over all surfaces entered through surfaces kwarg
        for i, surf in enumerate(surfaces):
            x_val = surf[:, 0]
            y_val = surf[:, 1]
            z_val = surf[:, 2]

            if 'plot_trisurf' in kwargs and True == kwargs['plot_trisurf']:
                triang = mtri.Triangulation(x_val, y_val)
                ax.plot_trisurf(triang, z_val, cmap='jet', alpha=0.5)
            else: ax.scatter(x_val, y_val, z_val, c='b', alpha=0.2)

            # Plot the vectors (quivers)
            for i, arg in enumerate(args): # args = vectors that have to be plotted
                for j, vectors in enumerate(arg):
                    if 'intersect' in kwargs:
                        X, Y, Z = intersect[j]
                    elif 'vector_surface' in kwargs:
                        if np.array_equal(surf, kwargs['vector_surface']):
                            # Calculate the center point of the surface
                            center_point = (x_val.sum(axis=0)/x_val.shape[0],
                                            y_val.sum(axis=0)/y_val.shape[0],
                                            z_val.sum(axis=0) /z_val.shape[0])

                            # Vector start point
                            X, Y, Z = center_point

                    # Vector length is standard = 5
                    if 'vector_length' in kwargs:
                        vector_length = kwargs['vector_length']
                        if isinstance(vector_length, (int, float)):
                            U, V, W = vectors * vector_length
                        elif isinstance(vector_length, (list, tuple, np.ndarray)) and i <= len(vector_length):
                            U, V, W = vectors * vector_length[i]
                    else:
                        U, V, W = vectors*5

                    #If the kwarg colors if given, apply the right color
                    if 'colors'in kwargs:
                        c = kwargs['colors'][i]
                    else: c = 'r'

                    # Add the vector to the axes objec
                    ax.quiver(X, Y, Z, U, V, W, color=c)

        # Labels, limits, show plot
        ax.set_xlabel('X-axis')
        ax.set_ylabel('Y-axis')
        ax.set_zlabel('Z-axis')

        ax.set_xlim(max_x, min_x)
        ax.set_ylim(max_y, min_y)
        ax.set_zlim(max_z, min_z)
        plt.show()

При построении с использованием диаграммы рассеяния график выглядит следующим образом:

enter image description here Так что в основном мой вопрос заключается в том, почему триангуляция работает хорошо для одной поверхностино не для другой, казалось бы, менее сложной поверхности, и как можно это исправить?

Спасибо.

...