/ examples / multiplication_puzzle..scad
multiplication_puzzle..scad
  1  piece_side_length = 25;
  2  // for n x n multiplication puzzle
  3  n = 9; // [1:9]
  4  spacing = 0.5;
  5  
  6  same_height = "NO"; // [YES, NO]
  7  height = 1;       // workable when same_height is "YES"
  8  
  9  module puzzle_piece(side_length, spacing) {
 10  	$fn = 48;
 11  
 12  	circle_radius = side_length / 10;
 13  	half_circle_radius = circle_radius / 2;
 14      half_side_length = side_length / 2;
 15  	side_length_div_4 = side_length / 4;
 16  	bulge_circle_radius = circle_radius - spacing;
 17  
 18      circle_x = half_circle_radius - half_side_length - spacing;
 19      circle_y = side_length_div_4 - half_side_length;
 20      circle_y2 = side_length_div_4 * 3 - half_side_length;
 21      
 22      module df_circles() {
 23          translate([circle_x, circle_y]) 
 24              circle(circle_radius);
 25          translate([circle_x, circle_y2]) 
 26              circle(circle_radius);
 27      }
 28      
 29      module bulge_circles() {
 30          translate([side_length + circle_x, circle_y]) 
 31              circle(bulge_circle_radius);
 32          translate([side_length + circle_x, circle_y2]) 
 33              circle(bulge_circle_radius);    
 34      }
 35  
 36      translate([half_side_length - spacing, half_side_length - spacing]) {
 37          difference() {
 38              square(side_length - spacing, center = true);            
 39              // left
 40              df_circles();
 41              // top
 42              rotate(-90) 
 43                  df_circles();       
 44          }
 45  
 46          // right
 47          bulge_circles();
 48          // bottom
 49          rotate(-90) 
 50              bulge_circles();
 51      }
 52  }
 53  
 54  module puzzle_piece_with_text(side_length, text, spacing) {
 55      half_side_length = side_length / 2;
 56  	
 57      difference() {
 58  		puzzle_piece(side_length, spacing);
 59  		translate([half_side_length, half_side_length]) 
 60          rotate(-45) 
 61              text(text, size = side_length / 3, halign = "center", valign = "center");
 62  	}
 63  }
 64  
 65  module multiplication_puzzle(n, piece_side_length, spacing, same_height = false, height = 1) {
 66      $fn = 48;
 67  	circle_radius = piece_side_length / 10;
 68  	half_circle_radius = circle_radius / 2;
 69  	side_length_div_4 = piece_side_length / 4;
 70      n_minus_one = n - 1;
 71  	
 72  	intersection() {
 73  		union() for(x = [0 : n_minus_one], y = [0 : n_minus_one]) {
 74              pos = [piece_side_length * x, piece_side_length * y];
 75              r = (x + 1) * (y + 1);
 76              linear_extrude(same_height ? height : r) union() {
 77                  translate(pos) 
 78                      puzzle_piece_with_text(piece_side_length, str(r), spacing);
 79                      
 80                  if(x == 0) {
 81                      x_offset = half_circle_radius - spacing * 2;
 82                      y_offset = piece_side_length * y - spacing;
 83                      translate([x_offset, side_length_div_4 + y_offset, 0]) 
 84                          circle(circle_radius);
 85                      translate([x_offset, side_length_div_4 * 3 + y_offset, 0]) 
 86                          circle(circle_radius);			
 87                  }
 88                  if(y == n_minus_one) {
 89                      x_offset = piece_side_length * x - spacing;
 90                      y_offset = piece_side_length * (y + 1) - half_circle_radius;
 91                      translate([side_length_div_4 + x_offset, y_offset]) 
 92                          circle(circle_radius);
 93                      translate([side_length_div_4 * 3 + x_offset, y_offset]) 
 94                          circle(circle_radius);	
 95  
 96                  }
 97              }
 98              linear_extrude((same_height ? height : r) - 0.6) 
 99              translate(pos) 
100                  puzzle_piece(piece_side_length, spacing);
101  		}
102  		
103  		linear_extrude(same_height ? height : n * n) 
104              square(piece_side_length * n - spacing * 1.5);
105  	}
106  }
107  
108  multiplication_puzzle(n, piece_side_length, spacing, same_height == "YES", height);