16 December, 2005
Boolean shapes
Last week, in one of the modules of the creative computing course, we were looking at boolean operations on shapes.
As an illustration, I wrote a little program in Python that could be used to show boolean operations on circles and squares. It was very simple - there was a super class called Shape that implemented methods called and_() or_() xor_() and andnot_(). Subclasses simply had to override the isin() method that, given a tuple containing xy coordinates, returned True for points within the shape and False otherwise.
To display the shape, there was a __repr__() method that scanned a 40 by 40 square of points, printing a hash (#) when the current location fell within the shape. The results of the boolean operations returned a string constructed in the same way.
Anyway, I gave the lecture and we looked at the output. It served its purpose , but I couldn't just leave it alone. The boolean operations, really, should return a Shape object. Then we could write, for example, a.and_(b).xor_(c). But the original code couldn't do this - the isin() method in Circle, for example, checked to see if the given point was within its radius. This wouldn't extend well to shapes that couldn't be calculated simply from a few parameters.
So, I've made a nicer version. Shape now has a list of points that are within it. Each subclass overrides the constructor to set up the initial list, and isin() now just checks the list for the given coordinates. It's made the subclasses a lot simpler, because isin() doesn't need to be overridden any more.
And, now that shapes are simply a list of points that fall within them, the boolean operations can return a Shape object too. So, it's now possible to operate on the results of the boolean operations.
I've also overloaded the operators & | - and / to call and_(), or_(), andnot_() and xor_() respectively, so you can write:
print (s - c)/c2
to show the shape s without c, xor'd with c2.
I know I shouldn't enjoy writing these little programs so much, but I do. I get a kick out of simple things done nicely.
Anyway, the code is in bools.py