GridFrame/diagramCavas/source/diagramEditor/layoutCalculator.cpp

266 lines
8.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"
#include "diagramEditor/diagramEditorStructContainer.h"
#include "diagramEditor/diagramEditorBaseBlock.h"
#include <QDebug>
FixedLayoutCalculator::FixedLayoutCalculator(DiagramEditorWizard* wizard)
: m_wizard(wizard) {}
QMap<DiagramEditorBaseBlock*, QPointF> FixedLayoutCalculator::calculateLayout() {
m_blockPositions.clear();
if (!m_wizard) {
qWarning() << "FixedLayoutCalculator: Wizard为空";
return m_blockPositions;
}
auto mapTotal = m_wizard->getContainerStruct();
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;
for (auto container : levelLayout.containers) {
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;
for (auto container : levelLayout.containers) {
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);
// 计算容器内设备位置
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();
QPointF center;
int blockType = block->getType();
if (blockType == 1) { // 母线
if (layer == 1) { // 母线1
center = QPointF(startX, midUpY + rec.height() * 0.5);
} else if (layer == 2) { // 母线2
center = QPointF(startX, midDownY - rec.height() * 0.5);
}
} else if (blockType == 2) { // 间隔
if (layer == 0) { // 上间隔
center = QPointF(currentX + rec.width() * 0.5,
midUpY - rec.height() * 0.5 - Constants::EDITOR_ITEM_HEIGHT * 0.5);
} else if (layer == 3) { // 下间隔
center = QPointF(currentX + rec.width() * 0.5,
midDownY + rec.height() * 0.5 + Constants::EDITOR_ITEM_HEIGHT * 0.5);
}
currentX += rec.width();
}
// 变压器不在这里处理
if (!center.isNull()) {
m_blockPositions[block] = center;
block->setSeceneDelta(center);
}
}
}
}
void FixedLayoutCalculator::calculateTransformerPositions(const QList<DiagramEditorStructContainer*>& transformers,
double& deltaY, double& lastMaxDownH) {
if (transformers.isEmpty()) return;
// 计算变压器尺寸
for (auto container : transformers) {
if (!container) continue;
auto mapBlocks = container->getBlockMap();
auto transBlocks = mapBlocks.value(1); // 变压器在layer 1
for (auto block : transBlocks) {
if (!block) continue;
QRectF rec = block->getRecSize();
container->setWidth(rec.width());
container->setHeight(rec.height());
break; // 只取第一个变压器
}
}
// 计算变压器位置
double startX = TRANSFORMER_START_X;
bool isFirstTransformer = true;
for (auto container : transformers) {
if (!container) continue;
// 计算垂直位置
if (isFirstTransformer) {
deltaY = deltaY + BUS_V_SPACING + lastMaxDownH + container->getHeight();
isFirstTransformer = false;
}
double centerY = deltaY - container->getHeight() * 0.5;
container->setStartY(centerY);
container->setStartX(startX);
// 计算变压器内部设备位置
auto mapBlocks = container->getBlockMap();
for (auto it = mapBlocks.begin(); it != mapBlocks.end(); ++it) {
for (auto block : it.value()) {
if (!block) continue;
QRectF rec = block->getRecSize();
QPointF center(startX + rec.width() * 0.5,
centerY + rec.height() * 0.5);
m_blockPositions[block] = center;
block->setSeceneDelta(center);
}
}
// 更新水平位置
startX += container->getWidth() + TRANSFORMER_SPACING;
}
}