julienr/meshcut

cross section

Closed this issue · 6 comments

I'm using your library for a program I'm making. It works very well except that when I run the cross_section code, the returned arrays seem to build up points of a line. When I connect all these points some appear to because I'm not sure where to connect the start and in points of each array.

Here I have a teapot.stl and here is the result I got out by "connecting the dots" if you will.

dots

connected dots

So I have no idea where to connect the start and end points. Is there something I'm missing?

This is the STL I'm using

I think the problem is due to the fact that the teapot mesh is not manifold : it has holes and basically consists of two parts.
By closing the holes in meshlab and merging close vertices (teapot.ply.zip), I get the following cut, which looks correct to me. The reason why there are two parts is because the lid is a separate part.

screen shot 2016-10-10 at 21 36 32

Here is a nice video about fixing non-manifold meshes in meshlab.

Does this help ?

Unfortunately, I did try completely closed meshes.

When I do a sphere I get an array of polylines. When I draw all the polylines I don't get a closed circle but instead a "C" shape.

When I do a sphere I get an array of polylines. When I draw all the polylines I don't get a closed circle but instead a "C" shape.

Sounds like a bug. Can you provide an example .ply where you observe this behavior ?

Attached is a zip of the 1mm Diameter Sphere that I am using that I created in solidworks. It is an STL file.

Included is also a SVG generated using the array of polylines obtained from the meshcut.cross_section fuction. You'll notice that at the bottom left corner of the circle there is a gap making the polyline not a complete closed loop.

Thanks for looking into this.

1mmDiameterSphere.zip

Edit:
And here is my code for converting my STL into a format that will work for the cross_section function.

print "Loading STL file..."
stl_mesh = mesh.Mesh.from_file('sphere.stl')
vertices = numpy.zeros((len(stl_mesh.vectors)*3, 3))
faces = numpy.array([[0, 0, 0]])
print "Creating an array of all the verticies..."
for i, f in enumerate(stl_mesh.vectors):
    for j in range(3):
        vertices[i*3+j] = f[j]
vertices = unique_rows(vertices)
print "Creating an array of all the connected faces..."
t0 = time.time()
for i, f in enumerate(stl_mesh.vectors):
    face = numpy.array([[0, 0, 0]])
    for j in range(3):
        face[0][j] = np.where(np.all(vertices==f[j], axis=1))[0][0]
        #for h, m in enumerate(vertices):
        #    if (m == tuple(f[j])).all():
        #        face[0][j] = h
    faces = numpy.concatenate((faces, face), axis=0)
    #break
t1 = time.time()
faces = numpy.delete(faces, 0, 0)

plane_orig = (0, 0.5, 0)
plane_norm = (0, 1, 0)
P = meshcut.cross_section(vertices, faces, plane_orig, plane_norm)

The problem is that STL files store vertices per face. If a vertex belongs to N faces, there will be N copies of this vertex in the file. So each face will look like a separate mesh to meshcut.

The solution is to do a preprocessing step to merge close vertices and recompute the face indices. I have implemented this in 1_stl_sphere_cut.py using your STL sphere as an example. Hope you don't mind me putting the .stl in the repo ?

Note that the "merge close vertices" implementation in this script is quite naive and will take a lot of time and memory if you have a big mesh. You might want to look at libigl implementation if you need to process larger meshes.

With that script, I get the following result, which looks good to me.

screen shot 2016-10-11 at 22 14 09

Wow thank you so much for working with me on this and taking the initiative to do so much to make sure this would work for me.

I'm looking into your implementation now. I definitely don't mind if you use my STL.