Maintain connectivity while cleaning tracks/vias
When merging segments that loop back on each other, we need to merge them in such a way to to keep the resulting endpoints connected to the original adjoining endpoints Fixes https://gitlab.com/kicad/code/kicad/issues/10780
This commit is contained in:
parent
8b1f1c0296
commit
8e9d44942f
|
@ -464,7 +464,40 @@ bool TRACKS_CLEANER::mergeCollinearSegments( PCB_TRACK* aSeg1, PCB_TRACK* aSeg2
|
|||
if( aSeg1->IsLocked() || aSeg2->IsLocked() )
|
||||
return false;
|
||||
|
||||
auto connectivity = m_brd->GetConnectivity();
|
||||
std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_brd->GetConnectivity();
|
||||
|
||||
std::vector<PCB_TRACK*> tracks = connectivity->GetConnectedTracks( aSeg1 );
|
||||
std::vector<PCB_TRACK*> tracks2 = connectivity->GetConnectedTracks( aSeg2 );
|
||||
|
||||
std::move( tracks2.begin(), tracks2.end(), std::back_inserter( tracks ) );
|
||||
|
||||
tracks.erase(
|
||||
std::remove_if( tracks.begin(), tracks.end(), [ aSeg1, aSeg2 ]( PCB_TRACK* aTest )
|
||||
{
|
||||
return ( aTest == aSeg1 ) || ( aTest == aSeg2 );
|
||||
} ), tracks.end() );
|
||||
|
||||
std::set<VECTOR2I> pts;
|
||||
|
||||
// Collect the unique points where the two tracks are connected to others
|
||||
for( PCB_TRACK* track : tracks )
|
||||
{
|
||||
if( track->IsPointOnEnds( aSeg1->GetStart() ) )
|
||||
pts.emplace( aSeg1->GetStart() );
|
||||
|
||||
if( track->IsPointOnEnds( aSeg1->GetEnd() ) )
|
||||
pts.emplace( aSeg1->GetEnd() );
|
||||
|
||||
if( track->IsPointOnEnds( aSeg2->GetStart() ) )
|
||||
pts.emplace( aSeg2->GetStart() );
|
||||
|
||||
if( track->IsPointOnEnds( aSeg2->GetEnd() ) )
|
||||
pts.emplace( aSeg2->GetEnd() );
|
||||
}
|
||||
|
||||
// This means there is a node in the center
|
||||
if( pts.size() > 2 )
|
||||
return false;
|
||||
|
||||
// Verify the removed point after merging is not a node.
|
||||
// If it is a node (i.e. if more than one other item is connected, the segments cannot be merged
|
||||
|
@ -492,17 +525,19 @@ bool TRACKS_CLEANER::mergeCollinearSegments( PCB_TRACK* aSeg1, PCB_TRACK* aSeg2
|
|||
dummy_seg.SetEnd( wxPoint( max_x, min_y ) );
|
||||
}
|
||||
|
||||
// Now find the removed end(s) and stop merging if it is a node:
|
||||
if( aSeg1->GetStart() != dummy_seg.GetStart() && aSeg1->GetStart() != dummy_seg.GetEnd() )
|
||||
// If the existing connected points are not the same as the points generated by our
|
||||
// min/max alg, then assign the missing points to the end closest. This ensures that
|
||||
// our replacment track is still connected
|
||||
for( auto pt : pts )
|
||||
{
|
||||
if( testTrackEndpointIsNode( aSeg1, true ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
if( aSeg1->GetEnd() != dummy_seg.GetStart() && aSeg1->GetEnd() != dummy_seg.GetEnd() )
|
||||
{
|
||||
if( testTrackEndpointIsNode( aSeg1, false ) )
|
||||
return false;
|
||||
if( !dummy_seg.IsPointOnEnds( wxPoint( pt.x, pt.y ) ) )
|
||||
{
|
||||
if( ( VECTOR2I( dummy_seg.GetStart() ) - pt ).SquaredEuclideanNorm() <
|
||||
( VECTOR2I( dummy_seg.GetEnd() ) - pt ).SquaredEuclideanNorm() )
|
||||
dummy_seg.SetStart( wxPoint( pt.x, pt.y ) );
|
||||
else
|
||||
dummy_seg.SetEnd( wxPoint( pt.x, pt.y ) );
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<CLEANUP_ITEM> item = std::make_shared<CLEANUP_ITEM>( CLEANUP_MERGE_TRACKS );
|
||||
|
|
Loading…
Reference in New Issue