tsp_cpp/snippets/pietMondrian.cpp

149 lines
4.9 KiB
C++
Raw Normal View History

2019-04-25 10:23:38 +02:00
#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;
}