61 auto vold =
static_cast<VIA*
>( aOld );
62 auto vnew =
static_cast<VIA*
>( aNew.get() );
65 newId =
static_cast<VIA*
>( aNew.get() )->Uid();
68 wxString::Format(
"replace-via node=%p vold=%p [%d %d]-> vnew=%p [%d %d] nid %llu",
m_currentNode, aOld,
69 vold->Pos().x, vold->Pos().y, aNew.get(), vnew->Pos().x,
70 vnew->Pos().y, newId ) );
82 if( aIncludeInChangedArea )
89 PNS_DBG(
Dbg(), AddShape, &r,
BLUE, 0, wxT(
"shove-changed-area" ) );
101 for(
auto lnk : aOld.
Links() )
107 bool foundPredecessor =
false;
123 rootEntry = oldLineIter->second;
124 foundPredecessor =
true;
130 if( !foundPredecessor )
233 const LINE& aShovedLine )
const
257 int obstacleLineWidth = aObstacleLine.
Width();
261 int holeClearance =
getClearance( viaHole, &aObstacleLine );
263 if( holeClearance +
via.Drill() / 2 > clearance +
via.Diameter( aObstacleLine.
Layer() ) / 2 )
264 clearance = holeClearance +
via.Drill() / 2 -
via.Diameter( aObstacleLine.
Layer() ) / 2;
270 if( ! aObstacleLine.
Walkaround( hull, path_cw,
true ) )
273 if( ! aObstacleLine.
Walkaround( hull, path_ccw,
false ) )
281 if( aObstacleLine.
CPoint( -1 ) != shortest.
CPoint( -1 ) )
306 PNS_DBG(
Dbg(), BeginGroup,
"shove-details", 1 );
308 for( attempt = 0; attempt < 4; attempt++ )
310 bool invertTraversal = ( attempt >= 2 );
311 bool clockwise = attempt % 2;
312 int vFirst = -1, vLast = -1;
314 LINE l( aObstacleLine );
317 for(
int i = 0; i < (int) aHulls.size(); i++ )
319 const SHAPE_LINE_CHAIN& hull = aHulls[invertTraversal ? aHulls.size() - 1 - i : i];
321 PNS_DBG(
Dbg(), AddShape, &hull,
YELLOW, 10000, wxString::Format(
"hull[%d]", i ) );
327 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"Fail-Walk %s %s %d\n" ),
340 for(
int i = 0; i < std::min(
path.PointCount(), obs.
PointCount() ); i++ )
351 for(
int i =
path.PointCount() - 1; i >= 0 && k >= 0; i--, k-- )
360 if( ( vFirst < 0 || vLast < 0 ) && !
path.CompareGeometry( aObstacleLine.
CLine() ) )
362 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"attempt %d fail vfirst-last" ),
369 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"attempt %d fail vend-start\n" ),
376 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"attempt %d fail direction-check" ),
382 if(
path.SelfIntersecting() )
384 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"attempt %d fail self-intersect" ),
406 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"attempt %d fail coll-check" ),
431 const int cHullFailureExpansionFactor = 10;
432 int extraHullExpansion = 0;
438 LINE obstacleLine( aObstacleLine );
439 std::optional<VIA> obsVia;
443 obsVia = aObstacleLine.
Via();
447 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"shove process-single: voe-cur %d voe-obs %d" ),
462 int obstacleLineWidth = obstacleLine.
Width();
463 int clearance =
getClearance( &aCurLine, &obstacleLine );
471 for(
int attempt = 0; attempt < 2; attempt++ )
475 hulls.reserve( currentLineSegmentCount + 1 );
477 for(
int i = 0; i < currentLineSegmentCount; i++ )
484 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"shove add-extra-clearance %d" ),
491 hulls.push_back( hull );
499 int holeClearance =
getClearance( viaHole, &obstacleLine );
500 int layer = aObstacleLine.
Layer();
502 if( holeClearance +
via.Drill() / 2 > viaClearance +
via.Diameter( layer ) / 2 )
504 viaClearance = holeClearance +
via.Drill() / 2 -
via.Diameter( layer ) / 2;
507 hulls.push_back( aCurLine.
Via().
Hull( viaClearance, obstacleLineWidth, layer ) );
518 extraHullExpansion += cHullFailureExpansionFactor;
534 LINE shovedLine( obstacleLine );
539 PNS_DBG(
Dbg(), Message,
"try walk (locked segments)");
545 const double extensionWalkThreshold = 1.0;
549 double extensionFactor = 0.0;
552 extensionFactor = shovedLen / obsLen - 1.0;
561 PNS_DBG(
Dbg(), AddItem, aObstacleSeg,
BLUE, 0, wxT(
"colliding-segment" ) );
563 PNS_DBG(
Dbg(), AddItem, &obstacleLine,
GREEN, 10000, wxString::Format(
"obstacle-line [l %d v %d]", obstacleLine.
Layer(), obstacleLine.
EndsWithVia() ) );
564 PNS_DBG(
Dbg(), AddItem, &shovedLine,
BLUE, 10000, wxT(
"shoved-line" ) );
569 int rank = aCurrent.
Rank();
570 shovedLine.
SetRank( rank - 1 );
592 LINE shovedLine( obstacleLine );
593 ARC tmp( *aObstacleArc );
600 const double extensionWalkThreshold = 1.0;
604 double extensionFactor = 0.0;
607 extensionFactor = shovedLen / obsLen - 1.0;
609 if( extensionFactor > extensionWalkThreshold )
615 PNS_DBG(
Dbg(), AddItem, &aCurrent,
RED, 10000, wxT(
"current-line" ) );
616 PNS_DBG(
Dbg(), AddItem, &obstacleLine,
GREEN, 10000, wxT(
"obstacle-line" ) );
617 PNS_DBG(
Dbg(), AddItem, &shovedLine,
BLUE, 10000, wxT(
"shoved-line" ) );
621 int rank = aCurrent.
Rank();
622 shovedLine.
SetRank( rank - 1 );
640 LINE shovedLine( aObstacle );
644 PNS_DBG(
Dbg(), AddItem, &aObstacle,
RED, 100000, wxT(
"obstacle-line" ) );
645 PNS_DBG(
Dbg(), AddItem, &aCurrent,
GREEN, 150000, wxT(
"current-line" ) );
646 PNS_DBG(
Dbg(), AddItem, &shovedLine,
BLUE, 200000, wxT(
"shoved-line" ) );
656 m_newHead = shovedLine;
662 shovedLine.
SetRank( aNextRank );
677 LINE walkaroundLine( aCurrent );
705 PNS_DBG(
Dbg(), BeginGroup,
"walk-cluster", 1 );
708 PNS_DBG(
Dbg(), AddItem, item,
RED, 10000, wxT(
"cl-item" ) );
719 int currentRank = aCurrent.
Rank();
722 bool success =
false;
724 PNS_DBG(
Dbg(), AddItem, &aCurrent,
RED, 10000, wxT(
"current-line" ) );
726 for(
int attempt = 0; attempt < 2; attempt++ )
728 if( attempt == 1 ||
Settings().JumpOverObstacles() )
729 nextRank = currentRank - 1;
731 nextRank = currentRank + 10000;
747 PNS_DBG(
Dbg(), AddItem, &walkaroundLine,
BLUE, 10000, wxT(
"walk-line" ) );
757 m_newHead = walkaroundLine;
789 walkaroundLine.
SetRank( nextRank );
803 PNS_DBG(
Dbg(), Message, wxString::Format(
"prune called" ) );
808 for(
const auto item : added )
812 auto litem =
static_cast<const LINKED_ITEM*
>( item );
867 wxString::Format(
"restore-springback-via depth=%d %d %d %d %d ",
903 wxString::Format(
"push-sp via depth=%d %d %d %d %d ", aNode->
Depth(), vhandle.
pos.
x,
950 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"via force [%d %d]\n" ), aForce.
x, aForce.
y ) );
953 if ( aForce.
x == 0 && aForce.
y == 0 )
958 PNS_DBG(
Dbg(), Message, wxT(
"weird, can't find the center-of-via joint\n" ) );
976 p0_pushed += aForce.
Resize( 2 );
979 std::unique_ptr<VIA> pushedVia =
Clone( *aVia );
980 pushedVia->SetPos( p0_pushed );
981 pushedVia->Mark( aVia->
Marker() );
993 if( lp.first.HasLockedSegments() )
996 assert( segIndex == 0 || ( segIndex == ( lp.first.SegmentCount() - 1 ) ) );
1001 lp.second = lp.first;
1002 lp.second.ClearLinks();
1003 lp.second.DragCorner( p0_pushed, lp.second.CLine().Find( p0 ) );
1004 lp.second.Line().Simplify2();
1005 draggedLines.push_back( lp );
1009 pushedVia->SetRank( aNewRank );
1010 PNS_DBG(
Dbg(), Message, wxString::Format(
"via rank %d, fanout %d\n", pushedVia->Rank(), (
int) draggedLines.size() ) );
1015 VIA *
v2 = pushedVia.get();
1020 if( draggedLines.empty() )
1033 PNS_DBG(
Dbg(), Message, wxString::Format(
"fan %d/%d\n", n, (
int) draggedLines.size() ) );
1036 if( lp.second.SegmentCount() )
1038 lp.second.ClearLinks();
1041 lp.second.LinkVia(
v2 );
1044 lp.second.SetRank( aNewRank );
1047 rootEntry->
newLine = lp.second;
1050 PNS_DBG(
Dbg(), Message, wxString::Format(
"PushViaF %p %d eov %d\n", &lp.second, lp.second.SegmentCount(), lp.second.EndsWithVia()?1:0 ) );
1074 assert( aObstacleVia );
1076 int clearance =
getClearance( aCurrent, aObstacleVia );
1080 bool lineCollision =
false;
1081 bool viaCollision =
false;
1082 bool solidCollision =
false;
1083 VECTOR2I mtvLine, mtvVia, mtvSolid;
1085 PNS_DBG(
Dbg(), BeginGroup,
"push-via-by-line", 1 );
1089 VIA vtmp ( *aObstacleVia );
1090 int layer = aCurrent->
Layer();
1098 LINE* currentLine = (
LINE*) aCurrent;
1110 clearance + currentLine->
Width() / 2,
1116 const VIA& currentVia = currentLine->
Via();
1133 PNS_DBG(
Dbg(), Message, wxT(
"collidee-is-solid" ) );
1135 solidCollision = aCurrent->
Shape( -1 )->
Collide( aObstacleVia->
Shape( -1 ), clearance,
1146 else if ( lineCollision )
1148 else if ( solidCollision )
1154 PNS_DBG(
Dbg(), Message, wxString::Format(
"push-or-shove-via st %d", st ) );
1171 auto p0 = aCurrent.
Via().
Pos();
1172 auto p1 = aObstacleVia->
Pos();
1174 int layer = aCurrent.
Layer();
1175 int dist = (p0 - p1).EuclideanNorm() - aCurrent.
Via().
Diameter( layer ) / 2
1176 - aObstacleVia->
Diameter( layer ) / 2;
1185 PNS_DBG(
Dbg(), Message, wxString::Format(
"via2via coll check dist %d cl %d delta %d pi %d\n", dist, clearance, dist - clearance, epInsideHull ? 1 : 0) );
1187 bool viaCollision =
false;
1198 return onCollidingVia( &aCurrent, aObstacleVia, aObstacleInfo, aCurrent.
Rank() - 1 );
1202 LINE cur( aCurrent );
1206 LINE shoved( aCurrent );
1252 LINE head( aCurrent );
1270 PNS_DBG(
Dbg(), AddItem, &aCurrent,
BLUE, 0, wxT(
"rr-current-line" ) );
1271 PNS_DBG(
Dbg(), AddItem, &shoved,
GREEN, 0, wxT(
"rr-shoved-line" ) );
1274 int currentRank = aCurrent.
Rank();
1280 shoved.
SetRank( currentRank );
1292 if( i->ContainsLink( aSeg ) )
1294 PNS_DBG(
Dbg(), Message, wxString::Format(
"Unwind lc %d (depth %d/%d)", i->SegmentCount(), d, (
int)
m_lineStack.size() ) );
1307 if( i->ContainsLink( aSeg ) )
1323 const LINE* l =
static_cast<const LINE*
>( aItem );
1335 PNS_DBG(
Dbg(), AddItem, &aL,
BLUE, 10000, wxT(
"push line stack failed" ) );
1365 if( i->ContainsLink( s ) )
1383 int layer = aCurrent->
Layer();
1399 for(
ITEM* link : links )
1404 maxw = std::max( seg->
Width(), maxw );
1408 const ARC* arc =
static_cast<const ARC*
>( link );
1409 maxw = std::max( arc->
Width(), maxw );
1415 if( maxw > 0 && maxw >= v->
Diameter( layer ) )
1419 wxString::Format(
"Fixup via: new-w %d via-w %d", maxw, v->
Diameter( layer ) ) );
1432 int sl = s->
Layer();
1439 for(
int i = 0; i < 2; i++ )
1478 wxString::Format( wxT(
"current sc=%d net=%s evia=%d" ),
1480 iface->GetNetName( currentLine.
Net() ),
1493 auto litem =
static_cast<const LINKED_ITEM*
>( item );
1516 wxString::Format(
"nearest %p %s rank %d",
1518 nearest->m_item->KindStr(),
1519 nearest->m_item->Rank() ) );
1529 PNS_DBG(
Dbg(), Message, wxT(
"no-nearest-item ") );
1535 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"iter %d: via-fixup %d" ), aIter, viaFixup?1:0 ) );
1538 ITEM* ni = nearest->m_item;
1541 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"NI: %s (%s) %p %d" ),
1545 : wxString( wxT(
"null" ) ),
1555 switch( ni->
Kind() )
1559 PNS_DBG(
Dbg(), BeginGroup, wxString::Format( wxT(
"iter %d: reverse-collide-via" ), aIter ), 0 );
1564 nearest->m_item->Layer() ) )
1566 PNS_DBG(
Dbg(), AddItem, nearest->m_item,
YELLOW, 100000, wxT(
"v2v nearesti" ) );
1585 PNS_DBG(
Dbg(), BeginGroup, wxString::Format( wxT(
"iter %d: reverse-collide-segment" ),
1626 PNS_DBG(
Dbg(), BeginGroup, wxString::Format( wxT(
"iter %d: reverse-collide-arc " ), aIter ), 0 );
1648 switch( ni->
Kind() )
1651 PNS_DBG(
Dbg(), BeginGroup, wxString::Format( wxT(
"iter %d: collide-segment " ), aIter ), 0 );
1664 PNS_DBG(
Dbg(), BeginGroup, wxString::Format( wxT(
"iter %d: collide-arc " ), aIter ), 0 );
1676 PNS_DBG(
Dbg(), BeginGroup, wxString::Format( wxT(
"iter %d: collide-via (fixup: %d)" ), aIter, 0 ), 0 );
1688 PNS_DBG(
Dbg(), BeginGroup, wxString::Format( wxT(
"iter %d: walk-solid " ), aIter ), 0);
1716 PNS_DBG(
Dbg(), Message, wxString::Format(
"ShoveStart [root: %d jts, current: %d jts]",
1736 PNS_DBG(
Dbg(), Message, wxString::Format(
"iter %d: node %p stack %d ",
m_iter,
1745 PNS_DBG(
Dbg(), Message, wxString::Format(
"Fail [time limit expired: %d iter %d iter limit %d",
1804 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"touch [found] uid=%llu type=%s"), link->Uid(), link->KindStr() ) );
1815 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"touch [create] uid=%llu type=%s"), link->Uid(), link->KindStr() ) );
1830 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"touch [create] uid=%llu"), aItem->
Uid() ) );
1836 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"touch [create] uid=%llu"), aItem->
Uid() ) );
1856 maxWidth = std::max( line.Width(), maxWidth );
1860 area->Inflate( maxWidth );
1910 std::set<const ITEM*> itemsChk;
1916 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"optimize inspect sc %d lc %d net %s"), (
int) l.SegmentCount(), (
int) l.PointCount(), iface->GetNetName( l.Net() ) ) );
1925 for(
int pass = 0; pass < n_passes; pass++ )
1934 LINE* rootLine =
nullptr;
1939 rootLine = rootEntry->rootLine;
1943 if( rootEntry->isHead )
1948 if( optimizer.
Optimize( &lineToOpt, &optimized, rootLine ) )
1954 PNS_DBG(
Dbg(), AddItem, rootLine,
RED, 0, wxT(
"shove-root-opt" ) );
1956 replaceLine( lineToOpt, optimized,
false, aNode );
1994 if ( iter->m_node == aNode )
2040 if ( iter->m_node == aNode )
2042 iter->m_locked =
false;
2072 rl->policy = aPolicy;
2078 rl->policy = aPolicy;
2106 std::vector<PNS::ITEM*> added, removed;
2109 wxString msg = wxString::Format(
"stats[%s]: added=%d, removed=%d, depth=%d", s, (
int) added.size(),
2110 (
int) removed.size(), (
int) node->
Depth() );
2120 if( headEntry.newHead )
2123 int n_lc = headEntry.newHead->LinkCount();
2128 wxString msg = wxString::Format(
2129 "remove newhead [net %-20s]: sc %d lc %d\n",
2130 iface->GetNetName( headEntry.newHead->Net() ).c_str().AsChar(),
2131 headEntry.newHead->SegmentCount(), n_lc );
2134 else if( headEntry.origHead )
2136 wxString msg = wxString::Format(
2137 "remove orighead [net %-20s]: sc %d lc %d node %p depth %d\n",
2138 iface->GetNetName( headEntry.origHead->Net() ).c_str().AsChar(),
2139 headEntry.origHead->SegmentCount(), headEntry.origHead->LinkCount(),
2159 if( headEntry.origHead )
2163 PNS_DBG(
Dbg(), Message, wxString::Format(
"orig LinkC=%d RE=%p", headEntry.origHead->LinkCount(), rootEntry ) );
2165 assert( rootEntry );
2166 assert( rootEntry->rootLine );
2168 if( rootEntry->newLine )
2170 headEntry.newHead = rootEntry->newLine;
2171 headEntry.geometryModified = !rootEntry->newLine->CLine().CompareGeometry( rootEntry->rootLine->CLine() );
2173 wxString msg = wxString::Format(
2174 "head %d/%d [net %-20s]: root %p, lc-root %d, lc-new %d\n", i, (
int)
m_headLines.size(),
2175 iface->GetNetName( rootEntry->rootLine->Net() ).c_str().AsChar(), rootEntry->rootLine, rootEntry->rootLine->LinkCount(), headEntry.newHead->LinkCount() );
2182 wxString msg = wxString::Format(
2183 "head %d/%d [net %-20s]: unmodified, lc-orig %d\n", i, (
int)
m_headLines.size(),
2184 iface->GetNetName( headEntry.origHead->Net() ).c_str().AsChar(),
2185 headEntry.origHead->LinkCount() );
2193 if( rootEntry->newVia )
2195 headEntry.geometryModified =
true;
2196 headEntry.theVia =
VIA_HANDLE( rootEntry->newVia->Pos(), rootEntry->newVia->Layers(), rootEntry->newVia->Net() );
2198 wxString msg = wxString::Format(
"[modif] via orig %p chk %p\n", headEntry.draggedVia, chk );
2201 assert( chk !=
nullptr );
2205 headEntry.theVia =
VIA_HANDLE( rootEntry->oldVia->Pos(), rootEntry->oldVia->Layers(), rootEntry->oldVia->Net() );
2207 wxString msg = wxString::Format(
"[unmodif] via orig %p chk %p\n", headEntry.draggedVia, chk );
2209 assert( chk !=
nullptr );
2237 PNS_DBG(
Dbg(), Message, wxString::Format(
"**** PreshoveCleanup %d -> %d\n", vc_prev, vc_post ) );
2239 if( vc_prev != vc_post )
2256 int currentHeadId = 0;
2271 PNS_DBG(
Dbg(), Message, wxString::Format(
"process head-via [%d %d] node=%p", l.theVia->pos.x, l.theVia->pos.y,
m_currentNode ) );
2273 assert( realVia !=
nullptr );
2274 headSet.
Add( realVia );
2278 headSet.
Add( *l.origHead );
2312 if( headLineEntry.theVia )
2323 viaRoot->oldVia = viaToDrag;
2324 headLineEntry.draggedVia = viaToDrag;
2326 st =
pushOrShoveVia( viaToDrag, ( headLineEntry.viaNewPos - viaToDrag->
Pos() ), 0 );
2334 assert( headLineEntry.origHead->LinkCount() == 0 );
2342 wxString::Format(
"touchRoot ohlc %d roots %d re=%p\n",
2343 headLineEntry.origHead->LinkCount(),
2348 LINE head( *headLineEntry.origHead );
2371 auto headVia =
Clone( head.
Via() );
2372 headVia->SetRank( 100000 );
2373 headLineEntry.origHead->LinkVia( headVia.get() );
2374 head.
LinkVia( headVia.get() );
2379 headRoot->isHead =
true;
2380 headRoot->rootLine =
new PNS::LINE( *headLineEntry.origHead );
2381 headRoot->policy = headLineEntry.policy;
2385 wxString::Format(
"headLC %d, rlLC %d oolc %d eov %d\n", head.
LinkCount(),
2386 headRoot->rootLine->LinkCount(),
2387 headLineEntry.origHead->LinkCount(),
2393 wxString::Format(
"Shove heads %d/%d h-lc=%d net=%s Line=%d Policy=%s",
2394 currentHeadId, totalHeads, head.
LinkCount(),
2395 iface->GetNetName( head.
Net() ), headRoot->newLine ? 1 : 0,
2397 : wxString( wxT(
"default[ne]" ) ) ) );
2418 wxString::Format(
"Shove status : %s after %d iterations, heads: %d",
2439 if( headEntry.prevVia )
2443 wxString::Format(
"Fail-restore via mod [%d, %d] orig [%d, %d]",
2444 headEntry.theVia->pos.x,
2445 headEntry.theVia->pos.y,
2446 headEntry.prevVia->pos.x,
2447 headEntry.prevVia->pos.y ) );
2449 headEntry.theVia = headEntry.prevVia;
2450 headEntry.geometryModified =
true;
2482 rv.Append(
"shove ");
2484 rv.Append(
"walk-forward ");
2486 rv.Append(
"walk-back ");
2488 rv.Append(
"ignore ");
2490 rv.Append(
"dont-optimize ");
constexpr EDA_IU_SCALE pcbIUScale
std::optional< BOX2I > OPT_BOX2I
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
@ ROUNDED_45
H/V/45 with filleted corners.
@ MITERED_45
H/V/45 with mitered corners (default)
virtual wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const
Return a user-visible description string of this item.
Base class for all P&S algorithms (shoving, walkaround, line placement, dragging, etc....
const BOX2I & VisibleViewArea() const
void SetDebugDecorator(DEBUG_DECORATOR *aDecorator)
Assign a debug decorator allowing this algo to draw extra graphics for visual debugging.
ROUTER * Router() const
Return current router settings.
ROUTING_SETTINGS & Settings() const
Return the logger object, allowing to dump geometry to a file.
DEBUG_DECORATOR * Dbg() const
int Width() const override
virtual void SetIteration(int iter)
void Add(const LINE &aLine)
Base class for PNS router board items.
BOARD_ITEM * Parent() const
virtual const std::string Format() const
virtual const SHAPE * Shape(int aLayer) const
Return the geometrical shape of the item.
const PNS_LAYER_RANGE & Layers() const
virtual NET_HANDLE Net() const
PnsKind Kind() const
Return the type (kind) of the item.
std::set< int > RelevantShapeLayers(const ITEM *aOther) const
Returns the set of layers on which either this or the other item can have a unique shape.
virtual int Layer() const
PnsKind
< Supported item types
bool Collide(const ITEM *aHead, const NODE *aNode, int aLayer, COLLISION_SEARCH_CONTEXT *aCtx=nullptr) const
Check for a collision (clearance violation) with between us and item aOther.
virtual const NODE * OwningNode() const
bool OfKind(int aKindMask) const
bool LayersOverlap(const ITEM *aOther) const
Return true if the set of layers spanned by aOther overlaps our layers.
virtual HOLE * Hole() const
virtual bool HasHole() const
virtual int Marker() const
A 2D point on a given set of layers and belonging to a certain net, that links together a number of b...
const std::vector< ITEM * > & LinkList() const
const ITEM_SET & CLinks() const
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
const VECTOR2I & CPoint(int aIdx) const
bool HasLockedSegments() const
int Rank() const override
void SetShape(const SHAPE_LINE_CHAIN &aLine)
Return the shape of the line.
virtual void Mark(int aMarker) const override
const SHAPE_LINE_CHAIN & CLine() const
void SetRank(int aRank) override
SHAPE_LINE_CHAIN & Line()
const SHAPE * Shape(int aLayer) const override
Modifiable accessor to the underlying shape.
virtual int Marker() const override
void AppendVia(const VIA &aVia)
virtual void Unmark(int aMarker=-1) const override
bool Walkaround(SHAPE_LINE_CHAIN aObstacle, SHAPE_LINE_CHAIN &aPre, SHAPE_LINE_CHAIN &aWalk, SHAPE_LINE_CHAIN &aPost, bool aCw) const
Calculate a line tightly wrapping a convex hull of an obstacle object (aObstacle).
const SEG CSegment(int aIdx) const
Set line width.
virtual LINE * Clone() const override
Return a deep copy of the item.
int Width() const
Return true if the line is geometrically identical as line aOther.
void Unlink(const LINKED_ITEM *aLink)
Return the list of links from the owning node that constitute this line (or NULL if the line is not l...
bool IsLinked() const
Check if the segment aLink is a part of the line.
std::vector< LINKED_ITEM * > & Links()
virtual void ClearLinks()
Return the number of segments that were assembled together to form this line.
Keep the router "world" - i.e.
NODE * Branch()
Create a lightweight copy (called branch) of self that tracks the changes (added/removed items) wrs t...
std::vector< ITEM * > ITEM_VECTOR
int GetClearance(const ITEM *aA, const ITEM *aB, bool aUseClearanceEpsilon=true) const
Return the pre-set worst case clearance between any pair of items.
void Replace(ITEM *aOldItem, std::unique_ptr< ITEM > aNewItem)
Replace an item with another one.
void GetUpdatedItems(ITEM_VECTOR &aRemoved, ITEM_VECTOR &aAdded)
Return the list of items removed and added in this branch with respect to the root branch.
OPT_OBSTACLE CheckColliding(const ITEM *aItem, int aKindMask=ITEM::ANY_T)
Check if the item collides with anything else in the world, and if found, returns the obstacle.
const JOINT * FindJoint(const VECTOR2I &aPos, int aLayer, NET_HANDLE aNet) const
Search for a joint at a given position, layer and belonging to given net.
std::optional< OBSTACLE > OPT_OBSTACLE
bool Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Add an item to the current node.
OPT_OBSTACLE NearestObstacle(const LINE *aLine, const COLLISION_SEARCH_OPTIONS &aOpts=COLLISION_SEARCH_OPTIONS())
Follow the line in search of an obstacle that is nearest to the starting to the line's starting point...
void LockJoint(const VECTOR2I &aPos, const ITEM *aItem, bool aLock)
int JointCount() const
Return the number of nodes in the inheritance chain (wrs to the root node).
VIA * FindViaByHandle(const VIA_HANDLE &handle) const
void ClearRanks(int aMarkerMask=MK_HEAD|MK_VIOLATION)
void Remove(ARC *aArc)
Remove an item from this branch.
const LINE AssembleLine(LINKED_ITEM *aSeg, int *aOriginSegmentIndex=nullptr, bool aStopAtLockedJoints=false, bool aFollowLockedSegments=false)
Follow the joint map to assemble a line connecting two non-trivial joints starting from segment aSeg.
Perform various optimizations of the lines being routed, attempting to make the lines shorter and les...
static bool Optimize(const LINE *aLine, int aEffortLevel, NODE *aWorld, const VECTOR2I &aV=VECTOR2I(0, 0))
void SetRestrictArea(const BOX2I &aArea, bool aStrict=true)
void SetCollisionMask(int aMask)
void SetEffortLevel(int aEffort)
@ LIMIT_CORNER_COUNT
Do not attempt to optimize if the resulting line's corner count is outside the predefined range.
@ SMART_PADS
Reroute pad exits.
@ MERGE_SEGMENTS
Reduce corner cost iteratively.
@ MERGE_OBTUSE
Reduce corner cost by merging obtuse segments.
virtual DEBUG_DECORATOR * GetDebugDecorator()=0
ROUTER_IFACE * GetInterface() const
TIME_LIMIT ShoveTimeLimit() const
PNS_OPTIMIZATION_EFFORT OptimizerEffort() const
Set the optimizer effort. Bigger means cleaner traces, but slower routing.
int ShoveIterationLimit() const
DIRECTION_45::CORNER_MODE GetCornerMode() const
int Width() const override
const SHAPE_LINE_CHAIN Hull(int aClearance, int aWalkaroundThickness, int aLayer=-1) const override
void SetSpringbackDoNotTouchNode(const NODE *aNode)
SHOVE_STATUS shoveIteration(int aIter)
SHOVE_STATUS shoveMainLoop()
std::vector< SHAPE_LINE_CHAIN > HULL_SET
void reconstructHeads(bool aShoveFailed)
std::pair< LINE, LINE > LINE_PAIR
SHOVE_STATUS onReverseCollidingVia(LINE &aCurrent, VIA *aObstacleVia, OBSTACLE &aObstacleInfo)
std::vector< LINE > m_lineStack
ROOT_LINE_ENTRY * findRootLine(const LINE &aLine)
std::vector< SPRINGBACK_TAG > m_nodeStack
SHOVE_STATUS onCollidingArc(LINE &aCurrent, ARC *aObstacleArc)
LINE assembleLine(const LINKED_ITEM *aSeg, int *aIndex=nullptr, bool aPreCleanup=false)
bool checkShoveDirection(const LINE &aCurLine, const LINE &aObstacleLine, const LINE &aShovedLine) const
SHOVE_STATUS onCollidingSegment(LINE &aCurrent, SEGMENT *aObstacleSeg)
SHOVE(NODE *aWorld, ROUTER *aRouter)
void DisablePostShoveOptimizations(int aMask)
bool RewindSpringbackTo(NODE *aNode)
bool pushLineStack(const LINE &aL, bool aKeepCurrentOnTop=false)
OPT_BOX2I totalAffectedArea() const
bool RewindToLastLockedNode()
std::deque< HEAD_LINE_ENTRY > m_headLines
const wxString formatPolicy(int aPolicy)
bool ShoveObstacleLine(const LINE &aCurLine, const LINE &aObstacleLine, LINE &aResultLine)
SHOVE_STATUS onCollidingVia(ITEM *aCurrent, VIA *aObstacleVia, OBSTACLE &aObstacleInfo, int aNextRank)
void sanityCheck(LINE *aOld, LINE *aNew)
int m_restrictSpringbackTagId
void runOptimizer(NODE *aNode)
ROOT_LINE_ENTRY * touchRootLine(const LINE &aLine)
const PNS::LINE GetModifiedHead(int aIndex) const
bool HeadsModified(int aIndex=-1) const
bool shoveLineToHullSet(const LINE &aCurLine, const LINE &aObstacleLine, LINE &aResultLine, const HULL_SET &aHulls)
void UnlockSpringbackNode(NODE *aNode)
NODE * reduceSpringback(const ITEM_SET &aHeadSet)
bool AddLockedSpringbackNode(NODE *aNode)
void SetDefaultShovePolicy(int aPolicy)
void AddHeads(const LINE &aHead, int aPolicy=SHP_DEFAULT)
void SetShovePolicy(const LINKED_ITEM *aItem, int aPolicy)
void unwindLineStack(const LINKED_ITEM *aSeg)
bool preShoveCleanup(LINE *aOld, LINE *aNew)
int getClearance(const ITEM *aA, const ITEM *aB) const
std::vector< LINE > m_optimizerQueue
ROOT_LINE_ENTRY * replaceLine(LINE &aOld, LINE &aNew, bool aIncludeInChangedArea=true, NODE *aNode=nullptr)
SHOVE_STATUS onCollidingSolid(LINE &aCurrent, ITEM *aObstacle, OBSTACLE &aObstacleInfo)
bool pushSpringback(NODE *aNode, const OPT_BOX2I &aAffectedArea)
SHOVE_STATUS onCollidingLine(LINE &aCurrent, LINE &aObstacle, int aNextRank)
bool fixupViaCollisions(const LINE *aCurrent, OBSTACLE &obs)
void replaceItems(ITEM *aOld, std::unique_ptr< ITEM > aNew)
bool shoveLineFromLoneVia(const LINE &aCurLine, const LINE &aObstacleLine, LINE &aResultLine)
const NODE * m_springbackDoNotTouchNode
SHOVE_STATUS pushOrShoveVia(VIA *aVia, const VECTOR2I &aForce, int aNextRank)
std::unordered_map< LINKED_ITEM::UNIQ_ID, ROOT_LINE_ENTRY * > m_rootLineHistory
void pruneRootLines(NODE *aRemovedNode)
const VIA_HANDLE GetModifiedHeadVia(int aIndex) const
std::vector< LINE_PAIR > LINE_PAIR_VEC
const CLUSTER AssembleCluster(ITEM *aStart, int aLayer, double aAreaExpansionLimit=0.0, NET_HANDLE aExcludedNet=nullptr)
int Diameter(int aLayer) const
void SetDiameter(int aLayer, int aDiameter)
const VECTOR2I & Pos() const
const SHAPE * Shape(int aLayer) const override
Return the geometrical shape of the item.
const SHAPE_LINE_CHAIN Hull(int aClearance=0, int aWalkaroundThickness=0, int aLayer=-1) const override
VIA * Clone() const override
Return a deep copy of the item.
void SetIterationLimit(const int aIterLimit)
void RestrictToCluster(bool aEnabled, const TOPOLOGY::CLUSTER &aCluster)
void SetSolidsOnly(bool aSolidsOnly)
STATUS Route(const LINE &aInitialPath, LINE &aWalkPath, bool aOptimize=true)
void SetAllowedPolicies(std::vector< WALK_POLICY > aPolicies)
static double DefaultAccuracyForPCB()
A dynamic state checking if a point lies within polygon with a dynamically built outline ( with each ...
void AddPolyline(const SHAPE_LINE_CHAIN &aPolyline)
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const override
Check if point aP lies inside a closed shape.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const SHAPE_LINE_CHAIN Reverse() const
Reverse point order in the line chain.
int PointCount() const
Return the number of points (vertices) in this line chain.
void Clear()
Remove all points from the line chain.
SHAPE_LINE_CHAIN & Simplify2(bool aRemoveColinear=true)
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
const std::string Format(bool aCplusPlus=true) const override
bool IsArcSegment(size_t aSegment) const
long long int Length() const
Return length of the line chain in Euclidean metric.
virtual bool Collide(const VECTOR2I &aP, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const
Check if the boundary of shape (this) lies closer to the point aP than aClearance,...
constexpr extended_type SquaredEuclideanNorm() const
Compute the squared euclidean norm of the vector, which is defined as (x ** 2 + y ** 2).
VECTOR2_TRAITS< int32_t >::extended_type extended_type
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Push and Shove diff pair dimensions (gap) settings dialog.
static void nodeStats(PNS::DEBUG_DECORATOR *dbg, NODE *node, wxString s)
OPT_BOX2I ChangedArea(const ITEM *aItemA, const ITEM *aItemB)
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
#define PNS_DBG(dbg, method,...)
#define PNS_DBGN(dbg, method)
VECTOR2I::extended_type ecoord
std::vector< FAB_LAYER_COLOR > dummy
std::function< bool(const ITEM *)> m_filter
Hold an object colliding with another object, along with some useful data about the collision.
int m_maxFanoutWidth
worst case (largest) width of the tracks connected to the item
ITEM * m_item
Item found to be colliding with m_head.
std::optional< VIA_HANDLE > theVia
std::optional< VIA_HANDLE > prevVia
std::optional< LINE > newLine
std::vector< VIA_HANDLE > m_draggedVias
std::set< ITEM * > m_items
LINE lines[MaxWalkPolicies]
STATUS status[MaxWalkPolicies]
VECTOR2< int32_t > VECTOR2I