Off-grid ERC warnings.

Fixes https://gitlab.com/kicad/code/kicad/issues/10379
This commit is contained in:
Jeff Young 2022-03-17 20:23:14 +00:00
parent 77c52ad5df
commit 41c0009c51
8 changed files with 96 additions and 5 deletions

View File

@ -495,6 +495,12 @@ void DIALOG_ERC::testErc()
tester.TestLibSymbolIssues();
}
if( settings.IsTestEnabled( ERCE_ENDPOINT_OFF_GRID ) )
{
AdvancePhase( _( "Checking for off grid pins and wires..." ) );
tester.TestOffGridEndpoints( m_parent->GetCanvas()->GetView()->GetGAL()->GetGridSize().x );
}
m_parent->ResolveERCExclusions();
// Display diags:

View File

@ -34,6 +34,8 @@
#include <sch_sheet.h>
#include <sch_sheet_pin.h>
#include <sch_textbox.h>
#include <sch_line.h>
#include <sch_pin.h>
#include <schematic.h>
#include <drawing_sheet/ds_draw_item.h>
#include <drawing_sheet/ds_proxy_view_item.h>
@ -705,10 +707,7 @@ int ERC_TESTER::TestLibSymbolIssues()
for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
{
SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item );
wxCHECK2( symbol, continue );
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
LIB_SYMBOL* libSymbolInSchematic = symbol->GetLibSymbolRef().get();
wxCHECK2( libSymbolInSchematic, continue );
@ -780,3 +779,75 @@ int ERC_TESTER::TestLibSymbolIssues()
return err_count;
}
int ERC_TESTER::TestOffGridEndpoints( int aGridSize )
{
// The minimal grid size allowed to place a pin is 25 mils
// the best grid size is 50 mils, but 25 mils is still usable
// this is because all symbols are using a 50 mils grid to place pins, and therefore
// the wires must be on the 50 mils grid
// So raise an error if a pin is not on a 25 mil (or bigger: 50 mil or 100 mil) grid
const int min_grid_size = Mils2iu( 25 );
const int clamped_grid_size = ( aGridSize < min_grid_size ) ? min_grid_size : aGridSize;
SCH_SCREENS screens( m_schematic->Root() );
int err_count = 0;
for( SCH_SCREEN* screen = screens.GetFirst(); screen != nullptr; screen = screens.GetNext() )
{
std::vector<SCH_MARKER*> markers;
for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
{
if( item->Type() == SCH_LINE_T && item->IsConnectable() )
{
SCH_LINE* line = static_cast<SCH_LINE*>( item );
if( ( line->GetStartPoint().x % clamped_grid_size ) != 0
|| ( line->GetStartPoint().y % clamped_grid_size) != 0 )
{
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_ENDPOINT_OFF_GRID );
ercItem->SetItems( line );
markers.emplace_back( new SCH_MARKER( ercItem, line->GetStartPoint() ) );
}
else if( ( line->GetEndPoint().x % clamped_grid_size ) != 0
|| ( line->GetEndPoint().y % clamped_grid_size) != 0 )
{
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_ENDPOINT_OFF_GRID );
ercItem->SetItems( line );
markers.emplace_back( new SCH_MARKER( ercItem, line->GetEndPoint() ) );
}
}
else if( item->Type() == SCH_SYMBOL_T )
{
SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
for( SCH_PIN* pin : symbol->GetPins( nullptr ) )
{
VECTOR2I pinPos = pin->GetTransformedPosition();
if( ( pinPos.x % clamped_grid_size ) != 0
|| ( pinPos.y % clamped_grid_size) != 0 )
{
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_ENDPOINT_OFF_GRID );
ercItem->SetItems( pin );
markers.emplace_back( new SCH_MARKER( ercItem, pinPos ) );
break;
}
}
}
}
for( SCH_MARKER* marker : markers )
{
screen->Append( marker );
err_count += 1;
}
}
return err_count;
}

View File

@ -128,6 +128,12 @@ public:
*/
int TestLibSymbolIssues();
/**
* Test pins and wire ends for being off grid.
* @return the error count
*/
int TestOffGridEndpoints( int aGridSize );
private:
SCHEMATIC* m_schematic;

View File

@ -46,6 +46,10 @@ ERC_ITEM ERC_ITEM::duplicateSheetName( ERCE_DUPLICATE_SHEET_NAME,
_( "Duplicate sheet names within a given sheet" ),
wxT( "duplicate_sheet_names" ) );
ERC_ITEM ERC_ITEM::endpointOffGrid( ERCE_ENDPOINT_OFF_GRID,
_( "Symbol pin or wire end off grid" ),
wxT( "endpoint_off_grid" ) );
ERC_ITEM ERC_ITEM::pinNotConnected( ERCE_PIN_NOT_CONNECTED,
_( "Pin not connected" ),
wxT( "pin_not_connected" ) );
@ -196,6 +200,7 @@ std::shared_ptr<ERC_ITEM> ERC_ITEM::Create( int aErrorCode )
switch( aErrorCode )
{
case ERCE_DUPLICATE_SHEET_NAME: return std::make_shared<ERC_ITEM>( duplicateSheetName );
case ERCE_ENDPOINT_OFF_GRID: return std::make_shared<ERC_ITEM>( endpointOffGrid );
case ERCE_PIN_NOT_CONNECTED: return std::make_shared<ERC_ITEM>( pinNotConnected );
case ERCE_PIN_NOT_DRIVEN: return std::make_shared<ERC_ITEM>( pinNotDriven );
case ERCE_POWERPIN_NOT_DRIVEN: return std::make_shared<ERC_ITEM>( powerpinNotDriven );

View File

@ -72,6 +72,7 @@ private:
static ERC_ITEM heading_misc;
static ERC_ITEM duplicateSheetName;
static ERC_ITEM endpointOffGrid;
static ERC_ITEM pinNotConnected;
static ERC_ITEM pinNotDriven;
static ERC_ITEM powerpinNotDriven;

View File

@ -94,6 +94,7 @@ ERC_SETTINGS::ERC_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) :
// Error is the default setting so set non-error priorities here.
m_Severities[ERCE_UNSPECIFIED] = RPT_SEVERITY_UNDEFINED;
m_Severities[ERCE_ENDPOINT_OFF_GRID] = RPT_SEVERITY_WARNING;
m_Severities[ERCE_PIN_TO_PIN_WARNING] = RPT_SEVERITY_WARNING;
m_Severities[ERCE_SIMILAR_LABELS] = RPT_SEVERITY_WARNING;
m_Severities[ERCE_GLOBLABEL] = RPT_SEVERITY_WARNING;

View File

@ -38,6 +38,7 @@ enum ERCE_T
ERCE_UNSPECIFIED = 0,
ERCE_FIRST,
ERCE_DUPLICATE_SHEET_NAME = ERCE_FIRST, ///< Duplicate sheet names within a given sheet.
ERCE_ENDPOINT_OFF_GRID, ///< Pin or wire-end off grid.
ERCE_PIN_NOT_CONNECTED, ///< Pin not connected and not no connect symbol.
ERCE_PIN_NOT_DRIVEN, ///< Pin connected to some others pins but no pin to drive it.
///< pins to drive it can be output, passive, 3sttae, I/O

View File

@ -888,7 +888,7 @@ std::vector<SCH_PIN*> SCH_SYMBOL::GetPins( const SCH_SHEET_PATH* aSheet ) const
int unit = GetUnitSelection( aSheet );
for( const auto& p : m_pins )
for( const std::unique_ptr<SCH_PIN>& p : m_pins )
{
if( unit && p->GetLibPin()->GetUnit() && ( p->GetLibPin()->GetUnit() != unit ) )
continue;