commit dd5fe910d87bc89f75e4e4e7423a2defca3153a3
Author: Quinta <0pietroquintavalle0@gmail.com>
Date: Sat Jul 13 15:12:05 2024 +0200
C++ is hard
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0080421
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+/build/
+/cmake-build-debug/
+/cmake-build-debug-mingw/
+/cmake-build-debug-visual-studio/
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/ForestFireCPP.iml b/.idea/ForestFireCPP.iml
new file mode 100644
index 0000000..f08604b
--- /dev/null
+++ b/.idea/ForestFireCPP.iml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..0b76fe5
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..703c914
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..4e51aab
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,13 @@
+cmake_minimum_required(VERSION 3.28)
+project(ForestFireCPP)
+
+set(CMAKE_CXX_STANDARD 17)
+
+# Add the vcpkg toolchain file
+set(CMAKE_TOOLCHAIN_FILE "C:/Users/0piet/vcpkg/scripts/buildsystems/vcpkg.cmake" CACHE STRING "Vcpkg toolchain file")
+
+find_package(SFML COMPONENTS system window graphics CONFIG REQUIRED)
+
+add_executable(ForestFireCPP main.cpp)
+
+target_link_libraries(ForestFireCPP PRIVATE sfml-system sfml-window sfml-graphics)
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..f75c977
--- /dev/null
+++ b/README.md
@@ -0,0 +1,77 @@
+# Forest Fire Simulation
+
+This C++ project simulates the spread of forest fires using a cellular automaton model. It provides a visual representation of fire propagation in a forest environment, taking into account various factors such as wind speed, direction, and different vegetation types.
+
+## Features
+
+- Interactive grid-based simulation
+- Customizable simulation parameters
+- Real-time visualization using SFML graphics library
+- Different vegetation types (Normal Forest, Dry Grass, Dense Trees, Water)
+- Wind speed and direction influence on fire spread
+- Zoom and pan functionality for detailed observation
+
+## Prerequisites
+
+To build and run this project, you'll need:
+
+- C++17 compatible compiler
+- CMake (version 3.28 or higher)
+- SFML library
+- vcpkg package manager (recommended for easy SFML installation)
+
+## Building the Project
+
+1. Clone the repository:
+```bash
+git clone
+```
+2. Install SFML using vcpkg:
+```bash
+vcpkg install sfml:x64-windows
+```
+3. Configure the project using CMake:
+```bash
+mkdir build && cd build
+cmake .. -DCMAKE_TOOLCHAIN_FILE=[path to vcpkg]/scripts/buildsystems/vcpkg.cmake
+```
+4. Build the project:
+```bash
+cmake --build .
+```
+
+## Running the Simulation
+
+After building the project, run the executable:
+
+```bash
+./ForestFireCPP
+```
+
+You will be prompted to enter simulation parameters:
+
+- Probability of fire spread (0.0 - 1.0)
+- Probability of spontaneous ignition (0.0 - 1.0)
+- Wind speed (0.0 - 1.0)
+- Wind direction in degrees (0 - 360)
+- Water ratio (0.0 - 1.0)
+
+After entering the parameters, press Enter to start the simulation.
+
+## Controls
+
+- Left-click and drag to pan the view
+- Mouse wheel to zoom in/out
+
+## Contributing
+
+Contributions to improve the simulation or add new features are welcome. Please feel free to submit pull requests or open issues for bugs and feature requests.
+
+## License
+
+This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
+
+## Acknowledgments
+
+- Inspired by various forest fire simulation models and cellular automaton concepts and my already existing Python project (https://github.com/Quinta0/ForestFire.git)
+- SFML library for graphics rendering (https://www.sfml-dev.org/)
\ No newline at end of file
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..d239f76
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,259 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+// Constants
+const int GRID_SIZE = 256;
+const float CELL_SIZE = 5.0f;
+
+// Vegetation types
+enum class CellType {
+ NormalForest,
+ DryGrass,
+ DenseTrees,
+ Water,
+ Burning,
+ Burned
+};
+
+// Simulation parameters
+struct SimParams {
+ float p = 0.8f;
+ float pstart = 0.01f;
+ float w_speed = 0.5f;
+ float w_direction = 30.0f;
+ float water_ratio = 0.175f;
+};
+
+// Grid class
+class Grid {
+public:
+ Grid() : size(0) {}
+
+ Grid(int size, float water_ratio) : size(size), cells(size, std::vector(size, CellType::NormalForest)) {
+ initializeGrid(water_ratio);
+ }
+
+ void initializeGrid(float water_ratio) {
+ // Initialize grid similar to Python version
+ cells[size / 2][size / 2] = CellType::Burning;
+ cells[size / 4][size / 4] = CellType::DryGrass;
+ cells[3 * size / 4][3 * size / 4] = CellType::DenseTrees;
+
+ // Implement water initialization
+ int num_water_cells = static_cast(size * size * water_ratio);
+ for (int i = 0; i < num_water_cells; ++i) {
+ int x = rand() % size;
+ int y = rand() % size;
+ cells[y][x] = CellType::Water;
+ }
+ }
+
+ void update(float p, float pstart, float w_speed, float w_direction) {
+ std::vector> new_cells = cells;
+ for (int y = 0; y < size; ++y) {
+ for (int x = 0; x < size; ++x) {
+ new_cells[y][x] = updateCell(x, y, p, pstart, w_speed, w_direction);
+ }
+ }
+ cells = new_cells;
+ }
+
+ CellType getCell(int x, int y) const {
+ return cells[y][x];
+ }
+
+private:
+ int size;
+ std::vector> cells;
+
+ CellType updateCell(int x, int y, float p, float pstart, float w_speed, float w_direction) {
+ CellType current = cells[y][x];
+ if (current == CellType::Burning) return CellType::Burned;
+ if (current == CellType::Burned || current == CellType::Water) return current;
+
+ for (const auto& neighbor : getNeighbors(x, y)) {
+ if (cells[neighbor.second][neighbor.first] == CellType::Burning) {
+ float angle = calculateAngle(x, y, neighbor.first, neighbor.second);
+ float directional_influence = calculateDirectionalInfluence(w_direction, angle);
+ float vegetation_factor = getVegetationFactor(current);
+ // Implement probability calculation and fire spread logic here
+ float adjusted_p = p * vegetation_factor * (1 + 0.1f * w_speed * directional_influence);
+
+ if (static_cast(rand()) / RAND_MAX < adjusted_p) {
+ return CellType::Burning;
+ }
+ }
+ }
+
+ if (static_cast(rand()) / RAND_MAX < pstart) {
+ return CellType::Burning;
+ }
+
+ return current;
+ }
+
+ std::vector> getNeighbors(int x, int y) {
+ std::vector> neighbors;
+ for (int dx = -1; dx <= 1; ++dx) {
+ for (int dy = -1; dy <= 1; ++dy) {
+ if (dx == 0 && dy == 0) continue;
+ int nx = x + dx, ny = y + dy;
+ if (nx >= 0 && nx < size && ny >= 0 && ny < size) {
+ neighbors.emplace_back(nx, ny);
+ }
+ }
+ }
+ return neighbors;
+ }
+
+ float calculateAngle(int x1, int y1, int x2, int y2) {
+ return std::atan2(y2 - y1, x2 - x1) * 180 / M_PI;
+ }
+
+ float calculateDirectionalInfluence(float w_direction, float angle) {
+ float angle_diff = std::abs(w_direction - angle);
+ angle_diff = std::min(angle_diff, 360.0f - angle_diff);
+ return 1.0f - (angle_diff / 180.0f);
+ }
+
+ float getVegetationFactor(CellType type) {
+ switch (type) {
+ case CellType::NormalForest: return 1.0f;
+ case CellType::DryGrass: return 1.5f;
+ case CellType::DenseTrees: return 0.5f;
+ case CellType::Water: return 0.0f;
+ default: return 1.0f;
+ }
+ }
+};
+
+// Main application class
+class ForestFireSim {
+public:
+ void getSimulationParameters() {
+ std::cout << "Enter simulation parameters:\n";
+ std::cout << "Probability of fire spread (0.0 - 1.0): ";
+ std::cin >> params.p;
+ std::cout << "Probability of spontaneous ignition (0.0 - 1.0): ";
+ std::cin >> params.pstart;
+ std::cout << "Wind speed (0.0 - 1.0): ";
+ std::cin >> params.w_speed;
+ std::cout << "Wind direction in degrees (0 - 360): ";
+ std::cin >> params.w_direction;
+ std::cout << "Water ratio (0.0 - 1.0): ";
+ std::cin >> params.water_ratio;
+ }
+
+ ForestFireSim() : window(sf::VideoMode(800, 600), "Forest Fire Simulation"),
+ view(window.getDefaultView()),
+ grid(GRID_SIZE, params.water_ratio) {
+ window.setView(view);
+ getSimulationParameters();
+ grid = Grid(GRID_SIZE, params.water_ratio);
+ }
+
+ void run() {
+ while (window.isOpen()) {
+ handleEvents();
+ update();
+ render();
+ }
+ }
+
+ void startSimulation() {
+ std::cout << "Press Enter to start the simulation...";
+ std::cin.ignore(std::numeric_limits::max(), '\n');
+ std::cin.get();
+ run();
+ }
+
+
+private:
+ sf::RenderWindow window;
+ Grid grid;
+ sf::View view;
+ SimParams params;
+ sf::Vector2f lastMousePos;
+ float zoomLevel = 1.0f;
+
+ void handleEvents() {
+ sf::Event event;
+ while (window.pollEvent(event)) {
+ if (event.type == sf::Event::Closed)
+ window.close();
+ else if (event.type == sf::Event::MouseButtonPressed) {
+ if (event.mouseButton.button == sf::Mouse::Left) {
+ lastMousePos = window.mapPixelToCoords(sf::Vector2i(event.mouseButton.x, event.mouseButton.y));
+ }
+ }
+ else if (event.type == sf::Event::MouseMoved) {
+ if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) {
+ sf::Vector2f newMousePos = window.mapPixelToCoords(sf::Vector2i(event.mouseMove.x, event.mouseMove.y));
+ sf::Vector2f deltaPos = lastMousePos - newMousePos;
+ view.move(deltaPos);
+ lastMousePos = newMousePos;
+ }
+ }
+ else if (event.type == sf::Event::MouseWheelScrolled) {
+ if (event.mouseWheelScroll.delta > 0)
+ zoomLevel *= 1.1f;
+ else if (event.mouseWheelScroll.delta < 0)
+ zoomLevel /= 1.1f;
+ view.setSize(window.getDefaultView().getSize());
+ view.zoom(zoomLevel);
+ }
+ }
+ }
+
+ void update() {
+ grid.update(params.p, params.pstart, params.w_speed, params.w_direction);
+ }
+
+ void render() {
+ window.clear(sf::Color::White);
+ window.setView(view);
+
+ // Draw grid
+ for (int y = 0; y < GRID_SIZE; ++y) {
+ for (int x = 0; x < GRID_SIZE; ++x) {
+ sf::RectangleShape cell(sf::Vector2f(CELL_SIZE, CELL_SIZE));
+ cell.setPosition(x * CELL_SIZE, y * CELL_SIZE);
+ cell.setFillColor(getCellColor(grid.getCell(x, y)));
+ window.draw(cell);
+ }
+ }
+
+ window.display();
+ }
+
+ sf::Color getCellColor(CellType type) {
+ switch (type) {
+ case CellType::NormalForest: return sf::Color::Green;
+ case CellType::DryGrass: return sf::Color::Yellow;
+ case CellType::DenseTrees: return sf::Color(0, 100, 0); // Dark Green
+ case CellType::Water: return sf::Color::Blue;
+ case CellType::Burning: return sf::Color::Red;
+ case CellType::Burned: return sf::Color::Black;
+ default: return sf::Color::White;
+ }
+ }
+};
+
+
+
+int main() {
+ srand(static_cast(time(0)));
+ ForestFireSim sim;
+ sim.startSimulation();
+ return 0;
+}
diff --git a/vcpkg-configuration.json b/vcpkg-configuration.json
new file mode 100644
index 0000000..2599769
--- /dev/null
+++ b/vcpkg-configuration.json
@@ -0,0 +1,14 @@
+{
+ "default-registry": {
+ "kind": "git",
+ "baseline": "3f530d4827b064f5894e94a8946473d40999826e",
+ "repository": "https://github.com/microsoft/vcpkg"
+ },
+ "registries": [
+ {
+ "kind": "artifact",
+ "location": "https://github.com/microsoft/vcpkg-ce-catalog/archive/refs/heads/main.zip",
+ "name": "microsoft"
+ }
+ ]
+}
diff --git a/vcpkg.json b/vcpkg.json
new file mode 100644
index 0000000..9e147fa
--- /dev/null
+++ b/vcpkg.json
@@ -0,0 +1,7 @@
+{
+ "name": "forest-fire-cpp",
+ "version-string": "0.1.0",
+ "dependencies": [
+ "sfml"
+ ]
+}