GME  13
AutoRouterPath.cpp
Go to the documentation of this file.
00001 // AutoRouterPath.cpp : Implementation of CAutoRouterPath
00002 
00003 #include "stdafx.h"
00004 #include "AutoRouterPath.h"
00005 #include "AutoRouterBox.h"
00006 #include "AutoRouterGraph.h"
00007 #include "AutoRouterPort.h"
00008 
00009 
00010 // CAutoRouterPath implementation
00011 
00012 CAutoRouterPath::CAutoRouterPath():
00013         owner(NULL),
00014         startport(NULL),
00015         endport(NULL),
00016         attributes(ARPATH_Default),
00017         state(ARPATHST_Default),
00018         isAutoRoutingOn(true)
00019 {
00020 }
00021 
00022 CAutoRouterPath::~CAutoRouterPath()
00023 {
00024         DeleteAll();
00025         this->SetOwner(NULL);
00026 }
00027 
00028 // --- Points
00029 
00030 POSITION CAutoRouterPath::GetPointPosAt(const CPoint& point, int nearness) const
00031 {
00032         POSITION pos = points.GetHeadPosition();
00033         while( pos != NULL )
00034         {
00035                 POSITION oldpos = pos;
00036                 if( IsPointNear(points.GetNext(pos), point, nearness) )
00037                         return oldpos;
00038         }
00039         
00040         return NULL;
00041 }
00042 
00043 POSITION CAutoRouterPath::GetEdgePosAt(const CPoint& point, int nearness) const
00044 {
00045         CPoint a;
00046         CPoint b;
00047 
00048         POSITION pos = points.GetTailEdge(a, b);
00049         while( pos != NULL )
00050         {
00051                 if( IsPointNearLine(point, a, b, nearness) )
00052                         return pos;
00053 
00054                 points.GetPrevEdge(pos, a, b);
00055         }
00056 
00057         return NULL;
00058 }
00059 
00060 bool CAutoRouterPath::IsConnected(void) const
00061 {
00062         return (state & ARPATHST_Connected) != 0;
00063 }
00064 
00065 void CAutoRouterPath::AddTail(CPoint& p)
00066 {
00067         ASSERT( !IsConnected() );
00068         points.AddTail(p);
00069 }
00070 
00071 void CAutoRouterPath::DeleteAll(void)
00072 {
00073         points.RemoveAll();
00074         state = ARPATHST_Default;
00075 }
00076 
00077 bool CAutoRouterPath::HasNoPoint(void) const
00078 {
00079         return points.IsEmpty() == TRUE;
00080 }
00081 
00082 long CAutoRouterPath::GetPointCount(void) const
00083 {
00084         return points.GetCount();
00085 }
00086 
00087 CPoint CAutoRouterPath::GetStartPoint(void) const
00088 {
00089         ASSERT( points.GetCount() >= 2 );
00090 
00091         return points.GetHead();
00092 }
00093 
00094 CPoint CAutoRouterPath::GetEndPoint(void) const
00095 {
00096         ASSERT( points.GetCount() >= 2 );
00097 
00098         return points.GetTail();
00099 }
00100 
00101 CRect CAutoRouterPath::GetStartBox(void) const
00102 {
00103         CAutoRouterBox* startbox = startport->GetOwner();
00104         return startbox->GetRect();
00105 }
00106 
00107 CRect CAutoRouterPath::GetEndBox(void) const
00108 {
00109         CAutoRouterBox* endbox = endport->GetOwner();
00110         return endbox->GetRect();
00111 }
00112 
00113 CPoint CAutoRouterPath::GetOutOfBoxStartPoint(RoutingDirection hintDir) const
00114 {
00115         const CRect startBoxRect = GetStartBox();
00116 
00117         ASSERT( hintDir != Dir_Skew );
00118         ASSERT( points.GetCount() >= 2 );
00119         POSITION pos = points.GetHeadPosition();
00120         CPoint p = points.GetNext(pos);
00121         RoutingDirection d = GetDir(points.GetAt(pos) - p);
00122         if (d == Dir_Skew)
00123                 d = hintDir;
00124         ASSERT( IsRightAngle(d) );
00125 
00126         GetPointCoord(p, d) = GetRectOuterCoord(startBoxRect, d);
00127         ASSERT( points.GetAt(pos) == p || GetDir(points.GetAt(pos) - p) == d ); 
00128 
00129         return p;
00130 }
00131 
00132 CPoint CAutoRouterPath::GetOutOfBoxEndPoint(RoutingDirection hintDir) const
00133 {
00134         const CRect endBoxRect = GetEndBox();
00135 
00136         ASSERT( hintDir != Dir_Skew );
00137         ASSERT( points.GetCount() >= 2 );
00138         POSITION pos = points.GetTailPosition();
00139         CPoint p = points.GetPrev(pos);
00140         RoutingDirection d = GetDir(points.GetAt(pos) - p);
00141         if (d == Dir_Skew)
00142                 d = hintDir;
00143         ASSERT( IsRightAngle(d) );
00144 
00145         GetPointCoord(p, d) = GetRectOuterCoord(endBoxRect, d);
00146         ASSERT( points.GetAt(pos) == p || GetDir(points.GetAt(pos) - p) == d ); 
00147 
00148         return p;
00149 }
00150 
00151 void CAutoRouterPath::SimplifyTrivially(void)
00152 {
00153         ASSERT( !IsConnected() );
00154 
00155         if( points.GetCount() <= 2 )
00156                 return;
00157         
00158         POSITION pos = points.GetHeadPosition();
00159 
00160         POSITION pos1 = pos;
00161         ASSERT( pos1 != NULL );
00162         CPoint p1 = points.GetNext(pos);
00163 
00164         POSITION pos2 = pos;
00165         ASSERT( pos2 != NULL );
00166         CPoint p2 = points.GetNext(pos);
00167 
00168         RoutingDirection dir12 = GetDir(p2-p1);
00169 
00170         POSITION pos3 = pos;
00171         ASSERT( pos3 != NULL );
00172         CPoint p3 = points.GetNext(pos);
00173 
00174         RoutingDirection dir23 = GetDir(p3-p2); 
00175 
00176         for(;;)
00177         {
00178                 if( dir12 == Dir_None || dir23 == Dir_None ||
00179                         (dir12 != Dir_Skew && dir23 != Dir_Skew &&
00180                         (dir12 == dir23 || dir12 == ReverseDir(dir23)) ) )
00181                 {
00182                         points.RemoveAt(pos2);
00183                         dir12 = GetDir(p3-p1);
00184                 }
00185                 else
00186                 {
00187                         pos1 = pos2;
00188                         p1 = p2;
00189                         dir12 = dir23;
00190                 }
00191 
00192                 if( pos == NULL )
00193                         return;
00194 
00195                 pos2 = pos3;
00196                 p2 = p3;
00197 
00198                 pos3 = pos;
00199                 p3 = points.GetNext(pos);
00200 
00201                 dir23 = GetDir(p3-p2);
00202         }
00203 
00204 #ifdef _DEBUG
00205         AssertValidPoints();
00206 #endif
00207 }
00208 
00209 CPointListPath& CAutoRouterPath::GetPointList(void)
00210 {
00211         return points;
00212 }
00213 
00214 void CAutoRouterPath::SetPoints(CPointListPath& pls)
00215 {
00216         points.RemoveAll();
00217         POSITION pos = pls.GetHeadPosition();
00218         while( pos != NULL )
00219         {
00220                 points.AddTail(pls.GetNext(pos));
00221         }
00222 }
00223 
00224 // --- Data
00225 
00226 CRect CAutoRouterPath::GetSurroundRect(void) const
00227 {
00228         CRect rect(INT_MAX,INT_MAX,INT_MIN,INT_MIN);
00229 
00230         POSITION pos = points.GetHeadPosition();
00231         while( pos != NULL )
00232         {
00233                 CPoint point = points.GetNext(pos);
00234 
00235                 rect.left = min(rect.left, point.x);
00236                 rect.top = min(rect.top, point.y);
00237                 rect.right = max(rect.right, point.x);
00238                 rect.bottom = max(rect.bottom, point.y);
00239         }
00240 
00241         if( rect.left == INT_MAX || rect.top == INT_MAX ||
00242                 rect.right == INT_MIN || rect.bottom == INT_MIN )
00243         {
00244                 rect.SetRectEmpty();
00245         }
00246 
00247         return rect;
00248 }
00249 
00250 bool CAutoRouterPath::IsEmpty(void) const
00251 {
00252         return points.IsEmpty() == TRUE;
00253 }
00254 
00255 bool CAutoRouterPath::IsPathAt(const CPoint& point, long nearness) const
00256 {
00257         return GetEdgePosAt(point, nearness) != NULL;
00258 }
00259 
00260 bool CAutoRouterPath::IsPathClip(const CRect& r, bool isStartOrEndRect) const
00261 {
00262         CPoint a;
00263         CPoint b;
00264 
00265         POSITION pos = points.GetTailEdge(a, b);
00266         int i = 0;
00267         int numEdges = points.GetSize() - 1;
00268         while( pos != NULL )
00269         {
00270                 if( isStartOrEndRect && ( i == 0 || i == numEdges - 1 ) )
00271                 {
00272                         if (IsPointIn(a, r, 1) &&
00273                                 IsPointIn(b, r, 1))
00274                         {
00275                                 return true;
00276                         }
00277                 }
00278                 else if( IsLineClipRect(a, b, r) )
00279                 {
00280                         return true;
00281                 }
00282 
00283                 points.GetPrevEdge(pos, a, b);
00284                 i++;
00285         }
00286 
00287         return false;
00288 }
00289 
00290 void CAutoRouterPath::SetAttributes(long attr)
00291 {
00292         attributes = attr;
00293 }
00294 
00295 long CAutoRouterPath::GetAttributes(void) const
00296 {
00297         return attributes;
00298 }
00299 
00300 bool CAutoRouterPath::IsFixed(void) const
00301 {
00302         return ((attributes & ARPATH_Fixed) != 0);
00303 }
00304 
00305 bool CAutoRouterPath::IsMoveable(void) const
00306 {
00307         return ((attributes & ARPATH_Fixed) == 0);
00308 }
00309 
00310 bool CAutoRouterPath::IsHighLighted(void) const
00311 {
00312         return ((attributes & ARPATH_HighLighted) != 0);
00313 }
00314 
00315 long CAutoRouterPath::GetState(void) const
00316 {
00317         return state;
00318 }
00319 
00320 void CAutoRouterPath::SetState(long s)
00321 {
00322         ASSERT( owner != NULL );
00323 
00324         state = s;
00325 
00326 #ifdef _DEBUG
00327         AssertValid();
00328 #endif
00329 }
00330 
00331 RoutingDirection CAutoRouterPath::GetEndDir(void) const
00332 {
00333         unsigned int a = attributes & ARPATH_EndMask;
00334         return  a & ARPATH_EndOnTop ? Dir_Top :
00335                         a & ARPATH_EndOnRight ? Dir_Right :
00336                         a & ARPATH_EndOnBottom ? Dir_Bottom :
00337                         a & ARPATH_EndOnLeft ? Dir_Left : Dir_None;
00338 }
00339 
00340 RoutingDirection CAutoRouterPath::GetStartDir(void) const
00341 {
00342         unsigned int a = attributes & ARPATH_StartMask;
00343         return  a & ARPATH_StartOnTop ? Dir_Top :
00344                         a & ARPATH_StartOnRight ? Dir_Right :
00345                         a & ARPATH_StartOnBottom ? Dir_Bottom :
00346                         a & ARPATH_StartOnLeft ? Dir_Left : Dir_None;
00347 }
00348 
00349 CAutoRouterGraph* CAutoRouterPath::GetOwner(void) const
00350 {
00351         return owner;
00352 }
00353 
00354 bool CAutoRouterPath::HasOwner(void) const
00355 {
00356         return owner != NULL;
00357 }
00358 
00359 void CAutoRouterPath::SetOwner(CAutoRouterGraph* graph)
00360 {
00361         owner = graph;
00362 }
00363 
00364 // --- Ports
00365 
00366 void CAutoRouterPath::SetStartPort(CAutoRouterPort* port)
00367 {
00368         startport = port;
00369 }
00370 
00371 void CAutoRouterPath::SetEndPort(CAutoRouterPort* port)
00372 {
00373         endport = port;
00374 }
00375 
00376 void CAutoRouterPath::ClearPorts(void)
00377 {
00378         startport = NULL;
00379         endport = NULL;
00380 }
00381 
00382 CAutoRouterPort* CAutoRouterPath::GetStartPort(void)
00383 {
00384         return startport;
00385 }
00386 
00387 CAutoRouterPort* CAutoRouterPath::GetEndPort(void)
00388 {
00389         return endport;
00390 }
00391 
00392 void CAutoRouterPath::SetEndDir(long arpath_end)
00393 {
00394         attributes = (attributes & ~ARPATH_EndMask) + (unsigned int)arpath_end;
00395 }
00396 
00397 void CAutoRouterPath::SetStartDir(long arpath_start)
00398 {
00399         attributes = (attributes & ~ARPATH_StartMask) + (unsigned int)arpath_start;
00400 }
00401 
00402 void CAutoRouterPath::SetCustomPathData(const std::vector<CustomPathData>& pDat)
00403 {
00404         customPathData = pDat;
00405 }
00406 
00407 void CAutoRouterPath::ApplyCustomizationsBeforeAutoConnectPoints(CPointListPath& plist)
00408 {
00409         plist.RemoveAll();
00410 
00411         if (customPathData.empty())
00412                 return;
00413 
00414         std::vector<CustomPathData>::iterator ii = customPathData.begin();
00415         while (ii != customPathData.end()) {
00416                 if ((*ii).GetType() == SimpleEdgeDisplacement) {
00417                         // it is done in a next phase
00418                 } else if ((*ii).GetType() == CustomPointCustomization) {
00419                         if (!isAutoRoutingOn)
00420                                 plist.AddTail(CPoint((*ii).GetX(), (*ii).GetY()));
00421                 } else {
00422                         // unknown displacement type
00423                 }
00424                 ++ii;
00425         }
00426 }
00427 
00428 void CAutoRouterPath::ApplyCustomizationsAfterAutoConnectPointsAndStuff(void)
00429 {
00430         if (customPathData.empty())
00431                 return;
00432 
00433         int numEdges = points.GetSize() - 1;
00434         if (isAutoRoutingOn) {
00435                 std::vector<CustomPathData>::iterator ii = customPathData.begin();
00436                 while (ii != customPathData.end()) {
00437                         if ((*ii).GetEdgeCount() != numEdges &&
00438                                 (*ii).GetType() == SimpleEdgeDisplacement)
00439                         {
00440                                 pathDataToDelete.push_back(*ii);
00441                                 ii = customPathData.erase(ii);
00442                         } else {
00443                                 ++ii;
00444                         }
00445                 }
00446         }
00447 
00448         CPoint* startpoint = NULL;
00449         CPoint* endpoint = NULL;
00450 
00451         int currEdgeIndex = 0;
00452         POSITION pos = points.GetHeadEdgePtrs(startpoint, endpoint);
00453         while (pos != NULL) {
00454                 std::vector<CustomPathData>::iterator ii = customPathData.begin();
00455                 while (ii != customPathData.end()) {
00456                         bool increment = true;
00457                         if (currEdgeIndex == (*ii).GetEdgeIndex()) {
00458                                 if ((*ii).GetType() == SimpleEdgeDisplacement) {
00459                                         RoutingDirection dir = GetDir(*endpoint - *startpoint);
00460                                         bool isHorizontalVar = (IsHorizontal(dir) != 0);
00461                                         bool doNotApply = false;
00462                                         if ((*ii).IsHorizontalOrVertical() == isHorizontalVar) {
00463                                                 int xToSet = (*ii).GetX();
00464                                                 int yToSet = (*ii).GetY();
00465                                                 // Check if the edge displacement at the end of the path
00466                                                 // is still within the boundary limits of the start or the end box
00467                                                 if (currEdgeIndex == 0 || currEdgeIndex == numEdges - 1) {
00468                                                         CRect startRect = startport->GetRect();
00469                                                         CRect endRect = endport->GetRect();
00470                                                         int minLimit = (currEdgeIndex == 0 ?
00471                                                                 ((*ii).IsHorizontalOrVertical() ? startRect.top : startRect.left) :
00472                                                                 ((*ii).IsHorizontalOrVertical() ? endRect.top : endRect.left));
00473                                                         int maxLimit = (currEdgeIndex == 0 ?
00474                                                                 ((*ii).IsHorizontalOrVertical() ? startRect.bottom : startRect.right) :
00475                                                                 ((*ii).IsHorizontalOrVertical() ? endRect.bottom : endRect.right));
00476                                                         int valueToSet = (*ii).IsHorizontalOrVertical() ? yToSet : xToSet;
00477                                                         if (valueToSet < minLimit || valueToSet > maxLimit)
00478                                                                 doNotApply = true;
00479                                                 }
00480                                                 if (!doNotApply) {
00481                                                         if ((*ii).IsHorizontalOrVertical()) {
00482                                                                 startpoint->y = yToSet;
00483                                                                 endpoint->y = yToSet;
00484                                                         } else {
00485                                                                 startpoint->x = xToSet;
00486                                                                 endpoint->x = xToSet;
00487                                                         }
00488                                                 }
00489                                         }
00490                                         if ((*ii).IsHorizontalOrVertical() != isHorizontalVar || doNotApply) {
00491                                                 // something went wrong, invalid data: direction (horz/vert) not match
00492 //                                              ASSERT(false);
00493                                                 pathDataToDelete.push_back(*ii);
00494                                                 ii = customPathData.erase(ii);
00495                                                 increment = false;
00496                                         }
00497                                 } else if ((*ii).GetType() == CustomPointCustomization) {
00498                                         // it is done in a previous phase
00499                                 } else {
00500                                         // unknown displacement type
00501                                 }
00502                         }
00503                         if (increment)
00504                                 ++ii;
00505                 }
00506 
00507                 points.GetNextEdgePtrs(pos, startpoint, endpoint);
00508                 currEdgeIndex++;
00509         }
00510 }
00511 
00512 void CAutoRouterPath::RemovePathCustomizations(void)
00513 {
00514         std::vector<CustomPathData>::iterator ii = customPathData.begin();
00515         while (ii != customPathData.end()) {
00516                 pathDataToDelete.push_back(*ii);
00517                 ++ii;
00518         }
00519         customPathData.clear();
00520 }
00521 
00522 void CAutoRouterPath::MarkPathCustomizationsForDeletion(long asp)
00523 {
00524         std::vector<CustomPathData>::iterator ii = customPathData.begin();
00525         while (ii != customPathData.end()) {
00526                 if ((*ii).GetAspect() == asp)
00527                         pathDataToDelete.push_back(*ii);
00528                 ++ii;
00529         }
00530 }
00531 
00532 void CAutoRouterPath::RemoveInvalidPathCustomizations(long asp)
00533 {
00534         // We only inhibit/delete those edges, which has an edge count
00535         // (redundand data intended for this very sanity check)
00536         // doesn't equal to edge count
00537         std::vector<CustomPathData>::iterator ii = customPathData.begin();
00538         int numEdges = points.GetSize() - 1;
00539         while (ii != customPathData.end()) {
00540                 if ((*ii).GetAspect() == asp) {
00541                         if ((*ii).GetEdgeCount() != numEdges &&
00542                                 (*ii).GetType() == SimpleEdgeDisplacement)
00543                         {
00544                                 ii = customPathData.erase(ii);
00545                         } else {
00546                                 ++ii;
00547                         }
00548                 } else {
00549                         ++ii;
00550                 }
00551         }
00552 }
00553 
00554 bool CAutoRouterPath::AreTherePathCustomizations(void) const
00555 {
00556         return !customPathData.empty();
00557 }
00558 
00559 bool CAutoRouterPath::AreThereDeletedPathCustomizations(void) const
00560 {
00561         return !pathDataToDelete.empty();
00562 }
00563 
00564 void CAutoRouterPath::GetDeletedCustomPathData(std::vector<CustomPathData>& cpd) const
00565 {
00566         std::vector<CustomPathData>::const_iterator ii = pathDataToDelete.begin();
00567         while(ii != pathDataToDelete.end()) {
00568                 cpd.push_back(*ii);
00569                 ++ii;
00570         }
00571 }
00572 
00573 void CAutoRouterPath::GetCustomizedEdgeIndexes(std::vector<int>& indexes) const
00574 {
00575         indexes.clear();
00576         std::vector<CustomPathData>::const_iterator ii = customPathData.begin();
00577         while(ii != customPathData.end())
00578         {
00579                 if (IsAutoRouted() && (*ii).GetType() == SimpleEdgeDisplacement ||
00580                         !IsAutoRouted() && (*ii).GetType() != SimpleEdgeDisplacement)
00581                 {
00582                         long edgeIndex = (*ii).GetEdgeIndex();
00583                         indexes.push_back(edgeIndex);
00584                 }
00585                 ++ii;
00586         }
00587 }
00588 
00589 bool CAutoRouterPath::IsAutoRouted(void) const
00590 {
00591         return isAutoRoutingOn;
00592 }
00593 
00594 void CAutoRouterPath::SetAutoRouting(bool autoRoutingState)
00595 {
00596         isAutoRoutingOn = autoRoutingState;
00597 }
00598 
00599 void CAutoRouterPath::Destroy(void)
00600 {
00601         SetStartPort(NULL);
00602         SetEndPort(NULL);
00603 }
00604 
00605 // --- External Pointer (ONLY FOR EXTERNAL USE)
00606 
00607 void* CAutoRouterPath::GetExtPtr() const
00608 {
00609         return extptr;
00610 }
00611 
00612 void CAutoRouterPath::SetExtPtr(void* p)
00613 {
00614         extptr = p;
00615 }
00616 
00617 // --- Debug
00618 
00619 #ifdef _DEBUG
00620 
00621 void CAutoRouterPath::AssertValid()
00622 {
00623         if( startport != NULL )
00624                 startport->AssertValid();
00625 
00626         if( endport != NULL )
00627                 endport->AssertValid();
00628 
00629         if( IsConnected() )
00630                 ASSERT( !points.IsEmpty() );
00631         else
00632                 ASSERT( points.IsEmpty() );
00633 }
00634 
00635 void CAutoRouterPath::AssertValidPos(POSITION pos) const
00636 {
00637         points.AssertValidPos(pos);
00638 }
00639 
00640 #pragma warning( disable : 4701 )
00641 
00642 void CAutoRouterPath::AssertValidPoints() const
00643 {
00644         points.AssertValid();
00645 
00646         if( points.IsEmpty() )
00647                 return;
00648 
00649 #ifdef _DEBUG_DEEP
00650         TRACE("CAutoRouterPath::AssertValidPoints (count=%ld) START\n", points.GetCount());
00651 #endif
00652 
00653         POSITION pos = points.GetHeadPosition();
00654         ASSERT( points.GetCount() >= 2 && pos != NULL );
00655 
00656         POSITION p1p = NULL;
00657         POSITION p2p = NULL;
00658         POSITION p3p;
00659 
00660         CPoint p1;
00661         CPoint p2;
00662 
00663         RoutingDirection d12;
00664         RoutingDirection d23;
00665         d23 = d12 = Dir_None;// init by zolmol
00666 
00667         while( pos != NULL )
00668         {
00669                 p3p = p2p;
00670                 p2p = p1p;
00671                 p1p = pos;
00672 
00673                 p2 = p1;
00674                 p1 = points.GetNext(pos);
00675 
00676 #ifdef _DEBUG_DEEP
00677                 TRACE("%p (%ld,%ld)\n", p1p, p1.x, p1.y);
00678 #endif
00679                 d23 = d12;
00680                 if( p2p != NULL )
00681                 {
00682                         d12 = GetDir(p2 - p1);
00683                         ASSERT( d12 == Dir_Skew || IsRightAngle(d12) );
00684                 }
00685 
00686                 if( p3p != NULL && d12 != Dir_Skew && d23 != Dir_Skew )
00687                         ASSERT( AreInRightAngle(d12, d23) );
00688         }
00689 
00690 #ifdef _DEBUG_DEEP
00691         TRACE("CAutoRouterPath::AssertValidPoints END\n");
00692 #endif
00693 
00694 }
00695 
00696 #endif
00697 
00698 // CAutoRouterPath