KGRKJGETMRETU895U-589TY5MIGM5JGB5SDFESFREWTGR54TY
Server : Apache/2.4.62
System : FreeBSD fbsdweb2.web.rcn.net 14.1-RELEASE FreeBSD 14.1-RELEASE releng/14.1-n267679-10e31f0946d8 GENERIC amd64
User : www ( 80)
PHP Version : 8.3.8
Disable Function : NONE
Directory :  /domains/gohover/cell/paprica/uploadtestfolder/Current Code/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /domains/gohover/cell/paprica/uploadtestfolder/Current Code/periodic_and_spiral_tiling_code.js





      


// don't forget to revist http://paulbourke.net/texture_colour/tilingplane/
   


//   Note:  find largest cell size in sample rather than average size.  Delete this comment when completed.


 function TArray_make_square_tiling(xmax, ymax) {
 var tilingarray = [] 
  for (var i = 0; i <xmax; i++) {
     for (var j = 0; j<ymax; j++) {
        tilingarray.push ([[i,j], [i+1, j],[ i+1, j+1], [i, j+1]]);
     }
  }
return tilingarray
}


function TArray_make_tetrakis_square_tiling(xmax, ymax) {
 var tilingarray = [] 
  var both;
  for (var i = 0; i <xmax; i++) {
     for (var j = 0; j<ymax; j++) {
        both = (i % 2) + (j % 2)
        if (both % 2) { // the odd case
            tilingarray.push ([[i,j], [i+1, j],[ i+1, j+1]]);
            tilingarray.push ([[i,j], [i+1, j+1],[ i, j+1]]);
         }
        else {  // the even case
            tilingarray.push ([[i,j], [i+1, j],[ i, j+1]]);
            tilingarray.push ([[i+1,j], [i+1, j+1],[ i, j+1]]);

        }
      }
    }
return tilingarray

}


function TArray_make_cairo_tiling(xmax, ymax) {
 var tilingarray = [] 

  var both;
  var inset = .94
  var a = 1.6
  var i,j
  for (var ii = 0; ii <xmax; ii++) {
     for (var jj = 0; jj<ymax; jj++) {
        both = (ii % 2) + (jj % 2)
        i = ii*3.2
        j = jj*3.2
        if (both % 2) { // the odd case
            tilingarray.push ([[i,j], [i+a,j+inset], [i+a,j+2*a-inset], [i,j+2*a], [i-inset,j+a]]);   // pointed left
            tilingarray.push  ([[i+a,j+inset], [i+2*a, j],[ i+2*a+inset, j+a],[i+2*a,j+2*a],[i+a,j+2*a-inset]]); // pointed right
         }
        else {  // the even case
            tilingarray.push  ([[i,j], [i+a,j-inset],[i+2*a,j],[i+2*a-inset,j+a],[i+inset,j+a]]);  // pointed up
            tilingarray.push  ([[i+inset,j+a],[i+2*a-inset,j+a],[i+2*a,j+2*a],[i+a,j+2*a+inset],[i,j+2*a]]);  // pointed down
        }
      }
    }
return tilingarray

}   



function TArray_make_hexagonal_tiling_from_triangles (xmax, ymax) { 
 var tilingarray = [] 
 var x,y;
 var height = Math.sqrt(3)/2
 xmax = Math.floor(xmax/1.5) // to prevent twice as many columns as requested
 ymax = Math.floor(ymax*1.5) // to prevent half as many rows as requested
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<ymax; j+=1) {
       if (j % 2) { // the odd case
          y = j*height-height*2
          x = i*3+1.5
        }
       else { // the even case
          y = j*height
          x = i*3
       }
       // creates hexagons with flat tops and bottoms.  Swap x and y for pointy tops and bottoms. 
       tilingarray.push ([[x,y], [x+0.5, y-height], [x+1.5, y-height], [x+2,y], [x+1.5, y+height], [x+0.5, y+height]]);     
       
     }
 }
return tilingarray
}


function TArray_make_regular_triangular_tiling (xmax, ymax) {
 var tilingarray = [] 
 var x,y;
 var height = Math.sqrt(3)/2
 for (var x = 1; x <xmax; x++) {
     for (var j = 1; j<ymax; j+=2) {
          y = j*height
          tilingarray.push ([[x,y], [x+1,y], [x+0.5, y-height]]);
          tilingarray.push ([[x,y], [x+1,y], [x+0.5, y+height]]);

          tilingarray.push ([[x+0.5, y-height], [x+1,y], [x+1.5, y-height]]);
          tilingarray.push ([[x+0.5, y+height], [x+1,y], [x+1.5, y+height]]);
         
     }
 }
return tilingarray
}

function TArray_make_regular_rhombic_tiling (xmax, ymax) {  
 var tilingarray = [] 
 var x,y;
 var centerx, centery
 var height = Math.sqrt(3)/2
 xmax = Math.floor(xmax/1.5) // to prevent twice as many columns as requested
 ymax = Math.floor(ymax*1.5) // to prevent half as many rows as requested
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<ymax; j+=1) {
       if (j % 2) { // the odd case
          y = j*height-height*2
          x = i*3+1.5
        }
       else { // the even case
          y = j*height 
          x = i*3 
       }
       centerx = x + 1
       centery = y
       // creates hexagons with flat tops and bottoms.  Swap x and y for pointy tops and bottoms. 
       tilingarray.push ([[x,y], [x+0.5, y-height], [x+1.5, y-height], [centerx, centery]]);     
       tilingarray.push ( [[x+1.5, y-height], [x+2,y], [x+1.5, y+height], [centerx, centery]]);  
       tilingarray.push ([[x,y], [centerx, centery], [x+1.5, y+height], [x+0.5, y+height]]);  
     }
 }
 return tilingarray
}


function TArray_make_deltoidal_trihexagonal_tiling (xmax, ymax) {
 var tilingarray = [] 
 var x,y;
 var height = Math.sqrt(3)/2
 xmax = Math.floor(xmax/1.5) // to prevent twice as many columns as requested
 ymax = Math.floor(ymax*1.5) // to prevent half as many rows as requested
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<ymax; j+=1) {
       if (j % 2) { // the odd case
          y = j*height-height*2
          x = i*3+1.5
        }
       else { // the even case
          y = j*height
          x = i*3
       }
       // creates hexagons with flat tops and bottoms.  Swap x and y for pointy tops and bottoms. 
       //tilingarray.push ([[x,y], [x+0.5, y-height], [x+1.5, y-height], [x+2,y], [x+1.5, y+height], [x+0.5, y+height]], "hexagon");  
       //                          v1         v2               v3                v4       v5                 v6   
                  // the center is [x+1, y]
                  // v1.5 = [x+0.25, y-height/2]
                  // v2.5 = [x+1, y-height]
                  // v3.5 = [x+1.75, y-height/2]
                  // v4.5 = [x+1.75, y+height/2]
                  // v5.5 = [x+1, y+height]
                  // v6.5 = [x+0.25, y+height/2]
                  
                    tilingarray.push ([ [x+0.25, y+height/2], [x,y], [x+0.25, y-height/2],  [x+1, y] ]);            // v6.5, v1, v1.5, center
                    tilingarray.push ([ [x+0.25, y-height/2],  [x+0.5, y-height], [x+1, y-height],   [x+1, y]]);    // v1.5, v2, v2.5, center
                       tilingarray.push ([  [x+1, y-height], [x+1.5, y-height], [x+1.75, y-height/2],  [x+1, y]]);  // v2.5, v3, v3.5, center
                       tilingarray.push ([  [x+1.75, y-height/2], [x+2,y],  [x+1.75, y+height/2],   [x+1, y]]);     // v3.5, v4, v4.5, center
                       tilingarray.push ([  [x+1.75, y+height/2],  [x+1.5, y+height],  [x+1, y+height],  [x+1, y]]); //  v4.5, v5, v5.5, center
                       tilingarray.push ([  [x+1, y+height],  [x+0.5, y+height],[x+0.25, y+height/2],  [x+1, y]]);  //  v5.5, v6, v6.5, center

     }
 }
 return tilingarray
}

function TArray_make_floret_pentagonal_tiling (xmax, ymax) {  
 var tilingarray = [] 
 var x,y;
 var height = Math.sqrt(3)/2
 xmax = Math.floor(xmax/1.66667) 
 ymax = Math.floor(ymax/1.66667) 
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<ymax; j+=1) {
          y = ( ( 5/2) * i - 0.5*j   ) * 2 * height                                   // j*height * 3   * 1.333333333333333
          x = ( -(Math.sqrt(3)/2)*i + 3*(Math.sqrt(3))/2*j  ) * 2 *height          // i*3 *2.15  +y    
        if (x > 0 && y > 0 && x <xmax*3 && y<ymax*3)  {
 
      // // 7 hexagons, with center one missing
      //     and the missing center hexagon has its own center at [x+1, y]
     // then convert them to pentagons

       tilingarray.push ([[x,y-2*height], [x+0.5, y-height-2*height], [x+1.5, y-height-2*height], [x+2,y-2*height],[x+1, y] ]);   // topmost pentagon  
       tilingarray.push ([[x-1.5,y-1*height], [x+0.5-1.5, y-height-1*height], [x+1.5-1.5, y-height-1*height],[x+1, y], [x+0.5-1.5, y+height-1*height]]);     // left top
       tilingarray.push ([[x+1, y], [x+0.5+1.5, y-height-1*height], [x+1.5+1.5, y-height-1*height], [x+2+1.5,y-1*height], [x+1.5+1.5, y+height-1*height], ]);     // right top
       tilingarray.push ([[x-1.5,y+1*height], [x+0.5-1.5, y-height+1*height], [x+1, y], [x+1.5-1.5, y+height+1*height], [x+0.5-1.5, y+height+1*height]]);     // left bottom
       tilingarray.push ([[x+1, y], [x+1.5+1.5, y-height+1*height], [x+2+1.5,y+1*height], [x+1.5+1.5, y+height+1*height], [x+0.5+1.5, y+height+1*height]]);     // right bottom
       tilingarray.push ([[x,y+2*height], [x+1, y], [x+2,y+2*height], [x+1.5, y+height+2*height], [x+0.5, y+height+2*height]]);   // bottommost pentagon  
       }
     }
 }
 return tilingarray
}


 
function TArray_make_kisrhombille_tiling (xmax, ymax) {
 var tilingarray = [] 
 var x,y;
 var height = Math.sqrt(3)/2
 xmax = Math.floor(xmax/1.5) // to prevent twice as many columns as requested
 ymax = Math.floor(ymax*1.5) // to prevent half as many rows as requested
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<ymax; j+=1) {
       if (j % 2) { // the odd case
          y = j*height-height*2
          x = i*3+1.5
        }
       else { // the even case
          y = j*height
          x = i*3
       }
       // creates hexagons with flat tops and bottoms.  Swap x and y for pointy tops and bottoms. 
       //tilingarray.push ([[x,y], [x+0.5, y-height], [x+1.5, y-height], [x+2,y], [x+1.5, y+height], [x+0.5, y+height]], "hexagon");  
       //                          v1         v2               v3                v4       v5                 v6   
                  // the center is [x+1, y]
                  // v1.5 = [x+0.25, y-height/2]
                  // v2.5 = [x+1, y-height]
                  // v3.5 = [x+1.75, y-height/2]
                  // v4.5 = [x+1.75, y+height/2]
                  // v5.5 = [x+1, y+height]
                  // v6.5 = [x+0.25, y+height/2]
                  
                    tilingarray.push ([ [x+0.25, y+height/2], [x,y],  [x+1, y] ]);            // v6.5, v1, v1.5, center
                    tilingarray.push ([ [x+0.25, y-height/2],  [x+0.5, y-height],   [x+1, y]]);    // v1.5, v2, v2.5, center
                    tilingarray.push ([  [x+1, y-height], [x+1.5, y-height],  [x+1, y]]);  // v2.5, v3, v3.5, center
                    tilingarray.push ([  [x+1.75, y-height/2], [x+2,y],    [x+1, y]]);     // v3.5, v4, v4.5, center
                    tilingarray.push ([  [x+1.75, y+height/2],  [x+1.5, y+height],   [x+1, y]]); //  v4.5, v5, v5.5, center
                    tilingarray.push ([  [x+1, y+height],  [x+0.5, y+height], [x+1, y]]);  //  v5.5, v6, v6.5, center


                    tilingarray.push ([ [x,y], [x+0.25, y-height/2],  [x+1, y] ]);            // v1, v1.5, center, v6.5
                    tilingarray.push ([  [x+0.5, y-height], [x+1, y-height],   [x+1, y]]);    // v1.5, v2, v2.5, center
                    tilingarray.push ([  [x+1.5, y-height], [x+1.75, y-height/2],  [x+1, y]]);  // v2.5, v3, v3.5, center
                    tilingarray.push ([   [x+2,y],  [x+1.75, y+height/2],   [x+1, y]]);     // v3.5, v4, v4.5, center
                    tilingarray.push ([  [x+1.5, y+height],  [x+1, y+height],  [x+1, y]]); //  v4.5, v5, v5.5, center
                    tilingarray.push ([   [x+0.5, y+height],[x+0.25, y+height/2],  [x+1, y]]);  //  v5.5, v6, v6.5, center

     }
 }
 return tilingarray
}




function TArray_make_triakis_triangular_tiling(xmax, ymax) {
 var tilingarray = [] 
 var x,y;
 var height = Math.sqrt(3)/2
 xmax = Math.floor(xmax/1.5/2.5) // to prevent twice as many columns as requested
 ymax = Math.floor(ymax*1.5/2.5) // to prevent half as many rows as requested
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<ymax; j+=1) {
       if (j % 2) { // the odd case
          y = j*height-height*2
          x = i*3+1.5
        }
       else { // the even case
          y = j*height
          x = i*3
       }
       // creates hexagons with flat tops and bottoms.  Swap x and y for pointy tops and bottoms. 

          tilingarray.push  ([ [x,y], [x+0.5, y-height], [x+1.5, y-height]]);  // v1, v2, v3
          tilingarray.push  ([  [x+1.5, y-height], [x+2,y], [x+1.5, y+height]]); // v3, v4, v5
          tilingarray.push  ([[x+1.5, y+height], [x+0.5, y+height], [x,y] ]);  // v5, v6, v1
           // the center is [x+1, y]
          tilingarray.push  ([ [x,y],  [x+1, y], [x+1.5, y-height]]);                // v1, center, v3
          tilingarray.push  ([  [x+1.5, y-height],  [x+1, y], [x+1.5, y+height]]); // v3, center, v5
          tilingarray.push  ([[x+1.5, y+height],  [x+1, y], [x,y] ]);             // v5, center, v1

       
     }
 }
 return tilingarray
}

function TArray_make_prismatic_pentagonal_tiling(xmax, ymax) {
 var tilingarray = [] 
 var x,y
 var height = Math.sqrt(3)/2
 var w1 = 1
 var w2 = w1/2
 var h1 = 1
 var h2 = (height + 0 + 0)/3
 xmax = Math.floor(xmax) // to prevent twice as many columns as requested
 ymax = Math.floor(ymax/2) // to prevent half as many rows as requested
 for (var x = 1; x <xmax; x++) {
     for (var j = 1; j<ymax; j+=2) {
          y = j*(h1+h2+h1)
          tilingarray.push ([[x,y], [x, y-h1], [x+w2, y-h1-h2], [x+w1, y-h1], [x+w1, y]])
          tilingarray.push ([[x,y], [x, y+h1], [x+w2, y+h1+h2], [x+w1, y+h1], [x+w1, y]])
          y = y + h1 + h2+h1
          tilingarray.push ([[x+w2,y], [x+w2, y-h1], [x+w2+w2, y-h1-h2], [x+w2+w1, y-h1], [x+w2+w1, y]])
          tilingarray.push ([[x+w2,y], [x+w2, y+h1], [x+w2+w2, y+h1+h2], [x+w2+w1, y+h1], [x+w2+w1, y]])
     }
 }
return tilingarray
}

 
function TArray_make_trihexagonal_tiling(xmax, ymax) {  
 var tilingarray = [] 
 var x,y;
 var height = Math.sqrt(3)/2
// xmax = Math.floor(xmax/1.5) // to prevent twice as many columns as requested
// ymax = Math.floor(ymax*1.5) // to prevent half as many rows as requested
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<ymax; j+=1) {
       if (j % 2) { // the odd case
          y = (j*height-height*2)*2
          x = (i*3+1.5)*2/3         
        }
       else { // the even case
          y = j*height*2
          x = i*2
       }
       tilingarray.push  ([[x,y], [x+0.5, y-height], [x+1.5, y-height], [x+2,y], [x+1.5, y+height], [x+0.5, y+height]]);     
       tilingarray.push  ([[x,y], [x+0.5, y-height], [x-0.5, y-height]]);
       tilingarray.push  ([[x+2,y], [x+1.5, y+height], [x+2.5, y+height]]);     
     }
 }
return tilingarray
}

function TArray_make_martini_lattice_tiling (xmax, ymax) {  
 var tilingarray = [] 
 var x,y;
 var height = Math.sqrt(3)/2
 xmax = Math.floor(xmax/1.5) // to prevent twice as many columns as requested
 ymax = Math.floor(ymax*1.5) // to prevent half as many rows as requested
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<ymax; j+=1) {
       if (j % 2) { // the odd case
          y = j*height-height*2
          x = i*3+1.5
        }
       else { // the even case
          y = j*height
          x = i*3
       }
       // creates hexagons with flat tops and bottoms.  Swap x and y for pointy tops and bottoms. 
        tilingarray.push ([[x+0.5/2, y-height/2], [x+0.5, y-height], [x+1, y-height], [x+1.75,y-height/2], [x+2,y], [x+1.75, y+height/2], [x+1, y+height], [x+0.5, y+height],[x+0.5/2, y+height/2]]);  
        tilingarray.push ([[x-0.5,y],[x+0.5/2, y-height/2], [x+0.5/2, y+height/2]]);    
       
     }
 }
  return tilingarray
}


// ======================================= MeshMakers ============================================

// example of use:       build_verts_and_faces ([[0,0], [x2, y2],[ x3, y3], [x4, y4]], "rhomb");


function make_square_tiling(xmax, ymax) {
  for (var i = 0; i <xmax; i++) {
     for (var j = 0; j<ymax; j++) {
        build_verts_and_faces ([[i,j], [i+1, j],[ i+1, j+1], [i, j+1]], "square");
     }
  }

}

function make_tetrakis_square_tiling(xmax, ymax) {
  var both;
  for (var i = 0; i <xmax; i++) {
     for (var j = 0; j<ymax; j++) {
        both = (i % 2) + (j % 2)
        if (both % 2) { // the odd case
            build_verts_and_faces ([[i,j], [i+1, j],[ i+1, j+1]], "triangle");
            build_verts_and_faces ([[i,j], [i+1, j+1],[ i, j+1]], "triangle");
         }
        else {  // the even case
            build_verts_and_faces ([[i,j], [i+1, j],[ i, j+1]], "triangle");
            build_verts_and_faces ([[i+1,j], [i+1, j+1],[ i, j+1]], "triangle");

        }
      }
    }
}

// a different way to make cairo tiling
// Here are voronoi derved cords via snub square
// pointed up:  [260.1, 240, 276.1, 230.6, 292.1, 240, 282.7, 256, 269.5, 256]
// pointed down: [260.1, 272, 269.5, 256, 282.7, 256, 292.1, 272, 276.1, 281.4]
// pointed right: [244.1, 249.4, 260.1, 240, 269.5, 256, 260.1, 272, 244.1, 262.6]
// pointed left: [282.7, 256, 292.1, 240, 308.1, 249.4, 308.1, 262.6, 292.1, 272]

/*
function make_cairo_tiling(xmax, ymax) {
  var both;
  var inset = 0.2
  for (var i = 0; i <xmax; i=i+32) {
     for (var j = 0; j<ymax; j=j+32) {
        both = (i % 2) + (j % 2)
        if (both % 2) { // the odd case
       //     build_verts_and_faces ([[i,j], [i+0.5,j+inset], [i+0.5,j+1-inset], [i,j+1], [i-inset,j+0.5]], "pent");   // pointed left
       //     build_verts_and_faces ([[i+0.5,j+inset], [i+1, j],[ i+1+inset, j+0.5],[i+1,j+1],[i+0.5,j+1-inset]], "pent"); // pointed right
         }
        else {  // the even case
                // pointed up:  [260.1, 240,    276.1, 230.6,    292.1, 240,    282.7, 256,    269.5, 256]

            build_verts_and_faces ([[i,j], [i+16,j-9.4],[i+32,j],[i+22.6,j+16],[i+9.4,j+16]], "pent");  // pointed up


     //     build_verts_and_faces ([[i,j], [i+0.5,j-inset],[i+1,j],[i+1-inset,j+0.5],[i+inset,j+0.5]], "pent");  // pointed up


  i + 1 - inset got replaced with 22.6 and inset = 9.4;   22.6 - 9.4 = 13.2   but +1 got replaced with  32, and 32 - 9.4 = 22.6 ha!

 so replace 1 with 32 and inset with 9.4 ==> done!

           build_verts_and_faces ([[i+inset,j+16],[i+1-inset,j+16],[i+1,j+1],[i+16,j+1+inset],[i,j+1]], "pent");  // pointed down
        }
      }
    }
}    
*/


function make_cairo_tiling(xmax, ymax) {
  var both;
  var inset = .94
  var a = 1.6
  var i,j
  for (var ii = 0; ii <xmax; ii++) {
     for (var jj = 0; jj<ymax; jj++) {
        both = (ii % 2) + (jj % 2)
        i = ii*3.2
        j = jj*3.2
        if (both % 2) { // the odd case
            build_verts_and_faces ([[i,j], [i+a,j+inset], [i+a,j+2*a-inset], [i,j+2*a], [i-inset,j+a]], "pent");   // pointed left
            build_verts_and_faces ([[i+a,j+inset], [i+2*a, j],[ i+2*a+inset, j+a],[i+2*a,j+2*a],[i+a,j+2*a-inset]], "pent"); // pointed right
         }
        else {  // the even case
            build_verts_and_faces ([[i,j], [i+a,j-inset],[i+2*a,j],[i+2*a-inset,j+a],[i+inset,j+a]], "pent");  // pointed up
            build_verts_and_faces ([[i+inset,j+a],[i+2*a-inset,j+a],[i+2*a,j+2*a],[i+a,j+2*a+inset],[i,j+2*a]], "pent");  // pointed down
        }
      }
    }
}         

/* The was the original Cairo tiling - where I tried to make the sides more equal.  The pentagons end up looking flattened.
function make_cairo_tiling(xmax, ymax) {
  var both;
  var inset = 0.2
  for (var i = 0; i <xmax; i++) {
     for (var j = 0; j<ymax; j++) {
        both = (i % 2) + (j % 2)
        if (both % 2) { // the odd case
       //     build_verts_and_faces ([[i,j], [i+0.5,j+inset], [i+0.5,j+1-inset], [i,j+1], [i-inset,j+0.5]], "pent");   // pointed left
       //     build_verts_and_faces ([[i+0.5,j+inset], [i+1, j],[ i+1+inset, j+0.5],[i+1,j+1],[i+0.5,j+1-inset]], "pent"); // pointed right
         }
        else {  // the even case
            build_verts_and_faces ([[i,j], [i+0.5,j-inset],[i+1,j],[i+1-inset,j+0.5],[i+inset,j+0.5]], "pent");  // pointed up
      //      build_verts_and_faces ([[i+inset,j+0.5],[i+1-inset,j+0.5],[i+1,j+1],[i+0.5,j+1+inset],[i,j+1]], "pent");  // pointed down
        }
      }
    }
}         
*/


 // octogons and squares -- see RhombSquareOctogon code for a stretched out explanation of how the octogon code works.

function make_truncated_square_tiling(xmax, ymax) {   
  var L = 1;  // L is the sidelength   // var centerx = (L + L*Math.sqrt(2))/2; // var centery =  L/2;
  var z = L * Math.sqrt(2)/2;
  var ii, jj, ioffset;
  xmax = xmax/2  // to prevent twice as many columns as requested
  for (var i = 0; i <xmax; i++) {
     for (var j = 0; j<ymax; j++) {
        ii =  i*(L +z * 2 + L)
        jj =  j*(L + z )
        ioffset = ii + L + z
        if (j % 2) { // for odd rows
          build_verts_and_faces ([[ioffset,jj], [ioffset-L,jj], [ioffset-L,jj+L], [ioffset,jj+L]], "square");
          build_verts_and_faces ([[ioffset,jj], [ioffset, L+jj],[ z+ioffset, L+z+jj], [L+z+ioffset, L+z+jj], 
                                  [L+z*2+ioffset, L+jj], [L+z*2+ioffset, jj], [L+z+ioffset, -z+jj], [z+ioffset, -z+jj] ], "octagon");
        }
        else {  // for even rows 
          build_verts_and_faces ([[ii,jj], [ii, L+jj],[ z+ii, L+z+jj], [L+z+ii, L+z+jj], 
                                  [L+z*2+ii, L+jj], [L+z*2+ii, jj], [L+z+ii, -z+jj], [z+ii, -z+jj] ], "octagon");
          build_verts_and_faces ([[L+z*2+ii, jj], [L+z*2+ii+L, jj],[L+z*2+ii+L, jj+L], [L+z*2+ii, jj+L]], "square");
        }
     }
   }
}

function make_snub_square_tiling(xmax, ymax) {
 var a = 2/(1+Math.sqrt(3)); // sidelength when imposed on a square grid with sielengths of 1
 var b = a/2;
 var h = a/2*Math.sqrt(3);
 for (var i = 1; i <xmax; i+=2) {
     for (var j = 1; j<ymax; j+=2) {
       build_verts_and_faces ([[i-b,j], [i,j-h], [i+b,j]], "triangle");
       build_verts_and_faces ([[i-b,j], [i,j+h], [i+b,j]], "triangle");
       build_verts_and_faces ([[i+b,j], [i+b+h,j-b], [i+b+h,j+b]], "triangle");
       build_verts_and_faces ([[i+b+h,j-b], [i+b+h+h,j], [i+b+h,j+b]], "triangle");

       build_verts_and_faces ([[i-h,j+1], [i,j-b+1], [i,j+b+1]], "triangle");
       build_verts_and_faces ([[i+h,j+1], [i,j-b+1], [i,j+b+1]], "triangle");

       build_verts_and_faces ([[i+h,j+1], [i+h+b,j+1-h], [i+h+b+b,j+1]], "triangle");
       build_verts_and_faces ([[i+h,j+1], [i+h+b,j+1+h], [i+h+b+b,j+1]], "triangle");

       build_verts_and_faces ([[i+b,j], [i,j-h], [i+h,j-h-b], [i+h+b, j-b]], "square");
       build_verts_and_faces ([[i+b+h+h,j], [i+b+h,j-b], [i+h+b+b,j-h-b], [i+h+b+h+b, j-h]], "square");

       build_verts_and_faces ([[i+h,j+1], [i,j-b+1], [i+b,j-h-b+1], [i+h+b, j-h+1]], "square");
       build_verts_and_faces ([[i+b+b+h,j+1], [i+b+h,j-h+1], [i+h+h+b,j-h-b+1], [i+h+b+h+b, j-b+1]], "square");

     }
 }
}







function make_regular_triangular_tiling (xmax, ymax) {
 var x,y;
 var height = Math.sqrt(3)/2
 for (var x = 1; x <xmax; x++) {
     for (var j = 1; j<ymax; j+=2) {
          y = j*height
          build_verts_and_faces ([[x,y], [x+1,y], [x+0.5, y-height]], "triangle");
          build_verts_and_faces ([[x,y], [x+1,y], [x+0.5, y+height]], "triangle");

          build_verts_and_faces ([[x+0.5, y-height], [x+1,y], [x+1.5, y-height]], "triangle");
          build_verts_and_faces ([[x+0.5, y+height], [x+1,y], [x+1.5, y+height]], "triangle");
         
     }
 }
}

function make_elongated_triangular_tiling(xmax, ymax) {
 var x,y;
 var height = Math.sqrt(3)/2
 xmax = Math.floor(xmax) // to prevent twice as many columns as requested
 ymax = Math.floor(ymax/2) // to prevent half as many rows as requested
 for (var x = 1; x <xmax; x++) {
     for (var j = 1; j<ymax; j+=2) {
          y = j*(height+1)
          build_verts_and_faces ([[x,y], [x+1,y], [x+0.5, y-height]], "triangle");
          build_verts_and_faces ([[x, y], [x+1, y], [x+1, y+1], [x, y+1]], "square");
          build_verts_and_faces ([[x,y+1], [x+1,y+1], [x+0.5, y+1+height]], "triangle");

         build_verts_and_faces ([[x+0.5,y+height+1], [x+0.5+1,y+height+1], [x+0.5+0.5, y+height+1-height]], "triangle");
         build_verts_and_faces ([[x+0.5, y+height+1], [x+0.5+1, y+height+1], [x+0.5+1, y+height+1+1], [x+0.5, y+height+1+1]], "square");
         build_verts_and_faces ([[x+0.5,y+height+1+1], [x+0.5+1,y+height+1+1], [x+0.5+0.5, y+height+1+1+height]], "triangle");
     }
 }
}


function make_prismatic_pentagonal_tiling(xmax, ymax) {
 var x,y
 var height = Math.sqrt(3)/2
 var w1 = 1
 var w2 = w1/2
 var h1 = 1
 var h2 = (height + 0 + 0)/3
 xmax = Math.floor(xmax) // to prevent twice as many columns as requested
 ymax = Math.floor(ymax/2) // to prevent half as many rows as requested
 for (var x = 1; x <xmax; x++) {
     for (var j = 1; j<ymax; j+=2) {
          y = j*(h1+h2+h1)
          build_verts_and_faces ([[x,y], [x, y-h1], [x+w2, y-h1-h2], [x+w1, y-h1], [x+w1, y]], "pentagon")
          build_verts_and_faces ([[x,y], [x, y+h1], [x+w2, y+h1+h2], [x+w1, y+h1], [x+w1, y]], "pentagon")
          y = y + h1 + h2+h1
          build_verts_and_faces ([[x+w2,y], [x+w2, y-h1], [x+w2+w2, y-h1-h2], [x+w2+w1, y-h1], [x+w2+w1, y]], "pentagon")
          build_verts_and_faces ([[x+w2,y], [x+w2, y+h1], [x+w2+w2, y+h1+h2], [x+w2+w1, y+h1], [x+w2+w1, y]], "pentagon")
     }
 }
}


        
/*  old version
function make_hexagonal_tiling_from_triangles (xmax, ymax) {  
 var x,y;
 var height = Math.sqrt(3)/2
 xmax = Math.floor(xmax/1.5) // to prevent twice as many columns as requested
 ymax = Math.floor(ymax*1.5) // to prevent half as many rows as requested
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<=ymax; j+=1) {
       if (j % 2) { // the odd case
          y = j*height-height*2
          x = i*3+1.5
        }
       else { // the even case
          y = j*height
          x = i*3
       }
       // creates hexagons with flat tops and bottoms.  Swap x and y for pointy tops and bottoms. 
       build_verts_and_faces ([[x,y], [x+0.5, y-height], [x+1.5, y-height], [x+2,y], [x+1.5, y+height], [x+0.5, y+height]], "hexagon");     
       
     }
 }
}
*/


/*  This version makes pointy-top hexagons
function  make_hexagonal_tiling_from_triangles (xmax, ymax) {
   ymax = Math.floor(ymax*0.5)
   var x = 0; 
   var y = 0;
   var width = Math.sqrt(3)/2
   var hexcoords1 = [[x,y], [ x-width, y+0.5], [ x-width, y+1.5], [x, y+2], [ x+width, y+1.5], [x+width, y+0.5 ]]
   var xoffset = Math.abs(hexcoords1[0][0] - hexcoords1[4][0])
   var yoffset = Math.abs(hexcoords1[0][1] - hexcoords1[4][1])
   var hexcoords2 = []
   for (i = 0; i < 6; i++) {
      hexcoords2[i] = [hexcoords1[i][0] + xoffset, hexcoords1[i][1] + yoffset]
   }
  var data = [{face: hexcoords1, name: "hexagon"},
              {face: hexcoords2, name: "hexagon"} ]
  square_tiling_from_data (xmax, ymax, xoffset*2, yoffset*2, data)
}
*/

// This version makes flat-top hexagons
function  make_hexagonal_tiling_from_triangles (xmax, ymax) {
   var x = 0; 
   var y = 0;
   var height = Math.sqrt(3)/2
   var hexcoords1 = [[x,y], [x+0.5, y-height], [x+1.5, y-height], [x+2,y], [x+1.5, y+height], [x+0.5, y+height]]
   var xoffset = Math.abs(hexcoords1[0][0] - hexcoords1[4][0] )
   var yoffset = Math.abs(hexcoords1[0][1] - hexcoords1[4][1])
   console.log(yoffset + "   " +  height)

   var hexcoords2 = []
   for (i = 0; i < 6; i++) {
      hexcoords2[i] = [hexcoords1[i][0] + xoffset, hexcoords1[i][1] + yoffset]
   }
  var data = [{face: hexcoords1, name: "hexagon"},
              {face: hexcoords2, name: "hexagon"} ]
  square_tiling_from_data (xmax, ymax,xoffset*2, yoffset*2, data)
}


/* old version
function make_regular_rhombic_tiling (xmax, ymax) {  
 var x,y;
 var centerx, centery
 var height = Math.sqrt(3)/2
 xmax = Math.floor(xmax/1.5) // to prevent twice as many columns as requested
 ymax = Math.floor(ymax*1.5) // to prevent half as many rows as requested
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<=ymax; j+=1) {
       if (j % 2) { // the odd case
          y = j*height-height*2
          x = i*3+1.5
        }
       else { // the even case
          y = j*height 
          x = i*3 
       }
       centerx = x + 1
       centery = y
       // creates hexagons with flat tops and bottoms.  Swap x and y for pointy tops and bottoms. 
       build_verts_and_faces ([[x,y], [x+0.5, y-height], [x+1.5, y-height], [centerx, centery]], "rhomb");     
       build_verts_and_faces ( [[x+1.5, y-height], [x+2,y], [x+1.5, y+height], [centerx, centery]], "rhomb");  
       build_verts_and_faces ([[x,y], [centerx, centery], [x+1.5, y+height], [x+0.5, y+height]], "rhomb");  
     }
 }
}
*/
 
function make_regular_rhombic_tiling (xmax, ymax) {  
  // ymax = Math.floor(ymax*0.5)
   var x = 0; 
   var y = 0;
   var height = Math.sqrt(3)/2
   var centerx = 1
   var centery = 0
   var rhomb1 = [[x,y], [x+0.5, y-height], [x+1.5, y-height], [centerx, centery]]
   var rhomb2 = [[x+1.5, y-height], [x+2,y], [x+1.5, y+height], [centerx, centery]]
   var rhomb3 = [[x,y], [centerx, centery], [x+1.5, y+height], [x+0.5, y+height]]
   var rhomb4 =  []
   var rhomb5 =  []
   var rhomb6 =  []
   var xoffset =    Math.abs(rhomb1[0][0] - rhomb2[2][0] )
   var yoffset =    Math.abs(rhomb1[0][1] - rhomb2[2][1] )


   for (var i=0; i<4; i++) {
      rhomb4[i] =  [rhomb1[i][0] + xoffset, rhomb1[i][1] + yoffset]
      rhomb5[i] =  [rhomb2[i][0] + xoffset, rhomb2[i][1] + yoffset]
      rhomb6[i] =  [rhomb3[i][0] + xoffset, rhomb3[i][1] + yoffset]
   }
   var data = [{face: rhomb1, name: "rhomb"},
              {face: rhomb2, name: "rhomb"},
              {face: rhomb3, name: "rhomb"},
              {face: rhomb4, name: "rhomb"},
              {face: rhomb5, name: "rhomb"},
              {face: rhomb6, name: "rhomb"}]
   square_tiling_from_data (xmax, ymax,xoffset*2, yoffset*2, data)
}
 

 /*
function make_trihexagonal_tiling(xmax, ymax) {  
 var x,y;
 var height = Math.sqrt(3)/2
// xmax = Math.floor(xmax/1.5) // to prevent twice as many columns as requested
// ymax = Math.floor(ymax*1.5) // to prevent half as many rows as requested
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<ymax; j+=1) {
       if (j % 2) { // the odd case
          y = (j*height-height*2)*2
          x = (i*3+1.5)*2/3         
        }
       else { // the even case
          y = j*height*2
          x = i*2
       }
       build_verts_and_faces ([[x,y], [x+0.5, y-height], [x+1.5, y-height], [x+2,y], [x+1.5, y+height], [x+0.5, y+height]], "hexagon");     
       build_verts_and_faces ([[x,y], [x+0.5, y-height], [x-0.5, y-height]], "triangle");
       build_verts_and_faces ([[x+2,y], [x+1.5, y+height], [x+2.5, y+height]], "triangle");     
     }
 }
}
 */

function   make_trihexagonal_tiling(xmax, ymax) {
   ymax = Math.floor(ymax*0.5)
   var x = 0; 
   var y = 0;
   var height = Math.sqrt(3)/2
   var hexcoords1 = [[x,y], [x+0.5, y-height], [x+1.5, y-height], [x+2,y], [x+1.5, y+height], [x+0.5, y+height]]
   var triangle1 = [ [x+0.5, y-height],[ x+1, y-2*height], [x+1.5, y-height]]
   var triangle2 = [ [x+1.5, y+height], [x+1, y+2*height], [x+0.5, y+height]]
   var hexcoords2 = []
   var triangle3 =  []
   var triangle4 =  []
   var xoffset =  (  Math.abs(hexcoords1[0][0] - hexcoords1[3][0] ))/2  //   
   var yoffset = Math.abs(hexcoords1[0][1] - hexcoords1[3][1] - 2*height)  // also height*2

   for (var i = 0; i < 6; i++) {
      hexcoords2[i] = [hexcoords1[i][0] + xoffset, hexcoords1[i][1] + yoffset]
   }
   for (var i=0; i<3; i++) {
      triangle3[i] =  [triangle1[i][0] + xoffset, triangle1[i][1] + yoffset]
      triangle4[i] =  [triangle2[i][0] + xoffset, triangle2[i][1] + yoffset]
   }
   var data = [{face: hexcoords1, name: "hexagon"},
              {face: triangle1, name: "triangle"},
              {face: triangle2, name: "triangle"},

              {face: hexcoords2, name: "hexagon"},
              {face: triangle3, name: "triangle"},
              {face: triangle4, name: "triangle"}]
   square_tiling_from_data (xmax, ymax,xoffset*2, yoffset*2, data)
}




function  make_truncated_hexagonal_tiling (xmax, ymax) {    // dodecagons and triangles
 var x,y;
 var height = Math.sqrt(3)/2
 xmax = Math.floor(xmax/1.5) // to prevent twice as many columns as requested
 ymax = Math.floor(ymax*1.5) // to prevent half as many rows as requested
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<=ymax; j+=1) {
       if (j % 2) { // the odd case
    
          y = j*(height + 1)-(height + 1)*2
          x =  (i*3+1.5) * (2*height+2)/(height*2)    
        }
       else { // the even case
          y = j*(height + 1)
          x =  (i*3) * (2*height+2)/(height*2)      
       }
       build_verts_and_faces ([[x,y-0.5],[x+height+0.5-height,y-height-0.5],[x+height+0.5, y-height-1], 
                              [x+height+1.5, y-height-1], [x+height+1.5+height, y - height -0.5], [x+height+2+height, y-0.5],
                              [x+height+2+height, y+0.5], [x+height+1.5+height, y + height +0.5],[x+height+1.5, y+height+1],
                              [x+height+0.5, y+height+1],[x+height+0.5-height,y+height+0.5], [x,y+0.5]], "dodecagon")
       build_verts_and_faces ([[x,y-0.5], [x,y+0.5], [x-height, y]], "triangle")
       build_verts_and_faces ([[x+height+2+height, y-0.5], [x+height+2+height, y+0.5], [x+height+2+height+height, y]], "triangle")
     }
 }
} 




function make_truncated_trihexagonal_tiling (xmax, ymax) {   // dodecagons, hexagons, and squares
 var x,y;
 var height = Math.sqrt(3)/2
  xmax = Math.floor(xmax*3) // to prevent twice as many columns as requested
  ymax = Math.floor(ymax/1.5) // to prevent half as many rows as requested
 for (var i = 0; i <ymax; i+=1) {
     for (var j = 0; j<=xmax; j+=2) {
          x =    j*(height + 1.5)  
          y =   i*(3*height+1.5)*2

       build_verts_and_faces ([[x,y-0.5],[x+height+0.5-height,y-height-0.5],[x+height+0.5, y-height-1], 
                              [x+height+1.5, y-height-1], [x+height+1.5+height, y - height -0.5], [x+height+2+height, y-0.5],
                              [x+height+2+height, y+0.5], [x+height+1.5+height, y + height +0.5],[x+height+1.5, y+height+1],
                              [x+height+0.5, y+height+1],[x+height+0.5-height,y+height+0.5], [x,y+0.5]], "dodecagon")
       // creates hexagons with flat tops and bottoms.  Swap x and y for pointy tops and bottoms. 
       build_verts_and_faces ([[x,y-0.5], [x, y+0.5], [x-1, y+0.5],[x-1, y-0.5]], "square");
       build_verts_and_faces ([[x-1.5,y-height-0.5], [x+0.5-1.5, y-height-height-0.5], [x+1.5-1.5, y-height-height-0.5], [x+2-1.5,y-height-0.5], [x+1.5-1.5, y+height-height-0.5], [x+0.5-1.5, y+height-height-0.5]], "hexagon");  
       build_verts_and_faces ([[x-1.5,y+height+0.5], [x+0.5-1.5, y+height+height+0.5], [x+1.5-1.5, y+height+height+0.5], [x+2-1.5,y+height+0.5], [x+1.5-1.5, y-height+height+0.5], [x+0.5-1.5, y-height+height+0.5]], "hexagon"); 
       build_verts_and_faces ([  [x+height+0.5, y+height+1],[x+height+0.5-height,y+height+0.5],[x+1.5-1.5, y+height+height+0.5], [x+height-0.5+0.5, y+height+1+height]], "square");
       build_verts_and_faces ([  [x+height+0.5, y-height-1],[x+height+0.5-height,y-height-0.5],[x+1.5-1.5, y-height-height-0.5], [x+height-0.5+0.5, y-height-1-height]], "square");

           x = x + (height + 1.5)-(height + 1.5)*2 
           y = y + 3*height + 1.5       

       build_verts_and_faces ([[x,y-0.5],[x+height+0.5-height,y-height-0.5],[x+height+0.5, y-height-1], 
                              [x+height+1.5, y-height-1], [x+height+1.5+height, y - height -0.5], [x+height+2+height, y-0.5],
                              [x+height+2+height, y+0.5], [x+height+1.5+height, y + height +0.5],[x+height+1.5, y+height+1],
                              [x+height+0.5, y+height+1],[x+height+0.5-height,y+height+0.5], [x,y+0.5]], "dodecagon")
       // creates hexagons with flat tops and bottoms.  Swap x and y for pointy tops and bottoms. 
       build_verts_and_faces ([[x,y-0.5], [x, y+0.5], [x-1, y+0.5],[x-1, y-0.5]], "square");
       build_verts_and_faces ([[x-1.5,y-height-0.5], [x+0.5-1.5, y-height-height-0.5], [x+1.5-1.5, y-height-height-0.5], [x+2-1.5,y-height-0.5], [x+1.5-1.5, y+height-height-0.5], [x+0.5-1.5, y+height-height-0.5]], "hexagon");  
       build_verts_and_faces ([[x-1.5,y+height+0.5], [x+0.5-1.5, y+height+height+0.5], [x+1.5-1.5, y+height+height+0.5], [x+2-1.5,y+height+0.5], [x+1.5-1.5, y-height+height+0.5], [x+0.5-1.5, y-height+height+0.5]], "hexagon"); 
       build_verts_and_faces ([  [x+height+0.5, y+height+1],[x+height+0.5-height,y+height+0.5],[x+1.5-1.5, y+height+height+0.5], [x+height-0.5+0.5, y+height+1+height]], "square");
       build_verts_and_faces ([  [x+height+0.5, y-height-1],[x+height+0.5-height,y-height-0.5],[x+1.5-1.5, y-height-height-0.5], [x+height-0.5+0.5, y-height-1-height]], "square");

   }
 }
}



// Floret Pentagonal tiling
//    From Wolfram Alpha:  Translation vectors = (5/2, -sqrt(3)/2)  and  (-1/2, (3 sqrt(3))/2)
//     http://www.wolframalpha.com/input/?i=floret+pentagonal+tiling
//    In contrast, hexagonal tilings, oriented so that the hexagons have pointy tops, have 
//      translation vectors equal to (1, 0)  and  (1/2, sqrt(3)/2) (reverse x and y for flat tops)
//      Rhombille tiling, oriented with pointy tops have
//        translation vectors equal to (2, 0)  |  (1, sqrt(3))
//      and snub square has translation vectors equal to (1/2 (1+sqrt(3)), 1/2 (-1-sqrt(3)))  and  (1/2 (-1-sqrt(3)), 1/2 (-1-sqrt(3)))

function make_floret_pentagonal_tiling (xmax, ymax) {  
 var x,y;
 var height = Math.sqrt(3)/2
 xmax = Math.floor(xmax/1.66667) 
 ymax = Math.floor(ymax/1.66667) 
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<=ymax; j+=1) {
          y = ( ( 5/2) * i - 0.5*j   ) * 2 * height                                   // j*height * 3   * 1.333333333333333
          x = ( -(Math.sqrt(3)/2)*i + 3*(Math.sqrt(3))/2*j  ) * 2 *height          // i*3 *2.15  +y    
        if (x > 0 && y > 0 && x <xmax*3 && y<ymax*3)  {
 
      // // 7 hexagons, with center one missing
      //     and the missing center hexagon has its own center at [x+1, y]
     // then convert them to pentagons

       build_verts_and_faces ([[x,y-2*height], [x+0.5, y-height-2*height], [x+1.5, y-height-2*height], [x+2,y-2*height],[x+1, y] ], "pentagon");   // topmost pentagon  
       build_verts_and_faces ([[x-1.5,y-1*height], [x+0.5-1.5, y-height-1*height], [x+1.5-1.5, y-height-1*height],[x+1, y], [x+0.5-1.5, y+height-1*height]], "pentagon");     // left top
       build_verts_and_faces ([[x+1, y], [x+0.5+1.5, y-height-1*height], [x+1.5+1.5, y-height-1*height], [x+2+1.5,y-1*height], [x+1.5+1.5, y+height-1*height], ], "pentagon");     // right top
       build_verts_and_faces ([[x-1.5,y+1*height], [x+0.5-1.5, y-height+1*height], [x+1, y], [x+1.5-1.5, y+height+1*height], [x+0.5-1.5, y+height+1*height]], "pentagon");     // left bottom
       build_verts_and_faces ([[x+1, y], [x+1.5+1.5, y-height+1*height], [x+2+1.5,y+1*height], [x+1.5+1.5, y+height+1*height], [x+0.5+1.5, y+height+1*height]], "pentagon");     // right bottom
       build_verts_and_faces ([[x,y+2*height], [x+1, y], [x+2,y+2*height], [x+1.5, y+height+2*height], [x+0.5, y+height+2*height]], "pentagon");   // bottommost pentagon  
       }
     }
 }
}


//    From Wolfram Alpha:  Translation vectors = (5/2, -sqrt(3)/2)  and  (-1/2, (3 sqrt(3))/2)

function make_snub_trihexagonal_tiling (xmax, ymax) {  
 var x,y;
 var height = Math.sqrt(3)/2
// xmax = Math.floor(xmax/1.5) // to prevent twice as many columns as requested
// ymax = Math.floor(ymax*1.5) // to prevent half as many rows as requested
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<=ymax; j+=1) {
        x = ( ( 5/2) * i  - 0.5*j  ) 
        y = ( -(Math.sqrt(3)/2)*i + 3*(Math.sqrt(3))/2*j  )   
       if (x > 0 && y > 0 && x <xmax*1.5  && y<ymax*1.5)  {
             build_verts_and_faces ([[x,y], [x+0.5, y-height], [x+1.5, y-height], [x+2,y], [x+1.5, y+height], [x+0.5, y+height]], "hexagon");  
             build_verts_and_faces ([[x,y], [x+0.5,y+height], [x-0.5,y+height]], "triangle");  
             build_verts_and_faces ([[x,y+2*height], [x+0.5,y+height], [x-0.5,y+height]], "triangle");  
             build_verts_and_faces ([[x,y+2*height], [x+1,y+2*height], [x+0.5,y+height]], "triangle");  
             build_verts_and_faces ([[x+0.5,y+height], [x+1.5,y+height], [x+1,y+2*height]], "triangle");  
             build_verts_and_faces ([[x+1,y+2*height], [x+2,y+2*height], [x+1.5,y+height]], "triangle");  
             build_verts_and_faces ([[x+1.5,y+height], [x+2.5,y+height], [x+2,y+2*height]], "triangle");  
             build_verts_and_faces ([[x+1.5,y+height], [x+2.5,y+height], [x+2,y]], "triangle");  
             build_verts_and_faces ([[x+2,y], [x+3,y], [x+2.5,y+height]], "triangle");  
             build_verts_and_faces ([[x+1.5, y-height], [x+2.5, y-height],[x+2, y]], "triangle");  

      }
     }
 }
}



// height of above floret:  6*height = 6*(Math.sqrt(3)/2) = 3*(Math.sqrt(3)
// width of above floret:  4 units



function make_rhombitrihexagonal_tiling_from_triangles (xmax, ymax) {  
 var x,y;
 var height = Math.sqrt(3)/2
 xmax = Math.floor(xmax/1.5) // to prevent twice as many columns as requested
 ymax = Math.floor(ymax*1.5) // to prevent half as many rows as requested
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<=ymax; j+=1) {
       if (j % 2) { // the odd case
          y = (j*(height+0.5)-(height+0.5)*2) 
          x = i*(1.5+height)*2 + (1.5+height)         }
       else { // the even case
          y = j*(height+0.5)
          x = i*(1.5+height)*2
       }
        // here, x,y is the leftmost point of the flat-topped hexagon
        build_verts_and_faces ([[x,y], [x+0.5, y-height], [x+1.5, y-height], [x+2,y], [x+1.5, y+height], [x+0.5, y+height]], "hexagon");     
        build_verts_and_faces ([[x,y], [x-height,y-0.5],[x-height,y+0.5]], "triangle")
        build_verts_and_faces ([[x+0.5, y-height], [x+0.5,y-height-1],[x+0.5-height,y-height-0.5]], "triangle")
        build_verts_and_faces ([[x+0.5,y-height], [x+0.5,y-height-1],[x+1.5,y-height-1], [x+1.5,y-height] ], "square")
        build_verts_and_faces ([[x,y], [x+0.5,y-height],[x+0.5-height,y-height-0.5], [x-height,y-0.5]], "square")
        build_verts_and_faces ([[x,y], [x+0.5,y+height],[x+0.5-height,y+height+0.5], [x-height,y+0.5]], "square")
     }
  }
}



function make_deltoidal_trihexagonal_tiling (xmax, ymax) {
 var x,y;
 var height = Math.sqrt(3)/2
 xmax = Math.floor(xmax/1.5) // to prevent twice as many columns as requested
 ymax = Math.floor(ymax*1.5) // to prevent half as many rows as requested
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<=ymax; j+=1) {
       if (j % 2) { // the odd case
          y = j*height-height*2
          x = i*3+1.5
        }
       else { // the even case
          y = j*height
          x = i*3
       }
       // creates hexagons with flat tops and bottoms.  Swap x and y for pointy tops and bottoms. 
       //build_verts_and_faces ([[x,y], [x+0.5, y-height], [x+1.5, y-height], [x+2,y], [x+1.5, y+height], [x+0.5, y+height]], "hexagon");  
       //                          v1         v2               v3                v4       v5                 v6   
                  // the center is [x+1, y]
                  // v1.5 = [x+0.25, y-height/2]
                  // v2.5 = [x+1, y-height]
                  // v3.5 = [x+1.75, y-height/2]
                  // v4.5 = [x+1.75, y+height/2]
                  // v5.5 = [x+1, y+height]
                  // v6.5 = [x+0.25, y+height/2]
                  
                    build_verts_and_faces ([ [x+0.25, y+height/2], [x,y], [x+0.25, y-height/2],  [x+1, y] ], "kite");            // v6.5, v1, v1.5, center
                    build_verts_and_faces ([ [x+0.25, y-height/2],  [x+0.5, y-height], [x+1, y-height],   [x+1, y]], "kite");    // v1.5, v2, v2.5, center
                       build_verts_and_faces ([  [x+1, y-height], [x+1.5, y-height], [x+1.75, y-height/2],  [x+1, y]], "kite");  // v2.5, v3, v3.5, center
                       build_verts_and_faces ([  [x+1.75, y-height/2], [x+2,y],  [x+1.75, y+height/2],   [x+1, y]], "kite");     // v3.5, v4, v4.5, center
                       build_verts_and_faces ([  [x+1.75, y+height/2],  [x+1.5, y+height],  [x+1, y+height],  [x+1, y]], "kite"); //  v4.5, v5, v5.5, center
                       build_verts_and_faces ([  [x+1, y+height],  [x+0.5, y+height],[x+0.25, y+height/2],  [x+1, y]], "kite");  //  v5.5, v6, v6.5, center

     }
 }
}


function make_kisrhombille_tiling (xmax, ymax) {
 var x,y;
 var height = Math.sqrt(3)/2
 xmax = Math.floor(xmax/1.5) // to prevent twice as many columns as requested
 ymax = Math.floor(ymax*1.5) // to prevent half as many rows as requested
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<=ymax; j+=1) {
       if (j % 2) { // the odd case
          y = j*height-height*2
          x = i*3+1.5
        }
       else { // the even case
          y = j*height
          x = i*3
       }
       // creates hexagons with flat tops and bottoms.  Swap x and y for pointy tops and bottoms. 
       //build_verts_and_faces ([[x,y], [x+0.5, y-height], [x+1.5, y-height], [x+2,y], [x+1.5, y+height], [x+0.5, y+height]], "hexagon");  
       //                          v1         v2               v3                v4       v5                 v6   
                  // the center is [x+1, y]
                  // v1.5 = [x+0.25, y-height/2]
                  // v2.5 = [x+1, y-height]
                  // v3.5 = [x+1.75, y-height/2]
                  // v4.5 = [x+1.75, y+height/2]
                  // v5.5 = [x+1, y+height]
                  // v6.5 = [x+0.25, y+height/2]
                  
                    build_verts_and_faces ([ [x+0.25, y+height/2], [x,y],  [x+1, y] ], "kite");            // v6.5, v1, v1.5, center
                    build_verts_and_faces ([ [x+0.25, y-height/2],  [x+0.5, y-height],   [x+1, y]], "kite");    // v1.5, v2, v2.5, center
                    build_verts_and_faces ([  [x+1, y-height], [x+1.5, y-height],  [x+1, y]], "kite");  // v2.5, v3, v3.5, center
                    build_verts_and_faces ([  [x+1.75, y-height/2], [x+2,y],    [x+1, y]], "kite");     // v3.5, v4, v4.5, center
                    build_verts_and_faces ([  [x+1.75, y+height/2],  [x+1.5, y+height],   [x+1, y]], "kite"); //  v4.5, v5, v5.5, center
                    build_verts_and_faces ([  [x+1, y+height],  [x+0.5, y+height], [x+1, y]], "kite");  //  v5.5, v6, v6.5, center


                    build_verts_and_faces ([ [x,y], [x+0.25, y-height/2],  [x+1, y] ], "kite");            // v1, v1.5, center, v6.5
                    build_verts_and_faces ([  [x+0.5, y-height], [x+1, y-height],   [x+1, y]], "kite");    // v1.5, v2, v2.5, center
                    build_verts_and_faces ([  [x+1.5, y-height], [x+1.75, y-height/2],  [x+1, y]], "kite");  // v2.5, v3, v3.5, center
                    build_verts_and_faces ([   [x+2,y],  [x+1.75, y+height/2],   [x+1, y]], "kite");     // v3.5, v4, v4.5, center
                    build_verts_and_faces ([  [x+1.5, y+height],  [x+1, y+height],  [x+1, y]], "kite"); //  v4.5, v5, v5.5, center
                    build_verts_and_faces ([   [x+0.5, y+height],[x+0.25, y+height/2],  [x+1, y]], "kite");  //  v5.5, v6, v6.5, center

     }
 }
}



function make_triakis_triangular_tiling(xmax, ymax) {
var x,y;
 var height = Math.sqrt(3)/2
 xmax = Math.floor(xmax/1.5/2.5) // to prevent twice as many columns as requested
 ymax = Math.floor(ymax*1.5/2.5) // to prevent half as many rows as requested
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<=ymax; j+=1) {
       if (j % 2) { // the odd case
          y = j*height-height*2
          x = i*3+1.5
        }
       else { // the even case
          y = j*height
          x = i*3
       }
       // creates hexagons with flat tops and bottoms.  Swap x and y for pointy tops and bottoms. 
      // build_verts_and_faces ([[x,y], [x+0.5, y-height], [x+1.5, y-height], [x+2,y], [x+1.5, y+height], [x+0.5, y+height]], "hexagon");   

         build_verts_and_faces ([ [x,y], [x+0.5, y-height], [x+1.5, y-height]], "triangle");  // v1, v2, v3
         build_verts_and_faces ([  [x+1.5, y-height], [x+2,y], [x+1.5, y+height]], "triangle"); // v3, v4, v5
         build_verts_and_faces ([[x+1.5, y+height], [x+0.5, y+height], [x,y] ], "triangle");  // v5, v6, v1
           // the center is [x+1, y]
         build_verts_and_faces ([ [x,y],  [x+1, y], [x+1.5, y-height]], "triangle");                // v1, center, v3
         build_verts_and_faces ([  [x+1.5, y-height],  [x+1, y], [x+1.5, y+height]], "triangle"); // v3, center, v5
         build_verts_and_faces ([[x+1.5, y+height],  [x+1, y], [x,y] ], "triangle");             // v5, center, v1

       
     }
 }
}
        











// extra meshmakers


function make_squished_trihexagonal_tiling(xmax, ymax) {  
 var x,y;
 var height = Math.sqrt(3)/2
 xmax = Math.floor(xmax/1.5) // to prevent twice as many columns as requested
 ymax = Math.floor(ymax*1.5) // to prevent half as many rows as requested
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<=ymax; j+=1) {
       if (j % 2) { // the odd case
          y = j*height-height*2
          x = i*2+1
          continue;
        }
       else { // the even case
          y = j*height+height+height+height
          x = i*2
       }
       // creates hexagons with flat tops and bottoms.  Swap x and y for pointy tops and bottoms. 
       build_verts_and_faces ([[x,y], [x+0.5, y-height], [x+1.5, y-height], [x+2,y], [x+1.5, y+height], [x+0.5, y+height]], "hexagon");     
       build_verts_and_faces ([[x,y], [x+0.5, y-height], [x-0.5, y-height]], "triangle");
       build_verts_and_faces ([[x+2,y], [x+1.5, y+height], [x+2.5, y+height]], "triangle");     

     }
 }
}




function make_not_floret_pentagonal_tiling_has_symmetric_holes (xmax, ymax) {  // this also could be a starting point for many tilings...
 var x,y;
 var height = Math.sqrt(3)/2
 xmax = Math.floor(xmax/1.5) 
 ymax = Math.floor(ymax*1.5) 
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<=ymax; j+=1) {
       if (j % 2) { // the odd case
          y = (j*height)*3-(height*2)*3
          x = (i*3)*3+(1.5)*3
        }
       else { // the even case
          y = (j*height) * 3
          x = (i*3) * 3
       }
      // the missing center hexagon has its own center at [x+1, y]

       build_verts_and_faces ([[x,y-2*height], [x+0.5, y-height-2*height], [x+1.5, y-height-2*height], [x+2,y-2*height],[x+1, y] ], "hexagon");   // topmost hexagon  
       build_verts_and_faces ([[x-1.5,y-1*height], [x+0.5-1.5, y-height-1*height], [x+1.5-1.5, y-height-1*height],[x+1, y], [x+0.5-1.5, y+height-1*height]], "hexagon");     // left top
       build_verts_and_faces ([[x+1, y], [x+0.5+1.5, y-height-1*height], [x+1.5+1.5, y-height-1*height], [x+2+1.5,y-1*height], [x+1.5+1.5, y+height-1*height], ], "hexagon");     // right top
       build_verts_and_faces ([[x-1.5,y+1*height], [x+0.5-1.5, y-height+1*height], [x+1, y], [x+1.5-1.5, y+height+1*height], [x+0.5-1.5, y+height+1*height]], "hexagon");     // left bottom
       build_verts_and_faces ([[x+1, y], [x+1.5+1.5, y-height+1*height], [x+2+1.5,y+1*height], [x+1.5+1.5, y+height+1*height], [x+0.5+1.5, y+height+1*height]], "hexagon");     // right bottom
       build_verts_and_faces ([[x,y+2*height], [x+1, y], [x+2,y+2*height], [x+1.5, y+height+2*height], [x+0.5, y+height+2*height]], "hexagon");   // bottommost hexagon  
     }
 }
}


function make_rings_of_six_hexagons (xmax, ymax) {  // this could be a starting point for many tilings...
 var x,y;
 var height = Math.sqrt(3)/2
 xmax = Math.floor(xmax/1.5) // to prevent twice as many columns as requested
 ymax = Math.floor(ymax*1.5) // to prevent half as many rows as requested
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<=ymax; j+=1) {
       if (j % 2) { // the odd case
          y = (j*height)*3-(height*2)*3
          x = (i*3)*3+(1.5)*3
        }
       else { // the even case
          y = (j*height) * 3
          x = (i*3) * 3
       }

       build_verts_and_faces ([[x,y-2*height], [x+0.5, y-height-2*height], [x+1.5, y-height-2*height], [x+2,y-2*height], [x+1.5, y+height-2*height], [x+0.5, y+height-2*height]], "hexagon");   // topmost hexagon  
       build_verts_and_faces ([[x-1.5,y-1*height], [x+0.5-1.5, y-height-1*height], [x+1.5-1.5, y-height-1*height], [x+2-1.5,y-1*height], [x+1.5-1.5, y+height-1*height], [x+0.5-1.5, y+height-1*height]], "hexagon");     // left top
       build_verts_and_faces ([[x+1.5,y-1*height], [x+0.5+1.5, y-height-1*height], [x+1.5+1.5, y-height-1*height], [x+2+1.5,y-1*height], [x+1.5+1.5, y+height-1*height], [x+0.5+1.5, y+height-1*height]], "hexagon");     // right top
       build_verts_and_faces ([[x-1.5,y+1*height], [x+0.5-1.5, y-height+1*height], [x+1.5-1.5, y-height+1*height], [x+2-1.5,y+1*height], [x+1.5-1.5, y+height+1*height], [x+0.5-1.5, y+height+1*height]], "hexagon");     // left bottom
       build_verts_and_faces ([[x+1.5,y+1*height], [x+0.5+1.5, y-height+1*height], [x+1.5+1.5, y-height+1*height], [x+2+1.5,y+1*height], [x+1.5+1.5, y+height+1*height], [x+0.5+1.5, y+height+1*height]], "hexagon");     // right bottom
       build_verts_and_faces ([[x,y+2*height], [x+0.5, y-height+2*height], [x+1.5, y-height+2*height], [x+2,y+2*height], [x+1.5, y+height+2*height], [x+0.5, y+height+2*height]], "hexagon");   // bottommost hexagon  
     }
 }
}














// for spirals and circles see http://krazydad.com/tutorials/circles/













function make_offset_circles( n) 
{
  
 var cx = 0;
 var cy = 0;
 var   results = []                                      // global for now

 for (var j = 1; j <n; j++) { 
  var lg_rad = 1*j  // * Math.log(j) * Math.log(j) 
  var lg_circ = 2*Math.PI*lg_rad;
  
   for (var i = 1; i <= 10; ++i) {
      var offset =  (j % 2)*18*Math.PI/180
      var angle = i*2*Math.PI/10 + offset
      var x_pt = cx + Math.cos(angle)  * lg_rad;
      var y_pt = cy + Math.sin(angle)  * lg_rad;
      results.push({x: x_pt, y: y_pt, circle: j })


  }
 }
  return results
}


/*

m-odd:  i i+10,i+20, i+11
m-even:  i, i+10, i+20, i+9

9-odd:   i, i+10, i+20, i+1
9-even:  i, i+10, i+20, i+9   the m-even case
10-odd:  i, i+10, i+20, i+11  the m-odd case
10-even: i, i+10, i+20, i+19
*/

// Treat odd numbred rings differently, treat cells with indices ending in 9 or 0 differently.
function call_offset_circles (n) {
 /*
   x_to_verts = []
   vertexArray = [] 
   v_index = 1;
   vertexArray[0] = settypecellvertex  // This shouldn't be used, but  
   allcells = [] 
   aci = 0;  
   */
    var results = make_offset_circles(n)
   
   // first fill in the central zone

    for (var i = 0; i < 9; i++) {
      build_verts_and_faces([[0,0], [results[i].x, results[i].y], [results[i+11].x, results[i+11].y], [results[i+1].x, results[i+1].y]], "spiraledsquare")
    }
    // and fill in the last part of the central zone, where the indices must wrap back to zero
      build_verts_and_faces([[0,0], [results[9].x, results[9].y], [results[i+1].x, results[i+1].y], [results[i-9].x, results[i-9].y]], "spiraledsquare")


    // now build the vast majority of the tiling

    for (var i = 0;  i<results.length ; i++) {
       if ((i+20) < results.length) {

         var does_not_end_in_9 = (i + 1) % 10 
         var does_not_end_in_0 = (i % 10)
       
   
        if (does_not_end_in_9  && does_not_end_in_0) {  // doesn't end in 9 or 10,  seperately handle 9-even, 9-odd, 10-even, 10-odd, and then optionally consolidate if there is redundancy.  
           if (results[i].circle % 2) { // odd case
             build_verts_and_faces([[results[i].x, results[i].y], [results[i+10].x, results[i+10].y], [results[i+20].x, results[i+20].y], [results[i+11].x, results[i+11].y]], "spiraledsquare")
            } 
           else { // even case
             build_verts_and_faces([[results[i].x, results[i].y], [results[i+10].x, results[i+10].y], [results[i+20].x, results[i+20].y], [results[i+9].x, results[i+9].y]], "spiraledsquare")
           }
         }
         else if (does_not_end_in_0) { // ends in 9
         
           if (results[i].circle % 2) { // odd case
             build_verts_and_faces([[results[i].x, results[i].y], [results[i+10].x, results[i+10].y], [results[i+20].x, results[i+20].y], [results[i+1].x, results[i+1].y]], "spiraledsquare")
            } 
           else {
             build_verts_and_faces([[results[i].x, results[i].y], [results[i+10].x, results[i+10].y], [results[i+20].x, results[i+20].y], [results[i+9].x, results[i+9].y]], "spiraledsquare")
           }

         }
         else { // ends in zero
            if (results[i].circle % 2) { // odd case
             build_verts_and_faces([[results[i].x, results[i].y], [results[i+10].x, results[i+10].y], [results[i+20].x, results[i+20].y], [results[i+11].x, results[i+11].y]], "spiraledsquare")
            } 
           else {
             build_verts_and_faces([[results[i].x, results[i].y], [results[i+10].x, results[i+10].y], [results[i+20].x, results[i+20].y], [results[i+19].x, results[i+19].y]], "spiraledsquare")
           }

         }


       }
     }
    
   //  document.getElementById("PeriodicMeshmakers_Div").setAttribute("style", "display: none;")  

 //     initialize()

    //  ctxGrid.lineWidth = 0.4  // this is a bit arbitrary  -- but instead of shapesize/12, it must be much much smaller. 


  //    clearboard() 
 //     drawboard()  
 //     drawgrid()
        
}







function make_concentric_circles( n) 
{
  
 var cx = 0;
 var cy = 0;
 var   results = []                                      // global for now

 for (var j = 1; j <n; j++) { 
  var lg_rad = 1*j  
  var lg_circ = 2*Math.PI*lg_rad;
  
   for (var i = 1; i <= 10; ++i) {
      var offset = 0 //  (j % 2)*18*Math.PI/180
      var angle = i*2*Math.PI/10 + offset
      var x_pt = cx + Math.cos(angle)  * lg_rad;
      var y_pt = cy + Math.sin(angle)  * lg_rad;
      results.push({x: x_pt, y: y_pt })


  }
 }
  return results
}

function call_concentric_circles (n) {
  /*
   x_to_verts = []
   vertexArray = [] 
   v_index = 1;
   vertexArray[0] = settypecellvertex  // This shouldn't be used, but  
   allcells = [] 
   aci = 0;  
   */
    var results = make_concentric_circles(n)
    for (var i = 0;  i<results.length ; i++) {
       if ((i+10) < results.length) {
       
   
        if ((i+1) % 10) {
             build_verts_and_faces([[results[i].x, results[i].y], [results[i+10].x, results[i+10].y], [results[i+11].x, results[i+11].y], [results[i+1].x, results[i+1].y]], "spiraledsquare")
         }
         else { // ends in 10 // 9
             build_verts_and_faces([[results[i].x, results[i].y], [results[i+10].x, results[i+10].y], [results[i+1].x, results[i+1].y], [results[i-9].x, results[i-9].y]], "spiraledsquare")
         }


       }
     }
    /*
     document.getElementById("PeriodicMeshmakers_Div").setAttribute("style", "display: none;")  

      initialize()

      ctxGrid.lineWidth = 0.4  // this is a bit arbitrary  -- but instead of shapesize/12, it must be much much smaller. 


      clearboard() 
      drawboard()  
      drawgrid()
    */
}



















function make_KrazyDad_spiral6 ( nbr_circles)   {  //  code by Jim Bumgardner, modified for this tiling project
  var width = 900;
  var height = 900;

   // var nbr_circles =10000;
  var deviation = 5/8.0;
  
  var phi = (Math.sqrt(5)+1)/2 - 1;            // golden ratio
  var golden_angle = phi*2*Math.PI;            // golden angle
  
  var lg_rad = width * .45;
  var lg_area = Math.pow(lg_rad,2)*Math.PI;
  
  var mean_area = lg_area / nbr_circles;
  
  var min_area = mean_area * (1-deviation);
  var max_area = mean_area * (1+deviation);
  
  var cum_area = 0;
  
  var fudge = .87; // Fudge factor, since our circles don't actually fill up space entirely.
  
  var cx = width/2;
  var cy = height/2;
  
  var hue_incr =  .1;
  var angle_offset = 0
   
  results = []                                      // global for now

  
  var sm_area = lg_area / nbr_circles; // Area of our little circles, if they filled the space entirely
  var sm_rad = Math.sqrt( sm_area / Math.PI ); // This is related to the equation area = pi r squared


  for (var i = 1; i <= nbr_circles; ++i) {
  
    // var angle = i*golden_angle + angle_offset;
   //var angle = i*golden_angle/6                        // another way to make 10 arms
  //var angle = i*36*Math.PI/180
  var angle = i*golden_angle/12
 // var angle = i*golden_angle/12 * 1/0.95
//var angle = i*golden_angle *4
//var angle = i*18*Math.PI/180 * 1/0.95
//var angle = i*18*Math.PI/180   // "almost" works.
var angle = i*36*Math.PI/180 




  
    var ratio = i / nbr_circles;
//    var sm_area = min_area + ratio * (max_area - min_area);
//    var sm_rad = Math.sqrt( sm_area / Math.PI );
  
   // cum_area += sm_area;
      cum_area = i*sm_area;

    var spiral_rad = Math.sqrt( cum_area / Math.PI );
 
    var x_center = cx + Math.cos(angle) * spiral_rad;
    var y_center  = cy + Math.sin(angle) * spiral_rad;

    /*  
    var hue = hue_incr*i;
    hue -= Math.floor(hue);
    hue *= 360;
    hue = Math.round(hue)
    */

     //   results.push({x: x_center, y: y_center, myhue: hue })
      results.push({x: x_center, y: y_center })

  
    }
 return results
  
}


function call_KrazyDad_Spiral6 (n) {
   x_to_verts = []
   vertexArray = [] 
   v_index = 1;
   vertexArray[0] = settypecellvertex  // This shouldn't be used, but  
   allcells = [] 
   aci = 0;  

    var results = make_KrazyDad_spiral6(n)


    for (var i = 0; i < 9; i++) {
      build_verts_and_faces([[0,0], [results[i].x, results[i].y], [results[i+11].x, results[i+11].y], [results[i+1].x, results[i+1].y]], "spiraledsquare")
    }
    // and fill in the last part of the central zone, where the indices must wrap back to zero
      build_verts_and_faces([[0,0], [results[9].x, results[9].y], [results[i+1].x, results[i+1].y], [results[i-9].x, results[i-9].y]], "spiraledsquare")

    for (var i = n - 1 ; i--;) {
       if ((i+39) < n) {
        
       //   build_verts_and_faces([[results[i].x, results[i].y], [results[i+10].x, results[i+10].y], [results[i+27].x, results[i+27].y], [results[i+17].x, results[i+17].y]], "spiraledsquare");

       //    build_verts_and_faces([[results[i].x, results[i].y], [results[i+10].x, results[i+10].y], [results[i+39].x, results[i+39].y], [results[i+29].x, results[i+29].y]], "spiraledsquare");

      //  build_verts_and_faces([[results[i].x, results[i].y], [results[i+39].x, results[i+39].y], [results[i+68].x, results[i+68].y], [results[i+29].x, results[i+29].y]], "spiraledsquare");
    
      //   build_verts_and_faces([[results[i].x, results[i].y], [results[i+29].x, results[i+29].y], [results[i+97].x, results[i+97].y], [results[i+68].x, results[i+68].y]], "spiraledsquare");


 build_verts_and_faces([[results[i].x, results[i].y], [results[i+1].x, results[i+1].y], [results[i+11].x, results[i+11].y], [results[i+10].x, results[i+10].y]], "spiraledsquare");



       }
     }
     

      initialize()

ctxGrid.lineWidth = 0.4  // this is a bit arbitrary  -- but instead of shapesize/12, it must be much much smaller. 


      clearboard() 
      drawboard()  
      drawgrid()
        
}




























// I like the KrazyDad_spiral5 set of functions for its very slowly increasing/decreasing spiral.

function make_KrazyDad_spiral5 ( nbr_circles)   {  //  code by Jim Bumgardner, modified for this tiling project
  var width = 900;
  var height = 900;

   // var nbr_circles =10000;
  var deviation = 5/8.0;
  
  var phi = (Math.sqrt(5)+1)/2 - 1;            // golden ratio
  var golden_angle = phi*2*Math.PI;            // golden angle
  
  var lg_rad = width * .45;
  var lg_area = Math.pow(lg_rad,2)*Math.PI;
  
  var mean_area = lg_area / nbr_circles;
  
  var min_area = mean_area * (1-deviation);
  var max_area = mean_area * (1+deviation);
  
  var cum_area = 0;
  
  var fudge = .87; // Fudge factor, since our circles don't actually fill up space entirely.
  
  var cx = width/2;
  var cy = height/2;
  
  var hue_incr =  .1;
  var angle_offset = 0
   
  results = []                                      // global for now

  
  var sm_area = lg_area / nbr_circles; // Area of our little circles, if they filled the space entirely
  var sm_rad = Math.sqrt( sm_area / Math.PI ); // This is related to the equation area = pi r squared


  for (var i = 1; i <= nbr_circles; ++i) {
  
    // var angle = i*golden_angle + angle_offset;
   //var angle = i*golden_angle/6                        // another way to make 10 arms
  //var angle = i*36*Math.PI/180
  var angle = i*golden_angle/12
 // var angle = i*golden_angle/12 * 1/0.95
//var angle = i*golden_angle *4
var angle = i*18*Math.PI/180 * 1/0.95
var angle = i*18*Math.PI/180   // "almost" works.




  
    var ratio = i / nbr_circles;
//    var sm_area = min_area + ratio * (max_area - min_area);
//    var sm_rad = Math.sqrt( sm_area / Math.PI );
  
   // cum_area += sm_area;
      cum_area = i*sm_area;

    var spiral_rad = Math.sqrt( cum_area / Math.PI );
 
    var x_center = cx + Math.cos(angle) * spiral_rad;
    var y_center  = cy + Math.sin(angle) * spiral_rad;

    /*  
    var hue = hue_incr*i;
    hue -= Math.floor(hue);
    hue *= 360;
    hue = Math.round(hue)
    */

     //   results.push({x: x_center, y: y_center, myhue: hue })
      results.push({x: x_center, y: y_center })

  
    }
 return results
  
}


function call_KrazyDad_Spiral5 (n) {
   x_to_verts = []
   vertexArray = [] 
   v_index = 1;
   vertexArray[0] = settypecellvertex  // This shouldn't be used, but  
   allcells = [] 
   aci = 0;  

    var results = make_KrazyDad_spiral5(n)
    for (var i = n - 1 ; i--;) {
       if ((i+39) < n) {
        
       //   build_verts_and_faces([[results[i].x, results[i].y], [results[i+10].x, results[i+10].y], [results[i+27].x, results[i+27].y], [results[i+17].x, results[i+17].y]], "spiraledsquare");

       //    build_verts_and_faces([[results[i].x, results[i].y], [results[i+10].x, results[i+10].y], [results[i+39].x, results[i+39].y], [results[i+29].x, results[i+29].y]], "spiraledsquare");

      //  build_verts_and_faces([[results[i].x, results[i].y], [results[i+39].x, results[i+39].y], [results[i+68].x, results[i+68].y], [results[i+29].x, results[i+29].y]], "spiraledsquare");
    
      //   build_verts_and_faces([[results[i].x, results[i].y], [results[i+29].x, results[i+29].y], [results[i+97].x, results[i+97].y], [results[i+68].x, results[i+68].y]], "spiraledsquare");


 build_verts_and_faces([[results[i].x, results[i].y], [results[i+19].x, results[i+19].y], [results[i+39].x, results[i+39].y], [results[i+20].x, results[i+20].y]], "spiraledsquare");



       }
     }
     

      initialize()

ctxGrid.lineWidth = 0.4  // this is a bit arbitrary  -- but instead of shapesize/12, it must be much much smaller. 


      clearboard() 
      drawboard()  
      drawgrid()
        
}























function make_KrazyDad_spiral4 ( nbr_circles)   {  //  code by Jim Bumgardner, modified for this tiling project
  var width = 900;
  var height = 900;

   // var nbr_circles =10000;
  var deviation = 5/8.0;
  
  var phi = (Math.sqrt(5)+1)/2 - 1;            // golden ratio
  var golden_angle = phi*2*Math.PI;            // golden angle
  
  var lg_rad = width * .45;
  var lg_area = Math.pow(lg_rad,2)*Math.PI;
  
  var mean_area = lg_area / nbr_circles;
  
  var min_area = mean_area * (1-deviation);
  var max_area = mean_area * (1+deviation);
  
  var cum_area = 0;
  
  var fudge = .87; // Fudge factor, since our circles don't actually fill up space entirely.
  
  var cx = width/2;
  var cy = height/2;
  
  var hue_incr =  .1;
  var angle_offset = 0
   
  results = []                                      // global for now

  for (var i = 1; i <= nbr_circles; ++i) {
  
    // var angle = i*golden_angle + angle_offset;
var angle = i*golden_angle/6                        // another way to make 10 arms

  
    var ratio = i / nbr_circles;
    var sm_area = min_area + ratio * (max_area - min_area);
    var sm_rad = Math.sqrt( sm_area / Math.PI );
  
    cum_area += sm_area;
  
    var spiral_rad = Math.sqrt( cum_area / Math.PI );
 
    var x_center = cx + Math.cos(angle) * spiral_rad;
    var y_center  = cy + Math.sin(angle) * spiral_rad;

    /*  
    var hue = hue_incr*i;
    hue -= Math.floor(hue);
    hue *= 360;
    hue = Math.round(hue)
    */

     //   results.push({x: x_center, y: y_center, myhue: hue })
      results.push({x: x_center, y: y_center })

  
    }
 return results
  
}


function call_KrazyDad_Spiral4 (n) {
   x_to_verts = []
   vertexArray = [] 
   v_index = 1;
   vertexArray[0] = settypecellvertex  // This shouldn't be used, but  
   allcells = [] 
   aci = 0;  

    var results = make_KrazyDad_spiral4(n)
    for (var i = n - 1 ; i--;) {
       if ((i+97) < n) {
        
       //   build_verts_and_faces([[results[i].x, results[i].y], [results[i+10].x, results[i+10].y], [results[i+27].x, results[i+27].y], [results[i+17].x, results[i+17].y]], "spiraledsquare");

       //    build_verts_and_faces([[results[i].x, results[i].y], [results[i+10].x, results[i+10].y], [results[i+39].x, results[i+39].y], [results[i+29].x, results[i+29].y]], "spiraledsquare");

      //  build_verts_and_faces([[results[i].x, results[i].y], [results[i+39].x, results[i+39].y], [results[i+68].x, results[i+68].y], [results[i+29].x, results[i+29].y]], "spiraledsquare");
    
         build_verts_and_faces([[results[i].x, results[i].y], [results[i+29].x, results[i+29].y], [results[i+97].x, results[i+97].y], [results[i+68].x, results[i+68].y]], "spiraledsquare");



       }
     }
     

      initialize()

ctxGrid.lineWidth = 0.4  // this is a bit arbitrary  -- but instead of shapesize/12, it must be much much smaller. 


      clearboard() 
      drawboard()  
      drawgrid()
        
}




















function make_KrazyDad_spiral3 ( nbr_circles)   {  //  code by Jim Bumgardner, modified for this tiling project
  var width = 900;
  var height = 900;

   // var nbr_circles =10000;
  var deviation = 5/8.0;
  
  var phi = (Math.sqrt(5)+1)/2 - 1;            // golden ratio
  var golden_angle = phi*2*Math.PI;            // golden angle
  
  var lg_rad = width * .45;
  var lg_area = Math.pow(lg_rad,2)*Math.PI;
  
  var mean_area = lg_area / nbr_circles;
  
  var min_area = mean_area * (1-deviation);
  var max_area = mean_area * (1+deviation);
  
  var cum_area = 0;
  
  var fudge = .87; // Fudge factor, since our circles don't actually fill up space entirely.
  
  var cx = width/2;
  var cy = height/2;
  
  var hue_incr =  .1;
  var angle_offset = 0
   
  results = []                                      // global for now

  for (var i = 1; i <= nbr_circles; ++i) {
  
    // var angle = i*golden_angle + angle_offset;
var angle = i*golden_angle/2.1  // the golden angle produces 21 arms.  21/2.1 = 10 arms!  10 arms => 360 degrees/10 => 36 degrees each

  
    var ratio = i / nbr_circles;
    var sm_area = min_area + ratio * (max_area - min_area);
    var sm_rad = Math.sqrt( sm_area / Math.PI );
  
    cum_area += sm_area;
  
    var spiral_rad = Math.sqrt( cum_area / Math.PI );
 
    var x_center = cx + Math.cos(angle) * spiral_rad;
    var y_center  = cy + Math.sin(angle) * spiral_rad;

    /*  
    var hue = hue_incr*i;
    hue -= Math.floor(hue);
    hue *= 360;
    hue = Math.round(hue)
    */

     //   results.push({x: x_center, y: y_center, myhue: hue })
      results.push({x: x_center, y: y_center })

  
    }
 return results
  
}


function call_KrazyDad_Spiral3 (n) {
   x_to_verts = []
   vertexArray = [] 
   v_index = 1;
   vertexArray[0] = settypecellvertex  // This shouldn't be used, but  
   allcells = [] 
   aci = 0;  

    var results = make_KrazyDad_spiral3(n)
   // var resultslen = results.length // should be equal to n...
    for (var i = n - 1 ; i--;) {
       if ((i+27) < n) {
        
          build_verts_and_faces([[results[i].x, results[i].y], [results[i+10].x, results[i+10].y], [results[i+27].x, results[i+27].y], [results[i+17].x, results[i+17].y]], "spiraledsquare");
       }
     }
     

      initialize()

ctxGrid.lineWidth = 0.4  // this is a bit arbitrary  -- but instead of shapesize/12, it must be much much smaller. 


      clearboard() 
      drawboard()  
      drawgrid()
        
}



























function make_KrazyDad_spiral2 ( nbr_circles)   {  //  code by Jim Bumgardner, modified for this tiling project
  var width = 900;
  var height = 900;

   // var nbr_circles =10000;
  var deviation = 5/8.0;
  
  var phi = (Math.sqrt(5)+1)/2 - 1;            // golden ratio
  var golden_angle = phi*2*Math.PI;            // golden angle
  
  var lg_rad = width * .45;
  var lg_area = Math.pow(lg_rad,2)*Math.PI;
  
  var mean_area = lg_area / nbr_circles;
  
  var min_area = mean_area * (1-deviation);
  var max_area = mean_area * (1+deviation);
  
  var cum_area = 0;
  
  var fudge = .87; // Fudge factor, since our circles don't actually fill up space entirely.
  
  var cx = width/2;
  var cy = height/2;
  
  var hue_incr =  .1;
  var angle_offset = 0
   
  results = []                                      // global for now

  for (var i = 1; i <= nbr_circles; ++i) {
  
    var angle = i*golden_angle + angle_offset;
  
    var ratio = i / nbr_circles;
    var sm_area = min_area + ratio * (max_area - min_area);
    var sm_rad = Math.sqrt( sm_area / Math.PI );
  
    cum_area += sm_area;
  
    var spiral_rad = Math.sqrt( cum_area / Math.PI );
 
    var x_center = cx + Math.cos(angle) * spiral_rad;
    var y_center  = cy + Math.sin(angle) * spiral_rad;

    /*  
    var hue = hue_incr*i;
    hue -= Math.floor(hue);
    hue *= 360;
    hue = Math.round(hue)
    */

     //   results.push({x: x_center, y: y_center, myhue: hue })
      results.push({x: x_center, y: y_center })

  
    }
 return results
  
}


function call_KrazyDad_Spiral2 (n) {
   x_to_verts = []
   vertexArray = [] 
   v_index = 1;
   vertexArray[0] = settypecellvertex  // This shouldn't be used, but  
   allcells = [] 
   aci = 0;  

    var results = make_KrazyDad_spiral2(n)
   // var resultslen = results.length // should be equal to n...
    for (var i = n - 1 ; i--;) {
       if ((i+56) < n) {
        
          build_verts_and_faces([[results[i].x, results[i].y], [results[i+34].x, results[i+34].y], [results[i+55].x, results[i+55].y], [results[i+21].x, results[i+21].y]], "spiraledsquare");
       }
     }
     

      initialize()

ctxGrid.lineWidth = 0.4  // this is a bit arbitrary  -- but instead of shapesize/12, it must be much much smaller. 


      clearboard() 
      drawboard()  
      drawgrid()
        
}







//  Here is the Hex/Square Mix version by using Veronoi

// see http://krazydad.com/tutorials/circles_js/showexample.php?ex=phyllo_offset
//and
//     http://krazydad.com/tutorials/circles/showexample.php?ex=phyllo_animate
//and
// http://krazydad.com/tutorials/circles/
  

function call_KrazyDad_Spiral_Voronoi(n) {


 function make_krazydad_spiral (n) {

   function sq(n) {
        return Math.pow(n, 2)
    }


  var nbr_circles = n;
  var deviation = 5/8.0;
  
  var phi = (Math.sqrt(5)+1)/2 - 1;            // golden ratio
  var golden_angle = phi * Math.PI * 2;        // golden angle
  
  var width = 800;
  var height = 800;

  var lg_rad = width * .45;
  var lg_area = sq(lg_rad) * Math.PI;
  
  var mean_area = lg_area / nbr_circles;
  
  var min_area = mean_area * (1-deviation);
  var max_area = mean_area * (1+deviation);
  
  var cum_area = 0;
  
  var fudge = .87; // Fudge factor, since our circles don't actually fill up space entirely.
  
  var cx = width/2;
  var cy = height/2; 

  var results = []
  
  for (var i = 1; i <= nbr_circles; ++i) {
    var angle = i*golden_angle;
  
    var ratio = i /  nbr_circles;
    var sm_area = min_area + ratio * (max_area - min_area);
    var sm_dia = 2 * Math.sqrt( sm_area / Math.PI );
    var adj_sm_dia = sm_dia * fudge;
  
    cum_area += sm_area;
  
    var spiral_rad = Math.sqrt( cum_area / Math.PI );
  
    var x_center = cx + Math.cos(angle) * spiral_rad;
    var y_center  = cy + Math.sin(angle) * spiral_rad;
    results.push({x: x_center, y: y_center})
    
    //ellipse(x, y, adj_sm_dia, adj_sm_dia);
  }
  return results
}


    // first compute Voronoi, then erase the current memory

 // var  bbox = {xl:0, xr:mesh_x_size, yt:0, yb:mesh_y_size};
var  bbox = {xl:0, xr:800, yt:0, yb:800};

  voronoi = new Voronoi();

  var krazydad_results = make_krazydad_spiral(n)

  voronoi_result = voronoi.compute(krazydad_results, bbox);


 //  old_allcells = allcells
 //  old_aci = aci
   x_to_verts = []
   vertexArray = [] 
   v_index = 1;
   vertexArray[0] = settypecellvertex  // This shouldn't be used, but  
   allcells = [] 
   aci = 0;  
   // debugkeeptrack =  0;

     var resultslen = voronoi_result.cells.length
     for (var i = resultslen; i--;) {
        var resultcell = voronoi_result.cells[i]
        bogus_border_cell = false;

        if (resultcell.closeMe == false && resultcell.halfedges.length > 0) {
           var newcoords = []
           var candidate = []
           for (var j = resultcell.halfedges.length; j--;) {
               if (resultcell.halfedges[j].edge.rSite == null ) {  bogus_border_cell = true; break;}
               var newx = resultcell.halfedges[j].getEndpoint().x  
               var newy = resultcell.halfedges[j].getEndpoint().y 
               newx =  roundNumber(newx, 1) //Math.floor(newx)      //roundNumber(newx, 0)
               newy =  roundNumber(newy, 1) // Math.floor(newy)     // roundNumber(newy, 0)
               candidate = snap_to_closest_if_close_enough (newx, newy, newcoords, 1.6)        // instead of "1", the value of enough might have to be scaled
                                                                                  // ideally, it would be shapesize/10 or somesuch.
              if (detect_notflat_coord_duplicates(candidate, newcoords) == false) {
                      newcoords.push(candidate)  
              }
        
           }
           if (bogus_border_cell == false) {
             // build_verts_and_faces_veronoi_version (newcoords, "veronoi-derived cell");
              build_verts_and_faces(newcoords, "veronoi-derived cell");
           }
        }
      }
      initialize()
      clearboard() 
      drawboard()  
      drawgrid()
        

     // To do:   Garbage collect old_allcells by setting to [] (but see link below), or save it to use as an undo step (although after the undo, there will be more vertices unless old_vertexArray is created and restored.  

   //  see http://stackoverflow.com/questions/1232040/how-to-empty-an-array-in-javascript?rq=1
}



// call_KrazyDad_Spiral_Voronoi(200)

//  call_KrazyDad_Spiral_Voronoi(10000) // takes awile to generate but neat mix of hex and square grids!!!




// End of spiral section









//   EXPERIMENTAL SECTION FOR A GENERAL HEXAGONAL TILER

function hexagonal_tiling_in_general (xmax, ymax, unitcell_width, unitcell_height, hexfn) {  
 var x,y;
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<ymax; j+=1) {
       if (j % 2) { // the odd case
          y = j*(unitcell_height/2) - unitcell_height/2  //j*unitcell_height/2  -unitcell_height
          x = i*(unitcell_width*3/4*2)+unitcell_width*3/4
        }
       else { // the even case
          y = j*unitcell_height/2
          x = i*(unitcell_width*3/4*2)

       }
       // creates hexagons with flat tops and bottoms.  Swap x and y for pointy tops and bottoms. 
     hexfn(x,y,unitcell_width/2)
     }
 }
}

function hexagonal_tiling_in_general2 (xmax, ymax, unitcell_width, unitcell_height, offset,  hexfn) {  
 var x,y;
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<ymax; j+=1) {
          y = j*unitcell_height
          x = i*unitcell_width*1.5

         hexfn(x,y,unitcell_width/2)
         hexfn(x+unitcell_width*1.5/2,y+offset ,unitcell_width/2)

     }
 }
}


function  make_hexagonal_tile(x,y, sidelength) {
    var height = (Math.sqrt(3)/2)*sidelength  // half the height of the hexagon -- the height of any of the six equilateral triangles that mmake a hexagon
    build_verts_and_faces ([[x,y], [x+0.5*sidelength, y-height], [x+1.5*sidelength, y-height], [x+2*sidelength,y], [x+1.5*sidelength, y+height], [x+0.5*sidelength, y+height]], "hexagon"); 
}



function  make_double_hexagonal_tile(x,y, sidelength) {
    var height = (Math.sqrt(3)/2)*sidelength   
    build_verts_and_faces ([[x,y], [x+0.5*sidelength, y-height], [x+1.5*sidelength, y-height], [x+2*sidelength,y], [x+1.5*sidelength, y+height], [x+0.5*sidelength, y+height]], "hexagon"); 
   y = y + 2*height
   build_verts_and_faces ([[x,y], [x+0.5*sidelength, y-height], [x+1.5*sidelength/2, y-height], [x+2*sidelength,y], [x+1.5*sidelength, y+height], [x+0.5*sidelength, y+height]], "hexagon"); 
}
  

function  make_triple_hexagonal_tile(x,y, sidelength) {
    var height = (Math.sqrt(3)/2)*sidelength   
    build_verts_and_faces ([[x,y], [x+0.5*sidelength, y-height], [x+1.5*sidelength, y-height], [x+2*sidelength,y], [x+1.5*sidelength, y+height], [x+0.5*sidelength, y+height]], "hexagon"); 
   y = y + 2*height
   build_verts_and_faces ([[x,y], [x+0.5*sidelength, y-height], [x+1.5*sidelength/2, y-height], [x+2*sidelength,y], [x+1.5*sidelength, y+height], [x+0.5*sidelength, y+height]], "hexagon"); 
   y = y + 2*height
   build_verts_and_faces ([[x,y], [x+0.5*sidelength, y-height], [x+1.5*sidelength/2, y-height], [x+2*sidelength,y], [x+1.5*sidelength, y+height], [x+0.5*sidelength, y+height]], "hexagon"); 
}


function  make_double_wide_hex(x,y, sidelength) {
    var height = (Math.sqrt(3)/2)*sidelength   
    build_verts_and_faces ([[x,y], [x+0.5*sidelength, y-height], [x+1.5*sidelength, y-height], [x+2*sidelength,y], [x+1.5*sidelength, y+height], [x+0.5*sidelength, y+height]], "hexagon"); 
   x = x +sidelength*2*1.5/2
   y = y + height
   build_verts_and_faces ([[x,y], [x+0.5*sidelength, y-height], [x+1.5*sidelength, y-height], [x+2*sidelength,y], [x+1.5*sidelength, y+height], [x+0.5*sidelength, y+height]], "hexagon"); 
}
  

function  make_double_hex(x,y, unitcell_width) {
    var sidelength = unitcell_width/3
    var height = (Math.sqrt(3)/2)*sidelength   
    build_verts_and_faces ([[x,y], [x+0.5*sidelength, y-height], [x+1.5*sidelength, y-height], [x+2*sidelength,y], [x+1.5*sidelength, y+height], [x+0.5*sidelength, y+height]], "hexagon"); 
   x = x +sidelength*3/2
   y = y + height
   build_verts_and_faces ([[x,y], [x+0.5*sidelength, y-height], [x+1.5*sidelength, y-height], [x+2*sidelength,y], [x+1.5*sidelength, y+height], [x+0.5*sidelength, y+height]], "hexagon"); 
}


function  make_square(x,y, unitcell_width) {
    build_verts_and_faces ([[x,y], [x+unitcell_width, y], [x+unitcell_width, y+unitcell_width], [x,y+unitcell_width]], "square"); 
}  

function  make_square_zig(x,y, unitcell_width) {
    var width = unitcell_width/2
    build_verts_and_faces ([[x,y], [x+width, y], [x+width, y+width], [x,y+width]], "square"); 
    x= x + width
    y = y + width
    build_verts_and_faces ([[x,y], [x+width, y], [x+width, y+width], [x,y+width]], "square"); 
}  

               


function make_sideways_pentagon(x, y, radius) {  
  var pentcoords = []
  for (i = 0; i < 5; i++) {
    pentcoords[i] = [x + radius * Math.cos(2 * Math.PI * i / 5) ,  y + radius * Math.sin(2 * Math.PI * i / 5) ]   // cos and sin swapped
  }
  build_verts_and_faces(pentcoords, "Pentagon")
}

function make_pentagon(x, y, radius) {  
  var pentcoords = []
  for (i = 0; i < 5; i++) {
    pentcoords[i] = [x + radius * Math.sin(2 * Math.PI * i / 5) ,  y + radius * Math.cos(2 * Math.PI * i / 5) ]   
  }
  build_verts_and_faces(pentcoords, "Pentagon")
}

/*
function make_pentagon_back_to_back(x, y, radius) {  
    pentcoords1 = []
  for (i = 0; i < 5; i++) {
    pentcoords1[i] = [x + radius * Math.sin(2 * Math.PI * i / 5) ,  y + radius * Math.cos(2 * Math.PI * i / 5) ]   
  }
  build_verts_and_faces(pentcoords1, "Pentagon")
     height =  pentcoords1[0][1] - pentcoords1[3][1]
  y =  y - 4*radius + height
   radius = -radius
      pentcoords2 = []
  for (i = 0; i < 5; i++) {
    pentcoords2[i] = [x + radius * Math.sin(2 * Math.PI * i / 5) ,  y + radius * Math.cos(2 * Math.PI * i / 5) ]   
  }
  build_verts_and_faces(pentcoords2, "Pentagon")

}
*/


function make_pentagon_back_to_back(x, y) {  
    radius = 10
    pentcoords1 = []
  for (i = 0; i < 5; i++) {
    pentcoords1[i] = [x + radius * Math.sin(2 * Math.PI * i / 5) ,  y + radius * Math.cos(2 * Math.PI * i / 5) ]   
  }
  build_verts_and_faces(pentcoords1, "Pentagon")
     height =  Math.abs(pentcoords1[0][1] - pentcoords1[3][1])
     midheight =  Math.abs(pentcoords1[1][1] - pentcoords1[3][1])


    pentcoords2 = [[], [], [], [], []]
 pentcoords2[2] =  pentcoords1[2] 
 pentcoords2[3] =  pentcoords1[3] 

 pentcoords2[0][0] =  pentcoords1[0][0]
 pentcoords2[1][0] =  pentcoords1[1][0]
 pentcoords2[4][0] =  pentcoords1[4][0]

 pentcoords2[0][1] =   pentcoords1[0][1] - 2*height
 pentcoords2[1][1] =   pentcoords1[1][1] - 2*midheight
 pentcoords2[4][1] =   pentcoords1[4][1] - 2*midheight

   build_verts_and_faces(pentcoords2, "Pentagon")

    thinrhombcoords1 = [pentcoords1[1], pentcoords1[2] , pentcoords2[1], []]
   thinrhombcoords1[3][0] = pentcoords1[2][0] + 2*(Math.abs( pentcoords1[2][0] - pentcoords1[1][0]))
   thinrhombcoords1[3][1] =  pentcoords1[2][1]
  build_verts_and_faces(thinrhombcoords1, "thin_rhomb")


 
}


/*
function make_pentagon_durer1(x, y) {  
    radius = 10
    pentcoords1 = []
  for (i = 0; i < 5; i++) {
    pentcoords1[i] = [x + radius * Math.sin(2 * Math.PI * i / 5) ,  y + radius * Math.cos(2 * Math.PI * i / 5) ]   
  }
  build_verts_and_faces(pentcoords1, "Pentagon")
     height =  Math.abs(pentcoords1[0][1] - pentcoords1[3][1])
     midheight =  Math.abs(pentcoords1[1][1] - pentcoords1[3][1])


    pentcoords2 = [[], [], [], [], []]
 pentcoords2[2] =  pentcoords1[2] 
 pentcoords2[3] =  pentcoords1[3] 

 pentcoords2[0][0] =  pentcoords1[0][0]
 pentcoords2[1][0] =  pentcoords1[1][0]
 pentcoords2[4][0] =  pentcoords1[4][0]

 pentcoords2[0][1] =   pentcoords1[0][1] - 2*height
 pentcoords2[1][1] =   pentcoords1[1][1] - 2*midheight
 pentcoords2[4][1] =   pentcoords1[4][1] - 2*midheight

   build_verts_and_faces(pentcoords2, "Pentagon")

    thinrhombcoords1 = [pentcoords1[1], pentcoords1[2] , pentcoords2[1], []]
   thinrhombcoords1[3][0] = pentcoords1[2][0] + 2*(Math.abs( pentcoords1[2][0] - pentcoords1[1][0]))
   thinrhombcoords1[3][1] =  pentcoords1[2][1]
  build_verts_and_faces(thinrhombcoords1, "thin_rhomb")

    pentcoords4 = [[], [], [], [], []]
    pentcoords3 = [[], [], [], [], []]
    thinrhombcoords2 = [[], [], [], []]


   xoffset = Math.abs(pentcoords1[0][0] - pentcoords1[1][0])
   yoffset = Math.abs(pentcoords1[0][1] - pentcoords2[1][1])

 for (i = 0; i < 5; i++) {
    pentcoords3[i] = [pentcoords1[i][0] + xoffset, pentcoords1[i][1] + yoffset]
    pentcoords4[i] = [pentcoords2[i][0] + xoffset, pentcoords2[i][1] + yoffset]

  }

 for (i = 0; i < 4; i++) {

    thinrhombcoords2[i] = [thinrhombcoords1[i][0] + xoffset, thinrhombcoords1[i][1] + yoffset]
  }


   build_verts_and_faces(pentcoords3, "Pentagon")
   build_verts_and_faces(pentcoords4, "Pentagon")
   build_verts_and_faces(thinrhombcoords2, "thin_rhomb")




 
}


*/





// how about this:  let pentcoords[2] and pentcoords[3] be the same.  let pentcords[0 and 1 and 4] have the same x, but subtract ? from pentcoords[1 and 4] and ?? from pentcoords[0]
 
function make_pentagon_from_top(x, y, radius) {  
  y = y - radius
  var pentcoords = []
  for (i = 0; i < 5; i++) {
    pentcoords[i] = [x + radius * Math.sin(2 * Math.PI * i / 5) ,  y + radius * Math.cos(2 * Math.PI * i / 5) ]   
  }
  build_verts_and_faces(pentcoords, "Pentagon")
}


//  hexagonal_tiling_in_general (10, 10, 2,  Math.sqrt(3), make_hexagonal_tile)
//         initialize()


// hexagonal_tiling_in_general (10, 10, 2,  Math.sqrt(3)*2, make_double_hexagonal_tile)






function square_tiling_in_general (xmax, ymax, unitcell_width, unitcell_height, tilingfn) {  
 var x,y;
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<ymax; j+=1) {
          y = j*unitcell_height
          x = i*unitcell_width 

         tilingfn(x,y,unitcell_width, unitcell_height)

     }
 }
}



function make_durer_pentagon_and_thinrhomb_periodic_tiling(xmax, ymax) {  
  var radius = 5
  var x = 10
  var y = 10
  var pentcoords1 = []
  var pentcoords2 = [[], [], [], [], []]
  var pentcoords4 = [[], [], [], [], []]
  var pentcoords3 = [[], [], [], [], []]
  var thinrhombcoords1 = []
  var thinrhombcoords2 = [[], [], [], []]

  for (i = 0; i < 5; i++) {
    pentcoords1[i] = [x + radius * Math.sin(2 * Math.PI * i / 5) ,  y + radius * Math.cos(2 * Math.PI * i / 5) ]   
  }
  
   var height =     Math.abs(pentcoords1[0][1] - pentcoords1[3][1])
   var midheight =  Math.abs(pentcoords1[1][1] - pentcoords1[3][1])


   pentcoords2[2] =  pentcoords1[2] 
   pentcoords2[3] =  pentcoords1[3] 

   pentcoords2[0][0] =  pentcoords1[0][0]
   pentcoords2[1][0] =  pentcoords1[1][0]
   pentcoords2[4][0] =  pentcoords1[4][0]

   pentcoords2[0][1] =   pentcoords1[0][1] - 2*height
   pentcoords2[1][1] =   pentcoords1[1][1] - 2*midheight
   pentcoords2[4][1] =   pentcoords1[4][1] - 2*midheight


   thinrhombcoords1 = [pentcoords1[1], pentcoords1[2] , pentcoords2[1], []]
   thinrhombcoords1[3][0] = pentcoords1[2][0] + 2*(Math.abs( pentcoords1[2][0] - pentcoords1[1][0]))
   thinrhombcoords1[3][1] =  pentcoords1[2][1]


   var xoffset = Math.abs(pentcoords1[0][0] - pentcoords1[1][0])
   var yoffset = Math.abs(pentcoords1[0][1] - pentcoords2[1][1])

   for (i = 0; i < 5; i++) {
      pentcoords3[i] = [pentcoords1[i][0] + xoffset, pentcoords1[i][1] + yoffset]
      pentcoords4[i] = [pentcoords2[i][0] + xoffset, pentcoords2[i][1] + yoffset]
   }

   for (i = 0; i < 4; i++) {
     thinrhombcoords2[i] = [thinrhombcoords1[i][0] + xoffset, thinrhombcoords1[i][1] + yoffset]
   }
  var data = [{face: pentcoords1, name: "pentagon"},
              {face: pentcoords2, name: "pentagon"},
              {face: thinrhombcoords1, name: "rhomb"},

              {face: pentcoords3, name: "pentagon"},
              {face: pentcoords4, name: "pentagon"},
              {face: thinrhombcoords2, name: "rhomb"} ]

   square_tiling_from_data (xmax, ymax, xoffset*2, yoffset*2, data)
 
}




/*
data:
[  {face:  [[1,1],[2,1],[2,2],[1,2]], name: "square"},
   {face:  [[2,1],[2,2],[2,3],[1,3]], name: "square"},
   {face:  [[1,3],[2,3],[2,4],[1,4]], name: "square"}
]


*/

bob = [  {face:  [[1,1],[2,1],[2,2],[1,2]], name: "square"},
         {face:   [[1,2],[2,2],[2,3],[1,3]], name: "square"},
]

//bob = [  {face:  [[1,1],[2,1],[2,2],[1,2]], name: "square"}]

function square_tiling_from_data (xmax, ymax, offset_width, offset_height, verts_and_faces) {  
 var x,y;
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<ymax; j+=1) {
          y = j*offset_height
          x = i*offset_width 
          for (var f = verts_and_faces.length; f--;) {
            var theface = verts_and_faces[f].face
            var tempface = Array(theface.length)
            for (var v = theface.length; v--;) {
                tempface[v] = [theface[v][0] + x, theface[v][1] + y]
            }
            
            build_verts_and_faces (tempface,  verts_and_faces[f].name)
          }
    }
  }
}




/*
hexagonal_tiling_in_general2 (10, 10, 2,  Math.sqrt(3)*1, Math.sqrt(3)*1/2 , make_hexagonal_tile)
hexagonal_tiling_in_general2 (10, 10, 2,  Math.sqrt(3)*2, Math.sqrt(3)*2/4 , make_double_hexagonal_tile)
hexagonal_tiling_in_general2 (10, 10, 2,  Math.sqrt(3)*3, Math.sqrt(3)*3/6 , make_triple_hexagonal_tile)

hexagonal_tiling_in_general2 (10, 10, 4,  Math.sqrt(3), Math.sqrt(3)*1/2 , make_double_wide_hex)

square_tiling_in_general (10, 10, 3.5, Math.sqrt(3)*1.5, make_double_wide_hex)
square_tiling_in_general (10, 10, 1,1 ,make_square)
square_tiling_in_general (10, 10, 2,2 ,make_square_zig)

square_tiling_in_general (10, 10, 3,Math.sqrt(3) ,make_double_hex)  // this one works


square_tiling_in_general (100, 100, 3,Math.sqrt(3) ,make_double_hex)

initialize()

  document.getElementById("Meshmakers_Div").setAttribute("style", "display: none;")  

The anwer is to not think in terms of unitcell_width and unitcell_height, but rather in terms of "width until the computer should tile again"
and "height until the computer should tile again."

square_tiling_in_general (10, 10, 19.021130325903073, 36.180339887498945, make_pentagon_back_to_back)


document.getElementById("Meshmakers_Div").setAttribute("style", "display: none;")  
square_tiling_in_general (50, 50, 19.021130325903073, 58.54101966249685, make_pentagon_durer1)
initialize()


document.getElementById("Meshmakers_Div").setAttribute("style", "display: none;")  
make_durer_pentagon_and_thinrhomb_periodic_tiling(200, 50) 
initialize()


*/


function make_martini_lattice_tiling (xmax, ymax) {  
 var x,y;
 var height = Math.sqrt(3)/2
 xmax = Math.floor(xmax/1.5) // to prevent twice as many columns as requested
 ymax = Math.floor(ymax*1.5) // to prevent half as many rows as requested
 for (var i = 0; i <xmax; i+=1) {
     for (var j = 0; j<=ymax; j+=1) {
       if (j % 2) { // the odd case
          y = j*height-height*2
          x = i*3+1.5
        }
       else { // the even case
          y = j*height
          x = i*3
       }
       // creates hexagons with flat tops and bottoms.  Swap x and y for pointy tops and bottoms. 
       build_verts_and_faces ([[x+0.5/2, y-height/2], [x+0.5, y-height], [x+1, y-height], [x+1.75,y-height/2], [x+2,y], [x+1.75, y+height/2], [x+1, y+height], [x+0.5, y+height],[x+0.5/2, y+height/2]], "enneagon");  
       build_verts_and_faces ([[x-0.5,y],[x+0.5/2, y-height/2], [x+0.5/2, y+height/2]], "triangle");    
       
     }
 }
}
/*
//An example of use:
make_martini_lattice_tiling (100,100)
 document.getElementById("Meshmakers_Div").setAttribute("style", "display: none;")  
initialize()

// B26/S35 was one of my original examples.  Note that Starwars and B2/S2/C4 work too
// Starwars has three directions for spaceships and B2/S2/C4 spaceships use the *other* three directions.
//   In other words...
//
//    Note that this tiling has three fold, not six fold, symmetry! (Obvious once you look at the tiles, but...)
//
*/

Anon7 - 2021