diff --git a/CMakeLists.txt b/CMakeLists.txt index b135401..dd00341 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(graphs VERSION 0.0.49) +project(graphs VERSION 0.1.0) option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF) option(ENABLE_UBSAN "Enable the ub sanitizer" OFF) diff --git a/include/config.h b/include/config.h new file mode 100644 index 0000000..82eca05 --- /dev/null +++ b/include/config.h @@ -0,0 +1,41 @@ +#pragma once +/* + * Copyright (C) 2024 Brett Terpstra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef GRAPHS_CONFIG_H +#define GRAPHS_CONFIG_H + +#include +#include + +namespace conf +{ + inline constexpr float DEFAULT_COOLING_FACTOR = 0.999999f; + inline constexpr float DEFAULT_MIN_COOLING = 40; + inline constexpr float DEFAULT_SPRING_LENGTH = 175.0; + inline constexpr float DEFAULT_INITIAL_TEMPERATURE = 100; + + inline constexpr auto DEFAULT_IMAGE = "parker_point"; + inline constexpr auto POINT_OUTLINE_COLOR = blt::make_color(0, 0.6, 0.6); + inline constexpr auto POINT_HIGHLIGHT_COLOR = blt::make_color(0, 1.0, 1.0); + inline constexpr auto POINT_SELECT_COLOR = blt::make_color(0, 0.9, 0.7); + + inline constexpr auto EDGE_COLOR = blt::make_color(0, 0.8, 0); + inline constexpr auto EDGE_OUTLINE_COLOR = blt::make_color(0, 1, 0); +} + +#endif //GRAPHS_CONFIG_H diff --git a/include/force_algorithms.h b/include/force_algorithms.h index 97e22bb..785129c 100644 --- a/include/force_algorithms.h +++ b/include/force_algorithms.h @@ -24,16 +24,16 @@ #include #include #include +#include class force_equation { public: using node_pair = const std::pair&; protected: - float cooling_rate = 0.999999; - float min_cooling = 40; - float ideal_spring_length = 175.0; - float initial_temperature = 100; + float cooling_rate = conf::DEFAULT_COOLING_FACTOR; + float min_cooling = conf::DEFAULT_MIN_COOLING; + float initial_temperature = conf::DEFAULT_INITIAL_TEMPERATURE; struct equation_data { @@ -53,7 +53,7 @@ class force_equation public: - [[nodiscard]] virtual blt::vec2 attr(node_pair v1, node_pair v2) const = 0; + [[nodiscard]] virtual blt::vec2 attr(node_pair v1, node_pair v2, const edge& edge) const = 0; [[nodiscard]] virtual blt::vec2 rep(node_pair v1, node_pair v2) const = 0; @@ -75,10 +75,9 @@ class force_equation class Eades_equation : public force_equation { protected: - float repulsive_constant = 24.0; float spring_constant = 12.0; public: - [[nodiscard]] blt::vec2 attr(node_pair v1, node_pair v2) const final; + [[nodiscard]] blt::vec2 attr(node_pair v1, node_pair v2, const edge& edge) const final; [[nodiscard]] blt::vec2 rep(node_pair v1, node_pair v2) const final; @@ -93,7 +92,7 @@ class Eades_equation : public force_equation class Fruchterman_Reingold_equation : public force_equation { public: - [[nodiscard]] blt::vec2 attr(node_pair v1, node_pair v2) const final; + [[nodiscard]] blt::vec2 attr(node_pair v1, node_pair v2, const edge& edge) const final; [[nodiscard]] blt::vec2 rep(node_pair v1, node_pair v2) const final; diff --git a/include/graph.h b/include/graph.h index bda1be8..6d50303 100644 --- a/include/graph.h +++ b/include/graph.h @@ -19,10 +19,12 @@ #ifndef GRAPHS_GRAPH_H #define GRAPHS_GRAPH_H +#include #include #include #include #include +#include namespace im = ImGui; @@ -99,9 +101,12 @@ class graph_t connected_nodes[n2].insert(n1); } - [[nodiscard]] bool connected(blt::u64 e1, blt::u64 e2) const + [[nodiscard]] std::optional> connected(blt::u64 n1, blt::u64 n2) const { - return edges.contains({e1, e2}); + auto itr = edges.find(edge{n1, n2}); + if (itr == edges.end()) + return {}; + return *itr; } void render(); @@ -110,7 +115,7 @@ class graph_t { if (selected_node != -1) { - nodes[selected_node].setOutlineColor(color::POINT_OUTLINE_COLOR); + nodes[selected_node].outline_color = conf::POINT_OUTLINE_COLOR; easing.reset(); } selected_node = -1; @@ -215,7 +220,6 @@ class engine_t graph.process_mouse_drag(data.width, data.height); } - graph.render(); } }; diff --git a/include/graph_base.h b/include/graph_base.h index 91f4e21..6d2cd8b 100644 --- a/include/graph_base.h +++ b/include/graph_base.h @@ -22,71 +22,49 @@ #include #include #include -#include +#include - -class node +struct node { - private: - blt::gfx::point2d_t point; - float outline_scale = 1.25f; - blt::vec2 velocity; - blt::color4 outline_color = color::POINT_OUTLINE_COLOR; - public: - explicit node(const blt::gfx::point2d_t& point): point(point) - {} - - blt::vec2& getVelocityRef() - { - return velocity; - } - - blt::vec2& getPositionRef() - { - return point.pos; - } - - [[nodiscard]] const blt::vec2& getPosition() const - { - return point.pos; - } - - [[nodiscard]] auto& getRenderObj() const - { - return point; - } - - [[nodiscard]] float getOutlineScale() const - { - return outline_scale; - } - - void setOutlineScale(float outlineScale) - { - outline_scale = outlineScale; - } - - [[nodiscard]] const blt::color4& getOutlineColor() const - { - return outline_color; - } - - void setOutlineColor(const blt::color4& c) - { - outline_color = c; - } + float repulsiveness = 24.0f; + blt::gfx::point2d_t point; + float outline_scale = 1.25f; + blt::vec2 velocity; + blt::color4 outline_color = conf::POINT_OUTLINE_COLOR; + + explicit node(const blt::gfx::point2d_t& point): point(point) + {} + + blt::vec2& getVelocityRef() + { + return velocity; + } + + blt::vec2& getPositionRef() + { + return point.pos; + } + + [[nodiscard]] const blt::vec2& getPosition() const + { + return point.pos; + } + + [[nodiscard]] auto& getRenderObj() const + { + return point; + } }; -class edge +struct edge { - private: - blt::u64 i1, i2; + float ideal_spring_length = conf::DEFAULT_SPRING_LENGTH; float outline_scale = 2.0f; float thickness = 2.0f; - blt::color4 color = color::EDGE_COLOR; - blt::color4 outline_color = color::EDGE_OUTLINE_COLOR; - public: + blt::color4 color = conf::EDGE_COLOR; + blt::color4 outline_color = conf::EDGE_OUTLINE_COLOR; + edge(blt::u64 i1, blt::u64 i2): i1(i1), i2(i2) { BLT_ASSERT(i1 != i2 && "Indices cannot be equal!"); @@ -106,46 +84,10 @@ class edge { return i2; } - - [[nodiscard]] float getOutlineScale() const - { - return outline_scale; - } - - void setOutlineScale(float outlineScale) - { - outline_scale = outlineScale; - } - - [[nodiscard]] const blt::color4& getColor() const - { - return color; - } - - void setColor(const blt::color4& c) - { - color = c; - } - - [[nodiscard]] const blt::color4& getOutlineColor() const - { - return outline_color; - } - - void setOutlineColor(const blt::color4& outlineColor) - { - outline_color = outlineColor; - } - - [[nodiscard]] float getThickness() const - { - return thickness; - } - - void setThickness(float t) - { - thickness = t; - } + + private: + // we are trying to maintain this as an invariant. + blt::u64 i1, i2; }; struct edge_hash diff --git a/include/tokenizer.h b/include/tokenizer.h new file mode 100644 index 0000000..476e414 --- /dev/null +++ b/include/tokenizer.h @@ -0,0 +1,103 @@ +#pragma once +/* + * Copyright (C) 2024 Brett Terpstra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef GRAPHS_TOKENIZER_H +#define GRAPHS_TOKENIZER_H + +#include +#include + +namespace proc +{ + enum class token_e + { + SQUARE_OPEN, // [ + SQUARE_CLOSE, // ] + CURLY_OPEN, // { + CURLY_CLOSE, // } + DOUBLE_QUOTE, // " + SINGLE_QUOTE, // ' + SEMI, // ; + COLON, // : + COMMENT, // # or // + BLOCK_BEGIN, // /* or /** + BLOCK_CLOSE, // */ + STAR, // * + TEXT, // any text inside quotes + IDENT, // identifier + VALUE, // numeric value + EQUAL, // = + COMMA, // , + NEWLINE, // \n + }; + + struct token_t + { + // the type of this token + token_e token; + // position inside file + blt::size_t token_pos; + // all data associated with token. will contain all text if text or the token characters otherwise + std::string_view token_data; + }; + + /* + * Example format: + * + * // this is a comment! + * [[Textures]] + * parker.png + * silly.jpg; multiline.gif + * boi.bmp + * + * # so is this! + * [[Nodes]] + * jim: texture=parker.png, location=[0.0f, 10.0f]; + * parker: texture=parker.png + * brett + * + * // can't make the other kind but imagine it works + * [[Edges]] + * jim, parker; brett, parker + * brett, jim + * + * [[Descriptions]] + * brett: me silly + * parker: boyfriend <3 + * jim: parker's friend + */ + + class tokenizer + { + public: + explicit tokenizer(std::string_view str): data(str) + {} + + explicit tokenizer(std::string&& str): data(std::move(str)) + {} + + const std::vector& tokenize(); + + private: + std::string data; + blt::size_t current_pos = 0; + std::vector tokens; + }; +} + +#endif //GRAPHS_TOKENIZER_H diff --git a/lib/BLT-With-Graphics-Template b/lib/BLT-With-Graphics-Template index c9475af..bd9db11 160000 --- a/lib/BLT-With-Graphics-Template +++ b/lib/BLT-With-Graphics-Template @@ -1 +1 @@ -Subproject commit c9475afb2a37ce4126b5519b456f6e3ea4f9f978 +Subproject commit bd9db118274d5c0db22ec8e1237f3f3db5bbab8f diff --git a/src/force_algorithms.cpp b/src/force_algorithms.cpp index d2f02b7..ea4d995 100644 --- a/src/force_algorithms.cpp +++ b/src/force_algorithms.cpp @@ -15,6 +15,15 @@ * along with this program. If not, see . */ #include +#include + +/** + * Function for mixing between two points + */ +BLT_ATTRIB_NO_SIDE_EFFECTS inline float mix(const float v1, const float v2) +{ + return (v1 + v2) / 2.0f; +} /** * -------------------------------------------------------- @@ -37,9 +46,6 @@ force_equation::equation_data force_equation::calc_data(const std::pair& v1, const std::pair& v2) const +blt::vec2 Eades_equation::attr(const std::pair& v1, const std::pair& v2, const edge& edge) const { auto data = calc_data(v1, v2); - return (spring_constant * std::log(data.mag / ideal_spring_length) * data.unit) - rep(v1, v2); + return (spring_constant * std::log(data.mag / edge.ideal_spring_length) * data.unit) - rep(v1, v2); } blt::vec2 Eades_equation::rep(const std::pair& v1, const std::pair& v2) const { auto data = calc_data(v1, v2); // scaling factor included because of the scales this algorithm is working on (large viewport) - auto scale = (repulsive_constant * 10000) / data.mag_sq; + auto scale = (mix(v1.second.repulsiveness, v2.second.repulsiveness) * 10000) / data.mag_sq; return scale * data.unit_inv; } void Eades_equation::draw_inputs() { namespace im = ImGui; - im::InputFloat("Repulsive Constant", &repulsive_constant, 0.25, 10); im::InputFloat("Spring Constant", &spring_constant, 0.25, 10); } @@ -78,16 +83,17 @@ void Eades_equation::draw_inputs() * -------------------------------------------------------- */ -blt::vec2 Fruchterman_Reingold_equation::attr(const std::pair& v1, const std::pair& v2) const +blt::vec2 Fruchterman_Reingold_equation::attr(const std::pair& v1, const std::pair& v2, const edge& edge) const { auto data = calc_data(v1, v2); - float scale = data.mag_sq / ideal_spring_length; + float scale = data.mag_sq / edge.ideal_spring_length; return (scale * data.unit); } blt::vec2 Fruchterman_Reingold_equation::rep(const std::pair& v1, const std::pair& v2) const { auto data = calc_data(v1, v2); + const auto ideal_spring_length = conf::DEFAULT_SPRING_LENGTH; float scale = (ideal_spring_length * ideal_spring_length) / data.mag; return scale * data.unit_inv; } \ No newline at end of file diff --git a/src/graph.cpp b/src/graph.cpp index 1008e9c..dff5a0f 100644 --- a/src/graph.cpp +++ b/src/graph.cpp @@ -21,7 +21,6 @@ #include #include #include -#include extern blt::gfx::batch_renderer_2d renderer_2d; extern blt::gfx::matrix_state_manager global_matrices; @@ -44,8 +43,8 @@ void graph_t::render() { if (v1.first == v2.first) continue; - if (connected(v1.first, v2.first)) - attractive += equation->attr(v1, v2); + if (auto edge = connected(v1.first, v2.first)) + attractive += equation->attr(v1, v2, edge->get()); repulsive += equation->rep(v1, v2); } v1.second.getVelocityRef() = attractive + repulsive; @@ -63,7 +62,7 @@ void graph_t::render() } for (const auto& point : nodes) - renderer_2d.drawPointInternal(blt::gfx::render_info_t::make_info("parker_point", point.getOutlineColor(), point.getOutlineScale()), + renderer_2d.drawPointInternal(blt::gfx::render_info_t::make_info(conf::DEFAULT_IMAGE), point.getRenderObj(), 15.0f); for (const auto& edge : edges) { @@ -74,8 +73,8 @@ void graph_t::render() { auto n1 = nodes[edge.getFirst()]; auto n2 = nodes[edge.getSecond()]; - auto draw_info = blt::gfx::render_info_t::make_info(edge.getColor(), edge.getOutlineColor(), edge.getOutlineScale()); - renderer_2d.drawLine(draw_info, 5.0f, n1.getRenderObj().pos, n2.getRenderObj().pos, edge.getThickness()); + auto draw_info = blt::gfx::render_info_t::make_info(edge.color); + renderer_2d.drawLine(draw_info, 5.0f, n1.getRenderObj().pos, n2.getRenderObj().pos, edge.thickness); } } } @@ -105,7 +104,7 @@ void graph_t::process_mouse_drag(const blt::i32 width, const blt::i32 height) if (new_selection != selected_node) { if (selected_node != -1) - nodes[selected_node].setOutlineColor(color::POINT_OUTLINE_COLOR); + nodes[selected_node].outline_color = conf::POINT_OUTLINE_COLOR; } if (mouse_pressed && new_selection == -1 && selected_node != -1) @@ -124,7 +123,7 @@ void graph_t::process_mouse_drag(const blt::i32 width, const blt::i32 height) { auto& node = nodes[selected_node]; easing.progress(8 * static_cast(blt::gfx::getFrameDeltaSeconds())); - node.setOutlineColor(color::POINT_SELECT_COLOR); + node.outline_color = conf::POINT_SELECT_COLOR; node.getPositionRef() = mouse_pos; } } diff --git a/include/color_constants.h b/src/tokenizer.cpp similarity index 53% rename from include/color_constants.h rename to src/tokenizer.cpp index 1d00ab0..e8950da 100644 --- a/include/color_constants.h +++ b/src/tokenizer.cpp @@ -1,5 +1,5 @@ -#pragma once /* + * * Copyright (C) 2024 Brett Terpstra * * This program is free software: you can redistribute it and/or modify @@ -15,20 +15,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +#include -#ifndef GRAPHS_COLOR_CONSTANTS_H -#define GRAPHS_COLOR_CONSTANTS_H - -#include - -namespace color +const std::vector& proc::tokenizer::tokenize() { - static inline constexpr blt::color4 POINT_OUTLINE_COLOR = blt::make_color(0, 0.6, 0.6); - static inline constexpr blt::color4 POINT_HIGHLIGHT_COLOR = blt::make_color(0, 1.0, 1.0); - static inline constexpr blt::color4 POINT_SELECT_COLOR = blt::make_color(0, 0.9, 0.7); - - static inline constexpr blt::color4 EDGE_COLOR = blt::make_color(0, 0.8, 0); - static inline constexpr blt::color4 EDGE_OUTLINE_COLOR = blt::make_color(0, 1, 0); -} -#endif //GRAPHS_COLOR_CONSTANTS_H +}