Logo Search packages:      
Sourcecode: palapeli version File versions  Download package

void Palapeli::JigsawPattern::doSlice ( const QImage &  image  )  [protected, virtual]

Provides the slicing algorithm. This function splits a given image into pieces and defines relations between them. These pieces and relations are used to build the puzzle.

Parameters:
image the image to be sliced
See also:
addPiece, addRelation, reportPieceCount

Implements Palapeli::Pattern.

Definition at line 74 of file pattern-jigsaw.cpp.

References Palapeli::Pattern::addPiece(), Palapeli::Pattern::addRelation(), Palapeli::Pattern::CreatePuzzle, Palapeli::Pattern::mode(), and Palapeli::Pattern::reportPieceCount().

{
      reportPieceCount(m_xCount * m_yCount);
      if (mode() != CreatePuzzle)
            return;
      const int width = image.width(), height = image.height();
      const int pieceWidth = width / m_xCount, pieceHeight = height / m_yCount;
      const int plugPaddingX = pieceWidth / 2, plugPaddingY = pieceHeight / 2; //see below
      //find plug shape types, based on given seed
      qsrand(m_seed);
      int** horizontalPlugShapeTypes = new int*[m_xCount];
      int** verticalPlugShapeTypes = new int*[m_xCount];
      bool** horizontalPlugDirections = new bool*[m_xCount]; //true: male is left, female is right, plug points to the right
      bool** verticalPlugDirections = new bool*[m_xCount]; //true: male is above female, plug points down
      for (int x = 0; x < m_xCount; ++x)
      {
            horizontalPlugShapeTypes[x] = new int[m_yCount];
            verticalPlugShapeTypes[x] = new int[m_yCount];
            horizontalPlugDirections[x] = new bool[m_yCount];
            verticalPlugDirections[x] = new bool[m_yCount];
            for (int y = 0; y < m_yCount; ++y)
            {
                  //plugs along X axis
                  horizontalPlugShapeTypes[x][y] = qrand() % m_shapeCount + 1; //values: 1 .. m_shapeCount
                  horizontalPlugDirections[x][y] = qrand() % 2;
                  //plugs along Y axis
                  verticalPlugShapeTypes[x][y] = qrand() % m_shapeCount + 1;
                  verticalPlugDirections[x][y] = qrand() % 2;
            }
      }
      //make pieces
      for (int x = 0; x < m_xCount; ++x)
      {
            for (int y = 0; y < m_yCount; ++y)
            {
                  //some geometry
                  const QRect pieceBaseRect( //piece without plugs
                        x * pieceWidth,
                        y * pieceHeight,
                        pieceWidth,
                        pieceHeight
                  );
                  const QRect pieceRect( //piece with padding space for plugs (will overlap with neighbor piece rects)
                        x * pieceWidth - plugPaddingX,
                        y * pieceHeight - plugPaddingY,
                        pieceWidth + 2 * plugPaddingX,
                        pieceHeight + 2 * plugPaddingY
                  );
                  const QRect maskBaseRect( //the part of the mask that maps to pieceBaseRect
                        plugPaddingX,
                        plugPaddingY,
                        pieceWidth,
                        pieceHeight
                  );
                  const QRect maskRect( //the whole mask; maps to pieceRect
                        0,
                        0,
                        pieceWidth + 2 * plugPaddingX,
                        pieceHeight + 2 * plugPaddingY
                  );
                  //create the mask
                  QImage mask(maskRect.size(), QImage::Format_ARGB32_Premultiplied);
                  mask.fill(0x00000000); //fully transparent color
                  QPainter painter(&mask);
                  painter.setPen(Qt::NoPen);
                  painter.setBrush(Qt::black);
                  //left plug
                  painter.save();
                  if (x == 0)
                  {
                        //nothing to plug at the left side - use null shape which points to the right originally
                        painter.translate(maskRect.center());
                        painter.rotate(180);
                        painter.translate(-maskRect.center());
                        m_shapes[0]->render(&painter, maskRect);
                  }
                  else if (horizontalPlugDirections[x - 1][y]) //here is female plug which points to the left already
                  {
                        const int shapeType = horizontalPlugShapeTypes[x - 1][y];
                        m_shapes[2 * shapeType]->render(&painter, maskRect);
                  }
                  else //here is male plug which points to the right originally
                  {
                        painter.translate(maskRect.center());
                        painter.rotate(180);
                        painter.translate(-maskRect.center());
                        const int shapeType = horizontalPlugShapeTypes[x - 1][y];
                        m_shapes[2 * shapeType - 1]->render(&painter, maskRect);
                  }
                  painter.restore();
                  //right plug
                  painter.save();
                  if (x == m_xCount - 1)
                  {
                        //nothing to plug at the right side - use null shape which points to the right already
                        m_shapes[0]->render(&painter, maskRect);
                  }
                  else if (horizontalPlugDirections[x][y]) //here is male plug which points to the right already
                  {
                        const int shapeType = horizontalPlugShapeTypes[x][y];
                        m_shapes[2 * shapeType - 1]->render(&painter, maskRect);
                  }
                  else //here is female plug which points to the left originally
                  {
                        painter.translate(maskRect.center());
                        painter.rotate(180);
                        painter.translate(-maskRect.center());
                        const int shapeType = horizontalPlugShapeTypes[x][y];
                        m_shapes[2 * shapeType]->render(&painter, maskRect);
                  }
                  painter.restore();
                  //top plug
                  painter.save();
                  if (y == 0)
                  {
                        //nothing to plug at the top side - use null shape which points to the right originally
                        painter.translate(maskRect.center());
                        painter.rotate(-90);
                        painter.scale(qreal(maskRect.height()) / maskRect.width(), qreal(maskRect.width()) / maskRect.height());
                        painter.translate(-maskRect.center());
                        m_shapes[0]->render(&painter, maskRect);
                  }
                  else if (verticalPlugDirections[x][y - 1]) //here is female plug which points to the left originally
                  {
                        painter.translate(maskRect.center());
                        painter.rotate(90);
                        painter.scale(qreal(maskRect.height()) / maskRect.width(), qreal(maskRect.width()) / maskRect.height());
                        painter.translate(-maskRect.center());
                        const int shapeType = verticalPlugShapeTypes[x][y - 1];
                        m_shapes[2 * shapeType]->render(&painter, maskRect);
                  }
                  else //here is male plug which points to the right originally
                  {
                        painter.translate(maskRect.center());
                        painter.rotate(-90);
                        painter.scale(qreal(maskRect.height()) / maskRect.width(), qreal(maskRect.width()) / maskRect.height());
                        painter.translate(-maskRect.center());
                        const int shapeType = verticalPlugShapeTypes[x][y - 1];
                        m_shapes[2 * shapeType - 1]->render(&painter, maskRect);
                  }
                  painter.restore();
                  //bottom plug
                  painter.save();
                  if (y == m_yCount - 1)
                  {
                        //nothing to plug at the bottom side - use null shape which points to the right originally
                        painter.translate(maskRect.center());
                        painter.rotate(90);
                        painter.scale(qreal(maskRect.height()) / maskRect.width(), qreal(maskRect.width()) / maskRect.height());
                        painter.translate(-maskRect.center());
                        m_shapes[0]->render(&painter, maskRect);
                  }
                  else if (verticalPlugDirections[x][y]) //here is female plug which points to the left originally
                  {
                        painter.translate(maskRect.center());
                        painter.rotate(90);
                        painter.scale(qreal(maskRect.height()) / maskRect.width(), qreal(maskRect.width()) / maskRect.height());
                        painter.translate(-maskRect.center());
                        const int shapeType = verticalPlugShapeTypes[x][y];
                        m_shapes[2 * shapeType - 1]->render(&painter, maskRect);
                  }
                  else //here is male plug which points to the right originally
                  {
                        painter.translate(maskRect.center());
                        painter.rotate(-90);
                        painter.scale(qreal(maskRect.height()) / maskRect.width(), qreal(maskRect.width()) / maskRect.height());
                        painter.translate(-maskRect.center());
                        const int shapeType = verticalPlugShapeTypes[x][y];
                        m_shapes[2 * shapeType]->render(&painter, maskRect);
                  }
                  painter.restore();
                  //done creating the mask
                  painter.end();
                  addPiece(image.copy(pieceRect), mask, pieceRect);
            }
      }
      //build relationships between pieces
      for (int x = 0; x < m_xCount; ++x)
      {
            for (int y = 0; y < m_yCount; ++y)
            {
                  //along X axis (pointing left)
                  if (x != 0)
                        addRelation(x * m_yCount + y, (x - 1) * m_yCount + y);
                  //along Y axis (pointing up)
                  if (y != 0)
                        addRelation(x * m_yCount + y, x * m_yCount + (y - 1));
            }
      }
      //do some cleanup
      for (int x = 0; x < m_xCount - 1; ++x)
      {
            delete[] horizontalPlugShapeTypes[x];
            delete[] verticalPlugShapeTypes[x];
            delete[] horizontalPlugDirections[x];
            delete[] verticalPlugDirections[x];
      }
      delete[] horizontalPlugShapeTypes;
      delete[] verticalPlugShapeTypes;
      delete[] horizontalPlugDirections;
      delete[] verticalPlugDirections;
      //randomize to avoid any abstruse side effects
      qsrand(time(0));
}


Generated by  Doxygen 1.6.0   Back to index