Commit 16d5aa5f authored by CHEVALIER Arthur's avatar CHEVALIER Arthur Committed by Mathieu Faverge

feat(opengl): Added symbolic matrix visualizer

fix(src): Fixing some windows compatibility issues
parent e1d922d8
...@@ -54,6 +54,7 @@ CTestTestfile.cmake ...@@ -54,6 +54,7 @@ CTestTestfile.cmake
plugins/*/*_autogen plugins/*/*_autogen
src/*_autogen src/*_autogen
build* build*
.vs
# Generated files # Generated files
src/common/ViteConfig.hpp src/common/ViteConfig.hpp
......
...@@ -43,7 +43,6 @@ set (MATRIXVISUALIZER_hdrs ...@@ -43,7 +43,6 @@ set (MATRIXVISUALIZER_hdrs
Windows/MatrixGLWidget.hpp Windows/MatrixGLWidget.hpp
Common/QuadTree.hpp Common/QuadTree.hpp
Common/Node.hpp
) )
set (MATRIXVISUALIZER_srcs set (MATRIXVISUALIZER_srcs
...@@ -59,7 +58,6 @@ set (MATRIXVISUALIZER_srcs ...@@ -59,7 +58,6 @@ set (MATRIXVISUALIZER_srcs
Windows/MatrixGLWidget.cpp Windows/MatrixGLWidget.cpp
Common/QuadTree.cpp Common/QuadTree.cpp
Common/Node.cpp
) )
set (MATRIXVISUALIZER_forms_tmp set (MATRIXVISUALIZER_forms_tmp
......
#include "Node.hpp"
Node::Node()
{
m_children = nullptr;
}
#ifndef NODE_HPP
#define NODE_HPP
class Node
{
public:
Node();
private:
Node* m_children;
};
#endif
#include "QuadTree.hpp" #include "QuadTree.hpp"
QuadTree::QuadTree() #include "../Helper.hpp"
bool QuadTreeRecur(symbol_matrix_t* matrix, Node* actual, int cutsRemaining, int startColumn, int endColumn, int startRow, int endRow);
QuadTree::QuadTree(Node* root, symbol_matrix_t* matrix)
: m_root(root)
, m_matrix(matrix)
{
// Fill correct colors
move(0.f, 1.f, 0.f, 1.f);
}
void destroyRecur(Node* actual)
{ {
int i;
if (actual == nullptr)
return;
for (i = 0; i < actual->m_nbChildren; ++i)
destroyRecur(actual->m_children[i]);
delete actual;
}
QuadTree::~QuadTree()
{
// Destroy quadtree
destroyRecur(m_root);
symbol_matrix_deinit(m_matrix);
delete m_matrix;
} }
GLfloat QuadTree::getColor(int x, int y) GLfloat QuadTree::getColor(int x, int y)
{ {
return (float)(rand() % 100) / 100.f; return m_colors[x][y];
}
#include <iostream>
void QuadTree::move(float xStart, float xEnd, float yStart, float yEnd)
{
int i, j;
int startCblk = xStart * m_matrix->m_cblknbr;
int endCbkl = startCblk + (xEnd - xStart) * m_matrix->m_cblknbr;
int diffCblk = endCbkl - startCblk;
int startRow = yStart * m_matrix->m_rowsnbr;
int endRow = startRow + (yEnd - yStart) * m_matrix->m_rowsnbr;
int diffRow = endRow - startRow;
symbol_cblk_t* cblks = m_matrix->m_cblktab;
symbol_blok_t* bloks = m_matrix->m_bloktab;
for (i = 0; i < DEFAULT_LEVEL_POWER_2; ++i)
{
for (j = 0; j < DEFAULT_LEVEL_POWER_2; ++j)
{
m_colors[i][j] = 0.f;
}
}
float xCoeff = 256.f / (float)diffCblk;
float yCoeff = 256.f / (float)diffRow;
for (i = startCblk; i < endCbkl; ++i)
{
int firstBlokNum = cblks[i].m_bloknum;
int nextBlokNum = (i + 1 != m_matrix->m_cblknbr ? cblks[i + 1].m_bloknum : m_matrix->m_cblknbr);
int x = (float)i * xCoeff;
for (j = firstBlokNum; j < nextBlokNum; ++j)
{
symbol_blok_t* blok = &(bloks[j]);
if (blok->m_frownum > startRow && blok->m_frownum <= endRow)
{
int y = (float)blok->m_frownum * yCoeff;
m_colors[x][y] = 1.0f;
}
}
}
}
size_t GetMemoryLoadRecur(Node* actual)
{
int i;
size_t size = sizeof(Node);
for (i = 0; i < actual->m_nbChildren; ++i)
{
size += GetMemoryLoadRecur(actual->m_children[i]);
}
return size;
}
size_t GetMemoryLoad(Node* root)
{
size_t result = GetMemoryLoadRecur(root);
return result;
} }
QuadTree* QuadTree::constructFromSymbolMatrix(symbol_matrix_t* matrix) QuadTree* QuadTree::constructFromSymbolMatrix(symbol_matrix_t* matrix)
{ {
QuadTree* tree = new QuadTree(); Node* root = new Node;
// Construct quad tree
Helper::log(LogStatus::MESSAGE, "Starting building QuadTree");
root->m_id = 1;
QuadTreeRecur(matrix, root, QuadTree::DEFAULT_LEVEL, 0, matrix->m_cblknbr, 0, matrix->m_rowsnbr);
Helper::log(LogStatus::MESSAGE, "End building QuadTree");
size_t memory_load = GetMemoryLoad(root) + sizeof(QuadTree);
Helper::log(LogStatus::MESSAGE, "QuadTree takes %.2lf %s of memory !",
MEMORY_WRITE(memory_load), MEMORY_UNIT_WRITE(memory_load));
return new QuadTree(root, matrix);
}
bool QuadTreeRecur(symbol_matrix_t* matrix, Node* actual, int cutsRemaining, int startColumn, int endColumn, int startRow, int endRow)
{
int midCblk = (endColumn - startColumn) / 2;
int midRow = (endRow - startRow) / 2;
actual->m_startCblk = startColumn;
actual->m_endCblk = endColumn;
actual->m_startRow = startRow;
actual->m_endRow = endRow;
if (cutsRemaining == 0)
{
symbol_cblk_t* cblks = matrix->m_cblktab;
symbol_blok_t* bloks = matrix->m_bloktab;
int i, j;
for (i = startColumn; i <= endColumn; ++i)
{
int firstBlokNum = cblks[i].m_bloknum;
int nextBlokNum = (i + 1 != matrix->m_cblknbr ? cblks[i + 1].m_bloknum : matrix->m_cblknbr);
for (j = firstBlokNum; j < nextBlokNum; ++j)
{
symbol_blok_t* blok = &(bloks[j]);
if (blok->m_frownum >= startRow && blok->m_frownum <= endRow)
{
if (!(blok->m_flags & BLOK_FLAG_IN_TREE))
{
blok->m_localization = actual->m_id;
blok->m_flags |= BLOK_FLAG_IN_TREE;
}
}
}
}
return true;
}
else
{
int nbValidNode = 0;
Node* first = new Node;
first->m_id = actual->m_id << 2;
if (!QuadTreeRecur(matrix, first, cutsRemaining - 1, startColumn, startColumn + midCblk, startRow, startRow + midRow))
{
delete first;
first = nullptr;
}
else
nbValidNode++;
Node* second = new Node;
second->m_id = (actual->m_id << 2) | 1;
if (!QuadTreeRecur(matrix, second, cutsRemaining - 1, startColumn, startColumn + midCblk, startRow, startRow + midRow))
{
delete second;
second = nullptr;
}
else
nbValidNode++;
Node* third = new Node;
third->m_id = (actual->m_id << 2) | 2;
if (!QuadTreeRecur(matrix, third, cutsRemaining - 1, startColumn, startColumn + midCblk, startRow, startRow + midRow))
{
delete third;
third = nullptr;
}
else
nbValidNode++;
Node* fourth = new Node;
fourth->m_id = (actual->m_id << 2) | 3;
if (!QuadTreeRecur(matrix, fourth, cutsRemaining - 1, startColumn, startColumn + midCblk, startRow, startRow + midRow))
{
delete fourth;
fourth = nullptr;
}
else
nbValidNode++;
if (nbValidNode > 0)
{
actual->m_nbChildren = nbValidNode;
actual->m_children = (Node**)malloc(nbValidNode * sizeof(Node*));
Node** tmp = actual->m_children;
if (first != nullptr)
{
*tmp = first;
tmp++;
}
if (second != nullptr)
{
*tmp = second;
tmp++;
}
if (third != nullptr)
{
*tmp = third;
tmp++;
}
if (fourth != nullptr)
{
*tmp = fourth;
tmp++;
}
}
return tree; return nbValidNode > 0;
}
} }
\ No newline at end of file
...@@ -4,19 +4,42 @@ ...@@ -4,19 +4,42 @@
#include <QtOpenGL/QtOpenGL> #include <QtOpenGL/QtOpenGL>
#include "../Formats/SymbolMatrix.hpp" #include "../Formats/SymbolMatrix.hpp"
#include "Node.hpp"
typedef struct Node
{
uint32_t m_id;
int32_t m_nbChildren;
// Position
int32_t m_startCblk;
int32_t m_endCblk;
int32_t m_startRow;
int32_t m_endRow;
struct Node** m_children;
} Node;
class QuadTree class QuadTree
{ {
public: public:
QuadTree(); static const int DEFAULT_LEVEL = 8;
static const int DEFAULT_LEVEL_POWER_2 = 256;
public:
QuadTree(Node* root, symbol_matrix_t* matrix);
~QuadTree();
GLfloat getColor(int x, int y); GLfloat getColor(int x, int y);
void move(float xStart, float xEnd, float yStart, float yEnd);
static QuadTree* constructFromSymbolMatrix(symbol_matrix_t* matrix); static QuadTree* constructFromSymbolMatrix(symbol_matrix_t* matrix);
private: private:
Node m_root; Node* m_root;
symbol_matrix_t* m_matrix;
GLfloat m_colors[DEFAULT_LEVEL_POWER_2][DEFAULT_LEVEL_POWER_2];
}; };
#endif #endif
...@@ -16,20 +16,6 @@ static inline int32_t imax(int32_t a, int32_t b) ...@@ -16,20 +16,6 @@ static inline int32_t imax(int32_t a, int32_t b)
} }
/* Macros */ /* Macros */
#define MEMORY_WRITE(mem) ( ((mem) < 1<<10) ? \
( (double)(mem) ) : \
( ( (mem) < 1<<20 ) ? \
( (double)(mem)/(double)(1<<10) ) : \
( ((mem) < 1<<30 ) ? \
( (double)(mem)/(double)(1<<20) ) : \
( (double)(mem)/(double)(1<<30) ))))
#define MEMORY_UNIT_WRITE(mem) (((mem) < 1<<10) ? \
"o" : \
( ( (mem) < 1<<20 ) ? \
"Ko" : \
( ( (mem) < 1<<30 ) ? \
"Mo" : \
"Go" )))
#define memFree(ptr) free((void*)(ptr)) #define memFree(ptr) free((void*)(ptr))
#define memFree_null(ptr) do \ #define memFree_null(ptr) do \
{ \ { \
...@@ -40,7 +26,6 @@ static inline int32_t imax(int32_t a, int32_t b) ...@@ -40,7 +26,6 @@ static inline int32_t imax(int32_t a, int32_t b)
void symbol_matrix_init(symbol_matrix_t* matrix) void symbol_matrix_init(symbol_matrix_t* matrix)
{ {
memset(matrix, 0, sizeof(symbol_matrix_t)); memset(matrix, 0, sizeof(symbol_matrix_t));
matrix->m_schurfcol = -1;
return; return;
} }
...@@ -59,6 +44,8 @@ void symbol_matrix_deinit(symbol_matrix_t* matrix) ...@@ -59,6 +44,8 @@ void symbol_matrix_deinit(symbol_matrix_t* matrix)
return; return;
} }
#include <iostream>
void symbol_matrix_print_stats(symbol_matrix_t* matrix) void symbol_matrix_print_stats(symbol_matrix_t* matrix)
{ {
symbol_cblk_t* cblk; symbol_cblk_t* cblk;
......
...@@ -5,10 +5,10 @@ ...@@ -5,10 +5,10 @@
typedef struct symbol_cblk_s typedef struct symbol_cblk_s
{ {
int32_t m_fcolumn; int32_t m_fcolumn; // First column index
int32_t m_lcolnum; int32_t m_lcolnum; // Last column index (inclusive)
int32_t m_bloknum; int32_t m_bloknum; // First blok in column
int32_t m_flags; int32_t m_flags; // Flags
} symbol_cblk_t; } symbol_cblk_t;
#define CBLK_FLAG_2D 1 #define CBLK_FLAG_2D 1
...@@ -16,12 +16,35 @@ typedef struct symbol_cblk_s ...@@ -16,12 +16,35 @@ typedef struct symbol_cblk_s
typedef struct symbol_blok_s typedef struct symbol_blok_s
{ {
int32_t m_frownum; int32_t m_frownum; // First row index
int32_t m_lrownum; int32_t m_lrownum; // Last row index
int32_t m_lcblknm; // local int32_t m_lcblknm; // Local column blok
int32_t m_fcblknm; // facing int32_t m_fcblknm; // Facing column blok
uint32_t m_localization; // Localization
int32_t m_flags;
} symbol_blok_t; } symbol_blok_t;
#define BLOK_FLAG_IN_TREE 1
/*
How localization works ?
=> See Z-curve identification
We use Z-curve to ID the quadtree nodes and we flip the bit of the level.
For example if we are in the third level of quadtreefication and we have the ID 2:
0000 0000 0001 0010
^ ^
| ID of the node
Bit flipped for the level
With this technique we can store a 32 bits localization to allow 15 levels of details
and know the parents of any node due to the Z-curve :D
*/
typedef struct symbol_matrix_s typedef struct symbol_matrix_s
{ {
int32_t m_baseval; int32_t m_baseval;
...@@ -30,7 +53,7 @@ typedef struct symbol_matrix_s ...@@ -30,7 +53,7 @@ typedef struct symbol_matrix_s
int32_t m_cblknbr; int32_t m_cblknbr;
int32_t m_bloknbr; int32_t m_bloknbr;
int32_t m_nodenbr; int32_t m_nodenbr;
int32_t m_schurfcol; int32_t m_rowsnbr;
symbol_cblk_t* m_cblktab; symbol_cblk_t* m_cblktab;
symbol_blok_t* m_bloktab; symbol_blok_t* m_bloktab;
......
#include "Helper.hpp" #include "Helper.hpp"
#include <cstdarg> #include <cstdarg>
#include <iostream>
#include "MatrixVisualizer.hpp" #include "MatrixVisualizer.hpp"
......
...@@ -5,11 +5,26 @@ enum LogStatus ...@@ -5,11 +5,26 @@ enum LogStatus
{ {
MESSAGE, MESSAGE,
WARNING, WARNING,
ERROR, FATAL,
COUNT COUNT
}; };
#define MEMORY_WRITE(mem) ( ((mem) < 1<<10) ? \
( (double)(mem) ) : \
( ( (mem) < 1<<20 ) ? \
( (double)(mem)/(double)(1<<10) ) : \
( ((mem) < 1<<30 ) ? \
( (double)(mem)/(double)(1<<20) ) : \
( (double)(mem)/(double)(1<<30) ))))
#define MEMORY_UNIT_WRITE(mem) (((mem) < 1<<10) ? \
"o" : \
( ( (mem) < 1<<20 ) ? \
"Ko" : \
( ( (mem) < 1<<30 ) ? \
"Mo" : \
"Go" )))
namespace Helper namespace Helper
{ {
void log(LogStatus status, const char* format, ...); void log(LogStatus status, const char* format, ...);
......
...@@ -15,6 +15,9 @@ Matrix_visualizer::Matrix_visualizer() { ...@@ -15,6 +15,9 @@ Matrix_visualizer::Matrix_visualizer() {
s_plugin = this; s_plugin = this;
this->connect_widgets(); this->connect_widgets();
// For windows dev (pc: orange)
this->line_edit_symbol->setText("C:\\Data\\Lessons\\2017-2018\\PFA\\Matrix\\symb_lap40.txt");
} }
Matrix_visualizer* Matrix_visualizer::Get() Matrix_visualizer* Matrix_visualizer::Get()
...@@ -57,7 +60,7 @@ void Matrix_visualizer::execute(){ ...@@ -57,7 +60,7 @@ void Matrix_visualizer::execute(){
if (symbol_filepath.size() == 0) if (symbol_filepath.size() == 0)
{ {
Helper::log(LogStatus::ERROR, "Empty filepath for symbol matrix file..."); Helper::log(LogStatus::FATAL, "Empty filepath for symbol matrix file...");
return; return;
} }
...@@ -97,8 +100,8 @@ void Matrix_visualizer::log(LogStatus status, const char* format, va_list ap) ...@@ -97,8 +100,8 @@ void Matrix_visualizer::log(LogStatus status, const char* format, va_list ap)
case WARNING: case WARNING:
previous_text += "Warning: "; previous_text += "Warning: ";
break; break;
case ERROR: case FATAL:
previous_text += "ERROR: "; previous_text += "FATAL: ";
break; break;
default: default:
break; break;
......