Charles Croz 1 жил өмнө
parent
commit
37c864a982

+ 2 - 1
.vscode/settings.json

@@ -10,5 +10,6 @@
         "utility": "c",
         "terrain.h": "c",
         "iterator": "c"
-    }
+    },
+    "C_Cpp.default.compilerPath": "/usr/bin/g++"
 }

+ 0 - 0
.gitignore → C/.gitignore


+ 0 - 0
Makefile → C/Makefile


+ 0 - 0
main.c → C/main.c


+ 0 - 0
particles.h → C/particles.h


+ 0 - 0
terrain.h → C/terrain.h


+ 2 - 0
Cpp/.gitignore

@@ -0,0 +1,2 @@
+*.o
+particle

+ 16 - 0
Cpp/.vscode/c_cpp_properties.json

@@ -0,0 +1,16 @@
+{
+    "configurations": [
+        {
+            "name": "Linux",
+            "includePath": [
+                "${workspaceFolder}/**"
+            ],
+            "defines": [],
+            "compilerPath": "/usr/bin/g++",
+            "cStandard": "c17",
+            "cppStandard": "c++14",
+            "intelliSenseMode": "linux-clang-x64"
+        }
+    ],
+    "version": 4
+}

+ 60 - 0
Cpp/.vscode/settings.json

@@ -0,0 +1,60 @@
+{
+    "files.associations": {
+        "cstdint": "cpp",
+        "iostream": "cpp",
+        "array": "cpp",
+        "atomic": "cpp",
+        "bit": "cpp",
+        "*.tcc": "cpp",
+        "cctype": "cpp",
+        "chrono": "cpp",
+        "cinttypes": "cpp",
+        "clocale": "cpp",
+        "cmath": "cpp",
+        "compare": "cpp",
+        "complex": "cpp",
+        "concepts": "cpp",
+        "csignal": "cpp",
+        "cstdarg": "cpp",
+        "cstddef": "cpp",
+        "cstdio": "cpp",
+        "cstdlib": "cpp",
+        "cstring": "cpp",
+        "ctime": "cpp",
+        "cwchar": "cpp",
+        "cwctype": "cpp",
+        "deque": "cpp",
+        "list": "cpp",
+        "string": "cpp",
+        "unordered_map": "cpp",
+        "vector": "cpp",
+        "exception": "cpp",
+        "algorithm": "cpp",
+        "functional": "cpp",
+        "iterator": "cpp",
+        "memory": "cpp",
+        "memory_resource": "cpp",
+        "numeric": "cpp",
+        "random": "cpp",
+        "ratio": "cpp",
+        "string_view": "cpp",
+        "system_error": "cpp",
+        "tuple": "cpp",
+        "type_traits": "cpp",
+        "utility": "cpp",
+        "initializer_list": "cpp",
+        "iosfwd": "cpp",
+        "istream": "cpp",
+        "limits": "cpp",
+        "new": "cpp",
+        "numbers": "cpp",
+        "ostream": "cpp",
+        "semaphore": "cpp",
+        "sstream": "cpp",
+        "stdexcept": "cpp",
+        "stop_token": "cpp",
+        "streambuf": "cpp",
+        "thread": "cpp",
+        "typeinfo": "cpp"
+    }
+}

+ 26 - 0
Cpp/Makefile

@@ -0,0 +1,26 @@
+
+APP=particle
+OBJ=main.o Map.o Particle.o
+HEADERS=
+
+GPP=g++
+CFLAGS=-O3
+CLIB=-lm -lSDL2 -fopenmp
+
+all: $(APP)
+
+$(APP): $(OBJ) $(HEADERS)
+	$(GPP) -o $@ $^ $(CFLAGS) $(CLIB)
+
+main.o: main.cpp
+	$(GPP) -c -o $@ $< $(CFLAGS) $(CLIB)
+
+Map.o: Map.cpp
+	$(GPP) -c -o $@ $< $(CFLAGS) $(CLIB)
+
+Particle.o: Particle.cpp
+	$(GPP) -c -o $@ $< $(CFLAGS) $(CLIB)
+
+clean:
+	rm $(APP) $(OBJ)
+

+ 70 - 0
Cpp/Map.cpp

@@ -0,0 +1,70 @@
+#include "definitions.hpp"
+#include "Map.hpp"
+#include "Particle.hpp"
+#include <sys/types.h>
+#include <omp.h>
+
+Map::Map(size_t width, size_t height): m_width(width), m_height(height)
+{
+    m_surface = (size_t) width * (size_t) height;
+    m_tiles.resize(m_surface);
+    for(auto &tile : m_tiles){
+        tile.pheromone = 0;
+        tile.variation = 0;
+    }
+    m_tiles_swap.resize(m_surface);
+    for(auto &tile : m_tiles_swap){
+        tile.pheromone = 0;
+        tile.variation = 0;
+    }
+}
+
+void Map::populate(std::vector<Particle> && particles){
+    this->m_particles = std::move(particles);
+}
+
+inline size_t index(ssize_t i, ssize_t j, size_t height, size_t width){
+    if(i < 0)
+        i += height;
+    if(j < 0)
+        j += width;
+    if(i >= height)
+        i -= height;
+    if(j >= width)
+        j -= width;
+    return i * width + j;
+}
+
+void Map::update(numeric_t delta_t)
+{
+    #pragma omp parallel for
+    for(size_t i = 0 ; i < m_particles.size(); ++i){
+        m_particles[i].update(*this, delta_t, speed, steering, sampling_angle, sampling_distance);
+    }
+
+    for(size_t i = 0 ; i < m_particles.size(); ++i){
+        m_tiles[m_particles[i].tile_index(*this)].variation += increase * delta_t;
+        m_tiles_swap[m_particles[i].tile_index(*this)].population ++;
+    }
+
+    #pragma omp parallel for
+    for(size_t i = 0 ; i < m_tiles.size(); ++i){
+        m_tiles[i].variation -= decay * delta_t;
+        m_tiles[i].update();
+    }
+
+
+    #pragma omp parallel for
+    for(ssize_t i = 0 ; i < m_height; ++i){
+        for(ssize_t j = 0 ; j < m_width; ++j){
+            m_tiles_swap[index(i, j, m_height, m_width)].pheromone = 
+                m_tiles[index(i, j, m_height, m_width)].pheromone * (1 - 4 * diffusion * delta_t)
+                + m_tiles[index(i - 1, j, m_height, m_width)].pheromone * diffusion * delta_t
+                + m_tiles[index(i + 1, j, m_height, m_width)].pheromone * diffusion * delta_t
+                + m_tiles[index(i, j - 1, m_height, m_width)].pheromone * diffusion * delta_t
+                + m_tiles[index(i, j + 1, m_height, m_width)].pheromone * diffusion * delta_t;
+        }
+    }
+
+    std::swap(m_tiles, m_tiles_swap);
+}

+ 45 - 0
Cpp/Map.hpp

@@ -0,0 +1,45 @@
+#ifndef PARTICLE_MAP
+#define PARTICLE_MAP
+
+#include <vector>
+#include "definitions.hpp"
+#include "Tile.hpp"
+
+class Particle;
+
+class Map
+{
+private:
+    size_t m_width{};
+    size_t m_height{};
+    size_t m_surface{};
+
+    std::vector<Tile> m_tiles{};
+    std::vector<Tile> m_tiles_swap{};
+    std::vector<Particle> m_particles{};
+
+public:
+    numeric_t increase{};
+    numeric_t decay{};
+    numeric_t diffusion{};
+
+    numeric_t speed{};
+    numeric_t steering{};
+    numeric_t sampling_distance{};
+    numeric_t sampling_angle{};
+
+    Map(size_t width, size_t height);
+    ~Map() = default;
+
+    void populate(std::vector<Particle> && particles);
+
+    void update(numeric_t delta_t);
+
+    size_t width() const { return m_width ;}
+    size_t height() const { return m_height ;}
+    size_t surface() const { return m_surface ;}
+
+    const std::vector<Tile> &tiles() const { return m_tiles; };
+};
+
+#endif // PARTICLE_MAP

+ 74 - 0
Cpp/Particle.cpp

@@ -0,0 +1,74 @@
+#include "definitions.hpp"
+#include "Particle.hpp"
+#include "Map.hpp"
+
+#include <cmath>
+
+Particle::Particle(fpoint_t position, fpoint_t direction):
+                   m_position(position), m_direction(direction)
+{
+}
+
+fpoint_t fit_map(fpoint_t point, numeric_t width, numeric_t height){
+    if(point.x < 0){
+        point.x += width;
+    }
+    if(point.y < 0){
+        point.y += height;
+    }
+    if(point.x >= width){
+        point.x -= width;
+    }
+    if(point.y >= height){
+        point.y -= height;
+    }
+    return point;
+}
+
+fpoint_t ahead(fpoint_t point, fpoint_t direction, numeric_t distance){
+    point.x += direction.x * distance;
+    point.y += direction.y * distance;
+    return point;
+}
+
+fpoint_t rotate(fpoint_t vec, numeric_t angle_deg){
+    numeric_t C = cos(angle_deg * M_PI / 180.0);
+    numeric_t S = sin(angle_deg * M_PI / 180.0);
+    return {C * vec.x - S * vec.y, S * vec.x + C * vec.y};
+}
+
+
+size_t map_coord(fpoint_t point, icoord_t width, icoord_t height){
+    return (size_t) floor(point.y) * (size_t) width + (size_t) floor(point.x);
+}
+
+size_t Particle::tile_index(Map const &map)
+{
+    return map_coord(m_position, map.width(), map.height());
+}
+
+
+void Particle::update(Map const &map, 
+                      numeric_t delta_t, 
+                      numeric_t speed, 
+                      numeric_t steering, 
+                      numeric_t sampling_angle, 
+                      numeric_t sampling_distance)
+{
+    m_position.x += m_direction.x * speed * delta_t;
+    m_position.y += m_direction.y * speed * delta_t;
+    
+    m_position = fit_map(m_position, map.width(), map.height());
+
+    fpoint_t bit_ahead = fit_map(ahead(m_position, m_direction, sampling_distance), map.width(), map.height());
+    fpoint_t bit_right = fit_map(ahead(m_position, rotate(m_direction, -sampling_angle), sampling_distance), map.width(), map.height());
+    fpoint_t bit_left  = fit_map(ahead(m_position, rotate(m_direction,  sampling_angle), sampling_distance), map.width(), map.height());
+    numeric_t pheromone_ahead = map.tiles()[map_coord(bit_ahead, map.width(), map.height())].pheromone;
+    numeric_t pheromone_right = map.tiles()[map_coord(bit_right, map.width(), map.height())].pheromone;
+    numeric_t pheromone_left  = map.tiles()[map_coord(bit_left , map.width(), map.height())].pheromone;
+    if (pheromone_right > pheromone_ahead && pheromone_right > pheromone_left)
+        m_direction = rotate(m_direction, -steering * delta_t);
+    else if(pheromone_left > pheromone_ahead && pheromone_left > pheromone_right)
+        m_direction = rotate(m_direction,  steering * delta_t);
+
+}

+ 28 - 0
Cpp/Particle.hpp

@@ -0,0 +1,28 @@
+#ifndef PARTICLE_PARTICLE
+#define PARTICLE_PARTICLE
+
+#include "definitions.hpp"
+
+class Map;
+
+class Particle
+{
+private:
+    fpoint_t m_position;
+    fpoint_t m_direction;
+
+public:
+    Particle(fpoint_t m_position, fpoint_t m_direction);
+    Particle() = default;
+    ~Particle() = default;
+    
+    void update(Map const &map, 
+                numeric_t delta_t, 
+                numeric_t speed, 
+                numeric_t steering, 
+                numeric_t sampling_angle, 
+                numeric_t sampling_distance);
+    size_t tile_index(Map const &map);
+};
+
+#endif // PARTICLE_PARTICLE

+ 22 - 0
Cpp/Tile.hpp

@@ -0,0 +1,22 @@
+#ifndef PARTICLE_TILE
+#define PARTICLE_TILE
+
+#include "definitions.hpp"
+
+struct Tile {
+    numeric_t pheromone = 0;
+    numeric_t variation = 0;
+    size_t population = 0;
+
+    void update(){
+        pheromone += variation;
+        if(pheromone < 0)
+            pheromone = 0;
+        variation = 0;
+        population = 0;
+    }
+};
+
+
+
+#endif // PARTICLE_TILE

+ 24 - 0
Cpp/definitions.hpp

@@ -0,0 +1,24 @@
+#ifndef PARTICLE_DEFINITIONS
+#define PARTICLE_DEFINITIONS
+
+#include <cstdint>
+#include <cstddef>
+#include <cmath>
+
+using numeric_t = double;
+using icoord_t = size_t;
+using fcoord_t = double;
+
+typedef struct 
+{
+    icoord_t x;
+    icoord_t y;
+} ipoint_t;
+
+typedef struct 
+{
+    fcoord_t x;
+    fcoord_t y;
+} fpoint_t;
+
+#endif // PARTICLE_DEFINITIONS

+ 134 - 0
Cpp/main.cpp

@@ -0,0 +1,134 @@
+
+#include <iostream>
+#define _USE_MATH_DEFINES
+#include <cmath>
+
+#include "SDL2/SDL.h"
+#include <SDL2/SDL_image.h>
+#include <SDL2/SDL_timer.h>
+
+#include <vector>
+#include <thread>
+#include <chrono>
+
+#include "definitions.hpp"
+#include "Map.hpp"
+#include "Particle.hpp"
+#include "Tile.hpp"
+
+numeric_t my_rand(numeric_t min, numeric_t max){
+    numeric_t rand_x = (numeric_t)(rand())/(numeric_t)(RAND_MAX);
+    if(rand_x == 1)
+        rand_x = 0;
+    return min + rand_x * (max - min);
+}
+
+Uint8 clamp_Uint8(numeric_t x){
+    if(x >= 255.0f)
+        return 255;
+    if(x <= 0.0f)
+        return 0;
+    return (Uint8) x;
+}
+
+int main(int argc, char *argv[]){
+    size_t width = 600;
+    size_t height = 400;
+    size_t population = 100000;
+
+    numeric_t increase = 20;
+    numeric_t decay = 13;
+    numeric_t diffusion = 1.5;
+
+    numeric_t speed = 30;
+    numeric_t steering = 180;
+    numeric_t sampling_distance = 3;
+    numeric_t sampling_angle = 30;
+
+
+    numeric_t average_pop = (numeric_t)population / (numeric_t)(width * height);
+    numeric_t average_pheromone = (numeric_t)population * (numeric_t)(increase) / (numeric_t)(width * height);
+
+    Map map(width, height);
+    map.increase = increase;
+    map.decay = decay;
+    map.diffusion = diffusion;
+
+    map.speed = speed;
+    map.steering = steering;
+    map.sampling_angle = sampling_angle;
+    map.sampling_distance = sampling_distance;
+
+    {
+        std::vector<Particle> particles;
+        particles.reserve(population);
+        for(size_t i = 0 ; i < population ; i++){
+            fpoint_t pos{my_rand(0, width), my_rand(0, height)};
+            numeric_t angle = my_rand(0, 2*M_PI);
+            fpoint_t dir{(fcoord_t) cos(angle), (fcoord_t) sin(angle)};
+            particles.push_back(Particle(pos, dir));
+            // std::cout << "pos=" << pos.x << ";" << pos.x << " dir=" << dir.x << ";" << dir.y << "\n";
+        }
+
+        map.populate(std::move(particles));
+    }
+
+    SDL_Window* win;
+    SDL_Renderer* renderer;
+    Uint64 time_last;
+    Uint64 time_now;
+    numeric_t delta_time;
+    SDL_CreateWindowAndRenderer(width, height, 0, &win, &renderer);
+    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
+    SDL_RenderClear(renderer);
+    time_now = SDL_GetTicks64();
+
+    bool running = true;
+    while(running){SDL_Event event;
+    
+        // Events management
+        while (SDL_PollEvent(&event)) {
+            if(event.type == SDL_QUIT) {
+                running = false;
+                break;
+            }else if(event.type == SDL_KEYDOWN){
+                if(event.key.keysym.scancode == SDL_SCANCODE_K){
+                    map.increase = 0;
+                    map.decay = 1000;
+                    map.diffusion = 0.3;
+                    map.steering = 0;
+                }
+            }
+        }
+
+        time_last = time_now;
+        time_now = SDL_GetTicks64();
+        delta_time = (time_now - time_last) / 1000.0f;
+        // std::cout << delta_time << "\n";
+
+        map.update(delta_time);
+
+        SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
+        SDL_RenderClear(renderer);
+
+        for(size_t i = 0 ; i < height ; ++i){
+            for(size_t j = 0 ; j < width ; ++j){
+                Uint8 pheromone = clamp_Uint8( map.tiles().at(i * width + j).pheromone  * 255.0f/average_pheromone );
+                Uint8 tile_pop  = clamp_Uint8( map.tiles().at(i * width + j).population * 20.0f/average_pop );
+                SDL_SetRenderDrawColor(renderer, pheromone, tile_pop, tile_pop, 1);
+                // SDL_SetRenderDrawColor(renderer, pheromone, tile_pop, pheromone, 1);
+                SDL_RenderDrawPoint(renderer, j, i);
+            }
+        }
+
+        std::this_thread::sleep_for(std::chrono::milliseconds(20));
+        SDL_RenderPresent(renderer);
+    }
+
+    // destroy SDL things
+    SDL_DestroyWindow(win);
+    SDL_DestroyRenderer(renderer);
+    SDL_Quit();
+
+    return 0;
+}

BIN
Cpp/particle