64 VIA* vold =
static_cast<VIA*
>( aOld );
65 VIA* vnew =
static_cast<VIA*
>( aNew.get() );
68 newId =
static_cast<VIA*
>( aNew.get() )->
Uid();
71 wxString::Format(
"replace-via node=%p vold=%p [%d %d]-> vnew=%p [%d %d] nid %llu",
m_currentNode, aOld,
73 vnew->
Pos().
y, newId ) );
85 if( aIncludeInChangedArea )
92 PNS_DBG(
Dbg(), AddShape, &r,
BLUE, 0, wxT(
"shove-changed-area" ) );
114 bool foundPredecessor =
false;
130 rootEntry = oldLineIter->second;
131 foundPredecessor =
true;
137 if( !foundPredecessor )
152 aNode->
Replace( aOld, aNew, aAllowRedundantSegments );
154 m_currentNode->Replace( aOld, aNew, aAllowRedundantSegments );
244 const LINE& aShovedLine )
const
253 if( root && ( root->policy &
SHP_REVERSED ) && !loneVia )
255 cp = aCurLine.
CPoint( -1 );
265 wxString::Format(
"chkdir %d", inside?1:0 ) );
283 int obstacleLineWidth = aObstacleLine.
Width();
287 int holeClearance =
getClearance( viaHole, &aObstacleLine );
296 if( ! aObstacleLine.
Walkaround( hull, path_cw,
true ) )
299 if( ! aObstacleLine.
Walkaround( hull, path_ccw,
false ) )
329 const HULL_SET& aHulls,
bool aPermitAdjustingStart,
330 bool aPermitAdjustingEnd )
332 const int c_ENDPOINT_ON_HULL_THRESHOLD = 1000;
334 bool permitAdjustingEndpoints = aPermitAdjustingStart || aPermitAdjustingEnd;
336 PNS_DBG(
Dbg(), BeginGroup,
"shove-details", 1 );
338 for( attempt = 0; attempt < 4; attempt++ )
340 bool invertTraversal = ( attempt >= 2 );
341 bool clockwise = attempt % 2;
342 int vFirst = -1, vLast = -1;
344 LINE l( aObstacleLine );
351 int min_dist = std::numeric_limits<int>::max();
354 for(
int i = 0; i < (int) aHulls.size(); i++ )
357 aHulls[invertTraversal ? aHulls.size() - 1 - i : i];
364 dist = ( p - pref ).EuclideanNorm();
366 if( dist < c_ENDPOINT_ON_HULL_THRESHOLD && dist < min_dist )
374 minhull = invertTraversal ? aHulls.size() - 1 - i : i;
382 int minDist0, minDist1, minhull0 = -1, minhull1 = -1;
386 PNS_DBG(
Dbg(), Message, wxString::Format(
"mindists : %d %d hulls %d %d\n", minDist0, minDist1, minhull0, minhull1 ) );
388 if( minDist1 < c_ENDPOINT_ON_HULL_THRESHOLD && aPermitAdjustingEnd )
395 if( minDist0 < c_ENDPOINT_ON_HULL_THRESHOLD && aPermitAdjustingStart )
404 bool failWalk =
false;
406 for(
int i = 0; i < (int) aHulls.size(); i++ )
408 const SHAPE_LINE_CHAIN& hull = aHulls[invertTraversal ? aHulls.size() - 1 - i : i];
410 PNS_DBG(
Dbg(), AddShape, &hull,
YELLOW, 10000, wxString::Format(
"hull[%d]", i ) );
416 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"Fail-Walk %s %s %d\n" ),
432 for(
int i = 0; i < std::min(
path.PointCount(), obs.
PointCount() ); i++ )
443 for(
int i =
path.PointCount() - 1; i >= 0 && k >= 0; i--, k-- )
452 if( ( vFirst < 0 || vLast < 0 ) && !
path.CompareGeometry( obs ) )
454 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"attempt %d fail vfirst-last" ),
461 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"attempt %d fail vend-start\n" ),
468 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"attempt %d fail direction-check" ),
474 if(
path.SelfIntersecting() )
476 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"attempt %d fail self-intersect" ),
498 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"attempt %d fail coll-check" ),
524 const int cHullFailureExpansionFactor = 1000;
525 int extraHullExpansion = 0;
527 bool voeStart =
false, voeEnd =
false;
528 const JOINT* jtStart =
nullptr;
529 const JOINT* jtEnd =
nullptr;
538 voeStart = jtStart->
Via() !=
nullptr;
540 voeEnd = jtEnd->
Via() !=
nullptr;
545 LINE obstacleLine( aObstacleLine );
546 std::optional<VIA> obsVia;
550 obsVia = aObstacleLine.
Via();
554 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"shove process-single: voe-cur %d voe-obs %d" ),
569 int obstacleLineWidth = obstacleLine.
Width();
578 for(
int attempt = 0; attempt < 3; attempt++ )
582 hulls.reserve( currentLineSegmentCount + 1 );
584 for(
int i = 0; i < currentLineSegmentCount; i++ )
591 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"shove add-extra-clearance %d" ),
598 hulls.push_back( hull );
606 int holeClearance =
getClearance( viaHole, &obstacleLine );
607 int layer = aObstacleLine.
Layer();
609 if( holeClearance +
via.Drill() / 2 > viaClearance +
via.Diameter( layer ) / 2 )
611 viaClearance = holeClearance +
via.Drill() / 2 -
via.Diameter( layer ) / 2;
614 hulls.push_back( aCurLine.
Via().
Hull( viaClearance, obstacleLineWidth, layer ) );
617 bool permitMovingStart = (attempt >= 2) && !voeStart;
618 bool permitMovingEnd = (attempt >= 2) && !voeEnd;
620 if (
shoveLineToHullSet( aCurLine, obstacleLine, aResultLine, hulls, permitMovingStart, permitMovingEnd ) )
628 extraHullExpansion += cHullFailureExpansionFactor;
644 LINE shovedLine( obstacleLine );
649 PNS_DBG(
Dbg(), Message,
"try walk (locked segments)");
659 PNS_DBG(
Dbg(), AddItem, aObstacleSeg,
BLUE, 0, wxT(
"colliding-segment" ) );
662 PNS_DBG(
Dbg(), AddItem, &shovedLine,
BLUE, 10000, wxT(
"shoved-line" ) );
667 int rank = aCurrent.
Rank();
669 shovedLine.
SetRank( rank - 1 );
674 replaceLine( obstacleLine, shovedLine,
true,
false );
693 LINE shovedLine( obstacleLine );
694 ARC tmp( *aObstacleArc );
701 const double extensionWalkThreshold = 1.0;
705 double extensionFactor = 0.0;
708 extensionFactor = shovedLen / obsLen - 1.0;
710 if( extensionFactor > extensionWalkThreshold )
716 PNS_DBG(
Dbg(), AddItem, &aCurrent,
RED, 10000, wxT(
"current-line" ) );
717 PNS_DBG(
Dbg(), AddItem, &obstacleLine,
GREEN, 10000, wxT(
"obstacle-line" ) );
718 PNS_DBG(
Dbg(), AddItem, &shovedLine,
BLUE, 10000, wxT(
"shoved-line" ) );
722 int rank = aCurrent.
Rank();
723 shovedLine.
SetRank( rank - 1 );
725 replaceLine( obstacleLine, shovedLine,
true,
false );
740 LINE shovedLine( aObstacle );
744 PNS_DBG(
Dbg(), AddItem, &aObstacle,
RED, 100000, wxT(
"obstacle-line" ) );
745 PNS_DBG(
Dbg(), AddItem, &aCurrent,
GREEN, 150000, wxT(
"current-line" ) );
746 PNS_DBG(
Dbg(), AddItem, &shovedLine,
BLUE, 200000, wxT(
"shoved-line" ) );
756 m_newHead = shovedLine;
761 shovedLine.
SetRank( aNextRank );
778 LINE walkaroundLine( aCurrent );
806 PNS_DBG(
Dbg(), BeginGroup,
"walk-cluster", 1 );
809 PNS_DBG(
Dbg(), AddItem, item,
RED, 10000, wxT(
"cl-item" ) );
820 int currentRank = aCurrent.
Rank();
823 bool success =
false;
825 PNS_DBG(
Dbg(), AddItem, &aCurrent,
RED, 10000, wxT(
"current-line" ) );
827 for(
int attempt = 0; attempt < 2; attempt++ )
829 if( attempt == 1 ||
Settings().JumpOverObstacles() )
830 nextRank = currentRank - 1;
832 nextRank = currentRank + 10000;
848 PNS_DBG(
Dbg(), AddItem, &walkaroundLine,
BLUE, 10000, wxT(
"walk-line" ) );
858 m_newHead = walkaroundLine;
888 replaceLine( aCurrent, walkaroundLine,
true,
false );
889 walkaroundLine.
SetRank( nextRank );
903 PNS_DBG(
Dbg(), Message, wxString::Format(
"prune called" ) );
908 for(
const ITEM* item : added )
965 wxString::Format(
"restore-springback-via depth=%d %d %d %d %d ",
1001 wxString::Format(
"push-sp via depth=%d %d %d %d %d ", aNode->
Depth(), vhandle.
pos.
x,
1048 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"via force [%d %d]\n" ), aForce.
x, aForce.
y ) );
1051 if ( aForce.
x == 0 && aForce.
y == 0 )
1056 PNS_DBG(
Dbg(), Message, wxT(
"weird, can't find the center-of-via joint\n" ) );
1074 p0_pushed += aForce.
Resize( 2 );
1077 std::unique_ptr<VIA> pushedVia =
Clone( *aVia );
1078 pushedVia->SetPos( p0_pushed );
1079 pushedVia->Mark( aVia->
Marker() );
1091 if( lp.first.HasLockedSegments() )
1094 assert( segIndex == 0 || ( segIndex == ( lp.first.SegmentCount() - 1 ) ) );
1099 lp.second = lp.first;
1100 lp.second.ClearLinks();
1101 lp.second.DragCorner( p0_pushed, lp.second.CLine().Find( p0 ) );
1102 lp.second.Line().Simplify2();
1103 draggedLines.push_back( std::move( lp ) );
1107 pushedVia->SetRank( aNewRank );
1108 PNS_DBG(
Dbg(), Message, wxString::Format(
"via rank %d, fanout %d\n", pushedVia->Rank(), (
int) draggedLines.size() ) );
1113 VIA *
v2 = pushedVia.get();
1115 if( !aDontUnwindStack )
1120 if( draggedLines.empty() )
1131 if( !aDontUnwindStack )
1134 PNS_DBG(
Dbg(), Message, wxString::Format(
"fan %d/%d\n", n, (
int) draggedLines.size() ) );
1137 if( lp.second.SegmentCount() )
1139 lp.second.ClearLinks();
1142 lp.second.LinkVia(
v2 );
1144 if( !aDontUnwindStack )
1147 lp.second.SetRank( aNewRank );
1150 rootEntry->
newLine = lp.second;
1153 PNS_DBG(
Dbg(), Message, wxString::Format(
"PushViaF %p %d eov %d\n", &lp.second, lp.second.SegmentCount(), lp.second.EndsWithVia()?1:0 ) );
1177 assert( aObstacleVia );
1182 bool lineCollision =
false;
1183 bool viaCollision =
false;
1184 bool solidCollision =
false;
1185 VECTOR2I mtvLine, mtvVia, mtvSolid;
1187 PNS_DBG(
Dbg(), BeginGroup,
"push-via-by-line", 1 );
1191 VIA vtmp ( *aObstacleVia );
1192 int layer = aCurrent->
Layer();
1200 LINE* currentLine = (
LINE*) aCurrent;
1218 const VIA& currentVia = currentLine->
Via();
1235 PNS_DBG(
Dbg(), Message, wxT(
"collidee-is-solid" ) );
1248 else if ( lineCollision )
1250 else if ( solidCollision )
1256 PNS_DBG(
Dbg(), Message, wxString::Format(
"push-or-shove-via st %d", st ) );
1276 int layer = aCurrent.
Layer();
1277 int dist = (p0 - p1).EuclideanNorm() - aCurrent.
Via().
Diameter( layer ) / 2
1278 - aObstacleVia->
Diameter( layer ) / 2;
1288 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) );
1290 bool viaCollision =
false;
1301 return onCollidingVia( &aCurrent, aObstacleVia, aObstacleInfo, aCurrent.
Rank() - 1 );
1305 LINE cur( aCurrent );
1309 LINE shoved( aCurrent );
1355 LINE head( aCurrent );
1373 PNS_DBG(
Dbg(), AddItem, &aCurrent,
BLUE, 0, wxT(
"rr-current-line" ) );
1374 PNS_DBG(
Dbg(), AddItem, &shoved,
GREEN, 0, wxT(
"rr-shoved-line" ) );
1377 int currentRank = aCurrent.
Rank();
1384 shoved.
SetRank( currentRank );
1394 if( i->ContainsLink( aSeg ) )
1407 via =
static_cast<VIA*
>( l );
1448 const LINE* l =
static_cast<const LINE*
>( aItem );
1460 PNS_DBG(
Dbg(), AddItem, &aL,
BLUE, 10000, wxT(
"push line stack failed" ) );
1491 wxString::Format(
"cur lc %d lnk %p cnt %d", i->LinkCount(), s, aLine.
LinkCount() ) );
1493 if( i->ContainsLink( s ) && !s->OfKind(
ITEM::VIA_T ) )
1519 int layer = aCurrent->
Layer();
1535 for(
ITEM* link : links )
1540 maxw = std::max( seg->
Width(), maxw );
1544 const ARC* arc =
static_cast<const ARC*
>( link );
1545 maxw = std::max( arc->
Width(), maxw );
1551 if( maxw > 0 && maxw >= v->
Diameter( layer ) )
1555 wxString::Format(
"Fixup via: new-w %d via-w %d", maxw, v->
Diameter( layer ) ) );
1568 int sl = s->
Layer();
1575 for(
int i = 0; i < 2; i++ )
1613 auto viaEnd = jtViaEnd->Via();
1618 bool colliding =
m_currentNode->CheckColliding( viaEnd ).has_value();
1622 if( viaEnd && !current.
EndsWithVia() && colliding )
1645 wxString::Format( wxT(
"current sc=%d net=%s evia=%d" ),
1678 nearest =
m_currentNode->NearestObstacle( ¤tLine, opts );
1683 wxString::Format(
"nearest %p %s rank %d",
1685 nearest->m_item->KindStr(),
1686 nearest->m_item->Rank() ) );
1696 PNS_DBG(
Dbg(), Message, wxT(
"no-nearest-item ") );
1702 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"iter %d: via-fixup %d" ), aIter, viaFixup?1:0 ) );
1705 ITEM* ni = nearest->m_item;
1708 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"NI: %s (%s) %p %d" ),
1711 : wxString( wxT(
"null" ) ),
1721 switch( ni->
Kind() )
1725 PNS_DBG(
Dbg(), BeginGroup, wxString::Format( wxT(
"iter %d: reverse-collide-via" ), aIter ), 0 );
1732 nearest->m_item->Layer() ) )
1734 PNS_DBG(
Dbg(), AddItem, nearest->m_item,
YELLOW, 100000, wxT(
"v2v nearesti" ) );
1753 PNS_DBG(
Dbg(), BeginGroup, wxString::Format( wxT(
"iter %d: reverse-collide-segment" ),
1796 PNS_DBG(
Dbg(), BeginGroup, wxString::Format( wxT(
"iter %d: reverse-collide-arc " ), aIter ), 0 );
1818 switch( ni->
Kind() )
1821 PNS_DBG(
Dbg(), BeginGroup, wxString::Format( wxT(
"iter %d: collide-segment " ), aIter ), 0 );
1834 PNS_DBG(
Dbg(), BeginGroup, wxString::Format( wxT(
"iter %d: collide-arc " ), aIter ), 0 );
1846 PNS_DBG(
Dbg(), BeginGroup, wxString::Format( wxT(
"iter %d: collide-via (fixup: %d)" ), aIter, 0 ), 0 );
1858 PNS_DBG(
Dbg(), BeginGroup, wxString::Format( wxT(
"iter %d: walk-solid " ), aIter ), 0);
1886 PNS_DBG(
Dbg(), Message, wxString::Format(
"ShoveStart [root: %d jts, current: %d jts]",
1906 PNS_DBG(
Dbg(), Message, wxString::Format(
"iter %d: node %p stack %d ",
m_iter,
1915 PNS_DBG(
Dbg(), Message, wxString::Format(
"Fail [time limit expired: %d iter %d iter limit %d",
1974 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"touch [found] uid=%llu type=%s"), link->Uid(), link->KindStr() ) );
1985 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"touch [create] uid=%llu type=%s"), link->Uid(), link->KindStr() ) );
2000 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"touch [create] uid=%llu"), aItem->
Uid() ) );
2006 PNS_DBG(
Dbg(), Message, wxString::Format( wxT(
"touch [create] uid=%llu"), aItem->
Uid() ) );
2026 maxWidth = std::max( line.Width(), maxWidth );
2030 area->Inflate( maxWidth );
2080 std::set<const ITEM*> itemsChk;
2082 for(
int pass = 0; pass < n_passes; pass++ )
2091 LINE* rootLine =
nullptr;
2096 rootLine = rootEntry->rootLine;
2100 if( rootEntry->isHead )
2105 if( optimizer.
Optimize( &lineToOpt, &optimized, rootLine ) )
2113 replaceLine( lineToOpt, optimized,
false, aNode );
2151 if ( iter->m_node == aNode )
2197 if ( iter->m_node == aNode )
2199 iter->m_locked =
false;
2229 rl->policy = aPolicy;
2235 rl->policy = aPolicy;
2263 for (
auto lnk : head.
Links() )
2265 if( lnk->BelongsTo( aNode ) )
2276 for(
auto& item : added )
2279 if( rootEntry && rootEntry->isHead )
2296 if( headEntry.origHead )
2300 PNS_DBG(
Dbg(), Message, wxString::Format(
"orig LinkC=%d RE=%p", headEntry.origHead->LinkCount(), rootEntry ) );
2302 assert( rootEntry );
2303 assert( rootEntry->rootLine );
2305 if( rootEntry->newLine )
2307 headEntry.newHead = rootEntry->newLine;
2308 headEntry.geometryModified = !rootEntry->newLine->CLine().CompareGeometry( rootEntry->rootLine->CLine() );
2310 wxString msg = wxString::Format(
2311 "head %d/%d [net %-20s]: root %p, lc-root %d, lc-new %d\n", i, (
int)
m_headLines.size(),
2312 iface->GetNetName( rootEntry->rootLine->Net() ).c_str().AsChar(), rootEntry->rootLine, rootEntry->rootLine->LinkCount(), headEntry.newHead->LinkCount() );
2319 wxString msg = wxString::Format(
2320 "head %d/%d [net %-20s]: unmodified, lc-orig %d\n", i, (
int)
m_headLines.size(),
2321 iface->GetNetName( headEntry.origHead->Net() ).c_str().AsChar(),
2322 headEntry.origHead->LinkCount() );
2330 if( rootEntry->newVia )
2332 headEntry.geometryModified =
true;
2333 headEntry.theVia =
VIA_HANDLE( rootEntry->newVia->Pos(), rootEntry->newVia->Layers(), rootEntry->newVia->Net() );
2334 auto chk =
m_currentNode->FindViaByHandle( *headEntry.theVia );
2335 wxString msg = wxString::Format(
"[modif] via orig %p chk %p\n", headEntry.draggedVia, chk );
2338 assert( chk !=
nullptr );
2342 headEntry.theVia =
VIA_HANDLE( rootEntry->oldVia->Pos(), rootEntry->oldVia->Layers(), rootEntry->oldVia->Net() );
2343 auto chk =
m_currentNode->FindViaByHandle( *headEntry.theVia );
2344 wxString msg = wxString::Format(
"[unmodif] via orig %p chk %p\n", headEntry.draggedVia, chk );
2346 assert( chk !=
nullptr );
2374 PNS_DBG(
Dbg(), Message, wxString::Format(
"**** PreshoveCleanup %d -> %d\n", vc_prev, vc_post ) );
2376 if( vc_prev != vc_post )
2393 int currentHeadId = 0;
2408 PNS_DBG(
Dbg(), Message, wxString::Format(
"process head-via [%d %d] node=%p", l.theVia->pos.x, l.theVia->pos.y,
m_currentNode ) );
2410 assert( realVia !=
nullptr );
2411 headSet.
Add( realVia->Clone() );
2415 headSet.
Add( *l.origHead->Clone() );
2449 if( headLineEntry.theVia )
2460 viaRoot->oldVia = viaToDrag;
2461 headLineEntry.draggedVia = viaToDrag;
2463 st =
pushOrShoveVia( viaToDrag, ( headLineEntry.viaNewPos - viaToDrag->
Pos() ), 0,
true );
2471 assert( headLineEntry.origHead->LinkCount() == 0 );
2479 wxString::Format(
"touchRoot ohlc %d roots %d re=%p\n",
2480 headLineEntry.origHead->LinkCount(),
2485 LINE head( *headLineEntry.origHead );
2512 auto headVia =
Clone( head.
Via() );
2513 headVia->SetRank( 100000 );
2514 headLineEntry.origHead->LinkVia( headVia.get() );
2515 head.
LinkVia( headVia.get() );
2520 headRoot->isHead =
true;
2521 headRoot->rootLine =
new PNS::LINE( *headLineEntry.origHead );
2522 headRoot->policy = headLineEntry.policy;
2530 wxString::Format(
"headLC %d, rlLC %d oolc %d eov %d\n", head.
LinkCount(),
2531 headRoot->rootLine->LinkCount(),
2532 headLineEntry.origHead->LinkCount(),
2538 wxString::Format(
"Shove heads %d/%d h-lc=%d net=%s Line=%d Policy=%s",
2539 currentHeadId, totalHeads, head.
LinkCount(),
2540 iface->GetNetName( head.
Net() ), headRoot->newLine ? 1 : 0,
2542 : wxString( wxT(
"default[ne]" ) ) ) );
2563 wxString::Format(
"Shove status : %s after %d iterations, heads: %d",
2584 if( headEntry.prevVia )
2588 wxString::Format(
"Fail-restore via mod [%d, %d] orig [%d, %d]",
2589 headEntry.theVia->pos.x,
2590 headEntry.theVia->pos.y,
2591 headEntry.prevVia->pos.x,
2592 headEntry.prevVia->pos.y ) );
2594 headEntry.theVia = headEntry.prevVia;
2595 headEntry.geometryModified =
true;
2622 return wxT(
"default" );
2627 rv.Append(
"shove ");
2629 rv.Append(
"walk-forward ");
2631 rv.Append(
"walk-back ");
2633 rv.Append(
"ignore ");
2635 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.
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.
ALGO_BASE(ROUTER *aRouter)
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
const VECTOR2I & CLastPoint() 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
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.
std::optional< OBSTACLE > OPT_OBSTACLE
void Remove(ARC *aArc)
Remove an item from this branch.
Perform various optimizations of the lines being routed, attempting to make the lines shorter and les...
void SetRestrictArea(const BOX2I &aArea, bool aStrict=true)
void SetCollisionMask(int aMask)
void SetEffortLevel(int aEffort)
static bool Optimize(LINE *aLine, int aEffortLevel, NODE *aWorld, const VECTOR2I &aV=VECTOR2I(0, 0))
@ 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 wxString GetNetName(PNS::NET_HANDLE aNet) const =0
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 pushOrShoveVia(VIA *aVia, const VECTOR2I &aForce, int aNextRank, bool aDontUnwindStack=false)
SHOVE_STATUS onReverseCollidingVia(LINE &aCurrent, VIA *aObstacleVia, OBSTACLE &aObstacleInfo)
std::vector< LINE > m_lineStack
std::vector< SPRINGBACK_TAG > m_nodeStack
@ SHP_DONT_LOCK_ENDPOINTS
bool patchTadpoleVia(ITEM *nearest, LINE ¤t)
SHOVE_STATUS onCollidingArc(LINE &aCurrent, ARC *aObstacleArc)
bool shoveLineToHullSet(const LINE &aCurLine, const LINE &aObstacleLine, LINE &aResultLine, const HULL_SET &aHulls, bool aPermitAdjustingStart=false, bool aPermitAdjustingEnd=false)
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
void UnlockSpringbackNode(NODE *aNode)
NODE * reduceSpringback(const ITEM_SET &aHeadSet)
bool AddLockedSpringbackNode(NODE *aNode)
ROOT_LINE_ENTRY * findRootLine(const LINE &aLine) const
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
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)
bool pruneLineFromOptimizerQueue(const LINE &aLine)
void replaceItems(ITEM *aOld, std::unique_ptr< ITEM > aNew)
bool shoveLineFromLoneVia(const LINE &aCurLine, const LINE &aObstacleLine, LINE &aResultLine)
const NODE * m_springbackDoNotTouchNode
std::unordered_map< LINKED_ITEM::UNIQ_ID, ROOT_LINE_ENTRY * > m_rootLineHistory
void pruneRootLines(NODE *aRemovedNode)
const VIA_HANDLE GetModifiedHeadVia(int aIndex) const
ROOT_LINE_ENTRY * replaceLine(LINE &aOld, LINE &aNew, bool aIncludeInChangedArea=true, bool aAllowRedundantSegments=true, NODE *aNode=nullptr)
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
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 int 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)
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
const VECTOR2I NearestPoint(const VECTOR2I &aP, bool aAllowInternalShapePoints=true) const
Find a point on the line chain that is closest to point aP.
const VECTOR2I & CLastPoint() const
Return the last point in the line chain.
const std::string Format(bool aCplusPlus=true) const override
bool IsArcSegment(size_t aSegment) const
void Insert(size_t aVertex, const VECTOR2I &aP)
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.
OPT_BOX2I ChangedArea(const ITEM *aItemA, const ITEM *aItemB)
void removeHead(NODE *aNode, LINE &head)
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::vector< ITEM * > m_items
LINE lines[MaxWalkPolicies]
STATUS status[MaxWalkPolicies]
VECTOR2< int32_t > VECTOR2I