Compare commits
8 Commits
e1ddd85af5
...
ddf9b01651
Author | SHA1 | Date |
---|---|---|
|
ddf9b01651 | |
|
bd472eea1e | |
|
c74b1b54c1 | |
|
0682930521 | |
|
061fafd728 | |
|
b57ca6e57e | |
|
5661ba80e8 | |
|
dd6398223c |
|
@ -228,7 +228,14 @@ QList<std::shared_ptr<DAGOrderHelper>> DAGGraph::tidy_graph_nodes() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
void DAGGraph::graph_layer_nodes_sort_forward(int layer_index, const QList<std::shared_ptr<DAGOrderHelper>>& nodes) {
|
void dags::DAGGraph::graph_layout_layers_forward(const QList<std::shared_ptr<DAGOrderHelper>>& nodes)
|
||||||
|
{
|
||||||
|
for (auto layer_index = 0; layer_index < maxLayerCount(); ++layer_index) {
|
||||||
|
this->nodes_sort_forward_within_layer(layer_index, nodes);
|
||||||
|
this->nodes_sort_with_above(layer_index, nodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void DAGGraph::nodes_sort_forward_within_layer(int layer_index, const QList<std::shared_ptr<DAGOrderHelper>>& nodes) {
|
||||||
QList<std::shared_ptr<DAGOrderHelper>> nodes_within_current_layer;
|
QList<std::shared_ptr<DAGOrderHelper>> nodes_within_current_layer;
|
||||||
std::copy_if(nodes.begin(), nodes.end(), std::back_inserter(nodes_within_current_layer),
|
std::copy_if(nodes.begin(), nodes.end(), std::back_inserter(nodes_within_current_layer),
|
||||||
[=](std::shared_ptr<DAGOrderHelper> ins) { return ins->layerNumber() == layer_index; });
|
[=](std::shared_ptr<DAGOrderHelper> ins) { return ins->layerNumber() == layer_index; });
|
||||||
|
@ -270,44 +277,19 @@ void DAGGraph::graph_layer_nodes_sort_forward(int layer_index, const QList<std::
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 提取当前层次节点排序值
|
std::sort(nodes_within_current_layer.begin(), nodes_within_current_layer.end(),
|
||||||
this->current_nodelist_filling_indi(layer_index, nodes);
|
[](std::shared_ptr<DAGOrderHelper> a, std::shared_ptr<DAGOrderHelper> b) {
|
||||||
}
|
return a->sortNumber() < b->sortNumber();
|
||||||
|
});
|
||||||
|
|
||||||
this->nodes_sort_with_above(layer_index, nodes);
|
// 提取当前层次节点排序值
|
||||||
this->graph_layer_nodes_sort_forward(layer_index + 1, nodes);
|
this->current_nodelist_filling_indi(nodes_within_current_layer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dags::DAGGraph::current_nodelist_filling_indi(int layer_index, const QList<std::shared_ptr<DAGOrderHelper>>& nodes)
|
bool dags::DAGGraph::current_nodelist_filling_indi(const QList<std::shared_ptr<DAGOrderHelper>>& nodes_within_current_layer)
|
||||||
{
|
{
|
||||||
// 提取本层次节点
|
|
||||||
QList<std::shared_ptr<DAGOrderHelper>> nodes_within_current_layer;
|
|
||||||
std::copy_if(nodes.begin(), nodes.end(), std::back_inserter(nodes_within_current_layer),
|
|
||||||
[=](std::shared_ptr<DAGOrderHelper> ins) { return ins->layerNumber() == layer_index; });
|
|
||||||
if (!nodes_within_current_layer.size())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
std::sort(nodes_within_current_layer.begin(), nodes_within_current_layer.end(),
|
|
||||||
[](std::shared_ptr<DAGOrderHelper>a, std::shared_ptr<DAGOrderHelper> b)->bool {
|
|
||||||
auto prevs_a = a->getUpstreamNodes();
|
|
||||||
auto prevs_b = b->getUpstreamNodes();
|
|
||||||
|
|
||||||
if (!prevs_a.size() && !prevs_b.size())
|
|
||||||
return a > b;
|
|
||||||
if (!prevs_a.size())
|
|
||||||
return true;
|
|
||||||
if (!prevs_b.size())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto upnode_a = std::min_element(prevs_a.begin(), prevs_a.end(),
|
|
||||||
[](std::shared_ptr<DAGOrderHelper> a, std::shared_ptr<DAGOrderHelper> b) { return a->sortNumber() < b->sortNumber(); });
|
|
||||||
auto upnode_b = std::min_element(prevs_b.begin(), prevs_b.end(),
|
|
||||||
[](std::shared_ptr<DAGOrderHelper> a, std::shared_ptr<DAGOrderHelper> b) { return a->sortNumber() < b->sortNumber(); });
|
|
||||||
|
|
||||||
return (*upnode_a)->sortNumber() < (*upnode_b)->sortNumber();
|
|
||||||
});
|
|
||||||
|
|
||||||
// ÌáÈ¡½Úµã»®·Öµµ´Î
|
// ÌáÈ¡½Úµã»®·Öµµ´Î
|
||||||
QList<int> ordered_values;
|
QList<int> ordered_values;
|
||||||
std::transform(nodes_within_current_layer.begin(), nodes_within_current_layer.end(),
|
std::transform(nodes_within_current_layer.begin(), nodes_within_current_layer.end(),
|
||||||
|
@ -378,18 +360,18 @@ void dags::DAGGraph::nodes_sort_with_above(int layer_index, const QList<std::sha
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dags::DAGGraph::graph_adjust_after_layout(const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes)
|
void dags::DAGGraph::graph_adjust_layers_backward(const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes)
|
||||||
{
|
{
|
||||||
auto layer_index = this->maxLayerCount() - 1;
|
auto layer_index = this->maxLayerCount() - 1;
|
||||||
while (layer_index > -1) {
|
while (layer_index > -1) {
|
||||||
this->layer_adjust_via_next_sibling(layer_index, total_nodes);
|
auto nlist = this->layer_adjust_via_next_sibling(layer_index, total_nodes);
|
||||||
if (this->current_nodelist_filling_indi(layer_index, total_nodes))
|
if (this->current_nodelist_filling_indi(nlist))
|
||||||
this->nodes_sort_with_belows(layer_index, total_nodes);
|
this->nodes_sort_with_belows(layer_index, total_nodes);
|
||||||
layer_index--;
|
layer_index--;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dags::DAGGraph::layer_adjust_via_next_sibling(int curr_layer, const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes)
|
QList<std::shared_ptr<DAGOrderHelper>> dags::DAGGraph::layer_adjust_via_next_sibling(int curr_layer, const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes)
|
||||||
{
|
{
|
||||||
QList<std::shared_ptr<DAGOrderHelper>> curr_layer_nodes;
|
QList<std::shared_ptr<DAGOrderHelper>> curr_layer_nodes;
|
||||||
std::copy_if(total_nodes.begin(), total_nodes.end(), std::back_inserter(curr_layer_nodes),
|
std::copy_if(total_nodes.begin(), total_nodes.end(), std::back_inserter(curr_layer_nodes),
|
||||||
|
@ -399,7 +381,27 @@ bool dags::DAGGraph::layer_adjust_via_next_sibling(int curr_layer, const QList<s
|
||||||
this->node_adjust_via_next_sibling(node, total_nodes);
|
this->node_adjust_via_next_sibling(node, total_nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return curr_layer;
|
std::sort(curr_layer_nodes.begin(), curr_layer_nodes.end(),
|
||||||
|
[](std::shared_ptr<DAGOrderHelper>a, std::shared_ptr<DAGOrderHelper> b)->bool {
|
||||||
|
auto prevs_a = a->getUpstreamNodes();
|
||||||
|
auto prevs_b = b->getUpstreamNodes();
|
||||||
|
|
||||||
|
if (!prevs_a.size() && !prevs_b.size())
|
||||||
|
return a > b;
|
||||||
|
if (!prevs_a.size())
|
||||||
|
return true;
|
||||||
|
if (!prevs_b.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto upnode_a = std::min_element(prevs_a.begin(), prevs_a.end(),
|
||||||
|
[](std::shared_ptr<DAGOrderHelper> a, std::shared_ptr<DAGOrderHelper> b) { return a->sortNumber() < b->sortNumber(); });
|
||||||
|
auto upnode_b = std::min_element(prevs_b.begin(), prevs_b.end(),
|
||||||
|
[](std::shared_ptr<DAGOrderHelper> a, std::shared_ptr<DAGOrderHelper> b) { return a->sortNumber() < b->sortNumber(); });
|
||||||
|
|
||||||
|
return (*upnode_a)->sortNumber() < (*upnode_b)->sortNumber();
|
||||||
|
});
|
||||||
|
|
||||||
|
return curr_layer_nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dags::DAGGraph::node_adjust_via_next_sibling(std::shared_ptr<DAGOrderHelper> curr_node, const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes)
|
void dags::DAGGraph::node_adjust_via_next_sibling(std::shared_ptr<DAGOrderHelper> curr_node, const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes)
|
||||||
|
@ -468,7 +470,257 @@ void dags::DAGGraph::nodes_sort_with_belows(int curr_layer, const QList<std::sha
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dags::DAGGraph::graphLayout() {
|
void dags::DAGGraph::node_adjust_ingraph_forward(const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes)
|
||||||
|
{
|
||||||
|
int layer_index = 0;
|
||||||
|
while (this->nodes_revise_forward_within_layer(layer_index, total_nodes)) {
|
||||||
|
this->node_adjust_inlayer_partition_indi(layer_index, total_nodes);
|
||||||
|
this->nodes_sort_with_above(layer_index, total_nodes);
|
||||||
|
layer_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dags::DAGGraph::nodes_revise_forward_within_layer(int layer_index, const QList<std::shared_ptr<DAGOrderHelper>>& nodes)
|
||||||
|
{
|
||||||
|
if (layer_index) {
|
||||||
|
QList<std::shared_ptr<DAGOrderHelper>> nodes_within_current_layer;
|
||||||
|
std::copy_if(nodes.begin(), nodes.end(), std::back_inserter(nodes_within_current_layer),
|
||||||
|
[=](std::shared_ptr<DAGOrderHelper> n) { return n->layerNumber() == layer_index; });
|
||||||
|
|
||||||
|
QList<std::pair<int, int>> sort_arrows;
|
||||||
|
std::for_each(nodes_within_current_layer.begin(), nodes_within_current_layer.end(),
|
||||||
|
[&](std::shared_ptr<DAGOrderHelper> curr_node) {
|
||||||
|
auto prev_nodes = curr_node->getUpstreamNodes();
|
||||||
|
std::for_each(prev_nodes.begin(), prev_nodes.end(),
|
||||||
|
[&](std::shared_ptr<DAGOrderHelper> n) {
|
||||||
|
sort_arrows << std::make_pair(n->sortNumber().toInt(), curr_node->sortNumber().toInt());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
bool dags::DAGGraph::node_adjust_inlayer_forward(int curr_layer, const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes)
|
||||||
|
{
|
||||||
|
// 挑选当前层次节点
|
||||||
|
QList<std::shared_ptr<DAGOrderHelper>> curr_layer_nodes;
|
||||||
|
std::copy_if(total_nodes.begin(), total_nodes.end(), std::back_inserter(curr_layer_nodes),
|
||||||
|
[&](std::shared_ptr<DAGOrderHelper> inst) { return inst->layerNumber() == curr_layer; });
|
||||||
|
|
||||||
|
if (!curr_layer_nodes.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 计算排序系数
|
||||||
|
QList<std::tuple<std::shared_ptr<DAGOrderHelper>, qlonglong, qlonglong, qlonglong, qlonglong>> orders_helper;
|
||||||
|
std::transform(curr_layer_nodes.begin(), curr_layer_nodes.end(), std::back_inserter(orders_helper),
|
||||||
|
[&](std::shared_ptr<DAGOrderHelper> ins) {
|
||||||
|
auto val_p = this->node_evaluate_with_upstream(ins, total_nodes);
|
||||||
|
auto val_n = this->node_evaluate_with_downstream(ins, total_nodes);
|
||||||
|
return std::make_tuple(ins, val_n.first, val_n.second, val_p.first, val_p.second);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 排序当前层次节点
|
||||||
|
std::sort(orders_helper.begin(), orders_helper.end(), [](
|
||||||
|
std::tuple<std::shared_ptr<DAGOrderHelper>, qlonglong, qlonglong, qlonglong, qlonglong> a,
|
||||||
|
std::tuple<std::shared_ptr<DAGOrderHelper>, qlonglong, qlonglong, qlonglong, qlonglong> b)
|
||||||
|
{
|
||||||
|
auto prev_nodesa = std::get<0>(a)->getUpstreamNodes();
|
||||||
|
auto prev_nodesb = std::get<0>(b)->getUpstreamNodes();
|
||||||
|
if (!prev_nodesa.size() && !prev_nodesb.size())
|
||||||
|
return a < b;
|
||||||
|
|
||||||
|
if (prev_nodesa.size() && prev_nodesb.size()) {
|
||||||
|
if (std::get<3>(a) == std::get<3>(b)) {
|
||||||
|
if (std::get<4>(a) == std::get<4>(b)) {
|
||||||
|
if (std::get<1>(a) == std::get<1>(b)) {
|
||||||
|
return std::get<2>(a) < std::get<2>(b);
|
||||||
|
}
|
||||||
|
return std::get<1>(a) < std::get<1>(b);
|
||||||
|
}
|
||||||
|
return std::get<4>(a) < std::get<4>(b);
|
||||||
|
}
|
||||||
|
return std::get<3>(a) < std::get<3>(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prev_nodesa.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
QList<int> sort_values;
|
||||||
|
std::transform(curr_layer_nodes.begin(), curr_layer_nodes.end(), std::back_inserter(sort_values),
|
||||||
|
[](std::shared_ptr<DAGOrderHelper> ins) { return ins->sortNumber().toInt(); });
|
||||||
|
std::sort(sort_values.begin(), sort_values.end());
|
||||||
|
|
||||||
|
// 重新设定节点次序
|
||||||
|
for (auto idx = 0; idx < sort_values.size(); ++idx) {
|
||||||
|
std::get<0>(orders_helper[idx])->setSortNumber(sort_values[idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
bool dags::DAGGraph::node_adjust_inlayer_partition_indi(int layer_index, const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes)
|
||||||
|
{
|
||||||
|
// 提取层次节点并排序节点
|
||||||
|
QList<std::shared_ptr<DAGOrderHelper>> nodes_within_current_layer;
|
||||||
|
std::copy_if(total_nodes.begin(), total_nodes.end(), std::back_inserter(nodes_within_current_layer),
|
||||||
|
[=](std::shared_ptr<DAGOrderHelper> inst) {
|
||||||
|
return layer_index == inst->layerNumber();
|
||||||
|
});
|
||||||
|
std::sort(nodes_within_current_layer.begin(), nodes_within_current_layer.end(),
|
||||||
|
[](std::shared_ptr<DAGOrderHelper> a, std::shared_ptr<DAGOrderHelper> b) {
|
||||||
|
return a->sortNumber() < b->sortNumber();
|
||||||
|
});
|
||||||
|
if (!nodes_within_current_layer.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 获取布局系数
|
||||||
|
QList<std::pair<std::shared_ptr<DAGOrderHelper>, QVariant>> sort_helper;
|
||||||
|
for (auto& inst : nodes_within_current_layer) {
|
||||||
|
auto prev_nodes = inst->getUpstreamNodes();
|
||||||
|
if (!prev_nodes.size()) {
|
||||||
|
sort_helper.append(std::make_pair(inst, QVariant()));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto anchor_it = std::min_element(prev_nodes.begin(), prev_nodes.end(),
|
||||||
|
[](std::shared_ptr<DAGOrderHelper> a, std::shared_ptr<DAGOrderHelper> b) {
|
||||||
|
return a->layerNumber() < b->layerNumber();
|
||||||
|
});
|
||||||
|
sort_helper.append(std::make_pair(inst, (*anchor_it)->sortNumber()));
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QVariant> sort_backup;
|
||||||
|
std::transform(sort_helper.begin(), sort_helper.end(), std::back_inserter(sort_backup),
|
||||||
|
[](std::pair<std::shared_ptr<DAGOrderHelper>, QVariant> u) { return u.second; });
|
||||||
|
|
||||||
|
auto aligned_items_count = std::count_if(sort_backup.begin(), sort_backup.end(), [](QVariant u) { return !u.isNull(); });
|
||||||
|
if (!aligned_items_count)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 补全布局系数
|
||||||
|
QVariant start_value;
|
||||||
|
for (auto idx = 0; idx < sort_helper.size(); ++idx) {
|
||||||
|
auto curr_u = sort_helper[idx];
|
||||||
|
if (!curr_u.second.isNull()) {
|
||||||
|
start_value = curr_u.second;
|
||||||
|
if (idx > 0) {
|
||||||
|
auto u = sort_helper[0];
|
||||||
|
sort_helper[0] = std::make_pair(u.first, start_value.toInt() - 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int idx = 1; idx < sort_helper.size(); ++idx) {
|
||||||
|
auto prev_u = sort_helper[idx - 1];
|
||||||
|
auto curr_u = sort_helper[idx];
|
||||||
|
|
||||||
|
if (curr_u.second.isNull()) {
|
||||||
|
sort_helper[idx] = std::make_pair(curr_u.first, prev_u.second);
|
||||||
|
}
|
||||||
|
if (curr_u.second < prev_u.second) {
|
||||||
|
sort_helper[idx] = std::make_pair(curr_u.first, prev_u.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double sub_sum = 0;
|
||||||
|
// 计算修正系数
|
||||||
|
for (auto ndx = 0; ndx < sort_backup.size(); ndx++) {
|
||||||
|
auto valbk = sort_backup[ndx];
|
||||||
|
auto val2 = sort_helper[ndx].second;
|
||||||
|
if (!valbk.isNull()) {
|
||||||
|
sub_sum += val2.toDouble() - valbk.toDouble();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto val_revised = sub_sum / aligned_items_count;
|
||||||
|
std::for_each(sort_helper.begin(), sort_helper.end(),
|
||||||
|
[=](std::pair<std::shared_ptr<DAGOrderHelper>, QVariant> u) {
|
||||||
|
u.first->setSortNumber(u.second.toDouble() - val_revised);
|
||||||
|
});
|
||||||
|
|
||||||
|
this->current_nodelist_filling_indi(nodes_within_current_layer);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
std::pair<qlonglong, qlonglong> dags::DAGGraph::node_evaluate_with_downstream(std::shared_ptr<DAGOrderHelper> curr_node, const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes)
|
||||||
|
{
|
||||||
|
decltype(curr_node) next_node;
|
||||||
|
if (curr_node->isFakeNode()) {
|
||||||
|
auto n_data = curr_node->headsNode();
|
||||||
|
next_node = *std::find_if(total_nodes.begin(), total_nodes.end(), [&](decltype(curr_node) n) {
|
||||||
|
if (!n->isFakeNode()) {
|
||||||
|
return n->layerNode() == n_data;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto n_datas = curr_node->layerNode()->nextNodes();
|
||||||
|
if (!n_datas.size())
|
||||||
|
return std::make_pair(curr_node->layerNumber(), curr_node->sortNumber().toLongLong());
|
||||||
|
|
||||||
|
QList<std::shared_ptr<DAGOrderHelper>> next_nodes;
|
||||||
|
std::transform(n_datas.begin(), n_datas.end(), std::back_inserter(next_nodes),
|
||||||
|
[&](std::shared_ptr<DAGLayerHelper> inst) {
|
||||||
|
auto rst = std::find_if(total_nodes.begin(), total_nodes.end(), [&](decltype(curr_node) n) {
|
||||||
|
if (!n->isFakeNode()) {
|
||||||
|
return n->layerNode() == inst;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
return *rst;
|
||||||
|
});
|
||||||
|
next_node = *std::min_element(next_nodes.begin(), next_nodes.end(),
|
||||||
|
[](std::shared_ptr<DAGOrderHelper> a, std::shared_ptr<DAGOrderHelper> b) {
|
||||||
|
if (a->layerNumber() == b->layerNumber())
|
||||||
|
return a->sortNumber() < b->sortNumber();
|
||||||
|
return a->layerNumber() < b->layerNumber();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_pair(next_node->layerNumber(), next_node->sortNumber().toLongLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<qlonglong, qlonglong> dags::DAGGraph::node_evaluate_with_upstream(std::shared_ptr<DAGOrderHelper> curr_node, const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes)
|
||||||
|
{
|
||||||
|
auto prim_nodes = curr_node->getUpstreamNodes();
|
||||||
|
if (!prim_nodes.size())
|
||||||
|
return std::make_pair(curr_node->layerNumber(), curr_node->sortNumber().toLongLong());
|
||||||
|
|
||||||
|
QList<std::shared_ptr<DAGOrderHelper>> prev_nodes;
|
||||||
|
std::transform(prim_nodes.begin(), prim_nodes.end(), std::back_inserter(prev_nodes),
|
||||||
|
[&](std::shared_ptr<DAGOrderHelper> ins) {
|
||||||
|
if (!ins->isFakeNode()) {
|
||||||
|
return ins;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto prev_data = ins->tailsNode();
|
||||||
|
auto target_it = std::find_if(total_nodes.begin(), total_nodes.end(),
|
||||||
|
[&](std::shared_ptr<DAGOrderHelper> nins) {
|
||||||
|
if (!nins->isFakeNode())
|
||||||
|
return nins->layerNode() == prev_data;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
return *target_it;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
auto prev_it = std::min_element(prev_nodes.begin(), prev_nodes.end(),
|
||||||
|
[](std::shared_ptr<DAGOrderHelper> a, std::shared_ptr<DAGOrderHelper> b) {
|
||||||
|
if (a->layerNumber() == b->layerNumber())
|
||||||
|
return a->sortNumber() < b->sortNumber();
|
||||||
|
return a->layerNumber() < b->layerNumber();
|
||||||
|
});
|
||||||
|
return std::make_pair((*prev_it)->layerNumber(), (*prev_it)->sortNumber().toLongLong());
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
void dags::DAGGraph::primitiveGraphLayout() {
|
||||||
QList<std::shared_ptr<DAGLayerHelper>> sort_seqs;
|
QList<std::shared_ptr<DAGLayerHelper>> sort_seqs;
|
||||||
QList<std::shared_ptr<DAGLayerHelper>> refs;
|
QList<std::shared_ptr<DAGLayerHelper>> refs;
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -491,14 +743,23 @@ void dags::DAGGraph::graphLayout() {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto tidy_nodes = this->tidy_graph_nodes();
|
auto tidy_nodes = this->tidy_graph_nodes();
|
||||||
this->graph_layer_nodes_sort_forward(0, tidy_nodes);
|
this->graph_layout_layers_forward(tidy_nodes);
|
||||||
this->node_with_layout = tidy_nodes;
|
this->node_with_layout = tidy_nodes;
|
||||||
|
}
|
||||||
|
|
||||||
int times = 1;
|
void dags::DAGGraph::forwardsLayoutImpls()
|
||||||
while (times--) {
|
{
|
||||||
this->graph_adjust_after_layout(tidy_nodes);
|
this->graph_layout_layers_forward(this->node_with_layout);
|
||||||
this->graph_layer_nodes_sort_forward(0, tidy_nodes);
|
}
|
||||||
}
|
|
||||||
|
void dags::DAGGraph::backwardsLayoutImpls()
|
||||||
|
{
|
||||||
|
this->graph_adjust_layers_backward(this->node_with_layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dags::DAGGraph::adjustLayoutImpls()
|
||||||
|
{
|
||||||
|
//this->node_adjust_ingraph_forward(this->node_with_layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,10 @@ namespace dags {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void rebuildFromEdges(const QList<graph_data::Arrow>& arrow_list);
|
void rebuildFromEdges(const QList<graph_data::Arrow>& arrow_list);
|
||||||
void graphLayout();
|
void primitiveGraphLayout();
|
||||||
|
void forwardsLayoutImpls();
|
||||||
|
void backwardsLayoutImpls();
|
||||||
|
void adjustLayoutImpls();
|
||||||
|
|
||||||
QList<std::shared_ptr<DAGOrderHelper>> nodeWithLayout() const;
|
QList<std::shared_ptr<DAGOrderHelper>> nodeWithLayout() const;
|
||||||
int maxLayerCount() const;
|
int maxLayerCount() const;
|
||||||
|
@ -87,15 +90,26 @@ namespace dags {
|
||||||
int node_layering(const std::shared_ptr<DAGLayerHelper> &inst, int layer_current);
|
int node_layering(const std::shared_ptr<DAGLayerHelper> &inst, int layer_current);
|
||||||
int node_layering_adj(std::shared_ptr<DAGLayerHelper> inst);
|
int node_layering_adj(std::shared_ptr<DAGLayerHelper> inst);
|
||||||
QList<std::shared_ptr<DAGOrderHelper>> tidy_graph_nodes();
|
QList<std::shared_ptr<DAGOrderHelper>> tidy_graph_nodes();
|
||||||
void graph_layer_nodes_sort_forward(int layer_index, const QList<std::shared_ptr<DAGOrderHelper>> &nodes);
|
|
||||||
void graph_adjust_after_layout(const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes);
|
|
||||||
|
|
||||||
bool layer_adjust_via_next_sibling(int curr_layer, const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes);
|
void graph_layout_layers_forward(const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes);
|
||||||
|
void nodes_sort_forward_within_layer(int layer_index, const QList<std::shared_ptr<DAGOrderHelper>> &nodes);
|
||||||
|
|
||||||
|
void graph_adjust_layers_backward(const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes);
|
||||||
|
QList<std::shared_ptr<DAGOrderHelper>> layer_adjust_via_next_sibling(int curr_layer, const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes);
|
||||||
void node_adjust_via_next_sibling(std::shared_ptr<DAGOrderHelper> curr_node, const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes);
|
void node_adjust_via_next_sibling(std::shared_ptr<DAGOrderHelper> curr_node, const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes);
|
||||||
|
|
||||||
bool current_nodelist_filling_indi(int curr_layer, const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes);
|
bool current_nodelist_filling_indi(const QList<std::shared_ptr<DAGOrderHelper>>& ordered_nodes);
|
||||||
void nodes_sort_with_above(int curr_layer, const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes);
|
void nodes_sort_with_above(int curr_layer, const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes);
|
||||||
void nodes_sort_with_belows(int curr_layer, const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes);
|
void nodes_sort_with_belows(int curr_layer, const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes);
|
||||||
|
|
||||||
|
void node_adjust_ingraph_forward(const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes);
|
||||||
|
bool nodes_revise_forward_within_layer(int layer_index, const QList<std::shared_ptr<DAGOrderHelper>>& nodes);
|
||||||
|
bool node_adjust_inlayer_partition_indi(int layer_index, const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes);
|
||||||
|
|
||||||
|
|
||||||
|
//bool node_adjust_inlayer_forward(int curr_layer, const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes);
|
||||||
|
//std::pair<qlonglong, qlonglong> node_evaluate_with_downstream(std::shared_ptr<DAGOrderHelper> node, const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes);
|
||||||
|
//std::pair<qlonglong, qlonglong> node_evaluate_with_upstream(std::shared_ptr<DAGOrderHelper> node, const QList<std::shared_ptr<DAGOrderHelper>>& total_nodes);
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,7 +145,7 @@ void TransitionCurve::paint(QPainter* painter, const QStyleOptionGraphicsItem* o
|
||||||
}
|
}
|
||||||
|
|
||||||
DAGActiveView::DAGActiveView(QWidget* parent)
|
DAGActiveView::DAGActiveView(QWidget* parent)
|
||||||
: QGraphicsView(parent) {
|
: QGraphicsView(parent), _layout_engine(new DAGGraph){
|
||||||
this->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
|
this->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
|
||||||
this->setScene(&this->scene_bind);
|
this->setScene(&this->scene_bind);
|
||||||
|
|
||||||
|
@ -240,16 +240,10 @@ QList<IGraphNode*> DAGActiveView::layer_nodes_construction(const QHash<IGraphNod
|
||||||
|
|
||||||
#include <QTextEdit>
|
#include <QTextEdit>
|
||||||
void DAGActiveView::updateWithEdges(QList<graph_data::Arrow> arrows) {
|
void DAGActiveView::updateWithEdges(QList<graph_data::Arrow> arrows) {
|
||||||
// 헌뇜뎠품柬暠
|
_layout_engine->rebuildFromEdges(arrows);
|
||||||
this->scene_bind.clear();
|
_layout_engine->primitiveGraphLayout();
|
||||||
this->total_graph_nodes.clear();
|
|
||||||
|
|
||||||
DAGGraph tools;
|
this->refreshGraph();
|
||||||
tools.rebuildFromEdges(arrows);
|
|
||||||
tools.graphLayout();
|
|
||||||
|
|
||||||
auto total_nodes = tools.nodeWithLayout();
|
|
||||||
total_graph_nodes = this->layer_nodes_construction(QHash<IGraphNode*, std::shared_ptr<DAGOrderHelper>>(), total_nodes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DAGActiveView::highlightGraphLink(const QList<graph_data::Arrow> arrows) {
|
void DAGActiveView::highlightGraphLink(const QList<graph_data::Arrow> arrows) {
|
||||||
|
@ -307,6 +301,25 @@ void DAGActiveView::highlightGraphLink(const QList<graph_data::Arrow> arrows) {
|
||||||
this->update();
|
this->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DAGGraph* dags::DAGActiveView::layoutEngine() const
|
||||||
|
{
|
||||||
|
return this->_layout_engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dags::DAGActiveView::refreshGraph()
|
||||||
|
{
|
||||||
|
// Çå³ýµ±Ç°ÊÓͼ
|
||||||
|
this->scene_bind.clear();
|
||||||
|
this->total_graph_nodes.clear();
|
||||||
|
this->highlight_nodelist.clear();
|
||||||
|
|
||||||
|
auto total_nodes = _layout_engine->nodeWithLayout();
|
||||||
|
total_graph_nodes = this->layer_nodes_construction(QHash<IGraphNode*, std::shared_ptr<DAGOrderHelper>>(), total_nodes);
|
||||||
|
|
||||||
|
auto rect = this->scene()->itemsBoundingRect();
|
||||||
|
this->scene()->setSceneRect(rect);
|
||||||
|
}
|
||||||
|
|
||||||
void DAGActiveView::mousePressEvent(QMouseEvent* ev) {
|
void DAGActiveView::mousePressEvent(QMouseEvent* ev) {
|
||||||
QGraphicsView::mousePressEvent(ev);
|
QGraphicsView::mousePressEvent(ev);
|
||||||
|
|
||||||
|
@ -319,7 +332,7 @@ void DAGActiveView::mousePressEvent(QMouseEvent* ev) {
|
||||||
auto type_item = dynamic_cast<IGraphNode*>(gitem);
|
auto type_item = dynamic_cast<IGraphNode*>(gitem);
|
||||||
if (type_item->nodeType() == GraphNodeType::ActivePresentNode) {
|
if (type_item->nodeType() == GraphNodeType::ActivePresentNode) {
|
||||||
auto node = static_cast<ActivePresentNode*>(type_item);
|
auto node = static_cast<ActivePresentNode*>(type_item);
|
||||||
emit this->nodeClicked(ev->pos(), QList<QString>() << node->nodeName());
|
emit this->nodeClicked(ev->pos(), node->nodeName());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,8 +103,10 @@ namespace dags {
|
||||||
QList<IGraphNode*> highlight_nodelist;
|
QList<IGraphNode*> highlight_nodelist;
|
||||||
QList<IGraphNode*> total_graph_nodes;
|
QList<IGraphNode*> total_graph_nodes;
|
||||||
|
|
||||||
|
DAGGraph *const _layout_engine;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void nodeClicked(const QPointF &pos, const QList<QString> &node_name);
|
void nodeClicked(const QPointF &pos, const QString &node_name);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DAGActiveView(QWidget* parent = nullptr);
|
DAGActiveView(QWidget* parent = nullptr);
|
||||||
|
@ -112,6 +114,9 @@ namespace dags {
|
||||||
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);
|
||||||
|
|
||||||
|
DAGGraph* layoutEngine() const;
|
||||||
|
void refreshGraph();
|
||||||
|
|
||||||
// QGraphicsView
|
// QGraphicsView
|
||||||
virtual void mousePressEvent(QMouseEvent *ev) override;
|
virtual void mousePressEvent(QMouseEvent *ev) override;
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,13 @@ StoryPresent::StoryPresent(QWidget* parent)
|
||||||
auto view = mbar->addMenu(u8"ÊÓͼ");
|
auto view = mbar->addMenu(u8"ÊÓͼ");
|
||||||
view->addAction(u8"ËõС", this, &StoryPresent::lesser, Qt::CTRL + Qt::Key_N);
|
view->addAction(u8"ËõС", this, &StoryPresent::lesser, Qt::CTRL + Qt::Key_N);
|
||||||
view->addAction(u8"·Å´ó", this, &StoryPresent::bigger, Qt::CTRL + Qt::Key_P);
|
view->addAction(u8"·Å´ó", this, &StoryPresent::bigger, Qt::CTRL + Qt::Key_P);
|
||||||
|
|
||||||
|
auto layout = mbar->addMenu(u8"布局调整");
|
||||||
|
layout->addAction(u8"正向布局", this, &StoryPresent::forwardLayout, Qt::CTRL + Qt::Key_F);
|
||||||
|
layout->addAction(u8"逆向布局", this, &StoryPresent::backwardLayout, Qt::CTRL + Qt::Key_B);
|
||||||
|
//layout->addAction(u8"调整布局", this, &StoryPresent::adjustLayout, Qt::CTRL+Qt::Key_A);
|
||||||
|
|
||||||
|
connect(_story_present, &DAGActiveView::nodeClicked, this, &StoryPresent::nodeClickAccept);
|
||||||
}
|
}
|
||||||
|
|
||||||
StoryPresent::~StoryPresent()
|
StoryPresent::~StoryPresent()
|
||||||
|
@ -41,12 +48,14 @@ void StoryPresent::loadXAST(const QString& ast_path)
|
||||||
auto frag_temp = story_line->firstChild();
|
auto frag_temp = story_line->firstChild();
|
||||||
while (frag_temp) {
|
while (frag_temp) {
|
||||||
switch (frag_temp->type()) {
|
switch (frag_temp->type()) {
|
||||||
case SliceType::FragmentDefines: {
|
case SliceType::FragmentDefines:
|
||||||
|
{
|
||||||
auto arrow_tail = std::dynamic_pointer_cast<FragmentDefine>(frag_temp)->name() + u8"@" + story_line->name();
|
auto arrow_tail = std::dynamic_pointer_cast<FragmentDefine>(frag_temp)->name() + u8"@" + story_line->name();
|
||||||
arrows << graph_data::Arrow(arrow_start, arrow_tail);
|
arrows << graph_data::Arrow(arrow_start, arrow_tail);
|
||||||
arrow_start = arrow_tail;
|
arrow_start = arrow_tail;
|
||||||
}break;
|
}break;
|
||||||
case SliceType::FragmentRefers: {
|
case SliceType::FragmentRefers:
|
||||||
|
{
|
||||||
auto conv_refer = std::dynamic_pointer_cast<FragmentRefer>(frag_temp);
|
auto conv_refer = std::dynamic_pointer_cast<FragmentRefer>(frag_temp);
|
||||||
auto arrow_tail = conv_refer->fragmentRefer() + u8"@" + conv_refer->storyRefer();
|
auto arrow_tail = conv_refer->fragmentRefer() + u8"@" + conv_refer->storyRefer();
|
||||||
arrows << graph_data::Arrow(arrow_start, arrow_tail);
|
arrows << graph_data::Arrow(arrow_start, arrow_tail);
|
||||||
|
@ -62,6 +71,78 @@ void StoryPresent::loadXAST(const QString& ast_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <QTransform>
|
#include <QTransform>
|
||||||
|
void StoryPresent::nodeClickAccept(const QPointF& pos, const QString& node_name)
|
||||||
|
{
|
||||||
|
// 起始节点
|
||||||
|
if (!node_name.contains(u8"@")) {
|
||||||
|
auto story_line = this->_story_graph[node_name];
|
||||||
|
|
||||||
|
QList<QString> node_names;
|
||||||
|
node_names << node_name;
|
||||||
|
|
||||||
|
auto temp_node = story_line->firstChild();
|
||||||
|
while (temp_node) {
|
||||||
|
switch (temp_node->type()) {
|
||||||
|
case SliceType::FragmentDefines:
|
||||||
|
{
|
||||||
|
auto fragm = std::dynamic_pointer_cast<FragmentDefine>(temp_node);
|
||||||
|
node_names << QString(u8"%1@%2").arg(fragm->name(), node_name);
|
||||||
|
}break;
|
||||||
|
case SliceType::FragmentRefers:
|
||||||
|
{
|
||||||
|
auto frefer = std::dynamic_pointer_cast<FragmentRefer>(temp_node);
|
||||||
|
node_names << QString(u8"%1@%2").arg(frefer->fragmentRefer(), frefer->storyRefer());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
temp_node = temp_node->nextSlice();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<graph_data::Arrow> arrows;
|
||||||
|
for (auto idx = 1; idx < node_names.size(); ++idx) {
|
||||||
|
auto from = node_names[idx - 1];
|
||||||
|
auto to = node_names[idx];
|
||||||
|
|
||||||
|
arrows << graph_data::Arrow(from, to);
|
||||||
|
}
|
||||||
|
this->_story_present->highlightGraphLink(arrows);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto splits = node_name.split(u8"@", QString::SkipEmptyParts);
|
||||||
|
auto story_line = this->_story_graph[splits.last()];
|
||||||
|
auto fragm_slice = story_line->getFragment(splits.first());
|
||||||
|
auto fragm_defn = std::dynamic_pointer_cast<FragmentDefine>(fragm_slice);
|
||||||
|
|
||||||
|
auto refers = fragm_defn->referSlices();
|
||||||
|
|
||||||
|
if (!refers.size()) {
|
||||||
|
this->nodeClickAccept(QPointF(), story_line->name());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<std::shared_ptr<IElementSlice>> parent_slices;
|
||||||
|
std::transform(refers.begin(), refers.end(), std::back_inserter(parent_slices),
|
||||||
|
[](std::shared_ptr<IElementSlice> ins) { return ins->parentSlice().lock(); });
|
||||||
|
|
||||||
|
decltype(parent_slices) fliter_slices;
|
||||||
|
std::copy_if(parent_slices.begin(), parent_slices.end(), std::back_inserter(fliter_slices),
|
||||||
|
[](std::shared_ptr<IElementSlice> ins) { return ins->type() == SliceType::StoryDefines; });
|
||||||
|
|
||||||
|
QList<std::shared_ptr<StoryDefine>> lines = { story_line };
|
||||||
|
std::transform(fliter_slices.begin(), fliter_slices.end(), std::back_inserter(lines),
|
||||||
|
[](std::shared_ptr<IElementSlice> ins) { return std::dynamic_pointer_cast<StoryDefine>(ins); });
|
||||||
|
|
||||||
|
QMenu msep;
|
||||||
|
for (auto ln : lines) {
|
||||||
|
msep.addAction(ln->name(), [=](){
|
||||||
|
this->nodeClickAccept(QPointF(), ln->name());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
msep.exec(this->_story_present->mapToParent(pos.toPoint()));
|
||||||
|
}
|
||||||
|
}
|
||||||
void StoryPresent::bigger()
|
void StoryPresent::bigger()
|
||||||
{
|
{
|
||||||
_scale_value *= 1.1;
|
_scale_value *= 1.1;
|
||||||
|
@ -79,3 +160,21 @@ void StoryPresent::lesser()
|
||||||
trans_base.scale(_scale_value, _scale_value);
|
trans_base.scale(_scale_value, _scale_value);
|
||||||
this->_story_present->setTransform(trans_base);
|
this->_story_present->setTransform(trans_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StoryPresent::forwardLayout()
|
||||||
|
{
|
||||||
|
this->_story_present->layoutEngine()->forwardsLayoutImpls();
|
||||||
|
this->_story_present->refreshGraph();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StoryPresent::backwardLayout()
|
||||||
|
{
|
||||||
|
this->_story_present->layoutEngine()->backwardsLayoutImpls();
|
||||||
|
this->_story_present->refreshGraph();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StoryPresent::adjustLayout()
|
||||||
|
{
|
||||||
|
this->_story_present->layoutEngine()->adjustLayoutImpls();
|
||||||
|
this->_story_present->refreshGraph();
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,12 @@ private:
|
||||||
dags::DAGActiveView *const _story_present;
|
dags::DAGActiveView *const _story_present;
|
||||||
QHash<QString, std::shared_ptr<xast_parse::StoryDefine>> _story_graph;
|
QHash<QString, std::shared_ptr<xast_parse::StoryDefine>> _story_graph;
|
||||||
|
|
||||||
|
void nodeClickAccept(const QPointF &pos, const QString &node_name);
|
||||||
|
|
||||||
void bigger();
|
void bigger();
|
||||||
void lesser();
|
void lesser();
|
||||||
|
|
||||||
|
void forwardLayout();
|
||||||
|
void backwardLayout();
|
||||||
|
void adjustLayout();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue