Further simplify selection logic.

The select-single-wire stuff is no longer needed, and the prefer-wire-ends
stuff needs to be distance-based.

Also improved wire hit-testing to include bubbles the size of the dangling
symbol at each end.

Fixes https://gitlab.com/kicad/code/kicad/issues/9187
This commit is contained in:
Jeff Young 2021-09-21 18:15:41 +01:00
parent 28bd734313
commit ec2ac181a2
3 changed files with 29 additions and 34 deletions

View File

@ -788,7 +788,13 @@ bool SCH_LINE::HitTest( const wxPoint& aPosition, int aAccuracy ) const
else
aAccuracy = abs( aAccuracy );
return TestSegmentHit( aPosition, m_start, m_end, aAccuracy );
if( TestSegmentHit( aPosition, m_start, m_end, aAccuracy ) )
return true;
aAccuracy += Mils2iu( DANGLING_SYMBOL_SIZE );
return ( EuclideanNorm( aPosition - m_start ) < aAccuracy
|| EuclideanNorm( aPosition - m_end ) < aAccuracy );
}

View File

@ -1246,7 +1246,7 @@ void SCH_PAINTER::draw( const LIB_BEZIER *aCurve, int aLayer )
void SCH_PAINTER::drawDanglingSymbol( const wxPoint& aPos, int aWidth, bool aDrawingShadows )
{
wxPoint radius( aWidth + Mils2iu( DANGLING_SYMBOL_SIZE / 2 ),
aWidth + Mils2iu( DANGLING_SYMBOL_SIZE /2 ) );
aWidth + Mils2iu( DANGLING_SYMBOL_SIZE / 2 ) );
m_gal->SetIsStroke( true );
m_gal->SetIsFill( false );

View File

@ -981,9 +981,20 @@ void EE_SELECTION_TOOL::GuessSelectionCandidates( EE_COLLECTOR& collector, const
for( int i = collector.GetCount() - 1; i >= 0; --i )
{
EDA_ITEM* item = collector[ i ];
SCH_LINE* line = dynamic_cast<SCH_LINE*>( item );
if( item->HitTest( (wxPoint) aPos, 0 ) )
exactHits.insert( item );
// Lines are hard to hit. Give them a bit more slop to still be considered "exact".
if( line )
{
if( line->HitTest( (wxPoint) aPos, Mils2iu( DANGLING_SYMBOL_SIZE ) ) )
exactHits.insert( line );
}
else
{
if( item->HitTest( (wxPoint) aPos, 0 ) )
exactHits.insert( item );
}
}
if( exactHits.size() > 0 && exactHits.size() < (unsigned) collector.GetCount() )
@ -992,35 +1003,11 @@ void EE_SELECTION_TOOL::GuessSelectionCandidates( EE_COLLECTOR& collector, const
{
EDA_ITEM* item = collector[ i ];
if( !item->HitTest( (wxPoint) aPos, 0 ) )
if( !exactHits.count( item ) )
collector.Transfer( item );
}
}
// No need for multiple wires at a single point; if there's a junction select that;
// otherwise any of the wires will do
bool junction = false;
bool wiresOnly = true;
for( EDA_ITEM* item : collector )
{
if( item->Type() == SCH_JUNCTION_T )
junction = true;
else if( item->Type() != SCH_LINE_T )
wiresOnly = false;
}
if( wiresOnly )
{
for( int j = collector.GetCount() - 1; j >= 0; --j )
{
if( junction && collector[ j ]->Type() != SCH_JUNCTION_T )
collector.Transfer( j );
else if( !junction && j > 0 )
collector.Transfer( j );
}
}
// Find the closest item. (Note that at this point all hits are either exact or non-exact.)
EDA_ITEM* closest = nullptr;
int closestDist = INT_MAX;
@ -1032,7 +1019,13 @@ void EE_SELECTION_TOOL::GuessSelectionCandidates( EE_COLLECTOR& collector, const
if( exactHits.count( item ) )
{
dist = EuclideanNorm( bbox.GetCenter() - (wxPoint) aPos );
wxPoint pos( aPos );
SCH_LINE* line = dynamic_cast<SCH_LINE*>( item );
if( line )
dist = DistanceLinePoint( line->GetStartPoint(), line->GetEndPoint(), pos );
else
dist = EuclideanNorm( bbox.GetCenter() - pos ) * 2;
}
else
{
@ -1043,10 +1036,6 @@ void EE_SELECTION_TOOL::GuessSelectionCandidates( EE_COLLECTOR& collector, const
if( item->IsType( EE_COLLECTOR::FieldOwners ) )
dist += INT_MAX / 4;
// For wires, if we hit one of the endpoints, consider that perfect
if( item->Type() == SCH_LINE_T && ( item->GetFlags() & ( STARTPOINT | ENDPOINT ) ) )
dist = 0;
if( dist < closestDist )
{
closestDist = dist;