Site hosted by Angelfire.com: Build your free website today!
import javax.swing.*;
import java.awt.*;
import java.lang.Boolean;
import java.lang.String;

public class Tiler extends JApplet {

String tileName = "6_4 6_4 - 2D"; 
// we could check to see if type is right
  int firstPolygonSize = 6;
  int secondPolygonSize = 6;

// 0-net symmetry, 1-net sym. map, 2-adjacent, 3-adj. map, 4-size
// 5-BeginAt, 6-orientation, 7-stepsize (stepsize is -1 or 1 from orientation)
  int netEdgeData [][]= {
    { 0,1,2,3,4,5, 6,7,8,9,10,11 },
    { 0,0,0,0,0,0, 0,0,0,0,0,0},
    { 11,3,10,1,9,7, 8,5,6,4,2,0 },
    { 3 ,2,2 ,2,3,2, 2,2,2,3,2,3 },
    { 0,0,0,0,0,0, 0,0,0,0,0,0 },
    { 0,0,0,0,0,0, 0,0,0,0,0,0 },
    { 0,0,0,0,0,0, 0,0,0,0,0,0 },
    { 1,1,1,1,1,1, 1,1,1,1,1,1 }
  };

  int [][] netAngles = {
    { 1,0,0,0,0,0, 1,0,1,0,0,0,  360 },
    { 0,1,0,1,0,0, 0,0,0,0,0,1,  360 },
    { 0,0,1,0,1,0, 0,0,0,0,1,0,  360 },
    { 0,0,0,0,0,1, 0,1,0,1,0,0,  360 }
  };

// this array could be generated by the above...
  int [][] netEdgeGrow = {
    { 1,1,1,1,1,1, 1,1,1,1,1,1,  6,6 },
    { 1,0,0,0,0,0, 0,0,0,0,0,1,  1,1 },
    { 0,1,0,1,0,0, 1,0,1,0,0,0,  2,2 }, // combined two
    { 0,0,1,0,0,0, 0,0,0,0,1,0,  1,1 },
    { 0,0,0,0,1,0, 0,0,0,1,0,0,  1,1 },
    { 0,0,0,0,0,1, 0,1,0,0,0,0,  1,1 }
  };

  int tileLength = 10; // how many edge segments per tile - allow 6 + n
    

// only the above should change for different tilings.
// it seems that netEdgeGrow causes errors when less than 3

// these three arrays are always the same
// for transitive maps - edge to edge to edge
  int [][] mapping = {
    { 0,1,2,3 },
    { 1,0,3,2 },
    { 2,3,0,1 },
    { 3,2,1,0 }
  };

// to combine mappings to find symmetry
  int [][] edgeSymmetry = {
    { 0,1,2,3 },
    { 1,1,2,2 },
    { 2,2,2,2 },
    { 3,2,2,3 }
  };

// to find the lowest equivalent mapping in that symmetry
  int [][] symmetryToMap = {
    { 0,1,2,3 },
    { 0,0,2,2 },
    { 0,0,0,0 },
    { 0,1,1,0 }
  };

  int allPrint = 0; // 0 means don't print all. 1 means print all.
  int netEdgesSum = firstPolygonSize + secondPolygonSize; // How many edges - both net-tiles
  int maxCounter = netEdgeGrow.length; // how many levels of netEdgeGrow
//  int maxCounter = 4; // so that we don't have to try so many...

  int orientation, offset;
  //will fill in these arrays partially up to the counter, repeating through all possible
  int sum [] = new int[maxCounter];    // how many of that netEdgeGrow
  int first [] = new int[maxCounter];  // partial sum of length of first polygon
  int second [] = new int[maxCounter]; // partial sum of length of second polygon
  int repeat [] = new int[maxCounter]; // 0 = repeat, 1 = stop this iteration
  int counter, currentSum;

  //This is a hack to avoid an ugly error message in java 1.1
  public Tiler() {
    getRootPane().putClientProperty("defeatSystemEventQueueCheck",
                                    Boolean.TRUE);
  }

  public void init() {
  //    specify();
      cycle();
  }
    
  public void cycle() {
    sum[0] = 1;
    first[0]=firstPolygonSize;
    second[0]=secondPolygonSize;
    counter=1;
    sum[1] = 0;
    while (counter > 0) {
      first[counter] = first[counter-1] +
                       sum[counter]*netEdgeGrow [counter][netEdgesSum];
      second[counter] = second[counter-1] +
                        sum[counter]*netEdgeGrow [counter][netEdgesSum+1];
      if (first[counter] > tileLength) repeat[counter] = 1;
      if (second[counter] > tileLength) repeat[counter] = 1;
      while (repeat[counter] < 1) {
        counter++;
        repeat[counter]=0;
        sum[counter] = 0;
        // this sets the final amount exact for one polygon
        if (counter == maxCounter-1) {
          // need both these ifs to avoid dividing by zero
          if ( netEdgeGrow [counter][netEdgesSum] == 0) 
          sum[counter] = (tileLength-second[counter-1])/
                          netEdgeGrow [counter][netEdgesSum+1];
          if ( netEdgeGrow [counter][netEdgesSum] != 0) 
          sum[counter] = (tileLength-first[counter-1])/
                          netEdgeGrow [counter][netEdgesSum];
          first[counter] = first[counter-1]+
                           sum[counter]*netEdgeGrow [counter][netEdgesSum];
          second[counter] = second[counter-1] +
                            sum[counter]*netEdgeGrow [counter][netEdgesSum+1];
          // this loop is only if both tiles are correct length
          if ((first[counter] == tileLength) &&
              (second[counter] == tileLength)) {
              
            // sets the size row of netEdgeData by adding sum values from netEdgeGrow
            for (int counter2 = 0; counter2 < netEdgesSum; counter2++) {
              currentSum = 0;
              for (int sizeCounter = 0;
                   sizeCounter < maxCounter; sizeCounter++) {
                currentSum = currentSum +
                 netEdgeGrow[sizeCounter][counter2]*sum[sizeCounter];
              }
              netEdgeData [4][counter2] = currentSum;
            }

            // sets the beginAt row of netEdgeData for the first polygon
            for (int counter2 = 1; counter2 < firstPolygonSize;
                 counter2++) {
              netEdgeData[5][counter2] = (netEdgeData[5][counter2-1]+
               netEdgeData [4][counter2-1]);
            }

//  for (orientation = 1; orientation <2; orientation++) {
            for (orientation = 0; orientation < 2; orientation++) {
              // set netEdgeData orientation and stepsize
              for (int counter2 = firstPolygonSize;
                   counter2 < netEdgesSum ; counter2++) {
                netEdgeData[6][counter2] = orientation;
                netEdgeData[7][counter2] = 1-2*orientation;
              }     

              //change the size row of netEdgeData for 2nd polygon if needed
              if (orientation == 1) {
                for (int counter2 = firstPolygonSize;
                     counter2 < netEdgesSum ; counter2++) {
                  netEdgeData [4][counter2] = -1*netEdgeData [4][counter2];
                }
              }
//              for (offset = 2; offset < 4; offset++) {
              for (offset = 0; offset < tileLength; offset++) {


                // sets the beginAt row of netEdgeData for 2nd polygon
                // we must add tileLength to ensure is positive after MOD
                // the zero vertex is the base to measure from
                netEdgeData[5][firstPolygonSize] =
                 (offset-orientation+tileLength)%tileLength;
                for (int counter2 = firstPolygonSize+1;
                 counter2 < netEdgesSum ; counter2++) {
                   netEdgeData[5][counter2] = (netEdgeData[5][counter2-1]+
                   netEdgeData [4][counter2-1]+tileLength) % tileLength;
                }

                adjacentSetUp();  // should cycle through all possiblities
              
              } // end offset loop
            } // end orientation loop
          } // end both first and second == tileLength
          counter--;    
          sum[counter]++;
        } // end if counter == maxcounter-1
        first[counter] = first[counter-1]+
                         sum[counter]*netEdgeGrow [counter][netEdgesSum];
        second[counter] = second[counter-1] +
                          sum[counter]*netEdgeGrow [counter][netEdgesSum+1];
        if (first[counter] > tileLength) repeat[counter] = 1;
        if (second[counter] > tileLength) repeat[counter] = 1;
      } // end while (repeat[counter] < 1)
      counter--;
      sum[counter]++;
    } // end while counter>0
System.out.println("the end");
  } // end cycle()

  public void specify() {
    orientation = 0;
    offset = 6;
    sum[0] = 1;
    sum[1] = 2;
    sum[2] = 2;
    sum[3] = 0;
    sum[4] = 0;
    sum[5] = 0;
    sum[6] = 0;
    sum[7] = 0;
//    sum[8] = 1;
//    sum[9] = 1;
          
    // sets the size row of netEdgeData by adding sum values from netEdgeGrow
    for (int counter2 = 0; counter2 < netEdgesSum; counter2++) {
         currentSum = 0;
         for (int sizeCounter = 0;
            sizeCounter < maxCounter; sizeCounter++) {
             currentSum = currentSum +
              netEdgeGrow[sizeCounter][counter2]*sum[sizeCounter];
         }
         netEdgeData [4][counter2] = currentSum;
    }

    // should check if  same size polygons
        
    // sets the beginAt row of netEdgeData for the first polygon
    for (int counter2 = 1; counter2 < firstPolygonSize; counter2++) {
         netEdgeData[5][counter2] = (netEdgeData[5][counter2-1]+
         netEdgeData [4][counter2-1]);
    }

    // set netEdgeData orientation and stepsize
    for (int counter2 = firstPolygonSize; counter2 < netEdgesSum ; counter2++) {
          netEdgeData[6][counter2] = orientation;
          netEdgeData[7][counter2] = 1-2*orientation;
    }     

    //change the size row of netEdgeData for 2nd polygon if needed
    if (orientation == 1) {
       for (int counter2 = firstPolygonSize;
            counter2 < netEdgesSum ; counter2++) {
           netEdgeData [4][counter2] = -1*netEdgeData [4][counter2];
       }
    }

    // sets the beginAt row of netEdgeData for 2nd polygon
    // we must add tileLength to ensure is positive after MOD
    // the zero vertex is the base to measure from
    netEdgeData[5][firstPolygonSize] =
      (offset-orientation+tileLength)%tileLength;
    for (int counter2 = firstPolygonSize+1;
         counter2 < netEdgesSum ; counter2++) {
         netEdgeData[5][counter2] = (netEdgeData[5][counter2-1]+
         netEdgeData [4][counter2-1]+tileLength) % tileLength;
    }

    adjacentSetUp();  // should print the one specific example.
              
  } // end specify()

    
  void adjacentSetUp () {

    // print ID information
    System.out.println("Name: "+tileName);
    System.out.println("orient: " + orientation + " offset: " + offset);
    System.out.print("sum:");
    for (int i = 0; i<maxCounter;i++) {
      System.out.print(" "+sum[i]);
    }
    System.out.println();

    if (allPrint == 1) {
      // print net data.
      System.out.println("NetEdgeData");
      for (int i = 0;i<8;i++) {
        for (int j = 0;j<netEdgesSum;j++) {
          System.out.print("."+netEdgeData[i][j]);
        }
        System.out.println();
      } // end net data
    
      System.out.println("NetAngles");
      for (int i = 0;i<netAngles.length;i++) {
        for (int j = 0;j<netEdgesSum+1;j++) {
          System.out.print("/"+netAngles[i][j]);
        }
        System.out.println();
      } //end net angles
      
      System.out.println("NetEdgeGrow");
      for (int i = 0;i<netEdgeGrow.length;i++) {
        for (int j = 0;j<netEdgesSum+2;j++) {
          System.out.print("."+netEdgeGrow[i][j]);
        }
        System.out.println();
      } // end net egde grow
    } // end allPrint
    
// 0-edge symmetry, 1-first edge tile sym., 2-first edge tile sym. map
// 3-second edge tile sym., 4-second edge tile sym. map, 5-first tile adj.
// 6-first tile adj. map, 7-second tile adj., 8-second tile adj. map
// 9-resulting edge, 10-resulting edge map (both init to self)
    int [][] tileEdges = new int [11][tileLength];

// the second array index holds the angles followed by the sum in degrees
    int [] [] tileAngles = new int [netAngles.length+
                             2*(tileLength*2-netEdgesSum)][tileLength+1];

    // put netAngles in tileAngles
    for (int i = 0; i< netAngles.length;i++) {
      // to make sure that all is zero to start.
      for (int j = 0; j<tileLength;j++) {
        tileAngles [i][j] = 0;
      }
      for (int j =0; j< netEdgesSum;j++) {
        int nowAngle = (netEdgeData [5][j]+
                        netEdgeData[6][j]+tileLength)%tileLength;
        tileAngles [i][nowAngle]=
                           tileAngles [i][nowAngle]+netAngles[i][j];
      }
      // set the sum in degrees
      tileAngles [i][tileLength]=netAngles [i][netEdgesSum];
    }
      
    int angleCounter = netAngles.length;

    // first edge tile sym
    for (int i = 0;i<firstPolygonSize;i++) {
      int orient1 = netEdgeData [6][i];
      int edge2 = netEdgeData[0][i];
      int map2 = netEdgeData [1][i];
      int orient2 = netEdgeData [6][edge2];
      int sameOriented =mapping[orient1][orient2];
      int newMap = mapping [sameOriented] [map2];
      int size = Math.abs(netEdgeData[4][i]);
      if (size > 1) {
        int begin1 = netEdgeData[5][i];
        int begin2 = netEdgeData[5][edge2];
        int step1 = netEdgeData[7][i];
        int step2 = netEdgeData[7][edge2];
        if (map2==1 || map2 ==3) {
            begin2 = (begin2 + (size-1)*step2 + tileLength)%tileLength;
            step2 = -1*step2;
        }
        for (int i2 = 0; i2 < size; i2++) {
            if (i2 != size-1) {
                // we use ++, -- in case they are the same
                // (step# +1)/2 gives the larger of the two.
                tileAngles[angleCounter][(begin1+(step1+1)/2+tileLength)%tileLength]++;
                tileAngles[angleCounter][(begin2+(step2+1)/2+tileLength)%tileLength]--;
//  tileAngles[angleCounter][tileLength]=0;
                angleCounter++;
            }

            tileEdges[1][begin1] = begin2;
            tileEdges[2][begin1] = newMap;
            begin1 = (begin1 + step1 + tileLength)%tileLength;
            begin2 = (begin2 + step2 + tileLength)%tileLength;
        }
      } // end size > 1
      if (size == 1) {
          int begin1 = netEdgeData[5][i];
          tileEdges[1][begin1]= netEdgeData[5][edge2];
          tileEdges[2][begin1]= newMap;
      } // end size = 1     
    } //end first edge tile sym.

    // second edge tile sym
    for (int i = firstPolygonSize;i<netEdgesSum;i++) {
      int orient1 = netEdgeData [6][i];
      int edge2 = netEdgeData[0][i];
      int map2 = netEdgeData [1][i];
      int orient2 = netEdgeData [6][edge2];
      int sameOriented =mapping[orient1][orient2];
      int newMap = mapping [sameOriented] [map2];
      int size = Math.abs(netEdgeData[4][i]);
      if (size > 1) {
        int begin1 = netEdgeData[5][i];
        int begin2 = netEdgeData[5][edge2];
        int step1 = netEdgeData[7][i];
        int step2 = netEdgeData[7][edge2];
        if (map2==1 || map2 ==3) {
            begin2 = (begin2 + (size-1)*step2 + tileLength)%tileLength;
            step2 = -1*step2;
        }
        for (int i2 = 0; i2 < size; i2++) {
            // for internal angles of segment
            if (i2 != size-1) {
                // we use ++, -- in case they are the same
                // (step# +1)/2 gives the larger of the two.
                tileAngles[angleCounter][(begin1+(step1+1)/2+tileLength)%tileLength]++;
                tileAngles[angleCounter][(begin2+(step2+1)/2+tileLength)%tileLength]--;
//  tileAngles[angleCounter][tileLength]=0;
                angleCounter++;
            }
            tileEdges[3][begin1] = begin2;
            tileEdges[4][begin1] = newMap;
            begin1 = (begin1 + step1 + tileLength)%tileLength;
            begin2 = (begin2 + step2 + tileLength)%tileLength;
        }
      } // end size > 1
      if (size == 1) {
          int begin1 = netEdgeData[5][i];
          tileEdges[3][begin1]= netEdgeData[5][edge2];
          tileEdges[4][begin1]= newMap;
      } // end size = 1     
    } //end second edge tile sym.

    // first adj sym
    for (int i = 0;i<firstPolygonSize;i++) {
      int orient1 = netEdgeData [6][i];
      int edge2 = netEdgeData[2][i];
      int map2 = netEdgeData [3][i];
      int orient2 = netEdgeData [6][edge2];
      int sameOriented =mapping[orient1][orient2];
      int newMap = mapping [sameOriented] [map2];
      int size = Math.abs(netEdgeData[4][i]);
      if (size > 1) {
        int begin1 = netEdgeData[5][i];
        int begin2 = netEdgeData[5][edge2];
        int step1 = netEdgeData[7][i];
        int step2 = netEdgeData[7][edge2];
        if (map2==1 || map2 ==3) {
            begin2 = (begin2 + (size-1)*step2 + tileLength)%tileLength;
            step2 = -1*step2;
        }
        for (int i2 = 0; i2 < size; i2++) {
            if (i2 != size-1) {
                // we use ++, -- in case they are the same
                // (step# +1)/2 gives the larger of the two.
                tileAngles[angleCounter][(begin1+(step1+1)/2+tileLength)%tileLength]++;
                tileAngles[angleCounter][(begin2+(step2+1)/2+tileLength)%tileLength]++;
                tileAngles[angleCounter][tileLength]=360;
                angleCounter++;
            }
            tileEdges[5][begin1] = begin2;
            tileEdges[6][begin1] = newMap;
            begin1 = (begin1 + step1 + tileLength)%tileLength;
            begin2 = (begin2 + step2 + tileLength)%tileLength;
        }
      } // end size > 1
      if (size == 1) {
          int begin1 = netEdgeData[5][i];
          tileEdges[5][begin1]= netEdgeData[5][edge2];
          tileEdges[6][begin1]= newMap;
      } // end size = 1      
    } //end first adj. sym.

    // second adj sym
    for (int i = firstPolygonSize;i<netEdgesSum;i++) {
      int orient1 = netEdgeData [6][i];
      int edge2 = netEdgeData[2][i];
      int map2 = netEdgeData [3][i];
      int orient2 = netEdgeData [6][edge2];
      int sameOriented =mapping[orient1][orient2];
      int newMap = mapping [sameOriented] [map2];
      int size = Math.abs(netEdgeData[4][i]);
      if (size > 1) {
        int begin1 = netEdgeData[5][i];
        int begin2 = netEdgeData[5][edge2];
        int step1 = netEdgeData[7][i];
        int step2 = netEdgeData[7][edge2];
        if (map2==1 || map2 ==3) {
            begin2 = (begin2 + (size-1)*step2 + tileLength)%tileLength;
            step2 = -1*step2;
        }
        for (int i2 = 0; i2 < size; i2++) {
            if (i2 != size-1) {
                // we use ++, -- in case they are the same
                // (step# +1)/2 gives the larger of the two.
                tileAngles[angleCounter][(begin1+(step1+1)/2+tileLength)%tileLength]++;
                tileAngles[angleCounter][(begin2+(step2+1)/2+tileLength)%tileLength]++;
                tileAngles[angleCounter][tileLength]=360;
                angleCounter++;
            }
            tileEdges[7][begin1] = begin2;
            tileEdges[8][begin1] = newMap;
            begin1 = (begin1 + step1 + tileLength)%tileLength;
            begin2 = (begin2 + step2 + tileLength)%tileLength;
        }
      } // end size > 1
      if (size == 1) {
          int begin1 = netEdgeData[5][i];
          tileEdges[7][begin1]= netEdgeData[5][edge2];
          tileEdges[8][begin1]= newMap;
      } // end size = 1
    } //end second adj. sym.

    // to set all symmetry to 0 to start and all maps to self
    for (int i = 0;i<tileLength;i++) {
        tileEdges[0][i] = 0;
        tileEdges[9][i] = i; 
        tileEdges[10][i] = 0;
    } // end set all to self to start.

    if (allPrint == 1) {
      // print tileEdges[][]
      System.out.println("tileEdges");
      for (int i = 0;i<11;i++) {
        for (int j = 0;j<tileLength;j++) {
          System.out.print("."+tileEdges[i][j]);
        }
        System.out.println();
      }    
    } // end allPrint
    
    
// to set all maps to the lowest neighbor
// go through all pairs that are mapped. change the higher one to the lower.

   int minNeighbor=0, maxNeighbor=0;
   for (int i = 0; i < tileLength; i++) {
     for (int j = 1; j < 8; j = j + 2) {
       if (tileEdges[j][i] > tileEdges[j+2][i]) {
         minNeighbor = tileEdges[j+2][i];
         maxNeighbor = tileEdges[j][i];
       }
       else {
         minNeighbor = tileEdges[j][i];
         maxNeighbor = tileEdges[j+2][i];
       }
       int reMap = mapping[tileEdges[j+1][i]][tileEdges[j+3][i]];
       // changes all instances of MaxNeighbor to minNeighbor
       for (int i2 = 0;i2<tileLength;i2++) {
         if (tileEdges[1][i2]==maxNeighbor) {
           tileEdges[1][i2] = minNeighbor;
           tileEdges[2][i2] = mapping[tileEdges[2][i2]][reMap];
         }
         if (tileEdges[3][i2]==maxNeighbor) {
           tileEdges[3][i2] = minNeighbor;
           tileEdges[4][i2] = mapping[tileEdges[4][i2]][reMap];
         }
         if (tileEdges[5][i2]==maxNeighbor) {
           tileEdges[5][i2] = minNeighbor;
           tileEdges[6][i2] = mapping[tileEdges[6][i2]][reMap];
         }
         if (tileEdges[7][i2]==maxNeighbor) {
           tileEdges[7][i2] = minNeighbor;
           tileEdges[8][i2] = mapping[tileEdges[8][i2]][reMap];
         }
         if (tileEdges[9][i2]==maxNeighbor) {
           tileEdges[9][i2] = minNeighbor;
           tileEdges[10][i2] = mapping[tileEdges[10][i2]][reMap];
         }
       } // end for loop through all neighbor maps
     } // end j loop
   } // end i loop
  
   // this looks for symmetry of each edge.
   for (int i = 0;i<tileLength;i++) {
        int checkSym [] = {0,0,0,0};
        for (int j = 2;j<11;j=j+2) checkSym[tileEdges[j][i]]=1;
        int symCount = 0;
        int binarySum = 0;
        for (int j = 0; j<4;j++){
              if (checkSym[j] == 1) {
                  symCount++;
                  binarySum = binarySum + j;
              }
        }
        // if only one symmetry mapping - use it,
        // if more than three types -> straight line.
        // if two types: 0,1>1; 0,2>2; 0,3>3; 1,2>3; 1,3>2; 2,3>1
        if (symCount == 1) tileEdges[0][i]=0;
        if (symCount > 2) tileEdges[0][i]=2;
        if (symCount == 2) {
            if (binarySum <4) tileEdges[0][i] = binarySum;
            if (binarySum >3) tileEdges[0][i] = 6 - binarySum;
        }  // end symCount = 2         
    } // end find edge symmetry for each.

    // set symmetry of base edges
    for (int i = 0;i<tileLength;i++) {
      tileEdges[0][tileEdges[1][i]]=
      edgeSymmetry[tileEdges[0][i]] [tileEdges[0][tileEdges[1][i]]];
    } // end set symmetry of base edges.

    // choose best map for that symmetry
    for (int i = 0;i<tileLength;i++) {
      tileEdges[0][i]=tileEdges[0][tileEdges[1][i]];
      tileEdges[2][i]=symmetryToMap[tileEdges[0][i]][tileEdges[2][i]];
    } // end of choose correct map for that symmetry
      
      // print edge sym., which edge congruent to, mapping.
      System.out.print("Edge Sym ");
      for (int k = 0; k < tileLength; k++) {
          System.out.print(" "+tileEdges[0][k]);
      }
      System.out.println();
      System.out.print("Which Edge ");
      for (int k = 0; k < tileLength; k++) {
          System.out.print(tileEdges[1][k]+" ");
      }
      System.out.println();
      System.out.print("Mapping ");
      for (int k = 0; k < tileLength; k++) {
          System.out.print(tileEdges[2][k]+" ");
      }
      System.out.println();
     
// now work with the angles
      int row = 0;
      int angle = 0;
      int maxLength = tileAngles.length;
     
      // reduce the rows by common divisors
      for (int r = 0; r < maxLength;r++) {
         int GCD = 0;
         for (int a = 0; a<tileLength+1;a++) {
           int current = tileAngles[r][a];
           if (current!=0 && GCD != 1) {
              if (GCD == 0) GCD = Math.abs(current);
              for (int divisor = GCD; divisor > 0;divisor--) {
                if (GCD%divisor == 0 && current%divisor == 0) {
                   GCD = divisor;
                   divisor = 0;
                }
              }
           } // end current != 0 && GCD != 1  
         } // end find GCD for row r.
        if (GCD != 0) {
           int opposite = 1;
           if (tileAngles[r][tileLength]<0) opposite = -1;
           for (int a = 0; a<tileLength+1;a++) {
             tileAngles[r][a]=opposite*tileAngles[r][a]/GCD;
           }
         }
      } // end reduce rows
      
      // this does Gaussian elimination on angles.
      while (row < maxLength && angle < tileLength) {
          int maxValue = Math.abs(tileAngles[row][angle]);
          int maxRow = row;
          // find the largest value below the pivot row for this angle
          for (int r = row+1;r <maxLength;r++) {
              if (Math.abs(tileAngles[r][angle])>maxValue) {
                  maxValue = Math.abs(tileAngles[r][angle]);
                  maxRow = r;
              }
          }
          if (maxValue != 0) {
              // switchRows (row, maxRow);
              for (int a = 0; a < tileLength+1;a++) {
                  int variable = tileAngles[row][a];
                  tileAngles[row][a]=tileAngles[maxRow][a];
                  tileAngles[maxRow][a]=variable;
              }
              // don't divide row by maxValue - keep integer.
              // change all lower rows to not have value for angle.
              int rowMult = tileAngles[row][angle];  
              for (int r = 0;r<maxLength;r++) {
                if (r != row) {  // don't try to eliminate yourself...
                  // multiply the rows and add.
                  int rMult = tileAngles[r][angle];
                  if (rMult != 0) { // avoid useless multiplication of rows
                    for (int a = 0; a < tileLength+1;a++) {
                      tileAngles[r][a]= -rowMult * tileAngles[r][a] 
                                       + rMult * tileAngles[row][a];
                    }
                  }
                }
              }
              row = row + 1;
          }
          angle = angle + 1;      
      } // end Gaussian elimination while loop
      
      // reduce the rows by common divisors again
      for (int r = 0; r < maxLength;r++) {
         int GCD = 0;
         for (int a = 0; a<tileLength+1;a++) {
           int current = tileAngles[r][a];
           if (current!=0 && GCD != 1) {
              if (GCD == 0) GCD = Math.abs(current);
              for (int divisor = GCD; divisor > 0;divisor--) {
                if (GCD%divisor == 0 && current%divisor == 0) {
                   GCD = divisor;
                   divisor = 0;
                }
              }
           } // end current != 0 && GCD != 1  
         } // end find GCD for row r.
         if (GCD != 0) {
           int opposite = 1;
           if (tileAngles[r][tileLength]<0) opposite = -1;
           for (int a = 0; a<tileLength+1;a++) {
             tileAngles[r][a]=opposite*tileAngles[r][a]/GCD;
           }
         }
      } // end reduce rows

      // print tileAngles that aren't zeros
      System.out.println("tileAngles");
      for (int j = 0; j < tileAngles.length;j++) {
        String angleText = "";
        int sumAngles = 0;
        for (int i = 0; i < tileLength+1; i++) {
          sumAngles = sumAngles + Math.abs(tileAngles[j][i]);
          angleText = angleText+"."+tileAngles[j][i];
         //   System.out.print("."+tileAngles[j][i]);
        }
        if (sumAngles > 0) System.out.println(angleText);
//         System.out.print(angleText + " # ");
      }
      System.out.println();
  
  } // end adjacentSetup ()
} // end Tiler class