From b4c5e64db24386b77ae4713b67b40c3fc4cb9b7a Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Wed, 1 Dec 2021 14:42:44 +0000 Subject: [PATCH] Exclusions for Unconnected Items; Markers & exclusions for Parity checks Fixes https://gitlab.com/kicad/code/kicad/issues/5589 Fixes https://gitlab.com/kicad/code/kicad/issues/5504 --- include/marker_base.h | 4 +- pcbnew/CMakeLists.txt | 1 - pcbnew/board.cpp | 18 +- pcbnew/connectivity/connectivity_data.cpp | 61 +++++-- pcbnew/connectivity/connectivity_data.h | 6 + pcbnew/dialogs/dialog_drc.cpp | 42 +++-- pcbnew/dialogs/dialog_drc.h | 2 +- pcbnew/dialogs/dialog_drc_base.cpp | 4 + pcbnew/dialogs/dialog_drc_base.fbp | 8 +- pcbnew/dialogs/dialog_footprint_checker.cpp | 6 +- pcbnew/drc/drc_engine.cpp | 1 + pcbnew/drc/drc_item.cpp | 66 ++++++- pcbnew/drc/drc_item.h | 35 +++- pcbnew/drc/drc_results_provider.cpp | 95 ---------- pcbnew/drc/drc_results_provider.h | 163 ------------------ .../drc/drc_test_provider_sliver_checker.cpp | 1 + .../drc_test_provider_zone_connections.cpp | 1 + pcbnew/pcb_marker.cpp | 26 +++ pcbnew/pcb_marker.h | 9 +- pcbnew/ratsnest/ratsnest_data.cpp | 42 +++-- pcbnew/ratsnest/ratsnest_data.h | 21 +-- pcbnew/ratsnest/ratsnest_view_item.cpp | 6 +- pcbnew/tools/drc_tool.cpp | 31 +--- pcbnew/tools/drc_tool.h | 15 +- pcbnew/tools/footprint_editor_control.cpp | 6 +- qa/pcbnew/test_board_item.cpp | 1 + 26 files changed, 307 insertions(+), 364 deletions(-) delete mode 100644 pcbnew/drc/drc_results_provider.cpp delete mode 100644 pcbnew/drc/drc_results_provider.h diff --git a/include/marker_base.h b/include/marker_base.h index 7000082115..d95e869082 100644 --- a/include/marker_base.h +++ b/include/marker_base.h @@ -52,7 +52,9 @@ public: enum TYPEMARKER { MARKER_UNSPEC, MARKER_ERC, - MARKER_PCB, + MARKER_DRC, + MARKER_RATSNEST, + MARKER_PARITY, MARKER_SIMUL }; diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index a50c8de172..1ac3a4b688 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -231,7 +231,6 @@ set( PCBNEW_MICROWAVE_SRCS ) set( PCBNEW_DRC_SRCS - drc/drc_results_provider.cpp drc/drc_test_provider.cpp drc/drc_test_provider_annular_width.cpp drc/drc_test_provider_disallow.cpp diff --git a/pcbnew/board.cpp b/pcbnew/board.cpp index df501d7e38..494e34ce8a 100644 --- a/pcbnew/board.cpp +++ b/pcbnew/board.cpp @@ -221,13 +221,27 @@ void BOARD::IncrementTimeStamp() std::vector BOARD::ResolveDRCExclusions() { + std::shared_ptr conn = GetConnectivity(); + + auto setExcluded = + [&conn]( PCB_MARKER* aMarker ) + { + if( aMarker->GetMarkerType() == MARKER_BASE::MARKER_RATSNEST ) + { + const std::shared_ptr& rcItem = aMarker->GetRCItem(); + conn->AddExclusion( rcItem->GetMainItemID(), rcItem->GetAuxItemID() ); + } + + aMarker->SetExcluded( true ); + }; + for( PCB_MARKER* marker : GetBoard()->Markers() ) { auto i = m_designSettings->m_DrcExclusions.find( marker->Serialize() ); if( i != m_designSettings->m_DrcExclusions.end() ) { - marker->SetExcluded( true ); + setExcluded( marker ); m_designSettings->m_DrcExclusions.erase( i ); } } @@ -240,7 +254,7 @@ std::vector BOARD::ResolveDRCExclusions() if( marker ) { - marker->SetExcluded( true ); + setExcluded( marker ); newMarkers.push_back( marker ); } } diff --git a/pcbnew/connectivity/connectivity_data.cpp b/pcbnew/connectivity/connectivity_data.cpp index 03376bafec..85dd2ab1fd 100644 --- a/pcbnew/connectivity/connectivity_data.cpp +++ b/pcbnew/connectivity/connectivity_data.cpp @@ -150,10 +150,10 @@ void CONNECTIVITY_DATA::updateRatsnest() std::vector> returns( parallelThreadCount ); auto update_lambda = - [&nextNet, &dirty_nets]() -> size_t + [this, &nextNet, &dirty_nets]() -> size_t { for( size_t i = nextNet++; i < dirty_nets.size(); i = nextNet++ ) - dirty_nets[i]->Update(); + dirty_nets[i]->Update( m_exclusions ); return 1; }; @@ -405,12 +405,11 @@ unsigned int CONNECTIVITY_DATA::GetUnconnectedCount() const if( !net ) continue; - const std::vector& edges = net->GetUnconnected(); - - if( edges.empty() ) - continue; - - unconnected += edges.size(); + for( const CN_EDGE& edge : net->GetEdges() ) + { + if( edge.IsVisible() ) + ++unconnected; + } } return unconnected; @@ -801,6 +800,48 @@ void CONNECTIVITY_DATA::SetProgressReporter( PROGRESS_REPORTER* aReporter ) } +void CONNECTIVITY_DATA::AddExclusion( const KIID& aBoardItemId1, const KIID& aBoardItemId2 ) +{ + m_exclusions.insert( std::pair( aBoardItemId1, aBoardItemId2 ) ); + m_exclusions.insert( std::pair( aBoardItemId2, aBoardItemId1 ) ); + + for( RN_NET* rnNet : m_nets ) + { + for( CN_EDGE& edge : rnNet->GetEdges() ) + { + if( ( edge.GetSourceNode()->Parent()->m_Uuid == aBoardItemId1 + && edge.GetTargetNode()->Parent()->m_Uuid == aBoardItemId2 ) + || ( edge.GetSourceNode()->Parent()->m_Uuid == aBoardItemId2 + && edge.GetTargetNode()->Parent()->m_Uuid == aBoardItemId1 ) ) + { + edge.SetVisible( false ); + } + } + } +} + + +void CONNECTIVITY_DATA::RemoveExclusion( const KIID& aBoardItemId1, const KIID& aBoardItemId2 ) +{ + m_exclusions.erase( std::pair( aBoardItemId1, aBoardItemId2 ) ); + m_exclusions.erase( std::pair( aBoardItemId2, aBoardItemId1 ) ); + + for( RN_NET* rnNet : m_nets ) + { + for( CN_EDGE& edge : rnNet->GetEdges() ) + { + if( ( edge.GetSourceNode()->Parent()->m_Uuid == aBoardItemId1 + && edge.GetTargetNode()->Parent()->m_Uuid == aBoardItemId2 ) + || ( edge.GetSourceNode()->Parent()->m_Uuid == aBoardItemId2 + && edge.GetTargetNode()->Parent()->m_Uuid == aBoardItemId1 ) ) + { + edge.SetVisible( true ); + } + } + } +} + + const std::vector CONNECTIVITY_DATA::GetRatsnestForItems( std::vector aItems ) { std::set nets; @@ -879,9 +920,9 @@ const std::vector CONNECTIVITY_DATA::GetRatsnestForComponent( FOOTPRINT for( const auto& netcode : nets ) { - const auto& net = GetRatsnestForNet( netcode ); + RN_NET* net = GetRatsnestForNet( netcode ); - for( const auto& edge : net->GetEdges() ) + for( const CN_EDGE& edge : net->GetEdges() ) { auto srcNode = edge.GetSourceNode(); auto dstNode = edge.GetTargetNode(); diff --git a/pcbnew/connectivity/connectivity_data.h b/pcbnew/connectivity/connectivity_data.h index b2eb377a11..6af68f6626 100644 --- a/pcbnew/connectivity/connectivity_data.h +++ b/pcbnew/connectivity/connectivity_data.h @@ -297,6 +297,9 @@ public: return m_netclassMap; } + void AddExclusion( const KIID& aBoardItemId1, const KIID& aBoardItemId2 ); + void RemoveExclusion( const KIID& aBoardItemId1, const KIID& aBoardItemId2 ); + #ifndef SWIG const std::vector GetRatsnestForItems( const std::vector aItems ); @@ -326,6 +329,9 @@ private: /// Used to suppress ratsnest calculations on dynamic ratsnests bool m_skipRatsnest = false; + /// Ratsnest lines that have been excluded in DRC + std::set> m_exclusions; + KISPINLOCK m_lock; /// Map of netcode -> netclass the net is a member of; used for ratsnest painting diff --git a/pcbnew/dialogs/dialog_drc.cpp b/pcbnew/dialogs/dialog_drc.cpp index 691f1bffe5..a6a5ba6c75 100644 --- a/pcbnew/dialogs/dialog_drc.cpp +++ b/pcbnew/dialogs/dialog_drc.cpp @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include #include @@ -309,7 +311,7 @@ void DIALOG_DRC::SetMarkersProvider( RC_ITEMS_PROVIDER* aProvider ) } -void DIALOG_DRC::SetUnconnectedProvider( class RC_ITEMS_PROVIDER * aProvider ) +void DIALOG_DRC::SetRatsnestProvider( class RC_ITEMS_PROVIDER * aProvider ) { m_unconnectedItemsProvider = aProvider; m_unconnectedTreeModel->SetProvider( m_unconnectedItemsProvider ); @@ -451,11 +453,12 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent ) if( !node ) return; - std::shared_ptr rcItem = node->m_RcItem; - DRC_ITEM* drcItem = static_cast( rcItem.get() ); - wxString listName; - wxMenu menu; - wxString msg; + std::shared_ptr rcItem = node->m_RcItem; + DRC_ITEM* drcItem = static_cast( rcItem.get() ); + std::shared_ptr conn = m_currentBoard->GetConnectivity(); + wxString listName; + wxMenu menu; + wxString msg; switch( bds().m_DRCSeverities[ rcItem->GetErrorCode() ] ) { @@ -527,12 +530,19 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent ) { case 1: { - PCB_MARKER* marker = dynamic_cast( node->m_RcItem->GetParent() ); + PCB_MARKER* marker = dynamic_cast( rcItem->GetParent() ); if( marker ) { marker->SetExcluded( false ); - m_frame->GetCanvas()->GetView()->Update( marker ); + + if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS ) + conn->RemoveExclusion( drcItem->GetMainItemID(), drcItem->GetAuxItemID() ); + + if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS ) + m_frame->GetCanvas()->RedrawRatsnest(); + else + m_frame->GetCanvas()->GetView()->Update( marker ); // Update view static_cast( aEvent.GetModel() )->ValueChanged( node ); @@ -544,12 +554,19 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent ) case 2: { - PCB_MARKER* marker = dynamic_cast( node->m_RcItem->GetParent() ); + PCB_MARKER* marker = dynamic_cast( rcItem->GetParent() ); if( marker ) { marker->SetExcluded( true ); - m_frame->GetCanvas()->GetView()->Update( marker ); + + if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS ) + conn->AddExclusion( drcItem->GetMainItemID(), drcItem->GetAuxItemID() ); + + if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS ) + m_frame->GetCanvas()->RedrawRatsnest(); + else + m_frame->GetCanvas()->GetView()->Update( marker ); // Update view if( m_severities & RPT_SEVERITY_EXCLUSION ) @@ -646,9 +663,14 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent ) markers.erase( markers.begin() + i ); } else + { ++i; + } } + if( rcItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS ) + m_frame->GetCanvas()->RedrawRatsnest(); + // Rebuild model and view static_cast( aEvent.GetModel() )->SetProvider( m_markersProvider ); modified = true; diff --git a/pcbnew/dialogs/dialog_drc.h b/pcbnew/dialogs/dialog_drc.h index 8d121b1e25..87fc3960c8 100644 --- a/pcbnew/dialogs/dialog_drc.h +++ b/pcbnew/dialogs/dialog_drc.h @@ -52,7 +52,7 @@ public: void SetFootprintTestsRun() { m_footprintTestsRun = true; } void SetMarkersProvider( RC_ITEMS_PROVIDER* aProvider ); - void SetUnconnectedProvider( RC_ITEMS_PROVIDER* aProvider ); + void SetRatsnestProvider( RC_ITEMS_PROVIDER* aProvider ); void SetFootprintsProvider( RC_ITEMS_PROVIDER* aProvider ); void PrevMarker(); diff --git a/pcbnew/dialogs/dialog_drc_base.cpp b/pcbnew/dialogs/dialog_drc_base.cpp index 6a1ebb2f3e..5bad493d0d 100644 --- a/pcbnew/dialogs/dialog_drc_base.cpp +++ b/pcbnew/dialogs/dialog_drc_base.cpp @@ -235,8 +235,10 @@ DIALOG_DRC_BASE::DIALOG_DRC_BASE( wxWindow* parent, wxWindowID id, const wxStrin m_markerDataView->Connect( wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, wxDataViewEventHandler( DIALOG_DRC_BASE::OnDRCItemRClick ), NULL, this ); m_markerDataView->Connect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( DIALOG_DRC_BASE::OnDRCItemSelected ), NULL, this ); m_unconnectedDataView->Connect( wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, wxDataViewEventHandler( DIALOG_DRC_BASE::OnDRCItemDClick ), NULL, this ); + m_unconnectedDataView->Connect( wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, wxDataViewEventHandler( DIALOG_DRC_BASE::OnDRCItemRClick ), NULL, this ); m_unconnectedDataView->Connect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( DIALOG_DRC_BASE::OnDRCItemSelected ), NULL, this ); m_footprintsDataView->Connect( wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, wxDataViewEventHandler( DIALOG_DRC_BASE::OnDRCItemDClick ), NULL, this ); + m_footprintsDataView->Connect( wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, wxDataViewEventHandler( DIALOG_DRC_BASE::OnDRCItemRClick ), NULL, this ); m_footprintsDataView->Connect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( DIALOG_DRC_BASE::OnDRCItemSelected ), NULL, this ); m_ignoredList->Connect( wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, wxListEventHandler( DIALOG_DRC_BASE::OnIgnoreItemRClick ), NULL, this ); m_showAll->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_DRC_BASE::OnSeverity ), NULL, this ); @@ -261,8 +263,10 @@ DIALOG_DRC_BASE::~DIALOG_DRC_BASE() m_markerDataView->Disconnect( wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, wxDataViewEventHandler( DIALOG_DRC_BASE::OnDRCItemRClick ), NULL, this ); m_markerDataView->Disconnect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( DIALOG_DRC_BASE::OnDRCItemSelected ), NULL, this ); m_unconnectedDataView->Disconnect( wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, wxDataViewEventHandler( DIALOG_DRC_BASE::OnDRCItemDClick ), NULL, this ); + m_unconnectedDataView->Disconnect( wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, wxDataViewEventHandler( DIALOG_DRC_BASE::OnDRCItemRClick ), NULL, this ); m_unconnectedDataView->Disconnect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( DIALOG_DRC_BASE::OnDRCItemSelected ), NULL, this ); m_footprintsDataView->Disconnect( wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, wxDataViewEventHandler( DIALOG_DRC_BASE::OnDRCItemDClick ), NULL, this ); + m_footprintsDataView->Disconnect( wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, wxDataViewEventHandler( DIALOG_DRC_BASE::OnDRCItemRClick ), NULL, this ); m_footprintsDataView->Disconnect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( DIALOG_DRC_BASE::OnDRCItemSelected ), NULL, this ); m_ignoredList->Disconnect( wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, wxListEventHandler( DIALOG_DRC_BASE::OnIgnoreItemRClick ), NULL, this ); m_showAll->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_DRC_BASE::OnSeverity ), NULL, this ); diff --git a/pcbnew/dialogs/dialog_drc_base.fbp b/pcbnew/dialogs/dialog_drc_base.fbp index c3cefe757f..3f6444fdc6 100644 --- a/pcbnew/dialogs/dialog_drc_base.fbp +++ b/pcbnew/dialogs/dialog_drc_base.fbp @@ -954,17 +954,18 @@ OnDRCItemDClick + OnDRCItemRClick OnDRCItemSelected - + Schematic Parity (%d) 0 - + 1 1 1 @@ -1015,7 +1016,7 @@ wxTAB_TRAVERSAL - + bSizerFootprintsBox wxVERTICAL @@ -1046,6 +1047,7 @@ OnDRCItemDClick + OnDRCItemRClick OnDRCItemSelected diff --git a/pcbnew/dialogs/dialog_footprint_checker.cpp b/pcbnew/dialogs/dialog_footprint_checker.cpp index 428b2437c4..56ec7f0661 100644 --- a/pcbnew/dialogs/dialog_footprint_checker.cpp +++ b/pcbnew/dialogs/dialog_footprint_checker.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -91,7 +91,7 @@ void DIALOG_FOOTPRINT_CHECKER::runChecks() FOOTPRINT* footprint = board->GetFirstFootprint(); wxString msg; - SetMarkersProvider( new BOARD_DRC_ITEMS_PROVIDER( board ) ); + SetMarkersProvider( new DRC_ITEMS_PROVIDER( board, MARKER_BASE::MARKER_DRC ) ); deleteAllMarkers(); @@ -147,7 +147,7 @@ void DIALOG_FOOTPRINT_CHECKER::runChecks() footprint->CheckFootprintTHPadNoHoles( &tstHoleInTHPad ); m_checksRun = true; - SetMarkersProvider( new BOARD_DRC_ITEMS_PROVIDER( board ) ); + SetMarkersProvider( new DRC_ITEMS_PROVIDER( board, MARKER_BASE::MARKER_DRC ) ); refreshEditor(); } diff --git a/pcbnew/drc/drc_engine.cpp b/pcbnew/drc/drc_engine.cpp index 069079ea1c..77a2e82f5d 100644 --- a/pcbnew/drc/drc_engine.cpp +++ b/pcbnew/drc/drc_engine.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include diff --git a/pcbnew/drc/drc_item.cpp b/pcbnew/drc/drc_item.cpp index 395ef6bd64..a92a0f61f8 100644 --- a/pcbnew/drc/drc_item.cpp +++ b/pcbnew/drc/drc_item.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2007 Dick Hollenbeck, dick@softplc.com - * Copyright (C) 2015-2020 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 2015-2021 KiCad Developers, see change_log.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 @@ -28,6 +28,7 @@ #include #include #include +#include // These, being statically-defined, require specialized I18N handling. We continue to @@ -380,3 +381,66 @@ wxString DRC_ITEM::GetViolatingRuleDesc() const return _( "Local override" ); } + +void DRC_ITEMS_PROVIDER::SetSeverities( int aSeverities ) +{ + m_severities = aSeverities; + + m_filteredMarkers.clear(); + + for( PCB_MARKER* marker : m_board->Markers() ) + { + if( marker->GetMarkerType() != m_markerType ) + continue; + + if( marker->GetSeverity() & m_severities ) + m_filteredMarkers.push_back( marker ); + } +} + + +int DRC_ITEMS_PROVIDER::GetCount( int aSeverity ) const +{ + if( aSeverity < 0 ) + return m_filteredMarkers.size(); + + int count = 0; + + for( PCB_MARKER* marker : m_board->Markers() ) + { + if( marker->GetMarkerType() != m_markerType ) + continue; + + if( marker->GetSeverity() == aSeverity ) + count++; + } + + return count; +} + + +std::shared_ptr DRC_ITEMS_PROVIDER::GetItem( int aIndex ) const +{ + PCB_MARKER* marker = m_filteredMarkers[ aIndex ]; + + return marker ? marker->GetRCItem() : nullptr; +} + + +void DRC_ITEMS_PROVIDER::DeleteItem( int aIndex, bool aDeep ) +{ + PCB_MARKER* marker = m_filteredMarkers[ aIndex ]; + m_filteredMarkers.erase( m_filteredMarkers.begin() + aIndex ); + + if( aDeep ) + m_board->Delete( marker ); +} + + +void DRC_ITEMS_PROVIDER::DeleteAllItems( bool aIncludeExclusions, bool aDeep ) +{ + // Filtered list was already handled through DeleteItem() by the tree control + + if( aDeep ) + m_board->DeleteMARKERs( true, aIncludeExclusions ); +} diff --git a/pcbnew/drc/drc_item.h b/pcbnew/drc/drc_item.h index 4ed59f9126..865f9a52bf 100644 --- a/pcbnew/drc/drc_item.h +++ b/pcbnew/drc/drc_item.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2007 Dick Hollenbeck, dick@softplc.com - * Copyright (C) 2018-2020 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2018-2021 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 @@ -26,10 +26,13 @@ #define DRC_ITEM_H #include +#include class PCB_BASE_FRAME; class DRC_RULE; class DRC_TEST_PROVIDER; +class PCB_MARKER; +class BOARD; enum PCB_DRC_CODE { DRCE_FIRST = 1, @@ -198,4 +201,34 @@ private: DRC_TEST_PROVIDER* m_violatingTest = nullptr; }; + +class DRC_ITEMS_PROVIDER : public RC_ITEMS_PROVIDER +{ +public: + DRC_ITEMS_PROVIDER( BOARD* aBoard, MARKER_BASE::TYPEMARKER aMarkerType ) : + m_board( aBoard ), + m_markerType( aMarkerType ), + m_severities( 0 ) + { + } + + void SetSeverities( int aSeverities ) override; + + int GetCount( int aSeverity = -1 ) const override; + + std::shared_ptr GetItem( int aIndex ) const override; + + void DeleteItem( int aIndex, bool aDeep ) override; + + void DeleteAllItems( bool aIncludeExclusions, bool aDeep ) override; + +private: + BOARD* m_board; + MARKER_BASE::TYPEMARKER m_markerType; + + int m_severities; + std::vector m_filteredMarkers; +}; + + #endif // DRC_ITEM_H diff --git a/pcbnew/drc/drc_results_provider.cpp b/pcbnew/drc/drc_results_provider.cpp deleted file mode 100644 index 128d21ee44..0000000000 --- a/pcbnew/drc/drc_results_provider.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2018-2021 KiCad Developers, see change_log.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 - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include -#include "drc_results_provider.h" - -void BOARD_DRC_ITEMS_PROVIDER::SetSeverities( int aSeverities ) -{ - m_severities = aSeverities; - - m_filteredMarkers.clear(); - - for( PCB_MARKER* marker : m_board->Markers() ) - { - if( marker->GetSeverity() & m_severities ) - m_filteredMarkers.push_back( marker ); - } -} - - -int BOARD_DRC_ITEMS_PROVIDER::GetCount( int aSeverity ) const -{ - if( aSeverity < 0 ) - return m_filteredMarkers.size(); - - int count = 0; - - for( PCB_MARKER* marker : m_board->Markers() ) - { - if( marker->GetSeverity() == aSeverity ) - count++; - } - - return count; -} - - -void VECTOR_DRC_ITEMS_PROVIDER::SetSeverities( int aSeverities ) -{ - m_severities = aSeverities; - - BOARD_DESIGN_SETTINGS& bds = m_frame->GetBoard()->GetDesignSettings(); - - m_filteredVector.clear(); - - if( m_sourceVector ) - { - for( const std::shared_ptr& item : *m_sourceVector ) - { - if( bds.GetSeverity( item->GetErrorCode() ) & aSeverities ) - m_filteredVector.push_back( item ); - } - } -} - - -int VECTOR_DRC_ITEMS_PROVIDER::GetCount( int aSeverity ) const -{ - if( aSeverity < 0 ) - return m_filteredVector.size(); - - int count = 0; - BOARD_DESIGN_SETTINGS& bds = m_frame->GetBoard()->GetDesignSettings(); - - if( m_sourceVector ) - { - for( const std::shared_ptr& item : *m_sourceVector ) - { - if( bds.GetSeverity( item->GetErrorCode() ) == aSeverity ) - count++; - } - } - - return count; -} \ No newline at end of file diff --git a/pcbnew/drc/drc_results_provider.h b/pcbnew/drc/drc_results_provider.h deleted file mode 100644 index 622fde3f4a..0000000000 --- a/pcbnew/drc/drc_results_provider.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2018-2021 KiCad Developers, see change_log.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 - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - - -#ifndef DRC_PROVIDER__H -#define DRC_PROVIDER__H - -#include -#include -#include -#include -#include -#include - - -/** - * BOARD_DRC_ITEMS_PROVIDER - * is an implementation of the RC_ITEMS_PROVIDER interface which uses a BOARD instance - * to fulfill the interface. - */ -class BOARD_DRC_ITEMS_PROVIDER : public RC_ITEMS_PROVIDER -{ -private: - BOARD* m_board; - - int m_severities; - std::vector m_filteredMarkers; - -public: - BOARD_DRC_ITEMS_PROVIDER( BOARD* aBoard ) : - m_board( aBoard ), - m_severities( 0 ) - { - } - - void SetSeverities( int aSeverities ) override; - - int GetCount( int aSeverity = -1 ) const override; - - std::shared_ptr GetItem( int aIndex ) const override - { - PCB_MARKER* marker = m_filteredMarkers[ aIndex ]; - - return marker ? marker->GetRCItem() : nullptr; - } - - void DeleteItem( int aIndex, bool aDeep ) override - { - PCB_MARKER* marker = m_filteredMarkers[ aIndex ]; - m_filteredMarkers.erase( m_filteredMarkers.begin() + aIndex ); - - if( aDeep ) - m_board->Delete( marker ); - } - - void DeleteAllItems( bool aIncludeExclusions, bool aDeep ) override - { - // Filtered list was already handled through DeleteItem() by the tree control - - if( aDeep ) - m_board->DeleteMARKERs( true, aIncludeExclusions ); - } -}; - - -/** - * VECTOR_DRC_ITEMS_PROVIDER - * is an implementation of the interface named DRC_ITEMS_PROVIDER which uses a vector - * of pointers to DRC_ITEMs to fulfill the interface. No ownership is taken of the - * vector. - */ -class VECTOR_DRC_ITEMS_PROVIDER : public RC_ITEMS_PROVIDER -{ - PCB_BASE_FRAME* m_frame; - std::vector >* m_sourceVector; // owns its DRC_ITEMs - - int m_severities; - std::vector > m_filteredVector; // does not own its DRC_ITEMs - -public: - - VECTOR_DRC_ITEMS_PROVIDER( PCB_BASE_FRAME* aFrame, std::vector >* aList ) : - m_frame( aFrame ), - m_sourceVector( aList ), - m_severities( 0 ) - { - } - - void SetSeverities( int aSeverities ) override; - - int GetCount( int aSeverity = -1 ) const override; - - std::shared_ptr GetItem( int aIndex ) const override - { - return (m_filteredVector)[aIndex]; - } - - void DeleteItem( int aIndex, bool aDeep ) override - { - auto item = m_filteredVector[aIndex]; - m_filteredVector.erase( m_filteredVector.begin() + aIndex ); - - if( aDeep ) - { - for( size_t i = 0; i < m_sourceVector->size(); ++i ) - { - if( m_sourceVector->at( i ) == item ) - { - m_sourceVector->erase( m_sourceVector->begin() + i ); - break; - } - } - } - } - - void DeleteAllItems( bool aIncludeExclusions, bool aDeep ) override - { - if( aDeep ) - { - m_sourceVector->clear(); - } - - m_filteredVector.clear(); // no ownership of DRC_ITEM pointers - } -}; - - -/** - * RATSNEST_DRC_ITEMS_PROVIDER - */ -class RATSNEST_DRC_ITEMS_PROVIDER : public VECTOR_DRC_ITEMS_PROVIDER -{ - // TODO: for now this is just a vector, but we need to map it to some board-level - // data-structure so that deleting/excluding things can do a deep delete/exclusion - // which will be reflected in the ratsnest.... -public: - RATSNEST_DRC_ITEMS_PROVIDER( PCB_BASE_FRAME* aFrame, std::vector >* aList ) : - VECTOR_DRC_ITEMS_PROVIDER( aFrame, aList ) - { } -}; - - -#endif // DRC_PROVIDER__H diff --git a/pcbnew/drc/drc_test_provider_sliver_checker.cpp b/pcbnew/drc/drc_test_provider_sliver_checker.cpp index 23272d4c3c..3f26fd0000 100644 --- a/pcbnew/drc/drc_test_provider_sliver_checker.cpp +++ b/pcbnew/drc/drc_test_provider_sliver_checker.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include diff --git a/pcbnew/drc/drc_test_provider_zone_connections.cpp b/pcbnew/drc/drc_test_provider_zone_connections.cpp index a84c4b155e..151e244d54 100644 --- a/pcbnew/drc/drc_test_provider_zone_connections.cpp +++ b/pcbnew/drc/drc_test_provider_zone_connections.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include diff --git a/pcbnew/pcb_marker.cpp b/pcbnew/pcb_marker.cpp index 3e97a84ce5..9d9eec0bdc 100644 --- a/pcbnew/pcb_marker.cpp +++ b/pcbnew/pcb_marker.cpp @@ -49,8 +49,28 @@ PCB_MARKER::PCB_MARKER( std::shared_ptr aItem, const wxPoint& aPosition MARKER_BASE( SCALING_FACTOR, aItem ) { if( m_rcItem ) + { m_rcItem->SetParent( this ); + switch( m_rcItem->GetErrorCode() ) + { + case DRCE_UNCONNECTED_ITEMS: + SetMarkerType( MARKER_BASE::MARKER_RATSNEST ); + break; + + case DRCE_MISSING_FOOTPRINT: + case DRCE_DUPLICATE_FOOTPRINT: + case DRCE_EXTRA_FOOTPRINT: + case DRCE_NET_CONFLICT: + SetMarkerType( MARKER_BASE::MARKER_PARITY ); + break; + + default: + SetMarkerType( MARKER_BASE::MARKER_DRC ); + break; + } + } + m_Pos = aPosition; } @@ -168,6 +188,12 @@ SEVERITY PCB_MARKER::GetSeverity() const void PCB_MARKER::ViewGetLayers( int aLayers[], int& aCount ) const { + if( GetMarkerType() == MARKER_RATSNEST ) + { + aCount = 0; + return; + } + aCount = 2; aLayers[1] = LAYER_MARKER_SHADOWS; diff --git a/pcbnew/pcb_marker.h b/pcbnew/pcb_marker.h index 06d7f90c35..85205d3692 100644 --- a/pcbnew/pcb_marker.h +++ b/pcbnew/pcb_marker.h @@ -2,7 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2009-2018 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr - * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2021 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 @@ -27,7 +27,7 @@ #include -#include +#include #include class DRC_ITEM; @@ -74,7 +74,10 @@ public: bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override { - return HitTestMarker( aPosition, aAccuracy ); + if( GetMarkerType() == MARKER_RATSNEST ) + return false; + else + return HitTestMarker( aPosition, aAccuracy ); } EDA_ITEM* Clone() const override diff --git a/pcbnew/ratsnest/ratsnest_data.cpp b/pcbnew/ratsnest/ratsnest_data.cpp index 144d1ba3fe..68615bda51 100644 --- a/pcbnew/ratsnest/ratsnest_data.cpp +++ b/pcbnew/ratsnest/ratsnest_data.cpp @@ -107,7 +107,8 @@ private: }; -void RN_NET::kruskalMST( const std::vector &aEdges ) +void RN_NET::kruskalMST( std::vector& aEdges, + const std::set< std::pair >& aExclusions ) { disjoint_set dset( m_nodes.size() ); @@ -118,15 +119,20 @@ void RN_NET::kruskalMST( const std::vector &aEdges ) for( const CN_ANCHOR_PTR& node : m_nodes ) node->SetTag( i++ ); - for( const CN_EDGE& tmp : aEdges ) + for( CN_EDGE& tmp : aEdges ) { - int u = tmp.GetSourceNode()->GetTag(); - int v = tmp.GetTargetNode()->GetTag(); + const CN_ANCHOR_PTR& source = tmp.GetSourceNode(); + const CN_ANCHOR_PTR& target = tmp.GetTargetNode(); - if( dset.unite( u, v ) ) + if( dset.unite( source->GetTag(), target->GetTag() ) ) { if( tmp.GetWeight() > 0 ) + { + std::pair ids = { source->Parent()->m_Uuid, target->Parent()->m_Uuid }; + tmp.SetVisible( aExclusions.count( ids ) == 0 ); + m_rnEdges.push_back( tmp ); + } } } } @@ -171,7 +177,7 @@ public: m_allNodes.insert( aNode ); } - void Triangulate( std::vector& mstEdges) + void Triangulate( std::vector& mstEdges ) { std::vector node_pts; std::vector anchors; @@ -273,7 +279,7 @@ RN_NET::RN_NET() : m_dirty( true ) } -void RN_NET::compute() +void RN_NET::compute( const std::set< std::pair >& aExclusions ) { // Special cases do not need complicated algorithms (actually, it does not work well with // the Delaunay triangulator) @@ -287,9 +293,14 @@ void RN_NET::compute() auto last = ++m_nodes.begin(); // There can be only one possible connection, but it is missing - CN_EDGE edge ( *m_nodes.begin(), *last ); - edge.GetSourceNode()->SetTag( 0 ); - edge.GetTargetNode()->SetTag( 1 ); + CN_EDGE edge( *m_nodes.begin(), *last ); + const CN_ANCHOR_PTR& source = edge.GetSourceNode(); + const CN_ANCHOR_PTR& target = edge.GetTargetNode(); + std::pair ids = { source->Parent()->m_Uuid, target->Parent()->m_Uuid }; + + source->SetTag( 0 ); + target->SetTag( 1 ); + edge.SetVisible( aExclusions.count( ids ) == 0 ); m_rnEdges.push_back( edge ); } @@ -329,7 +340,7 @@ void RN_NET::compute() #ifdef PROFILE PROF_COUNTER cnt2("mst"); #endif - kruskalMST( triangEdges ); + kruskalMST( triangEdges, aExclusions ); #ifdef PROFILE cnt2.Show(); #endif @@ -337,9 +348,9 @@ void RN_NET::compute() -void RN_NET::Update() +void RN_NET::Update( const std::set< std::pair >& aExclusions ) { - compute(); + compute( aExclusions ); m_dirty = false; } @@ -462,8 +473,3 @@ bool RN_NET::NearestBicoloredPair( const RN_NET& aOtherNet, CN_ANCHOR_PTR& aNode } -void RN_NET::SetVisible( bool aEnabled ) -{ - for( CN_EDGE& edge : m_rnEdges ) - edge.SetVisible( aEnabled ); -} diff --git a/pcbnew/ratsnest/ratsnest_data.h b/pcbnew/ratsnest/ratsnest_data.h index 72ab8abe60..3a8a8f91f1 100644 --- a/pcbnew/ratsnest/ratsnest_data.h +++ b/pcbnew/ratsnest/ratsnest_data.h @@ -63,14 +63,6 @@ class RN_NET public: RN_NET(); - /** - * Set state of the visibility flag. - * - * @param aEnabled is new state. True if ratsnest for a given net is meant to be displayed, - * false otherwise. - */ - void SetVisible( bool aEnabled ); - /** * Mark ratsnest for given net as 'dirty', i.e. requiring recomputation. */ @@ -84,15 +76,10 @@ public: */ bool IsDirty() const { return m_dirty; } - /** - * Return pointer to a vector of edges that makes ratsnest for a given net. - */ - const std::vector GetUnconnected() const { return m_rnEdges; } - /** * Recompute ratsnest for a net. */ - void Update(); + void Update( const std::set< std::pair >& aExclusions ); void Clear(); void AddCluster( std::shared_ptr aCluster ); @@ -100,16 +87,18 @@ public: unsigned int GetNodeCount() const { return m_nodes.size(); } const std::vector& GetEdges() const { return m_rnEdges; } + std::vector& GetEdges() { return m_rnEdges; } bool NearestBicoloredPair( const RN_NET& aOtherNet, CN_ANCHOR_PTR& aNode1, CN_ANCHOR_PTR& aNode2 ) const; protected: ///< Recompute ratsnest from scratch. - void compute(); + void compute( const std::set< std::pair >& aExclusions ); ///< Compute the minimum spanning tree using Kruskal's algorithm - void kruskalMST( const std::vector &aEdges ); + void kruskalMST( std::vector& aEdges, + const std::set< std::pair >& aExclusions ); ///< Vector of nodes std::multiset m_nodes; diff --git a/pcbnew/ratsnest/ratsnest_view_item.cpp b/pcbnew/ratsnest/ratsnest_view_item.cpp index a8a5866225..c24dd549c7 100644 --- a/pcbnew/ratsnest/ratsnest_view_item.cpp +++ b/pcbnew/ratsnest/ratsnest_view_item.cpp @@ -172,10 +172,10 @@ void RATSNEST_VIEW_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const else gal->SetStrokeColor( color ); // using the default ratsnest color for not highlighted - for( const CN_EDGE& edge : net->GetUnconnected() ) + for( const CN_EDGE& edge : net->GetEdges() ) { - //if ( !edge.IsVisible() ) - // continue; + if( !edge.IsVisible() ) + continue; const CN_ANCHOR_PTR& sourceNode = edge.GetSourceNode(); const CN_ANCHOR_PTR& targetNode = edge.GetTargetNode(); diff --git a/pcbnew/tools/drc_tool.cpp b/pcbnew/tools/drc_tool.cpp index 287a6f9c91..1150713757 100644 --- a/pcbnew/tools/drc_tool.cpp +++ b/pcbnew/tools/drc_tool.cpp @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include DRC_TOOL::DRC_TOOL() : @@ -174,22 +174,8 @@ void DRC_TOOL::RunTests( PROGRESS_REPORTER* aProgressReporter, bool aRefillZones m_drcEngine->SetViolationHandler( [&]( const std::shared_ptr& aItem, wxPoint aPos ) { - if( aItem->GetErrorCode() == DRCE_MISSING_FOOTPRINT - || aItem->GetErrorCode() == DRCE_DUPLICATE_FOOTPRINT - || aItem->GetErrorCode() == DRCE_EXTRA_FOOTPRINT - || aItem->GetErrorCode() == DRCE_NET_CONFLICT ) - { - m_footprints.push_back( aItem ); - } - else if( aItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS ) - { - m_unconnected.push_back( aItem ); - } - else - { - PCB_MARKER* marker = new PCB_MARKER( aItem, aPos ); - commit.Add( marker ); - } + PCB_MARKER* marker = new PCB_MARKER( aItem, aPos ); + commit.Add( marker ); } ); m_drcEngine->RunTests( m_editFrame->GetUserUnits(), aReportAllTrackErrors, aTestFootprints ); @@ -225,11 +211,12 @@ void DRC_TOOL::updatePointers() if( m_drcDialog ) // Use dialog list boxes only in DRC_TOOL dialog { - m_drcDialog->SetMarkersProvider( new BOARD_DRC_ITEMS_PROVIDER( m_pcb ) ); - m_drcDialog->SetUnconnectedProvider( new RATSNEST_DRC_ITEMS_PROVIDER( m_editFrame, - &m_unconnected ) ); - m_drcDialog->SetFootprintsProvider( new VECTOR_DRC_ITEMS_PROVIDER( m_editFrame, - &m_footprints ) ); + m_drcDialog->SetMarkersProvider( new DRC_ITEMS_PROVIDER( m_pcb, + MARKER_BASE::MARKER_DRC ) ); + m_drcDialog->SetRatsnestProvider( new DRC_ITEMS_PROVIDER( m_pcb, + MARKER_BASE::MARKER_RATSNEST ) ); + m_drcDialog->SetFootprintsProvider( new DRC_ITEMS_PROVIDER( m_pcb, + MARKER_BASE::MARKER_PARITY ) ); } } diff --git a/pcbnew/tools/drc_tool.h b/pcbnew/tools/drc_tool.h index 595fd24139..218fab7624 100644 --- a/pcbnew/tools/drc_tool.h +++ b/pcbnew/tools/drc_tool.h @@ -106,15 +106,12 @@ private: EDA_UNITS userUnits() const { return m_editFrame->GetUserUnits(); } - PCB_EDIT_FRAME* m_editFrame; // The pcb frame editor which owns the board - BOARD* m_pcb; - DIALOG_DRC* m_drcDialog; - bool m_drcRunning; - - std::shared_ptr m_drcEngine; - - std::vector> m_unconnected; // list of unconnected pads - std::vector> m_footprints; // list of footprint warnings +private: + PCB_EDIT_FRAME* m_editFrame; + BOARD* m_pcb; + DIALOG_DRC* m_drcDialog; + bool m_drcRunning; + std::shared_ptr m_drcEngine; }; diff --git a/pcbnew/tools/footprint_editor_control.cpp b/pcbnew/tools/footprint_editor_control.cpp index 3ccc3af1a1..951ac8979e 100644 --- a/pcbnew/tools/footprint_editor_control.cpp +++ b/pcbnew/tools/footprint_editor_control.cpp @@ -43,7 +43,7 @@ #include #include #include -#include +#include FOOTPRINT_EDITOR_CONTROL::FOOTPRINT_EDITOR_CONTROL() : @@ -505,7 +505,9 @@ int FOOTPRINT_EDITOR_CONTROL::CheckFootprint( const TOOL_EVENT& aEvent ) } else // The dialog is just not visible (because the user has double clicked on an error item) { - m_checkerDialog->SetMarkersProvider( new BOARD_DRC_ITEMS_PROVIDER( m_frame->GetBoard() ) ); + m_checkerDialog->SetMarkersProvider( + new DRC_ITEMS_PROVIDER( m_frame->GetBoard(), MARKER_BASE::MARKER_DRC ) ); + m_checkerDialog->Show( true ); } return 0; diff --git a/qa/pcbnew/test_board_item.cpp b/qa/pcbnew/test_board_item.cpp index a17c914a41..a7b98f769a 100644 --- a/qa/pcbnew/test_board_item.cpp +++ b/qa/pcbnew/test_board_item.cpp @@ -24,6 +24,7 @@ #include #include #include +#include // Code under test #include