54static std::unordered_set<const NODE*> allocNodes;
67 allocNodes.insert(
this );
76 wxLogTrace( wxT(
"PNS" ), wxT(
"attempting to free a node that has kids." ) );
81 if( allocNodes.find(
this ) == allocNodes.end() )
83 wxLogTrace( wxT(
"PNS" ), wxT(
"attempting to free an already-free'd node." ) );
87 allocNodes.erase(
this );
92 std::vector<const ITEM*> toDelete;
93 std::vector<const ITEM*> parentedHoles;
95 toDelete.reserve(
m_index->Size() );
99 if( item->BelongsTo(
this ) )
103 HOLE* hole =
static_cast<HOLE*
>( item );
114 parentedHoles.push_back( hole );
120 toDelete.push_back(item);
125 toDelete.push_back(item);
136 for(
const ITEM* item : toDelete )
138 wxLogTrace( wxT(
"PNS" ), wxT(
"del item %p type %s" ), item, item->KindStr().c_str() );
157 int cl =
m_ruleResolver->Clearance( aA, aB, aUseClearanceEpsilon );
187 wxLogTrace( wxT(
"PNS" ), wxT(
"%d items, %d joints, %d overrides" ),
249 if( !aCandidate->
OfKind(
m_ctx->options.m_kindMask ) )
253 if(
m_item == aCandidate )
256 if(
m_ctx->options.m_filter && !
m_ctx->options.m_filter( aCandidate,
m_item ) )
259 if(
visit( aCandidate ) )
265 if(
m_ctx->options.m_limitCount > 0 && (
int)
m_ctx->obstacles.size() >=
m_ctx->options.m_limitCount )
285 assert( allocNodes.find(
this ) != allocNodes.end() );
300 return aObstacles.size();
310 for(
int i = 0; i < aLine->
CLine().SegmentCount(); i++ )
323 if( obstacleSet.empty() )
327 std::vector<OBSTACLE> obstacles( obstacleSet.begin(), obstacleSet.end() );
328 const int numObstacles = (int) obstacles.size();
330 const int layer = aLine->
Layer();
340 BOX2I bbox = cachedHull.BBox();
355 struct ObstacleHullData
361 std::vector<ObstacleHullData> hullData( numObstacles );
363 for(
int i = 0; i < numObstacles; i++ )
365 const OBSTACLE& obstacle = obstacles[i];
368 + aLine->
Width() / 2;
377 +
via.Diameter( aLine->
Layer() ) / 2;
379 hullData[i].viaHull = makeHull( ruleResolver->
HullCache( obstacle.
m_item,
380 viaClearance, 0, layer ) );
385 struct ObstacleResult
391 std::vector<ObstacleResult> results( numObstacles );
394 auto processObstacle = [&](
int i )
396 std::vector<SHAPE_LINE_CHAIN::INTERSECTION> ips;
397 ObstacleResult&
result = results[i];
406 int dist = linePath.
PathLength( ip.p, ip.index_their );
425 int dist = linePath.
PathLength( ip.p, ip.index_their );
440 constexpr int MIN_OBSTACLES_PER_BLOCK = 8;
441 constexpr int PARALLEL_THRESHOLD = MIN_OBSTACLES_PER_BLOCK;
443 if( numObstacles > PARALLEL_THRESHOLD )
446 std::size_t numBlocks = std::max<std::size_t>( 1, numObstacles / MIN_OBSTACLES_PER_BLOCK );
448 auto futures =
tp.submit_loop( 0, numObstacles, [&](
int i ) { processObstacle( i ); },
454 for(
int i = 0; i < numObstacles; i++ )
455 processObstacle( i );
464 for(
int i = 0; i < numObstacles; i++ )
468 nearest = obstacles[i];
472 if( results[i].dist == 0 )
478 nearest = obstacles[0];
515 const LINE* line =
static_cast<const LINE*
>( aItemA );
625 aSolid->SetOwner(
this );
666 switch( aItem->
Kind() )
695 for(
size_t i = 0; i < l.
ArcCount(); i++ )
707 auto newarc = std::make_unique< ARC >( aLine, s );
708 aLine.
Link( newarc.get() );
709 Add( std::move( newarc ),
true );
733 std::unique_ptr<SEGMENT> newseg = std::make_unique<SEGMENT>( aLine, s );
734 aLine.
Link( newseg.get() );
735 Add( std::move( newseg ),
true );
753bool NODE::Add( std::unique_ptr< SEGMENT > aSegment,
bool aAllowRedundant )
755 if( aSegment->Seg().A == aSegment->Seg().B )
757 wxLogTrace( wxT(
"PNS" ),
758 wxT(
"attempting to add a segment with same end coordinates, ignoring." ) );
782bool NODE::Add( std::unique_ptr< ARC > aArc,
bool aAllowRedundant )
807 if( edgeExclusion->Collide( aPos ) )
817 bool holeRemoved =
false;
846 m_root->m_garbageItems.insert( aItem );
885 std::vector<ITEM*> links( aJoint->
LinkList() );
897 auto range =
m_joints.equal_range( tag );
904 for(
auto f = range.first; f != range.second; ++f )
915 bool completelyErased =
false;
922 completelyErased =
true;
931 else if( !completelyErased )
960 add( aNewItem.release() );
967 Add( aNewLine, aAllowRedundantSegments );
1006 switch( aItem->
Kind() )
1032 LINE* l =
static_cast<LINE*
>( aItem );
1044 if(
via->HasHole() )
1047 via->Hole()->SetOwner(
via );
1063 std::vector<LINKED_ITEM*>& segRefs = aLine.
Links();
1082 bool& aGuardHit,
bool aStopAtLockedJoints,
bool aFollowLockedSegments,
1083 bool aAllowSegmentSizeMismatch )
1085 bool prevReversed =
false;
1088 const int startWidth = aCurrent->
Width();
1090 for(
int count = 0 ; ; ++count )
1092 const VECTOR2I p = aCurrent->
Anchor( aScanDirection ^ prevReversed );
1098 aCorners[aPos] = jt->
Pos();
1099 aSegments[aPos] = aCurrent;
1100 aArcReversed[aPos] =
false;
1104 if( ( aScanDirection && jt->
Pos() == aCurrent->
Anchor( 0 ) )
1105 || ( !aScanDirection && jt->
Pos() == aCurrent->
Anchor( 1 ) ) )
1107 aArcReversed[aPos] =
true;
1111 aPos += ( aScanDirection ? 1 : -1 );
1113 if( count && guard == p )
1115 if( aPos >= 0 && aPos < aLimit )
1116 aSegments[aPos] =
nullptr;
1124 if(
locked || aPos < 0 || aPos == aLimit )
1129 if( !
next || ( !aAllowSegmentSizeMismatch &&
next->Width() != startWidth ) )
1133 prevReversed = ( aCurrent && jt->
Pos() == aCurrent->
Anchor( aScanDirection ) );
1139 bool aFollowLockedSegments,
bool aAllowSegmentSizeMismatch )
1141 const int MaxVerts = 1024 * 16;
1143 std::array<VECTOR2I, MaxVerts + 1> corners;
1144 std::array<LINKED_ITEM*, MaxVerts + 1> segs;
1145 std::array<bool, MaxVerts + 1> arcReversed;
1148 bool guardHit =
false;
1150 int i_start = MaxVerts / 2;
1151 int i_end = i_start + 1;
1160 followLine( aSeg,
false, i_start, MaxVerts, corners.data(), segs.data(), arcReversed.data(),
1161 guardHit, aStopAtLockedJoints, aFollowLockedSegments, aAllowSegmentSizeMismatch );
1165 followLine( aSeg,
true, i_end, MaxVerts, corners.data(), segs.data(), arcReversed.data(),
1166 guardHit, aStopAtLockedJoints, aFollowLockedSegments, aAllowSegmentSizeMismatch );
1172 bool originSet =
false;
1176 for(
int i = i_start + 1; i < i_end; i++ )
1184 if( li && prev_seg != li )
1188 const ARC* arc =
static_cast<const ARC*
>( li );
1197 if( li == aSeg && aOriginSegmentIndex && !originSet )
1201 *aOriginSegmentIndex = line.
PointCount() - 1;
1213 if( aOriginSegmentIndex && *aOriginSegmentIndex >= pl.
SegmentCount() )
1216 wxASSERT_MSG( pl.
SegmentCount() != 0,
"assembled line should never be empty" );
1241 JOINT j_start, j_end;
1248 if( id_end < id_start )
1249 std::swap( id_end, id_start );
1251 if( id_start >= 0 && id_end >= 0 )
1254 aLines.push_back( line );
1271 m_index->SetDeferred(
false );
1278 const SEGMENT* locked_seg =
nullptr;
1279 std::vector<VVIA*> vvias;
1283 JOINT joint = jointPair.second;
1292 bool prev_mask =
false;
1293 std::optional<int> prev_mask_margin;
1295 bool is_width_change =
false;
1296 bool is_locked =
false;
1312 std::optional<int> mask_margin;
1316 mask = track->HasSolderMask();
1317 mask_margin = track->GetLocalSolderMaskMargin();
1324 prev_mask_margin = mask_margin;
1326 else if( w != prev_w || mask != prev_mask || mask_margin != prev_mask_margin )
1328 is_width_change =
true;
1331 max_w = std::max( w, max_w );
1334 is_locked = t->IsLocked();
1339 if( ( is_width_change || n_seg >= 3 || is_locked ) && n_solid == 0 && n_vias == 0 )
1349 const VECTOR2I& secondPos = ( locked_seg->
Seg().A == joint.
Pos() ) ?
1350 locked_seg->
Seg().
B :
1351 locked_seg->
Seg().
A;
1358 for(
auto vvia : vvias )
1377 f =
m_root->m_joints.find( tag );
1382 if( f->second.Pos() == aPos && f->second.Net() == aNet && f->second.Layers().Overlaps( aLayer ) )
1407 JOINT_MAP::iterator f =
m_joints.find( tag );
1409 std::pair<JOINT_MAP::iterator, JOINT_MAP::iterator> range;
1414 range =
m_root->m_joints.equal_range( tag );
1416 for( f = range.first; f != range.second; ++f )
1421 JOINT jt( aPos, aLayers, aNet );
1428 range =
m_joints.equal_range( tag );
1430 if( range.first ==
m_joints.end() )
1433 for( f = range.first; f != range.second; ++f )
1435 if( aLayers.
Overlaps( f->second.Layers() ) )
1437 jt.
Merge( f->second );
1451 wxLogTrace( wxT(
"PNS" ), wxT(
"joint layers %d-%d, net %d, pos %s, links: %d" ),
1455 m_tag.pos.Format().c_str(),
1482 std::unordered_set<SEGMENT*> all_segs;
1485 for( i = m_items.begin(); i != m_items.end(); i++ )
1488 all_segs.insert(
static_cast<SEGMENT*
>( *i ) );
1493 for( i =
m_root->m_items.begin(); i !=
m_root->m_items.end(); i++ )
1496 all_segs.insert(
static_cast<SEGMENT*
>(*i) );
1500 JOINT_MAP::iterator j;
1506 wxLogTrace( wxT(
"PNS" ), wxT(
"joint : %s, links : %d\n" ),
1507 j->second.GetPos().Format().c_str(), j->second.LinkCount() );
1508 JOINT::LINKED_ITEMS::const_iterator k;
1510 for( k = j->second.GetLinkList().begin(); k != j->second.GetLinkList().end(); ++k )
1512 const ITEM* m_item = *k;
1514 switch( m_item->GetKind() )
1519 wxLogTrace( wxT(
"PNS" ), wxT(
" -> seg %s %s\n" ),
1520 seg->GetSeg().A.
Format().c_str(),
1521 seg->GetSeg().B.
Format().c_str() );
1532 int lines_count = 0;
1534 while( !all_segs.empty() )
1536 SEGMENT* s = *all_segs.begin();
1539 LINE::LinkedSegments* seg_refs = l->GetLinkedSegments();
1543 wxLogTrace( wxT(
"PNS" ), wxT(
"Line: %s, net %d " ),
1544 l->GetLine().
Format().c_str(), l->GetNet() );
1547 for( std::vector<SEGMENT*>::iterator j = seg_refs->begin(); j != seg_refs->end(); ++j )
1549 wxLogTrace( wxT(
"PNS" ), wxT(
"%s " ), (*j)->GetSeg().A.Format().c_str() );
1551 if( j + 1 == seg_refs->end() )
1552 wxLogTrace( wxT(
"PNS" ), wxT(
"%s\n" ), (*j)->GetSeg().B.Format().c_str() );
1554 all_segs.erase( *j );
1560 wxLogTrace( wxT(
"PNS" ), wxT(
"Local joints: %d, lines : %d \n" ),
1575 aAdded.reserve(
m_index->Size() );
1578 aRemoved.push_back( item );
1581 aAdded.push_back( item );
1590 for(
NODE* node : kids )
1592 node->releaseChildren();
1603 std::vector<const ITEM*> toDelete;
1606 std::vector<const ITEM*> holes;
1610 if( !item->BelongsTo(
this ) )
1612 toDelete.push_back( item );
1614 if( item->HasHole() )
1615 holes.push_back( item->Hole() );
1625 for(
const ITEM* item : toDelete)
1671 for(
ITEM* item : *l_cur )
1673 if( item->OfKind( aKindMask ) && item->IsRoutable() )
1674 aItems.insert( item );
1684 for(
ITEM* item : *l_root )
1686 if( !
Overrides( item ) && item->OfKind( aKindMask ) && item->IsRoutable() )
1687 aItems.insert( item );
1698 item->SetRank( -1 );
1699 item->Mark( item->Marker() & ~aMarkerMask );
1706 std::vector<ITEM*> garbage;
1710 if( item->Marker() & aMarker )
1711 garbage.emplace_back( item );
1714 for(
ITEM* item : garbage )
1737 && ( ( A == a2 &&
B == b2 ) || ( A == b2 &&
B == a2 ) ) )
1766 ARC* seg2 =
static_cast<ARC*
>( item );
1772 && ( ( A == a2 &&
B == b2 ) || ( A == b2 &&
B == a2 ) ) )
1796 for( JOINT_MAP::value_type& j :
m_joints )
1798 if( !j.second.Layers().Overlaps( aLayerMask ) )
1801 if( aBox.
Contains( j.second.Pos() ) && j.second.LinkCount( aKindMask ) )
1803 aJoints.push_back( &j.second );
1811 for( JOINT_MAP::value_type& j :
m_root->m_joints )
1813 if( !
Overrides( &j.second ) && j.second.Layers().Overlaps( aLayerMask ) )
1815 if( aBox.
Contains( j.second.Pos() ) && j.second.LinkCount( aKindMask ) )
1817 aJoints.push_back( &j.second );
1836 for(
ITEM* item : *l_cur )
1838 if( item->Parent() == aParent )
1850 std::vector<ITEM*> ret;
1854 if( item->Parent() == aParent )
1855 ret.push_back( item );
1873 if( item->Net() == handle.
net && item->Layers().Overlaps(handle.
layers) )
1874 return static_cast<VIA*
>( item );
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
NETINFO_ITEM * GetNet() const
Return NETINFO_ITEM object for a given item.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual bool IsConnected() const
Returns information if the object is derived from BOARD_CONNECTED_ITEM.
constexpr coord_type GetLeft() const
constexpr bool Contains(const Vec &aPoint) const
constexpr coord_type GetRight() const
constexpr coord_type GetTop() const
constexpr coord_type GetBottom() const
@ ROUNDED_90
H/V with filleted corners.
@ MITERED_90
H/V only (90-degree corners)
virtual VECTOR2I Anchor(int n) const override
const SHAPE * Shape(int aLayer) const override
Return the geometrical shape of the item.
ITEM * ParentPadVia() const override
std::list< ITEM * > NET_ITEMS_LIST
int Size() const
Returns number of items stored in the index.
void Add(const LINE &aLine)
std::vector< ITEM * > & Items()
const std::vector< ITEM * > & CItems() const
Base class for PNS router board items.
void SetLayers(const PNS_LAYER_RANGE &aLayers)
virtual const std::string Format() const
virtual void Unmark(int aMarker=-1) const
virtual const SHAPE * Shape(int aLayer) const
Return the geometrical shape of the item.
void SetSourceItem(BOARD_ITEM *aSourceItem)
const PNS_LAYER_RANGE & Layers() const
virtual NET_HANDLE Net() const
PnsKind Kind() const
Return the type (kind) of the item.
void SetNet(NET_HANDLE aNet)
BOARD_ITEM * GetSourceItem() const
virtual void SetRank(int aRank)
virtual int Layer() const
void SetParent(BOARD_ITEM *aParent)
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.
bool OfKind(int aKindMask) const
virtual VECTOR2I Anchor(int n) 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
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
void Lock(bool aLock=true)
void Link(ITEM *aItem)
Link the joint to a given board item (when it's added to the NODE).
LINKED_ITEM * NextSegment(LINKED_ITEM *aCurrent, bool aAllowLockedSegs=false) const
For trivial joints, return the segment adjacent to (aCurrent).
HASH_TAG m_tag
hash tag for unordered_multimap
void Merge(const JOINT &aJoint)
bool Unlink(ITEM *aItem)
Unlink a given board item from the joint (upon its removal from a NODE)
const VECTOR2I & Pos() const
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
void ClipVertexRange(int aStart, int aEnd)
Clip the line to a given range of vertices.
const VECTOR2I & CPoint(int aIdx) const
Return the aIdx-th point of the line.
const SHAPE_LINE_CHAIN & CLine() const
const VECTOR2I & CLastPoint() const
SHAPE_LINE_CHAIN & Line()
Modifiable accessor to the underlying shape.
void SetWidth(int aWidth)
Set line width.
int Width() const
Return line width.
virtual int Width() const
void Link(LINKED_ITEM *aLink)
Add a reference to an item registered in a NODE that is a part of this line.
bool ContainsLink(const LINKED_ITEM *aItem) const
Check if the segment aLink is a part of the line.
std::vector< LINKED_ITEM * > & Links()
Return the list of links from the owning node that constitute this line (or NULL if the line is not l...
virtual void ClearLinks()
Erase the linking information. Used to detach the line from the owning node.
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...
void RemoveByMarker(int aMarker)
NODE * m_root
root node of the whole hierarchy
int FindLinesBetweenJoints(const JOINT &aA, const JOINT &aB, std::vector< LINE > &aLines)
Find all lines between a pair of joints. Used by the loop removal procedure.
void BeginBulkAdd()
Defer spatial index insertion during bulk population.
std::vector< ITEM * > ITEM_VECTOR
int GetClearance(const ITEM *aA, const ITEM *aB, bool aUseClearanceEpsilon=true) const
Return the expected clearance between items a and b.
void addSolid(SOLID *aSeg)
Helpers for adding/removing items.
void Replace(ITEM *aOldItem, std::unique_ptr< ITEM > aNewItem)
Replace an item with another one.
bool Overrides(ITEM *aItem) const
Check if this branch contains an updated version of the m_item from the root branch.
void removeSegmentIndex(SEGMENT *aSeg)
void rebuildJoint(const JOINT *aJoint, const ITEM *aItem)
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.
void addSegment(SEGMENT *aSeg)
std::vector< std::unique_ptr< SHAPE > > m_edgeExclusions
ARC * findRedundantArc(const VECTOR2I &A, const VECTOR2I &B, const PNS_LAYER_RANGE &lr, NET_HANDLE aNet)
JOINT_MAP::value_type TagJointPair
bool QueryEdgeExclusions(const VECTOR2I &aPos) const
void doRemove(ITEM *aItem)
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.
void addHole(HOLE *aHole)
std::optional< OBSTACLE > OPT_OBSTACLE
void unlinkJoint(const VECTOR2I &aPos, const PNS_LAYER_RANGE &aLayers, NET_HANDLE aNet, ITEM *aWhere)
Unlink an item from a joint.
std::unordered_set< ITEM * > m_garbageItems
void Dump(bool aLong=false)
Print the contents and joints structure.
void FindLineEnds(const LINE &aLine, JOINT &aA, JOINT &aB)
Find the joints corresponding to the ends of line aLine.
RULE_RESOLVER * GetRuleResolver() const
JOINT & touchJoint(const VECTOR2I &aPos, const PNS_LAYER_RANGE &aLayers, NET_HANDLE aNet)
Try to find matching joint and creates a new one if not found.
bool Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Add an item to the current node.
int QueryJoints(const BOX2I &aBox, std::vector< JOINT * > &aJoints, PNS_LAYER_RANGE aLayerMask=PNS_LAYER_RANGE::All(), int aKindMask=ITEM::ANY_T)
std::set< OBSTACLE > OBSTACLES
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.
INDEX * m_index
Geometric/Net index of the items.
std::unordered_set< ITEM * > m_override
hash of root's items that have been changed in this node
void AllItemsInNet(NET_HANDLE aNet, std::set< ITEM * > &aItems, int aKindMask=-1)
OPT_OBSTACLE NearestObstacle(const LINE *aLine, const COLLISION_SEARCH_OPTIONS &aOpts=COLLISION_SEARCH_OPTIONS())
Follow the line in search of an obstacle that is nearest to the starting to the line's starting point...
void LockJoint(const VECTOR2I &aPos, const ITEM *aItem, bool aLock)
void removeArcIndex(ARC *aVia)
void AddEdgeExclusion(std::unique_ptr< SHAPE > aShape)
int QueryColliding(const ITEM *aItem, OBSTACLES &aObstacles, const COLLISION_SEARCH_OPTIONS &aOpts=COLLISION_SEARCH_OPTIONS()) const
Find items colliding (closer than clearance) with the item aItem.
int m_maxClearance
worst case item-item clearance
VIA * FindViaByHandle(const VIA_HANDLE &handle) const
void removeViaIndex(VIA *aVia)
void add(ITEM *aItem, bool aAllowRedundant=false)
void followLine(LINKED_ITEM *aCurrent, bool aScanDirection, int &aPos, int aLimit, VECTOR2I *aCorners, LINKED_ITEM **aSegments, bool *aArcReversed, bool &aGuardHit, bool aStopAtLockedJoints, bool aFollowLockedSegments, bool aAllowSegmentSizeMismatch)
Scan the joint map, forming a line starting from segment (current).
void KillChildren()
Destroy all child nodes. Applicable only to the root node.
void removeSolidIndex(SOLID *aSeg)
int m_depth
depth of the node (number of parent nodes in the inheritance chain)
std::set< NODE * > m_children
list of nodes branched from this one
ITEM * FindItemByParent(const BOARD_ITEM *aParent)
JOINT_MAP m_joints
hash table with the joints, linking the items.
std::vector< ITEM * > FindItemsByParent(const BOARD_ITEM *aParent)
NODE * m_parent
node this node was branched from
void ClearRanks(int aMarkerMask=MK_HEAD|MK_VIOLATION)
void Remove(ARC *aArc)
Remove an item from this branch.
void Commit(NODE *aNode)
Apply the changes from a given branch (aNode) to the root branch.
RULE_RESOLVER * m_ruleResolver
Design rules resolver.
SEGMENT * findRedundantSegment(const VECTOR2I &A, const VECTOR2I &B, const PNS_LAYER_RANGE &lr, NET_HANDLE aNet)
void linkJoint(const VECTOR2I &aPos, const PNS_LAYER_RANGE &aLayers, NET_HANDLE aNet, ITEM *aWhere)
Touch a joint and links it to an m_item.
void FinalizeBulkAdd()
Build the spatial index from all items added since BeginBulkAdd().
const ITEM_SET HitTest(const VECTOR2I &aPoint) const
Find all items that contain the point aPoint.
OBSTACLE_VISITOR(const ITEM *aItem)
const NODE * m_node
node we are searching in (either root or a branch)
const ITEM * m_item
the item we are looking for collisions with
bool visit(ITEM *aCandidate)
std::optional< int > m_layerContext
void SetWorld(const NODE *aNode, const NODE *aOverride=nullptr)
const NODE * m_override
node that overrides root entries
void SetOwner(const ITEM_OWNER *aOwner)
Set the node that owns this item.
bool BelongsTo(const ITEM_OWNER *aNode) const
const ITEM_OWNER * Owner() const
Return the owner of this item, or NULL if there's none.
ROUTING_SETTINGS & Settings()
static ROUTER * GetInstance()
DIRECTION_45::CORNER_MODE GetCornerMode() const
virtual const SHAPE_LINE_CHAIN & HullCache(const ITEM *aItem, int aClearance, int aWalkaroundThickness, int aLayer)
virtual const std::string Format() const override
virtual bool HasHole() const override
virtual HOLE * Hole() const override
const VECTOR2I & Pos() const
const VECTOR2I & Pos() const
virtual HOLE * Hole() const override
virtual bool HasHole() const override
Represent a contiguous set of PCB layers.
bool Overlaps(const PNS_LAYER_RANGE &aOther) const
bool IsMultilayer() const
SHAPE_ARC Reversed() const
const VECTOR2I & GetP1() const
const VECTOR2I & GetP0() const
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const SHAPE_ARC & Arc(size_t aArc) const
int PointCount() const
Return the number of points (vertices) in this line chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
int SegmentCount() const
Return the number of segments in this line chain.
int PathLength(const VECTOR2I &aP, int aIndex=-1) const
Compute the walk path length from the beginning of the line chain and the point aP belonging to our l...
void RemoveDuplicatePoints()
Remove the duplicate points 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
int Find(const VECTOR2I &aP, int aThreshold=0) const
Search for point aP.
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,...
Push and Shove diff pair dimensions (gap) settings dialog.
std::unique_ptr< T > ItemCast(std::unique_ptr< S > aPtr)
void HullIntersection(const SHAPE_LINE_CHAIN &hull, const SHAPE_LINE_CHAIN &line, std::vector< SHAPE_LINE_CHAIN::INTERSECTION > &ips)
static std::vector< std::string > split(const std::string &aStr, const std::string &aDelim)
Split the input string into a vector of output strings.
std::set< OBSTACLE > & obstacles
bool m_useClearanceEpsilon
bool operator()(ITEM *aItem) override
HIT_VISITOR(ITEM_SET &aTab, const VECTOR2I &aPoint)
Joints are hashed by their position, layers and net.
bool operator()(ITEM *aCandidate) override
COLLISION_SEARCH_CONTEXT * m_ctx
DEFAULT_OBSTACLE_VISITOR(COLLISION_SEARCH_CONTEXT *aCtx, const ITEM *aItem)
virtual ~DEFAULT_OBSTACLE_VISITOR()
Hold an object colliding with another object, along with some useful data about the collision.
int m_distFirst
... and the distance thereof
int m_maxFanoutWidth
worst case (largest) width of the tracks connected to the item
ITEM * m_head
Line we search collisions against.
VECTOR2I m_ipFirst
First intersection between m_head and m_hull.
ITEM * m_item
Item found to be colliding with m_head.
Represent an intersection between two line segments.
wxString result
Test unit parsing edge cases and error handling.
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
BS::priority_thread_pool thread_pool
Casted dyn_cast(From aObject)
A lightweight dynamic downcast.
VECTOR2< int32_t > VECTOR2I