Search code examples
pythonmultidimensional-arraymeshtriangulationdelaunay

Create 3D triangulated mesh from scratch


What I am trying to do is to create a 3D triangulated mesh that can be parsed into a .vtk or .stl file for use in 3D printing application. Right now I am stuck with the creation of the triangle mesh. The geometry I want to create are basically three dimensional sine waves that have a certain thickness and intersect each other. So far I got one sine wave. Here's a MWE:

import matplotlib.pyplot as plt
import numpy as np
from scipy import ndimage
import scipy.spatial

# create empty 3d array
array = np.zeros((100, 100, 100))

# create 3D sine wave in empty array
strut = np.sin(np.linspace(1, 10, 100))*12
for k in enumerate(strut):
    y_shift = int(np.round(strut[k[0]]))
    array[k, 50 + y_shift, 50] = 1

pattern = np.ones((4, 4, 4))

# convolve the array with the pattern / apply thickness
conv_array = ndimage.convolve(array, pattern)

# create list with data coordinates from convolved array
data = list()
for j in range(conv_array.shape[0]):
    for k in range(conv_array.shape[1]):
        for l in range(conv_array.shape[2]):
            if conv_array[j, k, l] != 0:
                data.append([j, k, l])

data = np.asarray(data)

tri = scipy.spatial.Delaunay(data)

fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")
ax.hold(True)
ax.plot_trisurf(data[:, 0], data[:, 1], data[:, 2], triangles=tri.simplices)
plt.show()

What it does: I create an empty array which I fill with a sine wave represented by ones. I convolve that array with a rectangular array of a defined size, which gives me a thicker sine wave in space. Then the array gets converted into coordinate form so that it can be triangulated using Delaunay triangulation. What I get is this:

Plot

As you can see the triangulation kinda worked, but it fills the space between the sine wave amplitudes. Is there a way to remove the filled spaced? Or prevent it from doing them in the first place? The sine wave also looks wrong at the ends and I am not sure why. Is this even the best method to achieve want I am trying to do?

The parsing to a .vtk file should not present a problem, but I need a clean structure first. Thanks in advance for any kind of help!


Solution

  • Finally I got something very close to what I want. In case someone is interested in the answer:

    Instead of going with the point cloud approach I dug myself into VTK (which is a pain to learn, but has a lot of functionality) with python.

    My algorithm is basically this:

    1. Approximate the sine wave as a simple triangular wave first.
    2. Feed the x, y and z coordinates of the wave into a vtkPoints object
    3. Use vtkParametricSpline to get a smooth wave
    4. vtkSplineFilter to have control over the smoothness of the wave
    5. vtkTubeFilter to create a volume from the line
    6. vtkTriangleFilter for meshing
    7. vtkSTLWriter