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                for( 
CN_ITEM* citem : connectivity->ItemEntry( segment ).GetItems() )
 
  532                    std::vector<PCB_TRACK*> sameWidthCandidates;
 
  533                    std::vector<PCB_TRACK*> differentWidthCandidates;
 
  537                        if( !connected->Valid() )
 
  543                            && !filterItem( candidate ) )
 
  549                                sameWidthCandidates.push_back( candidateSegment );
 
  553                                differentWidthCandidates.push_back( candidateSegment );
 
  559                    if( !differentWidthCandidates.empty() )
 
  562                    for( 
PCB_TRACK* candidate : sameWidthCandidates )
 
  564                        if( candidate < segment ) 
 
  568                            && testMergeCollinearSegments( segment, candidate ) )
 
  570                            tracks.emplace_back( segment, candidate );
 
  584        auto merge_returns = 
tp.submit_blocks( 0, m_brd->Tracks().size(), track_loop );
 
  587        for( 
size_t ii = 0; ii < merge_returns.size(); ++ii )
 
  589            std::future<std::vector<std::pair<PCB_TRACK*, PCB_TRACK*>>>& ret = merge_returns[ii];
 
  593                for( 
auto& [seg1, seg2] : ret.get() )
 
  600                    mergeCollinearSegments( seg1, seg2 );
 
  612            while( !m_brd->BuildConnectivity() )
 
  615            std::lock_guard lock( m_mutex );
 
  616            m_connectedItemsCache.clear();
 
  617        } 
while( mergeSegments( m_brd->GetConnectivity()->GetConnectivityAlgo() ) );
 
  620    for( 
PCB_TRACK* track : m_brd->Tracks() )
 
 
  643    const unsigned p1s = 1 << 0;
 
  644    const unsigned p1e = 1 << 1;
 
  645    const unsigned p2s = 1 << 2;
 
  646    const unsigned p2e = 1 << 3;
 
  648    std::atomic<unsigned> flags = 0;
 
  650    auto collectPtsSeg1 =
 
  653                if( std::popcount( flags.load() ) > 2 )
 
  669                    if( !( flags & p1s ) && citem->HitTest( aSeg1->
GetStart(), ( aSeg1->
GetWidth() + 1 ) / 2 ) )
 
  672                    if( !( flags & p1e ) && citem->HitTest( aSeg1->
GetEnd(), ( aSeg1->
GetWidth() + 1 ) / 2 ) )
 
  677    auto collectPtsSeg2 =
 
  680                if( std::popcount( flags.load() ) > 2 )
 
  696                    if( !( flags & p2s ) && citem->HitTest( aSeg2->
GetStart(), ( aSeg2->
GetWidth() + 1 ) / 2 ) )
 
  699                    if( !( flags & p2e ) && citem->HitTest( aSeg2->
GetEnd(), ( aSeg2->
GetWidth() + 1 ) / 2 ) )
 
  709        if( item != aSeg1 && item != aSeg2 )
 
  710            collectPtsSeg1( item );
 
  718        if( item != aSeg1 && item != aSeg2 )
 
  719            collectPtsSeg2( item );
 
  723    if( std::popcount( flags.load() ) > 2 )
 
  732        aDummySeg = &dummy_seg;
 
  735    int min_x = std::min( aSeg1->
GetStart().
x,
 
  737    int min_y = std::min( aSeg1->
GetStart().
y,
 
  739    int max_x = std::max( aSeg1->
GetStart().
x,
 
  741    int max_y = std::max( aSeg1->
GetStart().
y,
 
  758    for( 
unsigned i = 0; i < 4; ++i )
 
  760        if( ( flags & ( 1 << i ) ) && !aDummySeg->
IsPointOnEnds( pts[i] ) )