电流流动效果实现

来源:互联网 发布:宝宝取名软件 编辑:程序博客网 时间:2024/04/30 09:21

前几天,到航天部实施项目,用户提出需求:希望电路分析后,能显示电路中电流流动效果。 回想起以前电力系统用户希望的电力接线图中潮流的需求,觉得这件事应该做一做了。

粗一想,不好做,但深入一想也容易解决,因此,花了一天时间,结果还令人满意。
大致应该分以下几步:
1.         设计处理对象及其成员与函数
2.         解决流动效果
3.         根据连接关系与分析结果确定各导线中电流方向
4.         联调
 
直观地想,电流流动效果应在导线中处理,在其每条线段中应知道如何画出效果。
首先,应由窗口进行调用或触发,演示时应有时钟。
加入TTimer *Timer_FlowEffect;
具体事务函数: void __fastcall ShowFlowEffect();
void __fastcall TCbwGraphBaseForm::ShowFlowEffect()
{
   Timer_FlowEffect
->Enabled = !Timer_FlowEffect->Enabled;
   FlushVector(FDemoLines, 
false);
   
if(Timer_FlowEffect->Enabled)
   
{
      GetBranchSimulateModule();
      FBranchSimulateModule
->DemoEffect(FDemoLines);
      vector
<TPin *> inPins, outPins;   
      CBW_ITERATOR(CbwObjects, FObjects)
      
{
         TWire 
* wire = dynamic_cast<TWire *>(*it);
         
if(wire)
            wire
->ShowDemoEffect(FDemoLines, inPins, outPins);
      }

   }

   
else
      RefreshCurrentScreen();
}

Timer_FlowEffectOnTimer事件中,进行动态显示效果展示而在导线类中加入演示效果处理函数:

void __fastcall TCbwGraphBaseForm::Timer_FlowEffectTimer(TObject *Sender)
{
   
static int count = 0;
   
int deltaLength = 10;
   
if(++count >= deltaLength)   count = 0;
   TCbwBrushData 
* brushData = new TCbwBrushData;
   brushData
->BrushStyle = cbgtGradient;
   brushData
->MixStyle = true;
   Gdiplus::Graphics graphics(PaintBox
->Canvas->Handle, ' ');
   CBW_ITERATOR(WireLines, FDemoLines)
   
{
      
double w = (*it)->LineWidth;
      
if(w < 2)   w = 2;
      brushData
->Color1 = (*it)->LineColor;
      brushData
->Color2 = 0xFFFFFF - brushData->Color1;
      RECT r 
= (*it)->Border->Rect;
      TRect clientRect 
= TRect(r.left, r.top, r.right, r.bottom);
      TRect brushRect;
      
switch((*it)->WireDirection)
      
{
      
case ctwdHorz:
         brushData
->BackgroundStyle = 0;
         
if((*it)->DemoDirection == clddForward)
            brushRect 
= TRect(clientRect.left + count, clientRect.top, clientRect.left + count + deltaLength, clientRect.bottom);
         
else
            brushRect 
= TRect(clientRect.right - count - deltaLength, clientRect.top, clientRect.right - count, clientRect.bottom);
         
break;
      
case ctwdVert:
         brushData
->BackgroundStyle = 1;
         
if((*it)->DemoDirection == clddForward)
            brushRect 
= TRect(clientRect.left, clientRect.top + count, clientRect.right, clientRect.top + count + deltaLength);
         
else
            brushRect 
= TRect(clientRect.left, clientRect.bottom - count - deltaLength, clientRect.right, clientRect.bottom - count);
         
break;
      }

      Gdiplus::Brush 
* brush1 = BrushByData(brushData, brushRect); //TRect(clientRect.left + count, clientRect.top, clientRect.left + count + deltaLength, clientRect.bottom);
      graphics.FillRectangle(brush1,
               
int(clientRect.left),
               
int(clientRect.top),
               
int(clientRect.right - clientRect.left),
               
int(clientRect.bottom - clientRect.top));
      delete brush1;
   }

   delete brushData;
}

 

void __fastcall TWire::ShowDemoEffect(WireLines& lines, vector<TPin *>& inPins, vector<TPin *>& outPins)
{
   vector
<TPad *> allPads, inPads, outPads;
   
for(int i = 0; i < MetaNumber; ++i)
   
{
      CBW_MACRO_CAST(TPad, pad, Meta(i));
      CBW_CONDITION_CONTINUE(
!pad);
      allPads.push_back(pad);
      
if(pad->Tag == 1)
         inPads.push_back(pad);
      
if(pad->Tag == -1)
         outPads.push_back(pad);
   }

   vector
<TWireLine *> inLines;
   
while(inPads.size())
   
{
      TPad 
* pad = inPads[0];
      vector
<TWireLine *> allLines;
      TWireLine 
* line = NULL;      // 找到对应子导线
      for(int i = 0; i < pad->ConnectedPointList->Count; ++i)
      
{
         TConnectPoint 
* cp = (TConnectPoint *)(pad->ConnectedPointList->Items[i]);
         line 
= dynamic_cast<TWireLine *>(cp->ParentLine);
         
if(!line)   continue;
         
if(AddItemToVector(inLines, line))
            allLines.push_back(line);
         
else
            line 
= NULL;
      }
 
      CBW_ITERATOR(vector
<TWireLine *>, allLines)
      
{
         line 
= *it;
         TPad 
* otherPad = line->BeginConnectPoint->Pad;
         
if(otherPad == pad)  otherPad = line->EndConnectPoint->Pad;
         
bool reverseFlag = false;
         
if(line->WireDirection == ctwdHorz)
            reverseFlag 
= (otherPad && otherPad->CentralPoint.x < pad->CentralPoint.x);
         
else
            reverseFlag 
= (otherPad && otherPad->CentralPoint.y < pad->CentralPoint.y);
         line
->DemoDirection = reverseFlag;
         
if(otherPad)
         
{
            
if(otherPad->Tag != -2)
               lines.push_back(line);
            
if(otherPad->Tag == 0)
            
{
               otherPad
->Tag = 1;
               
if(IndexOfItemInVector(inPads, otherPad) == -1)
                  inPads.push_back(otherPad);
            }

         }

      }

      inPads.erase(inPads.begin());
   }

}

 

enum CbwLineDemoDirection
{  // 导线演示方向
   clddForward,         // 前向: 左->右, 上->下
   clddReverse,         // 反向: 右->左, 下->上
   clddNone           // 无效果
}
;

 

   CbwLineDemoDirection  FDemoDirection;
__property CbwLineDemoDirection DemoDirection 
= { read = FDemoDirection, write = FDemoDirection};
这里,需要设计一个类型并在子导线类中加入成员 
到目前为止,若简单地设置导线的各子导线对象的DemoDirection为true或false,运行,发现效果已出现。YEAH。
 

剩下的事就是根据连接关系确定电流的真正流向,以此确定各导线的子导线的DemoDirection,该项工作可由仿真模块完成,因其中已建立了电路的连接关系模型。加入DemoEffect处理函数即可。

 

void __fastcall TCbwBranchModule::DemoEffect(WireLines& lines)
{
   
if(FSubModules.size())
      CBW_ITERATOR(vector
<TCbwBranchModule *>, FSubModules)
         (
*it)->DemoEffect(lines);
   
else
   
{  
      vector
<TPin *> inPins, outPins;
      vector
<TCbwNode *> inNodes, outNodes;
      AllInOutPins(inPins, outPins, inNodes, outNodes);
      CBW_ITERATOR(vector
<TCbwSimulateBranch *>, FSimulateBranches)
         (
*it)->ForwardFlag = false;

      CBW_ITERATOR(vector
<TPin *>, inPins)
         SetIOStatus(
*it, 1);
         
      vector
<TCbwBranch *> foundBranches;
      
while(inNodes.size())
      
{
         TCbwNode 
* node = inNodes[0];
         vector
<TCbwBranch *> branchesToCheck;
         CBW_ITERATOR(vector
<TCbwSimulateBranch *>, FSimulateBranches)
         
{
            TCbwBranch 
* branch = (*it)->BranchByNode(node, inNodes);
            
if(!branch) continue;
            
if(IndexOfItemInVector(foundBranches, branch) != -1)  continue;
            foundBranches.push_back(branch);
            branchesToCheck.push_back(branch);
         }

         CBW_ITERATOR(vector
<TCbwBranch *>, branchesToCheck)
            BranchWork(
*it, inNodes);
         inNodes.erase(inNodes.begin());
      }

   }

}

 对于仿真支路对象,则需要由节点返回其相应电路支路,设计一个函数。 

TCbwBranch * __fastcall TCbwSimulateBranch::BranchByNode(TCbwNode * node, vector<TCbwNode *>& inNodes)
{
   TCbwNode 
* currentNode = FBeginNode;
   
if(IndexOfItemInVector(inNodes, currentNode) != -1)
      FForwardFlag 
= true;
   CBW_ITERATOR(TCbwBranches, FBranches)
   
{
      
if(currentNode == node && FForwardFlag)  return *it;
      currentNode 
= (*it)->OtherNode(currentNode);
      
if(currentNode == node && !FForwardFlag)  return *it;
   }

   
return NULL;   
}
OK,现在再运行一把,万事OK,效果已达到预期。
可访问http://www.drgraph.com/download/flowDemo.swf查看效果
原创粉丝点击