// LayoutCalculator.cpp #include "diagramEditor/layoutCalculator.h" #include "diagramEditor/diagramEditorWizard.h" #include "diagramEditor/diagramEditorStructContainer.h" #include "diagramEditor/diagramEditorBaseBlock.h" #include FixedLayoutCalculator::FixedLayoutCalculator(DiagramEditorWizard* wizard) : m_wizard(wizard) {} QMap 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& 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; } }