107    if( 
m_tail.SegmentCount() == 0 )
 
 
  146        if( i.index_our < n )
 
 
  221    bool pullback_1 = 
false;    
 
  228    if( pullback_1 || pullback_2 )
 
  243        PNS_DBG( 
Dbg(), Message, wxString::Format( 
"Placer: pullback triggered [%d] [%s %s]",
 
 
  283    int reduce_index = -1;
 
  310    if( reduce_index >= 0 )
 
  312        PNS_DBG( 
Dbg(), Message, wxString::Format( 
"Placer: reducing tail: %d" , reduce_index ) );
 
  316        tail.
Remove( reduce_index + 1, -1 );
 
 
  345        PNS_DBG( 
Dbg(), Message, wxT( 
"Merge failed: not enough head segs." ) );
 
  351        PNS_DBG( 
Dbg(), Message, wxT( 
"Merge failed: head and tail discontinuous." ) );
 
  355    if( 
m_head.CountCorners( ForbiddenAngles ) != 0 )
 
  375        if( dir_head.
Angle( dir_tail ) & ForbiddenAngles )
 
  392    PNS_DBG( 
Dbg(), Message, wxString::Format( 
"Placer: merge %d, new direction: %s" , n_head,
 
 
  406    int idx = l.
Split( aP );
 
  416    PNS_DBG( 
Dbg(), AddPoint, aP, 
BLUE, 500000, wxString::Format( 
"hug-target-check-%d", idx ) );
 
  417    PNS_DBG( 
Dbg(), AddShape, &l2, 
BLUE, 500000, wxT( 
"hug-target-line" ) );
 
  419    if( dist < thresholdDist )
 
  429        aOut = std::move( l2 );
 
  430        thresholdDist = dist;
 
 
  440    std::vector<int>      dists;
 
  441    std::vector<VECTOR2I> pts;
 
  447    int accumulatedDist = 0;
 
  455        dists.push_back( ( aCursor - s.
A ).EuclideanNorm() );
 
  456        pts.push_back( s.
A );
 
  459        if( pn != s.
A && pn != s.
B )
 
  461            dists.push_back( ( pn - aCursor ).EuclideanNorm() );
 
  465        accumulatedDist += s.
Length();
 
  467        if ( accumulatedDist > lengthThreshold )
 
  474    dists.push_back( ( aCursor - lastP ).EuclideanNorm() );
 
  475    pts.push_back( lastP );
 
  477    int minDistLoc = std::numeric_limits<int>::max();
 
  479    int minDistGlob = std::numeric_limits<int>::max();
 
  482    for( 
int i = 0; i < dists.size(); i++ )
 
  486        if( d < minDistGlob )
 
  493    if( dists.size() >= 3 )
 
  495        for( 
int i = 0; i < dists.size() - 3; i++ )
 
  497            if( dists[i + 2] > dists[i + 1] && dists[i] > dists[i + 1] )
 
  499                int d = dists[i + 1];
 
  508        if( dists.back() < minDistLoc && minPLoc >= 0 )
 
  510            minDistLoc = dists.back();
 
  511            minPLoc    = dists.size() - 1;
 
  517        minDistLoc = minDistGlob;
 
  528        preferred = minPGlob;
 
  535    int thresholdDist = 0;
 
  543    int minDist = std::numeric_limits<int>::max();
 
  547    for( 
int i = 0; i < pts.size() ; i++)
 
 
  584        PNS_DBG( 
Dbg(), BeginGroup, wxString::Format( 
"walk-round-%d", round ), 0 );
 
  588        PNS_DBG( 
Dbg(), AddItem, &l1, 
BLUE, 20000, wxT( 
"walk-base-l1" ) );
 
  600        double hugThresholdLengthComplete =
 
  604        std::optional<LINE> bestLine;
 
  615                                                      : std::numeric_limits<int>::max();
 
  617                                                        : std::numeric_limits<int>::max();
 
  623            LINE tmpHead, tmpTail;
 
  635            PNS_DBG( 
Dbg(), AddItem, &wr.
lines[WP_CW], 
RED, 20000, wxT( 
"wf-result-cw-postopt" ) );
 
  637            bestLine = wr.
lines[WP_CW];
 
  644            LINE tmpHead, tmpTail;
 
  655            PNS_DBG( 
Dbg(), AddItem, &wr.
lines[WP_CCW], 
RED, 20000, wxT( 
"wf-result-ccw-postopt" ) );
 
  658            if( len_ccw < len_cw )
 
  659                bestLine = wr.
lines[WP_CCW];
 
  662        int bestLength = len_cw < len_ccw ? len_cw : len_ccw;
 
  664        if( bestLength < hugThresholdLengthComplete && bestLine.has_value() )
 
  666            walkFull.
SetShape( bestLine->CLine() );
 
  672        bool validCw = 
false;
 
  673        bool validCcw = 
false;
 
  674        int  distCcw = std::numeric_limits<int>::max();
 
  675        int  distCw = std::numeric_limits<int>::max();
 
  685                distCw = ( aP - l_cw.
CLastPoint() ).EuclideanNorm();
 
  687            PNS_DBG( 
Dbg(), AddShape, &l_cw, 
MAGENTA, 200000, wxString::Format( 
"wh-result-cw %s",
 
  688                                                                                 validCw ? 
"non-colliding" 
  697                distCcw = ( aP - l_ccw.
CLastPoint() ).EuclideanNorm();
 
  699            PNS_DBG( 
Dbg(), AddShape, &l_ccw, 
MAGENTA, 200000, wxString::Format( 
"wh-result-ccw %s",
 
  700                                                                                 validCcw ? 
"non-colliding" 
  705        if( distCw < distCcw && validCw )
 
  732    PNS_DBG( 
Dbg(), AddItem, &walkFull, 
GREEN, 200000, wxT( 
"walk-full" ) );
 
  737                 wxString::Format( 
"walk-via ok %d", aViaOk ? 1 : 0 ) );
 
  740    aWalkLine = walkFull;
 
 
  756    switch( 
Settings().OptimizerEffort() )
 
  780        PNS_DBG( 
Dbg(), AddItem, &walkFull, 
GREEN, 100000, wxString::Format( 
"collision check fail" ) );
 
  810    PNS_DBG( 
Dbg(), AddItem, &aNewHead, 
GREEN, 100000, wxString::Format( 
"walk-new-head" ) );
 
  811    PNS_DBG( 
Dbg(), AddItem, &aNewTail, 
BLUE, 100000, wxT( 
"walk-new-tail" ) );
 
 
  820    m_head.SetBlockingObstacle( 
nullptr );
 
  840        if( ( nearest - aP ).EuclideanNorm() < 
m_head.Width() / 2 )
 
  849    if( !
Settings().AllowDRCViolations() )
 
  853        if( obs && obs->m_distFirst != INT_MAX )
 
  856            m_head.SetBlockingObstacle( obs->m_item );
 
 
  871    LINE newTail( aOldTail );
 
  872    LINE newHead( aOldTail );
 
  917        newHead = std::move( l2 );
 
  920    PNS_DBG( 
Dbg(), AddItem, &newHead, 
BLUE, 500000, wxT( 
"head-post-split" ) );
 
  922    aNewHead = std::move( newHead );
 
  923    aNewTail = std::move( newTail );
 
 
  949    LINE newHead( walkSolids );
 
  952        PNS_DBG( 
Dbg(), AddPoint, newHead.
Via().
Pos(), 
RED, 1000000, wxString::Format( 
"SVIA [%d]", viaOk?1:0 ) );
 
  969    switch( 
Settings().OptimizerEffort() )
 
  994            newHead = 
m_shove->GetModifiedHead( 0 );
 
 
 1063    int tailLookbackSegments = 3;
 
 1068    int threshold = std::min( tail.
PointCount(), tailLookbackSegments + 1 );
 
 
 1115    bool go_back = 
false;
 
 1120    PNS_DBG( 
Dbg(), Message, wxString::Format( 
"routeStep: direction: %s head: %d, tail: %d shapes" ,
 
 1125    PNS_DBG( 
Dbg(), BeginGroup, wxT( 
"route-step" ), 0 );
 
 1130    for( i = 0; i < n_iter; i++ )
 
 1134        LINE newHead, newTail;
 
 1136        if( !go_back && 
Settings().FollowMouse() )
 
 1146        if( !
routeHead( aP, newHead, newTail ) )
 
 1148            m_tail = std::move( prevTail );
 
 1149            m_head = std::move( prevHead );
 
 1154            if( 
m_tail.PointCount() == 0 )
 
 1165        PNS_DBG( 
Dbg(), AddItem, &newHead, 
LIGHTGREEN, 100000, wxString::Format( 
"new_head [fail: %d]", fail?1:0 ) );
 
 1170        PNS_DBG( 
Dbg(), Message, wxString::Format( 
"N VIA H %d T %d\n", 
m_head.EndsWithVia() ? 1 : 0, 
m_tail.EndsWithVia() ? 1 : 0 ) );
 
 1172        m_head = std::move( newHead );
 
 1173        m_tail = std::move( newTail );
 
 1181        PNS_DBG( 
Dbg(), Message, wxString::Format( 
"SI VIA H %d T %d\n", 
m_head.EndsWithVia() ? 1 : 0, 
m_tail.EndsWithVia() ? 1 : 0 ) );
 
 1193        PNS_DBG( 
Dbg(), Message, wxString::Format( 
"PB VIA H %d T %d\n", 
m_head.EndsWithVia() ? 1 : 0, 
m_tail.EndsWithVia() ? 1 : 0 ) );
 
 1200    if( !fail && 
Settings().FollowMouse() )
 
 1207            PNS_DBG( 
Dbg(), Message, wxString::Format( 
"PreM VIA H %d T %d\n", 
m_head.EndsWithVia() ? 1 : 0, 
m_tail.EndsWithVia() ? 1 : 0 ) );
 
 1211            PNS_DBG( 
Dbg(), Message, wxString::Format( 
"PostM VIA H %d T %d\n", 
m_head.EndsWithVia() ? 1 : 0, 
m_tail.EndsWithVia() ? 1 : 0 ) );
 
 
 1228    if( !
m_head.PointCount() )
 
 1231    return m_head.CLastPoint() == aP;
 
 
 1304    std::unique_ptr<SEGMENT> s_new[2] = { 
Clone( *s_old ), 
Clone( *s_old ) };
 
 1306    s_new[0]->SetEnds( s_old->
Seg().
A, aP );
 
 1307    s_new[1]->SetEnds( aP, s_old->
Seg().
B );
 
 1310    aNode->
Add( std::move( s_new[0] ), 
true );
 
 1311    aNode->
Add( std::move( s_new[1] ), 
true );
 
 
 1330    ARC*             a_old = 
static_cast<ARC*
>( aArc );
 
 1333    std::unique_ptr<ARC> a_new[2] = { 
Clone( *a_old ), 
Clone( *a_old ) };
 
 1335    a_new[0]->Arc().ConstructFromStartEndCenter( o_arc.
GetP0(), aP, o_arc.
GetCenter(),
 
 1338    a_new[1]->Arc().ConstructFromStartEndCenter( aP, o_arc.
GetP1(), o_arc.
GetCenter(),
 
 1342    aNode->
Add( std::move( a_new[0] ), 
true );
 
 1343    aNode->
Add( std::move( a_new[1] ), 
true );
 
 
 1407        SEG seg = 
static_cast<SEGMENT*
>( aStartItem )->Seg();
 
 1411        else if( aP == seg.
B )
 
 1417        double angle = 
static_cast<SOLID*
>( aStartItem )->GetOrientation().AsDegrees();
 
 1422    PNS_DBG( 
Dbg(), Message, wxString::Format( 
"Posture: init %s, last seg %s",
 
 
 1472    wxLogTrace( wxT( 
"PNS" ), wxT( 
"world %p, intitial-direction %s layer %d" ),
 
 
 1489    if( aEndItem && aEndItem->
Owner() )
 
 1490        eiDepth = 
static_cast<const NODE*
>( aEndItem->
Owner() )->
Depth();
 
 1500    bool reachesEnd = 
route( aP );
 
 1509        const SEG targetSeg = 
static_cast<SEGMENT*
>( aEndItem )->Seg();
 
 1515            m_head.Line().SetPoint( 
m_head.PointCount() - 1, splitPoint );
 
 1529            && aEndItem && latestNode->
Depth() >= eiDepth
 
 
 1548    bool realEnd = 
false;
 
 1566            else if( 
m_router->GetInterface()->GetNetCode( aEndItem->
Net() ) <= 0 )
 
 1577    if( !
Settings().AllowDRCViolations() )
 
 1599            m_lastNode->GetUpdatedItems( removed, added );
 
 1659    for( 
int i = 0; i < lastV; i++ )
 
 1661        ssize_t arcIndex = l.
ArcIndex( i );
 
 1663        if( arcIndex < 0 || ( lastArc >= 0 && i == lastV - 1 && !l.
IsPtOnArc( lastV ) ) )
 
 1669            std::unique_ptr<SEGMENT> sp = std::make_unique<SEGMENT>( seg );
 
 1670            lastItem = sp.get();
 
 1677            if( arcIndex == lastArc )
 
 1684            std::unique_ptr<ARC> ap = std::make_unique<ARC>( arc );
 
 1685            lastItem = ap.get();
 
 1702    if( realEnd && lastItem )
 
 
 1752    std::optional<VECTOR2I> ret;
 
 1757    if( 
m_head.Line().PointCount() )
 
 1758        ret = 
m_head.Line().CPoint( 0 );
 
 
 1804        m_shove->RewindToLastLockedNode();
 
 
 1826    std::set<LINKED_ITEM *> toErase;
 
 1828    aNode->
Add( aLatest, 
true );
 
 1830    for( 
int s = 0; s < aLatest.
LinkCount(); s++ )
 
 1835        std::vector<LINE> lines;
 
 1844        int removedCount = 0;
 
 1847        for( 
LINE& line : lines )
 
 1851            if( !( line.ContainsLink( seg ) ) && line.SegmentCount() )
 
 1854                    toErase.insert( ss );
 
 1860        PNS_DBG( 
Dbg(), Message, wxString::Format( 
"total segs removed: %d/%d", removedCount, total ) );
 
 1866    aNode->
Remove( aLatest );
 
 
 1880    std::set<ITEM*> cleanup;
 
 1888                SEG refSeg = 
static_cast<SEGMENT*
>( aItem )->Seg();
 
 1894                    if( neighbor == aItem
 
 1896                        || !neighbor->LayersOverlap( aItem ) )
 
 1901                    if( 
static_cast<const SEGMENT*
>( neighbor )->Width()
 
 1902                            != 
static_cast<const SEGMENT*
>( aItem )->Width() )
 
 1907                    const SEG& testSeg = 
static_cast<const SEGMENT*
>( neighbor )->Seg();
 
 1911                        const JOINT* nA = aNode->
FindJoint( neighbor->Anchor( 0 ), neighbor );
 
 1912                        const JOINT* nB = aNode->
FindJoint( neighbor->Anchor( 1 ), neighbor );
 
 1914                        if( ( nA == aJoint && nB->
LinkCount() == 1 ) ||
 
 1915                            ( nB == aJoint && nA->
LinkCount() == 1 ) )
 
 1917                            cleanup.insert( neighbor );
 
 1920                    else if( testSeg.
Contains( refSeg ) )
 
 1925                        if( ( aA == aJoint && aB->
LinkCount() == 1 ) ||
 
 1926                            ( aB == aJoint && aA->
LinkCount() == 1 ) )
 
 1928                            cleanup.insert( aItem );
 
 1935    for( 
ITEM* item : added )
 
 1943        processJoint( jA, item );
 
 1944        processJoint( jB, item );
 
 1947    for( 
ITEM* seg : cleanup )
 
 1952    LINE l_orig = aNode->
AssembleLine( aLatest, 
nullptr, 
false, 
false, 
false );
 
 1966        PNS_DBG( 
Dbg(), AddItem, &l, 
RED, 100000, wxT(
"simplified"));
 
 
 1980        if( 
m_sizes.TrackWidthIsExplicit()
 
 1988        if( 
m_head.EndsWithVia() )
 
 
 2019    PNS_DBG( 
Dbg(), Message, wxString::Format( wxT( 
"buildInitialLine: m_direction %s, guessedDir %s, tail points %d" ),
 
 2042            if( !
m_tail.PointCount() )
 
 2060    PNS_DBG( 
Dbg(), AddItem, &aHead, 
CYAN, 10000, wxT( 
"initial-trace" ) );
 
 2078    for( 
int attempt = 0; attempt < 2; attempt++)
 
 2089            aHead = 
LINE( aHead, line );
 
 
 2148    st.
pts.push_back(pt);
 
 2151    m_stages.push_back( std::move( st ) );
 
 
constexpr Vec NearestPoint(const Vec &aPoint) const
Return the point in this rect that is closest to the provided point.
 
Represent route directions & corner angles in a 45-degree metric.
 
const SHAPE_LINE_CHAIN BuildInitialTrace(const VECTOR2I &aP0, const VECTOR2I &aP1, bool aStartDiagonal=false, CORNER_MODE aMode=CORNER_MODE::MITERED_45) const
Build a 2-segment line chain between points aP0 and aP1 and following 45-degree routing regime.
 
AngleType Angle(const DIRECTION_45 &aOther) const
Return the type of angle between directions (this) and aOther.
 
AngleType
Represent kind of angle formed by vectors heading in two DIRECTION_45s.
 
Directions
Available directions, there are 8 of them, as on a rectilinear map (north = up) + an extra undefined ...
 
@ ROUNDED_90
H/V with filleted corners.
 
@ MITERED_90
H/V only (90-degree corners)
 
@ ROUNDED_45
H/V/45 with filleted corners.
 
@ MITERED_45
H/V/45 with mitered corners (default)
 
const std::string Format() const
Format the direction in a human readable word.
 
KICAD_T Type() const
Returns the type of object.
 
void SetDebugDecorator(DEBUG_DECORATOR *aDecorator)
Assign a debug decorator allowing this algo to draw extra graphics for visual debugging.
 
void SetLogger(LOGGER *aLogger)
 
virtual LOGGER * Logger()
 
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
 
void SetWidth(int aWidth) override
 
FIXED_TAIL(int aLineCount=1)
 
bool PopStage(STAGE &aStage)
 
void AddStage(const VECTOR2I &aStart, int aLayer, bool placingVias, DIRECTION_45 direction, NODE *aNode)
 
std::vector< STAGE > m_stages
 
const std::vector< ITEM * > & CItems() const
 
Base class for PNS router board items.
 
BOARD_ITEM * Parent() const
 
virtual NET_HANDLE Net() const
 
PnsKind Kind() const
Return the type (kind) of the item.
 
void SetNet(NET_HANDLE aNet)
 
void SetLayer(int aLayer)
 
bool OfKind(int aKindMask) const
 
A 2D point on a given set of layers and belonging to a certain net, that links together a number of b...
 
int LinkCount(int aMask=-1) const
 
bool IsLineCorner(bool aAllowLockedSegs=false) const
Checks if a joint connects two segments of the same net, layer, and width.
 
const ITEM_SET & CLinks() const
 
bool mergeHead()
Moves "established" segments from the head to the tail if certain conditions are met.
 
bool SplitAdjacentArcs(NODE *aNode, ITEM *aArc, const VECTOR2I &aP)
Snaps the point aP to arc aArc.
 
bool handleSelfIntersections()
Check if the head of the track intersects its tail.
 
LINE_PLACER(ROUTER *aRouter)
 
bool SetLayer(int aLayer) override
Set the current routing layer.
 
NODE * m_lastNode
Postprocessed world state (including marked collisions & removed loops)
 
bool route(const VECTOR2I &aP)
Re-route the current track to point aP.
 
void updatePStart(const LINE &tail)
 
bool AbortPlacement() override
 
std::unique_ptr< SHOVE > m_shove
The shove engine.
 
const LINE Trace() const
Return the complete routed line.
 
bool splitHeadTail(const LINE &aNewLine, const LINE &aOldTail, LINE &aNewHead, LINE &aNewTail)
 
bool handlePullback()
Deal with pull-back: reduces the tail if head trace is moved backwards wrs to the current tail direct...
 
void setWorld(NODE *aWorld)
Set the board to route.
 
void UpdateSizes(const SIZES_SETTINGS &aSizes) override
Perform on-the-fly update of the width, via diameter & drill size from a settings class.
 
bool reduceTail(const VECTOR2I &aEnd)
Attempt to reduce the number of segments in the tail by trying to replace a certain number of latest ...
 
void SetOrthoMode(bool aOrthoMode) override
Function SetOrthoMode()
 
LINE m_tail
routing "tail": part of the track that has been already fixed due to collisions with obstacles
 
MOUSE_TRAIL_TRACER m_mouseTrailTracer
 
bool Start(const VECTOR2I &aP, ITEM *aStartItem) override
Start routing a single track at point aP, taking item aStartItem as anchor (unless NULL).
 
std::optional< VECTOR2I > m_last_p_end
 
bool optimizeTailHeadTransition()
Try to reduce the corner count of the most recent part of tail/head by merging obtuse/collinear segme...
 
bool HasPlacedAnything() const override
 
void routeStep(const VECTOR2I &aP)
Perform a single routing algorithm step, for the end point aP.
 
NODE * m_currentNode
Current world state.
 
bool buildInitialLine(const VECTOR2I &aP, LINE &aHead, PNS::PNS_MODE aMode, bool aForceNoVia=false)
 
bool cursorDistMinimum(const SHAPE_LINE_CHAIN &aL, const VECTOR2I &aCursor, double lengthThreshold, SHAPE_LINE_CHAIN &aOut)
 
LINE m_head
the volatile part of the track from the previously analyzed point to the current routing destination
 
void removeLoops(NODE *aNode, LINE &aLatest)
Searches aNode for traces concurrent to aLatest and removes them.
 
VECTOR2I m_fixStart
start point of the last 'fix'
 
bool rhMarkObstacles(const VECTOR2I &aP, LINE &aNewHead, LINE &aNewTail)
 
NODE * m_world
pointer to world to search colliding items
 
DIRECTION_45 m_initial_direction
routing direction for new traces
 
NODE * CurrentNode(bool aLoopsRemoved=false) const override
Return the most recent world state.
 
bool SplitAdjacentSegments(NODE *aNode, ITEM *aSeg, const VECTOR2I &aP)
Snaps the point aP to segment aSeg.
 
bool rhWalkBase(const VECTOR2I &aP, LINE &aWalkLine, int aCollisionMask, PNS::PNS_MODE aMode, bool &aViaOk)
 
void setInitialDirection(const DIRECTION_45 &aDirection)
Set preferred direction of the very first track segment to be laid.
 
void updateLeadingRatLine()
Draw the "leading" rats nest line, which connects the end of currently routed track and the nearest y...
 
bool routeHead(const VECTOR2I &aP, LINE &aNewHead, LINE &aNewTail)
Compute the head trace between the current start point (m_p_start) and point aP, starting with direct...
 
bool rhWalkOnly(const VECTOR2I &aP, LINE &aNewHead, LINE &aNewTail)
 
void FlipPosture() override
Toggle the current posture (straight/diagonal) of the trace head.
 
const VIA makeVia(const VECTOR2I &aP)
 
bool rhShoveOnly(const VECTOR2I &aP, LINE &aNewHead, LINE &aNewTail)
< Route step shove mode.
 
bool CommitPlacement() override
 
VECTOR2I m_p_start
current routing start (end of tail, beginning of head)
 
void GetModifiedNets(std::vector< NET_HANDLE > &aNets) const override
Function GetModifiedNets.
 
bool Move(const VECTOR2I &aP, ITEM *aEndItem) override
Move the end of the currently routed trace to the point aP, taking aEndItem as anchor (if not NULL).
 
void simplifyNewLine(NODE *aNode, LINKED_ITEM *aLatest)
Assemble a line starting from segment or arc aLatest, removes collinear segments and redundant vertic...
 
DIRECTION_45 m_direction
current routing direction
 
void initPlacement()
Initialize placement of a new line with given parameters.
 
const ITEM_SET Traces() override
Return the complete routed line, as a single-member ITEM_SET.
 
bool FixRoute(const VECTOR2I &aP, ITEM *aEndItem, bool aForceFinish) override
Commit the currently routed track to the parent node taking aP as the final end point and aEndItem as...
 
std::optional< VECTOR2I > UnfixRoute() override
 
bool ToggleVia(bool aEnabled) override
Enable/disable a via at the end of currently routed trace.
 
bool clipAndCheckCollisions(const VECTOR2I &aP, const SHAPE_LINE_CHAIN &aL, SHAPE_LINE_CHAIN &aOut, int &thresholdDist)
 
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
 
const VECTOR2I & CPoint(int aIdx) const
 
void SetShape(const SHAPE_LINE_CHAIN &aLine)
Return the shape of the line.
 
const SHAPE_LINE_CHAIN & CLine() const
 
const VECTOR2I & CLastPoint() const
 
SHAPE_LINE_CHAIN & Line()
 
void AppendVia(const VIA &aVia)
 
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.
 
LINKED_ITEM * GetLink(int aIndex) const
Erase the linking information. Used to detach the line from the owning node.
 
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...
 
int FindLinesBetweenJoints(const JOINT &aA, const JOINT &aB, std::vector< LINE > &aLines)
Find the joints corresponding to the ends of line aLine.
 
std::vector< ITEM * > ITEM_VECTOR
 
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
 
void FindLineEnds(const LINE &aLine, JOINT &aA, JOINT &aB)
Destroy all child nodes. Applicable only to the root node.
 
bool Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Add an item to the current node.
 
const LINE AssembleLine(LINKED_ITEM *aSeg, int *aOriginSegmentIndex=nullptr, bool aStopAtLockedJoints=false, bool aFollowLockedSegments=false, bool aAllowSegmentSizeMismatch=true)
Follow the joint map to assemble a line connecting two non-trivial joints starting from segment aSeg.
 
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 SetCollisionMask(int aMask)
 
void SetEffortLevel(int aEffort)
 
static bool Optimize(LINE *aLine, int aEffortLevel, NODE *aWorld, const VECTOR2I &aV=VECTOR2I(0, 0))
 
@ SMART_PADS
Reroute pad exits.
 
@ FANOUT_CLEANUP
Simplify pad-pad and pad-via connections if possible.
 
@ MERGE_SEGMENTS
Reduce corner cost iteratively.
 
@ MERGE_COLINEAR
Merge co-linear segments.
 
const ITEM_OWNER * Owner() const
Return the owner of this item, or NULL if there's none.
 
PLACEMENT_ALGO(ROUTER *aRouter)
 
virtual NET_HANDLE GetOrphanedNetHandle()=0
 
ROUTER_IFACE * GetInterface() const
 
int ViaForcePropIterationLimit() const
 
double WalkaroundHugLengthThreshold() const
 
bool GetFixAllSegments() const
 
PNS_MODE Mode() const
Set the routing mode.
 
DIRECTION_45::CORNER_MODE GetCornerMode() const
 
void SetWidth(int aWidth) override
 
bool LeadingRatLine(const LINE *aTrack, SHAPE_LINE_CHAIN &aRatLine)
 
const VECTOR2I & Pos() const
 
bool PushoutForce(NODE *aNode, const VECTOR2I &aDirection, VECTOR2I &aForce, int aCollisionMask=ITEM::ANY_T, int aMaxIterations=10)
 
void SetPos(const VECTOR2I &aPos)
 
void SetIterationLimit(const int aIterLimit)
 
void SetSolidsOnly(bool aSolidsOnly)
 
STATUS Route(const LINE &aInitialPath, LINE &aWalkPath, bool aOptimize=true)
 
void SetItemMask(int aMask)
 
void SetAllowedPolicies(std::vector< WALK_POLICY > aPolicies)
 
Represent a contiguous set of PCB layers.
 
const VECTOR2I NearestPoint(const VECTOR2I &aP) const
Compute a point on the segment (this) that is closest to point aP.
 
int Length() const
Return the length (this).
 
bool Collinear(const SEG &aSeg) const
Check if segment aSeg lies on the same line as (this).
 
bool Overlaps(const SEG &aSeg) const
 
bool Contains(const SEG &aSeg) const
 
VECTOR2I LineProject(const VECTOR2I &aP) const
Compute the perpendicular projection point of aP on a line passing through ends of the segment.
 
SEG Reversed() const
Returns the center point of the line.
 
int GetWidth() const override
 
const VECTOR2I & GetP1() const
 
const VECTOR2I & GetP0() const
 
const VECTOR2I & GetCenter() const
 
bool PointOnEdge(const VECTOR2I &aP, int aAccuracy=0) const
Check if point aP lies on an edge or vertex of the line chain.
 
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
 
bool IsPtOnArc(size_t aPtIndex) const
 
const SHAPE_ARC & Arc(size_t aArc) const
 
void SetPoint(int aIndex, const VECTOR2I &aPos)
Move a point to a specific location.
 
int Split(const VECTOR2I &aP, bool aExact=false)
Insert the point aP belonging to one of the our segments, splitting the adjacent segment in two.
 
int ShapeCount() const
Return the number of shapes (line segments or arcs) in this line chain.
 
int Intersect(const SEG &aSeg, INTERSECTIONS &aIp) const
Find all intersection points between our line chain and the segment aSeg.
 
int PointCount() const
Return the number of points (vertices) in this line chain.
 
void Replace(int aStartIndex, int aEndIndex, const VECTOR2I &aP)
Replace points with indices in range [start_index, end_index] with a single point aP.
 
ssize_t ArcIndex(size_t aSegment) const
Return the arc index for the given segment index.
 
void Clear()
Remove all points from the line chain.
 
void Simplify(int aTolerance=0)
Simplify the line chain by removing colinear adjacent segments and duplicate vertices.
 
const std::vector< SHAPE_ARC > & CArcs() const
 
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 SHAPE_LINE_CHAIN Slice(int aStartIndex, int aEndIndex) const
Return a subset of this line chain containing the [start_index, end_index] range of points.
 
int SegmentCount() const
Return the number of segments in this line chain.
 
const VECTOR2I & CLastPoint() const
Return the last point in the line chain.
 
void Remove(int aStartIndex, int aEndIndex)
Remove the range of points [start_index, end_index] from the line chain.
 
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
 
bool IsArcSegment(size_t aSegment) const
 
void RemoveShape(int aPointIndex)
Remove the shape at the given index from the line chain.
 
std::vector< INTERSECTION > INTERSECTIONS
 
long long int Length() const
Return length of the line chain in Euclidean metric.
 
int Find(const VECTOR2I &aP, int aThreshold=0) const
Search for point aP.
 
const std::vector< VECTOR2I > & CPoints() const
 
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
 
Push and Shove diff pair dimensions (gap) settings dialog.
 
@ RM_MarkObstacles
Ignore collisions, mark obstacles.
 
@ RM_Walkaround
Only walk around.
 
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
 
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
 
#define PNS_DBG(dbg, method,...)
 
#define PNS_DBGN(dbg, method)
 
std::vector< FIX_POINT > pts
 
LINE lines[MaxWalkPolicies]
 
STATUS status[MaxWalkPolicies]
 
Represent an intersection between two line segments.
 
@ PCB_PAD_T
class PAD, a pad in a footprint
 
VECTOR2< int32_t > VECTOR2I