179 std::shared_ptr<CONNECTIVITY_DATA> connectivity =
m_brd->GetConnectivity();
181 std::set<BOARD_ITEM *> toRemove;
185 if( segment->IsLocked() ||
filterItem( segment ) )
188 for(
PAD* testedPad : connectivity->GetConnectedPads( segment ) )
190 if( segment->GetNetCode() != testedPad->GetNetCode() )
192 std::shared_ptr<CLEANUP_ITEM> item;
199 item->SetItems( segment );
202 toRemove.insert( segment );
206 for(
PCB_TRACK* testedTrack : connectivity->GetConnectedTracks( segment ) )
208 if( segment->GetNetCode() != testedTrack->GetNetCode() )
210 std::shared_ptr<CLEANUP_ITEM> item;
217 item->SetItems( segment );
220 toRemove.insert( segment );
379 bool aDeleteDuplicateSegments,
bool aMergeSegments )
386 rtree.
Insert( track, track->GetLayer() );
391 std::set<BOARD_ITEM*> toRemove;
398 if( aDeleteDuplicateVias && track->Type() ==
PCB_VIA_T )
402 if(
via->GetStart() !=
via->GetEnd() )
403 via->SetEnd(
via->GetStart() );
409 return aItem->Type() == PCB_VIA_T
410 && !aItem->HasFlag( SKIP_STRUCT )
411 && !aItem->HasFlag( IS_DELETED );
416 PCB_VIA* other = static_cast<PCB_VIA*>( aItem );
418 if( via->GetPosition() == other->GetPosition()
419 && via->GetViaType() == other->GetViaType()
420 && via->GetLayerSet() == other->GetLayerSet() )
422 auto item = std::make_shared<CLEANUP_ITEM>( CLEANUP_REDUNDANT_VIA );
423 item->SetItems( via );
424 m_itemsList->push_back( std::move( item ) );
426 via->SetFlags( IS_DELETED );
427 toRemove.insert( via );
435 for(
PAD*
pad :
m_brd->GetConnectivity()->GetConnectedPads(
via ) )
439 if( (
pad->GetLayerSet() & all_cu ) == all_cu )
442 item->SetItems(
via,
pad );
446 toRemove.insert(
via );
454 if( aDeleteNullSegments && track->Type() !=
PCB_VIA_T )
456 if( track->IsNull() )
459 item->SetItems( track );
463 toRemove.insert( track );
467 if( aDeleteDuplicateSegments && track->Type() ==
PCB_TRACE_T && !track->IsNull() )
469 rtree.
QueryColliding( track, track->GetLayer(), track->GetLayer(),
473 return aItem->Type() == PCB_TRACE_T
474 && !aItem->HasFlag( SKIP_STRUCT )
475 && !aItem->HasFlag( IS_DELETED )
476 && !static_cast<PCB_TRACK*>( aItem )->IsNull();
481 PCB_TRACK* other = static_cast<PCB_TRACK*>( aItem );
483 if( track->IsPointOnEnds( other->GetStart() )
484 && track->IsPointOnEnds( other->GetEnd() )
485 && track->GetWidth() == other->GetWidth()
486 && track->GetLayer() == other->GetLayer() )
488 auto item = std::make_shared<CLEANUP_ITEM>( CLEANUP_DUPLICATE_TRACK );
489 item->SetItems( track );
490 m_itemsList->push_back( std::move( item ) );
492 track->SetFlags( IS_DELETED );
493 toRemove.insert( track );
504 removeItems( toRemove );
509 auto mergeSegments = [&]( std::shared_ptr<CN_CONNECTIVITY_ALGO> connectivity ) ->
bool
511 auto track_loop = [&](
int aStart,
int aEnd ) -> std::vector<std::pair<PCB_TRACK*, PCB_TRACK*>>
513 std::vector<std::pair<PCB_TRACK*, PCB_TRACK*>> tracks;
515 for(
int ii = aStart; ii < aEnd; ++ii )
517 PCB_TRACK* segment = m_brd->Tracks()[ii];
526 if( filterItem( segment ) )
530 auto& cnItems = connectivity->ItemEntry( segment ).GetItems();
532 for(
CN_ITEM* citem : cnItems )
536 std::vector<PCB_TRACK*> sameWidthCandidates;
537 std::vector<PCB_TRACK*> differentWidthCandidates;
541 if( !connected->Valid() )
547 && !filterItem( candidate ) )
553 sameWidthCandidates.push_back( candidateSegment );
557 differentWidthCandidates.push_back( candidateSegment );
563 if( !differentWidthCandidates.empty() )
566 for(
PCB_TRACK* candidate : sameWidthCandidates )
568 if( candidate < segment )
572 && testMergeCollinearSegments( segment, candidate ) )
574 tracks.emplace_back( segment, candidate );
588 auto merge_returns =
tp.submit_blocks( 0, m_brd->Tracks().size(), track_loop );
594 std::vector<std::pair<PCB_TRACK*, PCB_TRACK*>> mergePairs;
596 for(
auto& ret : merge_returns )
600 std::vector<std::pair<PCB_TRACK*, PCB_TRACK*>> pairs = ret.get();
601 mergePairs.insert( mergePairs.end(), pairs.begin(), pairs.end() );
605 for(
auto& [seg1, seg2] : mergePairs )
612 mergeCollinearSegments( seg1, seg2 );
622 while( !m_brd->BuildConnectivity() )
628 m_brd->GetConnectivity()->RecalculateRatsnest();
630 std::lock_guard lock( m_mutex );
631 m_connectedItemsCache.clear();
632 }
while( mergeSegments( m_brd->GetConnectivity()->GetConnectivityAlgo() ) );
635 for(
PCB_TRACK* track : m_brd->Tracks() )
658 const unsigned p1s = 1 << 0;
659 const unsigned p1e = 1 << 1;
660 const unsigned p2s = 1 << 2;
661 const unsigned p2e = 1 << 3;
663 std::atomic<unsigned> flags = 0;
665 auto collectPtsSeg1 =
668 if( std::popcount( flags.load() ) > 2 )
684 if( !( flags & p1s ) && citem->HitTest( aSeg1->
GetStart(), ( aSeg1->
GetWidth() + 1 ) / 2 ) )
687 if( !( flags & p1e ) && citem->HitTest( aSeg1->
GetEnd(), ( aSeg1->
GetWidth() + 1 ) / 2 ) )
692 auto collectPtsSeg2 =
695 if( std::popcount( flags.load() ) > 2 )
711 if( !( flags & p2s ) && citem->HitTest( aSeg2->
GetStart(), ( aSeg2->
GetWidth() + 1 ) / 2 ) )
714 if( !( flags & p2e ) && citem->HitTest( aSeg2->
GetEnd(), ( aSeg2->
GetWidth() + 1 ) / 2 ) )
724 if( item != aSeg1 && item != aSeg2 )
725 collectPtsSeg1( item );
733 if( item != aSeg1 && item != aSeg2 )
734 collectPtsSeg2( item );
738 if( std::popcount( flags.load() ) > 2 )
747 aDummySeg = &dummy_seg;
750 int min_x = std::min( aSeg1->
GetStart().
x,
752 int min_y = std::min( aSeg1->
GetStart().
y,
754 int max_x = std::max( aSeg1->
GetStart().
x,
756 int max_y = std::max( aSeg1->
GetStart().
y,
773 for(
unsigned i = 0; i < 4; ++i )
775 if( ( flags & ( 1 << i ) ) && !aDummySeg->
IsPointOnEnds( pts[i] ) )