Browse Source

Rewrite EDIT_TOOL::FilletTracks to only carry out the operation when one item is connected to the anchors

Fixes https://gitlab.com/kicad/code/kicad/-/issues/6103
6.0.7
Roberto Fernandez Bautista 5 years ago
committed by Seth Hillbrand
parent
commit
b29cd8e3a1
  1. 104
      pcbnew/tools/edit_tool.cpp

104
pcbnew/tools/edit_tool.cpp

@ -46,7 +46,9 @@
#include <tools/pad_tool.h> #include <tools/pad_tool.h>
#include <pad_naming.h> #include <pad_naming.h>
#include <view/view_controls.h> #include <view/view_controls.h>
#include <connectivity/connectivity_algo.h>
#include <connectivity/connectivity_data.h> #include <connectivity/connectivity_data.h>
#include <connectivity/connectivity_items.h>
#include <confirm.h> #include <confirm.h>
#include <bitmaps.h> #include <bitmaps.h>
#include <cassert> #include <cassert>
@ -747,30 +749,80 @@ int EDIT_TOOL::FilletTracks( const TOOL_EVENT& aEvent )
return 0; return 0;
} }
struct FILLET_OP
{
TRACK* t1;
TRACK* t2;
//If true, start point of track is modified after ARC is added, otherwise the end point:
bool t1Start = true;
bool t2Start = true;
};
std::vector<FILLET_OP> filletOperations;
KICAD_T track_types[] = { PCB_PAD_T, PCB_VIA_T, PCB_TRACE_T, PCB_ARC_T, EOT };
bool operationPerformedOnAtLeastOne = false; bool operationPerformedOnAtLeastOne = false;
bool didOneAttemptFail = false; bool didOneAttemptFail = false;
std::vector<BOARD_ITEM*> itemsToAddToSelection;
std::set<TRACK*> processedTracks;
for( auto it = selection.begin(); it != selection.end(); it++ ) for( auto it = selection.begin(); it != selection.end(); it++ )
{ {
TRACK* track1 = dyn_cast<TRACK*>( *it );
TRACK* track = dyn_cast<TRACK*>( *it );
if( !track1 || track1->Type() != PCB_TRACE_T || track1->IsLocked()
|| track1->GetLength() == 0 )
if( !track || track->Type() != PCB_TRACE_T || track->IsLocked()
|| track->GetLength() == 0 )
{ {
continue; continue;
} }
for( auto it2 = it + 1; it2 != selection.end(); it2++ )
auto processFilletOp =
[&]( bool aStartPoint )
{ {
TRACK* track2 = dyn_cast<TRACK*>( *it2 );
wxPoint anchor = ( aStartPoint ) ? track->GetStart() : track->GetEnd();
if( !track2 || track2->Type() != PCB_TRACE_T || track2->IsLocked()
|| track2->GetLength() == 0 )
std::vector<BOARD_CONNECTED_ITEM*> itemsOnAnchor =
board()->GetConnectivity()->GetConnectedItemsAtAnchor( track, VECTOR2I( anchor ),
track_types );
if( itemsOnAnchor.size() > 0 && selection.Contains( itemsOnAnchor.at( 0 ) )
&& itemsOnAnchor.at( 0 )->Type() == PCB_TRACE_T )
{ {
continue;
TRACK* trackOther = dyn_cast<TRACK*>( itemsOnAnchor.at( 0 ) );
// Make sure we don't fillet the same pair of tracks twice
if( processedTracks.find( trackOther ) == processedTracks.end() )
{
if( itemsOnAnchor.size() == 1 )
{
FILLET_OP filletOp;
filletOp.t1 = track;
filletOp.t2 = trackOther;
filletOp.t1Start = aStartPoint;
filletOp.t2Start = track->IsPointOnEnds( filletOp.t2->GetStart() );
filletOperations.push_back( filletOp );
} }
else
{
// User requested to fillet these two tracks but not possible as there are other
// elements connected at that point
didOneAttemptFail = true;
}
}
}
};
processFilletOp( true ); // on the start point of track
processFilletOp( false ); // on the end point of track
processedTracks.insert( track );
}
std::vector<BOARD_ITEM*> itemsToAddToSelection;
for( FILLET_OP filletOp : filletOperations )
{
TRACK* track1 = filletOp.t1;
TRACK* track2 = filletOp.t2;
bool trackOnStart = track1->IsPointOnEnds( track2->GetStart() ); bool trackOnStart = track1->IsPointOnEnds( track2->GetStart() );
bool trackOnEnd = track1->IsPointOnEnds( track2->GetEnd() ); bool trackOnEnd = track1->IsPointOnEnds( track2->GetEnd() );
@ -790,12 +842,12 @@ int EDIT_TOOL::FilletTracks( const TOOL_EVENT& aEvent )
wxPoint t1newPoint, t2newPoint; wxPoint t1newPoint, t2newPoint;
auto setIfPointOnSeg =
[]( wxPoint& aPointToSet, SEG aSegment, VECTOR2I aVecToTest )
auto setIfPointOnSeg = []( wxPoint& aPointToSet, SEG aSegment, VECTOR2I aVecToTest )
{ {
// Find out if we are within the segment
if( ( aSegment.NearestPoint( aVecToTest ) - aVecToTest ).EuclideanNorm()
< SHAPE_ARC::MIN_PRECISION_IU )
VECTOR2I segToVec = aSegment.NearestPoint( aVecToTest ) - aVecToTest;
// Find out if we are on the segment (minimum precision)
if( segToVec.EuclideanNorm() < SHAPE_ARC::MIN_PRECISION_IU )
{ {
aPointToSet.x = aVecToTest.x; aPointToSet.x = aVecToTest.x;
aPointToSet.y = aVecToTest.y; aPointToSet.y = aVecToTest.y;
@ -830,31 +882,19 @@ int EDIT_TOOL::FilletTracks( const TOOL_EVENT& aEvent )
m_commit->Modify( track1 ); m_commit->Modify( track1 );
m_commit->Modify( track2 ); m_commit->Modify( track2 );
if( track1->GetStart() == track2->GetStart() )
{
if( filletOp.t1Start )
track1->SetStart( t1newPoint ); track1->SetStart( t1newPoint );
track2->SetStart( t2newPoint );
}
else if( track1->GetStart() == track2->GetEnd() )
{
track1->SetStart( t1newPoint );
track2->SetEnd( t2newPoint );
}
else if( track1->GetEnd() == track2->GetEnd() )
{
track1->SetEnd( t1newPoint );
track2->SetEnd( t2newPoint );
}
else else
{
track1->SetEnd( t1newPoint ); track1->SetEnd( t1newPoint );
if( filletOp.t2Start )
track2->SetStart( t2newPoint ); track2->SetStart( t2newPoint );
}
else
track2->SetEnd( t2newPoint );
operationPerformedOnAtLeastOne = true; operationPerformedOnAtLeastOne = true;
} }
} }
}
m_commit->Push( _( "Fillet Tracks" ) ); m_commit->Push( _( "Fillet Tracks" ) );

Loading…
Cancel
Save