From b8b3d5c16dbdf3a9424e7714bb5faaf704b8c0c4 Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Fri, 14 Aug 2020 17:33:27 -0700 Subject: [PATCH] pcbnew: Remove all threading from dynamic ratsnest The last remaining threaded operation in dynamic ratsnest was the recalculation of the dynamic connectivity map. Because we do not require any of the extra features of the connectivity map, we can get away with a lightweight move of the anchors to update the ratsnest. The resulting connectivity tree is not valid but it is not needed for the ratsnest, which only needs a list of nets/anchors. --- pcbnew/connectivity/connectivity_algo.h | 3 - pcbnew/connectivity/connectivity_data.cpp | 30 +++++---- pcbnew/connectivity/connectivity_data.h | 19 +++++- pcbnew/connectivity/connectivity_items.h | 5 ++ pcbnew/tools/edit_tool.cpp | 20 +++--- pcbnew/tools/pcb_inspection_tool.cpp | 81 +++++++++-------------- pcbnew/tools/pcb_inspection_tool.h | 11 +-- 7 files changed, 86 insertions(+), 83 deletions(-) diff --git a/pcbnew/connectivity/connectivity_algo.h b/pcbnew/connectivity/connectivity_algo.h index 6f79ab3e6b..38041194d2 100644 --- a/pcbnew/connectivity/connectivity_algo.h +++ b/pcbnew/connectivity/connectivity_algo.h @@ -167,8 +167,6 @@ private: void searchConnections(); - void update(); - void propagateConnections( BOARD_COMMIT* aCommit = nullptr ); template @@ -281,7 +279,6 @@ public: void MarkNetAsDirty( int aNet ); void SetProgressReporter( PROGRESS_REPORTER* aReporter ); - }; /** diff --git a/pcbnew/connectivity/connectivity_data.cpp b/pcbnew/connectivity/connectivity_data.cpp index f71d9a1fa9..12d6a97ae5 100644 --- a/pcbnew/connectivity/connectivity_data.cpp +++ b/pcbnew/connectivity/connectivity_data.cpp @@ -95,6 +95,12 @@ void CONNECTIVITY_DATA::Build( const std::vector& aItems ) } +void CONNECTIVITY_DATA::Move( const VECTOR2I& aDelta ) +{ + m_connAlgo->ForEachAnchor( [&aDelta] ( CN_ANCHOR& anchor ) { anchor.Move( aDelta ); } ); +} + + void CONNECTIVITY_DATA::updateRatsnest() { #ifdef PROFILE @@ -255,24 +261,19 @@ void CONNECTIVITY_DATA::FindIsolatedCopperIslands( std::vector& aItems ) +void CONNECTIVITY_DATA::ComputeDynamicRatsnest( const std::vector& aItems, + const CONNECTIVITY_DATA* aDynamicData ) { + if( !aDynamicData ) + return; + m_dynamicRatsnest.clear(); - if( std::none_of( aItems.begin(), aItems.end(), []( const BOARD_ITEM* aItem ) - { return( aItem->Type() == PCB_TRACE_T || aItem->Type() == PCB_PAD_T || - aItem->Type() == PCB_ARC_T || aItem->Type() == PCB_ZONE_AREA_T || - aItem->Type() == PCB_MODULE_T || aItem->Type() == PCB_VIA_T ); } ) ) + // This gets connections between the stationary board and the + // moving selection + for( unsigned int nc = 1; nc < aDynamicData->m_nets.size(); nc++ ) { - return ; - } - - CONNECTIVITY_DATA connData( aItems, true ); - BlockRatsnestItems( aItems ); - - for( unsigned int nc = 1; nc < connData.m_nets.size(); nc++ ) - { - auto dynNet = connData.m_nets[nc]; + auto dynNet = aDynamicData->m_nets[nc]; if( dynNet->GetNodeCount() != 0 ) { @@ -291,6 +292,7 @@ void CONNECTIVITY_DATA::ComputeDynamicRatsnest( const std::vector& } } + // This gets the ratsnest for internal connections in the moving set const auto& edges = GetRatsnestForItems( aItems ); for( const auto& edge : edges ) diff --git a/pcbnew/connectivity/connectivity_data.h b/pcbnew/connectivity/connectivity_data.h index 0b44df6396..bd51480f98 100644 --- a/pcbnew/connectivity/connectivity_data.h +++ b/pcbnew/connectivity/connectivity_data.h @@ -125,6 +125,15 @@ public: */ bool Update( BOARD_ITEM* aItem ); + /** + * Moves the connectivity list anchors. N.B., this does not move the bounding + * boxes for the the RTree, so the use of this function will invalidate the + * connectivity data for uses other than the dynamic ratsnest + * + * @param aDelta vector for movement of the tree + */ + void Move( const VECTOR2I& aDelta ); + /** * Function Clear() * Erases the connectivity database. @@ -208,7 +217,8 @@ public: * Calculates the temporary dynamic ratsnest (i.e. the ratsnest lines that) * for the set of items aItems. */ - void ComputeDynamicRatsnest( const std::vector& aItems ); + void ComputeDynamicRatsnest( const std::vector& aItems, + const CONNECTIVITY_DATA* aDynamicData ); const std::vector& GetDynamicRatsnest() const { @@ -257,6 +267,13 @@ public: private: void updateRatsnest(); + + /** + * Updates the item positions without modifying the dirtyNet flag. This is valid only when the + * item list contains all elements in the connectivity database + * @param aItems List of items with new positions + */ + void updateItemPositions( const std::vector& aItems ); void addRatsnestCluster( const std::shared_ptr& aCluster ); std::shared_ptr m_connAlgo; diff --git a/pcbnew/connectivity/connectivity_items.h b/pcbnew/connectivity/connectivity_items.h index f907ff2e13..c19e55ec62 100644 --- a/pcbnew/connectivity/connectivity_items.h +++ b/pcbnew/connectivity/connectivity_items.h @@ -81,6 +81,11 @@ public: return m_pos; } + void Move( const VECTOR2I& aPos ) + { + m_pos += aPos; + } + const unsigned int Dist( const CN_ANCHOR& aSecond ) { return ( m_pos - aSecond.Pos() ).EuclideanNorm(); diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp index 19f1474eba..bf887328a3 100644 --- a/pcbnew/tools/edit_tool.cpp +++ b/pcbnew/tools/edit_tool.cpp @@ -390,6 +390,7 @@ int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference ) // Main loop: keep receiving events do { + VECTOR2I movement; editFrame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW ); grid.SetSnap( !evt->Modifier( MD_SHIFT ) ); grid.SetUseGrid( !evt->Modifier( MD_ALT ) ); @@ -421,7 +422,7 @@ int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference ) controls->ForceCursorPosition( true, m_cursor ); selection.SetReferencePoint( m_cursor ); - VECTOR2I movement( m_cursor - prevPos ); + movement = m_cursor - prevPos; prevPos = m_cursor; totalMovement += movement; @@ -494,7 +495,7 @@ int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference ) // start moving with the reference point attached to the cursor grid.SetAuxAxes( false ); - auto delta = m_cursor - selection.GetReferencePoint(); + movement = m_cursor - selection.GetReferencePoint(); // Drag items to the current cursor position for( EDA_ITEM* item : selection ) @@ -503,7 +504,7 @@ int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference ) if( item->GetParent() && item->GetParent()->IsSelected() ) continue; - static_cast( item )->Move( delta ); + static_cast( item )->Move( movement ); } selection.SetReferencePoint( m_cursor ); @@ -550,7 +551,7 @@ int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference ) } m_toolMgr->PostEvent( EVENTS::SelectedItemsModified ); - m_toolMgr->RunAction( PCB_ACTIONS::updateLocalRatsnest, false ); + m_toolMgr->RunAction( PCB_ACTIONS::updateLocalRatsnest, false, new VECTOR2I( movement ) ); } else if( evt->IsCancelInteractive() || evt->IsActivate() ) @@ -615,14 +616,11 @@ int EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, bool aPickReference ) // If canceled, we need to remove the dynamic ratsnest from the screen if( restore_state ) - { - m_toolMgr->RunAction( PCB_ACTIONS::hideDynamicRatsnest, true ); m_commit->Revert(); - } else - { m_commit->Push( _( "Drag" ) ); - } + + m_toolMgr->RunAction( PCB_ACTIONS::hideDynamicRatsnest, true ); if( unselect ) m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true ); @@ -1292,7 +1290,7 @@ int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent ) }); } } - + item->Move( translation ); switch( rotationAnchor ) @@ -1407,7 +1405,7 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent ) case PCB_GROUP_T: dupe_item = static_cast( orig_item )->DeepDuplicate(); break; - + default: // Silently drop other items (such as footprint texts) from duplication break; diff --git a/pcbnew/tools/pcb_inspection_tool.cpp b/pcbnew/tools/pcb_inspection_tool.cpp index a06f3d9323..cdaf7dda28 100644 --- a/pcbnew/tools/pcb_inspection_tool.cpp +++ b/pcbnew/tools/pcb_inspection_tool.cpp @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2019 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2019-2020 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -38,8 +38,7 @@ PCB_INSPECTION_TOOL::PCB_INSPECTION_TOOL() : { m_probingSchToPcb = false; m_lastNetcode = -1; - - m_slowRatsnest = false; + m_dynamicData = nullptr; } @@ -103,10 +102,6 @@ bool PCB_INSPECTION_TOOL::Init() selectionTool->GetToolMenu().AddSubMenu( netSubMenu ); menu.AddMenu( netSubMenu.get(), SELECTION_CONDITIONS::OnlyTypes( connectedTypes ) ); - m_ratsnestTimer.SetOwner( this ); - Connect( m_ratsnestTimer.GetId(), wxEVT_TIMER, - wxTimerEventHandler( PCB_INSPECTION_TOOL::ratsnestTimer ), NULL, this ); - return true; } @@ -429,6 +424,8 @@ int PCB_INSPECTION_TOOL::LocalRatsnestTool( const TOOL_EVENT& aEvent ) int PCB_INSPECTION_TOOL::UpdateSelectionRatsnest( const TOOL_EVENT& aEvent ) { + VECTOR2I* delta = aEvent.Parameter(); + auto selectionTool = m_toolMgr->GetTool(); auto& selection = selectionTool->GetSelection(); auto connectivity = getModel()->GetConnectivity(); @@ -436,62 +433,30 @@ int PCB_INSPECTION_TOOL::UpdateSelectionRatsnest( const TOOL_EVENT& aEvent ) if( selection.Empty() ) { connectivity->ClearDynamicRatsnest(); - } - else if( m_slowRatsnest ) - { - // Compute ratsnest only when user stops dragging for a moment - connectivity->HideDynamicRatsnest(); - m_ratsnestTimer.Start( 20 ); + delete m_dynamicData; + m_dynamicData = nullptr; } else { - // Check how much time doest it take to calculate ratsnest - PROF_COUNTER counter; - calculateSelectionRatsnest(); - counter.Stop(); - - // If it is too slow, then switch to 'slow ratsnest' mode when - // ratsnest is calculated when user stops dragging items for a moment - if( counter.msecs() > 25 ) - { - m_slowRatsnest = true; - connectivity->HideDynamicRatsnest(); - } + calculateSelectionRatsnest( *delta ); } + delete delta; return 0; } int PCB_INSPECTION_TOOL::HideDynamicRatsnest( const TOOL_EVENT& aEvent ) { - getModel()->GetConnectivity()->HideDynamicRatsnest(); - m_slowRatsnest = false; + getModel()->GetConnectivity()->ClearDynamicRatsnest(); + delete m_dynamicData; + m_dynamicData = nullptr; + return 0; } -void PCB_INSPECTION_TOOL::ratsnestTimer( wxTimerEvent& aEvent ) -{ - auto connectivity = getModel()->GetConnectivity(); - - m_ratsnestTimer.Stop(); - - /// Check how much time does it take to calculate ratsnest - PROF_COUNTER counter; - calculateSelectionRatsnest(); - counter.Stop(); - - /// If the ratsnest is fast enough, turn the slow ratsnest off - if( counter.msecs() <= 25 ) - m_slowRatsnest = false; - - m_frame->GetCanvas()->RedrawRatsnest(); - m_frame->GetCanvas()->Refresh(); -} - - -void PCB_INSPECTION_TOOL::calculateSelectionRatsnest() +void PCB_INSPECTION_TOOL::calculateSelectionRatsnest( const VECTOR2I& aDelta ) { SELECTION_TOOL* selectionTool = m_toolMgr->GetTool(); SELECTION& selection = selectionTool->GetSelection(); @@ -515,7 +480,25 @@ void PCB_INSPECTION_TOOL::calculateSelectionRatsnest() } } - connectivity->ComputeDynamicRatsnest( items ); + if( items.empty() || std::none_of( items.begin(), items.end(), []( const BOARD_ITEM* aItem ) + { return( aItem->Type() == PCB_TRACE_T || aItem->Type() == PCB_PAD_T || + aItem->Type() == PCB_ARC_T || aItem->Type() == PCB_ZONE_AREA_T || + aItem->Type() == PCB_MODULE_T || aItem->Type() == PCB_VIA_T ); } ) ) + { + return; + } + + if( !m_dynamicData ) + { + m_dynamicData = new CONNECTIVITY_DATA( items, true ); + connectivity->BlockRatsnestItems( items ); + } + else + { + m_dynamicData->Move( aDelta ); + } + + connectivity->ComputeDynamicRatsnest( items, m_dynamicData ); } diff --git a/pcbnew/tools/pcb_inspection_tool.h b/pcbnew/tools/pcb_inspection_tool.h index abbf9622e6..f40c855bc8 100644 --- a/pcbnew/tools/pcb_inspection_tool.h +++ b/pcbnew/tools/pcb_inspection_tool.h @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2019 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2019-2020 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -24,13 +24,14 @@ #ifndef __BOARD_STATISTICS_TOOL_H #define __BOARD_STATISTICS_TOOL_H - #include #include #include #include #include +class CONNECTIVITY_DATA; + /** * PCB_INSPECTION_TOOL * @@ -93,7 +94,7 @@ private: void ratsnestTimer( wxTimerEvent& aEvent ); ///> Recalculates dynamic ratsnest for the current selection - void calculateSelectionRatsnest(); + void calculateSelectionRatsnest( const VECTOR2I& aDelta ); bool highlightNet( const VECTOR2D& aPosition, bool aUseSelection ); @@ -110,11 +111,11 @@ private: bool m_probingSchToPcb; // Recursion guard when cross-probing to EESchema int m_lastNetcode; // Used for toggling between last two highlighted nets - bool m_slowRatsnest; // Indicates current selection ratsnest will be slow to calculate - wxTimer m_ratsnestTimer; // Timer to initiate lazy ratsnest calculation (ie: when slow) + CONNECTIVITY_DATA* m_dynamicData; // Cached connectivity data from the selection std::unique_ptr m_listNetsDialog; DIALOG_SELECT_NET_FROM_LIST::SETTINGS m_listNetsDialogSettings; + }; #endif //__BOARD_STATISTICS_TOOL_H