GridFrame/diagramCavas/source/diagramEditor/layoutCalculator.cpp

299 lines
9.8 KiB
C++
Raw Normal View History

2026-05-06 19:48:33 +08:00
// LayoutCalculator.cpp
#include "diagramEditor/layoutCalculator.h"
#include "diagramEditor/diagramEditorWizard.h"
2026-05-18 19:12:28 +08:00
#include "graphicsDataModel/diagramEditorModel.h"
2026-05-06 19:48:33 +08:00
#include "diagramEditor/diagramEditorStructContainer.h"
#include "diagramEditor/diagramEditorBaseBlock.h"
2026-05-18 19:12:28 +08:00
#include "diagramEditor/editPanel.h"
#include "diagramEditor/editScene.h"
2026-05-06 19:48:33 +08:00
#include <QDebug>
2026-05-18 19:12:28 +08:00
FixedLayoutCalculator::FixedLayoutCalculator(DiagramEditorModel* model)
: m_model(model) {}
2026-05-06 19:48:33 +08:00
QMap<DiagramEditorBaseBlock*, QPointF> FixedLayoutCalculator::calculateLayout() {
m_blockPositions.clear();
2026-05-18 19:12:28 +08:00
if (!m_model) {
2026-05-06 19:48:33 +08:00
qWarning() << "FixedLayoutCalculator: Wizard为空";
return m_blockPositions;
}
2026-05-18 19:12:28 +08:00
auto mapTotal = m_model->getWizard()->getContainerStruct();
2026-05-06 19:48:33 +08:00
double deltaY = 0;
double lastMaxDownH = 0;
// 按层级顺序处理
for (auto iter = mapTotal.begin(); iter != mapTotal.end(); ++iter) {
int level = iter.key();
if (level == Constants::TRANSFORMER_LEVEL) {
continue; // 变压器特殊处理
}
// 创建层级布局
LevelLayout levelLayout;
levelLayout.level = level;
levelLayout.containers = iter.value();
if (levelLayout.containers.isEmpty()) {
continue;
}
// 第一阶段:计算尺寸
calculateContainerSizes(levelLayout);
// 第二阶段:计算位置
calculatePositions(levelLayout, deltaY, lastMaxDownH);
// 处理变压器在层级0之后
if (level == 0 && mapTotal.contains(Constants::TRANSFORMER_LEVEL)) {
auto transformers = mapTotal.value(Constants::TRANSFORMER_LEVEL);
if (!transformers.isEmpty()) {
calculateTransformerPositions(transformers, deltaY, lastMaxDownH);
}
}
}
return m_blockPositions;
}
void FixedLayoutCalculator::calculateContainerSizes(LevelLayout& levelLayout) {
levelLayout.maxUpHeight = 0;
levelLayout.maxDownHeight = 0;
2026-05-11 18:38:15 +08:00
for (auto& container : levelLayout.containers) {
2026-05-06 19:48:33 +08:00
if (!container) continue;
auto mapBlocks = container->getBlockMap();
// 计算上间隔尺寸
auto topBays = mapBlocks.value(0);
double maxUp = 0;
double widthUp = 0;
for (auto block : topBays) {
if (!block) continue;
QRectF rec = block->getRecSize();
maxUp = qMax(maxUp, rec.height());
widthUp += 100 + rec.width();
}
maxUp += Constants::EDITOR_ITEM_HEIGHT;
levelLayout.maxUpHeight = qMax(levelLayout.maxUpHeight, maxUp);
// 计算下间隔尺寸
auto bottomBays = mapBlocks.value(3);
double maxDown = 0;
double widthDown = 0;
for (auto block : bottomBays) {
if (!block) continue;
QRectF rec = block->getRecSize();
maxDown = qMax(maxDown, rec.height());
widthDown += 100 + rec.width();
}
maxDown += Constants::EDITOR_ITEM_HEIGHT;
levelLayout.maxDownHeight = qMax(levelLayout.maxDownHeight, maxDown);
// 计算母线宽度
double busWidth = 0;
auto bus1 = mapBlocks.value(1);
auto bus2 = mapBlocks.value(2);
if (!bus1.isEmpty()) {
busWidth = qMax(busWidth, bus1.first()->getRecSize().width());
}
if (!bus2.isEmpty()) {
busWidth = qMax(busWidth, bus2.first()->getRecSize().width());
}
// 计算容器宽度
double containerWidth = qMax(widthUp, widthDown);
if (containerWidth < busWidth) {
containerWidth = busWidth;
}
// 设置容器尺寸
container->setWidth(containerWidth);
}
// 处理空的情况
if (levelLayout.maxUpHeight == 0) {
levelLayout.maxUpHeight = Constants::EDITOR_ITEM_HEIGHT;
}
if (levelLayout.maxDownHeight == 0) {
levelLayout.maxDownHeight = Constants::EDITOR_ITEM_HEIGHT;
}
}
void FixedLayoutCalculator::calculatePositions(LevelLayout& levelLayout,
double& deltaY, double& lastMaxDownH) {
double startX = CONTAINER_START_X;
bool isFirstContainer = true;
2026-05-11 18:38:15 +08:00
for (auto& container : levelLayout.containers) {
2026-05-06 19:48:33 +08:00
if (!container) continue;
// 设置容器高度
container->setMaxUpH(levelLayout.maxUpHeight);
container->setMaxDownH(levelLayout.maxDownHeight);
// 计算垂直位置(每行第一个容器计算一次)
if (isFirstContainer) {
if (levelLayout.level == 0) { // 首行
deltaY = container->getMaxUpH();
} else { // 其他行
deltaY = deltaY + BUS_V_SPACING + lastMaxDownH + container->getMaxUpH();
}
lastMaxDownH = container->getMaxDownH();
isFirstContainer = false;
}
// 设置容器的关键Y坐标
container->setMidUpY(deltaY);
container->setMidDownY(deltaY + BUS_V_SPACING);
container->setStartX(startX);
2026-05-14 20:11:48 +08:00
// 计算容器内间隔位置
2026-05-06 19:48:33 +08:00
calculateBlockPositionsInContainer(container, startX, deltaY, deltaY + BUS_V_SPACING);
// 更新水平位置
startX += container->getWidth() + CONTAINER_H_SPACING;
}
}
void FixedLayoutCalculator::calculateBlockPositionsInContainer(DiagramEditorStructContainer* container,
double startX,
double midUpY,
double midDownY) {
if (!container) return;
auto mapBlocks = container->getBlockMap();
double currentX = startX;
for (auto it = mapBlocks.begin(); it != mapBlocks.end(); ++it) {
int layer = it.key();
auto blocks = it.value();
for (auto block : blocks) {
if (!block) continue;
QRectF rec = block->getRecSize();
2026-05-14 20:11:48 +08:00
QPointF centerOffset = block->getCenterOffset(); //参考中心与boundingrect中心的偏移量
2026-05-06 19:48:33 +08:00
QPointF center;
int blockType = block->getType();
if (blockType == 1) { // 母线
if (layer == 1) { // 母线1
2026-05-14 20:11:48 +08:00
center = QPointF(startX-20, midUpY + rec.height() * 0.5);
2026-05-06 19:48:33 +08:00
} else if (layer == 2) { // 母线2
2026-05-14 20:11:48 +08:00
center = QPointF(startX-20, midDownY - rec.height() * 0.5);
2026-05-06 19:48:33 +08:00
}
} else if (blockType == 2) { // 间隔
2026-05-14 20:11:48 +08:00
/*int nLayout = 0; //默认垂直
auto pBay = dynamic_cast<DiagramEditorBayBlock*>(block);
if(pBay){
nLayout = pBay->getBayInfo().nLayout;
}*/
2026-05-06 19:48:33 +08:00
if (layer == 0) { // 上间隔
center = QPointF(currentX + rec.width() * 0.5,
2026-05-14 20:11:48 +08:00
midUpY - rec.height() * 0.5 + centerOffset.y() - Constants::EDITOR_ITEM_HEIGHT * 0.5);
2026-05-06 19:48:33 +08:00
} else if (layer == 3) { // 下间隔
center = QPointF(currentX + rec.width() * 0.5,
2026-05-14 20:11:48 +08:00
midDownY + rec.height() * 0.5 + centerOffset.y() + Constants::EDITOR_ITEM_HEIGHT * 0.5);
2026-05-06 19:48:33 +08:00
}
currentX += rec.width();
}
// 变压器不在这里处理
if (!center.isNull()) {
m_blockPositions[block] = center;
block->setSeceneDelta(center);
}
}
}
}
2026-05-18 19:12:28 +08:00
void FixedLayoutCalculator::calculateTransformerPositions(
const QList<DiagramEditorStructContainer*>& transformers,
double& deltaY, double& lastMaxDownH)
{
if (transformers.isEmpty())
return;
2026-05-06 19:48:33 +08:00
2026-05-18 19:12:28 +08:00
// ---------- ① 计算变压器尺寸 ----------
2026-05-06 19:48:33 +08:00
for (auto container : transformers) {
2026-05-18 19:12:28 +08:00
if (!container)
continue;
2026-05-06 19:48:33 +08:00
auto mapBlocks = container->getBlockMap();
2026-05-18 19:12:28 +08:00
auto transBlocks = mapBlocks.value(1); // layer 1
if (transBlocks.isEmpty())
continue;
2026-05-06 19:48:33 +08:00
for (auto block : transBlocks) {
2026-05-18 19:12:28 +08:00
if (!block)
continue;
2026-05-06 19:48:33 +08:00
QRectF rec = block->getRecSize();
container->setWidth(rec.width());
container->setHeight(rec.height());
2026-05-18 19:12:28 +08:00
break; // 仍然只取第一个
2026-05-06 19:48:33 +08:00
}
}
2026-05-18 19:12:28 +08:00
// ---------- ② 纵向位置(保持不变) ----------
double centerY = 0;
if (!transformers.isEmpty()) {
deltaY += CONTAINER_H_SPACING + lastMaxDownH + transformers.first()->getHeight();
centerY = deltaY - transformers.first()->getHeight() * 0.5;
}
2026-05-06 19:48:33 +08:00
2026-05-18 19:12:28 +08:00
// ---------- ③ 固定宽度水平布局 ----------
double sceneWidth = m_model->getPanel()->getScene()->width();
const int count = transformers.size();
2026-05-06 19:48:33 +08:00
2026-05-18 19:12:28 +08:00
// 没有变压器,直接返回
if (count == 0)
return;
// 等间距分布(含左右边距)
const double spacing = sceneWidth / (count + 1);
// ---------- ④ 逐个放置 ----------
for (int i = 0; i < count; ++i) {
auto container = transformers.at(i);
if (!container)
continue;
2026-05-06 19:48:33 +08:00
container->setStartY(centerY);
2026-05-18 19:12:28 +08:00
// 计算水平中心
const double centerX = spacing * (i + 1);
const double startX = centerX - container->getWidth() * 0.5;
2026-05-06 19:48:33 +08:00
container->setStartX(startX);
2026-05-18 19:12:28 +08:00
// ---------- ⑤ 内部 block 居中 ----------
2026-05-06 19:48:33 +08:00
auto mapBlocks = container->getBlockMap();
for (auto it = mapBlocks.begin(); it != mapBlocks.end(); ++it) {
for (auto block : it.value()) {
2026-05-18 19:12:28 +08:00
if (!block)
continue;
2026-05-06 19:48:33 +08:00
QRectF rec = block->getRecSize();
2026-05-18 19:12:28 +08:00
QPointF pos(
startX + rec.width() * 0.5,
centerY + rec.height() * 0.5
);
2026-05-06 19:48:33 +08:00
2026-05-18 19:12:28 +08:00
m_blockPositions[block] = pos;
block->setSeceneDelta(pos);
2026-05-06 19:48:33 +08:00
}
}
}
}