Search code examples
pythonnumpymatplotlibmayavi

Python / Numpy: Triangle mask from point mask


I'm working with a triangulated mesh consisting of points 3 x n and triangles specified by the point indices 3 x m. I can easily plot that e.g. using mlab

mesh = mlab.triangular_mesh(p[0,:],p[1,:],p[2,:],t.T

I am also generating a mask masking points which are out of bounds or nan, so I have a mask the size of n. Now I want to mask the triangles which have a masked point. My solutions so far:

1: Use the mask to turn all masked points into nan, e.g.

p[mask] = nan

mlab then still shows nan (I would need to include a threshold filter...) and I actually don't want to mess with my data

2: Generating a triangle mask, which I started like this

def triangleMask(triangles, pointmask):
    maskedTris = np.zeros((triangles.shape[1]), dtype=np.bool)
    maskedIdx = np.nonzero(pointmask)[0]
    for i,t in enumerate(triangles.T):
         if (i%5000) == 0:
             print('working it.:', i)
         for p in t:
             if p in maskedIdx:
                 maskedTris[i] = True
                 break

    return maskedTris

This works, but is not fast. And in my case, n = 250.000 and m = 500.000, so "not fast" is quite a problem.

I know there's a mask keyword in mlab, but I cant get it to work. Masking only the points in the triangular_mesh call yields and error since t then refers to indices which are larger than the size of p.


Solution

  • So you have a points array of shape (3, n), a triangles array of shape (3, m) and a point_mask boolean array of shape (n,), and would like to create a triangle_mask of shape (m,) holding True at position j if any of the indices in triangles[:, j] corresponds to a True in point_mask. You can do that with a little bit of fancy indexing:

    triangle_mask = np.any(point_mask[triangles], axis=0)
    

    To understand what's going on, point_mask[triangles] creates a boolean array of shape (3, m), with the value at position (i, j) being point_mask[triangles[i, j]].