Fix commit/view handling when dragging arcs
Fixes https://gitlab.com/kicad/code/kicad/-/issues/16145
This commit is contained in:
parent
7e68da7f7f
commit
f0988c3c5d
|
@ -528,8 +528,9 @@ int EDIT_TOOL::DragArcTrack( const TOOL_EVENT& aEvent )
|
|||
|
||||
if( theArc->GetAngle() + maxTangentDeviation >= ANGLE_180 )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Unable to resize arc tracks of %s or greater." ),
|
||||
EDA_UNIT_UTILS::UI::MessageTextFromValue( ANGLE_180 - maxTangentDeviation ) );
|
||||
wxString msg = wxString::Format(
|
||||
_( "Unable to resize arc tracks of %s or greater." ),
|
||||
EDA_UNIT_UTILS::UI::MessageTextFromValue( ANGLE_180 - maxTangentDeviation ) );
|
||||
frame()->ShowInfoBarError( msg );
|
||||
|
||||
return 0; // don't bother with > 180 degree arcs
|
||||
|
@ -542,8 +543,8 @@ int EDIT_TOOL::DragArcTrack( const TOOL_EVENT& aEvent )
|
|||
controls->ShowCursor( true );
|
||||
controls->SetAutoPan( true );
|
||||
|
||||
BOARD_COMMIT commit( this );
|
||||
bool restore_state = false;
|
||||
BOARD_COMMIT commit( this );
|
||||
bool restore_state = false;
|
||||
|
||||
commit.Modify( theArc );
|
||||
|
||||
|
@ -562,60 +563,61 @@ int EDIT_TOOL::DragArcTrack( const TOOL_EVENT& aEvent )
|
|||
tanEnd.A = *tanIntersect;
|
||||
tanEnd.B = theArc->GetEnd();
|
||||
|
||||
auto getUniqueTrackAtAnchorCollinear =
|
||||
[&]( const VECTOR2I& aAnchor, const SEG& aCollinearSeg ) -> PCB_TRACK*
|
||||
{
|
||||
std::shared_ptr<CONNECTIVITY_DATA> conn = board()->GetConnectivity();
|
||||
std::set<PCB_TRACK*> addedTracks;
|
||||
|
||||
// Allow items at a distance within the width of the arc track
|
||||
int allowedDeviation = theArc->GetWidth();
|
||||
auto getUniqueTrackAtAnchorCollinear = [&]( const VECTOR2I& aAnchor,
|
||||
const SEG& aCollinearSeg ) -> PCB_TRACK*
|
||||
{
|
||||
std::shared_ptr<CONNECTIVITY_DATA> conn = board()->GetConnectivity();
|
||||
|
||||
std::vector<BOARD_CONNECTED_ITEM*> itemsOnAnchor;
|
||||
// Allow items at a distance within the width of the arc track
|
||||
int allowedDeviation = theArc->GetWidth();
|
||||
|
||||
for( int i = 0; i < 3; i++ )
|
||||
{
|
||||
itemsOnAnchor = conn->GetConnectedItemsAtAnchor( theArc, aAnchor,
|
||||
{ PCB_PAD_T, PCB_VIA_T,
|
||||
PCB_TRACE_T, PCB_ARC_T },
|
||||
allowedDeviation );
|
||||
allowedDeviation /= 2;
|
||||
std::vector<BOARD_CONNECTED_ITEM*> itemsOnAnchor;
|
||||
|
||||
if( itemsOnAnchor.size() == 1 )
|
||||
break;
|
||||
}
|
||||
for( int i = 0; i < 3; i++ )
|
||||
{
|
||||
itemsOnAnchor = conn->GetConnectedItemsAtAnchor(
|
||||
theArc, aAnchor, { PCB_PAD_T, PCB_VIA_T, PCB_TRACE_T, PCB_ARC_T },
|
||||
allowedDeviation );
|
||||
allowedDeviation /= 2;
|
||||
|
||||
PCB_TRACK* track = nullptr;
|
||||
if( itemsOnAnchor.size() == 1 )
|
||||
break;
|
||||
}
|
||||
|
||||
if( itemsOnAnchor.size() == 1 && itemsOnAnchor.front()->Type() == PCB_TRACE_T )
|
||||
{
|
||||
track = static_cast<PCB_TRACK*>( itemsOnAnchor.front() );
|
||||
commit.Modify( track );
|
||||
PCB_TRACK* track = nullptr;
|
||||
|
||||
SEG trackSeg( track->GetStart(), track->GetEnd() );
|
||||
if( itemsOnAnchor.size() == 1 && itemsOnAnchor.front()->Type() == PCB_TRACE_T )
|
||||
{
|
||||
track = static_cast<PCB_TRACK*>( itemsOnAnchor.front() );
|
||||
commit.Modify( track );
|
||||
|
||||
// Allow deviations in colinearity as defined in ADVANCED_CFG
|
||||
if( trackSeg.Angle( aCollinearSeg ) > maxTangentDeviation )
|
||||
track = nullptr;
|
||||
}
|
||||
SEG trackSeg( track->GetStart(), track->GetEnd() );
|
||||
|
||||
if( !track )
|
||||
{
|
||||
track = new PCB_TRACK( theArc->GetParent() );
|
||||
track->SetStart( aAnchor );
|
||||
track->SetEnd( aAnchor );
|
||||
track->SetNet( theArc->GetNet() );
|
||||
track->SetLayer( theArc->GetLayer() );
|
||||
track->SetWidth( theArc->GetWidth() );
|
||||
track->SetLocked( theArc->IsLocked() );
|
||||
track->SetFlags( IS_NEW );
|
||||
getView()->Add( track );
|
||||
commit.Added( track );
|
||||
}
|
||||
// Allow deviations in colinearity as defined in ADVANCED_CFG
|
||||
if( trackSeg.Angle( aCollinearSeg ) > maxTangentDeviation )
|
||||
track = nullptr;
|
||||
}
|
||||
|
||||
return track;
|
||||
};
|
||||
if( !track )
|
||||
{
|
||||
track = new PCB_TRACK( theArc->GetParent() );
|
||||
track->SetStart( aAnchor );
|
||||
track->SetEnd( aAnchor );
|
||||
track->SetNet( theArc->GetNet() );
|
||||
track->SetLayer( theArc->GetLayer() );
|
||||
track->SetWidth( theArc->GetWidth() );
|
||||
track->SetLocked( theArc->IsLocked() );
|
||||
track->SetFlags( IS_NEW );
|
||||
getView()->Add( track );
|
||||
addedTracks.insert( track );
|
||||
}
|
||||
|
||||
PCB_TRACK* trackOnStart = getUniqueTrackAtAnchorCollinear( theArc->GetStart(), tanStart);
|
||||
return track;
|
||||
};
|
||||
|
||||
PCB_TRACK* trackOnStart = getUniqueTrackAtAnchorCollinear( theArc->GetStart(), tanStart );
|
||||
PCB_TRACK* trackOnEnd = getUniqueTrackAtAnchorCollinear( theArc->GetEnd(), tanEnd );
|
||||
|
||||
if( trackOnStart->GetLength() != 0 )
|
||||
|
@ -634,14 +636,13 @@ int EDIT_TOOL::DragArcTrack( const TOOL_EVENT& aEvent )
|
|||
if( tanIntersect = tanStart.IntersectLines( tanEnd ); !tanIntersect )
|
||||
return 0;
|
||||
|
||||
auto isTrackStartClosestToArcStart =
|
||||
[&]( PCB_TRACK* aTrack ) -> bool
|
||||
{
|
||||
double trackStartToArcStart = GetLineLength( aTrack->GetStart(), theArc->GetStart() );
|
||||
double trackEndToArcStart = GetLineLength( aTrack->GetEnd(), theArc->GetStart() );
|
||||
auto isTrackStartClosestToArcStart = [&]( PCB_TRACK* aTrack ) -> bool
|
||||
{
|
||||
double trackStartToArcStart = GetLineLength( aTrack->GetStart(), theArc->GetStart() );
|
||||
double trackEndToArcStart = GetLineLength( aTrack->GetEnd(), theArc->GetStart() );
|
||||
|
||||
return trackStartToArcStart < trackEndToArcStart;
|
||||
};
|
||||
return trackStartToArcStart < trackEndToArcStart;
|
||||
};
|
||||
|
||||
bool isStartTrackOnStartPt = isTrackStartClosestToArcStart( trackOnStart );
|
||||
bool isEndTrackOnStartPt = isTrackStartClosestToArcStart( trackOnEnd );
|
||||
|
@ -673,19 +674,18 @@ int EDIT_TOOL::DragArcTrack( const TOOL_EVENT& aEvent )
|
|||
// * *
|
||||
//
|
||||
|
||||
auto getFurthestPointToTanInterstect =
|
||||
[&]( VECTOR2I& aPointA, VECTOR2I& aPointB ) -> VECTOR2I
|
||||
{
|
||||
if( ( aPointA - *tanIntersect ).EuclideanNorm()
|
||||
> ( aPointB - *tanIntersect ).EuclideanNorm() )
|
||||
{
|
||||
return aPointA;
|
||||
}
|
||||
else
|
||||
{
|
||||
return aPointB;
|
||||
}
|
||||
};
|
||||
auto getFurthestPointToTanInterstect = [&]( VECTOR2I& aPointA, VECTOR2I& aPointB ) -> VECTOR2I
|
||||
{
|
||||
if( ( aPointA - *tanIntersect ).EuclideanNorm()
|
||||
> ( aPointB - *tanIntersect ).EuclideanNorm() )
|
||||
{
|
||||
return aPointA;
|
||||
}
|
||||
else
|
||||
{
|
||||
return aPointB;
|
||||
}
|
||||
};
|
||||
|
||||
CIRCLE maxTanCircle;
|
||||
VECTOR2I tanStartPoint = getFurthestPointToTanInterstect( tanStart.A, tanStart.B );
|
||||
|
@ -789,7 +789,7 @@ int EDIT_TOOL::DragArcTrack( const TOOL_EVENT& aEvent )
|
|||
break; // Finish
|
||||
}
|
||||
else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT )
|
||||
|| evt->IsDblClick( BUT_LEFT ) )
|
||||
|| evt->IsDblClick( BUT_LEFT ) )
|
||||
{
|
||||
// Eat mouse-up/-click events that leaked through from the lock dialog
|
||||
if( eatFirstMouseUp && !evt->IsAction( &ACTIONS::cursorClick ) )
|
||||
|
@ -817,19 +817,45 @@ int EDIT_TOOL::DragArcTrack( const TOOL_EVENT& aEvent )
|
|||
|
||||
if( trackOnStart->GetLength() <= maxLengthIU )
|
||||
{
|
||||
commit.Remove( trackOnStart );
|
||||
if( addedTracks.count( trackOnStart ) )
|
||||
{
|
||||
getView()->Remove( trackOnStart );
|
||||
addedTracks.erase( trackOnStart );
|
||||
delete trackOnStart;
|
||||
}
|
||||
else
|
||||
{
|
||||
commit.Remove( trackOnStart );
|
||||
}
|
||||
|
||||
theArc->SetStart( newStart );
|
||||
}
|
||||
|
||||
if( trackOnEnd->GetLength() <= maxLengthIU )
|
||||
{
|
||||
commit.Remove( trackOnEnd );
|
||||
if( addedTracks.count( trackOnEnd ) )
|
||||
{
|
||||
getView()->Remove( trackOnEnd );
|
||||
addedTracks.erase( trackOnEnd );
|
||||
delete trackOnEnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
commit.Remove( trackOnEnd );
|
||||
}
|
||||
|
||||
theArc->SetEnd( newEnd );
|
||||
}
|
||||
|
||||
if( theArc->GetLength() <= 0 )
|
||||
commit.Remove( theArc );
|
||||
|
||||
for( PCB_TRACK* added : addedTracks )
|
||||
{
|
||||
getView()->Remove( added );
|
||||
commit.Add( added );
|
||||
}
|
||||
|
||||
// Should we commit?
|
||||
if( restore_state )
|
||||
commit.Revert();
|
||||
|
|
Loading…
Reference in New Issue