#include #include #include #include static constexpr int minSideLength = 15; static constexpr float densityDecay = 0.6; void drawRectangle(sf::RectangleShape& rectangle, sf::RenderWindow& window, const float colorMean = 0.8) { static std::random_device randomDevice; static std::default_random_engine engine(randomDevice()); static std::poisson_distribution colorDistribution(colorMean); sf::Color rectangleColor; switch (colorDistribution(engine)) { case 0: rectangleColor = sf::Color::White; break; case 1: rectangleColor = sf::Color::Blue; break; case 2: rectangleColor = sf::Color::Red; break; case 3: rectangleColor = sf::Color::Yellow; break; default: rectangleColor = sf::Color::White; } rectangle.setFillColor(rectangleColor); rectangle.setOutlineThickness(1); rectangle.setOutlineColor(sf::Color::Black); window.draw(rectangle); } void divide(sf::RenderWindow& window, sf::RectangleShape* area, const float density=1, const float colorMean=0.8) { static std::random_device randomDevice; static std::default_random_engine engine(randomDevice()); std::bernoulli_distribution divisionDistribution(density); if(area->getSize().x == 0 || area->getSize().y == 0) { delete(area); } else if(area->getSize().x <= 2*minSideLength && area->getSize().y <= 2*minSideLength) { drawRectangle(*area,window,colorMean); delete(area); } else if(divisionDistribution(engine)) { const sf::Vector2f originalSize = area->getSize(); const sf::Vector2f originalPosition = area->getPosition(); delete(area); uint16_t maxX = originalSize.x - minSideLength + 1; // Add one to let the rectangle occupy all the space uint16_t maxY = originalSize.y - minSideLength + 1; uint16_t newLength = 0; if (maxX > minSideLength) { std::uniform_int_distribution lengthDistribution(minSideLength,maxX); newLength = lengthDistribution(engine); if(newLength == originalSize.x - minSideLength + 1) { newLength = originalSize.x; maxY--; // If the rectangle already occupies all x space, prevent it from occupying all y space } } else { newLength = originalSize.x; } uint16_t newWidth = 0; if (maxY > minSideLength) { std::uniform_int_distribution widthDistribution(minSideLength,maxY); newWidth = widthDistribution(engine); if(newWidth == originalSize.y - minSideLength + 1) { newWidth = originalSize.y; } } else { newWidth = originalSize.y; } sf::RectangleShape* firstRectangle = new sf::RectangleShape(sf::Vector2f(newLength,newWidth)); firstRectangle->setPosition(originalPosition.x,originalPosition.y); divide(window,firstRectangle,density*densityDecay,colorMean); sf::RectangleShape* secondRectangle = new sf::RectangleShape(sf::Vector2f(newLength,originalSize.y-newWidth)); secondRectangle->setPosition(originalPosition.x,originalPosition.y+newWidth); divide(window,secondRectangle,density*densityDecay,colorMean); sf::RectangleShape* thirdRectangle = new sf::RectangleShape(sf::Vector2f(originalSize.x-newLength,newWidth)); thirdRectangle->setPosition(originalPosition.x+newLength,originalPosition.y); divide(window,thirdRectangle,density*densityDecay,colorMean); sf::RectangleShape* fourthRectangle = new sf::RectangleShape(sf::Vector2f(originalSize.x-newLength,originalSize.y-newWidth)); fourthRectangle->setPosition(originalPosition.x+newLength,originalPosition.y+newWidth); divide(window,fourthRectangle,density*densityDecay,colorMean); } else { drawRectangle(*area,window,colorMean); delete(area); } } int main() { sf::RenderWindow window(sf::VideoMode(1067, 600), "Piet Mondrain style"); sf::RectangleShape* originalRectangle; window.display(); while (window.isOpen()) { sf::Event event; while (window.pollEvent(event)) { if (event.type == sf::Event::Closed) window.close(); if (event.type == sf::Event::KeyPressed) { if (event.key.code == sf::Keyboard::Key::Space) { window.clear(); originalRectangle = new sf::RectangleShape(sf::Vector2f(window.getSize().x,window.getSize().y)); divide(window,originalRectangle,1,0.6); window.display(); } } } } return 0; }