PuzzleSolver/Source/functions/solve/classExtension.cpp
Raphael Maenle 9b282e83ca generating "Random" Pieces from picture source now
rgb values stored as double in the piece base class. this is bound to change once other group has expanded piece base class.
2017-12-06 16:25:13 +01:00

341 lines
14 KiB
C++
Executable File

#include "../../header.h"
//shifts puzzle piece one to the right
void PuzzlePiece::shift(unsigned int moves)
{
shifts = (shifts+moves)%4;
setConnections(((getConnections() >> (moves*2)) | (getConnections() << sizeof(unsigned char)*8 - (moves*2))));
}
//creates random centerpiece
void PuzzlePiece::randomCenterPiece()
{
setConnections(0b00000000);
if(rand()%2)
setConnections(getConnections() | 0b01000000);
else
setConnections(getConnections() | 0b10000000);
if(rand()%2)
setConnections(getConnections() | 0b00010000);
else
setConnections(getConnections() | 0b00100000);
if(rand()%2)
setConnections(getConnections() | 0b00000100);
else
setConnections(getConnections() | 0b00001000);
if(rand()%2)
setConnections(getConnections() | 0b00000001);
else
setConnections(getConnections() | 0b00000010);
}
//tries all pieces in box from separator to end and places fitting into matrix. removes fitting piece
//use separator if you have to retract to a position
//seperator may be bigger than box size, if all puzzle pieces have already been looked at.
// it immediately retracts again then (returns -1)
unsigned int Puzzle::tryAllPieces(unsigned int m, unsigned int n, vector<PuzzlePiece>& myBox, unsigned int separator)
{
for(int i=separator; i<myBox.size();i++)
{
if(testRotationPiece(m,n,myBox[i]))
{
setPiece(m,n,myBox[i]);
myBox.erase(myBox.begin()+i);
return i;
}
}
return -1;
}
//tests the myPart in all 4 rotations at position m, n
bool Puzzle::testRotationPiece(unsigned int m, unsigned int n, PuzzlePiece& myPart, int nrOfRotations)
{
for(int rotation=0; rotation < nrOfRotations; rotation++)
{
if(PlaceOfPartGood(m,n,myPart))
return 1;
//cout << "was rotated in testRotationPiece" << endl;
myPart.shift(1);
}
//cout << "Was a bad part" << endl;
return 0;
}
//insterts piece at position in box according to boxidentifier and removes piece from puzzle
//this returns the position after!! the puzzle piece was put back in! not the boxidentifier of the piece. look that up in other function.
unsigned int Puzzle::putBackIntoBox(unsigned int m, unsigned int n, vector<PuzzlePiece>& myBox)
{
#ifdef debug
cout << "putting back" << endl;
cout << "Old Box: ";
printBox(myBox);
cout << endl;
#endif
for(int i = 0; i < myBox.size();i++)
{
if(myBox[i].getBoxIdentifier()>getPiece(m,n).getBoxIdentifier())
{
myBox.insert(myBox.begin()+i,getPiece(m,n));
removePiece(m,n);
return i+1;
}
}
//using push back, if the element was the last element in the vector chain
myBox.push_back(getPiece(m,n));
removePiece(m,n);
return myBox.size();
}
//checks if the myPart in its current orientation is legal in position m, n
bool Puzzle::PlaceOfPartGood(unsigned int m,unsigned int n, PuzzlePiece& myPart)
{
PuzzlePiece negativePart(0);
negativePart.setConnections(negativePart.getConnections() | (getPiece(m,n+1).getConnections() & 0b11000000));
negativePart.setConnections(negativePart.getConnections() | (getPiece(m-1,n).getConnections() & 0b00110000));
negativePart.setConnections(negativePart.getConnections() | (getPiece(m,n-1).getConnections() & 0b00001100));
negativePart.setConnections(negativePart.getConnections() | (getPiece(m+1,n).getConnections() & 0b00000011));
negativePart.shift(2);
if (
( ((((negativePart.getConnections() & 0b11000000) ^ (myPart.getConnections() & 0b11000000)) != 0b00000000) && (((myPart.getConnections() & 0b11000000) != 0b00000000) && (negativePart.getConnections() & 0b11000000) != 0b00000000))
|| ((((negativePart.getConnections() & 0b11000000) == 0b11000000) || ((myPart.getConnections() & 0b11000000) == 0b11000000)) && (((myPart.getConnections() & 0b11000000) != 0b00000000) && (negativePart.getConnections() & 0b11000000) != 0b00000000))
|| (((negativePart.getConnections() & 0b11000000) == 0b00000000) && ((myPart.getConnections() & 0b11000000) == 0b00000000)) )
&&
( ((((negativePart.getConnections() & 0b00110000) ^ (myPart.getConnections() & 0b00110000)) != 0b00000000) && (((myPart.getConnections() & 0b00110000) != 0b00000000) && (negativePart.getConnections() & 0b00110000) != 0b00000000))
|| ((((negativePart.getConnections() & 0b00110000) == 0b00110000) || ((myPart.getConnections() & 0b00110000) == 0b00110000)) && (((myPart.getConnections() & 0b00110000) != 0b00000000) && (negativePart.getConnections() & 0b00110000) != 0b00000000))
|| (((negativePart.getConnections() & 0b00110000) == 0b00000000) && ((myPart.getConnections() & 0b00110000) == 0b00000000)) )
&&
( ((((negativePart.getConnections() & 0b00001100) ^ (myPart.getConnections() & 0b00001100)) != 0b00000000) && (((myPart.getConnections() & 0b00001100) != 0b00000000) && (negativePart.getConnections() & 0b00001100) != 0b00000000))
|| ((((negativePart.getConnections() & 0b00001100) == 0b00001100) || ((myPart.getConnections() & 0b00001100) == 0b00001100)) && (((myPart.getConnections() & 0b00001100) != 0b00000000) && (negativePart.getConnections() & 0b00001100) != 0b00000000))
|| (((negativePart.getConnections() & 0b00001100) == 0b00000000) && ((myPart.getConnections() & 0b00001100) == 0b00000000)) )
&&
( ((((negativePart.getConnections() & 0b00000011) ^ (myPart.getConnections() & 0b00000011)) != 0b00000000) && (((myPart.getConnections() & 0b00000011) != 0b00000000) && (negativePart.getConnections() & 0b00000011) != 0b00000000))
|| ((((negativePart.getConnections() & 0b00000011) == 0b00000011) || ((myPart.getConnections() & 0b00000011) == 0b00000011)) && (((myPart.getConnections() & 0b00000011) != 0b00000000) && (negativePart.getConnections() & 0b00000011) != 0b00000000))
|| (((negativePart.getConnections() & 0b00000011) == 0b00000000) && ((myPart.getConnections() & 0b00000011) == 0b00000000)) )
)
{
//cout << "good Part: ";
//myPart.printPiece();
//cout << endl;
return 1;
}
//cout << "bad Part: ";
//myPart.printPiece();
//cout << endl;
return 0;
}
//TODO!!
//simpler algorithm to the first placeofpartgood
//not yet functional!!!
bool Puzzle::PlaceOfPart2Good(unsigned int m,unsigned int n, PuzzlePiece& myPart)
{
PuzzlePiece tmpPuzzlePiece = myPart;
//make tmp a negative part
if(((tmpPuzzlePiece.getConnections() & 0b11000000) != 0b11000000) || ((tmpPuzzlePiece.getConnections() & 0b11000000) != 0b00000000))
tmpPuzzlePiece.setConnections(tmpPuzzlePiece.getConnections() ^ 0b11000000);
if(((tmpPuzzlePiece.getConnections() & 0b00110000) != 0b00110000) || ((tmpPuzzlePiece.getConnections() & 0b00110000) != 0b00000000))
tmpPuzzlePiece.setConnections(tmpPuzzlePiece.getConnections() ^ 0b00110000);
if(((tmpPuzzlePiece.getConnections() & 0b00001100) != 0b00001100)|| ((tmpPuzzlePiece.getConnections() & 0b00001100) != 0b00000000))
tmpPuzzlePiece.setConnections(tmpPuzzlePiece.getConnections() ^ 0b00001100);
if(((tmpPuzzlePiece.getConnections() & 0b00000011) != 0b00000011) || ((tmpPuzzlePiece.getConnections() & 0b00000011) != 0b00000000))
tmpPuzzlePiece.setConnections(tmpPuzzlePiece.getConnections() ^ 0b00000011);
PuzzlePiece negativePart(0);
negativePart.setConnections(negativePart.getConnections() | (getPiece(m,n+1).getConnections() & 0b11000000));
negativePart.setConnections(negativePart.getConnections() | (getPiece(m-1,n).getConnections() & 0b00110000));
negativePart.setConnections(negativePart.getConnections() | (getPiece(m,n-1).getConnections() & 0b00001100));
negativePart.setConnections(negativePart.getConnections() | (getPiece(m+1,n).getConnections() & 0b00000011));
negativePart.shift(2);
//check tmp part with environment
if(((negativePart.getConnections() & 0b11000000) == (tmpPuzzlePiece.getConnections() & 0b11000000)) && ((negativePart.getConnections() & 0b00110000) == (tmpPuzzlePiece.getConnections ()& 0b00110000)) &&
((negativePart.getConnections() & 0b00001100) == (tmpPuzzlePiece.getConnections() & 0b00001100)) && ((negativePart.getConnections() & 0b00000011) == (tmpPuzzlePiece.getConnections() & 0b00000011)))
return 1;
return 0;
}
//prints the true puzzle (without 0 edges)
void Puzzle::printPuzzle()
{
cout << "current Puzzle: " << endl;
for(int i=1;i<row+1;i++)
{
for(int j=1;j<col+1;j++)
{
Matrix[i][j].printPiece();
cout << " ";
}
cout << endl;
}
cout << endl;
}
//creates a legal puzzle out of random pieces
void randomBox::createRandomAbstraction1()
{
PuzzlePiece temporaryRandomPiece(0);
for(int i=0;i<getRows();i++)
{
for(int j = 0; j < getCols();)
{
//create random piece, set edges according to position and check if piece is good
temporaryRandomPiece.randomCenterPiece();
if(i==0)
temporaryRandomPiece.setConnections(0b00111111 & temporaryRandomPiece.getConnections());
if(i==getRows()-1)
temporaryRandomPiece.setConnections(0b11110011 & temporaryRandomPiece.getConnections());
if(j==0)
temporaryRandomPiece.setConnections(0b11111100 & temporaryRandomPiece.getConnections());
if(j==getCols()-1)
temporaryRandomPiece.setConnections(0b11001111 & temporaryRandomPiece.getConnections());
if(PlaceOfPartGood(j,i,temporaryRandomPiece))
{
temporaryRandomPiece.assignIdentifier();
setPiece(j,i,temporaryRandomPiece);
j++;
}
}
}
}
void randomBox::createRandomAbstraction2()
{
//get a picture
cv::Mat PuzzlePicture = cv::imread("../../Codicil/Images/Balloons.jpg");
if(! PuzzlePicture.data )
{
cout << "Could not open or find the image" << std::endl ;
return;
}
//split a picture into mxn pieces
cv::Size smallSize ((int)(PuzzlePicture.cols/getCols()) ,(int)(PuzzlePicture.rows/getRows()));
// get the image data
vector<cv::Mat> smallChannels;
unsigned int i=0,j=0;
for ( int y=0; y<=PuzzlePicture.rows-smallSize.height; y += smallSize.height )
{
for ( int x=0 ; x<=PuzzlePicture.cols-smallSize.width; x += smallSize.width )
{
//split into different ROIs
cv::Rect rect = cv::Rect (x ,y , smallSize.width, smallSize.height );
cv::Mat tmpSmallPicture = cv::Mat(PuzzlePicture,rect);
cv::split(tmpSmallPicture, smallChannels);
//save color into individual PuzzlePieces in Matrix
PuzzlePiece tmpPiece = getPiece(j,i);
tmpPiece.r = cv::mean(smallChannels[0]).operator[](0);
tmpPiece.g = cv::mean(smallChannels[1]).operator[](0);
tmpPiece.b = cv::mean(smallChannels[2]).operator[](0);
setPiece(j,i,tmpPiece);
j++;
}
i++;
j=0;
}
}
void randomBox::putAllIntoBox() {
for (int i = 0; i < getRows(); i++)
{
for (int j = 0; j < getCols(); j++)
{
Box.push_back(getPiece(j,i));
}
}
}
//prints a box contents on console
void randomBox::printBox()
{
shuffle();
for (vector<PuzzlePiece>::iterator i = Box.begin(); i != Box.end(); i++)
{
(*i).printPiece();
cout << ' ';
}
cout << endl;
}
//shuffles around a box, randomizing pieces and orientation
vector<PuzzlePiece> randomBox::shuffle()
{
random_shuffle(Box.begin(),Box.end());
for (vector<PuzzlePiece>::iterator i = Box.begin(); i != Box.end(); i++)
{
i->shift(rand()%4);
i->resetShift();
}
numerateBox(Box);
return Box;
}
//creates a random box size m, n, shuffles it, and then retuns it
vector<PuzzlePiece> createBox(coor myCoor)
{
randomBox myFirstPuzzleBox(myCoor.m,myCoor.n);
myFirstPuzzleBox.createRandomAbstraction1();
myFirstPuzzleBox.createRandomAbstraction2();
myFirstPuzzleBox.putAllIntoBox();
myFirstPuzzleBox.printPuzzle();
return myFirstPuzzleBox.shuffle();
}
//prints contents of box
void printBox(vector<PuzzlePiece> myBox)
{
cout << "current Box: " << endl;
for (vector<PuzzlePiece>::iterator i = myBox.begin(); i != myBox.end(); i++)
{
(*i).printPiece();
cout << ' ';
}
cout << endl;
return;
}
//gives every element in box a box identifier.
void numerateBox(vector<PuzzlePiece>& myBox)
{
for(int i = 0; i< myBox.size();i++)
myBox[i].setBoxIdentifier(i);
return;
}
std::vector<PuzzlePiece> convertPart2PuzzlePiece(std::vector<Part> simplePartBox)
{
std::vector<PuzzlePiece> advancedPartBox;
for(int i=0;i<simplePartBox.size();i++)
{
PuzzlePiece tmpNewPiece(0);
tmpNewPiece.setConnections(simplePartBox[i].getConnections());
advancedPartBox.push_back(tmpNewPiece);
}
return advancedPartBox;
}