183 std::shared_ptr<CONNECTIVITY_DATA> connectivity =
m_brd->GetConnectivity();
185 std::set<BOARD_ITEM *> toRemove;
189 if( segment->IsLocked() ||
filterItem( segment ) )
192 for(
PAD* testedPad : connectivity->GetConnectedPads( segment ) )
194 if( segment->GetNetCode() != testedPad->GetNetCode() )
196 std::shared_ptr<CLEANUP_ITEM> item;
203 item->SetItems( segment );
206 toRemove.insert( segment );
210 for(
PCB_TRACK* testedTrack : connectivity->GetConnectedTracks( segment ) )
212 if( segment->GetNetCode() != testedTrack->GetNetCode() )
214 std::shared_ptr<CLEANUP_ITEM> item;
221 item->SetItems( segment );
224 toRemove.insert( segment );
383 bool aDeleteDuplicateSegments,
bool aMergeSegments )
390 rtree.
Insert( track, track->GetLayer() );
395 std::set<BOARD_ITEM*> toRemove;
402 if( aDeleteDuplicateVias && track->Type() ==
PCB_VIA_T )
406 if(
via->GetStart() !=
via->GetEnd() )
407 via->SetEnd(
via->GetStart() );
413 return aItem->Type() == PCB_VIA_T
414 && !aItem->HasFlag( SKIP_STRUCT )
415 && !aItem->HasFlag( IS_DELETED );
420 PCB_VIA* other = static_cast<PCB_VIA*>( aItem );
422 if( via->GetPosition() == other->GetPosition()
423 && via->GetViaType() == other->GetViaType()
424 && via->GetLayerSet() == other->GetLayerSet() )
426 auto item = std::make_shared<CLEANUP_ITEM>( CLEANUP_REDUNDANT_VIA );
427 item->SetItems( via );
428 m_itemsList->push_back( std::move( item ) );
430 via->SetFlags( IS_DELETED );
431 toRemove.insert( via );
439 for(
PAD*
pad :
m_brd->GetConnectivity()->GetConnectedPads(
via ) )
443 if( (
pad->GetLayerSet() & all_cu ) == all_cu )
446 item->SetItems(
via,
pad );
450 toRemove.insert(
via );
458 if( aDeleteNullSegments && track->Type() !=
PCB_VIA_T )
460 if( track->IsNull() )
463 item->SetItems( track );
467 toRemove.insert( track );
471 if( aDeleteDuplicateSegments && track->Type() ==
PCB_TRACE_T && !track->IsNull() )
473 rtree.
QueryColliding( track, track->GetLayer(), track->GetLayer(),
477 return aItem->Type() == PCB_TRACE_T
478 && !aItem->HasFlag( SKIP_STRUCT )
479 && !aItem->HasFlag( IS_DELETED )
480 && !static_cast<PCB_TRACK*>( aItem )->IsNull();
485 PCB_TRACK* other = static_cast<PCB_TRACK*>( aItem );
487 if( track->IsPointOnEnds( other->GetStart() )
488 && track->IsPointOnEnds( other->GetEnd() )
489 && track->GetWidth() == other->GetWidth()
490 && track->GetLayer() == other->GetLayer() )
492 auto item = std::make_shared<CLEANUP_ITEM>( CLEANUP_DUPLICATE_TRACK );
493 item->SetItems( track );
494 m_itemsList->push_back( std::move( item ) );
496 track->SetFlags( IS_DELETED );
497 toRemove.insert( track );
508 removeItems( toRemove );
513 auto mergeSegments = [&]( std::shared_ptr<CN_CONNECTIVITY_ALGO> connectivity ) ->
bool
515 auto track_loop = [&](
int aStart,
int aEnd ) -> std::vector<std::pair<PCB_TRACK*, PCB_TRACK*>>
517 std::vector<std::pair<PCB_TRACK*, PCB_TRACK*>> tracks;
519 for(
int ii = aStart; ii < aEnd; ++ii )
521 PCB_TRACK* segment = m_brd->Tracks()[ii];
530 if( filterItem( segment ) )
534 auto& cnItems = connectivity->ItemEntry( segment ).GetItems();
536 for(
CN_ITEM* citem : cnItems )
540 std::vector<PCB_TRACK*> sameWidthCandidates;
541 std::vector<PCB_TRACK*> differentWidthCandidates;
545 if( !connected->Valid() )
551 && !filterItem( candidate ) )
557 sameWidthCandidates.push_back( candidateSegment );
561 differentWidthCandidates.push_back( candidateSegment );
567 if( !differentWidthCandidates.empty() )
570 for(
PCB_TRACK* candidate : sameWidthCandidates )
572 if( candidate < segment )
576 && testMergeCollinearSegments( segment, candidate ) )
578 tracks.emplace_back( segment, candidate );
592 auto merge_returns =
tp.submit_blocks( 0, m_brd->Tracks().size(), track_loop );
595 for(
size_t ii = 0; ii < merge_returns.size(); ++ii )
597 std::future<std::vector<std::pair<PCB_TRACK*, PCB_TRACK*>>>& ret = merge_returns[ii];
601 for(
auto& [seg1, seg2] : ret.get() )
608 mergeCollinearSegments( seg1, seg2 );
620 while( !m_brd->BuildConnectivity() )
626 m_brd->GetConnectivity()->RecalculateRatsnest();
628 std::lock_guard lock( m_mutex );
629 m_connectedItemsCache.clear();
630 }
while( mergeSegments( m_brd->GetConnectivity()->GetConnectivityAlgo() ) );
633 for(
PCB_TRACK* track : m_brd->Tracks() )
656 const unsigned p1s = 1 << 0;
657 const unsigned p1e = 1 << 1;
658 const unsigned p2s = 1 << 2;
659 const unsigned p2e = 1 << 3;
661 std::atomic<unsigned> flags = 0;
663 auto collectPtsSeg1 =
666 if( std::popcount( flags.load() ) > 2 )
682 if( !( flags & p1s ) && citem->HitTest( aSeg1->
GetStart(), ( aSeg1->
GetWidth() + 1 ) / 2 ) )
685 if( !( flags & p1e ) && citem->HitTest( aSeg1->
GetEnd(), ( aSeg1->
GetWidth() + 1 ) / 2 ) )
690 auto collectPtsSeg2 =
693 if( std::popcount( flags.load() ) > 2 )
709 if( !( flags & p2s ) && citem->HitTest( aSeg2->
GetStart(), ( aSeg2->
GetWidth() + 1 ) / 2 ) )
712 if( !( flags & p2e ) && citem->HitTest( aSeg2->
GetEnd(), ( aSeg2->
GetWidth() + 1 ) / 2 ) )
722 if( item != aSeg1 && item != aSeg2 )
723 collectPtsSeg1( item );
731 if( item != aSeg1 && item != aSeg2 )
732 collectPtsSeg2( item );
736 if( std::popcount( flags.load() ) > 2 )
745 aDummySeg = &dummy_seg;
748 int min_x = std::min( aSeg1->
GetStart().
x,
750 int min_y = std::min( aSeg1->
GetStart().
y,
752 int max_x = std::max( aSeg1->
GetStart().
x,
754 int max_y = std::max( aSeg1->
GetStart().
y,
771 for(
unsigned i = 0; i < 4; ++i )
773 if( ( flags & ( 1 << i ) ) && !aDummySeg->
IsPointOnEnds( pts[i] ) )