Better error reporting for PTH pads.

This commit is contained in:
Jeff Young 2022-03-15 16:43:28 +00:00
parent cabcaf933c
commit 62f813fddc
3 changed files with 84 additions and 24 deletions

View File

@ -170,6 +170,8 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
m_DRCSeverities[ DRCE_COPPER_SLIVER ] = RPT_SEVERITY_WARNING;
m_DRCSeverities[ DRCE_ISOLATED_COPPER ] = RPT_SEVERITY_WARNING;
m_DRCSeverities[ DRCE_PADSTACK ] = RPT_SEVERITY_WARNING;
m_DRCSeverities[ DRCE_MISSING_FOOTPRINT ] = RPT_SEVERITY_WARNING;
m_DRCSeverities[ DRCE_DUPLICATE_FOOTPRINT ] = RPT_SEVERITY_WARNING;
m_DRCSeverities[ DRCE_EXTRA_FOOTPRINT ] = RPT_SEVERITY_WARNING;

View File

@ -1249,8 +1249,8 @@ bool DIALOG_PAD_PROPERTIES::padValuesOK()
warning_msgs.Add( _( "Warning: Pad size is less than zero." ) );
}
// Test hole size against pad size
if( m_dummyPad->IsOnCopperLayer() )
// Test hole against pad shape
if( m_dummyPad->IsOnCopperLayer() && m_dummyPad->GetDrillSize().x > 0 )
{
LSET lset = m_dummyPad->GetLayerSet() & LSET::AllCuMask();
PCB_LAYER_ID layer = lset.Seq().at( 0 );
@ -1260,19 +1260,23 @@ bool DIALOG_PAD_PROPERTIES::padValuesOK()
m_dummyPad->TransformShapeWithClearanceToPolygon( padOutline, layer, 0, maxError,
ERROR_LOC::ERROR_INSIDE );
const SHAPE_SEGMENT* drillShape = m_dummyPad->GetEffectiveHoleShape();
const SEG drillSeg = drillShape->GetSeg();
SHAPE_POLY_SET drillOutline;
TransformOvalToPolygon( drillOutline, drillSeg.A, drillSeg.B,
drillShape->GetWidth(), maxError, ERROR_LOC::ERROR_INSIDE );
drillOutline.BooleanSubtract( padOutline, SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
if( drillOutline.BBox().GetWidth() > 0 || drillOutline.BBox().GetHeight() > 0 )
if( !padOutline.Collide( m_dummyPad->GetPosition() ) )
{
warning_msgs.Add( _( "Warning: Pad drill will leave no copper or drill shape and "
"pad shape do not overlap." ) );
warning_msgs.Add( _( "Warning: Pad hole not inside pad shape." ) );
}
else if( m_dummyPad->GetAttribute() == PAD_ATTRIB::PTH )
{
const SHAPE_SEGMENT* drillShape = m_dummyPad->GetEffectiveHoleShape();
const SEG drillSeg = drillShape->GetSeg();
SHAPE_POLY_SET drillOutline;
TransformOvalToPolygon( drillOutline, drillSeg.A, drillSeg.B,
drillShape->GetWidth(), maxError, ERROR_LOC::ERROR_INSIDE );
padOutline.BooleanSubtract( drillOutline, SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
if( padOutline.IsEmpty() )
warning_msgs.Add( _( "Warning: Pad hole will leave no copper." ) );
}
}

View File

@ -21,20 +21,23 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <geometry/shape_segment.h>
#include <footprint.h>
#include <pad.h>
#include <pcb_track.h>
#include <board_design_settings.h>
#include <drc/drc_engine.h>
#include <drc/drc_item.h>
#include <drc/drc_rule.h>
#include <drc/drc_test_provider_clearance_base.h>
#include "convert_basic_shapes_to_polygon.h"
/*
Drilled hole size test. scans vias/through-hole pads and checks for min drill sizes
Errors generated:
- DRCE_DRILL_OUT_OF_RANGE
- DRCE_MICROVIA_DRILL_OUT_OF_RANGE
- DRCE_PADSTACK
*/
class DRC_TEST_PROVIDER_HOLE_SIZE : public DRC_TEST_PROVIDER
@ -61,8 +64,9 @@ public:
}
private:
void checkVia( PCB_VIA* via, bool aExceedMicro, bool aExceedStd );
void checkPad( PAD* aPad );
void checkViaHole( PCB_VIA* via, bool aExceedMicro, bool aExceedStd );
void checkPadHole( PAD* aPad );
void checkPadStack( PAD* aPad );
};
@ -75,15 +79,19 @@ bool DRC_TEST_PROVIDER_HOLE_SIZE::Run()
for( FOOTPRINT* footprint : m_drcEngine->GetBoard()->Footprints() )
{
if( m_drcEngine->IsErrorLimitExceeded( DRCE_DRILL_OUT_OF_RANGE ) )
if( m_drcEngine->IsErrorLimitExceeded( DRCE_DRILL_OUT_OF_RANGE )
&& m_drcEngine->IsErrorLimitExceeded( DRCE_PADSTACK ) )
{
break;
}
for( PAD* pad : footprint->Pads() )
{
if( m_drcEngine->IsErrorLimitExceeded( DRCE_DRILL_OUT_OF_RANGE ) )
break;
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_DRILL_OUT_OF_RANGE ) )
checkPadHole( pad );
checkPad( pad );
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_PADSTACK ) )
checkPadStack( pad );
}
}
}
@ -112,7 +120,7 @@ bool DRC_TEST_PROVIDER_HOLE_SIZE::Run()
if( exceedMicro && exceedStd )
break;
checkVia( static_cast<PCB_VIA*>( track ), exceedMicro, exceedStd );
checkViaHole( static_cast<PCB_VIA*>( track ), exceedMicro, exceedStd );
}
}
}
@ -122,8 +130,54 @@ bool DRC_TEST_PROVIDER_HOLE_SIZE::Run()
return !m_drcEngine->IsCancelled();
}
void DRC_TEST_PROVIDER_HOLE_SIZE::checkPadStack( PAD* aPad )
{
if( aPad->GetAttribute() == PAD_ATTRIB::PTH )
{
if( !aPad->IsOnCopperLayer() )
{
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_PADSTACK );
m_msg.Printf( _( " (PTH pad has no copper layers)" ) );
void DRC_TEST_PROVIDER_HOLE_SIZE::checkPad( PAD* aPad )
drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + m_msg );
drcItem->SetItems( aPad );
reportViolation( drcItem, aPad->GetPosition(), UNDEFINED_LAYER );
}
else
{
LSET lset = aPad->GetLayerSet() & LSET::AllCuMask();
PCB_LAYER_ID layer = lset.Seq().at( 0 );
int maxError = m_drcEngine->GetBoard()->GetDesignSettings().m_MaxError;
SHAPE_POLY_SET padOutline;
aPad->TransformShapeWithClearanceToPolygon( padOutline, layer, 0, maxError,
ERROR_LOC::ERROR_INSIDE );
const SHAPE_SEGMENT* drillShape = aPad->GetEffectiveHoleShape();
const SEG drillSeg = drillShape->GetSeg();
SHAPE_POLY_SET drillOutline;
TransformOvalToPolygon( drillOutline, drillSeg.A, drillSeg.B,
drillShape->GetWidth(), maxError, ERROR_LOC::ERROR_INSIDE );
padOutline.BooleanSubtract( drillOutline, SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
if( padOutline.IsEmpty() )
{
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_PADSTACK );
m_msg.Printf( _( " (PTH pad's hole leaves no copper)" ) );
drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + m_msg );
drcItem->SetItems( aPad );
reportViolation( drcItem, aPad->GetPosition(), UNDEFINED_LAYER );
}
}
}
}
void DRC_TEST_PROVIDER_HOLE_SIZE::checkPadHole( PAD* aPad )
{
int holeMinor = std::min( aPad->GetDrillSize().x, aPad->GetDrillSize().y );
int holeMajor = std::max( aPad->GetDrillSize().x, aPad->GetDrillSize().y );
@ -180,7 +234,7 @@ void DRC_TEST_PROVIDER_HOLE_SIZE::checkPad( PAD* aPad )
}
void DRC_TEST_PROVIDER_HOLE_SIZE::checkVia( PCB_VIA* via, bool aExceedMicro, bool aExceedStd )
void DRC_TEST_PROVIDER_HOLE_SIZE::checkViaHole( PCB_VIA* via, bool aExceedMicro, bool aExceedStd )
{
int errorCode;