File indexing completed on 2024-05-12 04:06:20
0001 /* 0002 SPDX-FileCopyrightText: 2010 Johannes Loehnert <loehnert.kde@gmx.de> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "grid.h" 0008 0009 #include <cmath> 0010 #include <QPainterPath> 0011 #include <QDebug> 0012 #include "utilities.h" 0013 0014 void RectMode::generateGrid(GoldbergEngine *e, int piece_count) const { 0015 // number of tries to resolve collision 0016 int collision_tries = 10 * e->m_plug_size * e->m_plug_size; 0017 if (collision_tries < 5) collision_tries = 5; 0018 const qreal collision_shrink_factor = 0.95; 0019 0020 0021 // calculate piece counts 0022 const int width = e->get_image_width(), height = e->get_image_height(); 0023 0024 int xCount; 0025 int yCount; 0026 getBestFit(xCount, yCount, 1.0 * width / height, piece_count); 0027 0028 const int pieceWidth = width / xCount, pieceHeight = height / yCount; 0029 e->m_length_base = (pieceWidth + pieceHeight) * 0.5 * e->m_plug_size; 0030 0031 GBClassicPlugParams** horizontalPlugParams = new GBClassicPlugParams*[xCount+1]; 0032 GBClassicPlugParams** verticalPlugParams = new GBClassicPlugParams*[xCount+1]; 0033 0034 for (int x = 0; x < xCount+1; ++x) { 0035 horizontalPlugParams[x] = new GBClassicPlugParams[yCount+1]; 0036 verticalPlugParams[x] = new GBClassicPlugParams[yCount+1]; 0037 for (int y = 0; y < yCount+1; ++y) { 0038 bool odd_tile = (x+y) % 2; 0039 //borders along X axis 0040 if (y==0 || y==yCount) { 0041 horizontalPlugParams[x][y] = e->initEdge(true); 0042 } 0043 else { 0044 horizontalPlugParams[x][y] = e->initEdge(false); 0045 } 0046 horizontalPlugParams[x][y].flipped ^= odd_tile ^ e->m_alternate_flip; 0047 horizontalPlugParams[x][y].unit_x = QLineF(x*pieceWidth, y*pieceHeight, (x+1)*pieceWidth, y*pieceHeight); 0048 if (x>0 && x < xCount) e->smooth_join(horizontalPlugParams[x][y], horizontalPlugParams[x-1][y]); 0049 0050 //borders along Y axis 0051 if (x==0 || x==xCount) { 0052 verticalPlugParams[x][y] = e->initEdge(true); 0053 } 0054 else { 0055 verticalPlugParams[x][y] = e->initEdge(false); 0056 } 0057 verticalPlugParams[x][y].flipped ^= odd_tile; 0058 verticalPlugParams[x][y].unit_x = QLineF(x*pieceWidth, y*pieceHeight, x*pieceWidth, (y+1)*pieceHeight); 0059 if (y>0 && y < yCount) e->smooth_join(verticalPlugParams[x][y], verticalPlugParams[x][y-1]); 0060 0061 // collision checking 0062 if (x > 0 && x < xCount) { 0063 bool v_intersects = true; 0064 QList<GBClassicPlugParams*> offenders; 0065 for (int i=0; i<collision_tries && v_intersects; i++) { 0066 offenders.clear(); 0067 if (i>0 && v_intersects) { 0068 //qDebug() << "collision: vertical edge, x=" << x << ", y=" << y; 0069 verticalPlugParams[x][y].size_correction *= collision_shrink_factor; 0070 e->reRandomizeEdge(verticalPlugParams[x][y], true); 0071 } 0072 v_intersects = e->plugsIntersect(verticalPlugParams[x][y], horizontalPlugParams[x-1][y], &offenders); 0073 if (y<yCount) v_intersects |= e->plugsIntersect(verticalPlugParams[x][y], horizontalPlugParams[x-1][y+1], &offenders); 0074 } 0075 if (v_intersects) { 0076 e->makePlugless(verticalPlugParams[x][y]); 0077 for (int i=0; i<offenders.size(); i++) e->makePlugless(*(offenders.at(i))); 0078 } 0079 } 0080 if (y>0 && y < yCount) { 0081 bool h_intersects = true; 0082 QList<GBClassicPlugParams*> offenders; 0083 for (int i=0; i<collision_tries && h_intersects; i++) { 0084 offenders.clear(); 0085 if (i>0 && h_intersects) { 0086 //qDebug() << "collision: horizontal edge, x=" << x << " y=" << y; 0087 horizontalPlugParams[x][y].size_correction *= collision_shrink_factor; 0088 e->reRandomizeEdge(horizontalPlugParams[x][y], true); 0089 } 0090 h_intersects = e->plugsIntersect(horizontalPlugParams[x][y], verticalPlugParams[x][y-1], &offenders); 0091 if (x<xCount) h_intersects |= e->plugsIntersect(horizontalPlugParams[x][y], verticalPlugParams[x][y], &offenders); 0092 } 0093 if (h_intersects) { 0094 e->makePlugless(horizontalPlugParams[x][y]); 0095 for (int i=0; i<offenders.size(); i++) e->makePlugless(*(offenders.at(i))); 0096 } 0097 } 0098 } 0099 } 0100 0101 //create pieces 0102 for (int x = 0; x < xCount; ++x) { 0103 for (int y = 0; y < yCount; ++y) { 0104 //create the mask path 0105 QPainterPath path; 0106 path.moveTo(horizontalPlugParams[x][y].unit_x.p1()); 0107 0108 // top, right, bottom, left plug 0109 e->addPlugToPath(path, false, horizontalPlugParams[x][y]); 0110 e->addPlugToPath(path, false, verticalPlugParams[x+1][y]); 0111 e->addPlugToPath(path, true, horizontalPlugParams[x][y+1]); 0112 e->addPlugToPath(path, true, verticalPlugParams[x][y]); 0113 0114 e->makePieceFromPath(x + y * xCount, path); 0115 } 0116 } 0117 0118 //create relations 0119 for (int x = 0; x < xCount; ++x) { 0120 for (int y = 0; y < yCount; ++y) { 0121 if (x != 0) e->addRelation(x + y * xCount, (x - 1) + y * xCount); 0122 if (y != 0) e->addRelation(x + y * xCount, x + (y - 1) * xCount); 0123 } 0124 } 0125 0126 //cleanup 0127 for (int x = 0; x < xCount + 1; ++x) { 0128 delete[] horizontalPlugParams[x]; 0129 delete[] verticalPlugParams[x]; 0130 } 0131 delete[] horizontalPlugParams; 0132 delete[] verticalPlugParams; 0133 } 0134