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] ) )