GME  13
AutoRouterGraph.cpp
Go to the documentation of this file.
00001 // AutoRouterGraph.cpp : Implementation of CAutoRouterGraph
00002 
00003 #include "stdafx.h"
00004 #include "AutoRouterGraph.h"
00005 #include "AutoRouterBox.h"
00006 #include "AutoRouterPort.h"
00007 #include "AutoRouterPath.h"
00008 #include "AutoRouterEdge.h"
00009 
00010 
00011 // --- CAutoRouterGraph
00012 
00013 CAutoRouterGraph::CAutoRouterGraph():
00014         horizontal(true),
00015         vertical(false)
00016 {
00017         horizontal.SetOwner(this);
00018         vertical.SetOwner(this);
00019 
00020         CalculateSelfPoints();
00021         AddSelfEdges();
00022 }
00023 
00024 // --- Boxes
00025 
00026 void CAutoRouterGraph::Remove(CAutoRouterBox* box)
00027 {
00028         DeleteBoxAndPortEdges(box);
00029 
00030         std::vector<CAutoRouterPath*>::iterator iter;
00031         iter = paths.begin();
00032         
00033         while(iter != paths.end())
00034         {
00035                 bool iteratorChanged = false;
00036 
00037                 CAutoRouterPath* path = *iter;
00038 
00039                 CAutoRouterPort* startPort = path->GetStartPort();
00040                 ASSERT(startPort != NULL);
00041                 CAutoRouterBox* startbox = startPort->GetOwner();
00042 
00043                 CAutoRouterPort* endPort = path->GetEndPort();
00044                 ASSERT(endPort != NULL);
00045                 CAutoRouterBox* endbox = endPort->GetOwner();
00046 
00047                 if( (startbox == box || endbox == box) )
00048                 {
00049                         //DeletePath:
00050                         if (path->HasOwner())
00051                         {
00052                                 DeleteEdges(path);
00053                                 path->SetOwner(NULL);
00054 
00055                                 iter = paths.erase(iter);
00056                                 iteratorChanged = true;
00057                         }
00058 
00059                         path->Destroy();        // ??
00060                 }
00061 
00062                 if (!iteratorChanged)
00063                         ++iter;
00064         }
00065 
00066         box->SetOwner(NULL);
00067 
00068         std::vector<CAutoRouterBox*>::iterator iter2 = std::find(boxes.begin(), boxes.end(), box);
00069 
00070         if (iter2 != boxes.end())
00071         {
00072                 boxes.erase(iter2);
00073         }
00074         else
00075         {
00076                 //error
00077                 ASSERT(false);
00078         }
00079 }
00080 
00081 void CAutoRouterGraph::DeleteAllBoxes()
00082 {
00083         for (CAutoRouterBoxList::size_type i = 0; i < boxes.size(); i++)
00084         {
00085                 //DeleteBoxAndPortEdges(boxes[i]);      // no need: there's a DeleteAllEdges in DeleteAll
00086                 boxes[i]->Destroy();
00087                 delete boxes[i];
00088         }
00089 
00090         boxes.clear();
00091 }
00092 
00093 CAutoRouterBox* CAutoRouterGraph::GetBoxAt(const CPoint& point, int nearness) const
00094 {
00095         std::vector<CAutoRouterBox*>::const_iterator iter = boxes.begin();
00096         while (iter != boxes.end())
00097         {
00098                 if ((*iter)->IsBoxAt(point, nearness))
00099                         return (*iter);
00100 
00101                 ++iter;
00102         }
00103 
00104         return NULL;
00105 }
00106 
00107 void CAutoRouterGraph::SetPortAttr(CAutoRouterPort* port, unsigned int attr)
00108 {
00109         DisconnectPathsFrom(port);
00110         port->SetAttributes(attr);
00111 }
00112 
00113 bool CAutoRouterGraph::IsRectClipBoxes(const CRect& rect) const
00114 {
00115         for (CAutoRouterBoxList::size_type i = 0; i < boxes.size(); i++)
00116         {
00117                 const CRect boxRect = boxes[i]->GetRect();
00118                 if( IsRectClip(rect, boxRect) )
00119                         return true;
00120         }
00121         return false;
00122 }
00123 
00124 bool CAutoRouterGraph::IsLineClipBoxes(const CPoint& p1, const CPoint& p2) const
00125 {
00126         CRect rect(p1, p2);
00127         rect.NormalizeRect();
00128         ASSERT( rect.left == rect.right || rect.top == rect.bottom );
00129 
00130         if( rect.left == rect.right)
00131                 rect.right++;
00132         if( rect.top == rect.bottom )
00133                 rect.bottom++;
00134 
00135         return IsRectClipBoxes(rect);
00136 }
00137 
00138 bool CAutoRouterGraph::CanBoxAt(const CRect& rect) const
00139 {
00140         return !IsRectClipBoxes(InflatedRect(rect, 1));
00141 }
00142 
00143 void CAutoRouterGraph::Add(CAutoRouterPath* path)
00144 {
00145         ASSERT( path != NULL );
00146         ASSERT(!path->HasOwner());
00147 
00148         path->SetOwner(this);
00149 
00150         paths.push_back(path);
00151 
00152         AddEdges(path);
00153 
00154 #ifdef _DEBUG
00155         AssertValidPath(path);
00156 #endif
00157 }
00158 
00159 void CAutoRouterGraph::Remove(CAutoRouterPath* path)
00160 {
00161         DeleteEdges(path);
00162 
00163         path->SetOwner(NULL);
00164 
00165         std::vector<CAutoRouterPath*>::iterator iter = std::find(paths.begin(), paths.end(), path);
00166 
00167         if (iter != paths.end())
00168         {
00169                 paths.erase(iter);
00170         }
00171         else
00172         {
00173                 //error
00174                 ASSERT(false);
00175         }
00176 }
00177 
00178 void CAutoRouterGraph::DeleteAllPaths()
00179 {
00180         std::vector<CAutoRouterPath*>::iterator iter;
00181         iter = paths.begin();
00182 
00183         while (iter != paths.end())
00184         {
00185                 //DeleteEdges(*iter);   // no need: there's a DeleteAllEdges in DeleteAll
00186 
00187                 (*iter)->SetOwner(NULL);
00188                 (*iter)->Destroy();
00189                 delete (*iter);
00190                 ++iter;
00191         }
00192 
00193         paths.clear();
00194 }
00195 
00196 CAutoRouterEdge* CAutoRouterGraph::GetListEdgeAt(const CPoint& point, int nearness) const
00197 {
00198         CAutoRouterEdge* edge;
00199 
00200         edge = horizontal.GetEdgeAt(point, nearness);
00201         if( edge )
00202                 return edge;
00203 
00204         return vertical.GetEdgeAt(point, nearness);
00205 }
00206 
00207 // --- Boxes && Paths
00208 
00209 CRect CAutoRouterGraph::GetSurroundRect(void) const
00210 {
00211         CRect rect(0,0,0,0);
00212 
00213         for (CAutoRouterBoxList::size_type i = 0; i < boxes.size(); i++)
00214         {
00215                 rect |= boxes[i]->GetRect();
00216         }
00217 
00218         for (CAutoRouterPathList::size_type i = 0; i < paths.size(); i++)
00219         {
00220                 rect |= paths[i]->GetSurroundRect();
00221         }
00222 
00223         return rect;
00224 }
00225 
00226 CAutoRouterBox* CAutoRouterGraph::GetOutOfBox(CPoint& point, RoutingDirection dir) const
00227 {
00228         ASSERT( IsRightAngle(dir) );
00229 
00230         CAutoRouterBox* boxby = NULL;
00231 
00232         std::vector<CAutoRouterBox*>::const_iterator iter = boxes.begin();
00233 
00234         while (iter != boxes.end())
00235         {
00236                 const CRect boxRect = (*iter)->GetRect();
00237                 if( boxRect.PtInRect(point) )
00238                 {
00239                         boxby = *iter;
00240                         iter = boxes.begin();
00241 
00242                         GetPointCoord(point, dir) = GetRectOuterCoord(boxRect, dir);
00243                 }
00244                 ++iter;
00245         }
00246 
00247         return boxby;
00248 }
00249 
00250 CAutoRouterBox* CAutoRouterGraph::GoToNextBox(CPoint& point, RoutingDirection dir, long stophere) const
00251 {
00252         ASSERT( IsRightAngle(dir) );
00253         ASSERT( GetPointCoord(point, dir) != stophere );
00254 
00255         CAutoRouterBox* boxby = NULL;
00256 
00257         std::vector<CAutoRouterBox*>::const_iterator iter = boxes.begin();
00258 
00259         while (iter != boxes.end())
00260         {
00261                 const CRect boxRect = (*iter)->GetRect();
00262                 if( IsPointInDirFrom(point, boxRect, ReverseDir(dir)) &&
00263                         IsPointBetweenSides(point, boxRect, dir) &&
00264                         IsCoordInDirFrom(stophere, GetRectOuterCoord(boxRect, ReverseDir(dir)), dir) )
00265                 {
00266                         stophere = GetRectOuterCoord(boxRect, ReverseDir(dir));
00267                         boxby = *iter;
00268                 }
00269                 ++iter;
00270         }
00271 
00272         GetPointCoord(point, dir) = stophere;
00273 
00274         return boxby;
00275 }
00276 
00277 void CAutoRouterGraph::GetLimitsOfEdge(const CPoint& startPt, const CPoint& endPt, long& min, long& max) const
00278 {
00279         long t;
00280         CPoint start = startPt;
00281         CPoint end = endPt;
00282 
00283         std::vector<CAutoRouterBox*>::const_iterator iter = boxes.begin();
00284 
00285         if( start.y == end.y )
00286         {
00287                 if( start.x > end.x )
00288                 {
00289                         t = start.x;
00290                         start.x = end.x;
00291                         end.x = t;
00292                 }
00293 
00294                 while( iter != boxes.end())
00295                 {
00296                         const CRect rect = (*iter)->GetRect();
00297                         ++iter;
00298 
00299                         if(start.x < rect.right && rect.left <= end.x)
00300                         {
00301                                 if( rect.bottom <= start.y && rect.bottom > min )
00302                                         min = rect.bottom;
00303                                 if( rect.top > start.y && rect.top < max )
00304                                         max = rect.top;
00305                         }
00306                 }
00307         }
00308         else
00309         {
00310                 ASSERT( start.x == end.x );
00311 
00312                 if( start.y > end.y )
00313                 {
00314                         t = start.y;
00315                         start.y = end.y;
00316                         end.y = t;
00317                 }
00318 
00319                 while( iter != boxes.end())
00320                 {
00321                         const CRect rect = (*iter)->GetRect();
00322                         ++iter;
00323 
00324                         if(start.y < rect.bottom && rect.top <= end.y)
00325                         {
00326                                 if( rect.right <= start.x && rect.right > min )
00327                                         min = rect.right;
00328                                 if( rect.left > start.x && rect.left < max )
00329                                         max = rect.left;
00330                         }
00331                 }
00332         }
00333 
00334         max--;
00335 }
00336 
00337 bool CAutoRouterGraph::Connect(CAutoRouterPath* path)
00338 {
00339         CAutoRouterPort* startport = path->GetStartPort();
00340         CAutoRouterPort* endport = path->GetEndPort();
00341 
00342         RoutingDirection startdir = path->GetStartDir();
00343         bool startportHasLimited = false;
00344         bool startportCanHave = true;
00345         if (startdir != Dir_None) {
00346                 startportHasLimited = startport->HasLimitedDirs();
00347                 startportCanHave = startport->CanHaveStartEndPointOn(startdir, true);
00348         }
00349         if( startdir == Dir_None ||                                                     // recalc startdir if empty
00350                 startportHasLimited && !startportCanHave)               // or is limited and userpref is invalid
00351         {
00352                 startdir = startport->GetStartEndDirTo(endport->GetCenter(), true);
00353         }
00354 
00355         RoutingDirection enddir = path->GetEndDir();
00356         bool endportHasLimited = false;
00357         bool endportCanHave = true;
00358         if (enddir != Dir_None) {
00359                 endportHasLimited = endport->HasLimitedDirs();
00360                 endportCanHave = endport->CanHaveStartEndPointOn(enddir, false);
00361         }
00362         if( enddir == Dir_None ||                                                       // like above
00363                 endportHasLimited && !endportCanHave)
00364         {
00365                 enddir = endport->GetStartEndDirTo(startport->GetCenter(), false, startport == endport ? startdir : Dir_None );
00366         }
00367 
00368         CPoint startpoint = startport->CreateStartEndPointOn(startdir);
00369         CPoint endpoint = endport->CreateStartEndPointOn(enddir);
00370 
00371         if( startpoint == endpoint )
00372                 startpoint = StepOneInDir(startpoint, NextClockwiseDir(startdir));
00373 
00374         return Connect(path, startpoint, endpoint);
00375 }
00376 
00377 bool CAutoRouterGraph::Connect(CAutoRouterPath* path, CPoint& startpoint, CPoint& endpoint)
00378 {
00379         ASSERT( path != NULL && path->GetOwner() == this );
00380         ASSERT( !path->IsConnected() );
00381         ASSERT( startpoint != endpoint );
00382 
00383         CAutoRouterPort* startPort = path->GetStartPort();
00384         ASSERT(startPort != NULL);
00385         RoutingDirection startdir = startPort->OnWhichEdge(startpoint);
00386 
00387         CAutoRouterPort* endPort = path->GetEndPort();
00388         ASSERT(endPort != NULL);
00389         RoutingDirection enddir = endPort->OnWhichEdge(endpoint);
00390         ASSERT( IsRightAngle(startdir) && IsRightAngle(enddir) );
00391 
00392         CPoint start = startpoint;
00393         GetOutOfBox(start, startdir);
00394         ASSERT( start != startpoint );
00395 
00396         CPoint end = endpoint;
00397         GetOutOfBox(end, enddir);
00398         ASSERT( end != endpoint );
00399 
00400         ASSERT( path->IsEmpty() );
00401 
00402         CPointListPath ret;
00403         bool isAutoRouted = path->IsAutoRouted();
00404         if (isAutoRouted)
00405                 ConnectPoints(ret, start, end, startdir, enddir);
00406 
00407         if (!isAutoRouted)
00408         {
00409                 CPointListPath ret2;
00410                 path->ApplyCustomizationsBeforeAutoConnectPoints(ret2);
00411 
00412                 if (ret2.GetCount() > 0)
00413                 {
00414                         ret.RemoveAll();
00415                         POSITION pos = ret2.GetHeadPosition();
00416                         while( pos != NULL )
00417                         {
00418                                 ret.AddTail(ret2.GetNext(pos));
00419                         }
00420                 }
00421         }
00422 
00423         path->DeleteAll();
00424 
00425         path->AddTail(startpoint);
00426         POSITION pos = ret.GetHeadPosition();
00427         while( pos != NULL )
00428         {
00429                 CPoint p = ret.GetNext(pos);
00430                 path->AddTail(p);
00431         }
00432         path->AddTail(endpoint);
00433 
00434         if (isAutoRouted) {
00435                 path->SimplifyTrivially();
00436                 SimplifyPathPoints(path);
00437                 CenterStairsInPathPoints(path, startdir, enddir);
00438         }
00439         path->SetState(ARPATHST_Connected);
00440 
00441         // Apply custom edge modifications - step 1
00442         // (Step 1: Move the desired edges - see in CAutoRouterGraph::Connect(CAutoRouterPath* path, CPoint& startpoint, CPoint& endpoint)
00443         //  Step 2: Fix the desired edges - see in CAutoRouterEdgeList::AddEdges(CAutoRouterPath* path))
00444         if (isAutoRouted)
00445                 path->ApplyCustomizationsAfterAutoConnectPointsAndStuff();
00446 
00447         return AddEdges(path);
00448 }
00449 
00450 void CAutoRouterGraph::ConnectPoints(CPointListPath& ret, CPoint& start, CPoint& end, RoutingDirection hintstartdir, RoutingDirection hintenddir)
00451 {
00452         ASSERT( ret.IsEmpty() );
00453 
00454         CPoint& thestart = start;
00455         POSITION retend = NULL;
00456 
00457         while( start != end )
00458         {
00459                 RoutingDirection dir1 = ExGetMajorDir(end-start);
00460                 RoutingDirection dir2 = ExGetMinorDir(end-start);
00461                 ASSERT( dir1 != Dir_None );
00462 
00463                 ASSERT( dir1 == GetMajorDir(end-start) );
00464                 ASSERT( dir2 == Dir_None || dir2 == GetMinorDir(end-start) );
00465 
00466                 if( retend == NULL && dir2 == hintstartdir && dir2 != Dir_None )
00467                 {
00468                         // i.e. std::swap(dir1, dir2);
00469                         dir2 = dir1;
00470                         dir1 = hintstartdir;
00471                 }
00472 
00473                 if (retend == NULL)
00474                         retend = ret.AddTail(start);
00475                 else
00476                         retend = ret.InsertAfter(retend, start);
00477                 CPoint old = start;
00478 
00479                 CAutoRouterBox* box = GoToNextBox(start, dir1, end);
00480                 if( start == old )
00481                 {
00482                         ASSERT( box != NULL );
00483                         const CRect rect = box->GetRect();
00484 
00485                         if( dir2 == Dir_None )
00486                                 dir2 = NextClockwiseDir(dir1);
00487 
00488                         ASSERT( dir1 != dir2 && dir1 != Dir_None && dir2 != Dir_None );
00489 
00490                         if( IsPointInDirFrom(end, rect, dir2) )
00491                         {
00492                                 ASSERT( !IsPointInDirFrom(start, rect, dir2) );
00493                                 GoToNextBox(start, dir2, end);
00494                                 // this assert fails if two boxes are adjacent, and a connection wants to go between
00495                                 ASSERT( IsPointInDirFrom(start, rect, dir2) );
00496                         }
00497                         else
00498                         {
00499                                 ASSERT( IsPointBetweenSides(end, rect, dir1) );
00500                                 ASSERT( !IsPointIn(end, rect) );
00501 
00502                                 int rev = 0;
00503 
00504                                 if( ReverseDir(dir2) == hintenddir )
00505                                         rev = 1;
00506                                 else if( dir2 != hintenddir )
00507                                 {
00508                                         if( IsPointBetweenSides(thestart, rect, dir1) )
00509                                         {
00510                                                 if(     IsPointInDirFrom(rect.TopLeft() + rect.BottomRight(), start + end, dir2) )
00511                                                         rev = 1;
00512                                         }
00513                                         else
00514                                                 if( IsPointInDirFrom(start, thestart, dir2) )
00515                                                         rev = 1;
00516                                 }
00517 
00518                                 if( rev )
00519                                 {
00520                                         dir2 = ReverseDir(dir2);
00521                                 }
00522 
00523                                 GetPointCoord(start, dir2) = GetRectOuterCoord(rect, dir2);
00524 
00525                                 ASSERT( start != old );
00526                                 ASSERT(retend != NULL);
00527                                 retend = ret.InsertAfter(retend, start);
00528 
00529                                 old = start;
00530 
00531                                 GetPointCoord(start, dir1) = GetRectOuterCoord(rect, dir1);
00532                                 ASSERT( IsPointInDirFrom(end, start, dir1) );
00533                                 if( GetPointCoord(start, dir1) != GetPointCoord(end, dir1) )
00534                                         GoToNextBox(start, dir1, end);
00535                         }
00536 
00537                         ASSERT( start != old );
00538                 }
00539         }
00540 
00541         ret.AddTail(end);
00542 }
00543 
00544 void CAutoRouterGraph::DisconnectAll()
00545 {
00546         std::vector<CAutoRouterPath*>::iterator iter;
00547         iter = paths.begin();
00548         
00549         while(iter != paths.end())
00550         {
00551                 Disconnect(*iter);
00552                 ++iter;
00553         }
00554 }
00555 
00556 void CAutoRouterGraph::Disconnect(CAutoRouterPath* path)
00557 {
00558         if( path->IsConnected() )
00559                 DeleteEdges(path);
00560 
00561         path->DeleteAll();
00562 }
00563 
00564 void CAutoRouterGraph::DisconnectPathsClipping(const CRect& rect)
00565 {
00566         std::vector<CAutoRouterPath*>::reverse_iterator iter;
00567         iter = paths.rbegin();
00568 
00569         while(iter != paths.rend())
00570         {
00571                 if( (*iter)->IsPathClip(rect) )
00572                         Disconnect(*iter);
00573                 ++iter;
00574         }
00575 }
00576 
00577 void CAutoRouterGraph::DisconnectPathsFrom(CAutoRouterBox* box)
00578 {
00579         std::vector<CAutoRouterPath*>::reverse_iterator iter;
00580         iter = paths.rbegin();
00581 
00582         while(iter != paths.rend())
00583         {
00584                 CAutoRouterPath* path = *iter;
00585 
00586                 CAutoRouterPort* startPort = path->GetStartPort();
00587                 ASSERT(startPort != NULL);
00588                 CAutoRouterBox* startbox = startPort->GetOwner();
00589                 ASSERT(startbox != NULL);
00590 
00591                 CAutoRouterPort* endPort = path->GetEndPort();
00592                 ASSERT(endPort != NULL);
00593                 CAutoRouterBox* endbox = endPort->GetOwner();
00594                 ASSERT(endbox != NULL);
00595 
00596                 if( (startbox == box || endbox == box) )
00597                         Disconnect(path);
00598 
00599                 ++iter;
00600         }
00601 }
00602 
00603 void CAutoRouterGraph::DisconnectPathsFrom(CAutoRouterPort* port)
00604 {
00605         std::vector<CAutoRouterPath*>::reverse_iterator iter;
00606         iter = paths.rbegin();
00607         
00608         while(iter != paths.rend())
00609         {
00610                 CAutoRouterPath* path = *iter;
00611 
00612                 CAutoRouterPort* startport = path->GetStartPort();
00613                 CAutoRouterPort* endport = path->GetEndPort();
00614 
00615                 if( (startport == port || endport == port) )
00616                         Disconnect(path);
00617 
00618                 ++iter;
00619         }
00620 }
00621 
00622 // --- Edges
00623 
00624 void CAutoRouterGraph::AddSelfEdges(void)
00625 {
00626         horizontal.AddEdges(this);
00627         vertical.AddEdges(this);
00628 }
00629 
00630 void CAutoRouterGraph::AddEdges(CAutoRouterGraph* graph)
00631 {
00632         horizontal.AddEdges(graph);
00633         vertical.AddEdges(graph);
00634 }
00635 
00636 void CAutoRouterGraph::AddEdges(CAutoRouterBox* box)
00637 {
00638         horizontal.AddEdges(box);
00639         vertical.AddEdges(box);
00640 }
00641 
00642 void CAutoRouterGraph::AddEdges(CAutoRouterPort* port)
00643 {
00644         horizontal.AddEdges(port);
00645         vertical.AddEdges(port);
00646 }
00647 
00648 bool CAutoRouterGraph::AddEdges(CAutoRouterPath* path)
00649 {
00650         return horizontal.AddEdges(path) && vertical.AddEdges(path);
00651 }
00652 
00653 void CAutoRouterGraph::DeleteEdges(CObject* object)
00654 {
00655         horizontal.DeleteEdges(object);
00656         vertical.DeleteEdges(object);
00657 }
00658 
00659 void CAutoRouterGraph::AddAllEdges()
00660 {
00661         ASSERT( horizontal.IsEmpty() && vertical.IsEmpty() );
00662 
00663         std::vector<CAutoRouterBox*>::iterator iter;
00664         iter = boxes.begin();
00665 
00666         while (iter != boxes.end())
00667         {
00668                 AddBoxAndPortEdges(*iter);
00669                 ++iter;
00670         }
00671 
00672         std::vector<CAutoRouterPath*>::iterator iterP;
00673         iterP = paths.begin();
00674 
00675         while (iterP != paths.end())
00676         {
00677                 AddEdges(*iterP);
00678                 iterP++;
00679         }
00680 }
00681 
00682 void CAutoRouterGraph::DeleteAllEdges()
00683 {
00684         horizontal.DeleteAllEdges();
00685         vertical.DeleteAllEdges();
00686 }
00687 
00688 void CAutoRouterGraph::AddBoxAndPortEdges(CAutoRouterBox* box)
00689 {
00690         ASSERT( box != NULL );
00691 
00692         AddEdges(box);
00693 
00694         const CAutoRouterPortList& pl = box->GetPortList();
00695         std::vector<CAutoRouterPort*>::const_iterator ii = pl.begin();
00696         while( ii != pl.end() ) {
00697                 AddEdges(*ii);
00698                 ++ii;
00699         }
00700 }
00701 
00702 void CAutoRouterGraph::DeleteBoxAndPortEdges(CAutoRouterBox* box)
00703 {
00704         ASSERT( box != NULL );
00705 
00706         DeleteEdges(box);
00707 
00708         const CAutoRouterPortList& pl = box->GetPortList();
00709         std::vector<CAutoRouterPort*>::const_iterator ii = pl.begin();
00710         while( ii != pl.end() ) {
00711                 DeleteEdges(*ii);
00712                 ++ii;
00713         }
00714 }
00715 
00716 CAutoRouterEdgeList& CAutoRouterGraph::GetEdgeList(bool ishorizontal)
00717 {
00718         return ishorizontal ? horizontal : vertical;
00719 }
00720 
00721 // --- Path && Edges
00722 
00723 bool CAutoRouterGraph::CanDeleteTwoEdgesAt(CAutoRouterPath* path, CPointListPath& points, POSITION pos) const
00724 {
00725 #ifdef _DEBUG
00726         ASSERT( path->GetOwner() == this );
00727         path->AssertValid();
00728         ASSERT( path->IsConnected() );
00729         points.AssertValidPos(pos);
00730 #ifdef _DEBUG_DEEP
00731 //      horizontal.AssertValidPathEdges(path, points);
00732 //      vertical.AssertValidPathEdges(path, points);
00733 #endif
00734 #endif
00735 
00736         POSITION pointpos = pos;
00737         CPoint point = points.GetNext(pos);
00738         POSITION npointpos = pos;
00739         if( npointpos == NULL )
00740                 return false;
00741         CPoint npoint = points.GetNext(pos);
00742         POSITION nnpointpos = pos;
00743         if( nnpointpos == NULL )
00744                 return false;
00745 
00746         pos = pointpos;
00747         points.GetPrev(pos);
00748         POSITION ppointpos = pos; if( ppointpos == NULL ) return false;
00749         CPoint ppoint = points.GetPrev(pos);
00750         POSITION pppointpos = pos; if( pppointpos == NULL ) return false;
00751         if( npoint == point) return false; // direction of zero-length edges can't be determined, so don't delete them
00752 
00753         ASSERT( pppointpos != NULL && ppointpos != NULL && pointpos != NULL && npointpos != NULL && nnpointpos != NULL );
00754 
00755         RoutingDirection dir = GetDir(npoint - point);
00756         ASSERT( IsRightAngle(dir) );
00757         bool ishorizontal = IsHorizontal(dir);
00758 
00759         CPoint newpoint;
00760         GetPointCoord(newpoint, ishorizontal) = GetPointCoord(npoint, ishorizontal);
00761         GetPointCoord(newpoint, !ishorizontal) = GetPointCoord(ppoint, !ishorizontal);
00762 
00763         ASSERT( GetDir(newpoint - ppoint) == dir );
00764 
00765         if( IsLineClipBoxes(newpoint, npoint) ) return false;
00766         if( IsLineClipBoxes(newpoint, ppoint) ) return false;
00767 
00768         return true;
00769 }
00770 
00771 void CAutoRouterGraph::DeleteTwoEdgesAt(CAutoRouterPath* path, CPointListPath& points, POSITION pos)
00772 {
00773 #ifdef _DEBUG
00774         ASSERT( path->GetOwner() == this );
00775         path->AssertValid();
00776         ASSERT( path->IsConnected() );
00777         points.AssertValidPos(pos);
00778 #ifdef _DEBUG_DEEP
00779 //      horizontal.AssertValidPathEdges(path, points);
00780 //      vertical.AssertValidPathEdges(path, points);
00781 #endif
00782 #endif
00783 
00784         POSITION pointpos = pos;
00785         CPoint* point = &(points.GetNext(pos));
00786         POSITION npointpos = pos;
00787         CPoint* npoint = &(points.GetNext(pos));
00788         POSITION nnpointpos = pos;
00789         CPoint* nnpoint = &(points.GetNext(pos));
00790         POSITION nnnpointpos = pos;
00791         pos = pointpos;
00792         points.GetPrev(pos);
00793         POSITION ppointpos = pos;
00794         CPoint* ppoint = &(points.GetPrev(pos));
00795         POSITION pppointpos = pos;
00796         CPoint* pppoint = &(points.GetAt(pos));
00797 
00798         ASSERT( pppointpos != NULL && ppointpos != NULL && pointpos != NULL && npointpos != NULL && nnpointpos != NULL );
00799         ASSERT( pppoint != NULL && ppoint != NULL && point != NULL && npoint != NULL && nnpoint != NULL );
00800 
00801         RoutingDirection dir = GetDir(*npoint - *point);
00802         ASSERT( IsRightAngle(dir) );
00803         bool ishorizontal = IsHorizontal(dir);
00804 
00805         CPoint newpoint;
00806         GetPointCoord(newpoint, ishorizontal) = GetPointCoord(*npoint, ishorizontal);
00807         GetPointCoord(newpoint, !ishorizontal) = GetPointCoord(*ppoint, !ishorizontal);
00808 
00809         ASSERT( GetDir(newpoint - *ppoint) == dir );
00810 
00811         ASSERT( !IsLineClipBoxes(newpoint, *npoint) );
00812         ASSERT( !IsLineClipBoxes(newpoint, *ppoint) );
00813 
00814         CAutoRouterEdgeList& hlist = GetEdgeList(ishorizontal);
00815         CAutoRouterEdgeList& vlist = GetEdgeList(!ishorizontal);
00816 
00817         CAutoRouterEdge* ppedge = hlist.GetEdgeByPointer(pppoint, ppoint);
00818         CAutoRouterEdge* pedge = vlist.GetEdgeByPointer(ppoint, point);
00819         CAutoRouterEdge* nedge = hlist.GetEdgeByPointer(point, npoint);
00820         CAutoRouterEdge* nnedge = vlist.GetEdgeByPointer(npoint, nnpoint);
00821 
00822         ASSERT( ppedge != NULL && pedge != NULL && nedge != NULL && nnedge != NULL );
00823 
00824         vlist.Delete(pedge);
00825         hlist.Delete(nedge);
00826 
00827         points.RemoveAt(pointpos);
00828         points.RemoveAt(npointpos);
00829         points.SetAt(ppointpos, newpoint);
00830 
00831         ASSERT( ppedge->GetEndPoint() == *ppoint && ppedge->GetEndPointNext() == *point );
00832         ppedge->SetEndPointNext(nnpoint);
00833 
00834         ASSERT( nnedge->GetStartPoint() == *npoint && nnedge->GetStartPointPrev() == *point );
00835         nnedge->SetStartPoint(ppoint);
00836         nnedge->SetStartPointPrev(pppoint);
00837 
00838         if( nnnpointpos != NULL )
00839         {
00840                 CAutoRouterEdge* nnnedge = hlist.GetEdgeByPointer(nnpoint, &(points.GetAt(nnnpointpos)));
00841                 ASSERT( nnnedge != NULL );
00842                 ASSERT( nnnedge->GetStartPointPrev() == *npoint && nnnedge->GetStartPoint() == *nnpoint );
00843                 nnnedge->SetStartPointPrev(ppoint);
00844         }
00845 
00846         if( *nnpoint == newpoint )
00847                 DeleteSamePointsAt(path, points, ppointpos);
00848 
00849 #ifdef _DEBUG_DEEP
00850         path->AssertValid();
00851         horizontal.AssertValidPathEdges(path, points);
00852         vertical.AssertValidPathEdges(path, points);
00853 #endif
00854 }
00855 
00856 void CAutoRouterGraph::DeleteSamePointsAt(CAutoRouterPath* path, CPointListPath& points, POSITION pos)
00857 {
00858 #ifdef _DEBUG
00859         ASSERT( path->GetOwner() == this );
00860         path->AssertValid();
00861         ASSERT( path->IsConnected() );
00862         points.AssertValidPos(pos);
00863 #endif
00864 
00865         POSITION pointpos = pos;
00866         CPoint* point = &(points.GetNext(pos));
00867         POSITION npointpos = pos;
00868         CPoint* npoint = &(points.GetNext(pos));
00869         POSITION nnpointpos = pos;
00870         CPoint* nnpoint = &(points.GetNext(pos));
00871         POSITION nnnpointpos = pos;
00872         pos = pointpos;
00873         points.GetPrev(pos);
00874         POSITION ppointpos = pos;
00875         CPoint* ppoint = &(points.GetPrev(pos));
00876         POSITION pppointpos = pos;
00877         CPoint* pppoint = pos == NULL ? NULL : &(points.GetAt(pos));
00878 
00879         ASSERT( ppointpos != NULL && pointpos != NULL && npointpos != NULL && nnpointpos != NULL );
00880         ASSERT( ppoint != NULL && point != NULL && npoint != NULL && nnpoint != NULL );
00881         ASSERT( *point == *npoint && *point != *ppoint );
00882 
00883         RoutingDirection dir = GetDir(*point - *ppoint);
00884         ASSERT( IsRightAngle(dir) );
00885         bool ishorizontal = IsHorizontal(dir);
00886 
00887         CAutoRouterEdgeList& hlist = GetEdgeList(ishorizontal);
00888         CAutoRouterEdgeList& vlist = GetEdgeList(!ishorizontal);
00889 
00890         CAutoRouterEdge* pedge = hlist.GetEdgeByPointer(ppoint, point);
00891         CAutoRouterEdge* nedge = vlist.GetEdgeByPointer(point, npoint);
00892         CAutoRouterEdge* nnedge = hlist.GetEdgeByPointer(npoint, nnpoint);
00893 
00894         ASSERT( pedge != NULL && nedge != NULL && nnedge != NULL );
00895 
00896         vlist.Delete(pedge);
00897         hlist.Delete(nedge);
00898 
00899         points.RemoveAt(pointpos);
00900         points.RemoveAt(npointpos);
00901 
00902         if( pppointpos != NULL )
00903         {
00904                 CAutoRouterEdge* ppedge = vlist.GetEdgeByPointer(pppoint, ppoint);
00905                 ASSERT( ppedge != NULL && ppedge->GetEndPoint() == *ppoint && ppedge->GetEndPointNext() == *point );
00906                 ppedge->SetEndPointNext(nnpoint);
00907         }
00908 
00909         ASSERT( nnedge->GetStartPoint() == *npoint && nnedge->GetStartPointPrev() == *point );
00910         nnedge->SetStartPoint(ppoint);
00911         nnedge->SetStartPointPrev(pppoint);
00912 
00913         if( nnnpointpos != NULL )
00914         {
00915                 CAutoRouterEdge* nnnedge = vlist.GetEdgeByPointer(nnpoint, &(points.GetAt(nnnpointpos)));
00916                 ASSERT( nnnedge != NULL && nnnedge->GetStartPointPrev() == *npoint && nnnedge->GetStartPoint() == *nnpoint );
00917                 nnnedge->SetStartPointPrev(ppoint);
00918         }
00919 
00920 #ifdef _DEBUG_DEEP
00921         path->AssertValid();
00922 //      horizontal.AssertValidPathEdges(path, points);
00923 //      vertical.AssertValidPathEdges(path, points);
00924 #endif
00925 }
00926 
00927 bool CAutoRouterGraph::SimplifyPaths()
00928 {
00929         bool was = false;
00930 
00931         std::vector<CAutoRouterPath*>::iterator iter;
00932         iter = paths.begin();
00933 
00934         while (iter != paths.end())
00935         {
00936                 CAutoRouterPath* path = *iter;
00937                 ++iter;
00938 
00939                 if (path->IsAutoRouted()) {
00940                         CPointListPath& pointList = path->GetPointList();
00941                         POSITION pointpos = pointList.GetHeadPosition();
00942 
00943                         while( pointpos != NULL )
00944                         {
00945                                 if( CanDeleteTwoEdgesAt(path, pointList, pointpos) )
00946                                 {
00947                                         DeleteTwoEdgesAt(path, pointList, pointpos);
00948                                         was = true;
00949                                         break;
00950                                 }
00951                                 pointList.GetNext(pointpos);
00952                         }
00953                 }
00954         }
00955 
00956         return was;
00957 }
00958 
00959 void CAutoRouterGraph::CenterStairsInPathPoints(CAutoRouterPath* path, RoutingDirection hintstartdir, RoutingDirection hintenddir)
00960 {
00961         ASSERT( path != NULL );
00962         ASSERT( !path->IsConnected() );
00963 
00964         CPointListPath& pointList = path->GetPointList();
00965         ASSERT( pointList.GetCount() >= 2 );
00966 
00967 #ifdef _DEBUG
00968         path->AssertValidPoints();
00969 #endif
00970 
00971         CPoint p1;
00972         CPoint p2;
00973         CPoint p3;
00974         CPoint p4;
00975 
00976         POSITION p1p = NULL;
00977         POSITION p2p = NULL;
00978         POSITION p3p = NULL;
00979         POSITION p4p = NULL;
00980 
00981         RoutingDirection d12 = Dir_None;
00982         RoutingDirection d23 = Dir_None;
00983         RoutingDirection d34 = Dir_None;
00984 
00985         const CPoint outOfBoxStartPoint = path->GetOutOfBoxStartPoint(hintstartdir);
00986         const CPoint outOfBoxEndPoint = path->GetOutOfBoxEndPoint(hintenddir);
00987 
00988         POSITION pos = pointList.GetHeadPosition();
00989         ASSERT( pos != NULL );
00990 
00991         p1p = pos;
00992         p1 = pointList.GetNext(pos);
00993 
00994         while( pos != NULL )
00995         {
00996                 p4p = p3p;
00997                 p3p = p2p;
00998                 p2p = p1p;
00999                 p1p = pos;
01000 
01001                 p4 = p3;
01002                 p3 = p2;
01003                 p2 = p1;
01004                 p1 = pointList.GetNext(pos);
01005 
01006                 d34 = d23;
01007                 d23 = d12;
01008 
01009                 if( p2p != NULL )
01010                 {
01011                         d12 = GetDir(p2 - p1);
01012 #ifdef _DEBUG
01013                         ASSERT( IsRightAngle(d12) );
01014                         if( p3p != NULL )
01015                                 ASSERT( AreInRightAngle(d12, d23) );
01016 #endif
01017                 }
01018 
01019                 if( p4p != NULL && d12 == d34 )
01020                 {
01021                         ASSERT( p1p != NULL && p2p != NULL && p3p != NULL && p4p != NULL );
01022 
01023                         CPoint np2 = p2;
01024                         CPoint np3 = p3;
01025                         bool h = IsHorizontal(d12);
01026 
01027                         long p4x = GetPointCoord(p4, h);
01028                         long p3x = GetPointCoord(p3, h);
01029                         long p1x = GetPointCoord(p1, h);
01030 
01031                         if( p1x < p4x )
01032                         {
01033                                 long t = p1x;
01034                                 p1x = p4x;
01035                                 p4x = t;
01036                         }
01037 
01038                         if( p4x < p3x && p3x < p1x )
01039                         {
01040                                 long m = (p4x + p1x)/2;
01041                                 GetPointCoord(np2, h) = m;
01042                                 GetPointCoord(np3, h) = m;
01043 
01044                                 GetLimitsOfEdge(np2, np3, p4x, p1x);
01045 
01046                                 m = (p4x + p1x)/2;
01047                                 GetPointCoord(np2, h) = m;
01048                                 GetPointCoord(np3, h) = m;
01049 
01050                                 if( !IsLineClipBoxes(np2, np3) &&
01051                                         !IsLineClipBoxes(p1p == pointList.GetTailPosition() ? outOfBoxEndPoint : p1, np2) &&
01052                                         !IsLineClipBoxes(p4p == pointList.GetHeadPosition() ? outOfBoxStartPoint : p4, np3) )
01053                                 {
01054                                         p2 = np2;
01055                                         p3 = np3;
01056                                         pointList.SetAt(p2p, p2);
01057                                         pointList.SetAt(p3p, p3);
01058                                 }
01059                         }
01060                 }
01061         }
01062 
01063 #ifdef _DEBUG
01064         path->AssertValidPoints();
01065 #endif
01066 }
01067 
01068 void CAutoRouterGraph::SimplifyPathPoints(CAutoRouterPath* path)
01069 {
01070         ASSERT( path != NULL );
01071         ASSERT( !path->IsConnected() );
01072 
01073         CPointListPath& pointList = path->GetPointList();
01074         ASSERT( pointList.GetCount() >= 2 );
01075 
01076 #ifdef _DEBUG
01077         path->AssertValidPoints();
01078 #endif
01079 
01080         CPoint p1;
01081         CPoint p2;
01082         CPoint p3;
01083         CPoint p4;
01084         CPoint p5;
01085 
01086         POSITION p1p = NULL;
01087         POSITION p2p = NULL;
01088         POSITION p3p = NULL;
01089         POSITION p4p = NULL;
01090         POSITION p5p = NULL;
01091 
01092         POSITION pos = pointList.GetHeadPosition();
01093         ASSERT( pos != NULL );
01094 
01095         p1p = pos;
01096         p1 = pointList.GetNext(pos);
01097 
01098         while( pos != NULL )
01099         {
01100                 p5p = p4p;
01101                 p4p = p3p;
01102                 p3p = p2p;
01103                 p2p = p1p;
01104                 p1p = pos;
01105 
01106                 p5 = p4;
01107                 p4 = p3;
01108                 p3 = p2;
01109                 p2 = p1;
01110                 p1 = pointList.GetNext(pos);
01111 
01112                 if( p5p != NULL )
01113                 {
01114                         ASSERT( p1p != NULL && p2p != NULL && p3p != NULL && p4p != NULL && p5p != NULL );
01115                         ASSERT( p1 != p2 && p2 != p3 && p3 != p4 && p4 != p5 );
01116 
01117                         RoutingDirection d = GetDir(p2 - p1);
01118                         ASSERT( IsRightAngle(d) );
01119                         bool h = IsHorizontal(d);
01120 
01121                         CPoint np3;
01122                         GetPointCoord(np3, h) = GetPointCoord(p5, h);
01123                         GetPointCoord(np3, !h) = GetPointCoord(p1, !h);
01124 
01125                         if( !IsLineClipBoxes(p2, np3) && !IsLineClipBoxes(np3, p4) )
01126                         {
01127                                 pointList.RemoveAt(p2p);
01128                                 pointList.RemoveAt(p4p);
01129                                 pointList.SetAt(p3p, np3);
01130                                 if( np3 == p1 )
01131                                         pointList.RemoveAt(p1p);
01132                                 if( np3 == p5 )
01133                                         pointList.RemoveAt(p5p);
01134 
01135                                 p1p = NULL;
01136                                 p2p = NULL;
01137                                 p3p = NULL;
01138                                 p4p = NULL;
01139 
01140                                 pos = pointList.GetHeadPosition();
01141                         }
01142                 }
01143         }
01144 
01145 #ifdef _DEBUG
01146         path->AssertValidPoints();
01147 #endif
01148 }
01149 
01150 void CAutoRouterGraph::ConnectAllDisconnectedPaths()
01151 {
01152         std::vector<CAutoRouterPath*>::iterator iter;
01153 
01154         bool success = false;
01155         bool giveup = false;
01156         while (!success && !giveup) {
01157                 success = true;
01158                 iter = paths.begin();
01159                 while (iter != paths.end() && success)
01160                 {
01161                         CAutoRouterPath* path = *iter;
01162 
01163                         if( !path->IsConnected() )
01164                         {
01165                                 success = Connect(path);
01166                                 if (!success) {
01167                                         // Something is messed up, probably an existing edge customization results in a zero length edge
01168                                         // In that case we try to delete any customization for this path to recover from the problem
01169                                         if (path->AreTherePathCustomizations())
01170                                                 path->RemovePathCustomizations();
01171                                         else
01172                                                 giveup = true;
01173                                 }
01174                         }
01175 
01176                         ++iter;
01177                 }
01178                 if (!success && !giveup)
01179                         DisconnectAll();        // There was an error, delete halfway results to be able to start a new pass
01180         }
01181 }
01182 
01183 // --- SelfPoints
01184 
01185 void CAutoRouterGraph::CalculateSelfPoints()
01186 {
01187         selfpoints[0].x = ED_MINCOORD;
01188         selfpoints[0].y = ED_MINCOORD;
01189 
01190         selfpoints[1].x = ED_MAXCOORD;
01191         selfpoints[1].y = ED_MINCOORD;
01192 
01193         selfpoints[2].x = ED_MAXCOORD;
01194         selfpoints[2].y = ED_MAXCOORD;
01195 
01196         selfpoints[3].x = ED_MINCOORD;
01197         selfpoints[3].y = ED_MAXCOORD;
01198 }
01199 
01200 CAutoRouterBox* CAutoRouterGraph::CreateBox(void) const
01201 {
01202         CAutoRouterBox* box = new CAutoRouterBox();
01203         ASSERT( box != NULL );
01204 
01205         return box;
01206 }
01207 
01208 void CAutoRouterGraph::AddBox(CAutoRouterBox* box)
01209 {
01210         ASSERT(box != NULL);
01211         if (box == NULL)
01212                 return;
01213 
01214         const CRect rect = box->GetRect();
01215 
01216         DisconnectPathsClipping(rect);
01217 
01218         box->SetOwner(this);
01219 
01220         boxes.push_back(box);
01221 
01222         AddBoxAndPortEdges(box);
01223 }
01224 
01225 void CAutoRouterGraph::DeleteBox(CAutoRouterBox* box)
01226 {
01227         ASSERT(box != NULL);
01228         if (box == NULL)
01229                 return;
01230 
01231         if( box->HasOwner() )
01232         {
01233                 Remove(box);
01234         }
01235         
01236         box->Destroy();
01237         delete box;
01238 }
01239 
01240 void CAutoRouterGraph::ShiftBoxBy(CAutoRouterBox* box, const CPoint& offset)
01241 {
01242         ASSERT(box != NULL);
01243         if (box == NULL)
01244                 return;
01245 
01246         DeleteBoxAndPortEdges(box);
01247         box->ShiftBy(offset);
01248         AddBoxAndPortEdges(box);
01249 
01250         const CRect rect = box->GetRect();
01251         DisconnectPathsClipping(rect);
01252         DisconnectPathsFrom(box);
01253 }
01254 
01255 long CAutoRouterGraph::AutoRoute(long aspect)
01256 {
01257         ConnectAllDisconnectedPaths();
01258 
01259         int updated = 0;
01260         int last = 0;
01261         int c = 100;            // max # of total op
01262         int dm = 10;            // max # of distribution op
01263         int d = 0;
01264 
01265         while( c > 0 )
01266         {
01267                 if( c > 0 )
01268                 {
01269                         if( last == 1 )
01270                                 break;
01271 
01272                         c--;
01273                         if( SimplifyPaths() )
01274                         {
01275                                 updated = 1;
01276                                 last = 1;
01277                         }
01278                 }
01279 
01280                 if( c > 0 )
01281                 {
01282                         if( last == 2 )
01283                                 break;
01284 
01285                         c--;
01286                         if( horizontal.Block_ScanBackward() )
01287                         {
01288                                 updated = 1;
01289 
01290                                 do {
01291                                         c--;
01292                                 } while( c > 0 && horizontal.Block_ScanBackward() );
01293 
01294                                 if( last < 2 || last > 5 )
01295                                         d = 0;
01296                                 else if( ++d >= dm )
01297                                         break;
01298 
01299                                 last = 2;
01300                         }
01301                 }
01302 
01303                 if( c > 0 )
01304                 {
01305                         if( last == 3 )
01306                                 break;
01307 
01308                         c--;
01309                         if( horizontal.Block_ScanForward() )
01310                         {
01311                                 updated = 1;
01312 
01313                                 do {
01314                                         c--;
01315                                 } while( c > 0 && horizontal.Block_ScanForward() );
01316 
01317                                 if( last < 2 || last > 5 )
01318                                         d = 0;
01319                                 else if( ++d >= dm )
01320                                         break;
01321 
01322                                 last = 3;
01323                         }
01324                 }
01325 
01326                 if( c > 0 )
01327                 {
01328                         if( last == 4 )
01329                                 break;
01330 
01331                         c--;
01332                         if( vertical.Block_ScanBackward() )
01333                         {
01334                                 updated = 1;
01335 
01336                                 do
01337                                 c--;
01338                                 while( c > 0 && vertical.Block_ScanBackward() );
01339 
01340                                 if( last < 2 || last > 5 )
01341                                         d = 0;
01342                                 else if( ++d >= dm )
01343                                         break;
01344 
01345                                 last = 4;
01346                         }
01347                 }
01348 
01349                 if( c > 0 )
01350                 {
01351                         if( last == 5 )
01352                                 break;
01353 
01354                         c--;
01355                         if( vertical.Block_ScanForward() )
01356                         {
01357                                 updated = 1;
01358 
01359                                 do
01360                                 c--;
01361                                 while( c > 0 && vertical.Block_ScanForward() );
01362 
01363                                 if( last < 2 || last > 5 )
01364                                         d = 0;
01365                                 else if( ++d >= dm )
01366                                         break;
01367 
01368                                 last = 5;
01369                         }
01370                 }
01371 
01372                 if( c > 0 )
01373                 {
01374                         if( last == 6 )
01375                                 break;
01376 
01377                         c--;
01378                         if( horizontal.Block_SwitchWrongs() )
01379                         {
01380                                 updated = 1;
01381                                 last = 6;
01382                         }
01383                 }
01384 
01385                 if( c > 0 )
01386                 {
01387                         if( last == 7 )
01388                                 break;
01389 
01390                         c--;
01391                         if( vertical.Block_SwitchWrongs() )
01392                         {
01393                                 updated = 1;
01394                                 last = 7;
01395                         }
01396                 }
01397 
01398                 if( last == 0 )
01399                         break;
01400         }
01401 
01402         if( c <= 0 )
01403         {
01404                 // MessageBeep(MB_ICONEXCLAMATION);
01405                 updated = -1;
01406         }
01407 
01408         // Check customized connection if there's any clip against boxes
01409         {
01410                 std::vector<CAutoRouterPath*>::iterator pathiter;
01411                 pathiter = paths.begin();
01412 
01413                 HRESULT hr = S_OK;
01414                 while (pathiter != paths.end())
01415                 {
01416                         CAutoRouterPath* path = *pathiter;
01417 
01418                         if (path->IsAutoRouted()) {     // comment this if you want the check to run for fully customizable connections
01419                                 if (path->AreTherePathCustomizations())
01420                                 {
01421                                         const CRect startBoxRect = path->GetStartBox();
01422                                         const CRect endBoxRect = path->GetEndBox();
01423 
01424                                         std::vector<CAutoRouterBox*>::const_iterator boxiter = boxes.begin();
01425 
01426                                         while (boxiter != boxes.end())
01427                                         {
01428                                                 const CRect boxRect = (*boxiter)->GetRect();
01429                                                 bool isStartOrEndRect = (!startBoxRect.IsRectEmpty() && IsRectIn(startBoxRect, boxRect) ||
01430                                                                                                  !endBoxRect.IsRectEmpty() && IsRectIn(endBoxRect, boxRect));
01431                                                 if (path->IsPathClip(boxRect, isStartOrEndRect))
01432                                                 {
01433                                                         path->MarkPathCustomizationsForDeletion(aspect);
01434                                                         updated = -2;
01435                                                 }
01436 
01437                                                 ++boxiter;
01438                                         }
01439                                 }
01440                         }
01441 
01442                         ++pathiter;
01443                 }
01444         }
01445 
01446         return updated;
01447 }
01448 
01449 void CAutoRouterGraph::DeletePath(CAutoRouterPath* path)
01450 {
01451         ASSERT(path != NULL);
01452         if (path == NULL)
01453                 return;
01454 
01455         if( path->HasOwner() )
01456         {
01457                 ASSERT( path->GetOwner() == this );
01458 
01459                 Remove(path);
01460         }
01461 
01462         path->Destroy();
01463         delete path;
01464 }
01465 
01466 void CAutoRouterGraph::DeleteAll(bool addBackSelfEdges)
01467 {
01468         DeleteAllPaths();
01469         DeleteAllBoxes();
01470         DeleteAllEdges();
01471         if (addBackSelfEdges)
01472                 AddSelfEdges();
01473 }
01474 
01475 CAutoRouterPath* CAutoRouterGraph::GetPathAt(const CPoint& point, long nearness)
01476 {
01477         std::vector<CAutoRouterPath*>::iterator iter;
01478         iter = paths.begin();
01479 
01480         while (iter != paths.end())
01481         {
01482                 CAutoRouterPath* path = *iter;
01483 
01484                 if( path->IsPathAt(point, nearness) )
01485                         return path;
01486 
01487                 ++iter;
01488         }
01489 
01490         return NULL;
01491 }
01492 
01493 CAutoRouterPath* CAutoRouterGraph::AddPath(bool isAutoRouted, CAutoRouterPort* startport, CAutoRouterPort* endport)
01494 {
01495         CAutoRouterPath* path = new CAutoRouterPath();
01496 
01497         path->SetAutoRouting(isAutoRouted);
01498         path->SetStartPort(startport);
01499         path->SetEndPort(endport);
01500         Add(path);
01501 
01502         return path;
01503 }
01504 
01505 bool CAutoRouterGraph::IsEdgeFixed(CAutoRouterPath* path, const CPoint& startpoint, const CPoint& endpoint)
01506 {
01507         RoutingDirection d = GetDir(endpoint - startpoint);
01508         bool h = IsHorizontal(d);
01509 
01510         CAutoRouterEdgeList& elist = GetEdgeList(h);
01511 
01512         CAutoRouterEdge* edge = elist.GetEdge(path, startpoint, endpoint);
01513         if (edge != NULL)
01514                 return edge->GetEdgeFixed() && !edge->GetEdgeCustomFixed();
01515 
01516         ASSERT(false);
01517         return true;
01518 }
01519 
01520 CPoint* CAutoRouterGraph::GetSelfPoints(void) const
01521 {
01522         return (CPoint*)selfpoints;
01523 }
01524 
01525 void CAutoRouterGraph::Destroy(void)
01526 {
01527         DeleteAll(false);
01528 
01529         horizontal.SetOwner(NULL);
01530         vertical.SetOwner(NULL);
01531 }
01532 
01533 #ifdef _DEBUG
01534 void CAutoRouterGraph::AssertValid() const
01535 {
01536         std::vector<CAutoRouterBox*>::const_iterator iter = boxes.begin();
01537 
01538         while (iter != boxes.end())
01539         {
01540                 AssertValidBox(*iter);
01541                 ++iter;
01542         }
01543 
01544         std::vector<CAutoRouterPath*>::const_iterator iter2 = paths.begin();
01545         
01546         while(iter2 != paths.end())
01547         {
01548                 AssertValidPath(*iter2);
01549                 ++iter2;
01550         }
01551 }
01552 
01553 void CAutoRouterGraph::AssertValidBox(CAutoRouterBox* box) const
01554 {
01555         box->AssertValid();
01556         ASSERT( box->GetOwner() == this );
01557 
01558         std::vector<CAutoRouterBox*>::const_iterator iter = std::find(boxes.begin(), boxes.end(), box);
01559         ASSERT (iter != boxes.end());
01560 }
01561 
01562 void CAutoRouterGraph::AssertValidPath(CAutoRouterPath* path) const
01563 {
01564         path->AssertValid();
01565         ASSERT( path->GetOwner() == this );
01566 
01567         std::vector<CAutoRouterPath*>::const_iterator iter = std::find(paths.begin(), paths.end(), path);
01568         ASSERT (iter != paths.end());
01569 
01570         CPointListPath& pointList = path->GetPointList();
01571 
01572         CAutoRouterPort* startPort = path->GetStartPort();
01573         ASSERT(startPort != NULL);
01574         startPort->AssertValid();
01575         CAutoRouterBox* ownerBox = startPort->GetOwner();
01576         CAutoRouterGraph* boxOwnerGraph = ownerBox->GetOwner();
01577         ASSERT( boxOwnerGraph == this );
01578         ownerBox->AssertValidPort(startPort);
01579 
01580         if( path->IsConnected() )
01581                 startPort->AssertValidStartEndPoint(pointList.GetHead(), Dir_None, 1);
01582 
01583         CAutoRouterPort* endPort = path->GetEndPort();
01584         ASSERT(endPort != NULL);
01585         endPort->AssertValid();
01586         CAutoRouterBox* ownerBox2 = endPort->GetOwner();
01587         ASSERT( ownerBox2->GetOwner() == this );
01588         ownerBox2->AssertValidPort(endPort);
01589 
01590         if( path->IsConnected() )
01591         {
01592                 endPort->AssertValidStartEndPoint(pointList.GetTail(), Dir_None, 0);
01593         }
01594         else
01595         {
01596                 ASSERT( path->HasNoPoint() );
01597         }
01598 
01599         path->AssertValidPoints();
01600 
01601         if( !pointList.IsEmpty() )
01602         {
01603                 ASSERT( pointList.GetCount() >= 2 );
01604                 POSITION pos = pointList.GetHeadPosition();
01605                 ASSERT( pos != NULL );
01606 
01607                 ASSERT( IsPointInBox(pointList.GetNext(pos)) );
01608 
01609                 while( pos != NULL )
01610                 {
01611                         CPoint p = pointList.GetNext(pos);
01612                         if( pos != NULL )
01613                                 ASSERT( !IsPointInBox(p) );
01614                         else
01615                                 ASSERT( IsPointInBox(p) );
01616                 }
01617         }
01618 }
01619 
01620 void CAutoRouterGraph::DumpPaths(int pos, int c)
01621 {
01622         TRACE2("Paths dump pos %ld, c %ld:\n", pos, c);
01623         std::vector<CAutoRouterPath*>::iterator iter;
01624         iter = paths.begin();
01625         int i = 0;
01626 
01627         while (iter != paths.end())
01628         {
01629                 TRACE1("%ld. Path:\n", i);
01630                 (*iter)->GetPointList().DumpPoints("DumpPaths");
01631 
01632                 ++iter;
01633                 i++;
01634         }
01635 
01636         DumpEdgeLists();
01637 }
01638 
01639 void CAutoRouterGraph::DumpEdgeLists(void)
01640 {
01641 #ifdef _DEBUG_DEEP
01642         horizontal.DumpEdges("Horizontal edges:");
01643         vertical.DumpEdges("Vertical edges:");
01644 #endif
01645 }
01646 #endif
01647 
01648 // CAutoRouterGraph