Compare commits

...

7 Commits

Author SHA1 Message Date
29230f4d07 Timing 2026-02-16 19:35:41 +01:00
6ff4a66551 Fix small mistake 2026-02-04 14:23:27 +01:00
45f73c721e Add savaToFile option 2026-02-04 13:18:54 +01:00
e99bd33985 update slike.cpp 2026-02-04 12:38:14 +01:00
40b2f963a6 save old data 2026-02-03 15:39:19 +01:00
cc00586bc9 add random/slike 2026-02-03 15:39:01 +01:00
d7ea0b99ac Add similarity and experimental drawBranch 2026-02-03 15:37:49 +01:00
21 changed files with 661 additions and 323 deletions

View File

@@ -8,7 +8,11 @@ set(CMAKE_CXX_STANDARD_REQUIRED True)
# set(CMAKE_VERBOSE_MAKEFILE ON)
add_compile_options(-ggdb)
include_directories(external/include/)
include_directories(
external/include
shared/inc
)
link_libraries(
${CMAKE_SOURCE_DIR}/external/libimgui.a
${CMAKE_SOURCE_DIR}/external/libraylib.a
@@ -18,50 +22,46 @@ link_libraries(
m
)
add_library(shared STATIC
shared/src/canvas/BackGround.cpp
shared/src/canvas/BackGroundColors.cpp
shared/src/canvas/Canvas.cpp
shared/src/canvas/Tree.cpp
shared/src/values/Dna.cpp
shared/src/values/DnaManager.cpp
shared/src/values/mrand.cpp
shared/src/values/Similarity.cpp
shared/src/TcpSocket.cpp
shared/src/sql.cpp
shared/src/timing.cpp
)
add_executable(app
app/src/main.cpp
app/src/App.cpp
app/src/DnaStore.cpp
app/src/sys.cpp
shared/src/canvas/BackGround.cpp
shared/src/canvas/BackGroundColors.cpp
shared/src/canvas/Canvas.cpp
shared/src/canvas/Tree.cpp
shared/src/values/Dna.cpp
shared/src/values/DnaManager.cpp
shared/src/values/mrand.cpp
shared/src/values/Similarity.cpp
shared/src/TcpSocket.cpp
)
# Add include directories
target_include_directories(app PRIVATE app/inc shared/inc )
target_include_directories(app PRIVATE app/inc)
target_link_libraries(app PRIVATE shared)
add_executable(server
server/src/server.cpp
server/src/checker.cpp
# add_executable(server
# server/src/server.cpp
# server/src/checker.cpp
# )
# target_include_directories(server PRIVATE server/inc)
# target_link_libraries(server PRIVATE shared)
shared/src/sql.cpp
shared/src/TcpSocket.cpp
shared/src/values/Dna.cpp
shared/src/values/DnaManager.cpp
shared/src/values/mrand.cpp
)
# Add include directories
target_include_directories(server PRIVATE server/inc shared/inc)
# add_executable(view
# view/src/main.cpp
# view/src/Vapp.cpp
# )
# target_include_directories(view PRIVATE view/inc)
# target_link_libraries(view PRIVATE shared)
add_executable(view
view/src/main.cpp
view/src/Vapp.cpp
shared/src/canvas/BackGround.cpp
shared/src/canvas/BackGroundColors.cpp
shared/src/canvas/Canvas.cpp
shared/src/canvas/Tree.cpp
shared/src/values/Dna.cpp
shared/src/values/DnaManager.cpp
shared/src/values/mrand.cpp
shared/src/values/Similarity.cpp
shared/src/sql.cpp
)
# Add include directories
target_include_directories(view PRIVATE view/inc shared/inc)
# add_executable(slike
# random/slike.cpp
# )
# target_link_libraries(slike PRIVATE shared)
file(COPY CascadiaCode.ttf DESTINATION "res")

BIN
CascadiaCode.ttf Normal file

Binary file not shown.

View File

@@ -18,30 +18,14 @@ private:
int screenWidth, screenHeight;
Canvas canvas;
int pos = 0;
std::array<RenderTexture2D, 2> canvasTexure = {0};
RenderTexture2D canvasTexure = {0};
float rotation = 0.0f;
Vector2 mouseStart;
bool validHit = false;
float len;
float ofset;
Liked topLiked = Liked::tbd;
Rectangle destA;
Rectangle destB;
Rectangle likeBox;
Rectangle disLikeBox;
std::array<UiUnit, 2> unit = {0};
UiUnit unit = {0};
DnaManagerData manager;
Rectangle likedTextBox;
Rectangle genTextBox;
Rectangle simTextBox;
float simil = 100.0f;
Color appColor = BLUE;
};

View File

@@ -2,241 +2,118 @@
#include <cmath>
#include "App.hpp"
#include "timing.hpp"
#include <raylib.h>
#include <raymath.h>
#define TOP (1 - pos)
#define BOTTOM pos
Font fontTtf;
Rectangle TextInSpace(Rectangle box, float textH, float textW, float margin, bool topOrBottom, bool leftOrRigth)
void DrawTextB(const char *text, float posX, float posY, int fontSize, Color color)
{
float br = box.width / box.height;
float tr = textW / textH;
Rectangle ret = {0, 0, 0, 0};
float hm = box.height * margin;
float wm = box.width * margin;
ret.height = box.height - hm;
ret.width = box.width - wm;
if (br < tr)
{
// bolj kvadrat izracunaj visino iz sirine
ret.height = ret.width / tr;
}
else
{
// bolj podolgovat izracunaj sirino iz visine
ret.width = ret.height * tr;
}
if (topOrBottom)
{
ret.y = box.y + hm;
}
else
{
ret.y = box.y + box.height - hm - ret.height;
}
if (leftOrRigth)
{
ret.x = box.x + wm;
}
else
{
ret.x = box.x + box.width - wm - ret.width;
}
return ret;
DrawTextEx(fontTtf, text, (Vector2){ posX, posY }, fontSize, 1, color);
}
// Dimentions for font size 20
// DISLIKE 83
// LIKE 46
// GEN 9999: 999/999 -> 200
constexpr float textMargin = 0.02f;
void App::init(int screenWidth, int screenHeight)
{
fontTtf = LoadFontEx("res/CascadiaCode.ttf", 32, 0, 0);
SetTextLineSpacing(16);
this->screenWidth = screenWidth;
this->screenHeight = screenHeight;
this->canvas.init(screenWidth);
// int s = MeasureText("GEN 9999: 999/999", 20);
// TraceLog(LOG_INFO, "%d", s);
for (size_t i = 0; i < canvasTexure.size(); i++)
{
canvasTexure[i] = LoadRenderTexture(screenWidth, screenWidth);
}
canvasTexure = LoadRenderTexture(screenWidth, screenWidth);
DnaStore::load(&manager);
simil = Similarity::calc_similarity(manager.vector);
upTex(Liked::tbd);
while (!canvas.tick(canvasTexure[TOP]))
while (!canvas.tick(canvasTexure))
{
// wait to finish drawing
}
pos = 1 - pos;
upTex(Liked::tbd);
while (!canvas.tick(canvasTexure[TOP]))
{
// wait to finish drawing
}
pos = 1 - pos;
float posY = (screenHeight - screenWidth) / 2.0f;
likedTextBox = TextInSpace({0,
0,
(float)screenWidth / 2.0f,
posY},
20.0f, 83.0f, textMargin, false, true);
genTextBox = TextInSpace({0,
posY + screenWidth,
(float)screenWidth,
posY},
20.0f, 200.0f, textMargin, true, true);
simTextBox = TextInSpace({(float)screenWidth / 2.0f,
likedTextBox.y,
(float)screenWidth / 2.0f,
likedTextBox.height},
20.0f, 60.0f, textMargin, false, false);
destB = {0, posY, (float)screenWidth, (float)screenWidth};
destA = destB;
float recPosX = screenWidth * 0.3f;
disLikeBox = {0, posY, (float)recPosX, (float)screenWidth};
likeBox = {screenWidth - recPosX, posY, (float)recPosX, (float)screenWidth};
if(!DnaStore::ping()){
appColor = RED;
}
destA = {0, posY, (float)screenWidth, (float)screenWidth};
}
void App::upTex(Liked liked)
{
if (liked != Liked::tbd)
{
unit[TOP].liked = liked;
bool ng = DnaManager::like(unit[TOP], &manager);
unit.liked = liked;
bool ng = DnaManager::like(unit, &manager);
if (ng)
{
DnaStore::saveGen(&manager);
DnaManager::newGen(&manager);
DnaStore::saveVec(&manager);
simil = Similarity::calc_similarity(manager.vector);
}
DnaStore::saveData(&manager);
}
unit[TOP] = DnaManager::next(&manager);
if (unit[TOP].dna != nullptr)
unit = DnaManager::next(&manager);
if (unit.dna != nullptr)
{
canvas.newGen(canvasTexure[TOP], unit[TOP].dna);
canvas.newGen(canvasTexure, unit.dna);
return;
}
BeginTextureMode(canvasTexure[TOP]);
BeginTextureMode(canvasTexure);
ClearBackground(BLACK);
DrawText("NEXT GEN", 10, 10, screenWidth/10, WHITE);
EndTextureMode();
}
void App::update()
{
bool isDone = canvas.tick(canvasTexure[BOTTOM]);
Vector2 mousePosition = GetMousePosition();
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
{
mouseStart = mousePosition;
validHit = CheckCollisionPointRec(mouseStart, destA);
len = Vector2Distance(mouseStart, {destB.x, destB.y});
ofset = std::atan2(destB.x - mouseStart.x, destB.y - mouseStart.y);
}
void App::update(){}
if (IsMouseButtonDown(MOUSE_BUTTON_LEFT) && validHit)
{
float dist = mousePosition.x - mouseStart.x;
float l = dist / screenWidth;
rotation = Lerp(45.0f, -45.0f, (l + 1) / 2);
enum class Rend_type{
every_frame,
in_one_frame,
over_frames,
};
float angle = ((rotation)*PI) / 180.0f;
angle += ofset;
Vector2 newCenter = {.x = len * std::sin(angle), .y = len * std::cos(angle)};
destA.x = newCenter.x + mousePosition.x;
destA.y = newCenter.y + mousePosition.y;
if (CheckCollisionPointRec(mousePosition, disLikeBox))
{
topLiked = Liked::no;
}
else if (CheckCollisionPointRec(mousePosition, likeBox))
{
topLiked = Liked::yes;
}
else
{
topLiked = Liked::tbd;
}
}
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT) && validHit)
{
if (isDone)
{
if (topLiked != Liked::tbd)
{
upTex(topLiked);
pos = 1 - pos; // switch bottom and top
}
}
rotation = 0.0f;
destA = destB;
topLiked = Liked::tbd;
}
}
constexpr Rend_type rend_type = Rend_type::over_frames;
void App::draw()
{
ClearBackground(appColor);
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT))
{
TraceLog(LOG_INFO, "CLICK");
upTex(Liked::yes);
if constexpr (rend_type == Rend_type::in_one_frame){
while (!canvas.tick(canvasTexure))
{
// wait to finish drawing
}
}
}
if constexpr (rend_type == Rend_type::over_frames){
canvas.tick(canvasTexure);
}
ClearBackground(BLUE);
int fps = GetFPS();
const char* fpstext = TextFormat("%04d FPS", fps);
DrawTextB(fpstext, 10, 10, 36, BLACK);
const char* ctext = TextFormat("%04ld Circles", canvas.tree.circles);
DrawTextB(ctext, 10, 50, 36, BLACK);
Rectangle source = {0, 0, (float)screenWidth, (float)-screenWidth};
Vector2 origin = {0.0f, 0.0f};
DrawTexturePro(canvasTexure[BOTTOM].texture, source, destB, origin, 0.0f, WHITE);
DrawTexturePro(canvasTexure[TOP].texture, source, destA, origin, 360 - rotation, WHITE);
const char *textGen = TextFormat("GEN %d: %d / %d", manager.generation, unit[TOP].index + 1, NUM_PER_GEN);
DrawText(textGen, genTextBox.x, genTextBox.y, genTextBox.height, BLACK);
const char *textProc = TextFormat("%.1f%%", simil);
DrawText(textProc, simTextBox.x, simTextBox.y, simTextBox.height, BLACK);
switch (topLiked)
{
case Liked::yes:
DrawText("LIKED", likedTextBox.x, likedTextBox.y, likedTextBox.height, BLACK);
break;
case Liked::no:
DrawText("DISLIKE", likedTextBox.x, likedTextBox.y, likedTextBox.height, BLACK);
break;
default:
break;
if constexpr (rend_type == Rend_type::every_frame){
canvas.newGen(canvasTexure, unit.dna);
while (!canvas.tick(canvasTexure))
{
// wait to finish drawing
}
}
DrawTexturePro(canvasTexure.texture, source, destA, origin, 360, WHITE);
}
void App::deinit()
{
for (size_t i = 0; i < canvasTexure.size(); i++)
{
UnloadRenderTexture(canvasTexure[i]);
}
UnloadRenderTexture(canvasTexure);
UnloadFont(fontTtf);
canvas.deinit();
}

View File

@@ -16,7 +16,7 @@
#define DATA_FILE_NAME "DATA.bin"
#define VECTOR_FILE_NAME "VECTOR.bin"
#define GEN_FILE_PATTRN "gen/%04d.bin"
#define HOST_NAME "petrovv.com"
#define HOST_NAME "localhost"
void DnaStore::load(DnaManagerData *data)
{

View File

@@ -1,5 +1,6 @@
#include <raylib.h>
#include "App.hpp"
#include "timing.hpp"
#if defined(PLATFORM_WEB)
#include <emscripten/emscripten.h>
@@ -7,12 +8,14 @@
static App app;
Timer t;
void UpdateDrawFrame()
{
app.update();
t.reset_and_start();
BeginDrawing();
app.draw();
EndDrawing();
t.stop_and_print("to draw frame");
}
int main(void)
@@ -34,7 +37,7 @@ int main(void)
#if defined(PLATFORM_WEB)
emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
#else
SetTargetFPS(60);
// SetTargetFPS(60);
while (!WindowShouldClose())
{
UpdateDrawFrame();

BIN
data.db Normal file

Binary file not shown.

View File

@@ -121,7 +121,7 @@ bool try_remove(std::filesystem::path path)
{
try
{
std::filesystem::remove("old_build");
std::filesystem::remove(path);
return true;
}
catch (const std::exception &e)

147
random/slike.cpp Normal file
View File

@@ -0,0 +1,147 @@
#include <raylib.h>
#include <raymath.h>
#include <cmath>
#include <vector>
Vector2 newPoint(Vector2 start, float len, float angleD){
float angleR = (angleD * PI) / 180; // radian
return {start.x + len * cos(angleR), start.y - len * sin(angleR)};
}
void drawBranch(Vector2 startV, Vector2 endV, Color startC, Color endC, int startR, int endR){
float fstep = 0.05;
for (float i = 0; i < 1.05; i += fstep)
{
Vector2 point = Vector2Lerp(startV, endV, i);
Color color = ColorLerp(startC, endC, i);
int size = Lerp(startR, endR, i);
DrawCircleV(point, size, color);
}
}
constexpr float screenWidth = 800;
constexpr float screenHeight = 800;
constexpr float len = 300;
constexpr float angleD = 100;
constexpr Vector2 start = {screenWidth / 2, screenHeight - 100};
constexpr float radius = 20;
constexpr float radiusS = 80;
constexpr float radiusE = 60;
constexpr Color colorS = RED;
constexpr Color colorE = GREEN;
typedef void (*slika)();
int idx = 0;
std::vector<slika> v_slik = {
[]()
{
DrawCircleV(start, radius, BLACK);
},
[]()
{
Vector2 end = {start.x, start.y - len};
DrawCircleV(start, radius, BLACK);
DrawLineEx(start, end, 10, BLACK);
},
[]()
{
Vector2 end = newPoint(start, len, angleD);
DrawCircleV(start, radius, BLACK);
DrawLineEx(start, end, 10, BLACK);
DrawCircleV(end, radius, BLACK);
DrawCircleSectorLines(start, len / 3, 360 - angleD, 360, 30, BLACK);
},
[]()
{
Vector2 end = newPoint(start, len, angleD);
DrawCircleV(start, radius, BLACK);
DrawLineEx(start, end, 10, BLACK);
DrawCircleV(end, radius, BLACK);
DrawCircleLinesV(start, radiusS, BLACK);
DrawCircleLinesV(end, radiusE, BLACK);
},
[]()
{
Vector2 end = newPoint(start, len, angleD);
DrawLineEx(start, end, 10, BLACK);
DrawCircleV(start, radiusS, colorS);
DrawCircleV(end, radiusE, colorE);
},
[]()
{
Vector2 end = newPoint(start, len, angleD);
drawBranch(start, end, colorS, colorE, radiusS, radiusE);
},
[]()
{
Vector2 p = newPoint(start, len, angleD);
drawBranch(start, p, colorS, colorE, radiusS, radiusE);
Vector2 p1 = newPoint(p, len, 135);
Vector2 p2 = newPoint(p, len, 90);
Vector2 p3 = newPoint(p, len, 45);
DrawLineEx(p, p1, 10, BLACK);
DrawLineEx(p, p2, 10, BLACK);
DrawLineEx(p, p3, 10, BLACK);
DrawCircleV(p, radius, BLACK);
DrawCircleV(p1, radius, BLACK);
DrawCircleV(p2, radius, BLACK);
DrawCircleV(p3, radius, BLACK);
},
[]()
{
Vector2 p = newPoint(start, len, angleD);
drawBranch(start, p, colorS, colorE, radiusS, radiusE);
Vector2 p1 = newPoint(p, len, 135);
Vector2 p2 = newPoint(p, len, 90);
Vector2 p3 = newPoint(p, len, 45);
drawBranch(p, p1, colorE, BLUE, radiusE, 50);
drawBranch(p, p2, colorE, ORANGE, radiusE, 50);
drawBranch(p, p3, colorE, PURPLE, radiusE, 50);
},
};
int main(int argc, char *argv[])
{
InitWindow(screenWidth, screenHeight, "Slike");
SetTargetFPS(60);
while (!WindowShouldClose())
{
BeginDrawing();
if (IsKeyPressed(KEY_S))
{
TakeScreenshot(TextFormat("slika%.2d.png", idx));
}
if (IsKeyPressed(KEY_N))
{
idx++;
if (idx >= v_slik.size())
idx = v_slik.size() - 1;
}
if (IsKeyPressed(KEY_P))
{
idx--;
if (idx < 0)
idx = 0;
}
ClearBackground(WHITE);
v_slik[idx]();
EndDrawing();
}
CloseWindow();
return 0;
}

View File

@@ -13,7 +13,6 @@ public:
void newGen(RenderTexture2D &target, Dna *dna);
bool tick(RenderTexture2D &target);
private:
BackGround backGround;
Tree tree;
};

View File

@@ -23,6 +23,7 @@ public:
void init(int size);
void draw(Dna *dna);
bool tick();
uint64_t circles;
private:
Dna *m_dna;
@@ -32,8 +33,10 @@ private:
Vector2 start = {0};
std::list<DrawArgs> drawCalls;
void drawBranch();
void calculateBranch();
void drawBranch_rlTriangle(Vector2 startPoint, Vector2 endPoint, Color startColor, Color endColor, float startThickness, float endThickness, float length);
void drawBranch_circles(Vector2 startPoint, Vector2 endPoint, Color startColor, Color endColor, float startThickness, float endThickness, float length);
inline size_t getNumOfBranches(int dep);
inline Color getStartColor(DrawArgs &arg);
inline Color getEndColor(int dep, Color &start);

18
shared/inc/timing.hpp Normal file
View File

@@ -0,0 +1,18 @@
#include <chrono>
struct Timer
{
std::chrono::steady_clock::time_point start_t;
std::chrono::steady_clock::time_point end_t;
std::chrono::nanoseconds dur;
void start();
void stop();
void reset();
void print(const char * str);
void stop_and_print(const char * str);
void reset_and_start();
};

View File

@@ -3,14 +3,14 @@
namespace Similarity
{
// float euclidean_distance(Dna *d1, Dna *d2); direct distance betwen vector. wont give 0 and 1
// float dot_product(Dna *d1, Dna *d2); doent return betwen 0 to 1
// float cosine_similarity(Dna *d1, Dna *d2);
// float cosine_similarity_int(Dna *d1, Dna *d2);
float euclidean_distance(Dna *d1, Dna *d2);// direct distance betwen vector. wont give 0 and 1
float dot_minmax(Dna *d1, Dna *d2); // doent return betwen 0 to 1
float cosine_similarity(Dna *d1, Dna *d2);
float cosine_similarity_int(Dna *d1, Dna *d2);
float hamming_distance(Dna *d1, Dna *d2);
float hamming_distance_without_seeds(Dna *d1, Dna *d2);
// float jaccard_index(Dna *d1, Dna *d2); // primerja unio genov naprimer gleda ce je gen za nebo isti z genom za barvo za liste, to nerabimo
// float levenshtein_distance(Dna *d1, Dna *d2); // odstranjen ker mi vrne iste podatke kot hamming distance ki je bolj enostaven za izracun
float levenshtein_distance(Dna *d1, Dna *d2); // odstranjen ker mi vrne iste podatke kot hamming distance ki je bolj enostaven za izracun
// float needleman_wunsch(Dna *d1, Dna *d2); used for bioinformatics and aligment. Dont need its aligned alredy
typedef float(simil_func)(Dna *d1, Dna *d2);

View File

@@ -1,4 +1,5 @@
#include <cmath>
#include <algorithm>
#include "canvas/BackGround.hpp"
#include "canvas/BackGroundColors.hpp"

View File

@@ -1,4 +1,5 @@
#include "canvas/Canvas.hpp"
#include "timing.hpp"
void Canvas::init(int size)
{
@@ -6,8 +7,13 @@ void Canvas::init(int size)
tree.init(size);
}
bool finished = false;
Timer timer;
void Canvas::newGen(RenderTexture2D &target, Dna *dna)
{
finished = false;
timer.reset_and_start();
BeginTextureMode(target);
ClearBackground(WHITE);
@@ -15,13 +21,20 @@ void Canvas::newGen(RenderTexture2D &target, Dna *dna)
tree.draw(dna);
EndTextureMode();
timer.stop();
}
bool Canvas::tick(RenderTexture2D &target)
{
timer.start();
BeginTextureMode(target);
bool ret = tree.tick();
EndTextureMode();
timer.stop();
if(ret && !finished){
finished = true;
timer.print("to draw canvas");
}
return ret;
}

View File

@@ -1,11 +1,13 @@
#include <cmath>
#include "canvas/Tree.hpp"
#include "timing.hpp"
#include <raylib.h>
#include <raymath.h>
#include <rlgl.h>
#define ITER_PER_FRAME 5000
#define ITER_PER_FRAME 10000
constexpr int maxColorChange = 15;
constexpr int minColorChange = -15;
@@ -40,27 +42,28 @@ void Tree::init(int size)
start.x = size / 2;
start.y = size;
calculateLevels(size);
//texBunny = LoadTexture("dot.png"); // bug add deinit to unload texutre
// texBunny = LoadTexture("dot.png"); // bug add deinit to unload texutre
}
void Tree::draw(Dna *dna)
{
circles = 0;
m_dna = dna;
branchSeed = dna->branchSeed;
drawCalls.push_back({start, 180.0f, 0});
tick();
}
bool Tree::tick()
{
size_t i = 0;
while (!drawCalls.empty())
using namespace std::chrono;
auto start = steady_clock::now();
nanoseconds dur = 0us;
while (!drawCalls.empty() && dur < 14ms)
{
drawBranch();
calculateBranch();
drawCalls.pop_front();
i++;
if (i >= ITER_PER_FRAME)
break;
auto end = steady_clock::now();
dur = end - start;
}
return drawCalls.empty();
@@ -68,7 +71,7 @@ bool Tree::tick()
// Private
void Tree::drawBranch()
void Tree::calculateBranch()
{
DrawArgs arg = drawCalls.front();
if (arg.dep == MAX_DEPTH)
@@ -82,23 +85,13 @@ void Tree::drawBranch()
int sizeStart = getStartSize(arg);
int sizeEnd = getEndSize(arg, sizeStart);
float fstep = 1.0 / ((length / sizeStart) * 2.0f);
Color colorStart = getStartColor(arg);
Color colorEnd = getEndColor(arg.dep, colorStart);
for (float i = 0; i < 1; i += fstep)
{
Vector2 point = Vector2Lerp(arg.start, end, i);
Color color = ColorLerp(colorStart, colorEnd, i);
int size = Lerp(sizeStart, sizeEnd, i);
DrawCircleV(point, size, color);
//DrawTextureEx(texBunny, point,0, ((float)size) / texBunny.height, color);
// use
// DrawRectangleGradientEx
}
// drawBranch_rlTriangle(arg.start, end, colorStart, colorEnd, sizeStart, sizeEnd, length);
drawBranch_circles(arg.start, end, colorStart, colorEnd, sizeStart, sizeEnd, length);
// DrawLineEx(arg.start, end, sizeStart, colorStart);
// add more branches to draw
if (arg.dep + 1 >= MAX_DEPTH)
@@ -116,6 +109,7 @@ void Tree::drawBranch()
inline size_t Tree::getNumOfBranches(int dep)
{
return 3;
if (m_dna->branches[dep].branchCount < 128)
return 2;
else
@@ -165,7 +159,7 @@ inline int Tree::getStartSize(DrawArgs &arg)
float mixLevel = m_dna->branches[arg.dep].sizeLevel / 255.0f;
size = std::lerp(size, sizes[MAX_DEPTH - arg.dep - 1], mixLevel);
if (size < 1)
//if (size < 1)
size = 1;
return size;
}
@@ -175,7 +169,7 @@ inline int Tree::getEndSize(DrawArgs &arg, int start)
int size = Remap(m_dna->branches[arg.dep].sizeChange, 0, 255, MinSizeChange, maxSizeChange);
size += start;
if (size < 1)
//if (size < 1)
size = 1;
return size;
}
@@ -183,9 +177,9 @@ inline int Tree::getEndSize(DrawArgs &arg, int start)
inline float Tree::getLength(DrawArgs &arg)
{
float lenght = lengths[arg.dep];
float lenghtRatio = Remap(m_dna->branches[arg.dep].length, 0, 255, 0.5f, 1.3f);
float lenghtRatio = Remap(255, 0, 255, 0.5f, 1.3f);
lenght *= lenghtRatio;
float lenghtVar = Remap(m_dna->branches[arg.dep].lengthVar, 0, 255, -0.15f, 0.15f);
float lenghtVar = Remap(255, 0, 255, -0.15f, 0.15f);
lenght += lenght * lenghtVar * mrand::getFloat(&branchSeed);
if (lenght < 1)
lenght = 1;
@@ -200,3 +194,64 @@ inline float Tree::getAngleVar(DrawArgs &arg)
return angleVar;
}
void Tree::drawBranch_circles(Vector2 startPoint, Vector2 endPoint, Color startColor, Color endColor, float startThickness, float endThickness, float length)
{
float fstep = 1.0 / ((length / startThickness) * 2.0f);
for (float i = 0; i < 1; i += fstep)
{
Vector2 point = Vector2Lerp(startPoint, endPoint, i);
Color color = ColorLerp(startColor, endColor, i);
int size = Lerp(startThickness, endThickness, i);
DrawCircleV(point, size, color);
circles++;
}
}
void Tree::drawBranch_rlTriangle(Vector2 startPoint, Vector2 endPoint, Color startColor, Color endColor, float startThickness, float endThickness, float length)
{
DrawCircleV(startPoint, startThickness, startColor);
DrawCircleV(endPoint, endThickness, endColor);
// Calculate the direction vector from startPoint to endPoint
Vector2 direction = {endPoint.x - startPoint.x, endPoint.y - startPoint.y};
// Normalize the direction vector
Vector2 normalizedDir = {direction.x / length, direction.y / length};
// Calculate the perpendicular vector (rotate 90 degrees)
Vector2 perpendicular = {-normalizedDir.y, normalizedDir.x};
// Calculate the four vertices of the quadrilateral
Vector2 topLeft = {
startPoint.x + perpendicular.x * startThickness,
startPoint.y + perpendicular.y * startThickness};
Vector2 topRight = {
endPoint.x + perpendicular.x * endThickness,
endPoint.y + perpendicular.y * endThickness};
Vector2 bottomLeft = {
startPoint.x - perpendicular.x * startThickness,
startPoint.y - perpendicular.y * startThickness};
Vector2 bottomRight = {
endPoint.x - perpendicular.x * endThickness,
endPoint.y - perpendicular.y * endThickness};
// Draw the two triangles to form the quadrilateral
rlBegin(RL_TRIANGLES);
// First triangle
rlColor4ub(startColor.r, startColor.g, startColor.b, startColor.a);
rlVertex2f(topLeft.x, topLeft.y);
rlColor4ub(endColor.r, endColor.g, endColor.b, endColor.a);
rlVertex2f(topRight.x, topRight.y);
rlColor4ub(startColor.r, startColor.g, startColor.b, startColor.a);
rlVertex2f(bottomLeft.x, bottomLeft.y);
// Second triangle
rlColor4ub(startColor.r, startColor.g, startColor.b, startColor.a);
rlVertex2f(bottomLeft.x, bottomLeft.y);
rlColor4ub(endColor.r, endColor.g, endColor.b, endColor.a);
rlVertex2f(topRight.x, topRight.y);
rlColor4ub(endColor.r, endColor.g, endColor.b, endColor.a);
rlVertex2f(bottomRight.x, bottomRight.y);
rlEnd();
}

42
shared/src/timing.cpp Normal file
View File

@@ -0,0 +1,42 @@
#include <raylib.h>
#include <chrono>
#include "timing.hpp"
using namespace std::chrono;
void Timer::start()
{
start_t = std::chrono::steady_clock::now();
}
void Timer::stop()
{
end_t = std::chrono::steady_clock::now();
dur += end_t - start_t;
}
void Timer::reset()
{
dur = 0ns;
}
void Timer::print(const char * str)
{
auto s = std::chrono::duration_cast<std::chrono::milliseconds>(dur);
if (s > 1000us)
{
TraceLog(LOG_INFO, "%ld ms %s", s.count(), str);
}
}
void Timer::stop_and_print(const char *str)
{
stop();
print(str);
}
void Timer::reset_and_start()
{
reset();
start();
}

View File

@@ -1,56 +1,88 @@
#include "values/Similarity.hpp"
#include <cmath>
#include <algorithm>
#include <numeric>
#include <raylib.h>
#include <chrono>
namespace Similarity
{
float dot_minmax(Dna *d1, Dna *d2)
{
uint64_t max = sizeof(Dna) * 255 * 255;
uint8_t *a = (uint8_t *)d1;
uint8_t *b = (uint8_t *)d2;
uint32_t result = 0;
for (size_t i = 0; i < sizeof(Dna); ++i)
{
result += static_cast<uint32_t>(a[i]) * static_cast<uint32_t>(b[i]);
}
return result / (double)max;
}
float euclidean_distance(Dna *d1, Dna *d2)
{
uint8_t *a = (uint8_t *)d1;
uint8_t *b = (uint8_t *)d2;
float sum = 0.0f;
for (size_t i = 0; i < sizeof(Dna); ++i)
{
float diff = static_cast<float>(a[i]) - static_cast<float>(b[i]);
sum += diff * diff;
}
float distance = std::sqrt(sum);
float max_distance = 255.0f * std::sqrt(static_cast<float>(sizeof(Dna)));
return 1 - (distance / max_distance);
}
// todo: use int8_t insted of uint8_t and map data
// 0 -> -128
// 255 -> 127
// int8_t = uint8_t - 128
// float cosine_similarity(Dna *d1, Dna *d2)
// {
// uint8_t *d1a = (uint8_t *)d1;
// uint8_t *d2a = (uint8_t *)d2;
float cosine_similarity(Dna *d1, Dna *d2)
{
uint8_t *d1a = (uint8_t *)d1;
uint8_t *d2a = (uint8_t *)d2;
// float mag1 = 0.0f;
// float mag2 = 0.0f;
// float dot_prod = 0.0f;
// for (size_t i = 0; i < sizeof(Dna); i++)
// {
// dot_prod += d1a[i] * d2a[i];
// mag1 += d1a[i] * d1a[i];
// mag2 += d2a[i] * d2a[i];
// }
// mag1 = sqrt(mag1);
// mag2 = sqrt(mag2);
float mag1 = 0.0f;
float mag2 = 0.0f;
float dot_prod = 0.0f;
for (size_t i = 0; i < sizeof(Dna); i++)
{
dot_prod += d1a[i] * d2a[i];
mag1 += d1a[i] * d1a[i];
mag2 += d2a[i] * d2a[i];
}
mag1 = sqrt(mag1);
mag2 = sqrt(mag2);
// return dot_prod / (mag1 * mag2);
// }
return dot_prod / (mag1 * mag2);
}
// float cosine_similarity_int(Dna *d1, Dna *d2)
// {
// auto map = [](uint8_t a) -> int8_t
// { return a - 128; };
// uint8_t *d1a = (uint8_t *)d1;
// uint8_t *d2a = (uint8_t *)d2;
// float mag1 = 0.0f;
// float mag2 = 0.0f;
// float dot_prod = 0.0f;
// for (size_t i = 0; i < sizeof(Dna); i++)
// {
// int8_t a = map(d1a[i]);
// int8_t b = map(d2a[i]);
// dot_prod += a * b;
// mag1 += a * a;
// mag2 += b * b;
// }
// mag1 = sqrt(mag1);
// mag2 = sqrt(mag2);
// return dot_prod / (mag1 * mag2);
// }
float cosine_similarity_int(Dna *d1, Dna *d2)
{
auto map = [](uint8_t a) -> int8_t
{ return a - 128; };
uint8_t *d1a = (uint8_t *)d1;
uint8_t *d2a = (uint8_t *)d2;
float mag1 = 0.0f;
float mag2 = 0.0f;
float dot_prod = 0.0f;
for (size_t i = 0; i < sizeof(Dna); i++)
{
int8_t a = map(d1a[i]);
int8_t b = map(d2a[i]);
dot_prod += a * b;
mag1 += a * a;
mag2 += b * b;
}
mag1 = sqrt(mag1);
mag2 = sqrt(mag2);
return dot_prod / (mag1 * mag2);
}
float hamming_distance(Dna *d1, Dna *d2)
{
@@ -84,8 +116,45 @@ namespace Similarity
return 1 - (distance / (end - start));
}
const char *nameofFunc(simil_func f)
{
if (f == &Similarity::euclidean_distance)
{
return "eucl";
}
else if (f == &Similarity::dot_minmax)
{
return "dot";
}
else if (f == &Similarity::cosine_similarity)
{
return "cos";
}
else if (f == &Similarity::cosine_similarity_int)
{
return "cos_i";
}
else if (f == &Similarity::hamming_distance)
{
return "hamming_distance";
}
else if (f == &Similarity::hamming_distance_without_seeds)
{
return "hamming_distance_without_seeds";
}
else if (f == &Similarity::levenshtein_distance)
{
return "leven";
}
else
{
return "unknown nameofFunc";
}
}
float calc_similarity(std::vector<Dna> &vec, simil_func f)
{
auto start = std::chrono::high_resolution_clock::now();
size_t num_pairs = (vec.size() * (vec.size() - 1)) / 2;
float total_similarity = 0.0;
@@ -97,6 +166,47 @@ namespace Similarity
}
}
float average_similarity = total_similarity / num_pairs;
auto stop = std::chrono::high_resolution_clock::now();
const auto int_ms = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
return average_similarity * 100.0f;
}
float levenshtein_distance(Dna *d1, Dna *d2)
{
size_t len = sizeof(Dna);
uint8_t *a = (uint8_t *)d1;
uint8_t *b = (uint8_t *)d2;
// Create a distance matrix
static std::vector<std::vector<uint32_t>> dp(len + 1, std::vector<uint32_t>(len + 1, 0));
// Initialize the first row and column
for (size_t i = 0; i <= len; ++i)
{
dp[i][0] = i;
}
for (size_t j = 0; j <= len; ++j)
{
dp[0][j] = j;
}
// Fill the distance matrix
for (size_t i = 1; i <= len; ++i)
{
for (size_t j = 1; j <= len; ++j)
{
uint32_t cost = (a[i - 1] == b[j - 1]) ? 0 : 1;
dp[i][j] = std::min({
dp[i - 1][j] + 1, // deletion
dp[i][j - 1] + 1, // insertion
dp[i - 1][j - 1] + cost // substitution
});
}
}
return 1 - (dp[len][len] / float(len + len));
}
}

14
tmp.txt Normal file
View File

@@ -0,0 +1,14 @@
eucl cos cos_i hamming dot leven
91 117 181 87 41 105799
60 78 305 250 40 100331
61 78 121 105 40 97438
66 81 124 106 40 97529
60 78 127 108 40 96296
62 85 131 104 39 96456
61 81 125 106 40 96510
61 81 125 103 40 97253
61 81 125 78 40 97409
60 82 125 103 40 99816
62 81 128 81 40 98978
68 81 126 58 40 98289
61 88 130 60 39 99663

View File

@@ -11,10 +11,11 @@ enum DrawingStage
drawTree,
drawBig,
calSim,
save,
done,
};
constexpr int numberOfFunc = 2;
constexpr int numberOfFunc = 6;
class Vapp
{
@@ -27,6 +28,7 @@ public:
private:
bool showSelection;
bool showStats;
bool saveToFile;
sqlite3 *db;
sqlite3_stmt *get_gen_num;
std::vector<int64_t> ids;
@@ -52,4 +54,5 @@ private:
std::vector<std::array<float, numberOfFunc>> similTable;
void setUpTable();
void drawToFile();
};

View File

@@ -6,12 +6,13 @@
#include <rlImGui.h>
#include <imgui.h>
#include <raylib.h>
#include <fstream>
const char select_user_id[] = "SELECT USER_ID FROM user_table GROUP BY USER_ID;";
constexpr int sizeOfCanvas = 1000;
void Vapp::init(char* filename)
void Vapp::init(char *filename)
{
bigTexture = LoadRenderTexture(sizeOfCanvas * 4, sizeOfCanvas * 4);
treeTexture = LoadRenderTexture(sizeOfCanvas, sizeOfCanvas);
@@ -100,11 +101,18 @@ void Vapp::update()
break;
case DrawingStage::calSim:
simil[0] = Similarity::calc_similarity(manager.vector, Similarity::hamming_distance);
simil[1] = Similarity::calc_similarity(manager.vector, Similarity::hamming_distance_without_seeds);
simil[0] = Similarity::calc_similarity(manager.vector, Similarity::euclidean_distance);
simil[1] = Similarity::calc_similarity(manager.vector, Similarity::cosine_similarity);
simil[2] = Similarity::calc_similarity(manager.vector, Similarity::cosine_similarity_int);
simil[3] = Similarity::calc_similarity(manager.vector, Similarity::hamming_distance);
simil[4] = Similarity::calc_similarity(manager.vector, Similarity::levenshtein_distance);
simil[5] = Similarity::calc_similarity(manager.vector, Similarity::dot_minmax);
stageOfDrawing = DrawingStage::save;
break;
case DrawingStage::save:
if(saveToFile) drawToFile();
stageOfDrawing = DrawingStage::done;
break;
case DrawingStage::done:
enableAll = true;
break;
@@ -132,6 +140,10 @@ void Vapp::draw()
{
setUpTable();
}
if(ImGui::MenuItem("Save to File", nullptr, saveToFile, true))
{
saveToFile = !saveToFile;
}
ImGui::EndMainMenuBar();
}
@@ -173,13 +185,35 @@ void Vapp::draw()
if (showStats)
{
ImGui::Begin("Status", &showStats);
ImGui::LabelText("##sim1", "hamming_distance: %f", simil[0]);
ImGui::LabelText("##sim2", "hamming_distance_without_seeds: %f", simil[1]);
ImGui::LabelText("##sim1", "euclidean_distance: %f", simil[0]);
ImGui::LabelText("##sim2", "cosine_similarity: %f", simil[1]);
ImGui::LabelText("##sim3", "cosine_similarity_int: %f", simil[2]);
ImGui::LabelText("##sim4", "hamming_distance: %f", simil[3]);
ImGui::LabelText("##sim5", "levenshtein_distance: %f", simil[4]);
ImGui::LabelText("##sim6", "dot_minmax: %f", simil[5]);
const ImGuiTableFlags flags = ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_ContextMenuInBody;
const int columns = numberOfFunc + 1;
if (ImGui::BeginTable("table1", columns, flags))
{
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::Text("index");
ImGui::TableSetColumnIndex(1);
ImGui::Text("euclidean_distance");
ImGui::TableSetColumnIndex(2);
ImGui::Text("cosine_similarity");
ImGui::TableSetColumnIndex(3);
ImGui::Text("cosine_similarity_int");
ImGui::TableSetColumnIndex(4);
ImGui::Text("hamming_distance");
ImGui::TableSetColumnIndex(5);
ImGui::Text("levenshtein_distance");
ImGui::TableSetColumnIndex(6);
ImGui::Text("dot_minmax");
for (int row = 0; row < similTable.size(); row++)
{
ImGui::TableNextRow();
@@ -277,7 +311,7 @@ void Vapp::setUpTable()
UiUnit unit = DnaManager::next(&manager);
if ((unit.index != pos))
{
// DOTO: SET ERROR
// TODO: SET ERROR
TraceLog(LOG_ERROR, "LOADING DNA");
sql::finalize(get_gen_stmt);
return;
@@ -290,9 +324,13 @@ void Vapp::setUpTable()
{
similTable.emplace_back();
int s = similTable.size() - 1;
similTable[s][0] = Similarity::calc_similarity(manager.vector, Similarity::hamming_distance);
similTable[s][1] = Similarity::calc_similarity(manager.vector, Similarity::hamming_distance_without_seeds);
similTable[s][0] = Similarity::calc_similarity(manager.vector, Similarity::euclidean_distance);
similTable[s][1] = Similarity::calc_similarity(manager.vector, Similarity::cosine_similarity);
similTable[s][2] = Similarity::calc_similarity(manager.vector, Similarity::cosine_similarity_int);
similTable[s][3] = Similarity::calc_similarity(manager.vector, Similarity::hamming_distance);
similTable[s][4] = Similarity::calc_similarity(manager.vector, Similarity::levenshtein_distance);
similTable[s][5] = Similarity::calc_similarity(manager.vector, Similarity::dot_minmax);
DnaManager::newGen(&manager);
}
else
@@ -301,7 +339,38 @@ void Vapp::setUpTable()
}
sql::reset(get_gen_stmt);
}
if(saveToFile)
{
int64_t id = ids[selected_id_index];
const char* buff = TextFormat("%ld.txt", id);
std::ofstream file(buff);
file << "| index | euclidean_distance | cosine_similarity | cosine_similarity_int | hamming_distance | levenshtein_distance | dot_minmax |\n";
file << "| --- | --- | --- | --- | --- | --- | --- |\n";
for (size_t i = 0; i < similTable.size(); i++)
{
file << "|" << i << "|";
for (size_t j = 0; j < similTable[i].size(); j++)
{
file << similTable[i][j] << "|";
}
file << "\n";
}
}
}
sql::finalize(get_gen_stmt);
}
void Vapp::drawToFile()
{
int64_t id = ids[selected_id_index];
char buff[50];
sprintf(buff, "%ld_%d.png", id, selected_gen);
Image image = LoadImageFromTexture(bigTexture.texture);
ExportImage(image, buff);
UnloadImage(image);
}