int WangTiles::SimpleCompaction(const TileSet & tileSet, vector< vector<Tile> > & result) { const int numTiles = tileSet.NumTiles(); const int numHColors = tileSet.NumHColors(); const int numVColors = tileSet.NumVColors(); const int numTilesPerColor = tileSet.NumTilesPerColor(); // find the best aspect ratio const int maxFactor = floor(sqrt(numTiles)); const int height = numVColors*numVColors; const int width = numHColors*numHColors*numTilesPerColor; { result = vector< vector<Tile> > (height); for(int i = 0; i < result.size(); i++) { result[i] = vector<Tile>(width); } } { int i = 0; int j = 0; for(int e1 = 0; e1 < numVColors; e1++) for(int e3 = 0; e3 < numVColors; e3++) for(int e0 = 0; e0 < numHColors; e0++) for(int e2 = 0; e2 < numHColors; e2++) { const vector<Tile> & tiles = tileSet.Tiles(e0, e1, e2, e3); for(int k = 0; k < tiles.size(); k++) { result[i][j] = tiles[k]; j++; if(j >= result[i].size()) { i++; j = 0; } } } } // done return 1; }
int WangTiles::SequentialTiling(const TileSet & tileSet, const int numRowTiles, const int numColTiles, vector< vector<Tile> > & result) { { // null initialization if(result.size() != numRowTiles) { result = vector< vector<Tile> >(numRowTiles); } for(int i = 0; i < result.size(); i++) { if(result[i].size() != numColTiles) { result[i] = vector<Tile>(numColTiles); } } { Tile empty; for(int i = 0; i < numRowTiles; i++) for(int j = 0; j < numColTiles; j++) { result[i][j] = empty; } } } { const int numHColors = tileSet.NumHColors(); const int numVColors = tileSet.NumVColors(); // add tiles for(int i = 0; i < numRowTiles; i++) for(int j = 0; j < numColTiles; j++) { // find out the color selection from neighbors int e0, e1, e2, e3; e0 = result[(i+numRowTiles-1)%numRowTiles][j].e2(); e1 = result[i][(j+1)%numColTiles].e3(); e2 = result[(i+1)%numRowTiles][j].e0(); e3 = result[i][(j+numColTiles-1)%numColTiles].e1(); if(e0 < 0) e0 = rand()%numHColors; if(e1 < 0) e1 = rand()%numVColors; if(e2 < 0) e2 = rand()%numHColors; if(e3 < 0) e3 = rand()%numVColors; const vector<Tile> & selections = tileSet.Tiles(e0, e1, e2, e3); if(selections.size() <= 0) { return 0; } result[i][j] = selections[rand()%selections.size()]; } } // done return 1; }
int WangTiles::OrthogonalCornerCompaction(const TileSet & tileSet, vector< vector<Tile> > & result) { const int numHColors = tileSet.NumHColors(); const int numVColors = tileSet.NumVColors(); const int numTilesPerColor = tileSet.NumTilesPerColor(); // find the best aspect ratio int numTilesPerColorH = numTilesPerColor; int numTilesPerColorV = 1; while((numHColors*numHColors*numTilesPerColorH > numVColors*numVColors*numTilesPerColorV) && (numTilesPerColorH%2 == 0)) { numTilesPerColorH /= 2; numTilesPerColorV *= 2; } const int height = numVColors*numVColors*numTilesPerColorV; const int width = numHColors*numHColors*numTilesPerColorH; { // space allocation for the result result = vector< vector<Tile> > (height); for(int i = 0; i < result.size(); i++) { result[i] = vector<Tile>(width); } } { vector<int> travelHEdges, travelVEdges; if(! TravelEdges(0, numHColors-1, travelHEdges)) return 0; if(! TravelEdges(0, numVColors-1, travelVEdges)) return 0; // put the tiles for(int i = 0; i < height; i++) for(int j = 0; j < width; j++) { int whichVBlock = i/(numVColors*numVColors); int whichHBlock = j/(numHColors*numHColors); int ec = whichVBlock*numTilesPerColorH + whichHBlock; int hIndex0 = j%(numHColors*numHColors); int hIndex2 = hIndex0 + 1; int vIndex1 = i%(numVColors*numVColors); int vIndex3 = vIndex1 + 1; int e0 = travelHEdges[hIndex0]; int e3 = travelVEdges[vIndex1]; int e2 = travelHEdges[hIndex0]; int e1 = travelVEdges[vIndex1]; // assignment const vector<Tile> & tiles = tileSet.Tiles(e0, e1, e2, e3); if(tiles.size() <= ec) { return 0; } result[i][j] = tiles[ec]; } } // done return 1; }
// algorithm: // find the tiling for each center color (i.e. assuming numTilesPerColor is 1) // and repeat the tiling for multiple numTilesPerColor int WangTiles::EvenCompaction(const TileSet & tileSet, vector< vector<Tile> > & result) { //const int numTiles = tileSet.NumTiles(); const int numHColors = tileSet.NumHColors(); const int numVColors = tileSet.NumVColors(); const int numTilesPerColor = tileSet.NumTilesPerColor(); // error checking if((numHColors*numVColors*numTilesPerColor)%4) { // illegal input sizes return 0; } // find the best aspect ratio int numTilesPerColorH = numTilesPerColor/2; int numTilesPerColorV = 2; { int hFactor = 1; int vFactor = 1; int numTilesPerColorhv = numTilesPerColor; if(numHColors%2) { hFactor *= 2; numTilesPerColorhv /= 2; } if(numVColors%2) { vFactor *= 2; numTilesPerColorhv /= 2; } const int maxFactor = ceil(sqrt(numTilesPerColorhv)); int factor = 1; for(int i = 1; i <= maxFactor; i++) { if((numTilesPerColorhv%i) == 0) factor = i; } if( (numVColors*numVColors*vFactor) < (numHColors*numHColors*hFactor) ) { factor = numTilesPerColorhv/factor; } numTilesPerColorH = factor * hFactor; numTilesPerColorV = numTilesPerColorhv/factor * vFactor; } const int height = numVColors*numVColors*numTilesPerColorV; const int width = numHColors*numHColors*numTilesPerColorH; { // space allocation for the result result = vector< vector<Tile> > (height); for(int i = 0; i < result.size(); i++) { result[i] = vector<Tile>(width); } } { // put the tiles for(int i = 0; i < height; i++) for(int j = 0; j < width; j++) { int ec = i/(numVColors*numVColors)*numTilesPerColorH + j/(numHColors*numHColors); int e0 = (j/numHColors)%numHColors; int e1 = (i/numVColors)%numVColors; int e2 = (j%numHColors); int e3 = (i%numVColors); if(j%2) { // swap e1 and e3 int tmp = e1; e1 = e3; e3 = tmp; } if(i%2) { // swap e0 and e2 int tmp = e0; e0 = e2; e2 = tmp; } // assignment const vector<Tile> & tiles = tileSet.Tiles(e0, e1, e2, e3); if(tiles.size() <= ec) { return 0; } result[i][j] = tiles[ec]; } } // done return 1; }
int WangTiles::RandomCompaction(const TileSet & tileSet, vector< vector<Tile> > & result) { const int numHColors = tileSet.NumHColors(); const int numVColors = tileSet.NumVColors(); const int numTilesPerColor = tileSet.NumTilesPerColor(); // find the best aspect ratio int numTilesPerColorH = numTilesPerColor; int numTilesPerColorV = 1; while((numVColors*numVColors*numTilesPerColorH > numHColors*numHColors*numTilesPerColorV) && (numTilesPerColorH%2 == 0)) { numTilesPerColorH /= 2; numTilesPerColorV *= 2; } const int height = numHColors*numHColors*numTilesPerColorV; const int width = numVColors*numVColors*numTilesPerColorH; { // space allocation for the result result = vector< vector<Tile> > (height); for(int i = 0; i < result.size(); i++) { result[i] = vector<Tile>(width); } } // do the random assignment { // build a random permutation deque<int> permutation(height*width); { for(int i = 0; i < permutation.size(); i++) { permutation[i] = i; } } deque<int> permutationNew; while(permutation.size() > 0) { const int select = rand()%permutation.size(); permutationNew.push_back(permutation[select]); permutation[select] = permutation[permutation.size()-1]; permutation.pop_back(); } permutation = permutationNew; for(int e1 = 0; e1 < numVColors; e1++) for(int e3 = 0; e3 < numVColors; e3++) for(int e0 = 0; e0 < numHColors; e0++) for(int e2 = 0; e2 < numHColors; e2++) { const vector<Tile> & tiles = tileSet.Tiles(e0, e1, e2, e3); for(int k = 0; k < tiles.size(); k++) { const int whereToGo = permutation[0]; permutation.pop_front(); const int row = whereToGo/width; const int col = whereToGo%width; result[row][col] = tiles[k]; } } } // done return 1; }