diff --git a/bin/test/data/log/test_log.txt b/bin/test/data/log/test_log.txt index 5ef4bcdf..6d2c61d5 100644 --- a/bin/test/data/log/test_log.txt +++ b/bin/test/data/log/test_log.txt @@ -1,27 +1,4 @@ ConfigManager.cpp ERROR: value path/to/nowhere is not present in config. -Token.cpp ERROR: Location Id was not referenced by this Token. -Node.cpp WARNING: Cannot change NodeType after it was already set from namespace to class -Edge.cpp ERROR: Nodes are not plain copies. -Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined -Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined -Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined -Storage.cpp INFO: file: input.cc < 0:0 0:0> -Storage.cpp INFO: class: A -Storage.cpp INFO: method: A::A -Storage.cpp INFO: global usage: A::A -> A::count -Storage.cpp INFO: method: A::getCount -Storage.cpp INFO: global usage: A::getCount -> A::count -Storage.cpp INFO: method: A::process -Storage.cpp INFO: field: A::count -Storage.cpp INFO: class: B -Storage.cpp INFO: inheritance: B : A -Storage.cpp INFO: method: B::process -Storage.cpp INFO: override: A::process -> B::process < 0:0 0:0> -Storage.cpp INFO: type usage: B::process -> int -Storage.cpp INFO: function: main -Storage.cpp INFO: type usage: main -> B -Storage.cpp INFO: call: main -> B::B -Storage.cpp INFO: call: main -> A::getCount Storage.cpp INFO: file: input.cc < 0:0 0:0> Storage.cpp INFO: class: A Storage.cpp INFO: method: A::A @@ -56,6 +33,29 @@ SearchMatch.cpp INFO: 237 A::A ^^^^ +Storage.cpp INFO: file: input.cc < 0:0 0:0> +Storage.cpp INFO: class: A +Storage.cpp INFO: method: A::A +Storage.cpp INFO: global usage: A::A -> A::count +Storage.cpp INFO: method: A::getCount +Storage.cpp INFO: global usage: A::getCount -> A::count +Storage.cpp INFO: method: A::process +Storage.cpp INFO: field: A::count +Storage.cpp INFO: class: B +Storage.cpp INFO: inheritance: B : A +Storage.cpp INFO: method: B::process +Storage.cpp INFO: override: A::process -> B::process < 0:0 0:0> +Storage.cpp INFO: type usage: B::process -> int +Storage.cpp INFO: function: main +Storage.cpp INFO: type usage: main -> B +Storage.cpp INFO: call: main -> B::B +Storage.cpp INFO: call: main -> A::getCount +Token.cpp ERROR: Location Id was not referenced by this Token. +Node.cpp WARNING: Cannot change NodeType after it was already set from namespace to class +Edge.cpp ERROR: Nodes are not plain copies. +Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined +Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined +Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined Settings.cpp WARNING: File for Settings not found. ConfigManager.cpp ERROR: value Bool is not present in config. ConfigManager.cpp ERROR: value Int is not present in config. @@ -71,6 +71,7 @@ ConfigManager.cpp ERROR: value Int is not present in config. ConfigManager.cpp ERROR: value Float is not present in config. ConfigManager.cpp ERROR: value String is not present in config. ConfigManager.cpp ERROR: value NewBool is not present in config. +Graph.cpp ERROR: Can't remove member edge, without removing the child node. Storage.cpp INFO: typedef: type -> int Storage.cpp INFO: class: Class Storage.cpp INFO: struct: Struct @@ -135,7 +136,6 @@ Storage.cpp INFO: file: file.h < 0:0 0:0> Storage.cpp INFO: file: file.cpp < 0:0 0:0> Storage.cpp INFO: include: f.h Storage.cpp INFO: include: file.h -Graph.cpp ERROR: Can't remove member edge, without removing the child node. TextAccess.cpp WARNING: Index 'firstLine' has to be lower or equal index 'lastLine', is 3 > 2 TextAccess.cpp WARNING: Tried to access index 10. Maximum index is 8 TextAccess.cpp WARNING: Tried to access index 10. Maximum index is 8 diff --git a/src/app/main.cpp b/src/app/main.cpp index 43a5578c..a29c35c9 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -15,7 +15,9 @@ void init() std::shared_ptr consoleLogger = std::make_shared(); consoleLogger->setLogLevel(Logger::LOG_WARNINGS | Logger::LOG_ERRORS); LogManager::getInstance()->addLogger(consoleLogger); - LogManager::getInstance()->addLogger(std::make_shared()); + std::shared_ptr fileLogger = std::make_shared(); + fileLogger->setLogLevel(Logger::LOG_ALL); + LogManager::getInstance()->addLogger(fileLogger); utility::loadFontsFromDirectory("data/fonts", ".otf"); } diff --git a/src/app/qt/utility/QtGraphPostprocessor.cpp b/src/app/qt/utility/QtGraphPostprocessor.cpp index 6aa7a7fa..af0a01ac 100644 --- a/src/app/qt/utility/QtGraphPostprocessor.cpp +++ b/src/app/qt/utility/QtGraphPostprocessor.cpp @@ -1,5 +1,6 @@ #include "QtGraphPostprocessor.h" +// remark: maybe those two values could at some point be moved to an external config file (?) unsigned int QtGraphPostprocessor::s_cellSize = 20; unsigned int QtGraphPostprocessor::s_cellPadding = 10; @@ -9,7 +10,7 @@ void QtGraphPostprocessor::doPostprocessing(std::list>::iterator it = nodes.begin(); - for(; it != nodes.end(); it++) + for (; it != nodes.end(); it++) { - if((*it)->getSize().x < divisor) + if ((*it)->getSize().x < divisor) { divisor = (*it)->getSize().x; } - if((*it)->getSize().y < divisor) + if ((*it)->getSize().y < divisor) { divisor = (*it)->getSize().y; } - if((*it)->getSize().x > maxNodeSize) + if ((*it)->getSize().x > maxNodeSize) { maxNodeSize = (*it)->getSize().x; } - else if((*it)->getSize().y > maxNodeSize) + else if ((*it)->getSize().y > maxNodeSize) { maxNodeSize = (*it)->getSize().y; } @@ -49,14 +50,16 @@ void QtGraphPostprocessor::doPostprocessing(std::list heatMap = buildHeatMap(nodes, divisor, maxNodeSize); @@ -64,7 +67,7 @@ void QtGraphPostprocessor::doPostprocessing(std::listsetPosition(alignOnRaster(node->getPosition())); } @@ -73,18 +76,18 @@ Vec2i QtGraphPostprocessor::alignOnRaster(Vec2i position) { int rasterPosDivisor = s_cellSize + s_cellPadding; - if(position.x % rasterPosDivisor != 0) + if (position.x % rasterPosDivisor != 0) { int t = position.x / rasterPosDivisor; int r = position.x % rasterPosDivisor; - if(std::abs(r) > rasterPosDivisor/2) + if (std::abs(r) > rasterPosDivisor/2) { - if(t != 0) + if (t != 0) { t += (t / std::abs(t)); } - else if(r != 0) + else if (r != 0) { t += (r / std::abs(r)); } @@ -93,7 +96,7 @@ Vec2i QtGraphPostprocessor::alignOnRaster(Vec2i position) position.x = t * rasterPosDivisor; } - if(position.y % rasterPosDivisor != 0) + if (position.y % rasterPosDivisor != 0) { int t = position.y / rasterPosDivisor; int r = position.y % rasterPosDivisor; @@ -120,18 +123,18 @@ void QtGraphPostprocessor::resolveOutliers(std::list>::iterator it = nodes.begin(); - for(; it != nodes.end(); it++) + for (; it != nodes.end(); it++) { Vec2i pos = (*it)->getPosition(); Vec2i toCenterOfMass = centerPoint - pos; - if(toCenterOfMass.getLength() > maxDist) + if (toCenterOfMass.getLength() > maxDist) { maxDist = toCenterOfMass.getLength(); } } it = nodes.begin(); - for(; it != nodes.end(); it++) + for (; it != nodes.end(); it++) { Vec2i pos = (*it)->getPosition(); Vec2i toCenterOfMass = centerPoint - pos; @@ -145,7 +148,7 @@ void QtGraphPostprocessor::resolveOutliers(std::list QtGraphPostprocessor::buildHeatMap(const std::list>& nodes, const int atomarNodeSize, const int maxNodeSize) { - int heatMapWidth = maxNodeSize * nodes.size() / atomarNodeSize; + int heatMapWidth = (maxNodeSize * nodes.size() / atomarNodeSize) * 5; // theoretically the nodes could horizontally or vertically far from the center, therefore '*5' (it's kinda arbitrary, generally *2 should suffice, I use *5 to prevent problems in extrem cases) int heatMapHeight = heatMapWidth; MatrixDynamicBase heatMap(heatMapWidth, heatMapHeight); @@ -155,18 +158,23 @@ MatrixDynamicBase QtGraphPostprocessor::buildHeatMap(const std::li { int left = (*it)->getPosition().x / atomarNodeSize + heatMapWidth/2; int up = (*it)->getPosition().y / atomarNodeSize + heatMapHeight/2; - int width = (*it)->getSize().x / atomarNodeSize; - int height = (*it)->getSize().y / atomarNodeSize; + Vec2i size = calculateRasterNodeSize(*it); + int width = size.x; + int height = size.y; - if(left + width > heatMapWidth || left < 0) - continue; - - if(up + height > heatMapHeight || up < 0) - continue; - - for(int i = 0; i < width; i++) + if (left + width > heatMapWidth || left < 0) { - for(int j = 0; j < height; j++) + continue; + } + + if (up + height > heatMapHeight || up < 0) + { + continue; + } + + for (int i = 0; i < width; i++) + { + for (int j = 0; j < height; j++) { unsigned int x = left + i; unsigned int y = up + j; @@ -187,46 +195,48 @@ void QtGraphPostprocessor::resolveOverlap(std::list bool overlap = true; int iterationCount = 0; - int maxIterations = 10; + int maxIterations = 15; - while(overlap && iterationCount < maxIterations) + while (overlap && iterationCount < maxIterations) { + LOG_WARNING_STREAM(<< iterationCount); + overlap = false; iterationCount++; std::list>::iterator it = nodes.begin(); - for(; it != nodes.end(); it++) + for (; it != nodes.end(); it++) { - Vec2i nodePos((*it)->getPosition().x / divisor + heatMapWidth/2, - (*it)->getPosition().y / divisor + heatMapHeight/2); - Vec2i nodeSize((*it)->getSize().x / divisor, - (*it)->getSize().y / divisor); + Vec2i nodePos(0, 0); + nodePos.x = (*it)->getPosition().x / divisor + heatMapWidth/2; + nodePos.y = (*it)->getPosition().y / divisor + heatMapHeight/2; + Vec2i nodeSize = calculateRasterNodeSize(*it); - if(nodePos.x + nodeSize.x > heatMapWidth || nodePos.x < 0) + if (nodePos.x + nodeSize.x > heatMapWidth || nodePos.x < 0) + { + LOG_WARNING("Leaving heatmap area in x"); continue; + } - if(nodePos.y + nodeSize.y > heatMapHeight || nodePos.y < 0) + if (nodePos.y + nodeSize.y > heatMapHeight || nodePos.y < 0) + { + LOG_WARNING("Leaving heatmap area in y"); continue; + } Vec2f grad(0.0f, 0.0f); - if(getHeatmapGradient(grad, heatMap, nodePos, nodeSize)) + if (getHeatmapGradient(grad, heatMap, nodePos, nodeSize)) { overlap = true; } // handle overlap with no gradient // e.g. when a node lies completely on top of another - // float gradLength = grad.getLength(); - - if(grad.getLengthSquared() <= 0.000001f) + if (grad.getLengthSquared() <= 0.000001f && overlap) { - int val = heatMap.getValue(nodePos.x, nodePos.y); - if(val > 1) - { - grad = (*it)->getPosition(); - grad.normalize(); - grad *= -1.0f; - } + grad = (*it)->getPosition(); + grad.normalize(); + grad *= -1.0f; } // remove node temporarily from heat map, it will be re-added at the new position later on @@ -239,29 +249,40 @@ void QtGraphPostprocessor::resolveOverlap(std::list int maxOffset = 2*divisor; // prevent the graph from "exploding" again... - if(xOffset > maxOffset) + if (xOffset > maxOffset) + { xOffset = maxOffset; - else if(xOffset < -maxOffset) + } + else if (xOffset < -maxOffset) + { xOffset = -maxOffset; + } - if(yOffset > maxOffset) + if (yOffset > maxOffset) + { yOffset = maxOffset; - else if(yOffset < -maxOffset) + } + else if (yOffset < -maxOffset) + { yOffset = -maxOffset; + } Vec2i pos = (*it)->getPosition(); pos += Vec2i(xOffset, yOffset); - // grid allignment - // pos.x = (pos.x / divisor) * divisor; - // pos.y = (pos.y / divisor) * divisor; (*it)->setPosition(pos); - allignNodeOnRaster((*it).get()); + alignNodeOnRaster((*it).get()); // re-add node to heat map at new position nodePos.x = (*it)->getPosition().x / divisor + heatMapWidth/2; nodePos.y = (*it)->getPosition().y / divisor + heatMapHeight/2; + modifyHeatmapArea(heatMap, nodePos, nodeSize, 1); + + if(getHeatmapGradient(grad, heatMap, nodePos, nodeSize)) + { + overlap = true; + } } } } @@ -270,19 +291,19 @@ void QtGraphPostprocessor::modifyHeatmapArea(MatrixDynamicBase& he { bool wentOutOfRange = false; - for(int i = 0; i < size.x; i++) + for (int i = 0; i < size.x; i++) { - for(int j = 0; j < size.y; j++) + for (int j = 0; j < size.y; j++) { int x = leftUpperCorner.x + i; int y = leftUpperCorner.y + j; - if(x < 0 || x > static_cast(heatMap.getColumnsCount()-1)) + if (x < 0 || x > static_cast(heatMap.getColumnsCount()-1)) { wentOutOfRange = true; continue; } - if(y < 0 || y > static_cast(heatMap.getRowsCount()-1)) + if (y < 0 || y > static_cast(heatMap.getRowsCount()-1)) { wentOutOfRange = true; continue; @@ -291,7 +312,7 @@ void QtGraphPostprocessor::modifyHeatmapArea(MatrixDynamicBase& he unsigned int value = heatMap.getValue(x, y); heatMap.setValue(x, y, value+modifier); - if(wentOutOfRange == true) + if (wentOutOfRange == true) { LOG_WARNING("Left matrix range while trying to modify values."); } @@ -303,13 +324,17 @@ bool QtGraphPostprocessor::getHeatmapGradient(Vec2f& outGradient, const MatrixDy { bool overlap = false; - for(int i = 0; i < size.x; i++) + for (int i = 0; i < size.x; i++) { - for(int j = 0; j < size.y; j++) + for (int j = 0; j < size.y; j++) { int x = leftUpperCorner.x + i; int y = leftUpperCorner.y + j; + // weight factors that emphasize gradients near the nodes center + int hMagFactor = std::max(1, (int)(size.x*0.5 - std::abs(i+1 - size.x*0.5))); + int vMagFactor = std::max(1, (int)(size.y*0.5 - std::abs(j+1 - size.y*0.5))); + // if x and y lie directly at the border not all 4 neighbours can be checked if(x < 1 || x > static_cast(heatMap.getColumnsCount()-2)) continue; @@ -317,10 +342,11 @@ bool QtGraphPostprocessor::getHeatmapGradient(Vec2f& outGradient, const MatrixDy continue; float val = heatMap.getValue(x, y); - float xP1 = heatMap.getValue(x+1, y); - float xM1 = heatMap.getValue(x-1, y); - float yP1 = heatMap.getValue(x, y+1); - float yM1 = heatMap.getValue(x, y-1); + + float xP1 = heatMap.getValue(x+1, y) * hMagFactor; + float xM1 = heatMap.getValue(x-1, y) * hMagFactor; + float yP1 = heatMap.getValue(x, y+1) * vMagFactor; + float yM1 = heatMap.getValue(x, y-1) * vMagFactor; xP1 = std::sqrt(xP1); xM1 = std::sqrt(xM1); @@ -332,7 +358,7 @@ bool QtGraphPostprocessor::getHeatmapGradient(Vec2f& outGradient, const MatrixDy outGradient += Vec2f(xOffset, yOffset); - if(val > 1) + if (val > 1) { overlap = true; } @@ -342,10 +368,57 @@ bool QtGraphPostprocessor::getHeatmapGradient(Vec2f& outGradient, const MatrixDy return overlap; } +Vec2f QtGraphPostprocessor::heatMapRayCast(const MatrixDynamicBase& heatMap, const Vec2f& startPosition, const Vec2f& direction, const int minValue) +{ + float xOffset = 0.0f; + float yOffset = 0.0f; + + if(std::abs(direction.x) > 0.0000000001f) + { + xOffset = direction.x / std::abs(direction.x); + } + if(std::abs(direction.y) > 0.0000000001f) + { + yOffset = direction.y / std::abs(direction.y); + } + + if(startPosition.x < 1 || startPosition.x > static_cast(heatMap.getColumnsCount()-2)) + return Vec2f(0.0f, 0.0f); + if(startPosition.y < 1 || startPosition.y > static_cast(heatMap.getRowsCount()-2)) + return Vec2f(0.0f, 0.0f); + + Vec2f length(0.0f, 0.0f); + + bool hit = false; + + float posX = startPosition.x + xOffset; + float posY = startPosition.y + yOffset; + + do + { + if(heatMap.getValue(posX, posY) >= minValue) + { + hit = true; + length.x = length.x + xOffset; + length.y = length.y + yOffset; + + posX += xOffset; + posY += yOffset; + } + else + { + hit = false; + } + } + while(hit); + + return length; +} + void QtGraphPostprocessor::resizeNodes(std::list>& nodes) { std::list>::iterator it = nodes.begin(); - for(; it != nodes.end(); it++) + for (; it != nodes.end(); it++) { Vec2i size = (*it)->getSize(); @@ -363,22 +436,36 @@ void QtGraphPostprocessor::resizeNodes(std::list>& } size.y = newHeight; - /*if(size.x % atomarSize != 0) - { - int multiplier = size.x / atomarSize; - ++multiplier; - - size.x = atomarSize * multiplier; - } - - if(size.y % atomarSize != 0) - { - int multiplier = size.y / atomarSize; - ++multiplier; - - size.y = atomarSize * multiplier; - }*/ - (*it)->setSize(size); } } + +Vec2i QtGraphPostprocessor::calculateRasterNodeSize(const std::shared_ptr& node) +{ + Vec2i size = node->getSize(); + Vec2i rasterSize(0, 0); + + while(size.x > 0) + { + size.x = size.x - s_cellSize; + if(size.x > 0) + { + size.x = size.x - s_cellPadding; + } + + rasterSize.x = rasterSize.x + 1; + } + + while(size.y > 0) + { + size.y = size.y - s_cellSize; + if(size.y > 0) + { + size.y = size.y - s_cellPadding; + } + + rasterSize.y = rasterSize.y + 1; + } + + return rasterSize; +} diff --git a/src/app/qt/utility/QtGraphPostprocessor.h b/src/app/qt/utility/QtGraphPostprocessor.h index cc68660d..07983fed 100644 --- a/src/app/qt/utility/QtGraphPostprocessor.h +++ b/src/app/qt/utility/QtGraphPostprocessor.h @@ -13,7 +13,7 @@ class QtGraphPostprocessor public: static void doPostprocessing(std::list>& nodes); - static void allignNodeOnRaster(QtGraphNode* node); + static void alignNodeOnRaster(QtGraphNode* node); static Vec2i alignOnRaster(Vec2i position); private: @@ -25,7 +25,9 @@ private: static void resolveOverlap(std::list>& nodes, MatrixDynamicBase& heatMap, const int divisor); static void modifyHeatmapArea(MatrixDynamicBase& heatMap, const Vec2i& leftUpperCorner, const Vec2i& size, const int modifier); static bool getHeatmapGradient(Vec2f& outGradient, const MatrixDynamicBase& heatMap, const Vec2i& leftUpperCorner, const Vec2i& size); + static Vec2f heatMapRayCast(const MatrixDynamicBase& heatMap, const Vec2f& startPosition, const Vec2f& direction, const int minValue); static void resizeNodes(std::list>& nodes); + static Vec2i calculateRasterNodeSize(const std::shared_ptr& node); }; #endif // QT_GRAPH_POSTPROCESSOR_H diff --git a/src/app/qt/view/graphElements/nodeComponents/QtGraphNodeComponentMoveable.cpp b/src/app/qt/view/graphElements/nodeComponents/QtGraphNodeComponentMoveable.cpp index f3109da4..08a4f6b6 100644 --- a/src/app/qt/view/graphElements/nodeComponents/QtGraphNodeComponentMoveable.cpp +++ b/src/app/qt/view/graphElements/nodeComponents/QtGraphNodeComponentMoveable.cpp @@ -47,6 +47,6 @@ void QtGraphNodeComponentMoveable::nodeMouseReleaseEvent(QGraphicsSceneMouseEven std::shared_ptr node = m_graphNode.lock(); if (node != NULL) { - QtGraphPostprocessor::allignNodeOnRaster(node.get()); + QtGraphPostprocessor::alignNodeOnRaster(node.get()); } }