View Issue Details

IDProjectCategoryView StatusLast Update
0001248FreeCADBugpublic2014-12-26 18:36
Reporterpkoning Assigned To 
PrioritynormalSeveritymajorReproducibilityalways
Status closedResolutionno change required 
Product Version0.13 
Summary0001248: Boolean operations are very unreliable
DescriptionI'm having a running battle with boolean operations. They sometimes work, but more often than not produce the wrong answer. "common" ends up doing a cut, for example. Or the result of "common" depends on the order of the operands. Or sometimes "a.cut(b)" produces a-b and sometimes b-a. It may depend on the object sizes.

Attached is a simple test case. I'm trying to draw decks inside the solid, so "deck = deck.common (solid)" is the thing to do. The actual outcome I get is as if I had done "deck = deck.cut(solid)" (in the sense of "deck - solid").

BTW, it would be good to document what the operand order of "cut" is; I don't see in in the API docs.
Additional InformationMac version of V0.13, on Mac OS 10.8.4 (64 bit).
TagsNo tags attached.
FreeCAD Information

Activities

pkoning

2013-09-22 19:11

reporter   ~0003622

For grins, I just tried to use the "cut" operation (deck = deck.cut (solid)). That also does the wrong thing -- it acts like "common".

Ok, so now I have a workaround. Try cut or common, see how it decides to behave for a particular pair of operands; if I get the wrong answer, use the other function.

It's a bit like having + sometimes act like -, depending on which arguments you give it. Very strange indeed.

tanderson69

2013-09-22 19:43

developer   ~0003623

this problem is pretty common. What is happening is your solid is turned inside out. If you do "part/reverse shapes" then the booleans will work as expected.

pkoning

2013-09-22 23:01

reporter   ~0003624

How can a solid be turned inside out? It doesn't LOOK inside out. And what makes it inside out? Does this have to do with the direction in which the edges are drawn? (I remember "even/odd winding rule" and "non-zero winding rule" from PostScript).

This wouldn't be nearly so annoying if it were documented. The API documentation, unfortunately, is nearly nonexistent, and I'm left to discover all these things the hard way. That makes it really difficult to tell a bug from a "feature".

Do other CSG tools (like POVRAY) have this sort of weird behavior? I'm getting tempted to skip FreeCAD and just have my Python scripts generate *.pov files directly instead.

wmayer

2013-09-23 05:35

administrator   ~0003626

In order to boolean operations it is important to know for the algorithm what is inside and what outside, otherwise it shows the symptoms you described.

By default in FreeCAD shapes are rendered that inside and outside looks the same (which is nice for non-solids). But you can change this by selecting the object and choosing "One side" in the property editor for Lighting. Then it will become obvious that your shape has wrong orientation.

pkoning

2013-09-23 13:34

reporter   ~0003642

Ok, that makes sense. So now the question is: HOW do I know what is inside and outside?

I looked around the FreeCAD documentation and found nothing that gives me a clue. So I tried the Povray documentation since that too does CSG. It says that the surface normal points out.

Ok, so my guess is that I ran into trouble because some of the faces have a normal that points out, and some have a normal that points in. I couldn't find any documentation that describes how the normal of a face is determined, either. As a guess, it might be related to the order in which the edges (in my case, the points of the makePolygon) are listed. So I changed that order, and yes, that changes the direction of the normal.

No luck. I now have every face of the solid with an outward-pointing normal, and still I get the wrong solid.

I can hack around this by testing whether a point that's supposed to be inside actually is, and doing solid.reverse() if it isn't. But that's a horrible hack. A user of the API should be able to predict the behavior of the system from well defined rules, and as matters stand right now, that is not the case at all.

wmayer

2013-09-25 14:22

administrator   ~0003668

Your script contains two errors:
The order of the points that create face "tf" must be flipped, i.e:
> tf = Part.Face (Part.makePolygon ([un1, un3, un4, un2, un1]))

Then there is a side effect when mirroring a face: it changes its orientation. The result of this seems that the whole solid has wrong orientation. So, to fix this change your method "mir" to:

def mir (s, v):
    """Given a face or solid, return that mirrored by the supplied vector.
    """
    # To make things confusing, mirror() return a shape, and we need
    # a solid or shape, so extract that.
    ret = s.mirror (origin, v)
    if isinstance (s, Part.Face):
        ret.reverse()
        return ret.Faces[0]
    else:
        return ret.Solids[0]

I do not know if this applies to solids, too. You have to check this.

pkoning

2013-09-26 11:57

reporter   ~0003674

Thanks.

The surprising part is that I tried reversing the order of the edges of the polygon, and that didn't seem to make a difference.

The other problem is that all this appears to be undocumented. It would be good to document how the orientation of a shape is determined, and what that implies for solids built from those shapes.

yorik

2013-11-04 13:47

administrator  

boolbug.py (Attachment missing)

normandc

2014-12-26 18:35

manager   ~0005446

The problem here was caused by an invalid script creating inside out solids, booleans are not at fault so I'm closing this report.

Issue History

Date Modified Username Field Change
2013-09-22 19:07 pkoning New Issue
2013-09-22 19:07 pkoning File Added: boolbug.py
2013-09-22 19:11 pkoning Note Added: 0003622
2013-09-22 19:43 tanderson69 Note Added: 0003623
2013-09-22 23:01 pkoning Note Added: 0003624
2013-09-23 05:35 wmayer Note Added: 0003626
2013-09-23 13:34 pkoning Note Added: 0003642
2013-09-25 14:22 wmayer Note Added: 0003668
2013-09-26 11:57 pkoning Note Added: 0003674
2013-11-04 13:47 yorik File Deleted: boolbug.py
2013-11-04 13:47 yorik File Added: boolbug.py
2014-12-26 18:35 normandc Note Added: 0005446
2014-12-26 18:36 normandc Status new => closed
2014-12-26 18:36 normandc Resolution open => no change required