149 lines
No EOL
4.9 KiB
C++
149 lines
No EOL
4.9 KiB
C++
#include <SFML/Graphics.hpp>
|
|
#include <random>
|
|
#include <time.h>
|
|
#include <inttypes.h>
|
|
|
|
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<uint8_t> 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<uint16_t> 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<uint16_t> 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;
|
|
} |