48    LINE l = 
m_world->AssembleLine( root, 
nullptr, 
false, 
false, 
false );
 
 
   68    std::deque<const JOINT*> searchQueue;
 
   71    searchQueue.push_back( aStart );
 
   72    processed.insert( aStart );
 
   74    while( !searchQueue.empty() )
 
   76        const JOINT* current = searchQueue.front();
 
   77        searchQueue.pop_front();
 
   83                const JOINT* a = 
m_world->FindJoint( item->Anchor( 0 ), item );;
 
   84                const JOINT* b = 
m_world->FindJoint( item->Anchor( 1 ), item );;
 
   85                const JOINT* 
next = ( *a == *current ) ? b : a;
 
   87                if( processed.find( 
next ) == processed.end() )
 
   89                    processed.insert( 
next );
 
   90                    searchQueue.push_back( 
next );
 
 
  103    LINE track( *aTrack );
 
  109    std::unique_ptr<NODE> tmpNode( 
m_world->Branch() );
 
  112    tmpNode->Add( track );
 
  116    if( !jt || 
m_world->GetRuleResolver()->NetCode( jt->
Net() ) <= 0 )
 
 
  165    std::set<ITEM*> disconnected;
 
  167    m_world->AllItemsInNet( aStart->
Net(), disconnected );
 
  171        for( 
ITEM* link : jt->LinkList() )
 
  173            if( disconnected.find( link ) != disconnected.end() )
 
  174                disconnected.erase( link );
 
  178    int best_dist = INT_MAX;
 
  179    ITEM* best = 
nullptr;
 
  181    for( 
ITEM* item : disconnected )
 
  183        if( item->OfKind( aKindMask ) )
 
  185            for( 
int i = 0; i < item->AnchorCount(); i++ )
 
  188                int d = ( p - aStart->
Pos() ).EuclideanNorm();
 
 
  207                                              std::set<ITEM*>& aVisited,
 
  208                                              bool aFollowLockedSegments )
 
  210    static int depth = 0;
 
  213    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"followBranch[depth=%d]: joint at (%d,%d), prev=%p" ),
 
  214                depth, aJoint->
Pos().
x, aJoint->
Pos().
y, aPrev );
 
  221    for( 
ITEM* link : links )
 
  223        if( link->OfKind( 
ITEM::VIA_T ) && !aVisited.contains( link ) )
 
  228    for( 
ITEM* link : links )
 
  231            && link != aPrev && !aVisited.contains( link ) )
 
  236                                            false, aFollowLockedSegments );
 
  238            wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"followBranch[depth=%d]: branch %d - assembled line with %d segments" ),
 
  243                wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"followBranch[depth=%d]: branch %d - reversing line" ),
 
  244                            depth, branchCount );
 
  251                aVisited.insert( ll );
 
  254                aVisited.insert( 
via );
 
  257            wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"followBranch[depth=%d]: branch %d - line length=%d, recursing..." ),
 
  258                        depth, branchCount, lineLength );
 
  262            wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"followBranch[depth=%d]: branch %d - sub-path returned with length=%d, %d items" ),
 
  274            wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"followBranch[depth=%d]: branch %d - total length=%d (line=%d + sub=%d), best so far=%d" ),
 
  279                wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"followBranch[depth=%d]: branch %d - NEW BEST! Replacing best path" ),
 
  280                            depth, branchCount );
 
  287                aVisited.erase( ll );
 
  290                aVisited.erase( 
via );
 
  296        wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"followBranch[depth=%d]: no branches found, terminal joint" ), depth );
 
  300    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"followBranch[depth=%d]: returning best path with length=%d, %d items" ),
 
 
  307                                      const JOINT** aTerminalJointB,
 
  308                                      bool aFollowLockedSegments )
 
  312    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"=== followTrivialPath START ===" ) );
 
  313    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"followTrivialPath: initial line has %d segments, %zu links" ),
 
  315    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"followTrivialPath: line endpoints: (%d,%d) to (%d,%d)" ),
 
  322    std::set<ITEM*> visited;
 
  325        visited.insert( link );
 
  330    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"followTrivialPath: LEFT branch starting from joint at (%d,%d)" ),
 
  333    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"followTrivialPath: LEFT branch result: length=%d, %d items" ),
 
  334                left.m_length, 
left.m_items.Size() );
 
  336    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"followTrivialPath: RIGHT branch starting from joint at (%d,%d)" ),
 
  339    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"followTrivialPath: RIGHT branch result: length=%d, %d items" ),
 
  342    if( aTerminalJointA )
 
  343        *aTerminalJointA = 
left.m_end;
 
  345    if( aTerminalJointB )
 
  346        *aTerminalJointB = 
right.m_end;
 
  349    int leftSegCount = 0;
 
  350    int rightSegCount = 0;
 
  351    int initialSegCount = 0;
 
  360        path.Prepend( item );
 
  363            LINE* l = 
dynamic_cast<LINE*
>( item );
 
  377            LINE* l = 
dynamic_cast<LINE*
>( item );
 
  388    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"" ) );
 
  389    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"=== followTrivialPath SUMMARY ===" ) );
 
  390    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"Starting segment count: %d" ), initialSegCount );
 
  391    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"Left branch: %d segments, length=%d" ), leftSegCount, 
left.m_length );
 
  392    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"Initial line: %d segments, length=%lld" ), initialSegCount, aLine2->
CLine().
Length() );
 
  393    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"Right branch: %d segments, length=%d" ), rightSegCount, 
right.m_length );
 
  394    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"Total segments in path: %d" ), leftSegCount + initialSegCount + rightSegCount );
 
  395    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"Total path length: %d" ), totalLength );
 
  396    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"Total items in result: %d" ), 
path.Size() );
 
  397    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"=== followTrivialPath END ===" ) );
 
  398    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"" ) );
 
 
  405                                              std::pair<const JOINT*, const JOINT*>* aTerminalJoints,
 
  406                                              bool aFollowLockedSegments )
 
  408    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"*** AssembleTrivialPath: START ***" ) );
 
  409    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"AssembleTrivialPath: aStart=%p, kind=%s" ),
 
  410                aStart, aStart->
KindStr().c_str() );
 
  417        wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"AssembleTrivialPath: starting from VIA" ) );
 
  423            wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"AssembleTrivialPath: VIA is fanout, returning empty" ) );
 
  429        for( 
ITEM* item : links )
 
  434                wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"AssembleTrivialPath: found segment/arc from VIA" ) );
 
  442        wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"AssembleTrivialPath: starting from SEGMENT/ARC" ) );
 
  447        wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"AssembleTrivialPath: no segment found, returning empty" ) );
 
  453    LINE l = 
m_world->AssembleLine( seg, 
nullptr, 
false, aFollowLockedSegments );
 
  455    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"AssembleTrivialPath: assembled line with %d segments, length=%lld" ),
 
  458    const JOINT* jointA = 
nullptr;
 
  459    const JOINT* jointB = 
nullptr;
 
  463    if( aTerminalJoints )
 
  465        wxASSERT( jointA && jointB );
 
  466        *aTerminalJoints = std::make_pair( jointA, jointB );
 
  467        wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"AssembleTrivialPath: terminal joints at (%d,%d) and (%d,%d)" ),
 
  471    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"AssembleTrivialPath: returning path with %d items" ), 
path.Size() );
 
  472    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"*** AssembleTrivialPath: END ***" ) );
 
  473    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"" ) );
 
 
  482    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"" ) );
 
  483    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"########## AssembleTuningPath: START ##########" ) );
 
  484    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"AssembleTuningPath: aStart=%p, kind=%s" ),
 
  485                aStart, aStart->
KindStr().c_str() );
 
  487    std::pair<const JOINT*, const JOINT*> joints;
 
  490    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"AssembleTuningPath: initial path has %d items" ), initialPath.
Size() );
 
  495    auto getPadFromJoint =
 
  496            []( 
const JOINT* aJoint, 
PAD** aTargetPad, 
SOLID** aTargetSolid )
 
  506                            *aTargetPad = 
static_cast<PAD*
>( bi );
 
  509                                *aTargetSolid = 
static_cast<SOLID*
>( item );
 
  519        getPadFromJoint( joints.first, &padA, aStartPad );
 
  521            wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"AssembleTuningPath: found start pad at joint (%d,%d)" ),
 
  522                        joints.first->Pos().x, joints.first->Pos().y );
 
  527        getPadFromJoint( joints.second, &padB, aEndPad );
 
  529            wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"AssembleTuningPath: found end pad at joint (%d,%d)" ),
 
  530                        joints.second->Pos().x, joints.second->Pos().y );
 
  535        wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"AssembleTuningPath: no pads found, returning initial path" ) );
 
  536        wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"########## AssembleTuningPath: END ##########" ) );
 
  537        wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"" ) );
 
  541    auto processPad = [&]( 
PAD* aPad, 
int aLayer )
 
  543        wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"AssembleTuningPath: processing pad, optimizing trace in pad" ) );
 
  544        for( 
int idx = 0; idx < initialPath.
Size(); idx++ )
 
  549            LINE*        line = 
static_cast<LINE*
>( initialPath[idx] );
 
  553            int lengthBefore = slc.
Length();
 
  555            int lengthAfter = slc.
Length();
 
  557            if( lengthBefore != lengthAfter )
 
  558                wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"AssembleTuningPath: optimized line %d, length changed from %d to %d" ),
 
  559                            idx, lengthBefore, lengthAfter );
 
  564        processPad( padA, joints.first->Layer() );
 
  567        processPad( padB, joints.second->Layer() );
 
  572    for( 
int idx = 0; idx < initialPath.
Size(); idx++ )
 
  576            LINE* line = 
static_cast<LINE*
>( initialPath[idx] );
 
  582    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"AssembleTuningPath: final path has %d items, %d lines, total length=%d" ),
 
  583                initialPath.
Size(), lineCount, totalLength );
 
  584    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"########## AssembleTuningPath: END ##########" ) );
 
  585    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"" ) );
 
 
  612    if( !coupledNet || !startItem )
 
  617    std::vector<ITEM*> pItems;
 
  618    std::vector<ITEM*> nItems;
 
  623            pItems.push_back( item );
 
  626    std::set<ITEM*> coupledItems;
 
  627    m_world->AllItemsInNet( coupledNet, coupledItems );
 
  629    for( 
ITEM* item : coupledItems )
 
  632            nItems.push_back( item );
 
  637    SEG::ecoord  minDist_sq = std::numeric_limits<SEG::ecoord>::max();
 
  638    SEG::ecoord  minDistTarget_sq = std::numeric_limits<SEG::ecoord>::max();
 
  641    auto findNItem = [&]( 
ITEM* p_item )
 
  643        for( 
ITEM* n_item : nItems )
 
  645            SEG::ecoord dist_sq = std::numeric_limits<SEG::ecoord>::max();
 
  647            if( n_item->Kind() != p_item->Kind() )
 
  670                const ARC* p_arc = 
static_cast<const ARC*
>( p_item );
 
  671                const ARC* n_arc = 
static_cast<const ARC*
>( n_item );
 
  685            if( dist_sq <= minDist_sq )
 
  687                SEG::ecoord distTarget_sq = n_item->Shape( -1 )->SquaredDistance( targetPoint );
 
  688                if( distTarget_sq < minDistTarget_sq )
 
  690                    minDistTarget_sq = distTarget_sq;
 
  691                    minDist_sq = dist_sq;
 
  700    findNItem( startItem );
 
  705        std::set<ITEM*> linksToTest;
 
  717                    linksToTest.emplace( link );
 
  721        for( 
ITEM* link : linksToTest )
 
  730    if( 
m_world->GetRuleResolver()->DpNetPolarity( refNet ) < 0 )
 
  744        const ARC* refArc = 
static_cast<ARC*
>( refItem );
 
  745        const ARC* coupledArc = 
static_cast<ARC*
>( coupledItem );
 
 
  760    std::deque<ITEM*> pending;
 
  767    pending.push_back( aStart );
 
  770    int64_t initialArea = clusterBBox.
GetArea();
 
  772    while( !pending.empty() )
 
  775        ITEM* top = pending.front();
 
  781        m_world->QueryColliding( top, obstacles, opts ); 
 
  783        for( 
const OBSTACLE& obs : obstacles )
 
  790            if( aExcludedNet && obs.m_item->Net() == aExcludedNet )
 
  796                clusterBBox.
Merge( line.CLine().BBox() );
 
  800                clusterBBox.
Merge( obs.m_item->Shape( aLayer )->BBox() );
 
  803            const int64_t currentArea = clusterBBox.
GetArea();
 
  804            const double areaRatio = (double) currentArea / (
double) ( initialArea + 1 );
 
  806            if( aAreaExpansionLimit > 0.0 && areaRatio > aAreaExpansionLimit )
 
  809            if( cluster.
m_items.find( obs.m_item ) == cluster.
m_items.end() &&
 
  810                obs.m_item->Layers().Overlaps( aLayer ) && !( obs.m_item->Marker() & 
MK_HEAD ) )
 
  812                cluster.
m_items.insert( obs.m_item );
 
  813                pending.push_back( obs.m_item );
 
 
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
 
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
 
constexpr ecoord_type GetArea() const
Return the area of the rectangle.
 
KICAD_T Type() const
Returns the type of object.
 
static void OptimiseTraceInPad(SHAPE_LINE_CHAIN &aLine, const PAD *aPad, PCB_LAYER_ID aPcbLayer)
Optimises the given trace / line to minimise the electrical path length within the given pad.
 
int Width() const override
 
const SHAPE_ARC & CArc() const
 
Basic class for a differential pair.
 
void SetWidth(int aWidth)
 
void Add(const LINE &aLine)
 
Base class for PNS router board items.
 
void SetLayers(const PNS_LAYER_RANGE &aLayers)
 
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.
 
virtual int Layer() const
 
bool OfKind(int aKindMask) const
 
virtual VECTOR2I Anchor(int n) const
 
std::string KindStr() const
 
virtual int AnchorCount() 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
 
NET_HANDLE Net() const override
 
int LinkCount(int aMask=-1) const
 
bool IsNonFanoutVia() const
 
const ITEM_SET & CLinks() const
 
const VECTOR2I & Pos() const
 
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 Reverse()
Clip the line to the nearest obstacle, traversing from the line's start vertex (0).
 
int Width() const
Return true if the line is geometrically identical as line aOther.
 
bool IsLinked() const
Check if the segment aLink is a part of the line.
 
std::vector< LINKED_ITEM * > & Links()
 
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.
 
std::set< OBSTACLE > OBSTACLES
 
virtual PCB_LAYER_ID GetBoardLayerFromPNSLayer(int aLayer) const =0
 
int Width() const override
 
PATH_RESULT followBranch(const JOINT *aJoint, LINKED_ITEM *aPrev, std::set< ITEM * > &aVisited, bool aFollowLockedSegments)
 
ITEM * NearestUnconnectedItem(const JOINT *aStart, int *aAnchor=nullptr, int aKindMask=ITEM::ANY_T)
 
std::set< const JOINT * > JOINT_SET
 
bool LeadingRatLine(const LINE *aTrack, SHAPE_LINE_CHAIN &aRatLine)
 
const DIFF_PAIR AssembleDiffPair(SEGMENT *aStart)
 
ITEM_SET followTrivialPath(LINE *aLine, const JOINT **aTerminalJointA, const JOINT **aTerminalJointB, bool aFollowLockedSegments=false)
 
const ITEM_SET ConnectedItems(const JOINT *aStart, int aKindMask=ITEM::ANY_T)
 
bool NearestUnconnectedAnchorPoint(const LINE *aTrack, VECTOR2I &aPoint, PNS_LAYER_RANGE &aLayers, ITEM *&aItem)
 
const CLUSTER AssembleCluster(ITEM *aStart, int aLayer, double aAreaExpansionLimit=0.0, NET_HANDLE aExcludedNet=nullptr)
 
const JOINT_SET ConnectedJoints(const JOINT *aStart)
 
const ITEM_SET AssembleTuningPath(ROUTER_IFACE *aRouterIface, ITEM *aStart, SOLID **aStartPad=nullptr, SOLID **aEndPad=nullptr)
Like AssembleTrivialPath, but follows the track length algorithm, which discards segments that are fu...
 
const int DP_PARALLELITY_THRESHOLD
 
const ITEM_SET AssembleTrivialPath(ITEM *aStart, std::pair< const JOINT *, const JOINT * > *aTerminalJoints=nullptr, bool aFollowLockedSegments=false)
Assemble a trivial path between two joints given a starting item.
 
bool SimplifyLine(LINE *aLine)
 
Represent a contiguous set of PCB layers.
 
ecoord SquaredDistance(const SEG &aSeg) const
 
VECTOR2I::extended_type ecoord
 
static SEG::ecoord Square(int a)
 
bool ApproxParallel(const SEG &aSeg, int aDistanceThreshold=1) const
 
const VECTOR2I & GetCenter() const
 
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
 
int PointCount() const
Return the number of points (vertices) in this line chain.
 
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.
 
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
 
long long int Length() const
Return length of the line chain in Euclidean metric.
 
virtual VECTOR2I Centre() const
Compute a center-of-mass of the shape.
 
virtual const BOX2I BBox(int aClearance=0) const =0
Compute a bounding box of the shape, with a margin of aClearance a collision.
 
constexpr extended_type Cross(const VECTOR2< T > &aVector) const
Compute cross product of self with aVector.
 
constexpr extended_type SquaredEuclideanNorm() const
Compute the squared euclidean norm of the vector, which is defined as (x ** 2 + y ** 2).
 
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
 
PCB_LAYER_ID
A quick note on layer IDs:
 
Push and Shove diff pair dimensions (gap) settings dialog.
 
bool commonParallelProjection(SEG p, SEG n, SEG &pClip, SEG &nClip)
 
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
 
Hold an object colliding with another object, along with some useful data about the collision.
 
std::set< ITEM * > m_items
 
@ PCB_PAD_T
class PAD, a pad in a footprint
 
VECTOR2< int32_t > VECTOR2I