GME
13
|
00001 00002 #include "stdafx.h" 00003 #include "afxcoll.h" 00004 #include "afxtempl.h" 00005 #include "float.h" 00006 00007 #include <map> 00008 00009 #include "AutoRouterGraph.h" 00010 #include "AutoRouterEdge.h" 00011 #include "AutoRouterPath.h" 00012 #include "AutoRouterBox.h" 00013 #include "AutoRouterPort.h" 00014 00015 #define EDLS_S (ED_SMALLGAP) 00016 #define EDLS_R (ED_SMALLGAP+1) 00017 #define EDLS_D (ED_MAXCOORD-ED_MINCOORD) 00018 00019 /* 00020 In this file every comments refer to the horizontal case, that is, each edge is 00021 horizontal. 00022 */ 00023 00024 /* 00025 Every CAutoRouterEdge belongs to an edge of a CAutoRouterPath, CAutoRouterBox or CAutoRouterPort. This edge is 00026 Represented by a CAutoRouterPoint with its next point. The variable 'point' will refer 00027 to this CAutoRouterPoint. 00028 00029 The coordinates of an edge are 'x1', 'x2' and 'y' where x1/x2 is the x-coordinate 00030 of the left/right point, and y is the common y-coordinate of the points. 00031 00032 The edges are ordered according to their y-coordinates. The first edge has 00033 the least y-coordinate (topmost), and its pointer is in 'order_first'. 00034 We use the 'order' prefix in the variable names to refer to this order. 00035 00036 We will walk from top to bottom (from the 'order_first' along the 'order_next'). 00037 We keep track a "section" of some edges. If we have an infinite horizontal line, 00038 then the section consists of those edges that are above the line and not blocked 00039 by another edge which is closer to the line. Each edge in the section has 00040 a viewable portion from the line (the not blocked portion). The coordinates 00041 of this portion are 'section_x1' and 'section_x2'. We have an order of the edges 00042 belonging to the current section. The 'section_first' refers to the leftmost 00043 edge in the section, while the 'section_next' to the next from left to right. 00044 00045 We say that the CAutoRouterEdge E1 "precede" the CAutoRouterEdge E2 if there is no other CAutoRouterEdge which 00046 totally blocks S1 from S2. So a section consists of the preceding edges of an 00047 infinite edge. We say that E1 is "adjacent" to E2, if E1 is the nearest edge 00048 to E2 which precede it. Clearly, every edge has at most one adjacent precedence. 00049 00050 The edges of any CAutoRouterBox or CAutoRouterPort are fixed. We will continually fix the edges 00051 of the CAutoRouterPaths. But first we need some definition. 00052 00053 We call a set of edges as a "block" if the topmost (first) and bottommost (last) 00054 edges of it are fixed while the edges between them are not. Furthermore, every 00055 edge is adjacent to the next one in the order. Every edge in the block has an 00056 "index". The index of the first one (topmost) is 0, of the second is 1, and so on. 00057 We call the index of the last edge (# of edges - 1) as the index of the entire box. 00058 The "depth" of a block is the difference of the y-coordinates of the first and last 00059 edges of it. The "goal gap" of the block is the quotient of the depth and index 00060 of the block. If the difference of the y-coordinates of the adjacent edges in 00061 the block are all equal to the goal gap, then we say that the block is evenly 00062 distributed. 00063 00064 So we search the block which has minimal goal gap. Then if it is not evenly 00065 distributed, then we shift the not fixed edges to the desired position. It is 00066 not hard to see that if the block has minimal goal gap (among the all 00067 possibilities of blocks), then in this way we do not move any edges into boxes. 00068 Finally, we set the (inner) edges of the block to be fixed (except the topmost and 00069 bottommost edges, since they are already fixed). And we again begin the search. 00070 If every edge is fixed, then we have finished. This is the basic idea. We will 00071 refine this algorithm. 00072 00073 The variables related to the blocks are prefixed by 'block'. Note that the 00074 variables of an edge are refer to that block in which this edge is inner! The 00075 'block_oldgap' is the goal gap of the block when it was last evenly distributed. 00076 00077 The variables 'canstart' and 'canend' means that this egde can start and/or end 00078 a block. The top edge of a box only canend, while a fixed edge of a path can both 00079 start and end of a block. 00080 00081 */ 00082 00083 00084 // --------------------------- CAutoRouterEdge 00085 00086 CAutoRouterEdge::CAutoRouterEdge() 00087 { 00088 this->owner = NULL; 00089 00090 this->startpoint_prev = NULL; 00091 this->startpoint = NULL; 00092 this->endpoint = NULL; 00093 this->endpoint_next = NULL; 00094 00095 this->position_y = 0; 00096 this->position_x1 = 0; 00097 this->position_x2 = 0; 00098 this->bracket_closing = 0; 00099 this->bracket_opening = 0; 00100 00101 this->order_prev = NULL; 00102 this->order_next = NULL; 00103 00104 this->edge_fixed = 0; 00105 this->edge_customFixed = 0; 00106 this->edge_canpassed = 0; 00107 00108 this->position_y = 0; 00109 00110 this->block_prev = NULL; 00111 this->block_next = NULL; 00112 this->block_trace = NULL; 00113 00114 this->closest_prev = NULL; 00115 this->closest_next = NULL; 00116 } 00117 00118 CAutoRouterEdge::~CAutoRouterEdge() 00119 { 00120 } 00121 00122 CObject* CAutoRouterEdge::GetOwner(void) const 00123 { 00124 return owner; 00125 } 00126 00127 void CAutoRouterEdge::SetOwner(CObject* owner) 00128 { 00129 this->owner = owner; 00130 } 00131 00132 CPoint CAutoRouterEdge::GetStartPointPrev(void) const 00133 { 00134 return startpoint_prev == NULL ? emptyPoint : *startpoint_prev; 00135 } 00136 00137 bool CAutoRouterEdge::IsStartPointPrevNull(void) const 00138 { 00139 return startpoint_prev == NULL; 00140 } 00141 00142 void CAutoRouterEdge::SetStartPointPrev(CPoint* point) 00143 { 00144 startpoint_prev = point; 00145 } 00146 00147 CPoint CAutoRouterEdge::GetStartPoint(void) const 00148 { 00149 return startpoint == NULL ? emptyPoint : *startpoint; 00150 } 00151 00152 bool CAutoRouterEdge::IsSameStartPointByPointer(const CPoint* point) const 00153 { 00154 return startpoint == point; 00155 } 00156 00157 bool CAutoRouterEdge::IsStartPointNull(void) const 00158 { 00159 return startpoint == NULL; 00160 } 00161 00162 void CAutoRouterEdge::SetStartPoint(CPoint* point) 00163 { 00164 startpoint = point; 00165 RecalculateDirection(); 00166 } 00167 00168 void CAutoRouterEdge::SetStartPointX(int x) 00169 { 00170 startpoint->x = x; 00171 } 00172 00173 void CAutoRouterEdge::SetStartPointY(int y) 00174 { 00175 startpoint->y = y; 00176 } 00177 00178 CPoint CAutoRouterEdge::GetEndPoint(void) const 00179 { 00180 return endpoint == NULL ? emptyPoint : *endpoint; 00181 } 00182 00183 bool CAutoRouterEdge::IsEndPointNull(void) const 00184 { 00185 return endpoint == NULL; 00186 } 00187 00188 void CAutoRouterEdge::SetEndPoint(CPoint* point) 00189 { 00190 endpoint = point; 00191 RecalculateDirection(); 00192 } 00193 00194 void CAutoRouterEdge::SetStartAndEndPoint(CPoint* startPoint, CPoint* endPoint) 00195 { 00196 startpoint = startPoint; 00197 endpoint = endPoint; 00198 RecalculateDirection(); 00199 } 00200 00201 void CAutoRouterEdge::SetEndPointX(int x) 00202 { 00203 endpoint->x = x; 00204 } 00205 00206 void CAutoRouterEdge::SetEndPointY(int y) 00207 { 00208 endpoint->y = y; 00209 } 00210 00211 CPoint CAutoRouterEdge::GetEndPointNext(void) const 00212 { 00213 return endpoint_next == NULL ? emptyPoint : *endpoint_next; 00214 } 00215 00216 bool CAutoRouterEdge::IsEndPointNextNull(void) const 00217 { 00218 return endpoint_next == NULL; 00219 } 00220 00221 void CAutoRouterEdge::SetEndPointNext(CPoint* point) 00222 { 00223 endpoint_next = point; 00224 } 00225 00226 float CAutoRouterEdge::GetPositionY(void) const 00227 { 00228 return position_y; 00229 } 00230 00231 void CAutoRouterEdge::SetPositionY(float y) 00232 { 00233 position_y = y; 00234 } 00235 00236 void CAutoRouterEdge::AddToPositionY(float dy) 00237 { 00238 position_y += dy; 00239 } 00240 00241 int CAutoRouterEdge::GetPositionX1(void) const 00242 { 00243 return position_x1; 00244 } 00245 00246 void CAutoRouterEdge::SetPositionX1(int x1) 00247 { 00248 position_x1 = x1; 00249 } 00250 00251 int CAutoRouterEdge::GetPositionX2(void) const 00252 { 00253 return position_x2; 00254 } 00255 00256 void CAutoRouterEdge::SetPositionX2(int x2) 00257 { 00258 position_x2 = x2; 00259 } 00260 00261 bool CAutoRouterEdge::GetBracketClosing(void) const 00262 { 00263 return bracket_closing; 00264 } 00265 00266 void CAutoRouterEdge::SetBracketClosing(bool b) 00267 { 00268 bracket_closing = b; 00269 } 00270 00271 bool CAutoRouterEdge::GetBracketOpening(void) const 00272 { 00273 return bracket_opening; 00274 } 00275 00276 void CAutoRouterEdge::SetBracketOpening(bool b) 00277 { 00278 bracket_opening = b; 00279 } 00280 00281 CAutoRouterEdge* CAutoRouterEdge::GetOrderNext(void) 00282 { 00283 return order_next; 00284 } 00285 00286 void CAutoRouterEdge::SetOrderNext(CAutoRouterEdge* ordernext) 00287 { 00288 order_next = ordernext; 00289 } 00290 00291 CAutoRouterEdge* CAutoRouterEdge::GetOrderPrev(void) 00292 { 00293 return order_prev; 00294 } 00295 00296 void CAutoRouterEdge::SetOrderPrev(CAutoRouterEdge* orderprev) 00297 { 00298 order_prev = orderprev; 00299 } 00300 00301 long CAutoRouterEdge::GetSectionX1(void) 00302 { 00303 return section_x1; 00304 } 00305 00306 void CAutoRouterEdge::SetSectionX1(long x1) 00307 { 00308 section_x1 = x1; 00309 } 00310 00311 long CAutoRouterEdge::GetSectionX2(void) 00312 { 00313 return section_x2; 00314 } 00315 00316 void CAutoRouterEdge::SetSectionX2(long x2) 00317 { 00318 section_x2 = x2; 00319 } 00320 00321 CAutoRouterEdge* CAutoRouterEdge::GetSectionNext(void) 00322 { 00323 return section_next; 00324 } 00325 00326 CAutoRouterEdge** CAutoRouterEdge::GetSectionNextPtr(void) 00327 { 00328 return §ion_next; 00329 } 00330 00331 void CAutoRouterEdge::SetSectionNext(CAutoRouterEdge* sectionnext) 00332 { 00333 section_next = sectionnext; 00334 } 00335 00336 CAutoRouterEdge* CAutoRouterEdge::GetSectionDown(void) 00337 { 00338 return section_down; 00339 } 00340 00341 CAutoRouterEdge** CAutoRouterEdge::GetSectionDownPtr(void) 00342 { 00343 return §ion_down; 00344 } 00345 00346 void CAutoRouterEdge::SetSectionDown(CAutoRouterEdge* sectiondown) 00347 { 00348 section_down = sectiondown; 00349 } 00350 00351 bool CAutoRouterEdge::GetEdgeFixed(void) 00352 { 00353 return edge_fixed; 00354 } 00355 00356 void CAutoRouterEdge::SetEdgeFixed(bool ef) 00357 { 00358 edge_fixed = ef; 00359 } 00360 00361 bool CAutoRouterEdge::GetEdgeCustomFixed(void) 00362 { 00363 return edge_customFixed; 00364 } 00365 00366 void CAutoRouterEdge::SetEdgeCustomFixed(bool ecf) 00367 { 00368 edge_customFixed = ecf; 00369 } 00370 00371 bool CAutoRouterEdge::GetEdgeCanpassed(void) 00372 { 00373 return edge_canpassed; 00374 } 00375 00376 void CAutoRouterEdge::SetEdgeCanpassed(bool ecp) 00377 { 00378 edge_canpassed = ecp; 00379 } 00380 00381 RoutingDirection CAutoRouterEdge::GetDirection(void) 00382 { 00383 return edge_direction; 00384 } 00385 00386 void CAutoRouterEdge::SetDirection(RoutingDirection dir) 00387 { 00388 edge_direction = dir; 00389 } 00390 00391 void CAutoRouterEdge::RecalculateDirection(void) 00392 { 00393 ASSERT(startpoint != NULL && endpoint != NULL); 00394 edge_direction = GetDir(*endpoint - *startpoint); 00395 } 00396 00397 CAutoRouterEdge* CAutoRouterEdge::GetBlockPrev(void) 00398 { 00399 return block_prev; 00400 } 00401 00402 void CAutoRouterEdge::SetBlockPrev(CAutoRouterEdge* bp) 00403 { 00404 block_prev = bp; 00405 } 00406 00407 CAutoRouterEdge* CAutoRouterEdge::GetBlockNext(void) 00408 { 00409 return block_next; 00410 } 00411 00412 void CAutoRouterEdge::SetBlockNext(CAutoRouterEdge* bn) 00413 { 00414 block_next = bn; 00415 } 00416 00417 CAutoRouterEdge* CAutoRouterEdge::GetBlockTrace(void) 00418 { 00419 return block_trace; 00420 } 00421 00422 void CAutoRouterEdge::SetBlockTrace(CAutoRouterEdge* bt) 00423 { 00424 block_trace = bt; 00425 } 00426 00427 CAutoRouterEdge* CAutoRouterEdge::GetClosestPrev(void) 00428 { 00429 return closest_prev; 00430 } 00431 00432 void CAutoRouterEdge::SetClosestPrev(CAutoRouterEdge* cp) 00433 { 00434 closest_prev = cp; 00435 } 00436 00437 CAutoRouterEdge* CAutoRouterEdge::GetClosestNext(void) 00438 { 00439 return closest_next; 00440 } 00441 00442 void CAutoRouterEdge::SetClosestNext(CAutoRouterEdge* cn) 00443 { 00444 closest_next = cn; 00445 } 00446 00447 00448 // --------------------------- CAutoRouterEdgeList 00449 00450 00451 CAutoRouterEdgeList::CAutoRouterEdgeList(bool h) 00452 { 00453 owner = NULL; 00454 00455 ishorizontal = (h != 0); 00456 00457 Init_Order(); 00458 Init_Section(); 00459 } 00460 00461 CAutoRouterEdgeList::~CAutoRouterEdgeList() 00462 { 00463 Check_Order(); 00464 Check_Section(); 00465 } 00466 00467 void CAutoRouterEdgeList::SetOwner(CAutoRouterGraph* o) 00468 { 00469 owner = o; 00470 } 00471 00472 // --- Edges 00473 00474 typedef std::pair<long,long> Long_Pair; 00475 00476 bool CAutoRouterEdgeList::AddEdges(CAutoRouterPath* path) 00477 { 00478 ASSERT_VALID(path); 00479 ASSERT( path->GetOwner() == owner ); 00480 ASSERT_VALID( path->GetStartPort() ); 00481 ASSERT_VALID( path->GetEndPort() ); 00482 00483 bool isPathAutoRouted = path->IsAutoRouted(); 00484 // Apply custom edge modifications - step 2, part 1 00485 // (Step 1: Move the desired edges 00486 // Step 2: Fix the desired edges) 00487 bool hasCustomEdge = false; 00488 std::map<long,long> customizedIndexes; // convert array to a map for easier lookup 00489 std::vector<int> indexes; 00490 path->GetCustomizedEdgeIndexes(indexes); 00491 00492 if (isPathAutoRouted) { 00493 std::vector<int>::iterator ii = indexes.begin(); 00494 while (ii != indexes.end()) { 00495 hasCustomEdge = true; 00496 customizedIndexes.insert(Long_Pair(*ii, 0)); 00497 ++ii; 00498 } 00499 } else { 00500 hasCustomEdge = true; 00501 } 00502 00503 std::map<long,long>::const_iterator indIter; 00504 CPointListPath& pointList = path->GetPointList(); 00505 long currEdgeIndex = pointList.GetSize() - 2; 00506 00507 CPoint* startpoint = NULL; 00508 CPoint* endpoint = NULL; 00509 00510 POSITION pos = pointList.GetTailEdgePtrs(startpoint, endpoint); 00511 while( pos != NULL ) 00512 { 00513 RoutingDirection dir = GetDir(*endpoint - *startpoint); 00514 00515 bool skipEdge = false; 00516 if (dir == Dir_None) 00517 skipEdge = true; 00518 bool isMovable = path->IsMoveable(); 00519 if( !isMovable && dir != Dir_Skew) 00520 { 00521 bool goodAngle = IsRightAngle(dir); 00522 ASSERT( goodAngle ); 00523 if (!goodAngle) 00524 skipEdge = true; 00525 } 00526 00527 if( !skipEdge && 00528 (//dir == Dir_Skew || -> do not add skew lines now, auto routing cannot do anything with it 00529 IsRightAngle(dir) && IsHorizontal(dir) == ishorizontal) ) 00530 { 00531 CAutoRouterEdge* edge = new CAutoRouterEdge(); 00532 00533 edge->SetOwner(path); 00534 00535 edge->SetStartAndEndPoint(startpoint, endpoint); 00536 edge->SetStartPointPrev(pointList.GetPointBeforeEdge(pos)); 00537 edge->SetEndPointNext(pointList.GetPointAfterEdge(pos)); 00538 00539 // Apply custom edge modifications - step 2, part 2 00540 if (hasCustomEdge) 00541 { 00542 bool isEdgeCustomFixed = false; 00543 if (isPathAutoRouted) { 00544 indIter = customizedIndexes.find(currEdgeIndex); 00545 isEdgeCustomFixed = (indIter != customizedIndexes.end()); 00546 } else { 00547 isEdgeCustomFixed = true; 00548 } 00549 edge->SetEdgeCustomFixed(isEdgeCustomFixed); 00550 } 00551 else 00552 { 00553 edge->SetEdgeCustomFixed(dir == Dir_Skew); 00554 } 00555 00556 CAutoRouterPort* startPort = path->GetStartPort(); 00557 ASSERT(startPort != NULL); 00558 bool isStartPortConnectToCenter = startPort->IsConnectToCenter(); 00559 00560 CAutoRouterPort* endPort = path->GetEndPort(); 00561 ASSERT(endPort != NULL); 00562 bool isEndPortConnectToCenter = endPort->IsConnectToCenter(); 00563 bool isPathFixed = path->IsFixed(); 00564 edge->SetEdgeFixed(edge->GetEdgeCustomFixed() || isPathFixed || 00565 (edge->IsStartPointPrevNull() && isStartPortConnectToCenter) || 00566 (edge->IsEndPointNextNull() && isEndPortConnectToCenter)); 00567 00568 if (dir != Dir_Skew) 00569 { 00570 Position_LoadY(edge); 00571 Position_LoadB(edge); 00572 } 00573 else 00574 { 00575 edge->SetPositionY(0.0); 00576 edge->SetBracketOpening(false); 00577 edge->SetBracketClosing(false); 00578 } 00579 Insert(edge); 00580 } 00581 00582 pointList.GetPrevEdgePtrs(pos, startpoint, endpoint); 00583 currEdgeIndex--; 00584 } 00585 00586 return true; 00587 } 00588 00589 CAutoRouterEdge* CAutoRouterEdgeList::GetEdge(CAutoRouterPath* path, const CPoint& startpoint, const CPoint& endpoint) const 00590 { 00591 CAutoRouterEdge* edge = order_first; 00592 while( edge != NULL ) 00593 { 00594 if( edge->GetStartPoint() == startpoint ) 00595 { 00596 if( edge->GetOwner() == path ) 00597 break; 00598 } 00599 00600 edge = edge->GetOrderNext(); 00601 } 00602 00603 ASSERT( edge != NULL ); 00604 return edge; 00605 } 00606 00607 CAutoRouterEdge* CAutoRouterEdgeList::GetEdgeByPointer(const CPoint* startpoint, const CPoint* endpoint) const 00608 { 00609 CAutoRouterEdge* edge = order_first; 00610 while( edge != NULL ) 00611 { 00612 if( edge->IsSameStartPointByPointer(startpoint) ) 00613 { 00614 break; 00615 } 00616 00617 edge = edge->GetOrderNext(); 00618 } 00619 00620 ASSERT( edge != NULL ); 00621 return edge; 00622 } 00623 00624 CAutoRouterEdge* CAutoRouterEdgeList::GetEdgeAt(const CPoint& point, int nearness) const 00625 { 00626 CAutoRouterEdge* edge = order_first; 00627 while( edge ) 00628 { 00629 if( IsPointNearLine(point, edge->GetStartPoint(), edge->GetEndPoint(), nearness) ) 00630 return edge; 00631 00632 edge = edge->GetOrderNext(); 00633 } 00634 00635 return NULL; 00636 } 00637 00638 #ifdef _DEBUG 00639 00640 void CAutoRouterEdgeList::AssertValidPathEdges(CAutoRouterPath* path, CPointListPath& points) const 00641 { 00642 ASSERT( path != NULL ); 00643 CAutoRouterGraph* ownerGraph = path->GetOwner(); 00644 ASSERT( ownerGraph == owner ); 00645 00646 CPoint* startpoint = NULL; 00647 CPoint* endpoint = NULL; 00648 00649 POSITION pos = points.GetTailEdgePtrs(startpoint, endpoint); 00650 while( pos != NULL ) 00651 { 00652 RoutingDirection dir = GetDir(*endpoint - *startpoint); 00653 00654 if( path->IsMoveable() ) 00655 ASSERT( IsRightAngle(dir) ); 00656 00657 if( IsRightAngle(dir) && IsHorizontal(dir) == ishorizontal ) 00658 { 00659 CAutoRouterEdge* edge = GetEdgeByPointer(startpoint, endpoint); 00660 ASSERT( edge != NULL ); 00661 00662 ASSERT( edge->GetOwner() == path ); 00663 00664 ASSERT( edge->GetStartPoint() == *startpoint ); 00665 ASSERT( edge->GetEndPoint() == *endpoint ); 00666 if (edge->IsStartPointPrevNull()) 00667 ASSERT( points.GetPointBeforeEdge(pos) == NULL ); 00668 else 00669 ASSERT( edge->GetStartPointPrev() == *(points.GetPointBeforeEdge(pos)) ); 00670 if (edge->IsEndPointNextNull()) 00671 ASSERT( points.GetPointAfterEdge(pos) == NULL ); 00672 else 00673 ASSERT( edge->GetEndPointNext() == *(points.GetPointAfterEdge(pos)) ); 00674 } 00675 00676 points.GetPrevEdgePtrs(pos, startpoint, endpoint); 00677 } 00678 00679 CAutoRouterEdge* edge = order_first; 00680 while( edge != NULL ) 00681 { 00682 if( edge->GetOwner() == path ) 00683 { 00684 POSITION pos = points.GetEdgePosForStartPoint(edge->GetStartPoint()); 00685 ASSERT( pos != NULL ); 00686 ASSERT( *(points.GetStartPoint(pos)) == edge->GetStartPoint() ); 00687 ASSERT( *(points.GetEndPoint(pos)) == edge->GetEndPoint() ); 00688 if (edge->IsStartPointPrevNull()) 00689 ASSERT( points.GetPointBeforeEdge(pos) == NULL ); 00690 else 00691 ASSERT( *(points.GetPointBeforeEdge(pos)) == edge->GetStartPointPrev() ); 00692 if (edge->IsEndPointNextNull()) 00693 ASSERT( points.GetPointAfterEdge(pos) == NULL ); 00694 else 00695 ASSERT( *(points.GetPointAfterEdge(pos)) == edge->GetEndPointNext() ); 00696 } 00697 00698 edge = edge->GetOrderNext(); 00699 } 00700 } 00701 00702 void CAutoRouterEdgeList::DumpEdges(const CString& headMsg) 00703 { 00704 #ifdef _DEBUG_DEEP 00705 TRACE0(headMsg + "\n"); 00706 CAutoRouterEdge* edge = order_first; 00707 int i = 0; 00708 while( edge != NULL ) 00709 { 00710 TRACE1("\t %ld.: ", i); 00711 TRACE2("sp %ld, %ld ", edge->IsStartPointNull() ? -1 : edge->GetStartPoint().x, edge->IsStartPointNull() ? -1 : edge->GetStartPoint().y); 00712 TRACE2("ep %ld, %ld ", edge->IsEndPointNull() ? -1 : edge->GetEndPoint().x, edge->IsEndPointNull() ? -1 : edge->GetEndPoint().y); 00713 TRACE2("spp %ld, %ld ", edge->IsStartPointPrevNull() ? -1 : edge->GetStartPointPrev().x, edge->IsStartPointPrevNull() ? -1 : edge->GetStartPointPrev().y); 00714 TRACE2("epn %ld, %ld\n", edge->IsEndPointNextNull() ? -1 : edge->GetEndPointNext().x, edge->IsEndPointNextNull() ? -1 : edge->GetEndPointNext().y); 00715 TRACE0("\t\t"); 00716 TRACE3("py %f px1 %ld px2 %ld ", edge->GetPositionY(), edge->GetPositionX1(), edge->GetPositionX2()); 00717 TRACE2("bc %ld bo %ld ", edge->GetBracketClosing(), edge->GetBracketOpening()); 00718 TRACE2("sx1 %ld sx2 %ld ", edge->GetSectionX1(), edge->GetSectionX2()); 00719 TRACE2("f %d cp %d\n", edge->GetEdgeFixed(), edge->GetEdgeCanpassed()); 00720 00721 edge = edge->GetOrderNext(); 00722 i++; 00723 } 00724 #endif 00725 } 00726 00727 #endif 00728 00729 void CAutoRouterEdgeList::AddEdges(CAutoRouterPort* port) 00730 { 00731 ASSERT_VALID(port); 00732 ASSERT( port->GetOwner()->GetOwner() == owner ); 00733 00734 if (port->IsConnectToCenter() || port->GetOwner()->IsAtomic()) 00735 return; 00736 00737 CPoint* selfpoints = port->GetSelfPoints(); 00738 00739 for(int i = 0; i < 4; i++) 00740 { 00741 CPoint* startpoint_prev = &(selfpoints[(i + 3) % 4]); 00742 CPoint* startpoint = &(selfpoints[i]); 00743 CPoint* endpoint = &(selfpoints[(i + 1) % 4]); 00744 CPoint* endpoint_next = &(selfpoints[(i + 2) % 4]); 00745 00746 RoutingDirection dir = GetDir(*endpoint - *startpoint); 00747 ASSERT( IsRightAngle(dir) ); 00748 00749 bool canHaveStartEndPointHorizontal = port->CanHaveStartEndPointHorizontal(ishorizontal); 00750 if( IsHorizontal(dir) == ishorizontal && canHaveStartEndPointHorizontal ) 00751 { 00752 CAutoRouterEdge* edge = new CAutoRouterEdge(); 00753 00754 edge->SetOwner(port); 00755 00756 edge->SetStartAndEndPoint(startpoint, endpoint); 00757 edge->SetStartPointPrev(startpoint_prev); 00758 edge->SetEndPointNext(endpoint_next); 00759 00760 edge->SetEdgeFixed(true); 00761 00762 Position_LoadY(edge); 00763 Position_LoadB(edge); 00764 00765 if( edge->GetBracketClosing() ) 00766 edge->AddToPositionY(0.999F); 00767 00768 Insert(edge); 00769 } 00770 } 00771 } 00772 00773 void CAutoRouterEdgeList::AddEdges(CAutoRouterBox* box) 00774 { 00775 ASSERT_VALID(box); 00776 ASSERT( box->GetOwner() == owner ); 00777 00778 CPoint* selfpoints = box->GetSelfPoints(); 00779 00780 for(int i = 0; i < 4; i++) 00781 { 00782 CPoint* startpoint_prev = &(selfpoints[(i + 3) % 4]); 00783 CPoint* startpoint = &(selfpoints[i]); 00784 CPoint* endpoint = &(selfpoints[(i + 1) % 4]); 00785 CPoint* endpoint_next = &(selfpoints[(i + 2) % 4]); 00786 00787 RoutingDirection dir = GetDir(*endpoint - *startpoint); 00788 ASSERT( IsRightAngle(dir) ); 00789 00790 if( IsHorizontal(dir) == ishorizontal ) 00791 { 00792 CAutoRouterEdge* edge = new CAutoRouterEdge(); 00793 00794 edge->SetOwner(box); 00795 00796 edge->SetStartAndEndPoint(startpoint, endpoint); 00797 edge->SetStartPointPrev(startpoint_prev); 00798 edge->SetEndPointNext(endpoint_next); 00799 00800 edge->SetEdgeFixed(true); 00801 00802 Position_LoadY(edge); 00803 Position_LoadB(edge); 00804 00805 if( edge->GetBracketClosing() ) 00806 edge->AddToPositionY(0.999F); 00807 00808 Insert(edge); 00809 } 00810 } 00811 } 00812 00813 void CAutoRouterEdgeList::AddEdges(CAutoRouterGraph* graph) 00814 { 00815 ASSERT_VALID(graph); 00816 ASSERT( graph == owner ); 00817 00818 CPoint* selfpoints = graph->GetSelfPoints(); 00819 00820 for(int i = 0; i < 4; i++) 00821 { 00822 CPoint* startpoint_prev = &(selfpoints[(i + 3) % 4]); 00823 CPoint* startpoint = &(selfpoints[i]); 00824 CPoint* endpoint = &(selfpoints[(i + 1) % 4]); 00825 CPoint* endpoint_next = &(selfpoints[(i + 2) % 4]); 00826 00827 RoutingDirection dir = GetDir(*endpoint - *startpoint); 00828 ASSERT( IsRightAngle(dir) ); 00829 00830 if( IsHorizontal(dir) == ishorizontal ) 00831 { 00832 CAutoRouterEdge* edge = new CAutoRouterEdge(); 00833 00834 edge->SetOwner(graph); 00835 00836 edge->SetStartAndEndPoint(startpoint, endpoint); 00837 edge->SetStartPointPrev(startpoint_prev); 00838 edge->SetEndPointNext(endpoint_next); 00839 00840 edge->SetEdgeFixed(true); 00841 00842 Position_LoadY(edge); 00843 Insert(edge); 00844 } 00845 } 00846 } 00847 00848 void CAutoRouterEdgeList::DeleteEdges(CObject* object) 00849 { 00850 CAutoRouterEdge* edge = order_first; 00851 while( edge != NULL ) 00852 { 00853 if( edge->GetOwner() == object ) 00854 { 00855 CAutoRouterEdge* next = edge->GetOrderNext(); 00856 Delete(edge); 00857 edge = next; 00858 } 00859 else 00860 edge = edge->GetOrderNext(); 00861 } 00862 } 00863 00864 void CAutoRouterEdgeList::DeleteAllEdges() 00865 { 00866 while( order_first ) 00867 Delete(order_first); 00868 } 00869 00870 bool CAutoRouterEdgeList::IsEmpty() const 00871 { 00872 return order_first == NULL; 00873 } 00874 00875 // --- Position 00876 00877 long CAutoRouterEdgeList::Position_GetRealY(const CAutoRouterEdge* edge) const 00878 { 00879 if( ishorizontal ) 00880 { 00881 ASSERT( edge->GetStartPoint().y == edge->GetEndPoint().y ); 00882 return edge->GetStartPoint().y; 00883 } 00884 00885 ASSERT( edge->GetStartPoint().x == edge->GetEndPoint().x ); 00886 return edge->GetStartPoint().x; 00887 } 00888 00889 void CAutoRouterEdgeList::Position_SetRealY(CAutoRouterEdge* edge, long y) const 00890 { 00891 ASSERT( edge != NULL && !edge->IsStartPointNull() && !edge->IsEndPointNull() ); 00892 00893 if( ishorizontal ) 00894 { 00895 ASSERT( edge->GetStartPoint().y == edge->GetEndPoint().y ); 00896 edge->SetStartPointY(y); 00897 edge->SetEndPointY(y); 00898 } 00899 else 00900 { 00901 ASSERT( edge->GetStartPoint().x == edge->GetEndPoint().x ); 00902 edge->SetStartPointX(y); 00903 edge->SetEndPointX(y); 00904 } 00905 } 00906 00907 void CAutoRouterEdgeList::Position_GetRealX(const CAutoRouterEdge* edge, long& x1, long& x2) const 00908 { 00909 ASSERT( edge != NULL && !edge->IsStartPointNull() && !edge->IsEndPointNull() ); 00910 00911 if( ishorizontal ) 00912 { 00913 ASSERT( edge->GetStartPoint().y == edge->GetEndPoint().y ); 00914 if( edge->GetStartPoint().x < edge->GetEndPoint().x ) 00915 { 00916 x1 = edge->GetStartPoint().x; 00917 x2 = edge->GetEndPoint().x; 00918 } 00919 else 00920 { 00921 x1 = edge->GetEndPoint().x; 00922 x2 = edge->GetStartPoint().x; 00923 } 00924 } 00925 else 00926 { 00927 ASSERT( edge->GetStartPoint().x == edge->GetEndPoint().x ); 00928 if( edge->GetStartPoint().y < edge->GetEndPoint().y ) 00929 { 00930 x1 = edge->GetStartPoint().y; 00931 x2 = edge->GetEndPoint().y; 00932 } 00933 else 00934 { 00935 x1 = edge->GetEndPoint().y; 00936 x2 = edge->GetStartPoint().y; 00937 } 00938 } 00939 } 00940 00941 void CAutoRouterEdgeList::Position_GetRealO(const CAutoRouterEdge* edge, long& o1, long& o2) const 00942 { 00943 ASSERT( edge != NULL && !edge->IsStartPointNull() && !edge->IsEndPointNull() ); 00944 00945 if( ishorizontal ) 00946 { 00947 ASSERT( edge->GetStartPoint().y == edge->GetEndPoint().y ); 00948 if( edge->GetStartPoint().x < edge->GetEndPoint().x ) 00949 { 00950 o1 = edge->IsStartPointPrevNull() ? 0 : edge->GetStartPointPrev().y - edge->GetStartPoint().y; 00951 o2 = edge->IsEndPointNextNull() ? 0 : edge->GetEndPointNext().y - edge->GetEndPoint().y; 00952 } 00953 else 00954 { 00955 o1 = edge->IsEndPointNextNull() ? 0 : edge->GetEndPointNext().y - edge->GetEndPoint().y; 00956 o2 = edge->IsStartPointPrevNull() ? 0 : edge->GetStartPointPrev().y - edge->GetStartPoint().y; 00957 } 00958 } 00959 else 00960 { 00961 ASSERT( edge->GetStartPoint().x == edge->GetEndPoint().x ); 00962 if( edge->GetStartPoint().y < edge->GetEndPoint().y ) 00963 { 00964 o1 = edge->IsStartPointPrevNull() ? 0 : edge->GetStartPointPrev().x - edge->GetStartPoint().x; 00965 o2 = edge->IsEndPointNextNull() ? 0 : edge->GetEndPointNext().x - edge->GetEndPoint().x; 00966 } 00967 else 00968 { 00969 o1 = edge->IsEndPointNextNull() ? 0 : edge->GetEndPointNext().x - edge->GetEndPoint().x; 00970 o2 = edge->IsStartPointPrevNull() ? 0 : edge->GetStartPointPrev().x - edge->GetStartPoint().x; 00971 } 00972 } 00973 } 00974 00975 void CAutoRouterEdgeList::Position_LoadY(CAutoRouterEdge* edge) const 00976 { 00977 ASSERT( edge != NULL && edge->GetOrderNext() == NULL && edge->GetOrderPrev() == NULL ); 00978 00979 edge->SetPositionY((float) Position_GetRealY(edge)); 00980 } 00981 00982 void CAutoRouterEdgeList::Position_LoadB(CAutoRouterEdge* edge) const 00983 { 00984 ASSERT( edge != NULL ); 00985 00986 edge->SetBracketOpening(!edge->GetEdgeFixed() && Bracket_IsOpening(edge)); 00987 edge->SetBracketClosing(!edge->GetEdgeFixed() && Bracket_IsClosing(edge)); 00988 } 00989 00990 void CAutoRouterEdgeList::PositionAll_StoreY() const 00991 { 00992 CAutoRouterEdge* edge = order_first; 00993 while( edge ) 00994 { 00995 Position_SetRealY(edge, (long) edge->GetPositionY()); 00996 00997 edge = edge->GetOrderNext(); 00998 } 00999 } 01000 01001 void CAutoRouterEdgeList::PositionAll_LoadX() const 01002 { 01003 CAutoRouterEdge* edge = order_first; 01004 while( edge ) 01005 { 01006 long ex1, ex2; 01007 Position_GetRealX(edge, ex1, ex2); 01008 edge->SetPositionX1(ex1); 01009 edge->SetPositionX2(ex2); 01010 01011 edge = edge->GetOrderNext(); 01012 } 01013 } 01014 01015 #ifdef _DEBUG 01016 01017 void CAutoRouterEdgeList::AssertValidPositions() const 01018 { 01019 CAutoRouterEdge* edge = order_first; 01020 while( edge ) 01021 { 01022 long y = Position_GetRealY(edge); 01023 ASSERT( edge->GetPositionY() - 1 <= y && y <= edge->GetPositionY() + 1 ); 01024 01025 if( edge->GetOrderPrev() ) 01026 { 01027 ASSERT( edge->GetOrderPrev()->GetPositionY() <= edge->GetPositionY() ); 01028 ASSERT( Position_GetRealY(edge->GetOrderPrev()) <= y ); 01029 } 01030 01031 if( edge->GetOrderNext() ) 01032 { 01033 ASSERT( edge->GetPositionY() <= edge->GetOrderNext()->GetPositionY() ); 01034 ASSERT( y <= Position_GetRealY(edge->GetOrderNext()) ); 01035 } 01036 01037 edge = edge->GetOrderNext(); 01038 } 01039 } 01040 01041 #endif 01042 01043 // --- Order 01044 01045 void CAutoRouterEdgeList::Init_Order() 01046 { 01047 order_first = NULL; 01048 order_last = NULL; 01049 } 01050 01051 void CAutoRouterEdgeList::Check_Order() 01052 { 01053 ASSERT( order_first == NULL && order_last == NULL ); 01054 } 01055 01056 void CAutoRouterEdgeList::InsertBefore(CAutoRouterEdge* edge, CAutoRouterEdge* before) 01057 { 01058 ASSERT( edge != NULL && before != NULL && edge != before ); 01059 ASSERT( edge->GetOrderNext() == NULL && edge->GetOrderPrev() == NULL ); 01060 01061 edge->SetOrderPrev(before->GetOrderPrev()); 01062 edge->SetOrderNext(before); 01063 01064 if( before->GetOrderPrev() ) 01065 { 01066 ASSERT( before->GetOrderPrev()->GetOrderNext() == before ); 01067 before->GetOrderPrev()->SetOrderNext(edge); 01068 01069 ASSERT( order_first != before ); 01070 } 01071 else 01072 { 01073 ASSERT( order_first == before ); 01074 order_first = edge; 01075 } 01076 01077 before->SetOrderPrev(edge); 01078 } 01079 01080 void CAutoRouterEdgeList::InsertAfter(CAutoRouterEdge* edge, CAutoRouterEdge* after) 01081 { 01082 ASSERT( edge != NULL && after != NULL && edge != after ); 01083 ASSERT( edge->GetOrderNext() == NULL && edge->GetOrderPrev() == NULL ); 01084 01085 edge->SetOrderNext(after->GetOrderNext()); 01086 edge->SetOrderPrev(after); 01087 01088 if( after->GetOrderNext() ) 01089 { 01090 ASSERT( after->GetOrderNext()->GetOrderPrev() == after ); 01091 after->GetOrderNext()->SetOrderPrev(edge); 01092 01093 ASSERT( order_last != after ); 01094 } 01095 else 01096 { 01097 ASSERT( order_last == after ); 01098 order_last = edge; 01099 } 01100 01101 after->SetOrderNext(edge); 01102 } 01103 01104 void CAutoRouterEdgeList::InsertLast(CAutoRouterEdge* edge) 01105 { 01106 ASSERT( edge != NULL ); 01107 ASSERT( edge->GetOrderPrev() == NULL && edge->GetOrderNext() == NULL ); 01108 01109 edge->SetOrderPrev(order_last); 01110 01111 if( order_last ) 01112 { 01113 ASSERT( order_last->GetOrderNext() == NULL ); 01114 ASSERT( order_first != NULL ); 01115 01116 order_last->SetOrderNext(edge); 01117 order_last = edge; 01118 } 01119 else 01120 { 01121 ASSERT( order_first == NULL ); 01122 01123 order_first = edge; 01124 order_last = edge; 01125 } 01126 } 01127 01128 void CAutoRouterEdgeList::Insert(CAutoRouterEdge* edge) 01129 { 01130 ASSERT( edge != NULL ); 01131 ASSERT( edge->GetOrderPrev() == NULL && edge->GetOrderNext() == NULL ); 01132 01133 float y = edge->GetPositionY(); 01134 ASSERT( ED_MINCOORD <= y && y <= ED_MAXCOORD ); 01135 01136 CAutoRouterEdge* insert = order_first; 01137 // FIXME: std::sort would be better than insertion sort 01138 while( insert && insert->GetPositionY() < y ) 01139 insert = insert->GetOrderNext(); 01140 01141 if( insert ) 01142 InsertBefore(edge, insert); 01143 else 01144 InsertLast(edge); 01145 } 01146 01147 void CAutoRouterEdgeList::Remove(CAutoRouterEdge* edge) 01148 { 01149 ASSERT( edge != NULL ); 01150 01151 if( order_first == edge ) 01152 order_first = edge->GetOrderNext(); 01153 01154 if( edge->GetOrderNext() ) 01155 edge->GetOrderNext()->SetOrderPrev(edge->GetOrderPrev()); 01156 01157 if( order_last == edge ) 01158 order_last = edge->GetOrderPrev(); 01159 01160 if( edge->GetOrderPrev() ) 01161 edge->GetOrderPrev()->SetOrderNext(edge->GetOrderNext()); 01162 01163 edge->SetOrderNext(NULL); 01164 edge->SetOrderPrev(NULL); 01165 } 01166 01167 void CAutoRouterEdgeList::Delete(CAutoRouterEdge* edge) 01168 { 01169 ASSERT( edge != NULL ); 01170 01171 Remove(edge); 01172 01173 edge->SetOwner(NULL); 01174 01175 delete edge; 01176 } 01177 01178 CAutoRouterEdge* CAutoRouterEdgeList::SlideButNotPassEdges(CAutoRouterEdge* edge, float y) 01179 { 01180 ASSERT( edge != NULL ); 01181 ASSERT( ED_MINCOORD < y && y < ED_MAXCOORD ); 01182 01183 float oldy = edge->GetPositionY(); 01184 ASSERT( ED_MINCOORD < oldy && oldy < ED_MAXCOORD ); 01185 01186 if( oldy == y ) 01187 return NULL; 01188 01189 long x1 = edge->GetPositionX1(); 01190 long x2 = edge->GetPositionX2(); 01191 CAutoRouterEdge* ret = NULL; 01192 01193 CAutoRouterEdge* insert = edge; 01194 if( oldy < y ) 01195 { 01196 while( insert->GetOrderNext() ) 01197 { 01198 insert = insert->GetOrderNext(); 01199 01200 if( y < insert->GetPositionY() ) 01201 break; 01202 01203 if( !insert->GetEdgeCanpassed() && Intersect(x1, x2, insert->GetPositionX1(), insert->GetPositionX2() ) ) 01204 { 01205 ret = insert; 01206 y = insert->GetPositionY(); 01207 break; 01208 } 01209 } 01210 01211 if( edge != insert && insert->GetOrderPrev() != edge ) 01212 { 01213 Remove(edge); 01214 InsertBefore(edge, insert); 01215 } 01216 } 01217 else 01218 { 01219 while( insert->GetOrderPrev() ) 01220 { 01221 insert = insert->GetOrderPrev(); 01222 01223 if( y > insert->GetPositionY() ) 01224 break; 01225 01226 if( !insert->GetEdgeCanpassed() && Intersect(x1, x2, insert->GetPositionX1(), insert->GetPositionX2() ) ) 01227 { 01228 ret = insert; 01229 y = insert->GetPositionY(); 01230 break; 01231 } 01232 } 01233 01234 if( edge != insert && insert->GetOrderNext() != edge ) 01235 { 01236 Remove(edge); 01237 InsertAfter(edge, insert); 01238 } 01239 01240 } 01241 01242 #ifdef _DEBUG 01243 if( edge->GetOrderNext() ) 01244 ASSERT( y <= edge->GetOrderNext()->GetPositionY() ); 01245 01246 if( edge->GetOrderPrev() ) 01247 ASSERT( edge->GetOrderPrev()->GetPositionY() <= y ); 01248 #endif 01249 01250 edge->SetPositionY(y); 01251 01252 return ret; 01253 } 01254 01255 #ifdef _DEBUG 01256 01257 void CAutoRouterEdgeList::AssertValidOrder() const 01258 { 01259 ASSERT( order_first != NULL && order_last != NULL ); 01260 ASSERT( order_first->GetOrderPrev() == NULL ); 01261 ASSERT( order_last->GetOrderNext() == NULL ); 01262 01263 float y = ED_MINCOORD; 01264 01265 TRACE("CAutoRouterEdgeList::AssertValidOrder (horizontal=%d) START\n", ishorizontal); 01266 01267 CAutoRouterEdge* edge = order_first; 01268 while( edge != order_last ) 01269 { 01270 TRACE("edge=%p, position_y=%f\n", edge, edge->GetPositionY()); 01271 01272 ASSERT( edge != NULL ); 01273 ASSERT( y <= edge->GetPositionY() ); 01274 ASSERT( edge->GetOrderNext()->GetOrderPrev() == edge ); 01275 01276 y = edge->GetPositionY(); 01277 edge = edge->GetOrderNext(); 01278 } 01279 01280 TRACE("edge=%p, position_y=%f\n", edge, edge->GetPositionY()); 01281 TRACE("CAutoRouterEdgeList::AssertValidOrder (horizontal=%d) END\n", ishorizontal); 01282 01283 ASSERT( y <= ED_MAXCOORD ); 01284 } 01285 01286 #endif 01287 01288 // --- Section 01289 01290 void CAutoRouterEdgeList::Init_Section() 01291 { 01292 section_first = NULL; 01293 section_blocker = NULL; 01294 section_ptr2blocked = NULL; 01295 } 01296 01297 void CAutoRouterEdgeList::Check_Section() 01298 { 01299 ASSERT( section_blocker == NULL && section_ptr2blocked == NULL ); 01300 } 01301 01302 void CAutoRouterEdgeList::Section_Reset() 01303 { 01304 ASSERT( section_blocker == NULL && section_ptr2blocked == NULL ); 01305 01306 section_first = NULL; 01307 } 01308 01309 void CAutoRouterEdgeList::Section_BeginScan(CAutoRouterEdge* blocker) 01310 { 01311 ASSERT( section_blocker == NULL && section_ptr2blocked == NULL ); 01312 01313 section_blocker = blocker; 01314 01315 section_blocker->SetSectionX1(section_blocker->GetPositionX1()); 01316 section_blocker->SetSectionX2(section_blocker->GetPositionX2()); 01317 01318 section_blocker->SetSectionNext(NULL); 01319 section_blocker->SetSectionDown(NULL); 01320 } 01321 01322 #define section_blocked (*section_ptr2blocked) 01323 bool CAutoRouterEdgeList::Section_HasBlockedEdge() 01324 { 01325 ASSERT( section_blocker != NULL ); 01326 01327 long b1 = section_blocker->GetSectionX1(); 01328 long b2 = section_blocker->GetSectionX2(); 01329 ASSERT( b1 <= b2 ); 01330 01331 if( section_ptr2blocked == NULL ) 01332 { 01333 section_ptr2blocked = §ion_first; 01334 } 01335 else 01336 { 01337 CAutoRouterEdge* current_edge = section_blocked; 01338 01339 ASSERT( current_edge != NULL ); 01340 01341 CAutoRouterEdge* e = current_edge->GetSectionDown(); 01342 CAutoRouterEdge* o = NULL; 01343 01344 long a1 = current_edge->GetSectionX1(); 01345 long a2 = current_edge->GetSectionX2(); 01346 ASSERT( a1 <= a2 ); 01347 01348 ASSERT( b1 <= a2 && a1 <= b2 ); // not case 1 or 6 01349 01350 if( a1 < b1 && b2 < a2 ) // case 3 01351 { 01352 section_ptr2blocked = current_edge->GetSectionDownPtr(); 01353 } 01354 else if( b1 <= a1 && a2 <= b2 ) // case 4 01355 { 01356 if( e ) 01357 { 01358 while( e->GetSectionNext() ) 01359 e = e->GetSectionNext(); 01360 01361 e->SetSectionNext(current_edge->GetSectionNext()); 01362 section_blocked = current_edge->GetSectionDown(); 01363 } 01364 else 01365 section_blocked = current_edge->GetSectionNext(); 01366 } 01367 else if( b1 <= a1 && b2 < a2 ) // case 5 01368 { 01369 ASSERT( a1 <= b2 ); 01370 01371 a1 = b2 + 1; 01372 01373 while( e && e->GetSectionX1() <= a1 ) 01374 { 01375 ASSERT( e->GetSectionX1() <= e->GetSectionX2() ); 01376 01377 if( a1 <= e->GetSectionX2() ) 01378 a1 = e->GetSectionX2() + 1; 01379 01380 o = e; 01381 e = e->GetSectionNext(); 01382 } 01383 01384 if( o ) 01385 { 01386 section_blocked = current_edge->GetSectionDown(); 01387 o->SetSectionNext(current_edge); 01388 current_edge->SetSectionDown(e); 01389 } 01390 01391 ASSERT( b2 < a1 ); 01392 current_edge->SetSectionX1(a1); 01393 } 01394 else // case 2 01395 { 01396 ASSERT( a1 < b1 && b1 <= a2 && a2 <= b2 ); 01397 01398 section_ptr2blocked = current_edge->GetSectionDownPtr(); 01399 01400 while( e ) 01401 { 01402 o = e; 01403 e = e->GetSectionNext(); 01404 01405 if( o->GetSectionX2() + 1 < b1 && ( e == NULL || o->GetSectionX2() + 1 < e->GetSectionX1() ) ) 01406 section_ptr2blocked = o->GetSectionNextPtr(); 01407 } 01408 01409 if( section_blocked ) 01410 { 01411 ASSERT( o != NULL ); 01412 o->SetSectionNext(current_edge->GetSectionNext()); 01413 01414 current_edge->SetSectionX2( 01415 (section_blocked->GetSectionX1() < b1 ? section_blocked->GetSectionX1() : b1) - 1); 01416 01417 current_edge->SetSectionNext(section_blocked); 01418 section_blocked = NULL; 01419 } 01420 else 01421 current_edge->SetSectionX2(b1 - 1); 01422 01423 section_ptr2blocked = current_edge->GetSectionNextPtr(); 01424 } 01425 } 01426 01427 ASSERT( section_ptr2blocked != NULL ); 01428 while( section_blocked ) 01429 { 01430 long a1 = section_blocked->GetSectionX1(); 01431 long a2 = section_blocked->GetSectionX2(); 01432 01433 if( a2 < b1 ) // case 1 01434 { 01435 section_ptr2blocked = section_blocked->GetSectionNextPtr(); 01436 01437 ASSERT( section_ptr2blocked != NULL ); 01438 continue; 01439 } 01440 else if( b2 < a1 ) // case 6 01441 break; 01442 01443 if( a1 < b1 && b2 < a2 ) // case 3 01444 { 01445 long x = b1; 01446 01447 CAutoRouterEdge* e = section_blocked->GetSectionDown(); 01448 for(;;) 01449 { 01450 if( e == NULL || x < e->GetSectionX1() ) 01451 return true; 01452 else if( x <= e->GetSectionX2() ) 01453 { 01454 x = e->GetSectionX2() + 1; 01455 if( b2 < x ) 01456 break; 01457 } 01458 01459 e = e->GetSectionNext(); 01460 } 01461 01462 section_ptr2blocked = section_blocked->GetSectionDownPtr(); 01463 continue; 01464 } 01465 01466 return true; 01467 } 01468 01469 ASSERT( section_blocker->GetSectionNext() == NULL && section_blocker->GetSectionDown() == NULL ); 01470 01471 section_blocker->SetSectionNext(section_blocked); 01472 section_blocked = section_blocker; 01473 01474 section_blocker = NULL; 01475 section_ptr2blocked = NULL; 01476 01477 return false; 01478 } 01479 #undef section_blocked 01480 01481 CAutoRouterEdge* CAutoRouterEdgeList::Section_GetBlockedEdge() 01482 { 01483 ASSERT( section_blocker != NULL && section_ptr2blocked != NULL && *section_ptr2blocked != NULL ); 01484 #ifdef _DEBUG_DEEP 01485 AssertValidSection(); 01486 #endif 01487 01488 return *section_ptr2blocked; 01489 } 01490 01491 bool CAutoRouterEdgeList::Section_IsImmediate() 01492 { 01493 ASSERT( section_blocker != NULL && section_ptr2blocked != NULL && *section_ptr2blocked != NULL ); 01494 01495 CAutoRouterEdge* section_blocked = *section_ptr2blocked; 01496 CAutoRouterEdge* e = section_blocked->GetSectionDown(); 01497 01498 long a1 = section_blocked->GetSectionX1(); 01499 long a2 = section_blocked->GetSectionX2(); 01500 long p1 = section_blocked->GetPositionX1(); 01501 long p2 = section_blocked->GetPositionX2(); 01502 long b1 = section_blocker->GetSectionX1(); 01503 long b2 = section_blocker->GetSectionX2(); 01504 01505 ASSERT( b1 <= a2 && a1 <= b2 ); // not case 1 or 6 01506 01507 // NOTE WE CHANGED THE CONDITIONS (A1<=B1 AND B2<=A2) 01508 // BECAUSE HERE WE NEED THIS! 01509 01510 if( a1 <= b1 ) 01511 { 01512 while( e != NULL && e->GetSectionX2() < b1 ) 01513 e = e->GetSectionNext(); 01514 01515 if( b2 <= a2 ) 01516 return e == NULL || b2 < e->GetSectionX1(); // case 3 01517 01518 return e == NULL && a2 == p2; // case 2 01519 } 01520 01521 if( b2 <= a2 ) 01522 return a1 == p1 && (e == NULL || b2 < e->GetSectionX1()); // case 5 01523 01524 return e == NULL && a1 == p1 && a2 == p2; // case 4 01525 } 01526 01527 #ifdef _DEBUG 01528 01529 void CAutoRouterEdgeList::Section_AssertLevel(CAutoRouterEdge* level, long x1, long x2) const 01530 { 01531 while( level ) 01532 { 01533 ASSERT( level->GetPositionX1() <= level->GetSectionX1() && level->GetSectionX2() <= level->GetPositionX2() ); 01534 ASSERT( x1 < level->GetSectionX1() && level->GetSectionX1() <= level->GetSectionX2() && level->GetSectionX2() < x2 ); 01535 ASSERT( level->GetSectionNext() == NULL || level->GetSectionX2() < level->GetSectionNext()->GetSectionX1() ); 01536 01537 Section_AssertLevel(level->GetSectionDown(), level->GetSectionX1(), level->GetSectionX2()); 01538 01539 level = level->GetSectionNext(); 01540 } 01541 } 01542 01543 void CAutoRouterEdgeList::AssertValidSection() const 01544 { 01545 Section_AssertLevel(section_first, ED_MINCOORD-1, ED_MAXCOORD+1); 01546 } 01547 01548 void CAutoRouterEdgeList::AssertSectionReady() const 01549 { 01550 ASSERT( section_blocker == NULL && section_ptr2blocked == NULL ); 01551 } 01552 01553 #endif 01554 01555 // --- Bracket 01556 01557 bool CAutoRouterEdgeList::Bracket_IsClosing(const CAutoRouterEdge* edge) const 01558 { 01559 ASSERT( edge != NULL ); 01560 ASSERT( !edge->IsStartPointNull() && !edge->IsEndPointNull() ); 01561 01562 CPoint start = edge->GetStartPoint(); 01563 CPoint end = edge->GetEndPoint(); 01564 01565 #ifdef _DEBUG 01566 if( ishorizontal ) 01567 { 01568 ASSERT( start.y == end.y ); 01569 01570 if( !edge->IsStartPointPrevNull() ) 01571 ASSERT( edge->GetStartPointPrev().x == start.x ); 01572 01573 if( !edge->IsEndPointNextNull() ) 01574 ASSERT( edge->GetEndPointNext().x == end.x ); 01575 } 01576 else 01577 { 01578 ASSERT( start.x == end.x ); 01579 01580 if( !edge->IsStartPointPrevNull() ) 01581 ASSERT( edge->GetStartPointPrev().y == start.y ); 01582 01583 if( !edge->IsEndPointNextNull() ) 01584 ASSERT( edge->GetEndPointNext().y == end.y ); 01585 } 01586 #endif 01587 01588 if( edge->IsStartPointPrevNull() || edge->IsEndPointNextNull() ) 01589 return false; 01590 01591 return ishorizontal ? 01592 (edge->GetStartPointPrev().y < start.y && edge->GetEndPointNext().y < end.y ) : 01593 (edge->GetStartPointPrev().x < start.x && edge->GetEndPointNext().x < end.x ); 01594 } 01595 01596 bool CAutoRouterEdgeList::Bracket_IsOpening(const CAutoRouterEdge* edge) const 01597 { 01598 ASSERT( edge != NULL ); 01599 ASSERT( !edge->IsStartPointNull() && !edge->IsEndPointNull() ); 01600 01601 CPoint start = edge->GetStartPoint(); 01602 CPoint end = edge->GetEndPoint(); 01603 #ifdef _DEBUG 01604 if( ishorizontal ) 01605 { 01606 ASSERT( start.y == end.y ); 01607 01608 if( !edge->IsStartPointPrevNull() ) 01609 ASSERT( edge->GetStartPointPrev().x == start.x ); 01610 01611 if( !edge->IsEndPointNextNull() ) 01612 ASSERT( edge->GetEndPointNext().x == end.x ); 01613 } 01614 else 01615 { 01616 ASSERT( start.x == end.x ); 01617 01618 if( !edge->IsStartPointPrevNull() ) 01619 ASSERT( edge->GetStartPointPrev().y == start.y ); 01620 01621 if( !edge->IsEndPointNextNull() ) 01622 ASSERT( edge->GetEndPointNext().y == end.y ); 01623 } 01624 #endif 01625 01626 if( edge->IsStartPointPrevNull() || edge->IsEndPointNextNull() ) 01627 return false; 01628 01629 return ishorizontal ? 01630 (edge->GetStartPointPrev().y > start.y && edge->GetEndPointNext().y > end.y ) : 01631 (edge->GetStartPointPrev().x > start.x && edge->GetEndPointNext().x > end.x ); 01632 } 01633 01634 bool CAutoRouterEdgeList::Bracket_IsSmallGap(const CAutoRouterEdge* blocked, const CAutoRouterEdge* blocker) const 01635 { 01636 return Bracket_IsOpening(blocked) || Bracket_IsClosing(blocker); 01637 } 01638 01639 bool CAutoRouterEdgeList::Bracket_ShouldBeSwitched(const CAutoRouterEdge* edge, const CAutoRouterEdge* next) const 01640 { 01641 ASSERT( edge != NULL && next != NULL ); 01642 01643 long ex1, ex2, eo1, eo2; 01644 Position_GetRealX(edge, ex1, ex2); 01645 Position_GetRealO(edge, eo1, eo2); 01646 01647 long nx1, nx2, no1, no2; 01648 Position_GetRealX(next, nx1, nx2); 01649 Position_GetRealO(next, no1, no2); 01650 01651 int c1, c2; 01652 01653 if( (nx1 < ex1 && ex1 < nx2 && eo1 > 0 ) || (ex1 < nx1 && nx1 < ex2 && no1 < 0) ) 01654 c1 = +1; 01655 else if( ex1 == nx1 && eo1 == 0 && no1 == 0 ) 01656 c1 = 0; 01657 else 01658 c1 = -9; 01659 01660 if( (nx1 < ex2 && ex2 < nx2 && eo2 > 0 ) || (ex1 < nx2 && nx2 < ex2 && no2 < 0) ) 01661 c2 = +1; 01662 else if( ex2 == nx2 && eo2 == 0 && no2 == 0 ) 01663 c2 = 0; 01664 else 01665 c2 = -9; 01666 01667 return (c1 + c2) > 0; 01668 } 01669 01670 // --- Block 01671 01672 #define FLT_EQU(A,B) (((A) - 0.1F < (B)) && ((B) < (A) + 0.1F)) 01673 01674 #define S EDLS_S 01675 #define R EDLS_R 01676 #define D EDLS_D 01677 01678 inline float Block_GetF(float d, int b, int s) 01679 { 01680 float f = d/(b+s); 01681 01682 if( b == 0 && R <= f ) 01683 f += (D-R); 01684 else if( S < f && s > 0 ) 01685 f = ((D-S)*d - S*(D-R)*s) / ((D-S)*b + (R-S)*s); 01686 01687 return f; 01688 } 01689 01690 inline float Block_GetG(float d, int b, int s) 01691 { 01692 float g = d/(b+s); 01693 01694 if( S < g && b > 0 ) 01695 g = ((R-S)*d + S*(D-R)*b) / ((D-S)*b + (R-S)*s); 01696 01697 return g; 01698 } 01699 01700 #undef S 01701 #undef R 01702 #undef D 01703 01704 bool CAutoRouterEdgeList::Block_PushBackward(CAutoRouterEdge* blocked, CAutoRouterEdge* blocker) 01705 { 01706 bool modified = false; 01707 01708 ASSERT( blocked != NULL && blocker != NULL ); 01709 ASSERT( blocked->GetPositionY() <= blocker->GetPositionY() ); 01710 ASSERT( blocked->GetBlockPrev() != NULL ); 01711 01712 float f = 0; 01713 float g = 0; 01714 01715 CAutoRouterEdge* edge = blocked; 01716 CAutoRouterEdge* trace = blocker; 01717 01718 float d = trace->GetPositionY() - edge->GetPositionY(); 01719 ASSERT( d >= 0 ); 01720 01721 int s = (edge->GetBracketOpening() || trace->GetBracketClosing()); 01722 int b = 1 - s; 01723 01724 for(;;) 01725 { 01726 edge->SetBlockTrace(trace); 01727 trace = edge; 01728 edge = edge->GetBlockPrev(); 01729 01730 if( edge == NULL ) 01731 break; 01732 01733 float d2 = trace->GetPositionY() - edge->GetPositionY(); 01734 ASSERT( d2 >= 0 ); 01735 01736 if( edge->GetBracketOpening() || trace->GetBracketClosing() ) 01737 { 01738 g = Block_GetG(d,b,s); 01739 if( d2 <= g ) 01740 { 01741 f = Block_GetF(d,b,s); 01742 break; 01743 } 01744 s++; 01745 } 01746 else 01747 { 01748 f = Block_GetF(d,b,s); 01749 if( d2 <= f ) 01750 { 01751 g = Block_GetG(d,b,s); 01752 break; 01753 } 01754 b++; 01755 } 01756 01757 d += d2; 01758 } 01759 01760 if( b+s > 1 ) 01761 { 01762 if( edge == NULL ) 01763 { 01764 f = Block_GetF(d,b,s); 01765 g = Block_GetG(d,b,s); 01766 } 01767 01768 ASSERT( FLT_EQU(d, f*b + g*s) ); 01769 01770 edge = trace; 01771 ASSERT( edge != NULL && edge != blocked ); 01772 01773 float y = edge->GetPositionY(); 01774 01775 do 01776 { 01777 ASSERT( edge != NULL && edge->GetBlockTrace() != NULL ); 01778 trace = edge->GetBlockTrace(); 01779 01780 y += (edge->GetBracketOpening() || trace->GetBracketClosing()) ? g : f; 01781 01782 if( y + 0.001F < trace->GetPositionY() ) 01783 { 01784 modified = true; 01785 if( SlideButNotPassEdges(trace, y) ) 01786 trace->SetBlockPrev(NULL); 01787 } 01788 01789 edge = trace; 01790 } while( edge != blocked ); 01791 #ifdef _DEBUG 01792 y += (edge->GetBracketOpening() || blocker->GetBracketClosing()) ? g : f; 01793 ASSERT( FLT_EQU(y, blocker->GetPositionY()) ); 01794 #endif 01795 } 01796 01797 return modified; 01798 } 01799 01800 bool CAutoRouterEdgeList::Block_PushForward(CAutoRouterEdge* blocked, CAutoRouterEdge* blocker) 01801 { 01802 bool modified = false; 01803 01804 ASSERT( blocked != NULL && blocker != NULL ); 01805 ASSERT( blocked->GetPositionY() >= blocker->GetPositionY() ); 01806 ASSERT( blocked->GetBlockNext() != NULL ); 01807 01808 float f = 0; 01809 float g = 0; 01810 01811 CAutoRouterEdge* edge = blocked; 01812 CAutoRouterEdge* trace = blocker; 01813 01814 float d = edge->GetPositionY() - trace->GetPositionY(); 01815 ASSERT( d >= 0 ); 01816 01817 int s = (trace->GetBracketOpening() || edge->GetBracketClosing()); 01818 int b = 1 - s; 01819 01820 for(;;) 01821 { 01822 edge->SetBlockTrace(trace); 01823 trace = edge; 01824 edge = edge->GetBlockNext(); 01825 01826 if( edge == NULL ) 01827 break; 01828 01829 float d2 = edge->GetPositionY() - trace->GetPositionY(); 01830 ASSERT( d2 >= 0 ); 01831 01832 if( trace->GetBracketOpening() || edge->GetBracketClosing() ) 01833 { 01834 g = Block_GetG(d,b,s); 01835 if( d2 <= g ) 01836 { 01837 f = Block_GetF(d,b,s); 01838 break; 01839 } 01840 s++; 01841 } 01842 else 01843 { 01844 f = Block_GetF(d,b,s); 01845 if( d2 <= f ) 01846 { 01847 g = Block_GetG(d,b,s); 01848 break; 01849 } 01850 b++; 01851 } 01852 01853 d += d2; 01854 } 01855 01856 if( b+s > 1 ) 01857 { 01858 if( edge == NULL ) 01859 { 01860 f = Block_GetF(d,b,s); 01861 g = Block_GetG(d,b,s); 01862 } 01863 01864 ASSERT( FLT_EQU(d, f*b + g*s) ); 01865 01866 edge = trace; 01867 ASSERT( edge != NULL && edge != blocked ); 01868 01869 float y = edge->GetPositionY(); 01870 01871 do 01872 { 01873 ASSERT( edge != NULL && edge->GetBlockTrace() != NULL ); 01874 trace = edge->GetBlockTrace(); 01875 01876 y -= (trace->GetBracketOpening() || edge->GetBracketClosing()) ? g : f; 01877 01878 if( trace->GetPositionY() < y - 0.001F ) 01879 { 01880 modified = true; 01881 if( SlideButNotPassEdges(trace, y) ) 01882 trace->SetBlockNext(NULL); 01883 } 01884 01885 edge = trace; 01886 } while( edge != blocked ); 01887 #ifdef _DEBUG 01888 y -= (blocker->GetBracketOpening() || edge->GetBracketClosing()) ? g : f; 01889 ASSERT( FLT_EQU(y, blocker->GetPositionY()) ); 01890 #endif 01891 } 01892 01893 return modified; 01894 } 01895 01896 bool CAutoRouterEdgeList::Block_ScanForward() 01897 { 01898 #ifdef _DEBUG_DEEP 01899 AssertValidOrder(); 01900 AssertSectionReady(); 01901 AssertValidPositions(); 01902 #endif 01903 01904 PositionAll_LoadX(); 01905 01906 bool modified = false; 01907 01908 Section_Reset(); 01909 CAutoRouterEdge* blocker = order_first; 01910 while( blocker ) 01911 { 01912 CAutoRouterEdge* bmin = NULL; 01913 CAutoRouterEdge* smin = NULL; 01914 float bmin_f = ED_MINCOORD - 1; 01915 float smin_f = ED_MINCOORD - 1; 01916 01917 Section_BeginScan(blocker); 01918 while( Section_HasBlockedEdge() ) 01919 { 01920 if( Section_IsImmediate() ) 01921 { 01922 CAutoRouterEdge* blocked = Section_GetBlockedEdge(); 01923 ASSERT( blocked != NULL ); 01924 01925 if( blocked->GetBlockPrev() != NULL ) 01926 modified |= Block_PushBackward(blocked, blocker); 01927 01928 if( !blocker->GetEdgeFixed() ) 01929 { 01930 if( blocked->GetBracketOpening() || blocker->GetBracketClosing() ) 01931 { 01932 if( smin_f < blocked->GetPositionY() ) 01933 { 01934 smin_f = blocked->GetPositionY(); 01935 smin = blocked; 01936 } 01937 } 01938 else 01939 { 01940 if( bmin_f < blocked->GetPositionY() ) 01941 { 01942 bmin_f = blocked->GetPositionY(); 01943 bmin = blocked; 01944 } 01945 } 01946 } 01947 } 01948 } 01949 01950 if( bmin ) 01951 { 01952 if( smin ) 01953 { 01954 blocker->SetClosestPrev(smin_f > bmin_f ? smin : bmin); 01955 01956 bmin_f = blocker->GetPositionY() - bmin_f; 01957 smin_f = Block_GetF(blocker->GetPositionY() - smin_f, 0, 1); 01958 01959 blocker->SetBlockPrev(smin_f < bmin_f ? smin : bmin); 01960 } 01961 else 01962 { 01963 blocker->SetBlockPrev(bmin); 01964 blocker->SetClosestPrev(bmin); 01965 } 01966 } 01967 else 01968 { 01969 blocker->SetBlockPrev(smin); 01970 blocker->SetClosestPrev(smin); 01971 } 01972 01973 #ifdef _DEBUG 01974 if( !blocker->GetEdgeFixed() ) 01975 { 01976 CAutoRouterPath* ownerPath = static_cast<CAutoRouterPath*>(blocker->GetOwner()); 01977 if (ownerPath->IsHighLighted()) 01978 { 01979 ASSERT(false); 01980 break; 01981 } 01982 } 01983 #endif 01984 01985 blocker = blocker->GetOrderNext(); 01986 } 01987 01988 PositionAll_StoreY(); 01989 01990 #ifdef _DEBUG_DEEP 01991 AssertValidOrder(); 01992 AssertSectionReady(); 01993 AssertValidPositions(); 01994 #endif 01995 01996 return modified; 01997 } 01998 01999 bool CAutoRouterEdgeList::Block_ScanBackward() 02000 { 02001 #ifdef _DEBUG_DEEP 02002 AssertValidOrder(); 02003 AssertSectionReady(); 02004 AssertValidPositions(); 02005 #endif 02006 02007 PositionAll_LoadX(); 02008 02009 bool modified = false; 02010 02011 Section_Reset(); 02012 CAutoRouterEdge* blocker = order_last; 02013 while( blocker ) 02014 { 02015 CAutoRouterEdge* bmin = NULL; 02016 CAutoRouterEdge* smin = NULL; 02017 float bmin_f = ED_MAXCOORD + 1; 02018 float smin_f = ED_MAXCOORD + 1; 02019 02020 Section_BeginScan(blocker); 02021 while( Section_HasBlockedEdge() ) 02022 { 02023 if( Section_IsImmediate() ) 02024 { 02025 CAutoRouterEdge* blocked = Section_GetBlockedEdge(); 02026 ASSERT( blocked != NULL ); 02027 02028 if( blocked->GetBlockNext() != NULL ) 02029 modified |= Block_PushForward(blocked, blocker); 02030 02031 if( !blocker->GetEdgeFixed() ) 02032 { 02033 if( blocker->GetBracketOpening() || blocked->GetBracketClosing() ) 02034 { 02035 if( smin_f > blocked->GetPositionY() ) 02036 { 02037 smin_f = blocked->GetPositionY(); 02038 smin = blocked; 02039 } 02040 } 02041 else 02042 { 02043 if( bmin_f > blocked->GetPositionY() ) 02044 { 02045 bmin_f = blocked->GetPositionY(); 02046 bmin = blocked; 02047 } 02048 } 02049 } 02050 } 02051 } 02052 02053 if( bmin ) 02054 { 02055 if( smin ) 02056 { 02057 blocker->SetClosestNext(smin_f < bmin_f ? smin : bmin); 02058 02059 bmin_f = bmin_f - blocker->GetPositionY(); 02060 smin_f = Block_GetF(smin_f - blocker->GetPositionY(), 0, 1); 02061 02062 blocker->SetBlockNext(smin_f < bmin_f ? smin : bmin); 02063 } 02064 else 02065 { 02066 blocker->SetBlockNext(bmin); 02067 blocker->SetClosestNext(bmin); 02068 } 02069 } 02070 else 02071 { 02072 blocker->SetBlockNext(smin); 02073 blocker->SetClosestNext(smin); 02074 } 02075 02076 #ifdef _DEBUG 02077 if( !blocker->GetEdgeFixed() ) 02078 { 02079 CAutoRouterPath* ownerPath = static_cast<CAutoRouterPath*>(blocker->GetOwner()); 02080 if (ownerPath->IsHighLighted()) 02081 { 02082 ASSERT(false); 02083 break; 02084 } 02085 } 02086 #endif 02087 02088 blocker = blocker->GetOrderPrev(); 02089 } 02090 02091 PositionAll_StoreY(); 02092 02093 #ifdef _DEBUG_DEEP 02094 AssertValidOrder(); 02095 AssertSectionReady(); 02096 AssertValidPositions(); 02097 #endif 02098 02099 return modified; 02100 } 02101 02102 bool CAutoRouterEdgeList::Block_SwitchWrongs() 02103 { 02104 bool was = false; 02105 02106 PositionAll_LoadX(); 02107 02108 CAutoRouterEdge* second = order_first; 02109 while( second != NULL ) 02110 { 02111 if( second->GetClosestPrev() != NULL && second->GetClosestPrev()->GetClosestNext() != second && 02112 second->GetClosestNext() != NULL && second->GetClosestNext()->GetClosestPrev() == second ) 02113 02114 { 02115 ASSERT( !second->GetEdgeFixed() ); 02116 02117 CAutoRouterEdge* edge = second; 02118 CAutoRouterEdge* next = edge->GetClosestNext(); 02119 02120 while( next != NULL && edge == next->GetClosestPrev() ) 02121 { 02122 ASSERT( edge != NULL && !edge->GetEdgeFixed() ); 02123 ASSERT( next != NULL && !next->GetEdgeFixed() ); 02124 02125 float ey = edge->GetPositionY(); 02126 float ny = next->GetPositionY(); 02127 02128 ASSERT( ey <= ny ); 02129 02130 if( ey + 1 <= ny && Bracket_ShouldBeSwitched(edge, next) ) 02131 { 02132 was = true; 02133 02134 ASSERT( !edge->GetEdgeCanpassed() && !next->GetEdgeCanpassed() ); 02135 edge->SetEdgeCanpassed(true); 02136 next->SetEdgeCanpassed(true); 02137 02138 int a = SlideButNotPassEdges(edge, (ny+ey)/2 + 0.001F) != NULL; 02139 a |= SlideButNotPassEdges(next, (ny+ey)/2 - 0.001F) != NULL; 02140 02141 if( a ) 02142 { 02143 edge->SetClosestPrev(NULL); 02144 edge->SetClosestNext(NULL); 02145 next->SetClosestPrev(NULL); 02146 next->SetClosestNext(NULL); 02147 02148 edge->SetEdgeCanpassed(false); 02149 next->SetEdgeCanpassed(false); 02150 break; 02151 } 02152 02153 if( edge->GetClosestPrev() != NULL && edge->GetClosestPrev()->GetClosestNext() == edge ) 02154 edge->GetClosestPrev()->SetClosestNext(next); 02155 02156 if( next->GetClosestNext() != NULL && next->GetClosestNext()->GetClosestPrev() == next) 02157 next->GetClosestNext()->SetClosestPrev(edge); 02158 02159 edge->SetClosestNext(next->GetClosestNext()); 02160 next->SetClosestNext(edge); 02161 next->SetClosestPrev(edge->GetClosestPrev()); 02162 edge->SetClosestPrev(next); 02163 02164 edge->SetEdgeCanpassed(false); 02165 next->SetEdgeCanpassed(false); 02166 02167 ASSERT( !Bracket_ShouldBeSwitched(next, edge) ); 02168 02169 if( next->GetClosestPrev() != NULL && next->GetClosestPrev()->GetClosestNext() == next ) 02170 edge = next->GetClosestPrev(); 02171 else 02172 next = edge->GetClosestNext(); 02173 } 02174 else 02175 { 02176 edge = next; 02177 next = next->GetClosestNext(); 02178 } 02179 } 02180 } 02181 02182 second = second->GetOrderNext(); 02183 } 02184 02185 if( was ) 02186 PositionAll_StoreY(); 02187 02188 return was; 02189 } 02190