mikedh / trimesh

Python library for loading and using triangular meshes.
https://trimesh.org
MIT License
3k stars 581 forks source link

Boolean fails after previously having worked #798

Open steersteer opened 4 years ago

steersteer commented 4 years ago

Hi, I'm getting this error despite having success before, any ideas?

Traceback (most recent call last): File "F:/OneDrive - Heriot-Watt University/Heriot Watt/Year 4/Thesis/01_Project/Code/Tester 2.5/Tester 2.5.py", line 333, in boolean('whole', 'trabecular') File "F:/OneDrive - Heriot-Watt University/Heriot Watt/Year 4/Thesis/01_Project/Code/Tester 2.5/Tester 2.5.py", line 131, in boolean meshh = bool.difference(meshlist, engine='scad') File "C:\Users\whywo\AppData\Local\Programs\Python\Python37\lib\site-packages\trimesh\boolean.py", line 25, in difference result = _engines[engine](meshes, operation='difference', kwargs) File "C:\Users\whywo\AppData\Local\Programs\Python\Python37\lib\site-packages\trimesh\interfaces\scad.py", line 65, in boolean return interface_scad(meshes, script, debug=debug, kwargs) File "C:\Users\whywo\AppData\Local\Programs\Python\Python37\lib\site-packages\trimesh\interfaces\scad.py", line 53, in interface_scad result = scad.run(_scad_executable + ' $SCRIPT -o $MESH_POST') File "C:\Users\whywo\AppData\Local\Programs\Python\Python37\lib\site-packages\trimesh\interfaces\generic.py", line 94, in run startupinfo=startupinfo) File "C:\Users\whywo\AppData\Local\Programs\Python\Python37\lib\subprocess.py", line 363, in check_call raise CalledProcessError(retcode, cmd) subprocess.CalledProcessError: Command '['C:\Program', 'Files\OpenSCAD\openscad.exe', 'C:\Users\whywo\AppData\Local\Temp\tmp1x1uao4r', '-o', 'C:\Users\whywo\AppData\L ocal\Temp\tmp5vw5i22k.off']' returned non-zero exit status 1.

steersteer commented 4 years ago

I should add, OpenSCAD is installed in the same location as before

moloney commented 4 years ago

I ran into this issue as well. There were two distinct problems:

1) The ".off" input files were sometimes created erroneously empty (pass debug=True and look at the files in /tmp) 2) The result of the intersection is sometimes empty, in which case openscad returns 1

Setting exchange='stl' in trimesh.interfaces.scad fixed the first issue for me (happy to submit a patch if that is the correct fix), and then I can catch the CalledProcessError to detect empty results and thus work around the second issue (in a non-ideal way as this could potentially mask other errors).

jpmaterial commented 3 years ago

I ran into this issue as well. Empty intersection shouldn't raise an exception all the way to the application programmer. Script for reproduction:

import trimesh

box0 = trimesh.creation.box((1,1,1),  trimesh.transformations.translation_matrix( (1,0,0) ) )
box1 = trimesh.creation.box((1,1,1),  trimesh.transformations.translation_matrix( (-1,0,0) ) )
empty = trimesh.boolean.intersection([box0,box1])

I understand that OpenSCAD's behavior is unfortunate in this regard, especially since we don't know under which other circumstances it might return 1. But at least make it explicit for the trimesh user - catch the CalledProcessError and when the return value was one, raise another exception with the message "OpenSCAD returned 1 - this usually means the intersection was empty". That would change nothing about the core problem, but one could handle it better and more future-proofly (i.e. this work-around exception simply wouldn't get thrown anymore once there is an actual fix, but other returncode-1-issues would come through) and it is quick to do.

An actual solution would probably mean scripting OpenSCAD differently.