From c02f3dd80b6b1d2633f2f583bf50fdda1090aec1 Mon Sep 17 00:00:00 2001 From: Arthur Sonzogni Date: Sun, 18 Mar 2018 15:51:42 +0100 Subject: [PATCH] Add Planar graph [WIP] --- src/CMakeLists.txt | 4 +- src/boost | 1 + src/environment.h | 2 + src/index.html | 68 ++-- src/tools.json | 66 ++++ src/translator/planar_graph/CMakeLists.txt | 14 + src/translator/planar_graph/PlanarGraph.cpp | 345 ++++++++++++++++++-- src/translator/planar_graph/PlanarGraph.h | 39 ++- 8 files changed, 474 insertions(+), 65 deletions(-) create mode 120000 src/boost create mode 100644 src/environment.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5b3d1b5..76c6eb6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -34,13 +34,13 @@ if (Web) # Emscripten options string(APPEND CMAKE_CXX_FLAGS " -Os") - string(APPEND CMAKE_CXX_FLAGS " -Os") string(APPEND CMAKE_CXX_FLAGS " -s WASM=1") + string(APPEND CMAKE_CXX_FLAGS " -s DEMANGLE_SUPPORT=1") string(APPEND CMAKE_CXX_FLAGS " --js-opts 3") string(APPEND CMAKE_CXX_FLAGS " --llvm-lto 3") string(APPEND CMAKE_CXX_FLAGS " --llvm-opts 3") - string(APPEND CMAKE_CXX_FLAGS " -s ASSERTIONS=0") + string(APPEND CMAKE_CXX_FLAGS " -s ASSERTIONS=2") string(APPEND CMAKE_CXX_FLAGS " --closure 1") string(APPEND CMAKE_CXX_FLAGS " --no-heap-copy") string(APPEND CMAKE_CXX_FLAGS " -s EXPORTED_FUNCTIONS='[\"_translate\"]'") diff --git a/src/boost b/src/boost new file mode 120000 index 0000000..2d6e0ad --- /dev/null +++ b/src/boost @@ -0,0 +1 @@ +/usr/include/boost \ No newline at end of file diff --git a/src/environment.h b/src/environment.h new file mode 100644 index 0000000..3de85e0 --- /dev/null +++ b/src/environment.h @@ -0,0 +1,2 @@ +const char* test_directory = "/home/sonzogna/programmation/real/Diagon/src/test"; +const char* git_version = "21"; diff --git a/src/index.html b/src/index.html index 5c3a7ec..a0b6a70 100644 --- a/src/index.html +++ b/src/index.html @@ -60,7 +60,7 @@
- + @@ -77,23 +77,6 @@ let errors = document.getElementById('errors'); let tools_data = []; errors.value = ''; -function print(text) { - if (arguments.length > 1) - text = Array.prototype.slice.call(arguments).join(' '); - errors.value += text + '\n'; -}; - -window.Module = { - preRun: [], - postRun: [], - print: print, - printErr: print, - canvas: undefined, -}; - - - - + diff --git a/src/tools.json b/src/tools.json index 47fa6db..0adf49e 100644 --- a/src/tools.json +++ b/src/tools.json @@ -58,6 +58,7 @@ } ] }, + { "tool": "PlanarGraph", "description": "Planar graph", @@ -65,6 +66,71 @@ { "title": "------------------------", "empty": true + }, + { + "title":"if then else loop", + "content": [ + "if -> \"then A\" -> end", + "if -> \"then B\" -> end", + "end -> loop -> if" + ] + }, + { + "title":"test", + "content": [ + "A -- B", + "A -- C", + "A -- D -- G", + "B -- Z", + "C -- Z" + ] + }, + { + "title": "Big graph", + "content": [ + "a -- b", + "a -- c", + "a -- d", + "b -- c", + "b -- e", + "c -- e", + "c -- f", + "d -- f", + "d -- g", + "e -- h", + "f -- h", + "f -- i", + "f -- j", + "f -- g", + "g -- k", + "h -- o", + "h -- l", + "i -- l", + "i -- m", + "i -- j", + "j -- m", + "j -- n", + "j -- k", + "k -- n", + "k -- r", + "l -- o", + "l -- m", + "m -- o", + "m -- p", + "m -- n", + "n -- q", + "n -- r", + "o -- s", + "o -- p", + "p -- s", + "p -- t", + "p -- q", + "q -- t", + "q -- r", + "r -- t", + "s -- z", + "t -- z" + ] } ] }, diff --git a/src/translator/planar_graph/CMakeLists.txt b/src/translator/planar_graph/CMakeLists.txt index 0810614..50d1929 100644 --- a/src/translator/planar_graph/CMakeLists.txt +++ b/src/translator/planar_graph/CMakeLists.txt @@ -1,5 +1,19 @@ ANTLR(PlanarGraph.g4) +set(Boost_USE_STATIC_LIBS ON) +set(Boost_USE_MULTITHREADED OFF) +set(Boost_USE_STATIC_RUNTIME ON) +#find_package(Boost) +#include_directories(${Boost_INCLUDE_DIRS}/boost/graph) +#include_directories(${Boost_INCLUDE_DIRS}) +#message(STATUS ${Boost_INCLUDE_DIRS}) + + +get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES) +foreach(dir ${dirs}) + message(STATUS "dir='${dir}'") +endforeach() + add_library(translator_planar_graph STATIC PlanarGraphLexer.cpp PlanarGraphParser.cpp diff --git a/src/translator/planar_graph/PlanarGraph.cpp b/src/translator/planar_graph/PlanarGraph.cpp index 6e09202..1c150a8 100644 --- a/src/translator/planar_graph/PlanarGraph.cpp +++ b/src/translator/planar_graph/PlanarGraph.cpp @@ -1,4 +1,5 @@ #include +#include #include #include "screen/Screen.h" @@ -6,10 +7,79 @@ #include "translator/planar_graph/PlanarGraphLexer.h" #include "translator/planar_graph/PlanarGraphParser.h" +// With emscripten, you may need to execute in the src directory. +// # ln -s /usr/include/boost/ boost +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using Graph = boost::adjacency_list, + boost::property>; + +using Embedding = + std::vector::edge_descriptor>>; + +using Coordinates = struct { + size_t x; + size_t y; +}; + +using StraightLineDrawing = std::vector; + std::unique_ptr PlanarGraphTranslator() { return std::make_unique(); } +struct PlanarGraph::DrawnEdge { + int x; + int vertex_up; + int vertex_down; + int y_up; + int y_down; + void Draw(Screen& screen, PlanarGraph& graph) { + if (graph.arrow_style[vertex_up][vertex_down] == ArrowStyle::NONE) + return; + + int top = 3 * y_up - 1; + int bottom = 3 * y_down + 3; + + screen.DrawVerticalLine(top + 1, bottom - 1, x); + + if (graph.arrow_style[vertex_down][vertex_up] == ArrowStyle::LINE) + screen.DrawPixel(x, top, U'┬'); + else + screen.DrawPixel(x, top, U'△'); + + if (graph.arrow_style[vertex_up][vertex_down] == ArrowStyle::LINE) + screen.DrawPixel(x, bottom, U'┴'); + else + screen.DrawPixel(x, bottom, U'▽'); + } +}; + +struct PlanarGraph::DrawnVertex { + int left; + int right; + int y; + std::wstring text; + void Draw(Screen& screen) { + screen.DrawBox(left, 3 * y, right - left + 1, 3); + int text_position = left + 1 + (right - left - 1 - text.size()) / 2; + screen.DrawText(text_position, 3 * y + 1, text); + } + std::vector edges; +}; + void PlanarGraph::Process(const std::string& input) { Read(input); Write(); @@ -23,13 +93,6 @@ void PlanarGraph::Read(const std::string& input) { antlr4::CommonTokenStream tokens(&lexer); tokens.fill(); - // for (auto token : tokens.getTokens()) { - // std::cout << token->toString() << std::endl; - //} - - // Parser. - //output_ = parser.graph()->toStringTree(&parser); - PlanarGraphParser parser(&tokens); ReadGraph(parser.graph()); } @@ -49,8 +112,8 @@ void PlanarGraph::ReadEdges(PlanarGraphParser::EdgesContext* edges) { for (PlanarGraphParser::ArrowContext* arrow : edges->arrow()) { arrows.push_back(ReadArrow(arrow)); } - for(int i = 0; iRIGHT_ARROW()) return Arrow::RIGHT; if (arrow->NONE_ARROW()) @@ -91,23 +154,257 @@ PlanarGraph::Arrow PlanarGraph::ReadArrow(PlanarGraphParser::ArrowContext * } std::wstring PlanarGraph::ArrowToString(PlanarGraph::Arrow arrow) { - switch(arrow) { - case Arrow::RIGHT: return L"->"; - case Arrow::NONE: return L"--"; - case Arrow::LEFT_RIGHT: return L"<->"; - case Arrow::LEFT: return L"<-"; + switch (arrow) { + case Arrow::RIGHT: + return L"->"; + case Arrow::NONE: + return L"--"; + case Arrow::LEFT_RIGHT: + return L"<->"; + case Arrow::LEFT: + return L"<-"; } } +void InitializeEdgeIndex(Graph& graph) { + boost::property_map::type e_index = + boost::get(boost::edge_index, graph); + boost::graph_traits::edges_size_type edge_count = 0; + boost::graph_traits::edge_iterator ei, ei_end; + for (boost::tie(ei, ei_end) = boost::edges(graph); ei != ei_end; ++ei) + boost::put(e_index, *ei, edge_count++); +} + +void Print(Graph& graph) { + std::cout << "-----" << std::endl; + auto edges = boost::edges(graph); + for (auto edge = edges.first; edge != edges.second; ++edge) { + std::cout << boost::source(*edge, graph) << "->" << boost::target(*edge, graph) << std::endl; + } + std::cout << "-----" << std::endl; +} + +bool ComputePlanarEmbedding(const Graph& graph, Embedding& embedding) { + embedding = Embedding(boost::num_vertices(graph)); + return boost::boyer_myrvold_planarity_test( + boost::boyer_myrvold_params::graph = graph, + boost::boyer_myrvold_params::embedding = embedding.data()); +} + void PlanarGraph::Write() { - int width = 30; - int height = 30; - Screen screen(width, height); - int y = 0; - for(int i = 0; i DrawNode = [&](int i) -> void { + if (is_drawn[i]) + return; + DrawnVertex& vertex = drawn_vertices[i]; + int child_left = -1; + int child_right = -1; + // Draw our childrens. + for (auto j : down_children[i]) { + DrawNode(j); + + auto& child = drawn_vertices[j]; + DrawnEdge edge; + edge.vertex_up = i; + edge.vertex_down = j; + edge.y_up = y[i] + 1; + edge.y_down = y[j] - 1; + + // Make the child bigger if we need to. + child.right = std::max(child.right, x[y[j]-1]+3); + x[y[j]] = child.right; + refresh_x(y[j]); + + edge.x = child.left + 1; + edge.x = std::max(edge.x, x[y[i]] + 2); + if (y[j] != y[i] + 1) { + edge.x = std::max(edge.x, x[child.y - 1] + 1); + } + vertex.edges.push_back(edge); + + x[y[i]+1] = std::max(x[y[i]+1], edge.x); + refresh_x(y[i]+1); + + if (child_left == -1) { + child_left = edge.x - 1; + } + child_right = edge.x + 1; + + } + + // Draw ourself. + vertex.text = id_to_name[i]; + vertex.y = y[i]; + vertex.left = std::max(0, std::max(child_left, x[y[i]] + 1)); + vertex.right = + std::max(child_right, (int)(vertex.left + vertex.text.size() + 1)); + x[y[i]] = vertex.right; + refresh_x(y[i]); + + // Mark ourself as drawn. + is_drawn[i] = true; + }; + for (int i : ordering) { + if (y[i] == 0) { + DrawNode(i); + } + } + Draw(); } diff --git a/src/translator/planar_graph/PlanarGraph.h b/src/translator/planar_graph/PlanarGraph.h index fb18d95..e79c7b8 100644 --- a/src/translator/planar_graph/PlanarGraph.h +++ b/src/translator/planar_graph/PlanarGraph.h @@ -8,6 +8,15 @@ #include "translator/Translator.h" #include "translator/planar_graph/PlanarGraphParser.h" +struct Box { + int left; + int right; + int top; + int bottom; + static Box Union(Box A, Box B); + static Box Translate(Box A, int x, int y); +}; + class PlanarGraph : public Translator { public: virtual ~PlanarGraph() = default; @@ -16,6 +25,12 @@ class PlanarGraph : public Translator { //---------------------------------------------------------------------------- private: + std::string output_; + + std::map name_to_id; + std::vector id_to_name; + int next_id = 0; + enum class Arrow { RIGHT, LEFT_RIGHT, @@ -23,19 +38,27 @@ class PlanarGraph : public Translator { LEFT, }; - - struct Vertex { + struct Edge { int from; int to; Arrow arrow; }; + std::vector vertex; - std::vector vertex; - std::map name_to_id; - std::vector id_to_name; - int next_id = 0; + enum class ArrowStyle { + NONE, + LINE, + ARROW + }; + std::map> arrow_style; - std::string output_; + struct DrawnEdge; + struct DrawnVertex; + + struct Node { + int id; + std::vector childs; + }; //---------------------------------------------------------------------------- void Read(const std::string& input); @@ -45,6 +68,8 @@ class PlanarGraph : public Translator { Arrow ReadArrow(PlanarGraphParser::ArrowContext* arrow); void Write(); std::wstring ArrowToString(Arrow arrow); + std::vector> ConnectedComponent( + const std::vector& vertex); //---------------------------------------------------------------------------- };