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
plugins/*/*_autogen
src/*_autogen
build*
.vs
# Generated files
src/common/ViteConfig.hpp
......
......@@ -43,7 +43,6 @@ set (MATRIXVISUALIZER_hdrs
Windows/MatrixGLWidget.hpp
Common/QuadTree.hpp
Common/Node.hpp
)
set (MATRIXVISUALIZER_srcs
......@@ -59,7 +58,6 @@ set (MATRIXVISUALIZER_srcs
Windows/MatrixGLWidget.cpp
Common/QuadTree.cpp
Common/Node.cpp
)
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"
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)
{
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* 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");
return tree;
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 nbValidNode > 0;
}
}
\ No newline at end of file
......@@ -4,19 +4,42 @@
#include <QtOpenGL/QtOpenGL>
#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
{
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);
static QuadTree* constructFromSymbolMatrix(symbol_matrix_t* matrix);
void move(float xStart, float xEnd, float yStart, float yEnd);
static QuadTree* constructFromSymbolMatrix(symbol_matrix_t* matrix);
private:
Node m_root;
Node* m_root;
symbol_matrix_t* m_matrix;
GLfloat m_colors[DEFAULT_LEVEL_POWER_2][DEFAULT_LEVEL_POWER_2];
};
#endif
......@@ -16,20 +16,6 @@ static inline int32_t imax(int32_t a, int32_t b)
}
/* 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_null(ptr) do \
{ \
......@@ -40,7 +26,6 @@ static inline int32_t imax(int32_t a, int32_t b)
void symbol_matrix_init(symbol_matrix_t* matrix)
{
memset(matrix, 0, sizeof(symbol_matrix_t));
matrix->m_schurfcol = -1;
return;
}
......@@ -59,6 +44,8 @@ void symbol_matrix_deinit(symbol_matrix_t* matrix)
return;
}
#include <iostream>
void symbol_matrix_print_stats(symbol_matrix_t* matrix)
{
symbol_cblk_t* cblk;
......
......@@ -5,10 +5,10 @@
typedef struct symbol_cblk_s
{
int32_t m_fcolumn;
int32_t m_lcolnum;
int32_t m_bloknum;
int32_t m_flags;
int32_t m_fcolumn; // First column index
int32_t m_lcolnum; // Last column index (inclusive)
int32_t m_bloknum; // First blok in column
int32_t m_flags; // Flags
} symbol_cblk_t;
#define CBLK_FLAG_2D 1
......@@ -16,12 +16,35 @@ typedef struct symbol_cblk_s
typedef struct symbol_blok_s
{
int32_t m_frownum;
int32_t m_lrownum;
int32_t m_lcblknm; // local
int32_t m_fcblknm; // facing
int32_t m_frownum; // First row index
int32_t m_lrownum; // Last row index
int32_t m_lcblknm; // Local column blok
int32_t m_fcblknm; // Facing column blok
uint32_t m_localization; // Localization
int32_t m_flags;
} 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
{
int32_t m_baseval;
......@@ -30,7 +53,7 @@ typedef struct symbol_matrix_s
int32_t m_cblknbr;
int32_t m_bloknbr;
int32_t m_nodenbr;
int32_t m_schurfcol;
int32_t m_rowsnbr;
symbol_cblk_t* m_cblktab;
symbol_blok_t* m_bloktab;
......
#include "Helper.hpp"
#include <cstdarg>
#include <iostream>
#include "MatrixVisualizer.hpp"
......
......@@ -5,11 +5,26 @@ enum LogStatus
{
MESSAGE,
WARNING,
ERROR,
FATAL,
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
{
void log(LogStatus status, const char* format, ...);
......
......@@ -15,6 +15,9 @@ Matrix_visualizer::Matrix_visualizer() {
s_plugin = this;
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()
......@@ -57,7 +60,7 @@ void Matrix_visualizer::execute(){
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;
}
......@@ -97,8 +100,8 @@ void Matrix_visualizer::log(LogStatus status, const char* format, va_list ap)
case WARNING:
previous_text += "Warning: ";
break;
case ERROR:
previous_text += "ERROR: ";
case FATAL:
previous_text += "FATAL: ";
break;
default:
break;
......
#include "Pastix.hpp"
#include "../../Helper.hpp"
#include <iostream>
#include <cstdlib>
#include <ctype.h>
int pastix_read_symbol(FILE* stream, symbol_matrix_t* matrix)
{
int32_t versval;
int32_t i, j;
int32_t cblknum;
int32_t bloknum;
if ((pastix_read_int(stream, &versval) +
pastix_read_int(stream, &matrix->m_cblknbr) +
pastix_read_int(stream, &matrix->m_bloknbr) +
pastix_read_int(stream, &matrix->m_nodenbr) +
pastix_read_int(stream, &matrix->m_baseval) != 5) ||
int32_t result = 0;
result += pastix_read_int(stream, &versval);
result += pastix_read_int(stream, &matrix->m_cblknbr);
result += pastix_read_int(stream, &matrix->m_bloknbr);
result += pastix_read_int(stream, &matrix->m_nodenbr);
result += pastix_read_int(stream, &matrix->m_baseval);
if ((result != 5) ||
(versval < 0) ||
(versval > 1) ||
(matrix->m_bloknbr < matrix->m_cblknbr) ||
(matrix->m_nodenbr < matrix->m_cblknbr))
{
Helper::log(LogStatus::ERROR, "Loading symbol file %s, bad header !");
Helper::log(LogStatus::FATAL, "Loading symbol file, bad header !");
return 1;
}
Helper::log(LogStatus::MESSAGE,
"Loaded header:\n"
" Version: %10d\n"
" Number of cblk: %10d\n"
" Number of blok: %10d\n"
" Number of nodes: %10d\n"
" Base value: %10d\n",
versval,
matrix->m_cblknbr, matrix->m_bloknbr,
matrix->m_nodenbr, matrix->m_baseval
);
matrix->m_cblktab = (symbol_cblk_t*)malloc((matrix->m_cblknbr + 1) * sizeof(symbol_cblk_t));
matrix->m_bloktab = (symbol_blok_t*)malloc(matrix->m_bloknbr * sizeof(symbol_blok_t));
if (matrix->m_cblktab == nullptr || matrix->m_bloktab == nullptr)
{
Helper::log(LogStatus::ERROR, "Out of memory while allocating tabs !");
Helper::log(LogStatus::FATAL, "Out of memory while allocating tabs !");
return 1;
}
......@@ -50,12 +43,14 @@ int pastix_read_symbol(FILE* stream, symbol_matrix_t* matrix)
int32_t cblknbr = matrix->m_cblknbr;
for (cblknum = 0; cblknum < cblknbr; ++cblknum)
{
if ((pastix_read_int(stream, &(matrix->m_cblktab[cblknum].m_fcolumn)) +
pastix_read_int(stream, &(matrix->m_cblktab[cblknum].m_lcolnum)) +
pastix_read_int(stream, &(matrix->m_cblktab[cblknum].m_bloknum)) != 3) ||
result = pastix_read_int(stream, &(matrix->m_cblktab[cblknum].m_fcolumn));
result += pastix_read_int(stream, &(matrix->m_cblktab[cblknum].m_lcolnum));
result += pastix_read_int(stream, &(matrix->m_cblktab[cblknum].m_bloknum));
if ((result != 3) ||
(matrix->m_cblktab[cblknum].m_fcolumn > matrix->m_cblktab[cblknum].m_lcolnum))
{
Helper::log(LogStatus::ERROR, "Bad input while reading cblk !");
Helper::log(LogStatus::FATAL, "Bad input while reading cblk !");
return 1;
}
......@@ -66,30 +61,53 @@ int pastix_read_symbol(FILE* stream, symbol_matrix_t* matrix)
matrix->m_cblktab[cblknbr].m_bloknum = matrix->m_bloknbr + matrix->m_baseval;
int32_t bloknbr = matrix->m_bloknbr;
int32_t maxrow = 0;
for (bloknum = 0; bloknum < bloknbr; ++bloknum)
{
if ((pastix_read_int(stream, &matrix->m_bloktab[bloknum].m_frownum) +
pastix_read_int(stream, &matrix->m_bloktab[bloknum].m_lrownum) +
pastix_read_int(stream, &matrix->m_bloktab[bloknum].m_fcblknm) != 3) ||
result = pastix_read_int(stream, &matrix->m_bloktab[bloknum].m_frownum);
result += pastix_read_int(stream, &matrix->m_bloktab[bloknum].m_lrownum);
result += pastix_read_int(stream, &matrix->m_bloktab[bloknum].m_fcblknm);
if ((result != 3) ||
(matrix->m_bloktab[bloknum].m_frownum > matrix->m_bloktab[bloknum].m_lrownum))
{
Helper::log(LogStatus::ERROR, "Bad input while reading blok !", bloknum);
Helper::log(LogStatus::FATAL, "Bad input while reading blok %d !", bloknum);
return 1;
}
if (matrix->m_bloktab[bloknum].m_lrownum > maxrow)
maxrow = matrix->m_bloktab[bloknum].m_lrownum;
matrix->m_bloktab[bloknum].m_localization = 0;
matrix->m_bloktab[bloknum].m_flags = 0;
// Compatibility block
{
int32_t tmp;
if ((versval == 0) && (pastix_read_int(stream, &tmp) != 1))
{
Helper::log(LogStatus::ERROR, "Bad input while reading lefval !");
Helper::log(LogStatus::FATAL, "Bad input while reading lefval !");
return 1;
}
}
}
matrix->m_dof = 1;
matrix->m_rowsnbr = maxrow + 1;
Helper::log(LogStatus::MESSAGE,
"Loaded header:\n"
" Version: %10d\n"
" Number of cblk: %10d\n"
" Number of rows: %10d\n"
" Number of blok: %10d\n"
" Number of nodes: %10d\n"
" Base value: %10d\n",
versval,
matrix->m_cblknbr, matrix->m_rowsnbr,
matrix->m_bloknbr, matrix->m_nodenbr,
matrix->m_baseval
);
return 0;
}
......
......@@ -2,11 +2,9 @@
#include "MatrixWindow.hpp"
#define BACKGROUND_COLOR_R 0.f
#define BACKGROUND_COLOR_G 0.f
#define BACKGROUND_COLOR_B 0.f
#define NB_BLOK_BY_SIDE 256
#define BACKGROUND_COLOR_R 1.f
#define BACKGROUND_COLOR_G 1.f
#define BACKGROUND_COLOR_B 1.f
/* Helpers */
static void drawSquare(GLfloat x, GLfloat y, GLfloat dx, GLfloat dy, GLfloat r, GLfloat g, GLfloat b)
......@@ -28,25 +26,32 @@ static void drawEmpty()
glBegin(GL_TRIANGLES);
glColor3f(BACKGROUND_COLOR_R, BACKGROUND_COLOR_G, BACKGROUND_COLOR_B);
glVertex2f(0, NB_BLOK_BY_SIDE);
glVertex2f(NB_BLOK_BY_SIDE, NB_BLOK_BY_SIDE);
glVertex2f(NB_BLOK_BY_SIDE, 0);
glVertex2f(0, QuadTree::DEFAULT_LEVEL_POWER_2);
glVertex2f(QuadTree::DEFAULT_LEVEL_POWER_2, QuadTree::DEFAULT_LEVEL_POWER_2);
glVertex2f(QuadTree::DEFAULT_LEVEL_POWER_2, 0);
glEnd();
}
MatrixGLWidget::MatrixGLWidget(QWidget* parent, symbol_matrix_t* matrix)
MatrixGLWidget::MatrixGLWidget(QWidget* parent, symbol_matrix_t* matrix, QLabel* label)
#ifdef USE_QT5
: QOpenGLWidget(parent)
#else
: QGLWidget(parent)
#endif
, m_label(label)
, m_frameCount(0)
{
this->setFixedSize(MATRIX_WINDOW_LENGTH, MATRIX_WINDOW_HEIGHT);
m_quadtree = QuadTree::constructFromSymbolMatrix(matrix);
symbol_matrix_deinit(matrix);
delete matrix;
#ifdef USE_QT5
connect(&m_updateTimer, &QTimer::timeout, this, &MatrixGLWidget::updateTimer);
#else
connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateTimer()));
#endif
m_updateTimer.start(1000 / 60);
}
MatrixGLWidget::~MatrixGLWidget()
......@@ -63,7 +68,7 @@ void MatrixGLWidget::initializeGL()