Use view's RTree for redrawing netnames.

This commit is contained in:
Jeff Young 2024-06-14 00:20:37 +01:00
parent c9ddcd618d
commit 7fef6e8d83
6 changed files with 75 additions and 115 deletions

View File

@ -399,35 +399,19 @@ void VIEW::SetRequired( int aLayerId, int aRequiredId, bool aRequired )
}
// stupid C++... python lambda would do this in one line
template <class CONTAINER>
struct QUERY_VISITOR
{
typedef typename CONTAINER::value_type item_type;
QUERY_VISITOR( CONTAINER& aCont, int aLayer ) :
m_cont( aCont ), m_layer( aLayer )
{
}
bool operator()( VIEW_ITEM* aItem )
{
if( aItem->viewPrivData()->GetFlags() & VISIBLE )
m_cont.push_back( VIEW::LAYER_ITEM_PAIR( aItem, m_layer ) );
return true;
}
CONTAINER& m_cont;
int m_layer;
};
int VIEW::Query( const BOX2I& aRect, std::vector<LAYER_ITEM_PAIR>& aResult ) const
{
if( m_orderedLayers.empty() )
return 0;
int layer = UNDEFINED_LAYER;
auto visitor =
[&]( VIEW_ITEM* item ) -> bool
{
aResult.push_back( VIEW::LAYER_ITEM_PAIR( item, layer ) );
return true;
};
std::vector<VIEW_LAYER*>::const_reverse_iterator i;
// execute queries in reverse direction, so that items that are on the top of
@ -438,7 +422,7 @@ int VIEW::Query( const BOX2I& aRect, std::vector<LAYER_ITEM_PAIR>& aResult ) con
if( ( *i )->displayOnly || !( *i )->visible )
continue;
QUERY_VISITOR<std::vector<LAYER_ITEM_PAIR> > visitor( aResult, ( *i )->id );
layer = ( *i )->id;
( *i )->items->Query( aRect, visitor );
}
@ -446,6 +430,22 @@ int VIEW::Query( const BOX2I& aRect, std::vector<LAYER_ITEM_PAIR>& aResult ) con
}
void VIEW::Query( const BOX2I& aRect, const std::function<bool( VIEW_ITEM* )>& aFunc ) const
{
if( m_orderedLayers.empty() )
return;
for( const auto& i : m_orderedLayers )
{
// ignore layers that do not contain actual items (i.e. the selection box, menus, floats)
if( i->displayOnly || !i->visible )
continue;
i->items->Query( aRect, aFunc );
}
}
VECTOR2D VIEW::ToWorld( const VECTOR2D& aCoord, bool aAbsolute ) const
{
const MATRIX3x3D& matrix = m_gal->GetScreenWorldMatrix();

View File

@ -108,13 +108,19 @@ public:
/**
* Find all visible items that touch or are within the rectangle \a aRect.
*
* @param aRect area to search for items
* @param aResult result of the search, containing VIEW_ITEMs associated with their layers.
* Sorted according to the rendering order (items that are on top of the
* rendering stack as first).
* @return Number of found items.
*/
virtual int Query( const BOX2I& aRect, std::vector<LAYER_ITEM_PAIR>& aResult ) const;
int Query( const BOX2I& aRect, std::vector<LAYER_ITEM_PAIR>& aResult ) const;
/**
* Run a function on all visible items that touch or are within the rectangle \a aRect.
*
* @param aFunc the function to be executed; return true to continue, false to end query.
*/
void Query( const BOX2I& aRect, const std::function<bool( VIEW_ITEM* )>& aFunc ) const;
/**
* Set the item visibility.

View File

@ -579,6 +579,15 @@ BOARD_ITEM_CONTAINER* PCB_EDIT_FRAME::GetModel() const
void PCB_EDIT_FRAME::redrawNetnames()
{
/*
* While new items being scrolled into the view will get painted, they will only get
* annotated with netname instances currently within the view. Subsequent panning will not
* draw newly-visible netname instances because the item has already been drawn.
*
* This routine, fired on idle if the viewport has changed, looks for visible items that
* might have multiple netname instances and redraws them. (It does not need to handle pads
* and vias because they only ever have a single netname instance drawn on them.)
*/
PCBNEW_SETTINGS* cfg = dynamic_cast<PCBNEW_SETTINGS*>( Kiface().KifaceSettings() );
if( !cfg || cfg->m_Display.m_NetNames < 2 )
@ -586,46 +595,24 @@ void PCB_EDIT_FRAME::redrawNetnames()
KIGFX::VIEW* view = GetCanvas()->GetView();
BOX2D viewport = view->GetViewport();
int maxCount = 200;
int count = 0;
double scale = view->GetScale();
m_lastNetnamesViewport = viewport;
// Inflate to catch most of the track width
BOX2I_MINMAX clipbox( BOX2ISafe( viewport.Inflate( pcbIUScale.mmToIU( 2.0 ) ) ) );
PCB_LAYER_ID activeLayer =
GetDisplayOptions().m_ContrastModeDisplay != HIGH_CONTRAST_MODE::NORMAL
? GetActiveLayer()
: UNDEFINED_LAYER;
for( PCB_TRACK* track : GetBoard()->Tracks() )
{
// Don't need to update vias
if( track->Type() == PCB_VIA_T )
continue;
// Don't update invisible tracks
if( !clipbox.Intersects( BOX2I_MINMAX( track->GetStart(), track->GetEnd() ) ) )
continue;
if( track->ViewGetLOD( GetNetnameLayer( track->GetLayer() ), view ) < view->GetScale() )
{
if( viewport != track->GetCachedViewport() )
view->Query( BOX2ISafe( viewport ),
[&]( KIGFX::VIEW_ITEM* viewItem ) -> bool
{
if( ++count > maxCount )
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( viewItem );
if( item->IsConnected()
&& ( item->Type() == PCB_TRACE_T || item->Type() == PCB_SHAPE_T )
&& item->ViewGetLOD( GetNetnameLayer( item->GetLayer() ), view ) < scale )
{
// We've used up enough time for now. Zero out m_lastNetnamesViewport so
// the idle handler will give us another crack at it.
m_lastNetnamesViewport = BOX2D();
break;
view->Update( item, KIGFX::REPAINT );
}
view->Update( track, KIGFX::REPAINT );
track->SetCachedViewport( viewport );
}
}
}
return true;
} );
}

View File

@ -121,7 +121,6 @@ PCB_VIA& PCB_VIA::operator=( const PCB_VIA &aOther )
m_Width = aOther.m_Width;
m_Start = aOther.m_Start;
m_End = aOther.m_End;
m_CachedViewport = aOther.m_CachedViewport;
m_viaType = aOther.m_viaType;
m_padStack = aOther.m_padStack;

View File

@ -219,24 +219,6 @@ public:
return true;
}
/**
* @return last viewport used to render track net names.
*/
BOX2D GetCachedViewport()
{
return m_CachedViewport;
}
/**
* Set the cached viewport used to render track net names.
*
* @param aViewport
*/
void SetCachedViewport( const BOX2D& aViewport )
{
m_CachedViewport = aViewport;
}
virtual double Similarity( const BOARD_ITEM& aOther ) const override;
virtual bool operator==( const BOARD_ITEM& aOther ) const override;
@ -261,11 +243,9 @@ protected:
std::vector<MSG_PANEL_ITEM>& aList ) const;
protected:
int m_Width; ///< Thickness of track, or via diameter
VECTOR2I m_Start; ///< Line start point
VECTOR2I m_End; ///< Line end point
BOX2D m_CachedViewport; ///> Last viewport used to draw this track's net
int m_Width; ///< Thickness of track, or via diameter
VECTOR2I m_Start; ///< Line start point
VECTOR2I m_End; ///< Line end point
};

View File

@ -1244,29 +1244,22 @@ int PCB_SELECTION_TOOL::ClearSelection( const TOOL_EVENT& aEvent )
int PCB_SELECTION_TOOL::SelectAll( const TOOL_EVENT& aEvent )
{
KIGFX::VIEW* view = getView();
// hold all visible items
std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
// Filter the view items based on the selection box
BOX2I selectionBox;
// Intermediate step to allow filtering against hierarchy
GENERAL_COLLECTOR collection;
BOX2I selectionBox;
selectionBox.SetMaximum();
view->Query( selectionBox, selectedItems ); // Get the list of selected items
for( const KIGFX::VIEW::LAYER_ITEM_PAIR& item_pair : selectedItems )
{
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( item_pair.first );
getView()->Query( selectionBox,
[&]( KIGFX::VIEW_ITEM* viewItem ) -> bool
{
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( viewItem );
if( !item || !Selectable( item ) || !itemPassesFilter( item, true ) )
continue;
if( !item || !Selectable( item ) || !itemPassesFilter( item, true ) )
return true;
collection.Append( item );
}
collection.Append( item );
return true;
} );
FilterCollectorForHierarchy( collection, true );
@ -1283,26 +1276,21 @@ int PCB_SELECTION_TOOL::SelectAll( const TOOL_EVENT& aEvent )
int PCB_SELECTION_TOOL::UnselectAll( const TOOL_EVENT& aEvent )
{
KIGFX::VIEW* view = getView();
// hold all visible items
std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
// Filter the view items based on the selection box
BOX2I selectionBox;
selectionBox.SetMaximum();
view->Query( selectionBox, selectedItems ); // Get the list of selected items
for( const KIGFX::VIEW::LAYER_ITEM_PAIR& item_pair : selectedItems )
{
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( item_pair.first );
getView()->Query( selectionBox,
[&]( KIGFX::VIEW_ITEM* viewItem ) -> bool
{
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( viewItem );
if( !item || !Selectable( item ) )
continue;
if( !item || !Selectable( item ) )
return true;
unselect( item );
}
unselect( item );
return true;
} );
m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );