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
This commit is contained in:
Jeff Young 2021-12-01 14:42:44 +00:00
parent 567948cb39
commit b4c5e64db2
26 changed files with 307 additions and 364 deletions

View File

@ -52,7 +52,9 @@ public:
enum TYPEMARKER {
MARKER_UNSPEC,
MARKER_ERC,
MARKER_PCB,
MARKER_DRC,
MARKER_RATSNEST,
MARKER_PARITY,
MARKER_SIMUL
};

View File

@ -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

View File

@ -221,13 +221,27 @@ void BOARD::IncrementTimeStamp()
std::vector<PCB_MARKER*> BOARD::ResolveDRCExclusions()
{
std::shared_ptr<CONNECTIVITY_DATA> conn = GetConnectivity();
auto setExcluded =
[&conn]( PCB_MARKER* aMarker )
{
if( aMarker->GetMarkerType() == MARKER_BASE::MARKER_RATSNEST )
{
const std::shared_ptr<RC_ITEM>& 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<PCB_MARKER*> BOARD::ResolveDRCExclusions()
if( marker )
{
marker->SetExcluded( true );
setExcluded( marker );
newMarkers.push_back( marker );
}
}

View File

@ -150,10 +150,10 @@ void CONNECTIVITY_DATA::updateRatsnest()
std::vector<std::future<size_t>> 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<CN_EDGE>& 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<KIID, KIID>( aBoardItemId1, aBoardItemId2 ) );
m_exclusions.insert( std::pair<KIID, KIID>( 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<KIID, KIID>( aBoardItemId1, aBoardItemId2 ) );
m_exclusions.erase( std::pair<KIID, KIID>( 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<CN_EDGE> CONNECTIVITY_DATA::GetRatsnestForItems( std::vector<BOARD_ITEM*> aItems )
{
std::set<int> nets;
@ -879,9 +920,9 @@ const std::vector<CN_EDGE> 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();

View File

@ -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<CN_EDGE> GetRatsnestForItems( const std::vector<BOARD_ITEM*> 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<std::pair<KIID, KIID>> m_exclusions;
KISPINLOCK m_lock;
/// Map of netcode -> netclass the net is a member of; used for ratsnest painting

View File

@ -29,6 +29,8 @@
#include <kiface_base.h>
#include <macros.h>
#include <pad.h>
#include <drc/drc_item.h>
#include <connectivity/connectivity_data.h>
#include <pcb_edit_frame.h>
#include <pcbnew_settings.h>
#include <tool/tool_manager.h>
@ -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<RC_ITEM> rcItem = node->m_RcItem;
DRC_ITEM* drcItem = static_cast<DRC_ITEM*>( rcItem.get() );
wxString listName;
wxMenu menu;
wxString msg;
std::shared_ptr<RC_ITEM> rcItem = node->m_RcItem;
DRC_ITEM* drcItem = static_cast<DRC_ITEM*>( rcItem.get() );
std::shared_ptr<CONNECTIVITY_DATA> 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<PCB_MARKER*>( node->m_RcItem->GetParent() );
PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( 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<RC_TREE_MODEL*>( aEvent.GetModel() )->ValueChanged( node );
@ -544,12 +554,19 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent )
case 2:
{
PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( node->m_RcItem->GetParent() );
PCB_MARKER* marker = dynamic_cast<PCB_MARKER*>( 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<RC_TREE_MODEL*>( aEvent.GetModel() )->SetProvider( m_markersProvider );
modified = true;

View File

@ -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();

View File

@ -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 );

View File

@ -954,17 +954,18 @@
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnDataViewCtrlItemActivated">OnDRCItemDClick</event>
<event name="OnDataViewCtrlItemContextMenu">OnDRCItemRClick</event>
<event name="OnDataViewCtrlSelectionChanged">OnDRCItemSelected</event>
</object>
</object>
</object>
</object>
</object>
<object class="notebookpage" expanded="0">
<object class="notebookpage" expanded="1">
<property name="bitmap"></property>
<property name="label">Schematic Parity (%d)</property>
<property name="select">0</property>
<object class="wxPanel" expanded="0">
<object class="wxPanel" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -1015,7 +1016,7 @@
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property>
<object class="wxBoxSizer" expanded="0">
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bSizerFootprintsBox</property>
<property name="orient">wxVERTICAL</property>
@ -1046,6 +1047,7 @@
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnDataViewCtrlItemActivated">OnDRCItemDClick</event>
<event name="OnDataViewCtrlItemContextMenu">OnDRCItemRClick</event>
<event name="OnDataViewCtrlSelectionChanged">OnDRCItemSelected</event>
</object>
</object>

View File

@ -27,7 +27,7 @@
#include <tools/pcb_actions.h>
#include <footprint.h>
#include <pcb_marker.h>
#include <drc/drc_results_provider.h>
#include <drc/drc_item.h>
#include <footprint_edit_frame.h>
#include <convert_shape_list_to_polygon.h>
#include <tools/footprint_editor_control.h>
@ -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();
}

View File

@ -33,6 +33,7 @@
#include <drc/drc_rule.h>
#include <drc/drc_rule_condition.h>
#include <drc/drc_test_provider.h>
#include <drc/drc_item.h>
#include <footprint.h>
#include <pad.h>
#include <pcb_track.h>

View File

@ -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 <drc/drc_item.h>
#include <drc/drc_rule.h>
#include <board.h>
#include <pcb_marker.h>
// 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<RC_ITEM> 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 );
}

View File

@ -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 <rc_item.h>
#include <marker_base.h>
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<RC_ITEM> 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<PCB_MARKER*> m_filteredMarkers;
};
#endif // DRC_ITEM_H

View File

@ -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 <board_design_settings.h>
#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<DRC_ITEM>& 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<DRC_ITEM>& item : *m_sourceVector )
{
if( bds.GetSeverity( item->GetErrorCode() ) == aSeverity )
count++;
}
}
return count;
}

View File

@ -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 <board.h>
#include <pcb_marker.h>
#include <pcb_base_frame.h>
#include <drc/drc_item.h>
#include <widgets/ui_common.h>
#include <functional>
/**
* 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<PCB_MARKER*> 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<RC_ITEM> 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<std::shared_ptr<DRC_ITEM> >* m_sourceVector; // owns its DRC_ITEMs
int m_severities;
std::vector<std::shared_ptr<DRC_ITEM> > m_filteredVector; // does not own its DRC_ITEMs
public:
VECTOR_DRC_ITEMS_PROVIDER( PCB_BASE_FRAME* aFrame, std::vector<std::shared_ptr<DRC_ITEM> >* 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<RC_ITEM> 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<std::shared_ptr<DRC_ITEM> >* aList ) :
VECTOR_DRC_ITEMS_PROVIDER( aFrame, aList )
{ }
};
#endif // DRC_PROVIDER__H

View File

@ -28,6 +28,7 @@
#include <pcb_shape.h>
#include <geometry/shape_poly_set.h>
#include <drc/drc_rule.h>
#include <drc/drc_item.h>
#include <drc/drc_test_provider.h>
#include <advanced_config.h>

View File

@ -31,6 +31,7 @@
#include <geometry/shape_line_chain.h>
#include <geometry/shape_poly_set.h>
#include <drc/drc_rule.h>
#include <drc/drc_item.h>
#include <drc/drc_test_provider.h>

View File

@ -49,8 +49,28 @@ PCB_MARKER::PCB_MARKER( std::shared_ptr<RC_ITEM> 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;

View File

@ -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 <board_item.h>
#include <drc/drc_item.h>
#include <rc_item.h>
#include <marker_base.h>
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

View File

@ -107,7 +107,8 @@ private:
};
void RN_NET::kruskalMST( const std::vector<CN_EDGE> &aEdges )
void RN_NET::kruskalMST( std::vector<CN_EDGE>& aEdges,
const std::set< std::pair<KIID, KIID> >& aExclusions )
{
disjoint_set dset( m_nodes.size() );
@ -118,15 +119,20 @@ void RN_NET::kruskalMST( const std::vector<CN_EDGE> &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<KIID, KIID> 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<CN_EDGE>& mstEdges)
void Triangulate( std::vector<CN_EDGE>& mstEdges )
{
std::vector<double> node_pts;
std::vector<CN_ANCHOR_PTR> 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<KIID, KIID> >& 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<KIID, KIID> 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<KIID, KIID> >& 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 );
}

View File

@ -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<CN_EDGE> GetUnconnected() const { return m_rnEdges; }
/**
* Recompute ratsnest for a net.
*/
void Update();
void Update( const std::set< std::pair<KIID, KIID> >& aExclusions );
void Clear();
void AddCluster( std::shared_ptr<CN_CLUSTER> aCluster );
@ -100,16 +87,18 @@ public:
unsigned int GetNodeCount() const { return m_nodes.size(); }
const std::vector<CN_EDGE>& GetEdges() const { return m_rnEdges; }
std::vector<CN_EDGE>& 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<KIID, KIID> >& aExclusions );
///< Compute the minimum spanning tree using Kruskal's algorithm
void kruskalMST( const std::vector<CN_EDGE> &aEdges );
void kruskalMST( std::vector<CN_EDGE>& aEdges,
const std::set< std::pair<KIID, KIID> >& aExclusions );
///< Vector of nodes
std::multiset<CN_ANCHOR_PTR, CN_PTR_CMP> m_nodes;

View File

@ -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();

View File

@ -35,7 +35,7 @@
#include <board_design_settings.h>
#include <progress_reporter.h>
#include <drc/drc_engine.h>
#include <drc/drc_results_provider.h>
#include <drc/drc_item.h>
#include <netlist_reader/pcb_netlist.h>
DRC_TOOL::DRC_TOOL() :
@ -174,22 +174,8 @@ void DRC_TOOL::RunTests( PROGRESS_REPORTER* aProgressReporter, bool aRefillZones
m_drcEngine->SetViolationHandler(
[&]( const std::shared_ptr<DRC_ITEM>& 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 ) );
}
}

View File

@ -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<DRC_ENGINE> m_drcEngine;
std::vector<std::shared_ptr<DRC_ITEM>> m_unconnected; // list of unconnected pads
std::vector<std::shared_ptr<DRC_ITEM>> 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<DRC_ENGINE> m_drcEngine;
};

View File

@ -43,7 +43,7 @@
#include <dialogs/dialog_footprint_checker.h>
#include <footprint_wizard_frame.h>
#include <kiway.h>
#include <drc/drc_results_provider.h>
#include <drc/drc_item.h>
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;

View File

@ -24,6 +24,7 @@
#include <qa_utils/wx_utils/unit_test_utils.h>
#include <eda_item_test_utils.h>
#include <core/typeinfo.h>
#include <drc/drc_item.h>
// Code under test
#include <board.h>