Ease acquisition of a target item.
pickSingleItem() had a two-attempt algorithm, but the second attempt
was never made because we'd check for no hits before throwing out the
aAvoidItems.
The second attempt would fail anyway because QueryHoverItems() ignored
the aUseClearance flag when not idle, and didn't factor in the actual
clearance.
(cherry picked from commit d040690f60
)
This commit is contained in:
parent
03c3393616
commit
323a2d83fa
|
@ -119,31 +119,43 @@ bool ROUTER::RoutingInProgress() const
|
||||||
|
|
||||||
const ITEM_SET ROUTER::QueryHoverItems( const VECTOR2I& aP, bool aUseClearance )
|
const ITEM_SET ROUTER::QueryHoverItems( const VECTOR2I& aP, bool aUseClearance )
|
||||||
{
|
{
|
||||||
|
NODE* node;
|
||||||
|
int clearance;
|
||||||
|
|
||||||
if( m_state == IDLE || m_placer == nullptr )
|
if( m_state == IDLE || m_placer == nullptr )
|
||||||
{
|
{
|
||||||
if( aUseClearance )
|
node = m_world.get();
|
||||||
{
|
clearance = 0;
|
||||||
SEGMENT test( SEG( aP, aP ), -1 );
|
}
|
||||||
test.SetWidth( 1 );
|
else if( m_mode == PNS_MODE_ROUTE_SINGLE )
|
||||||
test.SetLayers( LAYER_RANGE::All() );
|
{
|
||||||
NODE::OBSTACLES obs;
|
node = m_placer->CurrentNode();
|
||||||
m_world->QueryColliding( &test, obs, ITEM::ANY_T, -1, false );
|
clearance = m_sizes.Clearance() + m_sizes.TrackWidth() / 2;
|
||||||
|
}
|
||||||
|
else if( m_mode == PNS_MODE_ROUTE_DIFF_PAIR )
|
||||||
|
{
|
||||||
|
node = m_placer->CurrentNode();
|
||||||
|
clearance = m_sizes.Clearance() + m_sizes.DiffPairWidth() / 2;
|
||||||
|
}
|
||||||
|
|
||||||
PNS::ITEM_SET ret;
|
if( aUseClearance )
|
||||||
|
{
|
||||||
|
SEGMENT test( SEG( aP, aP ), -1 );
|
||||||
|
test.SetWidth( 1 );
|
||||||
|
test.SetLayers( LAYER_RANGE::All() );
|
||||||
|
NODE::OBSTACLES obs;
|
||||||
|
node->QueryColliding( &test, obs, ITEM::ANY_T, -1, false, clearance );
|
||||||
|
|
||||||
for( OBSTACLE& obstacle : obs )
|
PNS::ITEM_SET ret;
|
||||||
ret.Add( obstacle.m_item, false );
|
|
||||||
|
|
||||||
return ret;
|
for( OBSTACLE& obstacle : obs )
|
||||||
}
|
ret.Add( obstacle.m_item, false );
|
||||||
else
|
|
||||||
{
|
return ret;
|
||||||
return m_world->HitTest( aP );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return m_placer->CurrentNode()->HitTest( aP );
|
return node->HitTest( aP );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,95 +110,108 @@ ITEM* TOOL_BASE::pickSingleItem( const VECTOR2I& aWhere, int aNet, int aLayer, b
|
||||||
dist[i] = VECTOR2I::ECOORD_MAX;
|
dist[i] = VECTOR2I::ECOORD_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
ITEM_SET candidates = m_router->QueryHoverItems( aWhere );
|
auto haveCandidates =
|
||||||
|
[&]()
|
||||||
if( candidates.Empty() )
|
|
||||||
candidates = m_router->QueryHoverItems( aWhere, true );
|
|
||||||
|
|
||||||
for( ITEM* item : candidates.Items() )
|
|
||||||
{
|
|
||||||
if( !item->IsRoutable() )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if( !IsCopperLayer( item->Layers().Start() ) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if( !m_iface->IsAnyLayerVisible( item->Layers() ) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if( alg::contains( aAvoidItems, item ) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// fixme: this causes flicker with live loop removal...
|
|
||||||
//if( item->Parent() && !item->Parent()->ViewIsVisible() )
|
|
||||||
// continue;
|
|
||||||
|
|
||||||
if( item->OfKind( ITEM::SOLID_T ) && aIgnorePads )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if( aNet <= 0 || item->Net() == aNet )
|
|
||||||
{
|
|
||||||
if( item->OfKind( ITEM::VIA_T | ITEM::SOLID_T ) )
|
|
||||||
{
|
{
|
||||||
SEG::ecoord d = ( item->Shape()->Centre() - aWhere ).SquaredEuclideanNorm();
|
for( ITEM* item : prioritized )
|
||||||
|
|
||||||
if( d < dist[2] )
|
|
||||||
{
|
{
|
||||||
prioritized[2] = item;
|
if( item )
|
||||||
dist[2] = d;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( item->Layers().Overlaps( tl ) && d < dist[0] )
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
for( bool useClearance : { false, true } )
|
||||||
|
{
|
||||||
|
ITEM_SET candidates = m_router->QueryHoverItems( aWhere, useClearance );
|
||||||
|
|
||||||
|
for( ITEM* item : candidates.Items() )
|
||||||
|
{
|
||||||
|
if( !item->IsRoutable() )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( !IsCopperLayer( item->Layers().Start() ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( !m_iface->IsAnyLayerVisible( item->Layers() ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( alg::contains( aAvoidItems, item ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// fixme: this causes flicker with live loop removal...
|
||||||
|
//if( item->Parent() && !item->Parent()->ViewIsVisible() )
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
if( item->OfKind( ITEM::SOLID_T ) && aIgnorePads )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if( aNet <= 0 || item->Net() == aNet )
|
||||||
|
{
|
||||||
|
if( item->OfKind( ITEM::VIA_T | ITEM::SOLID_T ) )
|
||||||
|
{
|
||||||
|
SEG::ecoord d = ( item->Shape()->Centre() - aWhere ).SquaredEuclideanNorm();
|
||||||
|
|
||||||
|
if( d < dist[2] )
|
||||||
|
{
|
||||||
|
prioritized[2] = item;
|
||||||
|
dist[2] = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( item->Layers().Overlaps( tl ) && d < dist[0] )
|
||||||
|
{
|
||||||
|
prioritized[0] = item;
|
||||||
|
dist[0] = d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // ITEM::SEGMENT_T | ITEM::ARC_T
|
||||||
|
{
|
||||||
|
LINKED_ITEM* li = static_cast<LINKED_ITEM*>( item );
|
||||||
|
SEG::ecoord d = std::min( ( li->Anchor( 0 ) - aWhere ).SquaredEuclideanNorm(),
|
||||||
|
( li->Anchor( 1 ) - aWhere ).SquaredEuclideanNorm() );
|
||||||
|
|
||||||
|
if( d < dist[3] )
|
||||||
|
{
|
||||||
|
prioritized[3] = item;
|
||||||
|
dist[3] = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( item->Layers().Overlaps( tl ) && d < dist[1] )
|
||||||
|
{
|
||||||
|
prioritized[1] = item;
|
||||||
|
dist[1] = d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( item->OfKind( ITEM::SOLID_T ) && item->IsFreePad() )
|
||||||
|
{
|
||||||
|
// Allow free pads only when already inside pad
|
||||||
|
if( item->Shape()->Collide( aWhere ) )
|
||||||
{
|
{
|
||||||
prioritized[0] = item;
|
prioritized[0] = item;
|
||||||
dist[0] = d;
|
dist[0] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // ITEM::SEGMENT_T | ITEM::ARC_T
|
else if ( item->Net() == 0 && m_router->Settings().Mode() == RM_MarkObstacles )
|
||||||
{
|
{
|
||||||
LINKED_ITEM* li = static_cast<LINKED_ITEM*>( item );
|
// Allow unconnected items as last resort in RM_MarkObstacles mode
|
||||||
SEG::ecoord d = std::min( ( li->Anchor( 0 ) - aWhere ).SquaredEuclideanNorm(),
|
if( item->Layers().Overlaps( tl ) )
|
||||||
( li->Anchor( 1 ) - aWhere ).SquaredEuclideanNorm() );
|
prioritized[4] = item;
|
||||||
|
|
||||||
if( d < dist[3] )
|
|
||||||
{
|
|
||||||
prioritized[3] = item;
|
|
||||||
dist[3] = d;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( item->Layers().Overlaps( tl ) && d < dist[1] )
|
|
||||||
{
|
|
||||||
prioritized[1] = item;
|
|
||||||
dist[1] = d;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( item->OfKind( ITEM::SOLID_T ) && item->IsFreePad() )
|
|
||||||
{
|
if( haveCandidates() )
|
||||||
// Allow free pads only when already inside pad
|
break;
|
||||||
if( item->Shape()->Collide( aWhere ) )
|
|
||||||
{
|
|
||||||
prioritized[0] = item;
|
|
||||||
dist[0] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( item->Net() == 0 && m_router->Settings().Mode() == RM_MarkObstacles )
|
|
||||||
{
|
|
||||||
// Allow unconnected items as last resort in RM_MarkObstacles mode
|
|
||||||
if( item->Layers().Overlaps( tl ) )
|
|
||||||
prioritized[4] = item;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ITEM* rv = nullptr;
|
ITEM* rv = nullptr;
|
||||||
|
|
||||||
bool highContrast = ( frame()->GetDisplayOptions().m_ContrastModeDisplay != HIGH_CONTRAST_MODE::NORMAL );
|
bool highContrast = ( frame()->GetDisplayOptions().m_ContrastModeDisplay != HIGH_CONTRAST_MODE::NORMAL );
|
||||||
|
|
||||||
for( int i = 0; i < candidateCount; i++ )
|
for( ITEM* item : prioritized )
|
||||||
{
|
{
|
||||||
ITEM* item = prioritized[i];
|
|
||||||
|
|
||||||
if( highContrast && item && !item->Layers().Overlaps( tl ) )
|
if( highContrast && item && !item->Layers().Overlaps( tl ) )
|
||||||
item = nullptr;
|
item = nullptr;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue