This is the tale of a project I recently completed with Saar, my 13-year old son. Saar is interested in the creative aspects of computers (along with playing games, of course). He likes to play around with graphics programs like GIMP and Photoshop, create Flash animations, and compose electronic music. He has also worked on a few games using programs like YoYo Games Game Maker, created some web sites, and built some cool LEGO Mind Storm projects. As a programmer, I tried for years to nudge him towards programming with less than stellar success (my fault for pushing too hard). Recently, I managed to engage him a little more and with the help of a great book Hello World! Computer Programming for Kids and Other Beginners. We worked together through the chapters and exercises and Saar did pretty well.
Then a couple of months ago, Saar suggested that we write a program to compute the area of a polygon. I got very excited because it was much more attainable than his previous ideas (writing a 3-D galactic space strategy game). I estimated it would take us two or three weeks. However, the project turned out to be a perfect example of Hofstadter's law: "It always takes longer than you expect, even when you take into account Hofstadter's Law."
Calculating the area of simple polygons (polygons with no holes) is not as simple as it seems. In addition, we wanted to have a nice UI where you can draw polygons on the screen and see a visualization of the algorithm in action. The complete source code is available here.
In Part 1 of this two-part article, I describe the design and architecture of PolyArea, the implementation of the algorithm itself, and the software development practices we have used. In Part 2 I describe the graphic and UI aspect of PolyArea.
Overall, the project has been a great experience, involving aspects of::
- Pure "research" (looking up formulae and simple algorithms)
- Mini-algorithm implementation like finding the distance between two points, finding the area of a triangle and the intersection of two lines.
- Custom graphics programming
It brought to the front some thorney programming points that bite newbies -- things like floating-point representation, comparing integers to floating-point numbers, and division by zero when computing the slope of a vertical line. It was also a great vehicle for proper software development: how to divide a project to multiple files/modules, writing unit tests to catch bugs early in isolated environment and separation of concerns (algorithmic code vs. visualization code).
The main algorithm (decomposition of the polygon into convex polygons and each convex polygon into triangles) is interesting and demonstrates common issues with computational geometry algorithms.
The user interface is user friendly and validates the polygons that you draw on-the-fly to make sure you don't create invalid polygons (e.g. with holes or intersecting lines).
Polygons are closed geometric shapes made of straight line segments. There are different types of polygons (concave, convex, simple, star shaped, etc). The polygons that the poly area project deals with are simple polygons -- the polygon sides don't cross themselves and contain no holes.
There are formulas for finding the area of a polygon given a set of vertices or the length of each side, but these are no fun (see http://en.wikipedia.org/wiki/Polygon). A much more educational endeavor is to find the area by dividing the polygon to smaller polygons and in particularly into triangles and then adding the area of the triangles. This is called "Polygon Triangulation" and there are several algorithms that accomplish this task. The algorithm we implement in this project is a little different for pedagogical reasons. The main motivation for this project is the creation process itself and coming up with an algorithm that is visually pleasing to track its progress.
The Poly Area Project
There are three main parts to the Poly Area Project:
- The Algorithmic core that deals with breaking a polygon to triangles. The algorithm uses several mini algorithms like finding the area of a triangle given its sides and the distance between two points. These mini algorithms are a perfect task for a beginner like Saar to experiment with.
- The UI is responsible for letting users draw the polygon and to paint it gradually when the polygon is complete. It turned out to be surprisingly complicated and it took awhile to get it right.
- PyGame is a cross-platform Python binding for the famous SDL (Simple DirectMedia Layer) game development library: http://www.libsdl.org/. It is used as the low-level graphics library for the project. The reason we chose PyGame and not a more standard graphics library like wxPython is that Saar was somewhat familiar with PyGame from the "Hello World" book.
We tried to build the program in a fairly disciplined fashion and use best practices even though it is a small project. For a newbie who only programmed several programming exercises it is a big project with multiple files and custom UI.
The programming language is, of course, Python. (Again, the complete Python source code for the project is available here.) I would go on a limb and say that Python is arguably the most scalable programming language from a learning perspective. It is one of the most readable and easy to learn programming languages, yet it can be used for enterprise-grade software projects too. It has excellent support for modular programming, object-oriented programming, good documentation, lots of third-party packages (many bindings for high-performance C/C++ libraries), great community and great IDEs. It is being used heavily by big players like Google, Nasa, YouTube (even before being bought by Google), Industrial Light and Magic. Don't forget Numenta (my company).
There are broadly speaking two schools of program design: top-down and bottom-up. Top-down means that you think about the big pieces of your program and how to connect them and then you take each piece and repeat the process of decomposition until you reach to pieces small enough to implement directly. The bottom-up approach is the opposite. You start with the smallest pieces, implement them and then combine them to bigger pieces and you keep going until you have the full-fledged program. Both approaches represent extremes that usually can't work for real-world programs (although pure bottom-up is much more practical). The approach we took in this project, which is the approach I prefer for most projects is a mostly bottom-up, but after I have in my mind the overall structure of the program. It is much easier to grow a program from small pieces that you can hook up together in flexible ways then trying to figure out all the interactions first (as required by top-down programming).
Unit testing is a staple of modern software development. Bottom-up programing lends itself naturally to unit testing because you develop small units in isolation that can be tested and then you combine them. Even-though poly area is a pretty small project we used unit testing for the algorithmic core.
The UI and PyGame support code has no tests and as a result I spent a considerable amount of time chasing bugs in the UI. Saar did a great job finding and pointing out these UI bugs. I think for a project of this size it is the right choice to test the UI manually. Automated UI testing is possible, but requires more effort and the cost/benefit ratio should be taken into account. For projects with significant UI that changes often it may be worthwhile to invest in a good automated UI test suite.