Add distances to a bunch of DRC violation reports.

This commit is contained in:
Jeff Young 2020-04-26 11:30:32 +01:00
parent 7e1294a4b7
commit a56191b658
7 changed files with 418 additions and 1188 deletions

View File

@ -67,6 +67,18 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin
SetLayoutDirection( wxLayout_LeftToRight );
// If we're in a dialog, we have to go looking for our parent frame
if( !m_edaFrame )
{
wxWindow* ancestor = aParentWindow->GetParent();
while( ancestor && !dynamic_cast<EDA_DRAW_FRAME*>( ancestor ) )
ancestor = ancestor->GetParent();
if( ancestor )
m_edaFrame = dynamic_cast<EDA_DRAW_FRAME*>( ancestor );
}
SwitchBackend( aGalType );
SetBackgroundStyle( wxBG_STYLE_CUSTOM );

View File

@ -941,7 +941,7 @@ void SCH_SHEET::GetNetListItem( NETLIST_OBJECT_LIST& aNetListItems, SCH_SHEET_PA
item->m_Start = item->m_End = sheetPin->GetPosition();
aNetListItems.push_back( item );
if( SCH_CONNECTION::IsBusLabel( sheetPin->GetText() ) )
if( SCH_CONNECTION::IsBusLabel( sheetPin->GetShownText() ) )
item->ConvertBusToNetListItems( aNetListItems );
}
}

View File

@ -93,6 +93,8 @@ public:
/// @copydoc SHAPE::Collide()
bool Collide( const SEG& aSeg, int aClearance = 0 ) const override;
bool DoCollide( const SEG& aSeg, int aClearance, int* aActualDist ) const;
/**
* Function GetPosition()
*

View File

@ -562,28 +562,38 @@ bool SHAPE::Collide( const SHAPE* aShape, int aClearance ) const
bool SHAPE_RECT::Collide( const SEG& aSeg, int aClearance ) const
{
//VECTOR2I pmin = VECTOR2I( std::min( aSeg.a.x, aSeg.b.x ), std::min( aSeg.a.y, aSeg.b.y ) );
//VECTOR2I pmax = VECTOR2I( std::max( aSeg.a.x, aSeg.b.x ), std::max( aSeg.a.y, aSeg.b.y ));
//BOX2I r( pmin, VECTOR2I( pmax.x - pmin.x, pmax.y - pmin.y ) );
int dummy;
return DoCollide( aSeg, aClearance, &dummy );
}
//if( BBox( 0 ).SquaredDistance( r ) > aClearance * aClearance )
// return false;
bool SHAPE_RECT::DoCollide( const SEG& aSeg, int aClearance, int* aActualDist ) const
{
if( BBox( 0 ).Contains( aSeg.A ) || BBox( 0 ).Contains( aSeg.B ) )
{
*aActualDist = 0;
return true;
}
VECTOR2I vts[] = { VECTOR2I( m_p0.x, m_p0.y ),
VECTOR2I( m_p0.x, m_p0.y + m_h ),
VECTOR2I( m_p0.x + m_w, m_p0.y + m_h ),
VECTOR2I( m_p0.x + m_w, m_p0.y ),
VECTOR2I( m_p0.x, m_p0.y ) };
VECTOR2I( m_p0.x, m_p0.y + m_h ),
VECTOR2I( m_p0.x + m_w, m_p0.y + m_h ),
VECTOR2I( m_p0.x + m_w, m_p0.y ),
VECTOR2I( m_p0.x, m_p0.y ) };
for( int i = 0; i < 4; i++ )
SEG s( vts[0], vts[1] );
SEG::ecoord dist_squared = s.SquaredDistance( aSeg );
for( int i = 1; i < 4; i++ )
{
SEG s( vts[i], vts[i + 1], i );
s = SEG( vts[i], vts[i + 1] );
dist_squared = std::min( dist_squared, s.SquaredDistance( aSeg ) );
}
if( s.Distance( aSeg ) < aClearance )
return true;
if( dist_squared < SEG::ecoord( aClearance ) * SEG::ecoord( aClearance ) )
{
*aActualDist = sqrt( dist_squared );
return true;
}
return false;

View File

@ -72,14 +72,6 @@ DRC::DRC() :
m_drcRun = false;
m_footprintsTested = false;
m_segmAngle = 0;
m_segmLength = 0;
m_xcliplo = 0;
m_ycliplo = 0;
m_xcliphi = 0;
m_ycliphi = 0;
}
@ -178,8 +170,9 @@ void DRC::DestroyDRCDialog( int aReason )
int DRC::TestZoneToZoneOutlines()
{
BOARD* board = m_pcbEditorFrame->GetBoard();
int nerrors = 0;
BOARD* board = m_pcbEditorFrame->GetBoard();
int nerrors = 0;
wxString msg;
std::vector<SHAPE_POLY_SET> smoothed_polys;
smoothed_polys.resize( board->GetAreaCount() );
@ -273,7 +266,7 @@ int DRC::TestZoneToZoneOutlines()
}
// Iterate through all the segments of refSmoothedPoly
std::set<wxPoint> conflictPoints;
std::map<wxPoint, int> conflictPoints;
for( auto refIt = smoothed_polys[ia].IterateSegmentsWithHoles(); refIt; refIt++ )
{
@ -307,16 +300,27 @@ int DRC::TestZoneToZoneOutlines()
&pt.x, &pt.y );
if( d < zone2zoneClearance )
conflictPoints.insert( pt );
{
if( conflictPoints.count( pt ) )
conflictPoints[ pt ] = std::min( conflictPoints[ pt ], d );
else
conflictPoints[ pt ] = d;
}
}
}
for( wxPoint pt : conflictPoints )
for( const std::pair<const wxPoint, int>& conflict : conflictPoints )
{
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_ZONES_TOO_CLOSE );
msg.Printf( drcItem->GetErrorText() + _( "(minimum %s; actual %s)" ),
MessageTextFromValue( userUnits(), zone2zoneClearance ),
MessageTextFromValue( userUnits(), conflict.second ) );
drcItem->SetErrorMessage( msg );
drcItem->SetItems( zoneRef, zoneToTest );
MARKER_PCB* marker = new MARKER_PCB( drcItem, pt );
MARKER_PCB* marker = new MARKER_PCB( drcItem, conflict.first );
addMarkerToPcb( marker );
nerrors++;
}
@ -534,17 +538,16 @@ bool DRC::doNetClass( const NETCLASSPTR& nc, wxString& msg )
const BOARD_DESIGN_SETTINGS& g = m_pcb->GetDesignSettings();
#define FmtVal( x ) GetChars( StringFromValue( m_pcbEditorFrame->GetUserUnits(), x ) )
#if 0 // set to 1 when (if...) BOARD_DESIGN_SETTINGS has a m_MinClearance value
if( nc->GetClearance() < g.m_MinClearance )
{
msg.Printf( _( "NETCLASS: \"%s\" has Clearance:%s which is less than global:%s" ),
nc->GetName(),
FmtVal( nc->GetClearance() ),
FmtVal( g.m_TrackClearance ) );
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_NETCLASS_CLEARANCE );
msg.Printf( drcItem->GetErrorText() + _( "(global minimum %s; '%s' minimum %s)" ),
MessageTextFromValue( userUnits(), g.m_TrackClearance, true ),
nc->GetName(),
MessageTextFromValue( userUnits(), nc->GetClearance(), true ) );
drcItem->SetErrorMessage( msg );
addMarkerToPcb( new MARKER_PCB( drcItem, wxPoint() ) );
ret = false;
@ -553,12 +556,13 @@ bool DRC::doNetClass( const NETCLASSPTR& nc, wxString& msg )
if( nc->GetTrackWidth() < g.m_TrackMinWidth )
{
msg.Printf( _( "NETCLASS: \"%s\" has TrackWidth:%s which is less than global:%s" ),
nc->GetName(),
FmtVal( nc->GetTrackWidth() ),
FmtVal( g.m_TrackMinWidth ) );
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_NETCLASS_TRACKWIDTH );
msg.Printf( drcItem->GetErrorText() + _( "(global minimum %s; '%s' minimum %s)" ),
MessageTextFromValue( userUnits(), g.m_TrackMinWidth, true ),
nc->GetName(),
MessageTextFromValue( userUnits(), nc->GetTrackWidth(), true ) );
drcItem->SetErrorMessage( msg );
addMarkerToPcb( new MARKER_PCB( drcItem, wxPoint() ) );
ret = false;
@ -566,12 +570,13 @@ bool DRC::doNetClass( const NETCLASSPTR& nc, wxString& msg )
if( nc->GetViaDiameter() < g.m_ViasMinSize )
{
msg.Printf( _( "NETCLASS: \"%s\" has Via Dia:%s which is less than global:%s" ),
nc->GetName(),
FmtVal( nc->GetViaDiameter() ),
FmtVal( g.m_ViasMinSize ) );
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_NETCLASS_VIASIZE );
msg.Printf( drcItem->GetErrorText() + _( "(global minimum %s; '%s' minimum %s)" ),
MessageTextFromValue( userUnits(), g.m_ViasMinSize, true ),
nc->GetName(),
MessageTextFromValue( userUnits(), nc->GetViaDiameter(), true ) );
drcItem->SetErrorMessage( msg );
addMarkerToPcb( new MARKER_PCB( drcItem, wxPoint() ) );
ret = false;
@ -579,12 +584,13 @@ bool DRC::doNetClass( const NETCLASSPTR& nc, wxString& msg )
if( nc->GetViaDrill() < g.m_ViasMinDrill )
{
msg.Printf( _( "NETCLASS: \"%s\" has Via Drill:%s which is less than global:%s" ),
nc->GetName(),
FmtVal( nc->GetViaDrill() ),
FmtVal( g.m_ViasMinDrill ) );
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_NETCLASS_VIADRILLSIZE );
msg.Printf( drcItem->GetErrorText() + _( "(global minimum %s; '%s' minimum %s)" ),
MessageTextFromValue( userUnits(), g.m_ViasMinDrill, true ),
nc->GetName(),
MessageTextFromValue( userUnits(), nc->GetViaDrill(), true ) );
drcItem->SetErrorMessage( msg );
addMarkerToPcb( new MARKER_PCB( drcItem, wxPoint() ) );
ret = false;
@ -592,12 +598,13 @@ bool DRC::doNetClass( const NETCLASSPTR& nc, wxString& msg )
if( nc->GetuViaDiameter() < g.m_MicroViasMinSize )
{
msg.Printf( _( "NETCLASS: \"%s\" has uVia Dia:%s which is less than global:%s" ),
nc->GetName(),
FmtVal( nc->GetuViaDiameter() ),
FmtVal( g.m_MicroViasMinSize ) );
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_NETCLASS_uVIASIZE );
msg.Printf( drcItem->GetErrorText() + _( "(global minimum %s; '%s' minimum %s)" ),
MessageTextFromValue( userUnits(), g.m_MicroViasMinSize, true ),
nc->GetName(),
MessageTextFromValue( userUnits(), nc->GetuViaDiameter(), true ) );
drcItem->SetErrorMessage( msg );
addMarkerToPcb( new MARKER_PCB( drcItem, wxPoint() ) );
ret = false;
@ -605,12 +612,13 @@ bool DRC::doNetClass( const NETCLASSPTR& nc, wxString& msg )
if( nc->GetuViaDrill() < g.m_MicroViasMinDrill )
{
msg.Printf( _( "NETCLASS: \"%s\" has uVia Drill:%s which is less than global:%s" ),
nc->GetName(),
FmtVal( nc->GetuViaDrill() ),
FmtVal( g.m_MicroViasMinDrill ) );
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_NETCLASS_uVIADRILLSIZE );
msg.Printf( drcItem->GetErrorText() + _( "(global minimum %s; '%s' minimum %s)" ),
MessageTextFromValue( userUnits(), g.m_MicroViasMinDrill, true ),
nc->GetName(),
MessageTextFromValue( userUnits(), nc->GetuViaDrill(), true ) );
drcItem->SetErrorMessage( msg );
addMarkerToPcb( new MARKER_PCB( drcItem, wxPoint() ) );
ret = false;
@ -1046,7 +1054,7 @@ void DRC::testCopperDrawItem( DRAWSEGMENT* aItem )
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_VIA_NEAR_COPPER );
drcItem->SetItems( track, aItem );
wxPoint pos = getLocation( track, aItem, itemSeg );
wxPoint pos = getLocation( track, itemSeg );
MARKER_PCB* marker = new MARKER_PCB( drcItem, pos );
addMarkerToPcb( marker );
}
@ -1055,7 +1063,7 @@ void DRC::testCopperDrawItem( DRAWSEGMENT* aItem )
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_COPPER );
drcItem->SetItems( track, aItem );
wxPoint pos = getLocation( track, aItem, itemSeg );
wxPoint pos = getLocation( track, itemSeg );
MARKER_PCB* marker = new MARKER_PCB( drcItem, pos );
addMarkerToPcb( marker );
}
@ -1136,7 +1144,7 @@ void DRC::testCopperTextItem( BOARD_ITEM* aTextItem )
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_VIA_NEAR_COPPER );
drcItem->SetItems( track, aTextItem );
wxPoint pos = getLocation( track, aTextItem, textSeg );
wxPoint pos = getLocation( track, textSeg );
MARKER_PCB* marker = new MARKER_PCB( drcItem, pos );
addMarkerToPcb( marker );
}
@ -1145,7 +1153,7 @@ void DRC::testCopperTextItem( BOARD_ITEM* aTextItem )
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_COPPER );
drcItem->SetItems( track, aTextItem );
wxPoint pos = getLocation( track, aTextItem, textSeg );
wxPoint pos = getLocation( track, textSeg );
MARKER_PCB* marker = new MARKER_PCB( drcItem, pos );
addMarkerToPcb( marker );
}
@ -1329,8 +1337,6 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, int x_li
for( D_PAD** pad_list = aStart; pad_list<aEnd; ++pad_list )
{
D_PAD* pad = *pad_list;
int allowed;
int actual;
wxString msg;
if( pad == aRefPad )
@ -1375,12 +1381,15 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, int x_li
PAD_SHAPE_OVAL : PAD_SHAPE_CIRCLE );
dummypad.SetOrientation( pad->GetOrientation() );
if( !checkClearancePadToPad( aRefPad, &dummypad, &allowed, &actual ) )
int minClearance = aRefPad->GetClearance( &dummypad );
int actual;
if( !checkClearancePadToPad( aRefPad, &dummypad, minClearance, &actual ) )
{
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_HOLE_NEAR_PAD );
msg.Printf( drcItem->GetErrorText() + _( "(minimum %s; actual %s)" ),
MessageTextFromValue( userUnits(), allowed, true ),
MessageTextFromValue( userUnits(), minClearance, true ),
MessageTextFromValue( userUnits(), actual, true ) );
drcItem->SetErrorMessage( msg );
@ -1400,12 +1409,15 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, int x_li
PAD_SHAPE_OVAL : PAD_SHAPE_CIRCLE );
dummypad.SetOrientation( aRefPad->GetOrientation() );
if( !checkClearancePadToPad( pad, &dummypad, &allowed, &actual ) )
int minClearance = pad->GetClearance( &dummypad );
int actual;
if( !checkClearancePadToPad( pad, &dummypad, minClearance, &actual ) )
{
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_HOLE_NEAR_PAD );
msg.Printf( drcItem->GetErrorText() + _( "(minimum %s; actual %s)" ),
MessageTextFromValue( userUnits(), allowed, true ),
MessageTextFromValue( userUnits(), minClearance, true ),
MessageTextFromValue( userUnits(), actual, true ) );
drcItem->SetErrorMessage( msg );
@ -1444,12 +1456,15 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, int x_li
continue;
}
if( !checkClearancePadToPad( aRefPad, pad, &allowed, &actual ) )
int minClearance = aRefPad->GetClearance( &dummypad );
int actual;
if( !checkClearancePadToPad( aRefPad, pad, minClearance, &actual ) )
{
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_PAD_NEAR_PAD1 );
msg.Printf( drcItem->GetErrorText() + _( "(minimum %s; actual %s)" ),
MessageTextFromValue( userUnits(), allowed, true ),
MessageTextFromValue( userUnits(), minClearance, true ),
MessageTextFromValue( userUnits(), actual, true ) );
drcItem->SetErrorMessage( msg );
@ -1572,7 +1587,7 @@ wxPoint DRC::getLocation( TRACK* aTrack, ZONE_CONTAINER* aConflictZone ) const
}
wxPoint DRC::getLocation( TRACK* aTrack, BOARD_ITEM* aConflitItem, const SEG& aConflictSeg ) const
wxPoint DRC::getLocation( TRACK* aTrack, const SEG& aConflictSeg ) const
{
wxPoint pt1 = aTrack->GetPosition();
wxPoint pt2 = aTrack->GetEnd();
@ -1580,7 +1595,7 @@ wxPoint DRC::getLocation( TRACK* aTrack, BOARD_ITEM* aConflitItem, const SEG& aC
// Do a binary search along the track for a "good enough" marker location
while( GetLineLength( pt1, pt2 ) > EPSILON )
{
if( aConflictSeg.Distance( pt1 ) < aConflictSeg.Distance( pt2 ) )
if( aConflictSeg.SquaredDistance( pt1 ) < aConflictSeg.SquaredDistance( pt2 ) )
pt2 = ( pt1 + pt2 ) / 2;
else
pt1 = ( pt1 + pt2 ) / 2;

View File

@ -34,10 +34,6 @@
#include <vector>
#include <tools/pcb_tool_base.h>
#define OK_DRC 0
#define BAD_DRC 1
/// DRC error codes:
enum PCB_DRC_CODE {
@ -155,29 +151,6 @@ private:
bool m_reportAllTrackErrors; // Report all tracks errors (or only 4 first errors)
bool m_testFootprints; // Test footprints against schematic
/* In DRC functions, many calculations are using coordinates relative
* to the position of the segment under test (segm to segm DRC, segm to pad DRC
* Next variables store coordinates relative to the start point of this segment
*/
wxPoint m_padToTestPos; // Position of the pad for segm-to-pad and pad-to-pad
wxPoint m_segmEnd; // End point of the reference segment (start = (0, 0) )
/* Some functions are comparing the ref segm to pads or others segments using
* coordinates relative to the ref segment considered as the X axis
* so we store the ref segment length (the end point relative to these axis)
* and the segment orientation (used to rotate other coordinates)
*/
double m_segmAngle; // Ref segm orientation in 0.1 degree
int m_segmLength; // length of the reference segment
/* variables used in checkLine to test DRC segm to segm:
* define the area relative to the ref segment that does not contains any other segment
*/
int m_xcliplo;
int m_ycliplo;
int m_xcliphi;
int m_ycliphi;
PCB_EDIT_FRAME* m_pcbEditorFrame; // The pcb frame editor which owns the board
BOARD* m_pcb;
SHAPE_POLY_SET m_board_outlines; // The board outline including cutouts
@ -207,7 +180,7 @@ private:
* Fetches a reasonable point for marking a violoation between two non-point objects.
*/
wxPoint getLocation( TRACK* aTrack, ZONE_CONTAINER* aConflictZone ) const;
wxPoint getLocation( TRACK* aTrack, BOARD_ITEM* aConflitItem, const SEG& aConflictSeg ) const;
wxPoint getLocation( TRACK* aTrack, const SEG& aConflictSeg ) const;
//-----<categorical group tests>-----------------------------------------
@ -301,16 +274,17 @@ private:
/**
* @param aRefPad The reference pad to check
* @param aPad Another pad to check against
* @param aAllowed [out] is the allowed distance (only guaranteed to be set for violations)
* @param aActual [out] it the actual difference (only guaranteed to be set for violations)
* @return bool - true if clearance between aRefPad and aPad is >= dist_min, else false
* @param aMinClearance is the minimum allowed distance between the pads
* @param aActual [out] it the actual distance (only guaranteed to be set for violations)
* @return bool - true if clearance between aRefPad and aPad is >= aMinClearance, else false
*/
bool checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad, int* aAllowed, int* aActual );
bool checkClearancePadToPad( D_PAD* aRefPad, D_PAD* aPad, int aMinClearance, int* aActual );
/**
* Check the distance from a pad to segment. This function uses several
* instance variable not passed in:
* // JEY TODO: nuke these:
* m_segmLength = length of the segment being tested
* m_segmAngle = angle of the segment with the X axis;
* m_segmEnd = end coordinate of the segment
@ -323,35 +297,10 @@ private:
* @return true distance >= dist_min,
* false if distance < dist_min
*/
bool checkClearanceSegmToPad( const D_PAD* aPad, int aSegmentWidth, int aMinDist,
int* aActualDist );
bool checkClearanceSegmToPad( const SEG& seg, int segWidth, const D_PAD* pad,
int minClearance, int* aActualDist );
/**
* Check the distance from a point to a segment.
*
* The segment is expected starting at 0,0, and on the X axis
* (used to test DRC between a segment and a round pad, via or round end of a track
* @param aCentre The coordinate of the circle's center
* @param aAllowed A "keep out" radius centered over the circle
* @param aLength The length of the segment (i.e. coordinate of end, because it is on
* the X axis)
* @param aActual [out] is the actual distance (only guaranteed to be set on violations)
* @return bool - true if distance >= radius, else
* false when distance < aAllowed
*/
static bool checkMarginToCircle( wxPoint aCentre, int aAllowed, int aLength, int* aActual );
/**
* Function checkLine
* (helper function used in drc calculations to see if one track is in contact with
* another track).
* Test if a line intersects a bounding box (a rectangle)
* The rectangle is defined by m_xcliplo, m_ycliplo and m_xcliphi, m_ycliphi
* return true if the line from aSegStart to aSegEnd is outside the bounding box
*/
bool checkLine( wxPoint aSegStart, wxPoint aSegEnd );
//-----</single tests>---------------------------------------------

File diff suppressed because it is too large Load Diff