diff --git a/src/graph/CMakeLists.txt b/src/graph/CMakeLists.txt index 379a365..2678952 100644 --- a/src/graph/CMakeLists.txt +++ b/src/graph/CMakeLists.txt @@ -4,5 +4,5 @@ include_directories(svg) add_subdirectory(svg) -add_library(graph graph.cc) +add_library(graph case.cc graph.cc) target_link_libraries(graph analyse svg) diff --git a/src/graph/case.cc b/src/graph/case.cc new file mode 100644 index 0000000..05f896a --- /dev/null +++ b/src/graph/case.cc @@ -0,0 +1,54 @@ +#include "graph.h" +#include "common.h" + +void GraphCase::render(SvgGraph &svg, const CaseSkin &skin) const { + /// precompute size info + auto raw_code = (uint64_t)code; + uint32_t block_width_2 = block_width * 2 + block_gap; + uint32_t case_width = block_width * 4 + block_gap * 5; + uint32_t case_height = block_width * 5 + block_gap * 6; + + /// case skeleton render + auto skeleton = new SvgRect {start, case_width, case_height}; + skeleton->color = skin.CASE_BG_COLOR; + skeleton->stroke = skin.CASE_BORDER_WIDTH; + skeleton->line_color = skin.CASE_BORDER_COLOR; + skeleton->radius = uint64_t(skin.CASE_RADIUS * (float)block_width); + svg.insert(skeleton); + + /// lambda for insert new block + auto new_block = [this, &skin, &svg](SvgRect *block) { + block->color = skin.BLOCK_BG_COLOR; + block->stroke = skin.BLOCK_BORDER_WIDTH; + block->line_color = skin.BLOCK_BORDER_COLOR; + block->radius = uint64_t(skin.BLOCK_RADIUS * (float)block_width); + svg.insert(block); + }; + + for (int addr = 0; raw_code; ++addr, raw_code >>= 3) { + /// calculate block address + uint32_t block_x = addr % 4; + uint32_t block_y = (addr - block_x) / 4; + Point block_start = { + start.x + block_x * block_width + (block_x + 1) * block_gap, + start.y + block_y * block_width + (block_y + 1) * block_gap, + }; + /// render into svg graph + switch (raw_code & 0b111) { + case B_1x1: + new_block(new SvgRect {block_start, block_width, block_width}); + break; + case B_1x2: + new_block(new SvgRect {block_start, block_width_2, block_width}); + break; + case B_2x1: + new_block(new SvgRect {block_start, block_width, block_width_2}); + break; + case B_2x2: + new_block(new SvgRect {block_start, block_width_2, block_width_2}); + break; + default: + continue; + } + } +} diff --git a/src/graph/graph.cc b/src/graph/graph.cc index 985cca7..865ad22 100644 --- a/src/graph/graph.cc +++ b/src/graph/graph.cc @@ -32,21 +32,8 @@ void Graph::svg_demo(Analyse::track_data_t track_data) { // } - auto p = Point{100, 200}; - auto rc = RawCode::unsafe_create(0x0603EDF5CAFFF5E2); - auto gc = GraphCase(p, rc, BLOCK_GAP, BLOCK_LENGTH); - auto skin = CaseSkin(); - auto svg = SvgGraph(2000, 2000); - - gc.render(svg, skin); - - std::cout << svg.dump() << std::endl; - - return; - - struct inner_t { uint64_t code; uint32_t layer_num; @@ -82,88 +69,24 @@ void Graph::svg_demo(Analyse::track_data_t track_data) { uint64_t MAIN_WIDTH = CASE_WIDTH * max_length_num + CASE_GAP_X * (max_length_num + 1); uint64_t MAIN_HEIGHT = CASE_HEIGHT * layer_data.size() + CASE_GAP_Y * (layer_data.size() + 1); -// std::cout << "MAIN_WIDTH = " << MAIN_WIDTH << std::endl; -// std::cout << "MAIN_HEIGHT = " << MAIN_HEIGHT << std::endl; - + auto svg = SvgGraph(MAIN_WIDTH, MAIN_HEIGHT); for (uint32_t i = 0; i < layer_data.size(); ++i) { uint64_t CASE_Y = CASE_GAP_Y * (i + 1) + CASE_HEIGHT * i; -// std::cout << "TOP: " << CASE_Y << std::endl; - uint64_t left_offset = (MAIN_WIDTH - (CASE_GAP_X * (layer_data[i].size() + 1) + CASE_WIDTH * layer_data[i].size())) / 2; for (uint32_t j = 0; j < layer_data[i].size(); ++j) { uint64_t CASE_X = CASE_GAP_X * (j + 1) + CASE_WIDTH * j + left_offset; -// printf("(%ld, %ld, %ld, %ld)\n", CASE_Y, CASE_X, CASE_WIDTH, CASE_HEIGHT); -// printf(R"( )", CASE_X, CASE_Y, CASE_WIDTH, CASE_HEIGHT); -// printf("\n"); - -// SvgCase tmp = SvgCase(); -// tmp.width = BLOCK_LENGTH; -// tmp.gap = BLOCK_GAP; -// tmp.left = CASE_X; -// tmp.top = CASE_Y; -// tmp.code = layer_data[i][j].code; -// tmp.render(); + auto g = GraphCase({CASE_X, CASE_Y}, RawCode::unsafe_create(layer_data[i][j].code), BLOCK_GAP, BLOCK_LENGTH); + g.render(svg, skin); } } + std::cout << svg.dump() << std::endl; } - -void GraphCase::render(SvgGraph &svg, const CaseSkin &skin) const { - /// precompute size info - auto raw_code = (uint64_t)code; - uint32_t block_width_2 = block_width * 2 + block_gap; - uint32_t case_width = block_width * 4 + block_gap * 5; - uint32_t case_height = block_width * 5 + block_gap * 6; - - /// case skeleton render - auto skeleton = new SvgRect {start, case_width, case_height}; - skeleton->color = skin.CASE_BG_COLOR; - skeleton->stroke = skin.CASE_BORDER_WIDTH; - skeleton->line_color = skin.CASE_BORDER_COLOR; - skeleton->radius = uint64_t(skin.CASE_RADIUS * (float)block_width); - svg.insert(skeleton); - - /// lambda for insert new block - auto new_block = [this, &skin, &svg](SvgRect *block) { - block->color = skin.BLOCK_BG_COLOR; - block->stroke = skin.BLOCK_BORDER_WIDTH; - block->line_color = skin.BLOCK_BORDER_COLOR; - block->radius = uint64_t(skin.BLOCK_RADIUS * (float)block_width); - svg.insert(block); - }; - - for (int addr = 0; raw_code; ++addr, raw_code >>= 3) { - /// calculate block address - uint32_t block_x = addr % 4; - uint32_t block_y = (addr - block_x) / 4; - Point block_start = { - start.x + block_x * block_width + (block_x + 1) * block_gap, - start.y + block_y * block_width + (block_y + 1) * block_gap, - }; - /// render into svg graph - switch (raw_code & 0b111) { - case B_1x1: - new_block(new SvgRect {block_start, block_width, block_width}); - break; - case B_1x2: - new_block(new SvgRect {block_start, block_width_2, block_width}); - break; - case B_2x1: - new_block(new SvgRect {block_start, block_width, block_width_2}); - break; - case B_2x2: - new_block(new SvgRect {block_start, block_width_2, block_width_2}); - break; - default: - continue; - } - } -} diff --git a/src/graph/graph.h b/src/graph/graph.h index a317ac4..4f462e1 100644 --- a/src/graph/graph.h +++ b/src/graph/graph.h @@ -2,27 +2,21 @@ #include "analyse.h" #include "svg/svg.h" - #include "raw_code.h" -//struct BlockOpt { -// uint32_t gap; -// uint32_t width; -//}; - class CaseSkin { public: /// case options float CASE_RADIUS = 0.2; - uint32_t CASE_BORDER_WIDTH = 2; - std::string CASE_BG_COLOR = "pink"; - std::string CASE_BORDER_COLOR = "blue"; + float CASE_BORDER_WIDTH = 1.5; + std::string CASE_BG_COLOR = "#52575c"; + std::string CASE_BORDER_COLOR = "#292a26"; /// block options float BLOCK_RADIUS = 0.3; - uint32_t BLOCK_BORDER_WIDTH = 1; - std::string BLOCK_BG_COLOR = "green"; - std::string BLOCK_BORDER_COLOR = "yellow"; + float BLOCK_BORDER_WIDTH = 0.8; + std::string BLOCK_BG_COLOR = "#C6840C"; + std::string BLOCK_BORDER_COLOR = "#f8f8f8"; // TODO: opacity options @@ -35,24 +29,22 @@ public: uint32_t block_gap; uint32_t block_width; + void render(SvgGraph &svg, const CaseSkin &skin) const; GraphCase(Point p, RawCode c, uint32_t gap, uint32_t width) : start(p), code(c) { block_gap = gap; block_width = width; } - - void render(SvgGraph &svg, const CaseSkin &skin) const; - }; class Graph { public: - uint64_t BLOCK_LENGTH = 12; - uint64_t BLOCK_GAP = 4; + uint64_t BLOCK_LENGTH = 10; + uint64_t BLOCK_GAP = 2; - uint64_t CASE_GAP_X = 12; - uint64_t CASE_GAP_Y = 20; + uint64_t CASE_GAP_X = 16; + uint64_t CASE_GAP_Y = 32; uint64_t CASE_WIDTH = BLOCK_LENGTH * 4 + BLOCK_GAP * 5; uint64_t CASE_HEIGHT = BLOCK_LENGTH * 5 + BLOCK_GAP * 6; diff --git a/src/graph/svg/svg.cc b/src/graph/svg/svg.cc index 0d8c450..aa0a323 100644 --- a/src/graph/svg/svg.cc +++ b/src/graph/svg/svg.cc @@ -1,7 +1,8 @@ #include "svg.h" -#include - +void SvgGraph::insert(SvgObject *obj) { + objects.emplace_back(obj); +} SvgGraph::~SvgGraph() { for (auto *object : objects) { @@ -9,11 +10,8 @@ SvgGraph::~SvgGraph() { } } -void SvgGraph::insert(SvgObject *obj) { - objects.emplace_back(obj); -} - std::string SvgLine::dump() const { + /// basic attributes of svg-line return ""; @@ -31,7 +29,7 @@ std::string SvgRect::dump() const { xml += "rx=\"" + std::to_string(radius) + "\" "; } /// style attribute of svg-rect - std::string style = "stroke-width:" + std::to_string(stroke) + ";"; + std::string style = "stroke-width:" + std::to_string(stroke).substr(0, 3) + ";"; if (!color.empty()) { style += "fill:" + color + ";"; } diff --git a/src/graph/svg/svg.h b/src/graph/svg/svg.h index 29c1c13..dc7c22e 100644 --- a/src/graph/svg/svg.h +++ b/src/graph/svg/svg.h @@ -4,32 +4,21 @@ #include #include +/// coordinate point class Point { public: uint64_t x; uint64_t y; }; +/// basic class of SVG element class SvgObject { public: virtual ~SvgObject() = default; virtual std::string dump() const = 0; }; -class SvgGraph { -public: - uint64_t width; - uint64_t height; - - ~SvgGraph(); - std::string dump() const; - void insert(SvgObject *obj); - SvgGraph(uint64_t w, uint64_t h) : width(w), height(h) {} - -private: - std::vector objects; -}; - +/// SVG line element class SvgLine : public SvgObject { public: Point start; @@ -43,14 +32,14 @@ public: // TODO: SvgLine(...) }; +/// SVG rectangle element class SvgRect : public SvgObject { public: Point start; uint64_t width; uint64_t height; - + float stroke = 0; uint64_t radius = 0; - uint32_t stroke = 0; std::string color; std::string line_color; @@ -62,3 +51,18 @@ public: std::string dump() const override; SvgRect(Point p, uint64_t w, uint64_t h) : start(p), width(w), height(h) {} }; + +/// SVG graph with multi element +class SvgGraph { +public: + uint64_t width; + uint64_t height; + + ~SvgGraph(); + std::string dump() const; + void insert(SvgObject *obj); + SvgGraph(uint64_t w, uint64_t h) : width(w), height(h) {} + +private: + std::vector objects; +};