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() );
389 std::set<BOARD_ITEM*> toRemove;
396 if( aDeleteDuplicateVias && track->Type() ==
PCB_VIA_T )
400 if(
via->GetStart() !=
via->GetEnd() )
401 via->SetEnd(
via->GetStart() );
407 return aItem->Type() == PCB_VIA_T
408 && !aItem->HasFlag( SKIP_STRUCT )
409 && !aItem->HasFlag( IS_DELETED );
414 PCB_VIA* other = static_cast<PCB_VIA*>( aItem );
416 if( via->GetPosition() == other->GetPosition()
417 && via->GetViaType() == other->GetViaType()
418 && via->GetLayerSet() == other->GetLayerSet() )
420 auto item = std::make_shared<CLEANUP_ITEM>( CLEANUP_REDUNDANT_VIA );
421 item->SetItems( via );
422 m_itemsList->push_back( std::move( item ) );
424 via->SetFlags( IS_DELETED );
425 toRemove.insert( via );
433 for(
PAD*
pad :
m_brd->GetConnectivity()->GetConnectedPads(
via ) )
437 if( (
pad->GetLayerSet() & all_cu ) == all_cu )
440 item->SetItems(
via,
pad );
444 toRemove.insert(
via );
452 if( aDeleteNullSegments && track->Type() !=
PCB_VIA_T )
454 if( track->IsNull() )
457 item->SetItems( track );
461 toRemove.insert( track );
465 if( aDeleteDuplicateSegments && track->Type() ==
PCB_TRACE_T && !track->IsNull() )
467 rtree.
QueryColliding( track, track->GetLayer(), track->GetLayer(),
471 return aItem->Type() == PCB_TRACE_T
472 && !aItem->HasFlag( SKIP_STRUCT )
473 && !aItem->HasFlag( IS_DELETED )
474 && !static_cast<PCB_TRACK*>( aItem )->IsNull();
479 PCB_TRACK* other = static_cast<PCB_TRACK*>( aItem );
481 if( track->IsPointOnEnds( other->GetStart() )
482 && track->IsPointOnEnds( other->GetEnd() )
483 && track->GetWidth() == other->GetWidth()
484 && track->GetLayer() == other->GetLayer() )
486 auto item = std::make_shared<CLEANUP_ITEM>( CLEANUP_DUPLICATE_TRACK );
487 item->SetItems( track );
488 m_itemsList->push_back( std::move( item ) );
490 track->SetFlags( IS_DELETED );
491 toRemove.insert( track );
502 removeItems( toRemove );
507 auto mergeSegments = [&]( std::shared_ptr<CN_CONNECTIVITY_ALGO> connectivity ) ->
bool
509 auto track_loop = [&](
int aStart,
int aEnd ) -> std::vector<std::pair<PCB_TRACK*, PCB_TRACK*>>
511 std::vector<std::pair<PCB_TRACK*, PCB_TRACK*>> tracks;
513 for(
int ii = aStart; ii < aEnd; ++ii )
515 PCB_TRACK* segment = m_brd->Tracks()[ii];
524 if( filterItem( segment ) )
528 auto& cnItems = connectivity->ItemEntry( segment ).GetItems();
530 for(
CN_ITEM* citem : cnItems )
534 std::vector<PCB_TRACK*> sameWidthCandidates;
535 std::vector<PCB_TRACK*> differentWidthCandidates;
539 if( !connected->Valid() )
545 && !filterItem( candidate ) )
551 sameWidthCandidates.push_back( candidateSegment );
555 differentWidthCandidates.push_back( candidateSegment );
561 if( !differentWidthCandidates.empty() )
564 for(
PCB_TRACK* candidate : sameWidthCandidates )
566 if( candidate < segment )
570 && testMergeCollinearSegments( segment, candidate ) )
572 tracks.emplace_back( segment, candidate );
586 auto merge_returns =
tp.submit_blocks( 0, m_brd->Tracks().size(), track_loop );
589 for(
size_t ii = 0; ii < merge_returns.size(); ++ii )
591 std::future<std::vector<std::pair<PCB_TRACK*, PCB_TRACK*>>>& ret = merge_returns[ii];
595 for(
auto& [seg1, seg2] : ret.get() )
602 mergeCollinearSegments( seg1, seg2 );
614 while( !m_brd->BuildConnectivity() )
620 m_brd->GetConnectivity()->RecalculateRatsnest();
622 std::lock_guard lock( m_mutex );
623 m_connectedItemsCache.clear();
624 }
while( mergeSegments( m_brd->GetConnectivity()->GetConnectivityAlgo() ) );
627 for(
PCB_TRACK* track : m_brd->Tracks() )
650 const unsigned p1s = 1 << 0;
651 const unsigned p1e = 1 << 1;
652 const unsigned p2s = 1 << 2;
653 const unsigned p2e = 1 << 3;
655 std::atomic<unsigned> flags = 0;
657 auto collectPtsSeg1 =
660 if( std::popcount( flags.load() ) > 2 )
676 if( !( flags & p1s ) && citem->HitTest( aSeg1->
GetStart(), ( aSeg1->
GetWidth() + 1 ) / 2 ) )
679 if( !( flags & p1e ) && citem->HitTest( aSeg1->
GetEnd(), ( aSeg1->
GetWidth() + 1 ) / 2 ) )
684 auto collectPtsSeg2 =
687 if( std::popcount( flags.load() ) > 2 )
703 if( !( flags & p2s ) && citem->HitTest( aSeg2->
GetStart(), ( aSeg2->
GetWidth() + 1 ) / 2 ) )
706 if( !( flags & p2e ) && citem->HitTest( aSeg2->
GetEnd(), ( aSeg2->
GetWidth() + 1 ) / 2 ) )
716 if( item != aSeg1 && item != aSeg2 )
717 collectPtsSeg1( item );
725 if( item != aSeg1 && item != aSeg2 )
726 collectPtsSeg2( item );
730 if( std::popcount( flags.load() ) > 2 )
739 aDummySeg = &dummy_seg;
742 int min_x = std::min( aSeg1->
GetStart().
x,
744 int min_y = std::min( aSeg1->
GetStart().
y,
746 int max_x = std::max( aSeg1->
GetStart().
x,
748 int max_y = std::max( aSeg1->
GetStart().
y,
765 for(
unsigned i = 0; i < 4; ++i )
767 if( ( flags & ( 1 << i ) ) && !aDummySeg->
IsPointOnEnds( pts[i] ) )