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

csg boolean node crashes given this .blend #3430

Closed
zeffii opened this issue Aug 1, 2020 · 12 comments
Closed

csg boolean node crashes given this .blend #3430

zeffii opened this issue Aug 1, 2020 · 12 comments
Labels

Comments

@zeffii
Copy link
Collaborator

zeffii commented Aug 1, 2020

again user at blenderartists gives an example where Sverchok crashes with no useful information, if the boolean node is connected to an output.

https://drive.google.com/file/d/1ZO0VlOqmzS6EculTa-LfRlF4z7549eOz/view

maybe recursion limit? maybe time for an alternative boolean library :)

mesh-to-solid - > boolean -> solid-to-mesh -> llimited dissolve, does work nicely tho.
image

@zeffii zeffii added the bug 🐛 label Aug 1, 2020
@Durman
Copy link
Collaborator

Durman commented Aug 1, 2020

Would be interesting to see performance differences.

@zeffii
Copy link
Collaborator Author

zeffii commented Aug 1, 2020

yummy. maybe this is going to happen https://pymesh.readthedocs.io/en/latest/mesh_boolean.html

https://github.com/PyMesh/PyMesh

@vicdoval
Copy link
Collaborator

vicdoval commented Aug 1, 2020

Also FreeCAD offers "mesh boolean"... but it seems it depends on OpenSCAD

https://wiki.freecadweb.org/Mesh_Intersection

@zeffii
Copy link
Collaborator Author

zeffii commented Aug 1, 2020

oh.. what have i done?

"""
in verts_a v
in faces_a s
in verts_b v
in faces_b s
in precision s d=0.1 n=2
out verts_new v
out faces_new s
enum = common fuse cut
"""

def ui(self, context, layout):
    layout.prop(self, 'custom_enum', expand=True)

import Part
import Mesh
from FreeCAD import Base
from sverchok.nodes.solid.mesh_to_solid import ensure_triangles
from sverchok.data_structure import updateNode, match_long_repeat as mlr

verts_a = self.inputs[0].sv_get(deepcopy=False)
faces_a = self.inputs[1].sv_get(deepcopy=False)
verts_b = self.inputs[2].sv_get(deepcopy=False)
faces_b = self.inputs[3].sv_get(deepcopy=False)

for v1, f1, v2, f2 in zip(*mlr([verts_a, faces_a, verts_b, faces_b])):
 
    tri_faces = ensure_triangles(v1, f1, True)
    faces_t = [[v1[c] for c in f] for f in tri_faces]
    mesh = Mesh.Mesh(faces_t)
    shape = Part.Shape()
    shape.makeShapeFromMesh(mesh.Topology, precision)
    shape = shape.removeSplitter()  # may slow it down, or be totally necessary
    solid_a = Part.makeSolid(shape)

    tri_faces_2 = ensure_triangles(v2, f2, True)
    faces_t_2 = [[v2[c] for c in f] for f in tri_faces_2]
    mesh_2 = Mesh.Mesh(faces_t_2)
    shape_2 = Part.Shape()
    shape_2.makeShapeFromMesh(mesh_2.Topology, precision)
    shape_2 = shape_2.removeSplitter()  # may slow it down, or be totally necessary
    solid_b = Part.makeSolid(shape_2)
    
    solid_out = getattr(solid_a, self.custom_enum)(solid_b)
    solid_out = solid_out.removeSplitter()
    
    rawdata = solid_out.tessellate(precision)
    b_verts = [(v.x, v.y, v.z) for v in rawdata[0]]
    verts_new.append(b_verts)
    faces_new.append(rawdata[1])

image

example snlite enums and lib import freecad

@zeffii
Copy link
Collaborator Author

zeffii commented Aug 1, 2020

nice work @vicdoval this was very easy to cobble together :)

@zeffii
Copy link
Collaborator Author

zeffii commented Aug 1, 2020

or even

"""
in verts_a v
in faces_a s
in verts_b v
in faces_b s
in precision s d=0.1 n=2
out verts_new v
out faces_new s
enum = common fuse cut
"""

def ui(self, context, layout):
    layout.prop(self, 'custom_enum', expand=True)

import Part
import Mesh
from FreeCAD import Base
from sverchok.nodes.solid.mesh_to_solid import ensure_triangles
from sverchok.data_structure import updateNode, match_long_repeat as mlr

verts_a = self.inputs[0].sv_get(deepcopy=False)
faces_a = self.inputs[1].sv_get(deepcopy=False)
verts_b = self.inputs[2].sv_get(deepcopy=False)
faces_b = self.inputs[3].sv_get(deepcopy=False)

def mesh_to_solid(verts, faces, precision):
    tri_faces = ensure_triangles(verts, faces, True)
    faces_t = [[verts[c] for c in f] for f in tri_faces]
    mesh = Mesh.Mesh(faces_t)
    shape = Part.Shape()
    shape.makeShapeFromMesh(mesh.Topology, precision)
    shape = shape.removeSplitter()  # may slow it down, or be totally necessary
    return Part.makeSolid(shape)

for v1, f1, v2, f2 in zip(*mlr([verts_a, faces_a, verts_b, faces_b])):
 
    solid_a = mesh_to_solid(v1, f1, precision)
    solid_b = mesh_to_solid(v2, f2, precision)
    solid_out = getattr(solid_a, self.custom_enum)(solid_b)
    solid_out = solid_out.removeSplitter()
    
    rawdata = solid_out.tessellate(precision)
    b_verts = [(v.x, v.y, v.z) for v in rawdata[0]]
    verts_new.append(b_verts)
    faces_new.append(rawdata[1])

image

@zeffii
Copy link
Collaborator Author

zeffii commented Aug 8, 2020

@vicdoval so we need some utils/modules/solid_helpers.py to collect a few of these convenience functions like svmesh_to_solid, would even simplify a few solids nodes..

@zeffii
Copy link
Collaborator Author

zeffii commented Aug 8, 2020

i mean.. we don't need.. but it would be useful.

@vicdoval
Copy link
Collaborator

vicdoval commented Aug 8, 2020

there is a utils/solid.py file with the solid to mesh functions used in the Solid Viewer (but I never removed the base code in the node because of subtle differences....) feel free to add anything you think it may be useful

@zeffii
Copy link
Collaborator Author

zeffii commented Aug 8, 2020

yes, i'll do that. maybe the 3 different flavours.

@zeffii
Copy link
Collaborator Author

zeffii commented Aug 15, 2020

so @vicdoval @Durman @nortikin @portnov

The tests in snlite are quite nice (except for the initial overhead) maybe it's worth adding a FreeCAD version of the boolean node with post processor (untriangulate). and the option to hot-swap the old node with new one. I may have time today.

@zeffii
Copy link
Collaborator Author

zeffii commented Aug 15, 2020

prelim docs

multi-Boolean (FreeCAD)
---

prerequisits: FreeCAD
This node uses a 3rd party library to perform boolean meshes.  It will work more robustly than the standard Sverchok 
boolean node.

The meshes must satisfy a few characteristics
- must be closed meshes. (closed like air-tight).
- must be manifold, no edge may connect more than 2 faces / no part of the mesh shall self intersect.
- your mesh will also not have vertices that overlap (ie exist in identical 3D space)

The inputs can be iteratively merged or not, so if the inputs are A and B and the output is C, then you can have two 
forms of output.
'''
C = (A1+B1) + (A2+B2) + (A3+B3)   (iteratively)
C1, C2, C3 = A1+B1, A2+B2, A3+B3  (individual)
'''
as a post processing step (if you don't want the default triangle-only output) you can use a built-in simplify surface 
function to get quads or larger n-gons

Efficiency
----------

The node uses the FreeCAD library, which in turn deals with solids. Internally this node converts all meshes to solids 
every time the node is told to update. This is not computationally efficient, by any stretch of the imagination, but we 
offer the node as a convenience for fast prototyping. The demanding user will prefer the ability to get a good boolean 
result, and pay the computational price of the overhead incurred by the `mesh_to_solid` function.

Due to the way Sverchok evaluates the nodetree, it may be more efficient to convert your meshes explicitly to Solids, and 
use the Boolean Node from the Solids (-> operations) menu.  This boolean node does all that under the hood. The 
trade-off is user-convenience *vs* computational-efficiency.

Macro
-------
When you're happy about the result of the Boolean (FreeCAD) node, you can increase computational efficiency by running 
the Macro (  `CBTS' ) "convert bool to solid".  This macro will replace the multi-boolean FreeCAD node,, with Two 
`Mesh-to-Solids` nodes, directly connected to the Solids Boolean node, and outputting to a `Solid-to-Mesh` node, and a 
simplify node with the same settings as the boolean node it replaced.  This expands the nodetree, but the result allows
you to potentially incur less overhead, for example: if you actively transform the solids prior to doing the boolean, then only the boolean operation is repeatedly done, but the mesh-to-solid conversion is done only once (or if something upstream from the mesh-to-solid nodes changes)

(show image)

If you don't care about efficiency, it's fine to use the brute-force method :) 

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

No branches or pull requests

3 participants