273 lines
9.2 KiB
C++
273 lines
9.2 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 centerOffset = block->getCenterOffset(); //参考中心与boundingrect中心的偏移量
|
||
QPointF center;
|
||
|
||
int blockType = block->getType();
|
||
|
||
if (blockType == 1) { // 母线
|
||
if (layer == 1) { // 母线1
|
||
center = QPointF(startX-20, midUpY + rec.height() * 0.5);
|
||
} else if (layer == 2) { // 母线2
|
||
center = QPointF(startX-20, midDownY - rec.height() * 0.5);
|
||
}
|
||
} else if (blockType == 2) { // 间隔
|
||
/*int nLayout = 0; //默认垂直
|
||
auto pBay = dynamic_cast<DiagramEditorBayBlock*>(block);
|
||
if(pBay){
|
||
nLayout = pBay->getBayInfo().nLayout;
|
||
}*/
|
||
|
||
if (layer == 0) { // 上间隔
|
||
center = QPointF(currentX + rec.width() * 0.5,
|
||
midUpY - rec.height() * 0.5 + centerOffset.y() - Constants::EDITOR_ITEM_HEIGHT * 0.5);
|
||
} else if (layer == 3) { // 下间隔
|
||
center = QPointF(currentX + rec.width() * 0.5,
|
||
midDownY + rec.height() * 0.5 + centerOffset.y() + 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;
|
||
}
|
||
}
|
||
|