Source code for pyleecan.Methods.Mesh.MeshMat.find_cell

# -*- coding: utf-8 -*-

import numpy as np


def find_cell(self, points, nb_pt, normal_t=None):
    """Return the cells containing the target point(s)

    Parameters
    ----------
    self : MeshMat
        an MeshMat object
    points : ndarray
        coordinates of the target point(s)
    nb_pt : int
        number of target points

    Returns
    -------
    cell_list: list
        A list of  of selected cells

    """
    # nmax_search = 3
    cells_list = list()
    cell_prop = list()

    nodes = self.node
    point_coord = nodes.coordinate
    nb_tot_pt = nodes.nb_node

    for ii in range(nb_pt):
        if nb_pt == 1:
            pt = points
        else:
            pt = points[ii, :]
        for key in self.cell:
            cells = self.cell[key]
            ref_cell = cells.interpolation.ref_cell
            connect = cells.connectivity
            nb_node_per_cell = cells.nb_node_per_cell
            # vertice0 = point_coord[connect[0]]
            # dist_ref = np.sqrt(
            #     np.square(vertice0[0, 0] - vertice0[1, 0])
            #     + np.square(vertice0[0, 1] - vertice0[1, 1])
            # )

            # compute the distance of all nodes to the current point 'pt'
            point_rep = np.tile(pt, (nb_tot_pt, 1))

            if self.dimension == 3:
                dist_node = np.reshape(
                    np.sqrt(
                        np.square(point_coord[:, 0] - point_rep[:, 0])
                        + np.square(point_coord[:, 1] - point_rep[:, 1])
                        + np.square(point_coord[:, 2] - point_rep[:, 2])
                    ),
                    (nb_tot_pt, 1),
                )
            else:
                dist_node = np.reshape(
                    np.sqrt(
                        np.square(point_coord[:, 0] - point_rep[:, 0])
                        + np.square(point_coord[:, 1] - point_rep[:, 1])
                    ),
                    (nb_tot_pt, 1),
                )
            # min_dist = np.min(dist_node)
            # min_node = np.where(dist_node == min_dist)[0]
            Imin_node = np.argsort(dist_node, axis=0)
            # Imin_node = Imin_node[0:nmax_search]  #

            # All selected nodes from the closest to the farthest are tested
            inode = 0
            # dontstop = True

            # while inode < nmax_search and inode < nb_tot_pt and dontstop:

            # get cells that contain the closest node and test if point is inside
            closest_cells = np.where(connect == Imin_node[inode])[0]
            nb_closest_elem = len(closest_cells)
            a, b = np.zeros(nb_closest_elem), np.zeros(nb_closest_elem)
            cell_prop = list()
            for ielt in range(nb_closest_elem):
                vert = self.get_vertice(closest_cells[ielt])[key]
                (is_inside, a[ielt], b[ielt]) = ref_cell.is_inside(vert, pt, normal_t)
                if is_inside:
                    # dontstop = False
                    cell_prop.append(key)
                    cell_prop.append(closest_cells[ielt])

                # inode = inode + 1
                # break

            # if no cell was found, give it a second try
            # TODO first check if outside mesh
            if len(cell_prop) == 0:
                # test all cells (sorted by center, i.e. mean of vertices)
                vert_cent = np.zeros(pt.shape)
                for icell in range(nb_node_per_cell):
                    vert_cent = (
                        vert_cent + point_coord[connect[:, icell]] / nb_node_per_cell
                    )

                if self.dimension == 3:
                    dist_vert_cent = np.reshape(
                        np.sqrt(
                            (vert_cent[:, 0] - pt[0]) ** 2
                            + (vert_cent[:, 1] - pt[1]) ** 2
                            + (vert_cent[:, 2] - pt[2]) ** 2
                        ),
                        (cells.nb_cell, 1),
                    )
                else:
                    dist_vert_cent = np.reshape(
                        np.sqrt(
                            (vert_cent[:, 0] - pt[0]) ** 2
                            + (vert_cent[:, 1] - pt[1]) ** 2
                        ),
                        (cells.nb_cell, 1),
                    )

                Imin_vert_cent = np.argsort(dist_vert_cent, axis=0)[:, 0]
                i = 0
                is_inside = False
                while i < cells.nb_cell and not is_inside:
                    vert = self.get_vertice(Imin_vert_cent[i])[key]
                    (is_inside, a, b) = ref_cell.is_inside(vert, pt, normal_t)
                    if is_inside:
                        # dontstop = False
                        cell_prop = [key, Imin_vert_cent[i]]
                    i += 1

            # No cell contain the point atleast (only possible if point is outside mesh)
            if len(cell_prop) == 0:
                cells_list.append(None)
            # one cell found
            elif len(cell_prop) == 2:
                cells_list.append(cell_prop)
            # more than one cells found
            elif len(cell_prop) > 2:
                ind = np.where(np.min(a) == a)[0][0]
                cells_list.append(cell_prop[2 * ind : 2 * ind + 2])

    return cells_list