183 std::shared_ptr<CONNECTIVITY_DATA> connectivity =
m_brd->GetConnectivity();
185 std::set<BOARD_ITEM *> toRemove;
189 if( segment->IsLocked() ||
filterItem( segment ) )
192 for(
PAD* testedPad : connectivity->GetConnectedPads( segment ) )
194 if( segment->GetNetCode() != testedPad->GetNetCode() )
196 std::shared_ptr<CLEANUP_ITEM> item;
203 item->SetItems( segment );
206 toRemove.insert( segment );
210 for(
PCB_TRACK* testedTrack : connectivity->GetConnectedTracks( segment ) )
212 if( segment->GetNetCode() != testedTrack->GetNetCode() )
214 std::shared_ptr<CLEANUP_ITEM> item;
221 item->SetItems( segment );
224 toRemove.insert( segment );
383 bool aDeleteDuplicateSegments,
bool aMergeSegments )
390 rtree.
Insert( track, track->GetLayer() );
393 std::set<BOARD_ITEM*> toRemove;
400 if( aDeleteDuplicateVias && track->Type() ==
PCB_VIA_T )
404 if(
via->GetStart() !=
via->GetEnd() )
405 via->SetEnd(
via->GetStart() );
411 return aItem->Type() == PCB_VIA_T
412 && !aItem->HasFlag( SKIP_STRUCT )
413 && !aItem->HasFlag( IS_DELETED );
418 PCB_VIA* other = static_cast<PCB_VIA*>( aItem );
420 if( via->GetPosition() == other->GetPosition()
421 && via->GetViaType() == other->GetViaType()
422 && via->GetLayerSet() == other->GetLayerSet() )
424 auto item = std::make_shared<CLEANUP_ITEM>( CLEANUP_REDUNDANT_VIA );
425 item->SetItems( via );
426 m_itemsList->push_back( std::move( item ) );
428 via->SetFlags( IS_DELETED );
429 toRemove.insert( via );
437 for(
PAD*
pad :
m_brd->GetConnectivity()->GetConnectedPads(
via ) )
441 if( (
pad->GetLayerSet() & all_cu ) == all_cu )
444 item->SetItems(
via,
pad );
448 toRemove.insert(
via );
456 if( aDeleteNullSegments && track->Type() !=
PCB_VIA_T )
458 if( track->IsNull() )
461 item->SetItems( track );
465 toRemove.insert( track );
469 if( aDeleteDuplicateSegments && track->Type() ==
PCB_TRACE_T && !track->IsNull() )
471 rtree.
QueryColliding( track, track->GetLayer(), track->GetLayer(),
475 return aItem->Type() == PCB_TRACE_T
476 && !aItem->HasFlag( SKIP_STRUCT )
477 && !aItem->HasFlag( IS_DELETED )
478 && !static_cast<PCB_TRACK*>( aItem )->IsNull();
483 PCB_TRACK* other = static_cast<PCB_TRACK*>( aItem );
485 if( track->IsPointOnEnds( other->GetStart() )
486 && track->IsPointOnEnds( other->GetEnd() )
487 && track->GetWidth() == other->GetWidth()
488 && track->GetLayer() == other->GetLayer() )
490 auto item = std::make_shared<CLEANUP_ITEM>( CLEANUP_DUPLICATE_TRACK );
491 item->SetItems( track );
492 m_itemsList->push_back( std::move( item ) );
494 track->SetFlags( IS_DELETED );
495 toRemove.insert( track );
506 removeItems( toRemove );
511 auto mergeSegments = [&]( std::shared_ptr<CN_CONNECTIVITY_ALGO> connectivity ) ->
bool
513 auto track_loop = [&](
int aStart,
int aEnd ) -> std::vector<std::pair<PCB_TRACK*, PCB_TRACK*>>
515 std::vector<std::pair<PCB_TRACK*, PCB_TRACK*>> tracks;
517 for(
int ii = aStart; ii < aEnd; ++ii )
519 PCB_TRACK* segment = m_brd->Tracks()[ii];
528 if( filterItem( segment ) )
532 auto& cnItems = connectivity->ItemEntry( segment ).GetItems();
534 for(
CN_ITEM* citem : cnItems )
538 std::vector<PCB_TRACK*> sameWidthCandidates;
539 std::vector<PCB_TRACK*> differentWidthCandidates;
543 if( !connected->Valid() )
549 && !filterItem( candidate ) )
555 sameWidthCandidates.push_back( candidateSegment );
559 differentWidthCandidates.push_back( candidateSegment );
565 if( !differentWidthCandidates.empty() )
568 for(
PCB_TRACK* candidate : sameWidthCandidates )
570 if( candidate < segment )
574 && testMergeCollinearSegments( segment, candidate ) )
576 tracks.emplace_back( segment, candidate );
590 auto merge_returns =
tp.submit_blocks( 0, m_brd->Tracks().size(), track_loop );
593 for(
size_t ii = 0; ii < merge_returns.size(); ++ii )
595 std::future<std::vector<std::pair<PCB_TRACK*, PCB_TRACK*>>>& ret = merge_returns[ii];
599 for(
auto& [seg1, seg2] : ret.get() )
606 mergeCollinearSegments( seg1, seg2 );
618 while( !m_brd->BuildConnectivity() )
624 m_brd->GetConnectivity()->RecalculateRatsnest();
626 std::lock_guard lock( m_mutex );
627 m_connectedItemsCache.clear();
628 }
while( mergeSegments( m_brd->GetConnectivity()->GetConnectivityAlgo() ) );
631 for(
PCB_TRACK* track : m_brd->Tracks() )
654 const unsigned p1s = 1 << 0;
655 const unsigned p1e = 1 << 1;
656 const unsigned p2s = 1 << 2;
657 const unsigned p2e = 1 << 3;
659 std::atomic<unsigned> flags = 0;
661 auto collectPtsSeg1 =
664 if( std::popcount( flags.load() ) > 2 )
680 if( !( flags & p1s ) && citem->HitTest( aSeg1->
GetStart(), ( aSeg1->
GetWidth() + 1 ) / 2 ) )
683 if( !( flags & p1e ) && citem->HitTest( aSeg1->
GetEnd(), ( aSeg1->
GetWidth() + 1 ) / 2 ) )
688 auto collectPtsSeg2 =
691 if( std::popcount( flags.load() ) > 2 )
707 if( !( flags & p2s ) && citem->HitTest( aSeg2->
GetStart(), ( aSeg2->
GetWidth() + 1 ) / 2 ) )
710 if( !( flags & p2e ) && citem->HitTest( aSeg2->
GetEnd(), ( aSeg2->
GetWidth() + 1 ) / 2 ) )
720 if( item != aSeg1 && item != aSeg2 )
721 collectPtsSeg1( item );
729 if( item != aSeg1 && item != aSeg2 )
730 collectPtsSeg2( item );
734 if( std::popcount( flags.load() ) > 2 )
743 aDummySeg = &dummy_seg;
746 int min_x = std::min( aSeg1->
GetStart().
x,
748 int min_y = std::min( aSeg1->
GetStart().
y,
750 int max_x = std::max( aSeg1->
GetStart().
x,
752 int max_y = std::max( aSeg1->
GetStart().
y,
769 for(
unsigned i = 0; i < 4; ++i )
771 if( ( flags & ( 1 << i ) ) && !aDummySeg->
IsPointOnEnds( pts[i] ) )