GridFrame/diagramCavas/source/graphicsDataModel/baseModel.cpp

463 lines
16 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;
}
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);