// LayoutCalculator.cpp #include "diagramEditor/layoutCalculator.h" #include "diagramEditor/diagramEditorWizard.h" #include "graphicsDataModel/diagramEditorModel.h" #include "diagramEditor/diagramEditorStructContainer.h" #include "diagramEditor/diagramEditorBaseBlock.h" #include "diagramEditor/editPanel.h" #include "diagramEditor/editScene.h" #include FixedLayoutCalculator::FixedLayoutCalculator(DiagramEditorModel* model) : m_model(model) {} QMap FixedLayoutCalculator::calculateLayout() { m_blockPositions.clear(); if (!m_model) { qWarning() << "FixedLayoutCalculator: Wizard为空"; return m_blockPositions; } auto mapTotal = m_model->getWizard()->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(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& 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 if (transBlocks.isEmpty()) continue; for (auto block : transBlocks) { if (!block) continue; QRectF rec = block->getRecSize(); container->setWidth(rec.width()); container->setHeight(rec.height()); break; // 仍然只取第一个 } } // ---------- ② 纵向位置(保持不变) ---------- double centerY = 0; if (!transformers.isEmpty()) { deltaY += CONTAINER_H_SPACING + lastMaxDownH + transformers.first()->getHeight(); centerY = deltaY - transformers.first()->getHeight() * 0.5; } // ---------- ③ 固定宽度水平布局 ---------- double sceneWidth = m_model->getPanel()->getScene()->width(); const int count = transformers.size(); // 没有变压器,直接返回 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; container->setStartY(centerY); // 计算水平中心 const double centerX = spacing * (i + 1); const double startX = centerX - container->getWidth() * 0.5; container->setStartX(startX); // ---------- ⑤ 内部 block 居中 ---------- 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 pos( startX + rec.width() * 0.5, centerY + rec.height() * 0.5 ); m_blockPositions[block] = pos; block->setSeceneDelta(pos); } } } }