2
$\begingroup$

I am trying to check if a cube and a cone with 7 vertices (python will show 8) intersect or not. To do so, I am using a boolean intersect modifier and check how many vertices are there, after adding the modifier. If it is non-zero then they are intersecting otherwise not. I am running the following codes.

# read the objects and print number of vertices and faces
cube = bpy.data.objects['Cube']
cone = bpy.data.objects['Cone']

print (len(cone.data.vertices),len(cube.data.vertices),len(cone.data.polygons),len(cube.data.polygons))
>> 8, 8, 8, 6


# select the cube and add intersect boolean modifier

bpy.ops.object.select_all(action='DESELECT')
cube.select_set(True)
intra = cube.modifiers.new(type="BOOLEAN", name="intersctn")
intra.object = cone
intra.operation = 'INTERSECT'

# check the number of vertices now
print (len(cone.data.vertices),len(cube.data.vertices),len(cone.data.polygons),len(cube.data.polygons))
>> 8, 8, 8, 6

The issue is, whether they are intersecting or not - the number of vertices or faces returns the same as the original cube. I can clearly see that number of vertices and faces has increased after adding the boolean modifier but the python giving me the wrong result. When they are not intersected, the faces and vertices supposed to be 0, but I am still getting 8 and 6. Is this a common issue with the intersect boolean modifier or do I have to update something?

$\endgroup$
4
$\begingroup$

Use the evaluated object

Modifiers don't alter the mesh, they "Modify, Generate, Deform or Physics" the mesh result ... using the mesh as input. Think of it like a method in mathematics sin(x) doesn't alter x it returns a result using x as input.

The result is available in newer versions of blender as the evaluated object.

How do I get a mesh data-block with modifiers and shape keys applied in Blender 2.8?

This is the result of all modifiers applied. It in no way applies the result to the mesh. As with most modifiers they are often not easily reversible if applied, and is not required to simply test if geom would be changed.

Test script looks at difference between edge count of cube unmodified and with all modifiers.

import bpy
context = bpy.context
scene = context.scene

cube = scene.objects.get("Cube")
cone = scene.objects.get("Cone")
if cube and cone:
    print(len(cube.data.edges))
    bm = cube.modifiers.new(name="Foo", type='BOOLEAN')
    bm.operation = 'INTERSECT'
    bm.object = cone
    dg = context.evaluated_depsgraph_get()
    eval_cube = cube.evaluated_get(dg)
    print(len(eval_cube.data.edges))

A better option would be to look at the evaluated object both before or after to see the change in evaluated meshes. (eg the cube could already have a stack of modifiers)

import bpy
context = bpy.context
scene = context.scene

cube = scene.objects.get("Cube")
cone = scene.objects.get("Cone")
if cube and cone:
    cube.evaluated_get(context.evaluated_depsgraph_get())
    print(len(eval_cube.data.edges))
    bm = cube.modifiers.new(name="Foo", type='BOOLEAN')
    bm.operation = 'INTERSECT'
    bm.object = cone
    
    eval_cube = cube.evaluated_get(context.evaluated_depsgraph_get())
    print(len(eval_cube.data.edges))
    cube.modifiers.remove(bm)

If the mesh has no modifiers of shapekeys prior to adding could check for this to avoid an unrequired evaluation.

prior_cube = (
    cube.evaluated_get(context.evaluated_depsgraph_get()) 
    if (
        cube.data.shape_keys 
        or cube.modifiers
        ) 
    else 
        cube
    )

enter image description here Test run, default cube on RHS has subsurf modifier. Results (before, after) are 12, 64 and 92, 192

An interesting technique to test for intersection. Could be on the slowish side. Looping over objects getting data and adding modifiers, then looping again would require only evaluating the context depsgraph twice instead of twice for each object.

$\endgroup$
2
  • $\begingroup$ It's really slow. I have 2400 cubes to check if each of them intersects with the cone or not. Just run the script and it seems like - it will take ages to complete. Do you have any suggestions on a faster method? $\endgroup$ – Sourav Oct 8 '20 at 17:34
  • 1
    $\begingroup$ Thought it may be. Commented here blender.stackexchange.com/questions/196970/… There are a number of other object in object Q&As been posted over the years. Wrap in simple tests like distance from centroid or bounding box tests to narrow down the selection before any expensive intersection test. Please consider editing other question with what you have tried or found so far. $\endgroup$ – batFINGER Oct 8 '20 at 18:04
1
$\begingroup$

The problem is you are not applying it. You should apply before printing.

bpy.ops.object.modifier_apply(modifier="intersctn", report=True)

Add the line above, after setting the modifier parameters.

Changed Script: (worked for me. Just make sure that you've selected the cube before running the script)

import bpy
cube = bpy.data.objects['Cube']
cone = bpy.data.objects['Cone']

print (len(cone.data.vertices),len(cube.data.vertices),len(cone.data.polygons),len(cube.data.polygons))


# select the cube and add intersect boolean modifier
bpy.ops.object.select_all(action='DESELECT')
cube.select_set(True)
intra = cube.modifiers.new(type="BOOLEAN", name="intersctn")
intra.object = cone
intra.operation = 'INTERSECT'
bpy.ops.object.modifier_apply(modifier="intersctn", report=True)

# check the number of vertices now
print (len(cone.data.vertices),len(cube.data.vertices),len(cone.data.polygons),len(cube.data.polygons))
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.