diff options
author | Philip Withnall <philip@tecnocode.co.uk> | 2013-08-16 20:09:44 (GMT) |
---|---|---|
committer | Philip Withnall <philip@tecnocode.co.uk> | 2013-08-16 20:09:44 (GMT) |
commit | ccf35761bca15c7f3524f3c38de820c9a05b9ec7 (patch) | |
tree | de4388b457a0b05a2ba930f700ac686edcc5a24a /PascalTriangle.activity/pascaltriangle.py | |
parent | de301fe72296f113da2439d859cd73ea244c0151 (diff) |
Implement drawing a Pascal triangle
This uses very basic graphics and is not yet interactive.
Diffstat (limited to 'PascalTriangle.activity/pascaltriangle.py')
-rwxr-xr-x | PascalTriangle.activity/pascaltriangle.py | 60 |
1 files changed, 59 insertions, 1 deletions
diff --git a/PascalTriangle.activity/pascaltriangle.py b/PascalTriangle.activity/pascaltriangle.py index 825fc9f..2acd364 100755 --- a/PascalTriangle.activity/pascaltriangle.py +++ b/PascalTriangle.activity/pascaltriangle.py @@ -26,10 +26,68 @@ class PascalTriangleActivity(activity.Activity): # The final step is to display this newly created widget. self.drawing_area.show() + # Set the initial size of the Pascal triangle to be drawn. This is + # the number of cells on its base (equivalently, the number of rows in + # the triangle). + self.triangle_size = 5 + + + """ + Calculate the Pascal number for the (row, column) cell, where row and column + are both 0-based. This is equivalent to calculating the Binomial coefficient + of (row choose column). + """ + def _calculate_pascal_number(self, row, column): + num = math.factorial(row) + denom = math.factorial(column) * math.factorial(row - column) + return num / denom + def _drawing_area_button_press_cb(self, widget, event, data = None): pass def _drawing_area_draw_cb(self, widget, ctx, data = None): - return False + # Default sizes (Cairo units). + padding = 10.0 + + # Widget allocation. + widget_height = widget.get_allocated_height() + base_width = widget.get_allocated_width() - 2.0 * padding + triangle_height = widget_height - 2.0 * padding + cell_width = base_width / self.triangle_size + cell_height = triangle_height / self.triangle_size + + # Draw the triangle rows from the top down. The row_order is the number + # of cells in the row (increasing from 1 to triangle_size, inclusive). + row_order = 1 + # X position of the first cell on the row + cell_start_x = padding + base_width / 2.0 - cell_width / 2.0 + + for row_index in range(self.triangle_size): + for column_index in range(row_order): + # Calculate the cell position. Add an offset every odd row so + # the triangle is balanced. + cell_x = cell_start_x + cell_width * column_index + cell_y = padding + cell_height * row_index + + # Draw the cell and fill it. + ctx.rectangle(cell_x, cell_y, cell_width, cell_height) + ctx.set_source_rgb(0.0, 0.0, 0.0) + ctx.stroke_preserve() + ctx.set_source_rgb(1.0, 1.0, 1.0) + ctx.fill() + + # Write its number. + cell_number = self._calculate_pascal_number(row_index, + column_index) + extents = ctx.text_extents(str(cell_number)) + ctx.move_to(cell_x + (cell_width - extents[2]) / 2.0, + cell_y + (cell_height - extents[3]) / 2.0) + ctx.set_source_rgb(0.0, 0.0, 0.0) + ctx.show_text(str(cell_number)) + + cell_start_x -= cell_width / 2.0 + row_order += 1 + + return True |