kicad/pcbnew/drc/drc_test_provider.cpp

277 lines
7.1 KiB
C++
Raw Normal View History

/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020 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 <drc/drc_engine.h>
#include <drc/drc_item.h>
2020-09-11 15:40:36 +00:00
#include <drc/drc_test_provider.h>
#include <class_track.h>
#include <class_module.h>
#include <class_pad.h>
#include <class_zone.h>
2020-06-13 23:28:08 +00:00
DRC_TEST_PROVIDER::DRC_TEST_PROVIDER() :
2020-09-11 21:50:53 +00:00
m_drcEngine( nullptr )
2020-06-13 23:28:08 +00:00
{
}
const wxString DRC_TEST_PROVIDER::GetName() const { return "<no name test>"; }
const wxString DRC_TEST_PROVIDER::GetDescription() const { return ""; }
2020-06-13 23:28:08 +00:00
2020-09-14 17:54:14 +00:00
void DRC_TEST_PROVIDER::reportViolation( std::shared_ptr<DRC_ITEM> item, wxPoint aMarkerPos )
{
2020-09-14 17:54:14 +00:00
item->SetViolatingTest( this );
m_drcEngine->ReportViolation( item, aMarkerPos );
}
2020-09-14 17:54:14 +00:00
void DRC_TEST_PROVIDER::reportProgress( double aProgress )
{
m_drcEngine->ReportProgress( aProgress );
}
2020-09-14 17:54:14 +00:00
void DRC_TEST_PROVIDER::reportStage( const wxString& aStageName )
{
2020-09-14 17:54:14 +00:00
m_drcEngine->ReportStage( aStageName );
reportAux( aStageName );
}
2020-09-14 17:54:14 +00:00
void DRC_TEST_PROVIDER::reportAux( wxString fmt, ... )
{
va_list vargs;
va_start( vargs, fmt );
wxString str;
str.PrintfV( fmt, vargs );
va_end( vargs );
m_drcEngine->ReportAux( str );
}
EDA_UNITS DRC_TEST_PROVIDER::userUnits() const
2020-06-13 23:28:08 +00:00
{
return m_drcEngine->UserUnits();
}
void DRC_TEST_PROVIDER::accountCheck( const DRC_RULE* ruleToTest )
{
auto it = m_stats.find( ruleToTest );
if( it == m_stats.end() )
m_stats[ ruleToTest ] = 1;
else
2020-09-14 17:54:14 +00:00
m_stats[ ruleToTest ] += 1;
}
2020-07-27 13:32:37 +00:00
void DRC_TEST_PROVIDER::accountCheck( const DRC_CONSTRAINT& constraintToTest )
{
accountCheck( constraintToTest.GetParentRule() );
}
void DRC_TEST_PROVIDER::reportRuleStatistics()
2020-07-27 13:32:37 +00:00
{
if( !m_isRuleDriven )
return;
2020-09-14 17:54:14 +00:00
m_drcEngine->ReportAux( "Rule hit statistics: " );
for( const std::pair<const DRC_RULE* const, int>& stat : m_stats )
2020-07-27 13:32:37 +00:00
{
2020-09-14 17:54:14 +00:00
if( stat.first )
{
m_drcEngine->ReportAux( wxString::Format( " - rule '%s': %d hits ",
stat.first->m_Name,
stat.second ) );
}
2020-07-27 13:32:37 +00:00
}
}
int DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T>& aTypes, LSET aLayers,
const std::function<bool( BOARD_ITEM*)>& aFunc )
{
BOARD *brd = m_drcEngine->GetBoard();
std::bitset<MAX_STRUCT_TYPE_ID> typeMask;
int n = 0;
if( aTypes.size() == 0 )
{
for( int i = 0; i < MAX_STRUCT_TYPE_ID; i++ )
typeMask[ i ] = true;
}
else
{
for( KICAD_T aType : aTypes )
typeMask[ aType ] = true;
}
for( TRACK* item : brd->Tracks() )
{
if( (item->GetLayerSet() & aLayers).any() )
{
if( typeMask[ PCB_TRACE_T ] && item->Type() == PCB_TRACE_T )
{
aFunc( item );
n++;
}
else if( typeMask[ PCB_VIA_T ] && item->Type() == PCB_VIA_T )
{
aFunc( item );
n++;
}
else if( typeMask[ PCB_ARC_T ] && item->Type() == PCB_ARC_T )
{
aFunc( item );
n++;
}
}
}
for( BOARD_ITEM* item : brd->Drawings() )
{
if( (item->GetLayerSet() & aLayers).any() )
{
if( typeMask[ PCB_DIMENSION_T ] && item->Type() == PCB_DIMENSION_T )
{
if( !aFunc( item ) )
return n;
n++;
}
else if( typeMask[ PCB_LINE_T ] && item->Type() == PCB_LINE_T )
{
if( !aFunc( item ) )
return n;
n++;
}
else if( typeMask[ PCB_TEXT_T ] && item->Type() == PCB_TEXT_T )
{
if( !aFunc( item ) )
return n;
n++;
}
else if( typeMask[ PCB_TARGET_T ] && item->Type() == PCB_TARGET_T )
{
if( !aFunc( item ) )
return n;
n++;
}
}
}
for( ZONE_CONTAINER* item : brd->Zones() )
{
if( (item->GetLayerSet() & aLayers).any() )
{
if( typeMask[ PCB_ZONE_AREA_T ] && item->Type() == PCB_ZONE_AREA_T )
{
if( !aFunc( item ) )
return n;
n++;
}
}
}
for( MODULE* mod : brd->Modules() )
{
if( typeMask[ PCB_MODULE_TEXT_T ] )
{
if( (mod->Reference().GetLayerSet() & aLayers).any() )
{
if( !aFunc( &mod->Reference() ) )
return n;
n++;
}
if( (mod->Value().GetLayerSet() & aLayers).any() )
{
if( !aFunc( &mod->Value() ) )
return n;
n++;
}
}
for( D_PAD* pad : mod->Pads() )
{
if( (pad->GetLayerSet() & aLayers).any() )
{
if( typeMask[ PCB_PAD_T ] && pad->Type() == PCB_PAD_T )
{
if( !aFunc( pad ) )
return n;
n++;
}
}
}
for( BOARD_ITEM* dwg : mod->GraphicalItems() )
{
if( (dwg->GetLayerSet() & aLayers).any() )
{
if( typeMask[ PCB_MODULE_TEXT_T ] && dwg->Type() == PCB_MODULE_TEXT_T )
{
if( !aFunc( dwg ) )
return n;
n++;
}
else if( typeMask[ PCB_MODULE_EDGE_T ] && dwg->Type() == PCB_MODULE_EDGE_T )
{
if( !aFunc( dwg ) )
return n;
n++;
}
}
}
for( ZONE_CONTAINER* zone : mod->Zones() )
{
if( (zone->GetLayerSet() & aLayers).any() )
{
if( typeMask[ PCB_MODULE_ZONE_AREA_T ] && zone->Type() == PCB_MODULE_ZONE_AREA_T )
{
if( ! aFunc( zone ) )
return n;
n++;
}
}
}
}
return n;
}