#include "graphicsDataModel/baseModel.h" #include "graphicsItem/itemPort.h" #include "graphicsItem/graphicsBaseItem.h" #include "baseProperty.h" #include "topologyManager.h" #include "powerEntity.h" #include "baseModelItem/electricBaseModelLineItem.h" void BaseModel::createTopoTerminalsByItem(GraphicsBaseItem* pItem,ModelFunctionType funType) { PowerEntity* pEntity = pItem->entity(); if(pEntity) { QMap mapPorts = pItem->getPorts(); //创建实体port对应的拓扑port for(auto &port:mapPorts) { TerminalType terType; HandleType tpe = port->getType(); switch (tpe) { case T_lineIn: terType = TerminalType::PowerInput; break; case T_lineOut: terType = TerminalType::PowerOutput; break; case T_lineInOut: terType = TerminalType::PowerConnect; break; case T_newTral: terType = TerminalType::NewTral; break; default: break; } QPointF f = port->pos(); auto pTer = TopologyManager::instance().createTerminal(pEntity->id(),terType,"",port->pos(),port->getId(),funType); if(pTer) pTer->setPortLocate(port->portPos()); } } } QPointF BaseModel::calculateBusPortPos(GraphicsBaseItem* pBus,GraphicsBaseItem* item,QPointF para) { QRectF recBus = pBus->sceneBoundingRect(); QRectF recItem = item->sceneBoundingRect(); // 判断item相对于bus的位置 bool itemIsBelowBus = recItem.top() > recBus.bottom(); qreal busReferenceY = itemIsBelowBus ? recBus.bottom() : recBus.top(); QLineF busLine = QLineF(recBus.left(), busReferenceY, recBus.right(), busReferenceY); QPointF p1 = busLine.p1(); QPointF p2 = busLine.p2(); // 计算投影点在线段上的位置 QPointF projection; if (busLine.length() == 0) { projection = p1; } else { QPointF vec = p2 - p1; // 如果para不是(0,0),则使用para点计算投影 // 否则使用item的中心点计算投影 QPointF pointToProject; if (para != QPointF(0, 0)) { pointToProject = para; } else { pointToProject = recItem.center(); } QPointF relPos = pointToProject - p1; qreal dot = QPointF::dotProduct(relPos, vec) / (busLine.length() * busLine.length()); dot = qBound(0.0, dot, 1.0); projection = p1 + dot * vec; } return projection; } ItemPort* BaseModel::getClosestUnusedPort(QMap mapPorts,GraphicsBaseItem* item,ModelFunctionType nType) { QMap mapDistance; // 收集所有端口及其距离 for(auto& port: mapPorts) { double dis = distanceBetweenItems(port, item); mapDistance.insert(dis, port); } for(auto& port:mapDistance){ //从小到大遍历 auto lst = TopologyManager::instance().getConnectionsForTerminal(port->getId(),nType); if(lst.isEmpty()){ //没被占用 return port; } } return nullptr; } ItemPort* BaseModel::selectBusOrNodePort( GraphicsBaseItem* pBusOrNode, GraphicsBaseItem* pOther, ModelFunctionType nType) { ItemPort* pPort = nullptr; int nTypeSelf = pBusOrNode->getProperty()->type(); if (nTypeSelf == 1) // 母线 { int index = pBusOrNode->addPort( p_movable, pBusOrNode->mapFromScene( calculateBusPortPos(pBusOrNode, pOther))); createTopoTerminalsByItem(pBusOrNode, nType); pPort = pBusOrNode->getPortPtr(index); } else // 节点 { int index = pBusOrNode->addPort( p_movable, QPoint(0,0)); createTopoTerminalsByItem(pBusOrNode, nType); pPort = pBusOrNode->getPortPtr(index); } return pPort; } ItemPort* BaseModel::selectDevicePortByMode( GraphicsBaseItem* pDevice, GraphicsBaseItem* pPeer, int nMode, int nParam, ModelFunctionType nType) { ItemPort* pPort = nullptr; QMap mapPorts = pDevice->getPorts(); if (nMode == 0) { pPort = getClosestUnusedPort(mapPorts, pPeer, nType); } else if (nMode == 1) // 中性点 { for (auto& port : mapPorts) { if (port->getType() == T_newTral) { int pos = port->portPos(); if ((nParam == 0 && pos == P_top) || (nParam == 1 && (pos == P_left || pos == P_right)) || (nParam == 2 && pos == P_down)) { pPort = port; break; } } } } else if (nMode == 2) // 非中性点 { for (auto& port : mapPorts) { if (port->getType() != T_newTral) { int pos = port->portPos(); if ((nParam == 0 && pos == P_top) || (nParam == 1 && (pos == P_left || pos == P_right)) || (nParam == 2 && pos == P_down)) { pPort = port; break; } } } } return pPort; } void BaseModel::selectNormalDevicePort( GraphicsBaseItem* pSrc, GraphicsBaseItem* pDest, int nMode, int nParam, ModelFunctionType nType, ItemPort*& pSrcPort, ItemPort*& pDestPort) { if (nMode == 1 || nMode == 2) { selectTransformerPort(pSrc, pDest, nMode, nParam, pSrcPort, pDestPort); } else { QMap mapSrc = pSrc->getPorts(); QMap mapDest = pDest->getPorts(); for (auto& port : mapSrc) if (port->getType() == T_lineOut) pSrcPort = port; for (auto& port : mapDest) if (port->getType() == T_lineIn) pDestPort = port; } } void BaseModel::selectTransformerPort( GraphicsBaseItem* pSrc, GraphicsBaseItem* pDest, int nMode, int nParam, ItemPort*& pSrcPort, ItemPort*& pDestPort) { int nTypeSrc = pSrc->getProperty()->type(); int nTypeDest = pDest->getProperty()->type(); QMap mapSrc = pSrc->getPorts(); QMap mapDest = pDest->getPorts(); // ===== nMode == 1:连接中性点 ===== if (nMode == 1) { // src 是变压器 if (nTypeSrc == 15 || nTypeSrc == 16) { for (auto& port : mapSrc) { int nTpe = port->getType(); int nPos = port->portPos(); if (nTpe == T_newTral) { if (nParam == 0 && nPos == P_top) { pSrcPort = port; break; } else if (nParam == 1 && (nPos == P_left || nPos == P_right)) { pSrcPort = port; break; } else if (nParam == 2 && nPos == P_down) { pSrcPort = port; break; } } } for (auto& port : mapDest) { if (port->getType() == T_lineIn) { pDestPort = port; break; } } } // dest 是变压器 else if (nTypeDest == 15 || nTypeDest == 16) { for (auto& port : mapSrc) { if (port->getType() == T_lineIn) { pSrcPort = port; break; } } for (auto& port : mapDest) { int nTpe = port->getType(); int nPos = port->portPos(); if (nTpe == T_newTral) { if (nParam == 0 && nPos == P_top) { pDestPort = port; break; } else if (nParam == 1 && (nPos == P_left || nPos == P_right)) { pDestPort = port; break; } else if (nParam == 2 && nPos == P_down) { pDestPort = port; break; } } } } } // ===== nMode == 2:连接非中性点 ===== else if (nMode == 2) { // src 是变压器 if (nTypeSrc == 15 || nTypeSrc == 16) { for (auto& port : mapSrc) { int nTpe = port->getType(); int nPos = port->portPos(); if (nTpe != T_newTral) { if (nParam == 0 && nPos == P_top) { pSrcPort = port; break; } else if (nParam == 1 && (nPos == P_left || nPos == P_right)) { pSrcPort = port; break; } else if (nParam == 2 && nPos == P_down) { pSrcPort = port; break; } } } int transType = 0; if (pSrcPort) transType = pSrcPort->getType(); for (auto& port : mapDest) { if (transType == T_lineOut && port->getType() == T_lineIn) { pDestPort = port; break; } else if (transType == T_lineIn && port->getType() == T_lineOut) { pDestPort = port; break; } } } // dest 是变压器 else if (nTypeDest == 15 || nTypeDest == 16) { for (auto& port : mapDest) { int nTpe = port->getType(); int nPos = port->portPos(); if (nTpe != T_newTral) { if (nParam == 0 && nPos == P_top) { pDestPort = port; break; } else if (nParam == 1 && (nPos == P_left || nPos == P_right)) { pDestPort = port; break; } else if (nParam == 2 && nPos == P_down) { pDestPort = port; break; } } } int transType = 0; if (pDestPort) transType = pDestPort->getType(); for (auto& port : mapSrc) { if (transType == T_lineOut && port->getType() == T_lineIn) { pSrcPort = port; break; } else if (transType == T_lineIn && port->getType() == T_lineOut) { pSrcPort = port; break; } } } } } void BaseModel::selectBusToBusPorts( GraphicsBaseItem* pSrc, GraphicsBaseItem* pDest, ModelFunctionType nType, ItemPort*& pSrcPort, ItemPort*& pDestPort) { int idx = pSrc->addPort( p_movable, pSrc->mapFromScene( calculateBusPortPos(pSrc, pDest))); createTopoTerminalsByItem(pSrc, nType); pSrcPort = pSrc->getPortPtr(idx); idx = pDest->addPort( p_movable, pDest->mapFromScene( calculateBusPortPos(pDest, pSrc))); createTopoTerminalsByItem(pDest, nType); pDestPort = pDest->getPortPtr(idx); } template void BaseModel::bindLineAndTopology( ItemPort* pSrcPort, ItemPort* pDestPort, TypeLine* pItem, GraphicsBaseItem* pSrc, GraphicsBaseItem* pDest, ModelFunctionType nType) { if (!pSrcPort || !pDestPort) return; pItem->setStartPoint(pSrcPort->scenePos()); pItem->setEndPoint(pDestPort->scenePos()); pItem->calculatePath(); PowerConnection* pCon = TopologyManager::instance().createConnection( pItem->itemId().toString(), pSrcPort->getId(), pDestPort->getId(), pSrc->itemId().toString(), pDest->itemId().toString(), nType); if (pCon) pCon->setState(DataState::Changed); pItem->getProperty()->setConnection( Connection( pSrc->itemId(), QUuid(pSrcPort->getId()), pSrcPort->getType(), pSrcPort->portPos(), pDest->itemId(), QUuid(pDestPort->getId()), pDestPort->getType(), pDestPort->portPos())); } template void BaseModel::establishConnection( GraphicsBaseItem* pSrc, GraphicsBaseItem* pDest, TypeLine* pItem, ModelFunctionType nType, int nMode, int nParam) { ItemPort* pSrcPort = nullptr; ItemPort* pDestPort = nullptr; auto pSrcData = pSrc->getProperty(); auto pDestData = pDest->getProperty(); int nTypeSrc = 0; int nTypeDest = 0; if(pSrcData) nTypeSrc = pSrcData->type(); if(pDestData) nTypeDest = pDestData->type(); // ===== 场景 1:源是母线或节点 ===== if ((nTypeSrc == 1 || nTypeSrc == 0) && (nTypeDest != 1 && nTypeDest != 0)) { pSrcPort = selectBusOrNodePort(pSrc, pDest, nType); pDestPort = selectDevicePortByMode(pDest, pSrc, nMode, nParam, nType); } // ===== 场景 2:目标是母线或节点 ===== else if ((nTypeDest == 1 || nTypeDest == 0) && (nTypeSrc != 1 && nTypeSrc != 0)) { pDestPort = selectBusOrNodePort(pDest, pSrc, nType); pSrcPort = selectDevicePortByMode(pSrc, pDest, nMode, nParam, nType); } // ===== 场景 3:两端都是母线或节点 ===== else if ((nTypeSrc == 1 || nTypeSrc == 0) && (nTypeDest == 1 || nTypeDest == 0)) { selectBusToBusPorts(pSrc, pDest, nType, pSrcPort, pDestPort); } // ===== 场景 4:普通设备 ↔ 设备 ===== else { selectNormalDevicePort(pSrc, pDest, nMode, nParam, nType, pSrcPort, pDestPort); } // ===== 绑定 ===== bindLineAndTopology(pSrcPort, pDestPort, pItem, pSrc, pDest, nType); } /*template void BaseModel::establishConnection(GraphicsBaseItem* pSrc,GraphicsBaseItem* pDest,TypeLine* pItem,ModelFunctionType nType,int nMode,int nParam) { ItemPort* pSrcPort = nullptr; ItemPort* pDestPort = nullptr; int nTypeSrc = pSrc->getProperty()->type(); int nTypeDest = pDest->getProperty()->type(); //if(pSrc->getItemType() == GIT_baseBus) if((nTypeSrc == 1 || nTypeSrc == 0) && (nTypeDest != 1 && nTypeDest != 0)) //src是母线或节点 { int index = 0; if(nTypeSrc == 1 ) index = pSrc->addPort(p_movable,pSrc->mapFromScene(calculateBusPortPos(pSrc,pDest))); else index = pSrc->addPort(p_movable,QPoint(0,0)); //节点port与自身坐标重合 createTopoTerminalsByItem(pSrc,nType); pSrcPort = pSrc->getPortPtr(index); QMap mapPorts = pDest->getPorts(); if(nMode == 0){ pDestPort = getClosestUnusedPort(mapPorts,pSrc,nType); } else if(nMode == 1){ for(auto& port:mapPorts) //连接中性点 { int nTpe = port->getType(); int nPos = port->portPos(); if(nTpe == T_newTral){ if(nParam == 0){ if(nPos == P_top){ pDestPort = port; } } else if(nParam == 1){ if(nPos == P_left || nPos == P_right){ pDestPort = port; } } else if(nParam == 2){ if(nPos == P_down){ pDestPort = port; } } } } } else if(nMode == 2){ for(auto& port:mapPorts) //连接非中性点 { int nTpe = port->getType(); int nPos = port->portPos(); if(nTpe != T_newTral){ if(nParam == 0){ if(nPos == P_top){ pDestPort = port; } } else if(nParam == 1){ if(nPos == P_left || nPos == P_right){ pDestPort = port; } } else if(nParam == 2){ if(nPos == P_down){ pDestPort = port; } } } } } } else if((nTypeDest == 1 || nTypeDest == 0) && (nTypeSrc != 1 && nTypeSrc != 0)) { int index = 0; if(nTypeDest == 1 ) index = pDest->addPort(p_movable,pDest->mapFromScene(calculateBusPortPos(pDest,pSrc))); else index = pDest->addPort(p_movable,QPoint(0,0)); //节点port与自身坐标重合 createTopoTerminalsByItem(pDest,nType); pDestPort = pDest->getPortPtr(index); QMap mapPorts = pSrc->getPorts(); if(nMode == 0){ pSrcPort = getClosestUnusedPort(mapPorts,pDest,nType); } else if(nMode == 1){ for(auto& port:mapPorts) //连接中性点 { int nTpe = port->getType(); int nPos = port->portPos(); if(nTpe == T_newTral){ if(nParam == 0){ if(nPos == P_top){ pSrcPort = port; } } else if(nParam == 1){ if(nPos == P_left || nPos == P_right){ pSrcPort = port; } } else if(nParam == 2){ if(nPos == P_down){ pSrcPort = port; } } } } } else if(nMode == 2){ for(auto& port:mapPorts) //连接非中性点 { int nTpe = port->getType(); int nPos = port->portPos(); if(nTpe != T_newTral){ if(nParam == 0){ if(nPos == P_top){ pSrcPort = port; } } else if(nParam == 1){ if(nPos == P_left || nPos == P_right){ pSrcPort = port; } } else if(nParam == 2){ if(nPos == P_down){ pSrcPort = port; } } } } } } else if((nTypeSrc == 1 || nTypeSrc == 0) && (nTypeDest == 1 || nTypeDest == 0)){ //两个都是母线或节点 int index = 0; if(nTypeSrc == 1 ) index = pSrc->addPort(p_movable,pSrc->mapFromScene(calculateBusPortPos(pSrc,pDest))); else index = pSrc->addPort(p_movable,QPoint(0,0)); //节点port与自身坐标重合 createTopoTerminalsByItem(pSrc,nType); pSrcPort = pSrc->getPortPtr(index); index = 0; if(nTypeDest == 1 ) index = pDest->addPort(p_movable,pDest->mapFromScene(calculateBusPortPos(pDest,pSrc))); else index = pDest->addPort(p_movable,QPoint(0,0)); //节点port与自身坐标重合 createTopoTerminalsByItem(pDest,nType); pDestPort = pDest->getPortPtr(index); } else { QMap mapSrc = pSrc->getPorts(); QMap mapDest = pDest->getPorts(); pSrcPort = nullptr; pDestPort = nullptr; if(nMode == 1){ //连接中性点 if(nTypeSrc == 15 || nTypeSrc == 16){ //src是变压器中性点 for(auto& port:mapSrc) //连接中性点 { int nTpe = port->getType(); int nPos = port->portPos(); if(nTpe == T_newTral){ if(nParam == 0){ if(nPos == P_top){ pSrcPort = port; } } else if(nParam == 1){ if(nPos == P_left || nPos == P_right){ pSrcPort = port; } } else if(nParam == 2){ if(nPos == P_down){ pSrcPort = port; } } } } for(auto& port:mapDest) { if(port->getType() == T_lineIn) { pDestPort = port; break; } } } else if(nTypeDest == 15 || nTypeDest == 16){ //dest是变压器中性点 for(auto& port:mapSrc) { if(port->getType() == T_lineIn) //始终从中性点出 { pSrcPort = port; break; } } for(auto& port:mapDest) //连接中性点 { int nTpe = port->getType(); int nPos = port->portPos(); if(nTpe == T_newTral){ if(nParam == 0){ if(nPos == P_top){ pDestPort = port; } } else if(nParam == 1){ if(nPos == P_left || nPos == P_right){ pDestPort = port; } } else if(nParam == 2){ if(nPos == P_down){ pDestPort = port; } } } } } } else if(nMode == 2){ //连接变压器 if(nTypeSrc == 15 || nTypeSrc == 16){ //src是变压器 for(auto& port:mapSrc) { int nTpe = port->getType(); int nPos = port->portPos(); if(nTpe != T_newTral){ if(nParam == 0){ if(nPos == P_top){ pSrcPort = port; } } else if(nParam == 1){ if(nPos == P_left || nPos == P_right){ pSrcPort = port; } } else if(nParam == 2){ if(nPos == P_down){ pSrcPort = port; } } } } int transType = 0; if(pSrcPort){ transType = pSrcPort->getType(); } for(auto& port:mapDest) //根据变压器端点选择连接端点类型 { if(transType == T_lineOut) { if(port->getType() == T_lineIn) { pDestPort = port; break; } } else{ if(port->getType() == T_lineOut) { pDestPort = port; break; } } } } else if(nTypeDest == 15 || nTypeDest == 16){ //dest是变压器 for(auto& port:mapDest) { int nTpe = port->getType(); int nPos = port->portPos(); if(nTpe != T_newTral){ if(nParam == 0){ if(nPos == P_top){ pDestPort = port; } } else if(nParam == 1){ if(nPos == P_left || nPos == P_right){ pDestPort = port; } } else if(nParam == 2){ if(nPos == P_down){ pDestPort = port; } } } } int transType = 0; if(pDestPort){ transType = pDestPort->getType(); } for(auto& port:mapSrc) //根据变压器端点选择连接端点类型 { if(transType == T_lineOut) { if(port->getType() == T_lineIn) { pSrcPort = port; break; } } else{ if(port->getType() == T_lineOut) { pSrcPort = port; break; } } } } } else{ for(auto& port:mapSrc) { if(port->getType() == T_lineOut) { pSrcPort = port; break; } } for(auto& port:mapDest) { if(port->getType() == T_lineIn) { pDestPort = port; break; } } } } if(pSrcPort && pDestPort) { QPointF srcPortPos = pSrcPort->scenePos(); QPointF destPortPos = pDestPort->scenePos(); pItem->setStartPoint(srcPortPos); pItem->setEndPoint(destPortPos); pItem->calculatePath(); PowerConnection* pCon = TopologyManager::instance().createConnection(pItem->itemId().toString(),pSrcPort->getId(),pDestPort->getId(),pSrc->itemId().toString(),pDest->itemId().toString(),nType); //创建拓扑连接(逻辑) if(pCon) pCon->setState(DataState::Changed); pItem->getProperty()->setConnection(Connection(pSrc->itemId(),QUuid(pSrcPort->getId()),pSrcPort->getType(),pSrcPort->portPos(),pDest->itemId(),QUuid(pDestPort->getId()),pDestPort->getType(),pDestPort->portPos())); } }*/ template void BaseModel::establishConnection(GraphicsBaseItem*,GraphicsBaseItem*,ElectricBaseModelLineItem*,ModelFunctionType,int,int);