This commit is contained in:
codeboss 2024-10-04 18:58:34 +08:00
parent 37e3119934
commit d416efb5b5
5 changed files with 103 additions and 47 deletions

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LocalDebuggerCommandArguments>--help</LocalDebuggerCommandArguments> <LocalDebuggerCommandArguments>--test</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

View File

@ -228,21 +228,22 @@ QList<std::shared_ptr<DAGOrderHelper>> DAGGraph::tidy_graph_nodes() {
} }
void DAGGraph::graph_layer_nodes_sort(int layer_index, QList<std::shared_ptr<DAGOrderHelper>> nodes) { void DAGGraph::graph_layer_nodes_sort(int layer_index, QList<std::shared_ptr<DAGOrderHelper>> nodes) {
QList<std::shared_ptr<DAGOrderHelper>> target_nodes_within_layer; QList<std::shared_ptr<DAGOrderHelper>> nodes_within_current_layer;
for (auto n : nodes) for (auto n : nodes)
if (n->layerNumber() == layer_index) { if (n->layerNumber() == layer_index) {
target_nodes_within_layer.append(n); nodes_within_current_layer.append(n);
} }
if (target_nodes_within_layer.size()) { if (nodes_within_current_layer.size()) {
// 计算当前层次所有节点排序
if (!layer_index) { if (!layer_index) {
for (auto idx = 0; idx < target_nodes_within_layer.size(); ++idx) { for (auto idx = 0; idx < nodes_within_current_layer.size(); ++idx) {
target_nodes_within_layer[idx]->setSortNumber(idx + 1); nodes_within_current_layer[idx]->setSortNumber(idx + 1);
} }
} }
else if (layer_index > 0) { else if (layer_index > 0) {
for (auto target_node : target_nodes_within_layer) { for (auto target_node : nodes_within_current_layer) {
QList<float> prev_sorts; QList<double> prev_sorts;
auto upstream_list = target_node->getUpstreamNodes(); auto upstream_list = target_node->getUpstreamNodes();
std::transform(upstream_list.begin(), upstream_list.end(), std::transform(upstream_list.begin(), upstream_list.end(),
std::back_inserter(prev_sorts), [](std::shared_ptr<DAGOrderHelper> inst) { std::back_inserter(prev_sorts), [](std::shared_ptr<DAGOrderHelper> inst) {
@ -250,21 +251,47 @@ void DAGGraph::graph_layer_nodes_sort(int layer_index, QList<std::shared_ptr<DAG
}); });
if (prev_sorts.size()) { if (prev_sorts.size()) {
target_node->setSortNumber(std::accumulate(prev_sorts.begin(), prev_sorts.end(), 0) / prev_sorts.size()); auto target_sum = std::accumulate(prev_sorts.begin(), prev_sorts.end(), 0.0);
target_node->setSortNumber(target_sum / prev_sorts.size());
} }
} }
std::sort(target_nodes_within_layer.begin(), target_nodes_within_layer.end(), // 当前层次节点排序值修正
[](std::shared_ptr<DAGOrderHelper> a, std::shared_ptr<DAGOrderHelper> b) { for (auto idx = 1; idx < nodes_within_current_layer.size(); ++idx) {
return a->sortNumber() < b->sortNumber(); auto prev = nodes_within_current_layer[idx - 1];
}); auto curr = nodes_within_current_layer[idx];
if (prev->sortNumber() == curr->sortNumber())
for (auto idx = 0; idx < target_nodes_within_layer.size(); ++idx) { curr->setSortNumber(curr->sortNumber() + DBL_MIN);
auto target_item = target_nodes_within_layer[idx];
target_item->setSortNumber(idx + 1);
} }
} }
// 提取所有已知节点
QList<std::shared_ptr<DAGOrderHelper>> sorting_nodes;
std::copy_if(nodes.begin(), nodes.end(), std::back_inserter(sorting_nodes),
[&](std::shared_ptr<DAGOrderHelper> n) { return n->layerNumber() <= layer_index; });
// 排序值提取与重排
QList<double> sort_values;
std::transform(sorting_nodes.begin(), sorting_nodes.end(), std::back_inserter(sort_values),
[](std::shared_ptr<DAGOrderHelper> n)->double { return n->sortNumber(); });
sort_values = sort_values.toSet().toList();
std::sort(sort_values.begin(), sort_values.end());
// 检索排序中轴
auto temp_anchor = std::make_pair<double, int>(DBL_MAX, -1);
for (int nidx = 0; nidx < sort_values.size(); ++nidx) {
auto value_span = std::abs(sort_values[nidx]);
if (value_span <= temp_anchor.first)
temp_anchor = std::make_pair(value_span, nidx);
}
// 排序值重整
for (int sorting_idx = 0; sorting_idx < sorting_nodes.size(); ++sorting_idx) {
auto node = sorting_nodes[sorting_idx];
auto sort_idx = sort_values.indexOf(node->sortNumber());
node->setSortNumber(sort_idx - temp_anchor.second);
}
this->graph_layer_nodes_sort(layer_index + 1, nodes); this->graph_layer_nodes_sort(layer_index + 1, nodes);
} }
} }

View File

@ -1,4 +1,5 @@
#include "dag_present.h" #include "dag_present.h"
#include <QDebug>
using namespace dags; using namespace dags;
@ -12,6 +13,7 @@ QString ActivePresentNode::nodeName() const {
QRectF ActivePresentNode::boundingRect() const { QRectF ActivePresentNode::boundingRect() const {
auto rect = this->measure_base.boundingRect(this->node_name); auto rect = this->measure_base.boundingRect(this->node_name);
rect.moveTo(0, 0);
return rect += QMarginsF(0, 0, 10, 10); return rect += QMarginsF(0, 0, 10, 10);
} }
@ -28,7 +30,7 @@ void ActivePresentNode::paint(QPainter* painter, const QStyleOptionGraphicsItem*
} }
painter->drawRect(outline); painter->drawRect(outline);
painter->drawText(outline - QMarginsF(5, 5, 5, 5), this->node_name); painter->drawText(outline - QMarginsF(5, 5, 0, 0), this->node_name);
painter->restore(); painter->restore();
} }
@ -60,9 +62,9 @@ void PenetrateNode::paint(QPainter* painter, const QStyleOptionGraphicsItem* opt
painter->save(); painter->save();
if (this->isHighlighted()) if (this->isHighlighted())
painter->fillRect(QRectF(0, -2, outline.width(), 4), Qt::red); painter->fillRect(QRectF(0, 2, outline.width(), 4), Qt::red);
else else
painter->fillRect(QRectF(0, -2, outline.width(), 4), Qt::black); painter->fillRect(QRectF(0, 2, outline.width(), 4), Qt::black);
painter->restore(); painter->restore();
} }
@ -75,10 +77,10 @@ void TransitionCurve::layoutRefresh() {
auto orect = this->start_node->boundingRect(); auto orect = this->start_node->boundingRect();
auto erect = this->end_node->boundingRect(); auto erect = this->end_node->boundingRect();
auto xpos = this->start_node->pos().x() + this->start_node->boundingRect().width(); auto xpos = this->start_node->pos().x() + orect.width();
auto width_value = this->end_node->pos().x() - this->start_node->pos().x() - orect.width();
auto ypos = std::min(this->start_node->pos().y(), this->end_node->pos().y()); auto ypos = std::min(this->start_node->pos().y(), this->end_node->pos().y());
auto width_value = this->end_node->pos().x() - xpos;
auto bottom_y = std::max(this->start_node->pos().y() + orect.height(), this->end_node->pos().y() + erect.height()); auto bottom_y = std::max(this->start_node->pos().y() + orect.height(), this->end_node->pos().y() + erect.height());
this->outline = QRectF(0, 0, width_value, bottom_y - ypos); this->outline = QRectF(0, 0, width_value, bottom_y - ypos);
@ -105,18 +107,20 @@ QRectF TransitionCurve::boundingRect() const {
void TransitionCurve::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { void TransitionCurve::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
auto outline = this->boundingRect(); auto outline = this->boundingRect();
auto start_rect = this->start_node->boundingRect(); auto start_rect = this->start_node->boundingRect();
auto end_rect = this->end_node->boundingRect(); auto end_rect = this->end_node->boundingRect();
auto aj_start_pos = this->start_node->pos() + QPointF(start_rect.width(), 0); start_rect.moveTo(this->start_node->pos());
auto aj_end_pos = this->end_node->pos(); end_rect.moveTo(this->end_node->pos());
auto aj_start_pos = start_rect.topRight();
auto aj_end_pos = end_rect.topLeft();
auto line_span = this->prev_layer_w - start_rect.width(); auto line_span = this->prev_layer_w - start_rect.width();
painter->save(); painter->save();
painter->setRenderHint(QPainter::Antialiasing); painter->setRenderHint(QPainter::Antialiasing);
auto start_pos = aj_start_pos - QGraphicsItem::pos(); auto start_pos = aj_start_pos - QGraphicsItem::pos() + QPointF(0, start_rect.height() / 2);
auto end_pos = aj_end_pos - QGraphicsItem::pos(); auto end_pos = aj_end_pos - QGraphicsItem::pos() + QPointF(0, end_rect.height() / 2);
auto line_epos = start_pos + QPointF(line_span, 0); auto line_epos = start_pos + QPointF(line_span, 0);
auto control_pos0 = line_epos + QPointF((outline.width() - line_span) / 3, 0); auto control_pos0 = line_epos + QPointF((outline.width() - line_span) / 3, 0);
@ -148,8 +152,7 @@ DAGActiveView::DAGActiveView(QWidget* parent)
this->setFont(f); this->setFont(f);
} }
QList<IGraphNode*> DAGActiveView::layer_nodes_construction( QList<IGraphNode*> DAGActiveView::layer_nodes_construction(const QHash<IGraphNode*, std::shared_ptr<DAGOrderHelper>>& prev_layer_helper,
const QHash<IGraphNode*, std::shared_ptr<DAGOrderHelper>>& prev_layer_helper,
const QList<std::shared_ptr<DAGOrderHelper>>& total_datas, int layer_idx, double prev_layer_end) { const QList<std::shared_ptr<DAGOrderHelper>>& total_datas, int layer_idx, double prev_layer_end) {
// 挑选当前层次节点 // 挑选当前层次节点
QList<std::shared_ptr<DAGOrderHelper>> current_layer_datas; QList<std::shared_ptr<DAGOrderHelper>> current_layer_datas;
@ -166,14 +169,13 @@ QList<IGraphNode*> DAGActiveView::layer_nodes_construction(
return current_nodes_helper.keys(); return current_nodes_helper.keys();
// 构建当前层次图形节点 // 构建当前层次图形节点
double ypos_acc = 0;
for (auto& data_node : current_layer_datas) { for (auto& data_node : current_layer_datas) {
if (data_node->isFakeNode()) { if (data_node->isFakeNode()) {
auto from = data_node->relateNode()->bindPoint().name(); auto from = data_node->relateNode()->bindPoint().name();
auto to = data_node->towardsNode()->bindPoint().name(); auto to = data_node->towardsNode()->bindPoint().name();
auto curr_gnode = new PenetrateNode(20, from, to); auto curr_gnode = new PenetrateNode(20, from, to);
curr_gnode->setPos(prev_layer_end, ypos_acc); this->scene_bind.addItem(curr_gnode);
ypos_acc += curr_gnode->boundingRect().height(); curr_gnode->setPos(prev_layer_end, data_node->sortNumber() * (this->node_span + this->font().pointSizeF()) * 7);
current_nodes_helper[curr_gnode] = data_node; current_nodes_helper[curr_gnode] = data_node;
} }
@ -183,12 +185,11 @@ QList<IGraphNode*> DAGActiveView::layer_nodes_construction(
node_type_vx = PrsnType::StartNode; node_type_vx = PrsnType::StartNode;
} }
auto curr_gnode = new ActivePresentNode(data_node->layerNode()->bindPoint().name(), node_type_vx, this->font()); auto curr_gnode = new ActivePresentNode(data_node->layerNode()->bindPoint().name(), node_type_vx, this->font());
curr_gnode->setPos(prev_layer_end, ypos_acc); this->scene_bind.addItem(curr_gnode);
ypos_acc += curr_gnode->boundingRect().height(); curr_gnode->setPos(prev_layer_end, data_node->sortNumber() * (this->node_span + this->font().pointSizeF()) * 7);
current_nodes_helper[curr_gnode] = data_node; current_nodes_helper[curr_gnode] = data_node;
} }
ypos_acc += this->node_span;
} }
// 对其当前层次节点宽度 // 对其当前层次节点宽度
@ -220,6 +221,7 @@ QList<IGraphNode*> DAGActiveView::layer_nodes_construction(
auto prev_data = prev_layer_helper[prev_gnode]; auto prev_data = prev_layer_helper[prev_gnode];
if (upstream_nodes.contains(prev_data)) { if (upstream_nodes.contains(prev_data)) {
auto line_cmbn = new TransitionCurve(prev_gnode, curr_gnode, prev_layer_width); auto line_cmbn = new TransitionCurve(prev_gnode, curr_gnode, prev_layer_width);
this->scene_bind.addItem(line_cmbn);
line_cmbn->layoutRefresh(); line_cmbn->layoutRefresh();
next_nodes << line_cmbn; next_nodes << line_cmbn;
} }
@ -232,17 +234,16 @@ QList<IGraphNode*> DAGActiveView::layer_nodes_construction(
} }
void DAGActiveView::updateWithEdges(QList<graph_data::Arrow> arrows) { void DAGActiveView::updateWithEdges(QList<graph_data::Arrow> arrows) {
// Çå³ýµ±Ç°ÊÓͼ
this->scene_bind.clear();
this->total_graph_nodes.clear();
DAGGraph tools; DAGGraph tools;
tools.rebuildFromEdges(arrows); tools.rebuildFromEdges(arrows);
tools.graphLayout(); tools.graphLayout();
auto total_nodes = tools.nodeWithLayout(); auto total_nodes = tools.nodeWithLayout();
total_graph_nodes = this->layer_nodes_construction(QHash<IGraphNode*, std::shared_ptr<DAGOrderHelper>>(), total_nodes);
auto gnodelist = this->layer_nodes_construction(QHash<IGraphNode*, std::shared_ptr<DAGOrderHelper>>(), total_nodes);
for (auto& gnode : gnodelist) {
this->scene_bind.addItem(dynamic_cast<QGraphicsItem*>(gnode));
total_graph_nodes << gnode;
}
} }
void DAGActiveView::highlightGraphLink(const QList<graph_data::Arrow> arrows) { void DAGActiveView::highlightGraphLink(const QList<graph_data::Arrow> arrows) {

View File

@ -109,15 +109,15 @@ namespace dags {
public: public:
DAGActiveView(QWidget* parent = nullptr); DAGActiveView(QWidget* parent = nullptr);
QList<IGraphNode*> layer_nodes_construction(
const QHash<IGraphNode*, std::shared_ptr<dags::DAGOrderHelper>>& prev_layer,
const QList<std::shared_ptr<dags::DAGOrderHelper>>& total_datas,
int layer_idx = 0, double prev_layer_end = 0);
void updateWithEdges(QList<graph_data::Arrow> arrows); void updateWithEdges(QList<graph_data::Arrow> arrows);
void highlightGraphLink(const QList<graph_data::Arrow> color_path); void highlightGraphLink(const QList<graph_data::Arrow> color_path);
// QGraphicsView
virtual void mousePressEvent(QMouseEvent *ev) override; virtual void mousePressEvent(QMouseEvent *ev) override;
private:
QList<IGraphNode*> layer_nodes_construction(const QHash<IGraphNode*, std::shared_ptr<dags::DAGOrderHelper>>& prev_layer,
const QList<std::shared_ptr<dags::DAGOrderHelper>>& total_datas, int layer_idx = 0, double prev_layer_end = 0);
}; };
}; };

View File

@ -22,6 +22,10 @@ int main(int argc, char* argv[]) {
cmdrec << help_mode; cmdrec << help_mode;
(*help_mode) << std::make_shared<IndexParam>(u8"StoryPresent", u8"程序名") << make_shared<FloatOption>(u8"help", u8"打印帮助文档"); (*help_mode) << std::make_shared<IndexParam>(u8"StoryPresent", u8"程序名") << make_shared<FloatOption>(u8"help", u8"打印帮助文档");
auto test_mode = std::make_shared<MatchMode>(0x000bu, u8"开发过程内部测试");
cmdrec << test_mode;
(*test_mode) << std::make_shared<IndexParam>(u8"StoryPresent", u8"程序名") << make_shared<FloatOption>(u8"test", u8"打印帮助文档");
auto rst = cmdrec.parse(argc, argv); auto rst = cmdrec.parse(argc, argv);
QTextEdit msg; QTextEdit msg;
msg.setReadOnly(true); msg.setReadOnly(true);
@ -37,6 +41,30 @@ int main(int argc, char* argv[]) {
msg.setPlainText(cmdrec.helperDoc()); msg.setPlainText(cmdrec.helperDoc());
msg.show(); msg.show();
break; break;
case 0x000bu:
{
auto arrows = QList<graph_data::Arrow>() <<
graph_data::Arrow(u8"a中文测试", u8"b中文测试") <<
graph_data::Arrow(u8"c中文测试", u8"b中文测试") <<
graph_data::Arrow(u8"c中文测试", u8"d中文测试") <<
graph_data::Arrow(u8"b中文测试", u8"e中文测试") <<
graph_data::Arrow(u8"d中文测试", u8"e中文测试") <<
graph_data::Arrow(u8"a中文测试", u8"e中文测试");
auto view = new dags::DAGActiveView;
view->updateWithEdges(arrows);
view->show();
//dags::DAGGraph tools;
//tools.rebuildFromEdges(arrows);
//tools.graphLayout();
//for (auto n : tools.nodeWithLayout()) {
// msg.setWindowTitle("layout-message");
// msg.append(QString("node:%3,layer:%1,sort:%2").arg(n->layerNumber()).arg(n->sortNumber()).arg(n->layerNode()->bindPoint().name()));
// msg.show();
//}
}break;
default: default:
break; break;
} }