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