GridFrame/diagramCavas/source/graphicsDataModel/baseModel.cpp

776 lines
25 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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<QString,ItemPort*> 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<QString,ItemPort*> mapPorts,GraphicsBaseItem* item,ModelFunctionType nType)
{
QMap<double,ItemPort*> 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<QString, ItemPort*> 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<QString, ItemPort*> mapSrc = pSrc->getPorts();
QMap<QString, ItemPort*> 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<QString, ItemPort*> mapSrc = pSrc->getPorts();
QMap<QString, ItemPort*> mapDest = pDest->getPorts();
// src 是变压器
if (nTypeSrc == 15 || nTypeSrc == 16)
{
for (auto& port : mapSrc)
{
int tpe = port->getType();
int pos = port->portPos();
if (tpe != T_newTral)
{
if ((nParam == 0 && pos == P_top) ||
(nParam == 1 && (pos == P_left || pos == P_right)) ||
(nParam == 2 && pos == P_down))
{
pSrcPort = port;
break;
}
}
}
int transType = pSrcPort ? pSrcPort->getType() : 0;
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 tpe = port->getType();
int pos = port->portPos();
if (tpe != T_newTral)
{
if ((nParam == 0 && pos == P_top) ||
(nParam == 1 && (pos == P_left || pos == P_right)) ||
(nParam == 2 && pos == P_down))
{
pDestPort = port;
break;
}
}
}
int transType = pDestPort ? pDestPort->getType() : 0;
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<typename TypeLine>
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<typename TypeLine>
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<typename TypeLine> 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<QString,ItemPort*> 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<QString,ItemPort*> 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<QString,ItemPort*> mapSrc = pSrc->getPorts();
QMap<QString,ItemPort*> 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<ElectricBaseModelLineItem>(GraphicsBaseItem*,GraphicsBaseItem*,ElectricBaseModelLineItem*,ModelFunctionType,int,int);