GME  13
AutoRouterEdge.cpp
Go to the documentation of this file.
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 &section_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 &section_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 = &section_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