diff --git a/pcbnew/router/pns_router.cpp b/pcbnew/router/pns_router.cpp index 4766ff0314..f5338b8324 100644 --- a/pcbnew/router/pns_router.cpp +++ b/pcbnew/router/pns_router.cpp @@ -119,31 +119,43 @@ bool ROUTER::RoutingInProgress() const const ITEM_SET ROUTER::QueryHoverItems( const VECTOR2I& aP, bool aUseClearance ) { + NODE* node; + int clearance; + if( m_state == IDLE || m_placer == nullptr ) { - if( aUseClearance ) - { - SEGMENT test( SEG( aP, aP ), -1 ); - test.SetWidth( 1 ); - test.SetLayers( LAYER_RANGE::All() ); - NODE::OBSTACLES obs; - m_world->QueryColliding( &test, obs, ITEM::ANY_T, -1, false ); + node = m_world.get(); + clearance = 0; + } + else if( m_mode == PNS_MODE_ROUTE_SINGLE ) + { + node = m_placer->CurrentNode(); + 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 ) - ret.Add( obstacle.m_item, false ); + PNS::ITEM_SET ret; - return ret; - } - else - { - return m_world->HitTest( aP ); - } + for( OBSTACLE& obstacle : obs ) + ret.Add( obstacle.m_item, false ); + + return ret; } else { - return m_placer->CurrentNode()->HitTest( aP ); + return node->HitTest( aP ); } } diff --git a/pcbnew/router/pns_tool_base.cpp b/pcbnew/router/pns_tool_base.cpp index 2884cf7505..fa309b6957 100644 --- a/pcbnew/router/pns_tool_base.cpp +++ b/pcbnew/router/pns_tool_base.cpp @@ -110,95 +110,108 @@ ITEM* TOOL_BASE::pickSingleItem( const VECTOR2I& aWhere, int aNet, int aLayer, b dist[i] = VECTOR2I::ECOORD_MAX; } - ITEM_SET candidates = m_router->QueryHoverItems( aWhere ); - - 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 ) ) + auto haveCandidates = + [&]() { - SEG::ecoord d = ( item->Shape()->Centre() - aWhere ).SquaredEuclideanNorm(); - - if( d < dist[2] ) + for( ITEM* item : prioritized ) { - prioritized[2] = item; - dist[2] = d; + if( item ) + 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( 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; - 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( 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; - } + // Allow unconnected items as last resort in RM_MarkObstacles mode + if( item->Layers().Overlaps( tl ) ) + prioritized[4] = item; } } - 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; - 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; - } + + if( haveCandidates() ) + break; } ITEM* rv = nullptr; 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 ) ) item = nullptr;