ui: fixed jumps in graph navigation

* moved graph postprocessing to GraphController to avoid reprocessing on edge activation
* animat sceneRect of the GraphView to avoid jump at end of animation
This commit is contained in:
Eberhard Graether
2015-06-09 22:51:09 +02:00
parent 0c41aecfc9
commit e85b9e7425
14 changed files with 178 additions and 128 deletions
-2
View File
@@ -40,8 +40,6 @@ add_files(
qt/graphics/QtStraightLineItem.h
qt/utility/QtDeviceScaledPixmap.h
qt/utility/QtGraphPostprocessor.cpp
qt/utility/QtGraphPostprocessor.h
qt/utility/QtHighlighter.cpp
qt/utility/QtHighlighter.h
qt/utility/QtThreadedFunctor.h
+38 -11
View File
@@ -6,12 +6,13 @@
#include <QGraphicsView>
#include <QPropertyAnimation>
#include <QParallelAnimationGroup>
#include <QScrollBar>
#include <QSequentialAnimationGroup>
#include "component/controller/helper/DummyEdge.h"
#include "component/controller/helper/DummyNode.h"
#include "component/controller/helper/GraphPostprocessor.h"
#include "qt/utility/QtGraphPostprocessor.h"
#include "qt/utility/utilityQt.h"
#include "qt/view/QtViewWidgetWrapper.h"
@@ -90,6 +91,17 @@ Vec2i QtGraphView::getViewSize() const
return Vec2i(view->width(), view->height());
}
void QtGraphView::centerScrollBars()
{
QGraphicsView* view = getView();
QScrollBar* hb = view->horizontalScrollBar();
QScrollBar* vb = view->verticalScrollBar();
hb->setValue((hb->minimum() + hb->maximum()) / 2);
vb->setValue((vb->minimum() + vb->maximum()) / 2);
}
void QtGraphView::finishedTransition()
{
for (const std::shared_ptr<QtGraphNode>& node : m_nodes)
@@ -170,10 +182,8 @@ void QtGraphView::doRebuildGraph(
}
}
QtGraphPostprocessor::doPostprocessing(m_nodes);
QPointF center = itemsBoundingRect(m_nodes).center();
Vec2i o = QtGraphPostprocessor::alignOnRaster(Vec2i(center.x(), center.y()));
Vec2i o = GraphPostprocessor::alignOnRaster(Vec2i(center.x(), center.y()));
QPointF offset = QPointF(o.x, o.y);
m_sceneRectOffset = offset - center;
@@ -214,9 +224,7 @@ void QtGraphView::doClear()
void QtGraphView::doResize()
{
int margin = 25;
QGraphicsView* view = getView();
view->setSceneRect(itemsBoundingRect(m_oldNodes).adjusted(-margin, -margin, margin, margin).translated(m_sceneRectOffset));
getView()->setSceneRect(getSceneRect(m_oldNodes));
}
std::shared_ptr<QtGraphNode> QtGraphView::findNodeRecursive(const std::list<std::shared_ptr<QtGraphNode>>& nodes, Id tokenId)
@@ -320,17 +328,21 @@ std::shared_ptr<QtGraphEdge> QtGraphView::createEdge(QGraphicsView* view, const
}
}
template <typename T>
QRectF QtGraphView::itemsBoundingRect(const std::list<std::shared_ptr<T>>& items) const
QRectF QtGraphView::itemsBoundingRect(const std::list<std::shared_ptr<QtGraphNode>>& items) const
{
QRectF boundingRect;
for (const std::shared_ptr<T>& item : items)
for (const std::shared_ptr<QtGraphNode>& item : items)
{
boundingRect |= item->sceneBoundingRect();
}
return boundingRect;
}
QRectF QtGraphView::getSceneRect(const std::list<std::shared_ptr<QtGraphNode>>& items) const
{
return itemsBoundingRect(items).adjusted(-25, -25, 25, 25).translated(m_sceneRectOffset);
}
void QtGraphView::compareNodesRecursive(
std::list<std::shared_ptr<QtGraphNode>> newSubNodes,
std::list<std::shared_ptr<QtGraphNode>> oldSubNodes,
@@ -429,7 +441,6 @@ void QtGraphView::createTransition()
}
// move and scale
if (remainingNodes.size())
{
QParallelAnimationGroup* remain = new QParallelAnimationGroup();
@@ -462,6 +473,22 @@ void QtGraphView::createTransition()
}
}
QPropertyAnimation* anim = new QPropertyAnimation(view, "sceneRect");
anim->setStartValue(view->sceneRect());
anim->setEndValue(getSceneRect(m_nodes));
if (remainingNodes.size())
{
anim->setDuration(300);
}
else
{
anim->setDuration(300);
connect(anim, SIGNAL(finished()), this, SLOT(centerScrollBars()));
}
remain->addAnimation(anim);
m_transition->addAnimation(remain);
}
+3 -2
View File
@@ -42,6 +42,7 @@ public:
virtual Vec2i getViewSize() const;
private slots:
void centerScrollBars();
void finishedTransition();
private:
@@ -61,8 +62,8 @@ private:
QGraphicsView* view, std::shared_ptr<QtGraphNode> parentNode, const DummyNode& node);
std::shared_ptr<QtGraphEdge> createEdge(QGraphicsView* view, const DummyEdge& edge);
template <typename T>
QRectF itemsBoundingRect(const std::list<std::shared_ptr<T>>& items) const;
QRectF itemsBoundingRect(const std::list<std::shared_ptr<QtGraphNode>>& items) const;
QRectF getSceneRect(const std::list<std::shared_ptr<QtGraphNode>>& items) const;
void compareNodesRecursive(
std::list<std::shared_ptr<QtGraphNode>> newSubNodes,
@@ -5,9 +5,10 @@
#include <QGraphicsSceneEvent>
#include <QPen>
#include "component/controller/helper/GraphPostprocessor.h"
#include "qt/graphics/QtRoundedRectItem.h"
#include "qt/utility/QtDeviceScaledPixmap.h"
#include "qt/utility/QtGraphPostprocessor.h"
#include "qt/view/graphElements/nodeComponents/QtGraphNodeComponent.h"
#include "qt/view/graphElements/QtGraphEdge.h"
@@ -250,9 +251,9 @@ void QtGraphNode::addSubNode(const std::shared_ptr<QtGraphNode>& node)
m_subNodes.push_back(node);
}
void QtGraphNode::moved()
void QtGraphNode::moved(const Vec2i& oldPosition)
{
QtGraphPostprocessor::alignNodeOnRaster(this);
setPosition(GraphPostprocessor::alignOnRaster(getPosition()));
}
void QtGraphNode::onClick()
+1 -1
View File
@@ -79,7 +79,7 @@ public:
virtual void addSubNode(const std::shared_ptr<QtGraphNode>& node);
virtual void onClick();
virtual void moved();
virtual void moved(const Vec2i& oldPosition);
virtual void updateStyle() = 0;
@@ -41,11 +41,11 @@ void QtGraphNodeData::onClick()
}
}
void QtGraphNodeData::moved()
void QtGraphNodeData::moved(const Vec2i& oldPosition)
{
QtGraphNode::moved();
QtGraphNode::moved(oldPosition);
MessageGraphNodeMove(m_data->getId(), getPosition()).dispatch();
MessageGraphNodeMove(m_data->getId(), getPosition() - oldPosition).dispatch();
}
void QtGraphNodeData::updateStyle()
@@ -18,7 +18,7 @@ public:
virtual Id getTokenId() const;
virtual void onClick();
virtual void moved();
virtual void moved(const Vec2i& oldPosition);
virtual void updateStyle();
protected:
@@ -19,8 +19,9 @@ void QtGraphNodeComponentMoveable::nodeMousePressEvent(QGraphicsSceneMouseEvent*
std::shared_ptr<QtGraphNode> node = m_graphNode.lock();
if (node != NULL)
{
m_mouseOffset.x = event->scenePos().x() - node->getPosition().x;
m_mouseOffset.y = event->scenePos().y() - node->getPosition().y;
m_oldPos = node->getPosition();
m_mouseOffset.x = event->scenePos().x() - m_oldPos.x;
m_mouseOffset.y = event->scenePos().y() - m_oldPos.y;
event->accept();
}
@@ -46,6 +47,6 @@ void QtGraphNodeComponentMoveable::nodeMouseReleaseEvent(QGraphicsSceneMouseEven
std::shared_ptr<QtGraphNode> node = m_graphNode.lock();
if (node != NULL)
{
node->moved();
node->moved(m_oldPos);
}
}
@@ -18,6 +18,7 @@ public:
private:
Vec2i m_mouseOffset;
Vec2i m_oldPos;
};
#endif // QT_GRAPH_NODE_COMPONENT_MOVEABLE
+2
View File
@@ -37,6 +37,8 @@ add_files(
component/controller/helper/DummyEdge.h
component/controller/helper/DummyNode.h
component/controller/helper/GraphPostprocessor.cpp
component/controller/helper/GraphPostprocessor.h
component/controller/helper/SnippetMerger.cpp
component/controller/helper/SnippetMerger.h
@@ -6,6 +6,7 @@
#include "component/controller/helper/DummyEdge.h"
#include "component/controller/helper/DummyNode.h"
#include "component/controller/helper/GraphPostprocessor.h"
#include "component/view/GraphView.h"
#include "component/view/GraphViewStyle.h"
#include "data/access/StorageAccess.h"
@@ -74,6 +75,8 @@ void GraphController::handleMessage(MessageGraphNodeExpand* message)
setActiveAndVisibility(m_activeTokenIds);
layoutNesting();
GraphPostprocessor::doPostprocessing(m_dummyNodes);
getView()->rebuildGraph(nullptr, m_dummyNodes, m_dummyEdges);
}
}
@@ -83,7 +86,7 @@ void GraphController::handleMessage(MessageGraphNodeMove* message)
DummyNode* node = findDummyNodeRecursive(m_dummyNodes, message->tokenId);
if (node)
{
node->position = message->position;
node->position += message->delta;
getView()->resizeView();
}
}
@@ -131,6 +134,7 @@ void GraphController::createDummyGraphForTokenIds(const std::vector<Id>& tokenId
layoutNesting();
GraphLayouter::layoutSpectralPrototype(m_dummyNodes, m_dummyEdges);
GraphPostprocessor::doPostprocessing(m_dummyNodes);
view->rebuildGraph(graph, m_dummyNodes, m_dummyEdges);
}
@@ -1,11 +1,11 @@
#include "QtGraphPostprocessor.h"
#include "component/controller/helper/GraphPostprocessor.h"
#include "component/view/GraphViewStyle.h"
unsigned int QtGraphPostprocessor::s_cellSize = GraphViewStyle::s_gridCellSize;
unsigned int QtGraphPostprocessor::s_cellPadding = GraphViewStyle::s_gridCellPadding;
unsigned int GraphPostprocessor::s_cellSize = GraphViewStyle::s_gridCellSize;
unsigned int GraphPostprocessor::s_cellPadding = GraphViewStyle::s_gridCellPadding;
void QtGraphPostprocessor::doPostprocessing(std::list<std::shared_ptr<QtGraphNode>>& nodes)
void GraphPostprocessor::doPostprocessing(std::vector<DummyNode>& nodes)
{
unsigned int atomarGridSize = s_cellSize;
@@ -20,30 +20,32 @@ void QtGraphPostprocessor::doPostprocessing(std::list<std::shared_ptr<QtGraphNod
int maxNodeSize = 0;
Vec2i centerOfMass(0, 0);
float totalMass = 0.0f;
std::list<std::shared_ptr<QtGraphNode>>::iterator it = nodes.begin();
for (; it != nodes.end(); it++)
for (const DummyNode& node : nodes)
{
if ((*it)->getSize().x < divisor)
const Vec2i& size = node.size;
if (size.x < divisor)
{
divisor = (*it)->getSize().x;
divisor = size.x;
}
if ((*it)->getSize().y < divisor)
if (size.y < divisor)
{
divisor = (*it)->getSize().y;
divisor = size.y;
}
if ((*it)->getSize().x > maxNodeSize)
if (size.x > maxNodeSize)
{
maxNodeSize = (*it)->getSize().x;
maxNodeSize = size.x;
}
else if ((*it)->getSize().y > maxNodeSize)
else if (size.y > maxNodeSize)
{
maxNodeSize = (*it)->getSize().y;
maxNodeSize = size.y;
}
float nodeMass = (*it)->getSize().getLengthSquared();
centerOfMass += (*it)->getPosition() * nodeMass;
float nodeMass = size.getLengthSquared();
centerOfMass += node.position * nodeMass;
totalMass += nodeMass;
}
@@ -55,10 +57,9 @@ void QtGraphPostprocessor::doPostprocessing(std::list<std::shared_ptr<QtGraphNod
// the nodes will be aligned everytime they move during post-processing
// align all nodes once here so that nodes that won't be moved again are aligned
it = nodes.begin();
for (; it != nodes.end(); it++)
for (DummyNode& node : nodes)
{
alignNodeOnRaster((*it).get());
alignNodeOnRaster(node);
}
MatrixDynamicBase<unsigned int> heatMap = buildHeatMap(nodes, divisor, maxNodeSize);
@@ -66,12 +67,12 @@ void QtGraphPostprocessor::doPostprocessing(std::list<std::shared_ptr<QtGraphNod
resolveOverlap(nodes, heatMap, divisor);
}
void QtGraphPostprocessor::alignNodeOnRaster(QtGraphNode* node)
void GraphPostprocessor::alignNodeOnRaster(DummyNode& node)
{
node->setPosition(alignOnRaster(node->getPosition()));
node.position = alignOnRaster(node.position);
}
Vec2i QtGraphPostprocessor::alignOnRaster(Vec2i position)
Vec2i GraphPostprocessor::alignOnRaster(Vec2i position)
{
int rasterPosDivisor = s_cellSize + s_cellPadding;
@@ -118,46 +119,50 @@ Vec2i QtGraphPostprocessor::alignOnRaster(Vec2i position)
return position;
}
void QtGraphPostprocessor::resolveOutliers(std::list<std::shared_ptr<QtGraphNode>>& nodes, const Vec2i& centerPoint)
void GraphPostprocessor::resolveOutliers(std::vector<DummyNode>& nodes, const Vec2i& centerPoint)
{
float maxDist = 0.0f;
std::list<std::shared_ptr<QtGraphNode>>::iterator it = nodes.begin();
for (; it != nodes.end(); it++)
for (const DummyNode& node : nodes)
{
Vec2i pos = (*it)->getPosition();
Vec2i toCenterOfMass = centerPoint - pos;
Vec2i toCenterOfMass = centerPoint - node.position;
if (toCenterOfMass.getLength() > maxDist)
{
maxDist = toCenterOfMass.getLength();
}
}
it = nodes.begin();
for (; it != nodes.end(); it++)
if (maxDist == 0.0f)
{
Vec2i pos = (*it)->getPosition();
Vec2i toCenterOfMass = centerPoint - pos;
return;
}
for (DummyNode& node : nodes)
{
Vec2i toCenterOfMass = centerPoint - node.position;
float dist = toCenterOfMass.getLength();
float distFactor = std::sqrt(dist/maxDist); // causes far away nodes to be effected stronger than nodes that are already close to the center
(*it)->setPosition(pos + toCenterOfMass * distFactor);
// causes far away nodes to be effected stronger than nodes that are already close to the center
float distFactor = std::sqrt(dist / maxDist);
node.position += toCenterOfMass * distFactor;
}
}
MatrixDynamicBase<unsigned int> QtGraphPostprocessor::buildHeatMap(const std::list<std::shared_ptr<QtGraphNode>>& nodes, const int atomarNodeSize, const int maxNodeSize)
{
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)
MatrixDynamicBase<unsigned int> GraphPostprocessor::buildHeatMap(
const std::vector<DummyNode>& nodes, const int atomarNodeSize, const int maxNodeSize
){
// 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 heatMapWidth = (maxNodeSize * nodes.size() / atomarNodeSize) * 5;
int heatMapHeight = heatMapWidth;
MatrixDynamicBase<unsigned int> heatMap(heatMapWidth, heatMapHeight);
std::list<std::shared_ptr<QtGraphNode>>::const_iterator it = nodes.cbegin();
for(; it != nodes.end(); it++)
for (const DummyNode& node : nodes)
{
int left = (*it)->getPosition().x / atomarNodeSize + heatMapWidth/2;
int up = (*it)->getPosition().y / atomarNodeSize + heatMapHeight/2;
Vec2i size = calculateRasterNodeSize(*it);
int left = node.position.x / atomarNodeSize + heatMapWidth / 2;
int up = node.position.y / atomarNodeSize + heatMapHeight / 2;
Vec2i size = calculateRasterNodeSize(node);
int width = size.x;
int height = size.y;
@@ -187,8 +192,9 @@ MatrixDynamicBase<unsigned int> QtGraphPostprocessor::buildHeatMap(const std::li
return heatMap;
}
void QtGraphPostprocessor::resolveOverlap(std::list<std::shared_ptr<QtGraphNode>>& nodes, MatrixDynamicBase<unsigned int>& heatMap, const int divisor)
{
void GraphPostprocessor::resolveOverlap(
std::vector<DummyNode>& nodes, MatrixDynamicBase<unsigned int>& heatMap, const int divisor
){
int heatMapWidth = heatMap.getColumnsCount();
int heatMapHeight = heatMap.getRowsCount();
@@ -203,13 +209,12 @@ void QtGraphPostprocessor::resolveOverlap(std::list<std::shared_ptr<QtGraphNode>
overlap = false;
iterationCount++;
std::list<std::shared_ptr<QtGraphNode>>::iterator it = nodes.begin();
for (; it != nodes.end(); it++)
for (DummyNode& node : nodes)
{
Vec2i nodePos(0, 0);
nodePos.x = (*it)->getPosition().x / divisor + heatMapWidth/2;
nodePos.y = (*it)->getPosition().y / divisor + heatMapHeight/2;
Vec2i nodeSize = calculateRasterNodeSize(*it);
Vec2i nodePos;
nodePos.x = node.position.x / divisor + heatMapWidth / 2;
nodePos.y = node.position.y / divisor + heatMapHeight / 2;
Vec2i nodeSize = calculateRasterNodeSize(node);
if (nodePos.x + nodeSize.x > heatMapWidth || nodePos.x < 0)
{
@@ -233,11 +238,11 @@ void QtGraphPostprocessor::resolveOverlap(std::list<std::shared_ptr<QtGraphNode>
// e.g. when a node lies completely on top of another
if (grad.getLengthSquared() <= 0.000001f && overlap)
{
grad = (*it)->getPosition();
grad = node.position;
grad.normalize();
// catch special case of node being at position 0/0
if(grad.getLengthSquared() <= 0.000001f)
if (grad.getLengthSquared() <= 0.000001f)
{
grad.y = 1.0f;
}
@@ -253,7 +258,7 @@ void QtGraphPostprocessor::resolveOverlap(std::list<std::shared_ptr<QtGraphNode>
int yOffset = grad.y * divisor;
int maxOffset = 2*divisor;
int maxOffset = 2 * divisor;
// prevent the graph from "exploding" again...
if (xOffset > maxOffset)
{
@@ -273,19 +278,17 @@ void QtGraphPostprocessor::resolveOverlap(std::list<std::shared_ptr<QtGraphNode>
yOffset = -maxOffset;
}
Vec2i pos = (*it)->getPosition();
pos += Vec2i(xOffset, yOffset);
(*it)->setPosition(pos);
node.position += Vec2i(xOffset, yOffset);
alignNodeOnRaster((*it).get());
alignNodeOnRaster(node);
// 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;
nodePos.x = node.position.x / divisor + heatMapWidth / 2;
nodePos.y = node.position.y / divisor + heatMapHeight / 2;
modifyHeatmapArea(heatMap, nodePos, nodeSize, 1);
if(getHeatmapGradient(grad, heatMap, nodePos, nodeSize))
if (getHeatmapGradient(grad, heatMap, nodePos, nodeSize))
{
overlap = true;
}
@@ -293,8 +296,9 @@ void QtGraphPostprocessor::resolveOverlap(std::list<std::shared_ptr<QtGraphNode>
}
}
void QtGraphPostprocessor::modifyHeatmapArea(MatrixDynamicBase<unsigned int>& heatMap, const Vec2i& leftUpperCorner, const Vec2i& size, const int modifier)
{
void GraphPostprocessor::modifyHeatmapArea(
MatrixDynamicBase<unsigned int>& heatMap, const Vec2i& leftUpperCorner, const Vec2i& size, const int modifier
){
bool wentOutOfRange = false;
for (int i = 0; i < size.x; i++)
@@ -326,8 +330,9 @@ void QtGraphPostprocessor::modifyHeatmapArea(MatrixDynamicBase<unsigned int>& he
}
}
bool QtGraphPostprocessor::getHeatmapGradient(Vec2f& outGradient, const MatrixDynamicBase<unsigned int>& heatMap, const Vec2i& leftUpperCorner, const Vec2i& size)
{
bool GraphPostprocessor::getHeatmapGradient(
Vec2f& outGradient, const MatrixDynamicBase<unsigned int>& heatMap, const Vec2i& leftUpperCorner, const Vec2i& size
){
bool overlap = false;
for (int i = 0; i < size.x; i++)
@@ -338,21 +343,25 @@ bool QtGraphPostprocessor::getHeatmapGradient(Vec2f& outGradient, const MatrixDy
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)));
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<int>(heatMap.getColumnsCount()-2))
if (x < 1 || x > static_cast<int>(heatMap.getColumnsCount() - 2))
{
continue;
if(y < 1 || y > static_cast<int>(heatMap.getRowsCount()-2))
}
if (y < 1 || y > static_cast<int>(heatMap.getRowsCount() - 2))
{
continue;
}
float val = heatMap.getValue(x, y);
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;
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);
@@ -374,24 +383,29 @@ bool QtGraphPostprocessor::getHeatmapGradient(Vec2f& outGradient, const MatrixDy
return overlap;
}
Vec2f QtGraphPostprocessor::heatMapRayCast(const MatrixDynamicBase<unsigned int>& heatMap, const Vec2f& startPosition, const Vec2f& direction, unsigned int minValue)
{
Vec2f GraphPostprocessor::heatMapRayCast(
const MatrixDynamicBase<unsigned int>& heatMap, const Vec2f& startPosition, const Vec2f& direction, unsigned int minValue
){
float xOffset = 0.0f;
float yOffset = 0.0f;
if(std::abs(direction.x) > 0.0000000001f)
if (std::abs(direction.x) > 0.0000000001f)
{
xOffset = direction.x / std::abs(direction.x);
}
if(std::abs(direction.y) > 0.0000000001f)
if (std::abs(direction.y) > 0.0000000001f)
{
yOffset = direction.y / std::abs(direction.y);
}
if(startPosition.x < 1 || startPosition.x > static_cast<int>(heatMap.getColumnsCount()-2))
if (startPosition.x < 1 || startPosition.x > static_cast<int>(heatMap.getColumnsCount() - 2))
{
return Vec2f(0.0f, 0.0f);
if(startPosition.y < 1 || startPosition.y > static_cast<int>(heatMap.getRowsCount()-2))
}
if (startPosition.y < 1 || startPosition.y > static_cast<int>(heatMap.getRowsCount() - 2))
{
return Vec2f(0.0f, 0.0f);
}
Vec2f length(0.0f, 0.0f);
@@ -402,7 +416,7 @@ Vec2f QtGraphPostprocessor::heatMapRayCast(const MatrixDynamicBase<unsigned int>
do
{
if(heatMap.getValue(posX, posY) >= minValue)
if (heatMap.getValue(posX, posY) >= minValue)
{
hit = true;
length.x = length.x + xOffset;
@@ -416,20 +430,20 @@ Vec2f QtGraphPostprocessor::heatMapRayCast(const MatrixDynamicBase<unsigned int>
hit = false;
}
}
while(hit);
while (hit);
return length;
}
Vec2i QtGraphPostprocessor::calculateRasterNodeSize(const std::shared_ptr<QtGraphNode>& node)
Vec2i GraphPostprocessor::calculateRasterNodeSize(const DummyNode& node)
{
Vec2i size = node->getSize();
Vec2i size = node.size;
Vec2i rasterSize(0, 0);
while(size.x > 0)
while (size.x > 0)
{
size.x = size.x - s_cellSize;
if(size.x > 0)
if (size.x > 0)
{
size.x = size.x - s_cellPadding;
}
@@ -437,10 +451,10 @@ Vec2i QtGraphPostprocessor::calculateRasterNodeSize(const std::shared_ptr<QtGrap
rasterSize.x = rasterSize.x + 1;
}
while(size.y > 0)
while (size.y > 0)
{
size.y = size.y - s_cellSize;
if(size.y > 0)
if (size.y > 0)
{
size.y = size.y - s_cellPadding;
}
@@ -1,32 +1,32 @@
#ifndef QT_GRAPH_POSTPROCESSOR_H
#define QT_GRAPH_POSTPROCESSOR_H
#ifndef GRAPH_POSTPROCESSOR_H
#define GRAPH_POSTPROCESSOR_H
#include <memory>
#include <list>
#include "utility/math/MatrixDynamicBase.h"
#include "qt/view/graphElements/QtGraphNode.h"
#include "component/controller/helper/DummyNode.h"
class QtGraphPostprocessor
class GraphPostprocessor
{
public:
static void doPostprocessing(std::list<std::shared_ptr<QtGraphNode>>& nodes);
static void doPostprocessing(std::vector<DummyNode>& nodes);
static void alignNodeOnRaster(QtGraphNode* node);
static void alignNodeOnRaster(DummyNode& node);
static Vec2i alignOnRaster(Vec2i position);
private:
static unsigned int s_cellSize;
static unsigned int s_cellPadding;
static MatrixDynamicBase<unsigned int> buildHeatMap(const std::list<std::shared_ptr<QtGraphNode>>& nodes, const int atomarNodeSize, const int maxNodeSize);
static void resolveOutliers(std::list<std::shared_ptr<QtGraphNode>>& nodes, const Vec2i& centerPoint);
static void resolveOverlap(std::list<std::shared_ptr<QtGraphNode>>& nodes, MatrixDynamicBase<unsigned int>& heatMap, const int divisor);
static MatrixDynamicBase<unsigned int> buildHeatMap(const std::vector<DummyNode>& nodes, const int atomarNodeSize, const int maxNodeSize);
static void resolveOutliers(std::vector<DummyNode>& nodes, const Vec2i& centerPoint);
static void resolveOverlap(std::vector<DummyNode>& nodes, MatrixDynamicBase<unsigned int>& heatMap, const int divisor);
static void modifyHeatmapArea(MatrixDynamicBase<unsigned int>& heatMap, const Vec2i& leftUpperCorner, const Vec2i& size, const int modifier);
static bool getHeatmapGradient(Vec2f& outGradient, const MatrixDynamicBase<unsigned int>& heatMap, const Vec2i& leftUpperCorner, const Vec2i& size);
static Vec2f heatMapRayCast(const MatrixDynamicBase<unsigned int>& heatMap, const Vec2f& startPosition, const Vec2f& direction, unsigned int minValue);
static Vec2i calculateRasterNodeSize(const std::shared_ptr<QtGraphNode>& node);
static Vec2i calculateRasterNodeSize(const DummyNode& node);
};
#endif // QT_GRAPH_POSTPROCESSOR_H
#endif // GRAPH_POSTPROCESSOR_H
@@ -5,12 +5,13 @@
#include "utility/messaging/Message.h"
#include "utility/types.h"
class MessageGraphNodeMove: public Message<MessageGraphNodeMove>
class MessageGraphNodeMove
: public Message<MessageGraphNodeMove>
{
public:
MessageGraphNodeMove(Id tokenId, Vec2i position)
MessageGraphNodeMove(Id tokenId, const Vec2i& delta)
: tokenId(tokenId)
, position(position)
, delta(delta)
{
}
@@ -20,7 +21,7 @@ public:
}
const Id tokenId;
const Vec2i position;
const Vec2i delta;
};
#endif // MESSAGE_GRAPH_NODE_MOVE_H