266 lines
8.8 KiB
C++
266 lines
8.8 KiB
C++
|
|
// 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;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|