From 35867c17afc206e8b8c38c5807eeaa7f2da1a5ec Mon Sep 17 00:00:00 2001 From: Manuel Date: Tue, 17 Feb 2015 23:40:53 -0800 Subject: [PATCH] ui: graph rastering Graph nodes are now placed within a raster. This is true for initial layout as well as drag-and-droped stuff. --- src/app/qt/utility/QtGraphPostprocessor.cpp | 111 +++++++++++++++--- src/app/qt/utility/QtGraphPostprocessor.h | 7 +- src/app/qt/view/graphElements/QtGraphNode.cpp | 3 + 3 files changed, 104 insertions(+), 17 deletions(-) diff --git a/src/app/qt/utility/QtGraphPostprocessor.cpp b/src/app/qt/utility/QtGraphPostprocessor.cpp index b914b777..9228b786 100644 --- a/src/app/qt/utility/QtGraphPostprocessor.cpp +++ b/src/app/qt/utility/QtGraphPostprocessor.cpp @@ -1,10 +1,13 @@ #include "QtGraphPostprocessor.h" +unsigned int QtGraphPostprocessor::s_cellSize = 20; +unsigned int QtGraphPostprocessor::s_cellPadding = 10; + void QtGraphPostprocessor::doPostprocessing(std::list>& nodes) { - unsigned int atomarGridSize = 20; + unsigned int atomarGridSize = s_cellSize; - resizeNodes(nodes, atomarGridSize); + resizeNodes(nodes); if(nodes.size() < 2) { @@ -50,10 +53,66 @@ void QtGraphPostprocessor::doPostprocessing(std::list heatMap = buildHeatMap(nodes, divisor, maxNodeSize); + resolveOverlap(nodes, heatMap, divisor); } +void QtGraphPostprocessor::allignNodeOnRaster(QtGraphNode* node) +{ + Vec2i position = node->getPosition(); + + int rasterPosDivisor = s_cellSize + s_cellPadding; + + if(position.x % rasterPosDivisor != 0) + { + int t = position.x / rasterPosDivisor; + int r = position.x % rasterPosDivisor; + + if(std::abs(r) > rasterPosDivisor/2) + { + if(t != 0) + { + t += (t / std::abs(t)); + } + else if(r != 0) + { + t += (r / std::abs(r)); + } + } + + position.x = t * rasterPosDivisor; + } + + if(position.y % rasterPosDivisor != 0) + { + int t = position.y / rasterPosDivisor; + int r = position.y % rasterPosDivisor; + + if (std::abs(r) > rasterPosDivisor/2) + { + if(t != 0) + { + t += (t / std::abs(t)); + } + else if(r != 0) + { + t += (r / std::abs(r)); + } + } + + position.y = t * rasterPosDivisor; + } + + node->setPosition(position); +} + void QtGraphPostprocessor::resolveOutliers(std::list>& nodes, const Vec2i& centerPoint) { float maxDist = 0.0f; @@ -109,6 +168,7 @@ MatrixDynamicBase QtGraphPostprocessor::buildHeatMap(const std::li unsigned int x = left + i; unsigned int y = up + j; unsigned int value = heatMap.getValue(x, y); + heatMap.setValue(x, y, value+1); } } @@ -173,24 +233,28 @@ void QtGraphPostprocessor::resolveOverlap(std::list int xOffset = grad.x * divisor; int yOffset = grad.y * divisor; - // prevent the graph from "exploding" again... - if(xOffset > divisor) - xOffset = divisor; - else if(xOffset < -divisor) - xOffset = -divisor; - if(yOffset > divisor) - yOffset = divisor; - else if(yOffset < -divisor) - yOffset = -divisor; + int maxOffset = 2*divisor; + // prevent the graph from "exploding" again... + if(xOffset > maxOffset) + xOffset = maxOffset; + else if(xOffset < -maxOffset) + xOffset = -maxOffset; + + if(yOffset > maxOffset) + 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; + // pos.x = (pos.x / divisor) * divisor; + // pos.y = (pos.y / divisor) * divisor; (*it)->setPosition(pos); + allignNodeOnRaster((*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; @@ -275,13 +339,28 @@ bool QtGraphPostprocessor::getHeatmapGradient(Vec2f& outGradient, const MatrixDy return overlap; } -void QtGraphPostprocessor::resizeNodes(std::list>& nodes, const unsigned int atomarSize) +void QtGraphPostprocessor::resizeNodes(std::list>& nodes) { std::list>::iterator it = nodes.begin(); for(; it != nodes.end(); it++) { Vec2i size = (*it)->getSize(); - if(size.x % atomarSize != 0) + + int newWidth = s_cellSize; + while(size.x - newWidth > 0) + { + newWidth += s_cellPadding + s_cellSize; + } + size.x = newWidth; + + int newHeight = s_cellSize; + while(size.y - newHeight > 0) + { + newHeight += s_cellPadding + s_cellSize; + } + size.y = newHeight; + + /*if(size.x % atomarSize != 0) { int multiplier = size.x / atomarSize; ++multiplier; @@ -295,7 +374,7 @@ void QtGraphPostprocessor::resizeNodes(std::list>& ++multiplier; size.y = atomarSize * multiplier; - } + }*/ (*it)->setSize(size); } diff --git a/src/app/qt/utility/QtGraphPostprocessor.h b/src/app/qt/utility/QtGraphPostprocessor.h index 55cad55f..583d9a3a 100644 --- a/src/app/qt/utility/QtGraphPostprocessor.h +++ b/src/app/qt/utility/QtGraphPostprocessor.h @@ -13,13 +13,18 @@ class QtGraphPostprocessor public: static void doPostprocessing(std::list>& nodes); + static void allignNodeOnRaster(QtGraphNode* node); + private: + static unsigned int s_cellSize; + static unsigned int s_cellPadding; + static MatrixDynamicBase buildHeatMap(const std::list>& nodes, const int atomarNodeSize, const int maxNodeSize); static void resolveOutliers(std::list>& nodes, const Vec2i& centerPoint); 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 void resizeNodes(std::list>& nodes, const unsigned int atomarSize); + static void resizeNodes(std::list>& nodes); }; #endif // QT_GRAPH_POSTPROCESSOR_H diff --git a/src/app/qt/view/graphElements/QtGraphNode.cpp b/src/app/qt/view/graphElements/QtGraphNode.cpp index a760b9ba..e3ea95de 100644 --- a/src/app/qt/view/graphElements/QtGraphNode.cpp +++ b/src/app/qt/view/graphElements/QtGraphNode.cpp @@ -9,6 +9,7 @@ #include "qt/graphics/QtGraphicsRoundedRectItem.h" #include "qt/utility/QtDeviceScaledPixmap.h" +#include "qt/utility/QtGraphPostprocessor.h" #include "qt/view/graphElements/nodeComponents/QtGraphNodeComponent.h" #include "qt/view/graphElements/QtGraphEdge.h" @@ -467,6 +468,8 @@ void QtGraphNode::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) parent->mouseReleaseEvent(event); } } + + QtGraphPostprocessor::allignNodeOnRaster(this); } void QtGraphNode::hoverEnterEvent(QGraphicsSceneHoverEvent* event)