GME
13
|
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