diff --git a/.idea/editor.xml b/.idea/editor.xml
new file mode 100644
index 0000000..206fe22
--- /dev/null
+++ b/.idea/editor.xml
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0a1ce6a..d29ce37 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25)
-project(graphs VERSION 0.0.26)
+project(graphs VERSION 0.0.27)
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
option(ENABLE_UBSAN "Enable the ub sanitizer" OFF)
diff --git a/src/main.cpp b/src/main.cpp
index 69d379b..ab1f4e4 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -27,6 +27,7 @@
#include
#include
#include
+#include
#include
#include
@@ -48,10 +49,11 @@ struct bounding_box
int min_y = 0;
int max_x = 0;
int max_y = 0;
-
- bounding_box(int min_x, int min_y, int max_x, int max_y): min_x(min_x), min_y(min_y), max_x(max_x), max_y(max_y)
- {}
-
+
+ bounding_box(const int min_x, const int min_y, const int max_x, const int max_y): min_x(min_x), min_y(min_y), max_x(max_x), max_y(max_y)
+ {
+ }
+
bool is_screen = true;
};
@@ -60,7 +62,7 @@ class graph_t
private:
std::vector nodes;
blt::hashset_t edges;
- blt::hashmap_t> connected_nodes;
+ blt::hashmap_t > connected_nodes;
bool sim = false;
bool run_infinitely = true;
float sim_speed = 1;
@@ -70,11 +72,11 @@ class graph_t
int max_iterations = 5000;
std::unique_ptr equation;
static constexpr float POINT_SIZE = 35;
-
+
blt::i32 current_node = -1;
-
- void create_random_graph(bounding_box bb, blt::size_t min_nodes, blt::size_t max_nodes, blt::f64 connectivity, blt::f64 scaling_connectivity,
- blt::f64 distance_factor)
+
+ void create_random_graph(bounding_box bb, const blt::size_t min_nodes, const blt::size_t max_nodes, const blt::f64 connectivity,
+ const blt::f64 scaling_connectivity, const blt::f64 distance_factor)
{
// don't allow points too close to the edges of the window.
if (bb.is_screen)
@@ -89,9 +91,9 @@ class graph_t
std::uniform_int_distribution node_count_dist(min_nodes, max_nodes);
std::uniform_real_distribution pos_x_dist(static_cast(bb.min_x), static_cast(bb.max_x));
std::uniform_real_distribution pos_y_dist(static_cast(bb.min_y), static_cast(bb.max_y));
-
- auto node_count = node_count_dist(dev);
-
+
+ const auto node_count = node_count_dist(dev);
+
for (blt::size_t i = 0; i < node_count; i++)
{
float x, y;
@@ -103,11 +105,10 @@ class graph_t
for (const auto& node : nodes)
{
const auto& rp = node.getRenderObj().pos;
- float dx = rp.x() - x;
- float dy = rp.y() - y;
- float dist = std::sqrt(dx * dx + dy * dy);
-
- if (dist <= POINT_SIZE)
+ const float dx = rp.x() - x;
+ const float dy = rp.y() - y;
+
+ if (const float dist = std::sqrt(dx * dx + dy * dy); dist <= POINT_SIZE)
{
can_break = false;
break;
@@ -118,27 +119,26 @@ class graph_t
} while (true);
nodes.push_back(node({x, y, POINT_SIZE}));
}
-
- for (const auto& node1 : blt::enumerate(nodes))
+
+ for (const auto& [index1, node1] : blt::enumerate(nodes))
{
- for (const auto& node2 : blt::enumerate(nodes))
+ for (const auto& [index2, node2] : blt::enumerate(nodes))
{
- if (node1.first == node2.first)
+ if (index1 == index2)
continue;
- auto diff = node2.second.getPosition() - node1.second.getPosition();
- auto diff_sq = (diff * diff);
- auto dist = distance_factor / static_cast(std::sqrt(diff_sq.x() + diff_sq.y()));
+ const auto diff = node2.getPosition() - node1.getPosition();
+ const auto diff_sq = (diff * diff);
+ const auto dist = distance_factor / static_cast(std::sqrt(diff_sq.x() + diff_sq.y()));
double dexp;
if (dist == 0)
dexp = 0;
else
dexp = 1 / (std::exp(dist) - dist);
- auto rand = chance(dev);
- if (rand <= connectivity && rand >= dexp * scaling_connectivity)
- connect(node1.first, node2.first);
+ if (const auto rand = chance(dev); rand <= connectivity && rand >= dexp * scaling_connectivity)
+ connect(index1, index2);
}
}
-
+
std::uniform_int_distribution node_select_dist(0ul, nodes.size() - 1);
for (blt::size_t i = 0; i < nodes.size(); i++)
{
@@ -158,18 +158,18 @@ class graph_t
}
}
}
-
+
public:
graph_t() = default;
-
- void make_new(const bounding_box& bb, blt::size_t min_nodes, blt::size_t max_nodes, blt::f64 connectivity)
+
+ void make_new(const bounding_box& bb, const blt::size_t min_nodes, const blt::size_t max_nodes, const blt::f64 connectivity)
{
create_random_graph(bb, min_nodes, max_nodes, connectivity, 0, 25);
use_Eades();
}
-
- void reset(const bounding_box& bb, blt::size_t min_nodes, blt::size_t max_nodes, blt::f64 connectivity, blt::f64 scaling_connectivity,
- blt::f64 distance_factor)
+
+ void reset(const bounding_box& bb, const blt::size_t min_nodes, const blt::size_t max_nodes, const blt::f64 connectivity,
+ const blt::f64 scaling_connectivity, const blt::f64 distance_factor)
{
sim = false;
current_iterations = 0;
@@ -179,20 +179,20 @@ class graph_t
connected_nodes.clear();
create_random_graph(bb, min_nodes, max_nodes, connectivity, scaling_connectivity, distance_factor);
}
-
- void connect(blt::u64 n1, blt::u64 n2)
+
+ void connect(const blt::u64 n1, const blt::u64 n2)
{
edges.insert(edge{n1, n2});
connected_nodes[n1].insert(n2);
connected_nodes[n2].insert(n1);
}
-
+
[[nodiscard]] bool connected(blt::u64 e1, blt::u64 e2) const
{
return edges.contains({e1, e2});
}
-
- void render(double frame_time)
+
+ void render(const double frame_time)
{
if (sim && (current_iterations < max_iterations || run_infinitely) && max_force_last > threshold)
{
@@ -217,14 +217,14 @@ class graph_t
// update positions
for (auto& v : nodes)
{
- float sim_factor = static_cast(frame_time * sim_speed) * 0.05f;
+ const float sim_factor = static_cast(frame_time * sim_speed) * 0.05f;
v.getPositionRef() += v.getVelocityRef() * equation->cooling_factor(current_iterations) * sim_factor;
max_force_last = std::max(max_force_last, v.getVelocityRef().magnitude());
}
current_iterations++;
}
}
-
+
for (const auto& point : nodes)
renderer_2d.drawPointInternal("parker_point", point.getRenderObj(), 10.0f);
for (const auto& edge : edges)
@@ -240,99 +240,94 @@ class graph_t
}
}
}
-
+
void reset_mouse_drag()
{
current_node = -1;
}
-
- void process_mouse_drag(blt::i32 width, blt::i32 height)
+
+ void process_mouse_drag(const blt::i32 width, const blt::i32 height)
{
- auto mouse_pos = blt::make_vec2(blt::gfx::calculateRay2D(width, height, global_matrices.getScale2D(), global_matrices.getView2D(),
- global_matrices.getOrtho()));
-
+ const auto mouse_pos = blt::make_vec2(blt::gfx::calculateRay2D(width, height, global_matrices.getScale2D(), global_matrices.getView2D(),
+ global_matrices.getOrtho()));
+
if (current_node < 0)
{
-
- for (const auto& n : blt::enumerate(nodes))
+ for (const auto& [index, node] : blt::enumerate(nodes))
{
- auto pos = n.second.getPosition();
-
- auto dist = pos - mouse_pos;
- auto mag = dist.magnitude();
-
- if (mag < POINT_SIZE)
+ const auto pos = node.getPosition();
+ const auto dist = pos - mouse_pos;
+
+ if (const auto mag = dist.magnitude(); mag < POINT_SIZE)
{
- current_node = static_cast(n.first);
+ current_node = static_cast(index);
break;
}
}
} else
- {
nodes[current_node].getPositionRef() = mouse_pos;
- }
}
-
+
void use_Eades()
{
equation = std::make_unique();
}
-
+
void use_Fruchterman_Reingold()
{
equation = std::make_unique();
}
-
+
void start_sim()
{
sim = true;
}
-
+
void stop_sim()
{
sim = false;
}
-
- std::string getSimulatorName()
+
+ [[nodiscard]] std::string getSimulatorName() const
{
return equation->name();
}
-
- auto* getSimulator()
+
+ [[nodiscard]] auto* getSimulator() const
{
return equation.get();
}
-
- auto getCoolingFactor()
+
+ [[nodiscard]] auto getCoolingFactor() const
{
return equation->cooling_factor(current_iterations);
}
-
+
void reset_iterations()
{
current_iterations = 0;
}
-
- bool& getIterControl()
+
+ [[nodiscard]] bool& getIterControl()
{
return run_infinitely;
}
-
- float& getSimSpeed()
+
+ [[nodiscard]] float& getSimSpeed()
{
return sim_speed;
}
-
- float& getThreshold()
+
+ [[nodiscard]] float& getThreshold()
{
return threshold;
}
-
- int& getMaxIterations()
+
+ [[nodiscard]] int& getMaxIterations()
{
return max_iterations;
}
-
+
[[nodiscard]] int numberOfNodes() const
{
return static_cast(nodes.size());
@@ -343,25 +338,20 @@ class engine_t
{
private:
graph_t graph;
- public:
- void init(const blt::gfx::window_data& data)
- {
- graph.make_new({0, 0, data.width, data.height}, 5, 25, 0.2);
- }
-
- void render(const blt::gfx::window_data& data, double ft)
+
+ void draw_gui(const blt::gfx::window_data& data, const double ft)
{
if (im::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize))
{
static int min_nodes = 5;
static int max_nodes = 25;
-
+
static bounding_box bb{0, 0, data.width, data.height};
-
+
static float connectivity = 0.12;
static float scaling_connectivity = 0.5;
static float distance_factor = 100;
-
+
//im::SetNextItemOpen(true, ImGuiCond_Once);
im::Text("FPS: %lf Frame-time (ms): %lf Frame-time (S): %lf", fps, ft * 1000.0, ft);
im::Text("Number of Nodes: %d", graph.numberOfNodes());
@@ -425,11 +415,11 @@ class engine_t
if (im::Button("Reset Iterations"))
graph.reset_iterations();
im::Text("Select a system:");
- auto current_sim = graph.getSimulatorName();
+ const auto current_sim = graph.getSimulatorName();
const char* items[] = {"Eades", "Fruchterman & Reingold"};
static int item_current = 0;
ImGui::ListBox("##SillyBox", &item_current, items, 2, 2);
-
+
if (strcmp(items[item_current], current_sim.c_str()) != 0)
{
switch (item_current)
@@ -450,14 +440,27 @@ class engine_t
}
im::End();
}
-
+ }
+
+ public:
+ void init(const blt::gfx::window_data& data)
+ {
+ graph.make_new({0, 0, data.width, data.height}, 5, 25, 0.2);
+ }
+
+ void render(const blt::gfx::window_data& data, const double ft)
+ {
+ draw_gui(data, ft);
+
auto& io = ImGui::GetIO();
-
+
if (!io.WantCaptureMouse && blt::gfx::isMousePressed(0))
graph.process_mouse_drag(data.width, data.height);
else
graph.reset_mouse_drag();
-
+
+
+
graph.render(ft);
}
};
@@ -468,37 +471,37 @@ void init(const blt::gfx::window_data& data)
{
using namespace blt::gfx;
resources.setPrefixDirectory("../");
-
+
resources.enqueue("res/debian.png", "debian");
resources.enqueue("res/parker.png", "parker");
resources.enqueue("res/parkerpoint.png", "parker_point");
resources.enqueue("res/parker cat ears.jpg", "parkercat");
-
+
global_matrices.create_internals();
resources.load_resources();
renderer_2d.create();
-
+
engine.init(data);
-
+
lastTime = blt::system::nanoTime();
}
void update(const blt::gfx::window_data& data)
{
global_matrices.update_perspectives(data.width, data.height, 90, 0.1, 2000);
-
+
//im::ShowDemoWindow();
-
+
engine.render(data, ft);
-
+
camera.update();
camera.update_view(global_matrices);
global_matrices.update();
-
+
renderer_2d.render();
-
- auto currentTime = blt::system::nanoTime();
- auto diff = currentTime - lastTime;
+
+ const auto currentTime = blt::system::nanoTime();
+ const auto diff = currentTime - lastTime;
lastTime = currentTime;
ft = static_cast(diff) / 1000000000.0;
fps = 1 / ft;
@@ -511,6 +514,6 @@ int main(int, const char**)
resources.cleanup();
renderer_2d.cleanup();
blt::gfx::cleanup();
-
+
return 0;
}