2
$\begingroup$

I'm attempting to do a boolean union between a cube and a polyhedron. It's getting error messages and the union doesn't complete. I thought that it might be a problem with something being co-planar, but I've tweaked the model so that isn't a possibility.

The errors for my test case are:

CSG failed, exception non intersecting group is not IN or OUT! (poly_a)
CSG failed, exception extern\carve\lib\triangulator.cpp:898  "didn't manage to link up hole!"
CSG failed, exception non intersecting group is not IN or OUT! (poly_a)
CSG failed, exception extern\carve\lib\triangulator.cpp:898  "didn't manage to link up hole!"

My test case is set up to do the union with either the polyhedron or with a cube of the same shape and dimensions. The union between the two cubes works fine.

Have I hit a bug, or am I making a mistake when I create my polyhedron?

For the record: Blender 2.71; Windows 7 64-Bit.

import bpy

def main(usePolyhedron):
    # Create object "A"
    if (usePolyhedron):
        points = [[0, 0, 0], [0, 0.3048, 0], [0.3048, 0.3048, 0], [0.3048, 0, 0], [0.3048, 0, 2.5000], [0.3048, 0.3048, 2.5000], [0, 0.3048, 2.5000], [0, 0, 2.5000]]
        faces = [[0, 1, 2, 3], [4, 5, 6, 7], [0, 7, 4, 3], [1, 6, 7, 0], [2, 5, 6, 1], [3, 4, 5, 2]]
        polyName = 'PolyhedronA'
        polyMeshName = polyName + 'Mesh'
        mesh = bpy.data.meshes.new(polyMeshName)
        verts = mesh.vertices
        verts.add (len(points))
        vindex = 0
        for p in points:
            verts[vindex].co = p
            verts[vindex].normal = (0.0,0.0,1.0)
            vindex += 1
        polygons = mesh.polygons
        polygons.add (len(faces))
        pindex = 0
        loops = mesh.loops
        loopCount = sum(len(f) for f in faces)
        loops.add(loopCount)
        lindex = 0
        edgeSet = set()
        for f in faces:
            curPoly = polygons[pindex]
            pindex += 1
            curPoly.vertices = f
            curPoly.loop_start = lindex
            lt = 0
            li = -1
            for v in f:
                loops[lindex].vertex_index = v
                lindex += 1
                lt += 1
                if li != -1:
                    edgeSet.add((min(li,v),max(li,v)))
                li = v
            edgeSet.add((min(li,f[0]),max(li,f[0])))
            curPoly.loop_total = lt
        edges = mesh.edges
        edges.add (len(edgeSet))
        eindex = 0
        for e in edgeSet:
            edges[eindex].vertices = [ ex for ex in e]
            eindex += 1
        if mesh.validate (False):
            print("Invalid mesh")
        mesh.update ()
        scene = bpy.context.scene
        objA = bpy.data.objects.new(polyName, mesh)
        objA.location = (0,0,0)
        scene.objects.link(objA)
        objA.select = False
    else:
        cubeName = 'CubeA'
        cubeSize = [0.3048, 0.3048, 2.5000]
        cubeOrigin = (0.1524, 0.1524, 1.2500)
        bpy.ops.mesh.primitive_cube_add (location=cubeOrigin)
        objA = bpy.context.object
        objA.name=cubeName
        meA = objA.data
        meA.name = cubeName + 'Mesh'
        objA.scale = [cubeSize[0]/2, cubeSize[1]/2, cubeSize[2]/2]
        objA.select = True
        bpy.context.scene.objects.active = objA
        bpy.context.scene.cursor_location = (0.0, 0.0, 0.0)
        bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
        bpy.context.scene.objects.active = None
        objA.select = False

    cubeName = 'CubeB'
    cubeSize = [0.3500, 0.3500, 0.3100]
    cubeOrigin = (0.1730, 0.1242, 2.4410)
    bpy.ops.mesh.primitive_cube_add (location=cubeOrigin)
    objB = bpy.context.object
    objB.name=cubeName
    me = objB.data
    me.name = cubeName + 'Mesh'
    objB.scale = [cubeSize[0]/2, cubeSize[1]/2, cubeSize[2]/2]
    objB.select = True
    bpy.context.scene.objects.active = objB
    bpy.context.scene.cursor_location = (0.0, 0.0, 0.0)
    bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
    bpy.context.scene.objects.active = None
    objB.select = False

    # Take the union of 'A' and 'B'
    modName = 'Union'
    bpy.context.scene.objects.active = objA
    boo = objA.modifiers.new(modName, 'BOOLEAN')
    boo.object = objB
    boo.operation = 'UNION'
    bpy.ops.object.modifier_apply(apply_as='DATA', modifier=modName)
    bpy.context.scene.objects.unlink(objB)
    bpy.context.scene.objects.active = None

if __name__ == '__main__':
    main(True)
$\endgroup$
0
$\begingroup$

I vote that this hits a bug. A small movement hides the error -

# Take the union of 'A' and 'B'
modName = 'Union'
bpy.context.scene.objects.active = objA
boo = objA.modifiers.new(modName, 'BOOLEAN')
boo.object = objB
boo.operation = 'UNION'
objB.location = (0.01, 0.0, 0.0)

But if you manually move the cube back to (0.0, 0.0, 0.0) the error returns.

I don't think that small a variation in location should effect the boolean modifier.

|improve this answer|||||
$\endgroup$
  • $\begingroup$ Thanks. A small variation in location is often the work-around when you have co-planar issues with the boolean modifiers -- trying to do a UNION between two objects that abut at a common face will often fail. I agree that that shouldn't be the case here, because there are no common faces, unless I messed something up in the polyhedron. $\endgroup$ – artk2002 Sep 8 '14 at 17:45
0
$\begingroup$

Solved my problem. The issue was the polyhedron. Looking at the normals after the polyhedron is created shows some pointing in and some pointing out. Correcting that (first by the UI and then by script) and everything worked fine.

|improve this answer|||||
$\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.