189 std::shared_ptr<CONNECTIVITY_DATA> connectivity =
m_brd->GetConnectivity();
191 std::set<BOARD_ITEM *> toRemove;
195 if( segment->IsLocked() ||
filterItem( segment ) )
198 for(
PAD* testedPad : connectivity->GetConnectedPads( segment ) )
200 if( segment->GetNetCode() != testedPad->GetNetCode() )
202 std::shared_ptr<CLEANUP_ITEM> item;
209 item->SetItems( segment );
212 toRemove.insert( segment );
216 for(
PCB_TRACK* testedTrack : connectivity->GetConnectedTracks( segment ) )
218 if( segment->GetNetCode() != testedTrack->GetNetCode() )
220 std::shared_ptr<CLEANUP_ITEM> item;
227 item->SetItems( segment );
230 toRemove.insert( segment );
389 bool aDeleteDuplicateSegments,
bool aMergeSegments )
401 std::set<BOARD_ITEM*> toRemove;
408 if( aDeleteDuplicateVias && track->Type() ==
PCB_VIA_T )
412 if(
via->GetStart() !=
via->GetEnd() )
413 via->SetEnd(
via->GetStart() );
419 return aItem->Type() == PCB_VIA_T
420 && !aItem->HasFlag( SKIP_STRUCT )
421 && !aItem->HasFlag( IS_DELETED );
426 PCB_VIA* other = static_cast<PCB_VIA*>( aItem );
428 if( via->GetPosition() == other->GetPosition()
429 && via->GetViaType() == other->GetViaType()
430 && via->GetLayerSet() == other->GetLayerSet() )
432 auto item = std::make_shared<CLEANUP_ITEM>( CLEANUP_REDUNDANT_VIA );
433 item->SetItems( via );
434 m_itemsList->push_back( std::move( item ) );
436 via->SetFlags( IS_DELETED );
437 toRemove.insert( via );
445 for(
PAD*
pad :
m_brd->GetConnectivity()->GetConnectedPads(
via ) )
449 if( (
pad->GetLayerSet() & all_cu ) == all_cu )
452 item->SetItems(
via,
pad );
456 toRemove.insert(
via );
464 if( aDeleteNullSegments && track->Type() !=
PCB_VIA_T )
466 if( track->IsNull() )
469 item->SetItems( track );
473 toRemove.insert( track );
477 if( aDeleteDuplicateSegments && track->Type() ==
PCB_TRACE_T && !track->IsNull() )
479 rtree.
QueryColliding( track, track->GetLayer(), track->GetLayer(),
483 return aItem->Type() == PCB_TRACE_T
484 && !aItem->HasFlag( SKIP_STRUCT )
485 && !aItem->HasFlag( IS_DELETED )
486 && !static_cast<PCB_TRACK*>( aItem )->IsNull();
491 PCB_TRACK* other = static_cast<PCB_TRACK*>( aItem );
493 if( track->IsPointOnEnds( other->GetStart() )
494 && track->IsPointOnEnds( other->GetEnd() )
495 && track->GetWidth() == other->GetWidth()
496 && track->GetLayer() == other->GetLayer() )
498 auto item = std::make_shared<CLEANUP_ITEM>( CLEANUP_DUPLICATE_TRACK );
499 item->SetItems( track );
500 m_itemsList->push_back( std::move( item ) );
502 track->SetFlags( IS_DELETED );
503 toRemove.insert( track );
514 removeItems( toRemove );
519 auto mergeSegments = [&]( std::shared_ptr<CN_CONNECTIVITY_ALGO> connectivity ) ->
bool
521 auto track_loop = [&](
int aStart,
int aEnd ) -> std::vector<std::pair<PCB_TRACK*, PCB_TRACK*>>
523 std::vector<std::pair<PCB_TRACK*, PCB_TRACK*>> tracks;
525 for(
int ii = aStart; ii < aEnd; ++ii )
527 PCB_TRACK* segment = m_brd->Tracks()[ii];
536 if( filterItem( segment ) )
540 auto& cnItems = connectivity->ItemEntry( segment ).GetItems();
542 for(
CN_ITEM* citem : cnItems )
546 std::vector<PCB_TRACK*> sameWidthCandidates;
547 std::vector<PCB_TRACK*> differentWidthCandidates;
551 if( !connected->Valid() )
557 && !filterItem( candidate ) )
563 sameWidthCandidates.push_back( candidateSegment );
567 differentWidthCandidates.push_back( candidateSegment );
573 if( !differentWidthCandidates.empty() )
576 for(
PCB_TRACK* candidate : sameWidthCandidates )
578 if( candidate < segment )
582 && testMergeCollinearSegments( segment, candidate ) )
584 tracks.emplace_back( segment, candidate );
598 auto merge_returns =
tp.submit_blocks( 0, m_brd->Tracks().size(), track_loop );
604 std::vector<std::pair<PCB_TRACK*, PCB_TRACK*>> mergePairs;
606 for(
auto& ret : merge_returns )
610 std::vector<std::pair<PCB_TRACK*, PCB_TRACK*>> pairs = ret.get();
611 mergePairs.insert( mergePairs.end(), pairs.begin(), pairs.end() );
615 for(
auto& [seg1, seg2] : mergePairs )
622 mergeCollinearSegments( seg1, seg2 );
632 while( !m_brd->BuildConnectivity() )
638 m_brd->GetConnectivity()->RecalculateRatsnest();
640 std::lock_guard lock( m_mutex );
641 m_connectedItemsCache.clear();
642 }
while( mergeSegments( m_brd->GetConnectivity()->GetConnectivityAlgo() ) );
645 for(
PCB_TRACK* track : m_brd->Tracks() )
668 const unsigned p1s = 1 << 0;
669 const unsigned p1e = 1 << 1;
670 const unsigned p2s = 1 << 2;
671 const unsigned p2e = 1 << 3;
673 std::atomic<unsigned> flags = 0;
675 auto collectPtsSeg1 =
678 if( std::popcount( flags.load() ) > 2 )
694 if( !( flags & p1s ) && citem->HitTest( aSeg1->
GetStart(), ( aSeg1->
GetWidth() + 1 ) / 2 ) )
697 if( !( flags & p1e ) && citem->HitTest( aSeg1->
GetEnd(), ( aSeg1->
GetWidth() + 1 ) / 2 ) )
702 auto collectPtsSeg2 =
705 if( std::popcount( flags.load() ) > 2 )
721 if( !( flags & p2s ) && citem->HitTest( aSeg2->
GetStart(), ( aSeg2->
GetWidth() + 1 ) / 2 ) )
724 if( !( flags & p2e ) && citem->HitTest( aSeg2->
GetEnd(), ( aSeg2->
GetWidth() + 1 ) / 2 ) )
734 if( item != aSeg1 && item != aSeg2 )
735 collectPtsSeg1( item );
743 if( item != aSeg1 && item != aSeg2 )
744 collectPtsSeg2( item );
748 if( std::popcount( flags.load() ) > 2 )
757 aDummySeg = &dummy_seg;
760 int min_x = std::min( aSeg1->
GetStart().
x,
762 int min_y = std::min( aSeg1->
GetStart().
y,
764 int max_x = std::max( aSeg1->
GetStart().
x,
766 int max_y = std::max( aSeg1->
GetStart().
y,
783 for(
unsigned i = 0; i < 4; ++i )
785 if( ( flags & ( 1 << i ) ) && !aDummySeg->
IsPointOnEnds( pts[i] ) )