Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Boolean difference feature error #447

Open
eduvillasr opened this issue Jun 22, 2021 · 37 comments
Open

Boolean difference feature error #447

eduvillasr opened this issue Jun 22, 2021 · 37 comments

Comments

@eduvillasr
Copy link

eduvillasr commented Jun 22, 2021

Hello,
This is my first time using pyvista and am running into the following error:

ERROR:root:No points to subdivide
ERROR:root:No points/cells to operate on
ERROR:root:No points/cells to operate on

MY CODE:

airplane = pyvista.PolyData('cube.stl')
ant = pyvista.PolyData('sphere3.stl')
ant.translate([0, 0, 10])
sig_embed_des = airplane.boolean_difference(ant)
sig_embed_des.save('boolean.stl')
boolean = pyvista.PolyData('boolean.stl')
boolean.save('boolean.stl')

I am trying to take the boolean difference of a small sphere located in the middle of a larger cube. The sphere is inside the cube completely and I am trying to make a small hole within the cube. When I run my command the boolean difference function is not working. I am unsure as to whether or not I can actually take the difference of one model completely inside another.

Thank you!!!

Example Data

@adamgranthendry
Copy link

Hello @eduvillasr. You may need to triangulate the surface of your cube. Per the examples, both surfaces must be triangulated for the operation to work (see Boolean Operations). Try this:

import pyvista as pv

cube = pv.PolyData('cube.stl').extract_surface().triangulate()
sphere = pv.PolyData('sphere.stl').extract_surface().triangulate()  # In case not already triangulated

diff = cube.boolean_difference(sphere)
diff.save('diff.stl')

@eduvillasr
Copy link
Author

eduvillasr commented Jul 12, 2021 via email

@akaszynski
Copy link
Member

Hello,

Take a look at our latest development docs at https://dev.pyvista.org/api/core/_autosummary/_autosummary/pyvista.PolyDataFilters.boolean_difference.html

There are quite a few enhancements to pyvista that will be released soon. To try these out, install the latest development version with:

pip install git+https://github.com/pyvista/pyvista.git

@eduvillasr
Copy link
Author

Thank you for the response.

I have tried using the new development version and I receive the same errors.
Do you think maybe PyVista is not able to boolean an object completely inside another object yet?
If so, are there any workarounds that you recommend?

Thank you!

@eduvillasr
Copy link
Author

Both meshes are triangulated as well as subdivided several times.

@akaszynski
Copy link
Member

There are severe limitations on VTK's Boolean filters. One thing you might try is flipping the normals on one or both of the meshes, but it might just come down to the inability for vtk to deal with this geometry.

Another issue might be if your meshes aren't manifold. If you're completely sure there shouldn't be an issue, upload your meshes here and I'll look at them.

@eduvillasr
Copy link
Author

eduvillasr commented Jul 12, 2021 via email

@adamgranthendry
Copy link

@eduvillasr Hi, yes, I also get the same errors you are getting with several different geometries regardless of how much I've subdivided a mesh or how the normals are pointing. I'm sorry it's not working for you. It's also not working for me. I wish the boolean filters would work better.

@akaszynski Does VTK have a boolean filter for voxel data? Perhaps the algorithms would succeed when using volumes rather than surfaces?

@adamgranthendry
Copy link

@eduvillasr FYI, I will look in Kitware's C++ source code to see if I can understand how the boolean operations work for PolyData. The source code can be found on GitHub here. I've found comparing pyvista's code and vtk's code very helpful when trying to understand underlying algorithms and debug tough problems.

@eduvillasr
Copy link
Author

Sounds good to me, I'll be doing the same then. Thank you for your help. If you are able to figure it out please let me know!

@adamgranthendry
Copy link

@eduvillasr I haven't found out what's happening with the boolean operators, but using select_enclosed_points is working for my application. Can you give the example here a try and let me know if that works for you?

@eduvillasr
Copy link
Author

I am getting the following error:

ValueError: Empty meshes cannot be plotted. Input mesh has zero points.

I am not sure if this is just a graphing error and if it has performed the operation. How could I save the result as an stl file?

Thanks again!

@eduvillasr
Copy link
Author

Here is my code^

import pyvista as pv

mesh = pv.PolyData('testcube.stl')
#cpos = [(13.0, 7.6, -13.85), (0.44, -0.4, -0.37), (-0.28, 0.9, 0.3)]

dargs = dict(show_edges=True)

Rotate the mesh to have a second mesh

rot = pv.PolyData('testsphere.stl')

###############################################################################

Mark points inside with 1 and outside with a 0

select = mesh.select_enclosed_points(rot)

select
###############################################################################

Extract two meshes, one completely inside and one completely outside the

enclosing surface.

inside = select.threshold(0.5)
outside = select.threshold(0.5, invert=True)

p = pv.Plotter()
p.add_mesh(outside, color="Crimson", **dargs)
p.add_mesh(inside, color="green", **dargs)
p.add_mesh(rot, color="mintcream", opacity=0.35, **dargs)
p.show()

@adamgranthendry
Copy link

@eduvillasr You can save the mesh directly as an stl like so:

inside.save('inside.stl')
outside.save('outside.stl')

If you are getting that error though, it probably means your PolyData has zero vertices (and/or zero cells). Also trying printing the mesh before saving, like so:

print(inside)
print(outside)

If it shows 0 verticies or 0 cells for either, then something is up and your surfaces might not actually be intersecting.

@eduvillasr
Copy link
Author

Well, it says it only supports .vtu and .vtk.

ValueError: Invalid file extension for this data type. Must be one of: dict_keys(['.vtu', '.vtk'])

inside = select.threshold(0.5)
outside = select.threshold(0.5, invert=True)

print(inside)
print(outside)

inside.save('inside.stl')
outside.save('outside.stl')

@adamgranthendry
Copy link

@eduvillasr Oh, that might be because it's not polydata yet (might be UnstructuredGrid data). Try using extract_surface() before saving:

inside = select.threshold(0.5).extract_surface()
outside = select.threshold(0.5, invert=True).extract_surface()

print(inside)
print(outside)

inside.save('inside.stl')
outside.save('outside.stl')

@eduvillasr
Copy link
Author

eduvillasr commented Jul 13, 2021 via email

@adamgranthendry
Copy link

@eduvillasr Yes, this is a substitute. I'm not able to recreate your problem as I can save files as stl's directly. What version of pyvista are you using?

@akaszynski Can you assist?

@eduvillasr
Copy link
Author

eduvillasr commented Jul 13, 2021 via email

@adamgranthendry
Copy link

adamgranthendry commented Jul 13, 2021

@eduvillasr Show me the printout of inside and outside. Please put the result in triple backticks (i.e. a codeblock) so it is formatted properly for viewing. That is, just run print(inside) and print(outside) and show me the results.

@eduvillasr
Copy link
Author

eduvillasr commented Jul 13, 2021

PolyData (0x21e66583a68)
  N Cells:      3166
  N Points:     2847
  X Bounds:     -4.446e+00, 5.998e+00
  Y Bounds:     -3.637e+00, 2.760e+00
  Z Bounds:     -1.690e+00, 1.690e+00
  N Arrays:     3

PolyData (0x21e5de43348)
  N Cells:      197
  N Points:     239
  X Bounds:     -1.838e+00, 1.679e+00
  Y Bounds:     -1.861e+00, 1.686e+00
  Z Bounds:     -1.701e+00, 1.701e+00
  N Arrays:     3

First one corresponds to outside
second to inside

@adamgranthendry
Copy link

@eduvillasr Plot it with pyvista. Don't use another reader. Run:

import pyvista as pv

mesh = pv.read('inside.stl')

p = pv.Plotter()
p.add_mesh(mesh)
p.show()

and show us the output.

@eduvillasr
Copy link
Author

eduvillasr commented Jul 13, 2021 via email

@adamgranthendry
Copy link

@eduvillasr The image doesn't render. Can you please retry to add it or provide us a link to somewhere we can see it?

@eduvillasr
Copy link
Author

https://imgur.com/a/rV3yvbe

sorry

@adamgranthendry
Copy link

@eduvillasr No problem. Looks like you got your stl!

@eduvillasr
Copy link
Author

eduvillasr commented Jul 13, 2021

Well I am using this same process with a sphere inside a cube and am getting the following image

https://imgur.com/a/2qvZGrb

The boolean function has not been performed here
The models I am using are the same ones I sent a couple comments ago

I visualized the model in blender to confirm that there is no hole inside the cube

@adamgranthendry
Copy link

@eduvillasr Oh I see. It may be something to do with the ordering of the points and faces returned. I would use MeshLab. It's a great program and also written with VTK.

@eduvillasr
Copy link
Author

eduvillasr commented Jul 13, 2021 via email

@eduvillasr
Copy link
Author

I have used MeshLab and the model still does not include the operation in it. It just shows a cube like the one in the link I sent. Maybe we just can't replicate what I am trying to do using PyVista yet?

@adamgranthendry
Copy link

adamgranthendry commented Jul 21, 2021

@eduvillasr Hmmm, I'm really sorry to hear that. Perhaps that is the case. @akaszynski mentioned VTK's builtin boolean operations were troublesome. I wonder if a better algorithm is required.

I was able to find the paper on which the boolean operations are based: here. Click the "Download Paper" link under the resources. There's also source code, though I believe it's in C++.

I hope this will provide you some guidance that will drive you to a successful solution. I'll do my best to continue to see if there's a way to fix the common issues that occur in pyvista.

@adamgranthendry
Copy link

@eduvillasr Also, FWIW, I found the Mister P. MeshLab Tutorials on youtube very helpful when I was first learning MeshLab. It's been a long while since I've used it, so I couldn't tell you how to perform boolean operations in it and your needs may be more advanced than what's included in the tutorials here. However, python also has a binding for MeshLab, appropriately called pymeshlab. Since both pyvista and meshlab use vtk under the hood, you might have some success with pymeshlab. Full disclosure though, I haven't used pymeshlab. Other vtk alternatives include itk and SimpleITK, but those are also by KitWare and use VTK under the hood.

@eduvillasr
Copy link
Author

eduvillasr commented Jul 21, 2021 via email

@adamgranthendry
Copy link

@eduvillasr Very happy to help! I enjoy it 👍🏻

@harshamarupudi56
Copy link

Has this issue been resolved? I have been having a similar issue

@adam-grant-hendry
Copy link

Has this issue been resolved? I have been having a similar issue

Unfortunately (AFAIK), not yet. I have not had time to look into this further since last year.

@harshamarupudi56
Copy link

harshamarupudi56 commented Aug 26, 2022

I was able to create a visualization using

mesh = pv.PolyData(filenameSTL) #convert STL file to pyvista polydata 
    sphere_b = pv.Sphere(center=(0.5, 0, 0))
  
    result = mesh.boolean_difference(sphere_b)
    pl = pv.Plotter()
    _ = pl.add_mesh(mesh, color='r', style='wireframe', line_width=3)
    _ = pl.add_mesh(sphere_b, color='b', style='wireframe', line_width=3)
    _ = pl.add_mesh(result, color='tan')
    pl.camera_position = 'xz'
    pl.show()

Not quite what I need it to do yet but it is a start.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants