I am generating 2D binary shapes in python. After that, I want them to be converted to a 3D STL file for 3D printing. This kind of works, but only with "simple" shapes like triangles and squares. For more complex shapes I get the following Shape :
So as we can see it kinda looks like the binary image but with some more "artifacts". I use:
Here is my code:
import numpy as np
from scipy.spatial import Delaunay
from stl import mesh
from numpy import loadtxt
def load_shape(id):
return loadtxt("../shapes/shape_{}.shape".format(id))
def extract_vertices(shape):
arr = []
for ix, x in enumerate(shape):
for iy, y in enumerate(x):
if y == 0:
arr.append([ix, iy])
return np.array(arr)
def vertices_2d_to_3d(vertices, z=10):
x, y = vertices.shape
new = np.zeros((x*2, y + 1))
for i, v in enumerate(vertices):
new[i] = [v[0], v[1], 0]
new[x+i] = [v[0], v[1], z]
return new
shape = load_shape(4)
vertices = extract_vertices(shape)
vertices = vertices_2d_to_3d(vertices, 10)
tri = Delaunay(vertices)
faces = tri.convex_hull
ms = mesh.Mesh(np.zeros(faces.shape[0], dtype=mesh.Mesh.dtype))
for i, f in enumerate(faces):
for j in range(3):
ms.vectors[i][j] = vertices[f[j],:]
ms.save('shape.stl')
Can anyone give me some hints on how to get rid of these "artifacts" and tell delaunay triangulation to not connect the vertices that are not in the shape?
One characteristic of the Delaunay is that it will always produce a convex polygon from a set of sample points. So if you use the Delaunay, you will need some way of knowing which triangles are inside your area of interest and which are outside.
To that end, one thing you might look into is the Constrained Delaunay Triangulation (CDT). Some Delaunay implementations allow you to specify constraints in terms of non-self-interesecting polygons that can be used to specify "triangles inside" and "triangles outside" the constraints. I'm not sure if scipy supports this, but its implementation is generally excellent, so I wouldn't be surprised if it does.
Also, you may find that the Delaunay produces a lot of "skinny" triangles in your polygons. Since you are doing 3D printing, you may want to find some way of fixing these up. You can do so by inserting artificial points (Steiner points) into the mesh. These can be just arbitrarily taken from a regular grid or, if you have an API that supports it, you can apply some kind of Delaunay Refinement to your triangulation.
Beyond that, I wonder if the problem you are trying to solve isn't really constructing a Delaunay, but rather triangulating a polygon. The wikipedia article cited in the earlier answer should give you a start on that.