Updating DRC to handle vias with differing layers
This commit is contained in:
parent
9a66a5acad
commit
41edf5c5bf
|
@ -592,7 +592,15 @@ void DRC::testTracks( BOARD_COMMIT& aCommit, wxWindow *aActiveWindow, bool aShow
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test new segment against tracks and pads, optionally against copper zones
|
// Test new segment against tracks and pads, optionally against copper zones
|
||||||
doTrackDrc( aCommit, *seg_it, seg_it + 1, m_pcb->Tracks().end(), m_testTracksAgainstZones );
|
LSEQ layer_seq = ( *seg_it )->GetLayerSet().Seq();
|
||||||
|
|
||||||
|
if( ( *seg_it )->Type() == PCB_VIA_T )
|
||||||
|
doSingleViaDRC( aCommit, static_cast<VIA*>( *seg_it ) );
|
||||||
|
else
|
||||||
|
doSingleTrackDRC( aCommit, *seg_it );
|
||||||
|
|
||||||
|
for( PCB_LAYER_ID layer : layer_seq )
|
||||||
|
doTrackDrc( aCommit, *seg_it, seg_it + 1, m_pcb->Tracks().end(), m_testTracksAgainstZones, layer );
|
||||||
|
|
||||||
// Test for dangling items
|
// Test for dangling items
|
||||||
int code = (*seg_it)->Type() == PCB_VIA_T ? DRCE_DANGLING_VIA : DRCE_DANGLING_TRACK;
|
int code = (*seg_it)->Type() == PCB_VIA_T ? DRCE_DANGLING_VIA : DRCE_DANGLING_TRACK;
|
||||||
|
|
|
@ -213,11 +213,28 @@ private:
|
||||||
* @param aStartIt the iterator to the first track to test
|
* @param aStartIt the iterator to the first track to test
|
||||||
* @param aEndIt the marker for the iterator end
|
* @param aEndIt the marker for the iterator end
|
||||||
* @param aTestZones true if should do copper zones test. This can be very time consumming
|
* @param aTestZones true if should do copper zones test. This can be very time consumming
|
||||||
|
* @param aLayer sets the layer to test against
|
||||||
* @return bool - true if no problems, else false and m_currentMarker is
|
* @return bool - true if no problems, else false and m_currentMarker is
|
||||||
* filled in with the problem information.
|
* filled in with the problem information.
|
||||||
*/
|
*/
|
||||||
void doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aStartIt,
|
void doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aStartIt,
|
||||||
TRACKS::iterator aEndIt, bool aTestZones );
|
TRACKS::iterator aEndIt, bool aTestZones, PCB_LAYER_ID aLayer );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test a single via for DRC errors
|
||||||
|
*
|
||||||
|
* @param aCommit The board commit to add DRC errors
|
||||||
|
* @param aRefVia The via to test against design settings
|
||||||
|
*/
|
||||||
|
void doSingleViaDRC( BOARD_COMMIT& aCommit, VIA* aRefVia );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test a single track segment for DRC errors
|
||||||
|
*
|
||||||
|
* @param aCommit The board commit to add DRC errors
|
||||||
|
* @param aRefSeg The track to test against design settings
|
||||||
|
*/
|
||||||
|
void doSingleTrackDRC( BOARD_COMMIT& aCommit, TRACK* aRefSeg );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -35,101 +35,42 @@
|
||||||
#include <geometry/shape_segment.h>
|
#include <geometry/shape_segment.h>
|
||||||
#include <convert_basic_shapes_to_polygon.h>
|
#include <convert_basic_shapes_to_polygon.h>
|
||||||
|
|
||||||
|
void DRC::doSingleViaDRC( BOARD_COMMIT& aCommit, VIA* aRefVia )
|
||||||
void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aStartIt,
|
|
||||||
TRACKS::iterator aEndIt, bool aTestZones )
|
|
||||||
{
|
{
|
||||||
BOARD_DESIGN_SETTINGS& bds = m_pcb->GetDesignSettings();
|
BOARD_DESIGN_SETTINGS& bds = m_pcb->GetDesignSettings();
|
||||||
|
|
||||||
|
|
||||||
SHAPE_SEGMENT refSeg( aRefSeg->GetStart(), aRefSeg->GetEnd(), aRefSeg->GetWidth() );
|
|
||||||
PCB_LAYER_ID refLayer = aRefSeg->GetLayer();
|
|
||||||
LSET refLayerSet = aRefSeg->GetLayerSet();
|
|
||||||
|
|
||||||
EDA_RECT refSegBB = aRefSeg->GetBoundingBox();
|
|
||||||
int refSegWidth = aRefSeg->GetWidth();
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************/
|
|
||||||
/* Phase 0 : via DRC tests : */
|
|
||||||
/******************************************/
|
|
||||||
|
|
||||||
if( aRefSeg->Type() == PCB_VIA_T )
|
|
||||||
{
|
|
||||||
VIA *refvia = static_cast<VIA*>( aRefSeg );
|
|
||||||
int viaAnnulus = ( refvia->GetWidth() - refvia->GetDrill() ) / 2;
|
|
||||||
int minAnnulus = refvia->GetMinAnnulus( refvia->GetLayer(), &m_clearanceSource );
|
|
||||||
|
|
||||||
// test if the via size is smaller than minimum
|
// test if the via size is smaller than minimum
|
||||||
if( refvia->GetViaType() == VIATYPE::MICROVIA )
|
if( aRefVia->GetViaType() == VIATYPE::MICROVIA )
|
||||||
{
|
{
|
||||||
if( viaAnnulus < minAnnulus )
|
if( aRefVia->GetWidth() < bds.m_MicroViasMinSize )
|
||||||
{
|
|
||||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_VIA_ANNULUS );
|
|
||||||
|
|
||||||
m_msg.Printf( _( "Via annulus too small (%s %s; actual %s)" ),
|
|
||||||
m_clearanceSource,
|
|
||||||
MessageTextFromValue( userUnits(), minAnnulus, true ),
|
|
||||||
MessageTextFromValue( userUnits(), viaAnnulus, true ) );
|
|
||||||
|
|
||||||
drcItem->SetErrorMessage( m_msg );
|
|
||||||
drcItem->SetItems( refvia );
|
|
||||||
|
|
||||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
|
|
||||||
addMarkerToPcb( aCommit, marker );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( refvia->GetWidth() < bds.m_MicroViasMinSize )
|
|
||||||
{
|
{
|
||||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_MICROVIA );
|
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_MICROVIA );
|
||||||
|
|
||||||
m_msg.Printf( drcItem->GetErrorText() + _( " (board minimum %s; actual %s)" ),
|
m_msg.Printf( drcItem->GetErrorText() + _( " (board minimum %s; actual %s)" ),
|
||||||
MessageTextFromValue( userUnits(), bds.m_MicroViasMinSize, true ),
|
MessageTextFromValue( userUnits(), bds.m_MicroViasMinSize, true ),
|
||||||
MessageTextFromValue( userUnits(), refvia->GetWidth(), true ) );
|
MessageTextFromValue( userUnits(), aRefVia->GetWidth(), true ) );
|
||||||
|
|
||||||
drcItem->SetErrorMessage( m_msg );
|
drcItem->SetErrorMessage( m_msg );
|
||||||
drcItem->SetItems( refvia );
|
drcItem->SetItems( aRefVia );
|
||||||
|
|
||||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
|
MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefVia->GetPosition() );
|
||||||
addMarkerToPcb( aCommit, marker );
|
addMarkerToPcb( aCommit, marker );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( bds.m_ViasMinAnnulus > minAnnulus )
|
if( aRefVia->GetWidth() < bds.m_ViasMinSize )
|
||||||
{
|
|
||||||
minAnnulus = bds.m_ViasMinAnnulus;
|
|
||||||
m_clearanceSource = _( "board minimum" );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( viaAnnulus < minAnnulus )
|
|
||||||
{
|
|
||||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_VIA_ANNULUS );
|
|
||||||
|
|
||||||
m_msg.Printf( _( "Via annulus too small (%s %s; actual %s)" ),
|
|
||||||
m_clearanceSource,
|
|
||||||
MessageTextFromValue( userUnits(), minAnnulus, true ),
|
|
||||||
MessageTextFromValue( userUnits(), viaAnnulus, true ) );
|
|
||||||
|
|
||||||
drcItem->SetErrorMessage( m_msg );
|
|
||||||
drcItem->SetItems( refvia );
|
|
||||||
|
|
||||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
|
|
||||||
addMarkerToPcb( aCommit, marker );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( refvia->GetWidth() < bds.m_ViasMinSize )
|
|
||||||
{
|
{
|
||||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_VIA );
|
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_VIA );
|
||||||
|
|
||||||
m_msg.Printf( drcItem->GetErrorText() + _( " (board minimum %s; actual %s)" ),
|
m_msg.Printf( drcItem->GetErrorText() + _( " (board minimum %s; actual %s)" ),
|
||||||
MessageTextFromValue( userUnits(), bds.m_ViasMinSize, true ),
|
MessageTextFromValue( userUnits(), bds.m_ViasMinSize, true ),
|
||||||
MessageTextFromValue( userUnits(), refvia->GetWidth(), true ) );
|
MessageTextFromValue( userUnits(), aRefVia->GetWidth(), true ) );
|
||||||
|
|
||||||
drcItem->SetErrorMessage( m_msg );
|
drcItem->SetErrorMessage( m_msg );
|
||||||
drcItem->SetItems( refvia );
|
drcItem->SetItems( aRefVia );
|
||||||
|
|
||||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
|
MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefVia->GetPosition() );
|
||||||
addMarkerToPcb( aCommit, marker );
|
addMarkerToPcb( aCommit, marker );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,56 +78,56 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
// test if via's hole is bigger than its diameter
|
// test if via's hole is bigger than its diameter
|
||||||
// This test is necessary since the via hole size and width can be modified
|
// This test is necessary since the via hole size and width can be modified
|
||||||
// and a default via hole can be bigger than some vias sizes
|
// and a default via hole can be bigger than some vias sizes
|
||||||
if( refvia->GetDrillValue() > refvia->GetWidth() )
|
if( aRefVia->GetDrillValue() > aRefVia->GetWidth() )
|
||||||
{
|
{
|
||||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_VIA_HOLE_BIGGER );
|
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_VIA_HOLE_BIGGER );
|
||||||
|
|
||||||
m_msg.Printf( drcItem->GetErrorText() + _( " (diameter %s; drill %s)" ),
|
m_msg.Printf( drcItem->GetErrorText() + _( " (diameter %s; drill %s)" ),
|
||||||
MessageTextFromValue( userUnits(), refvia->GetWidth(), true ),
|
MessageTextFromValue( userUnits(), aRefVia->GetWidth(), true ),
|
||||||
MessageTextFromValue( userUnits(), refvia->GetDrillValue(), true ) );
|
MessageTextFromValue( userUnits(), aRefVia->GetDrillValue(), true ) );
|
||||||
|
|
||||||
drcItem->SetErrorMessage( m_msg );
|
drcItem->SetErrorMessage( m_msg );
|
||||||
drcItem->SetItems( refvia );
|
drcItem->SetItems( aRefVia );
|
||||||
|
|
||||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
|
MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefVia->GetPosition() );
|
||||||
addMarkerToPcb( aCommit, marker );
|
addMarkerToPcb( aCommit, marker );
|
||||||
}
|
}
|
||||||
|
|
||||||
// test if the type of via is allowed due to design rules
|
// test if the type of via is allowed due to design rules
|
||||||
if( refvia->GetViaType() == VIATYPE::MICROVIA && !bds.m_MicroViasAllowed )
|
if( aRefVia->GetViaType() == VIATYPE::MICROVIA && !bds.m_MicroViasAllowed )
|
||||||
{
|
{
|
||||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_ALLOWED_ITEMS );
|
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_ALLOWED_ITEMS );
|
||||||
|
|
||||||
m_msg.Printf( _( "Microvia not allowed (board design rule constraints)" ) );
|
m_msg.Printf( _( "Microvia not allowed (board design rule constraints)" ) );
|
||||||
drcItem->SetErrorMessage( m_msg );
|
drcItem->SetErrorMessage( m_msg );
|
||||||
drcItem->SetItems( refvia );
|
drcItem->SetItems( aRefVia );
|
||||||
|
|
||||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
|
MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefVia->GetPosition() );
|
||||||
addMarkerToPcb( aCommit, marker );
|
addMarkerToPcb( aCommit, marker );
|
||||||
}
|
}
|
||||||
|
|
||||||
// test if the type of via is allowed due to design rules
|
// test if the type of via is allowed due to design rules
|
||||||
if( refvia->GetViaType() == VIATYPE::BLIND_BURIED && !bds.m_BlindBuriedViaAllowed )
|
if( aRefVia->GetViaType() == VIATYPE::BLIND_BURIED && !bds.m_BlindBuriedViaAllowed )
|
||||||
{
|
{
|
||||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_ALLOWED_ITEMS );
|
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_ALLOWED_ITEMS );
|
||||||
|
|
||||||
m_msg.Printf( _( "Blind/buried via not allowed (board design rule constraints)" ) );
|
m_msg.Printf( _( "Blind/buried via not allowed (board design rule constraints)" ) );
|
||||||
drcItem->SetErrorMessage( m_msg );
|
drcItem->SetErrorMessage( m_msg );
|
||||||
drcItem->SetItems( refvia );
|
drcItem->SetItems( aRefVia );
|
||||||
|
|
||||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
|
MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefVia->GetPosition() );
|
||||||
addMarkerToPcb( aCommit, marker );
|
addMarkerToPcb( aCommit, marker );
|
||||||
}
|
}
|
||||||
|
|
||||||
// For microvias: test if they are blind vias and only between 2 layers
|
// For microvias: test if they are blind vias and only between 2 layers
|
||||||
// because they are used for very small drill size and are drill by laser
|
// because they are used for very small drill size and are drill by laser
|
||||||
// and **only one layer** can be drilled
|
// and **only one layer** can be drilled
|
||||||
if( refvia->GetViaType() == VIATYPE::MICROVIA )
|
if( aRefVia->GetViaType() == VIATYPE::MICROVIA )
|
||||||
{
|
{
|
||||||
PCB_LAYER_ID layer1, layer2;
|
PCB_LAYER_ID layer1, layer2;
|
||||||
bool err = true;
|
bool err = true;
|
||||||
|
|
||||||
refvia->LayerPair( &layer1, &layer2 );
|
aRefVia->LayerPair( &layer1, &layer2 );
|
||||||
|
|
||||||
if( layer1 > layer2 )
|
if( layer1 > layer2 )
|
||||||
std::swap( layer1, layer2 );
|
std::swap( layer1, layer2 );
|
||||||
|
@ -205,16 +146,21 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
m_pcb->GetLayerName( layer2 ) );
|
m_pcb->GetLayerName( layer2 ) );
|
||||||
|
|
||||||
drcItem->SetErrorMessage( m_msg );
|
drcItem->SetErrorMessage( m_msg );
|
||||||
drcItem->SetItems( refvia );
|
drcItem->SetItems( aRefVia );
|
||||||
|
|
||||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
|
MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefVia->GetPosition() );
|
||||||
addMarkerToPcb( aCommit, marker );
|
addMarkerToPcb( aCommit, marker );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else // This is a track segment
|
|
||||||
|
|
||||||
|
void DRC::doSingleTrackDRC( BOARD_COMMIT& aCommit, TRACK* aRefSeg )
|
||||||
{
|
{
|
||||||
|
SHAPE_SEGMENT refSeg( aRefSeg->GetStart(), aRefSeg->GetEnd(), aRefSeg->GetWidth() );
|
||||||
|
EDA_RECT refSegBB = aRefSeg->GetBoundingBox();
|
||||||
|
int refSegWidth = aRefSeg->GetWidth();
|
||||||
|
|
||||||
int minWidth, maxWidth;
|
int minWidth, maxWidth;
|
||||||
aRefSeg->GetWidthConstraints( &minWidth, &maxWidth, &m_clearanceSource );
|
aRefSeg->GetWidthConstraints( &minWidth, &maxWidth, &m_clearanceSource );
|
||||||
|
|
||||||
|
@ -252,6 +198,79 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aStartIt,
|
||||||
|
TRACKS::iterator aEndIt, bool aTestZones, PCB_LAYER_ID aLayer )
|
||||||
|
{
|
||||||
|
BOARD_DESIGN_SETTINGS& bds = m_pcb->GetDesignSettings();
|
||||||
|
SHAPE_SEGMENT refSeg( aRefSeg->GetStart(), aRefSeg->GetEnd(), aRefSeg->GetWidth() );
|
||||||
|
|
||||||
|
EDA_RECT refSegBB = aRefSeg->GetBoundingBox();
|
||||||
|
SEG testSeg( aRefSeg->GetStart(), aRefSeg->GetEnd() );
|
||||||
|
int halfWidth = ( aRefSeg->GetWidth() + 1 ) / 2;
|
||||||
|
|
||||||
|
/******************************************/
|
||||||
|
/* Phase 0 : via DRC tests : */
|
||||||
|
/******************************************/
|
||||||
|
|
||||||
|
if( aRefSeg->Type() == PCB_VIA_T )
|
||||||
|
{
|
||||||
|
VIA* refvia = static_cast<VIA*>( aRefSeg );
|
||||||
|
int viaAnnulus = ( refvia->GetWidth() - refvia->GetDrill() ) / 2;
|
||||||
|
int minAnnulus = refvia->GetMinAnnulus( aLayer, &m_clearanceSource );
|
||||||
|
|
||||||
|
if( !refvia->IsPadOnLayer( aLayer ) )
|
||||||
|
{
|
||||||
|
halfWidth = ( refvia->GetDrillValue() + 1 ) / 2;
|
||||||
|
refSegBB = EDA_RECT( refvia->GetStart(),
|
||||||
|
wxSize( refvia->GetDrillValue(), refvia->GetDrillValue() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// test if the via size is smaller than minimum
|
||||||
|
if( refvia->GetViaType() == VIATYPE::MICROVIA )
|
||||||
|
{
|
||||||
|
if( viaAnnulus < minAnnulus )
|
||||||
|
{
|
||||||
|
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_VIA_ANNULUS );
|
||||||
|
|
||||||
|
m_msg.Printf( _( "Via annulus too small (%s %s; actual %s)" ),
|
||||||
|
m_clearanceSource,
|
||||||
|
MessageTextFromValue( userUnits(), minAnnulus, true ),
|
||||||
|
MessageTextFromValue( userUnits(), viaAnnulus, true ) );
|
||||||
|
|
||||||
|
drcItem->SetErrorMessage( m_msg );
|
||||||
|
drcItem->SetItems( refvia );
|
||||||
|
|
||||||
|
MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
|
||||||
|
addMarkerToPcb( aCommit, marker );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( bds.m_ViasMinAnnulus > minAnnulus )
|
||||||
|
{
|
||||||
|
minAnnulus = bds.m_ViasMinAnnulus;
|
||||||
|
m_clearanceSource = _( "board minimum" );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( viaAnnulus < minAnnulus )
|
||||||
|
{
|
||||||
|
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_VIA_ANNULUS );
|
||||||
|
|
||||||
|
m_msg.Printf( _( "Via annulus too small (%s %s; actual %s)" ),
|
||||||
|
m_clearanceSource,
|
||||||
|
MessageTextFromValue( userUnits(), minAnnulus, true ),
|
||||||
|
MessageTextFromValue( userUnits(), viaAnnulus, true ) );
|
||||||
|
|
||||||
|
drcItem->SetErrorMessage( m_msg );
|
||||||
|
drcItem->SetItems( refvia );
|
||||||
|
|
||||||
|
MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
|
||||||
|
addMarkerToPcb( aCommit, marker );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************/
|
/******************************************/
|
||||||
/* Phase 1 : test DRC track to pads : */
|
/* Phase 1 : test DRC track to pads : */
|
||||||
/******************************************/
|
/******************************************/
|
||||||
|
@ -269,20 +288,10 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
EDA_RECT inflatedBB = refSegBB;
|
EDA_RECT inflatedBB = refSegBB;
|
||||||
inflatedBB.Inflate( pad->GetBoundingRadius() + m_largestClearance );
|
inflatedBB.Inflate( pad->GetBoundingRadius() + m_largestClearance );
|
||||||
|
|
||||||
/// We setup the dummy pad to use in case we need to only draw the hole outline rather
|
|
||||||
/// than the pad itself
|
|
||||||
D_PAD dummypad( pad->GetParent() );
|
|
||||||
dummypad.SetNetCode( pad->GetNetCode() );
|
|
||||||
dummypad.SetSize( pad->GetDrillSize() );
|
|
||||||
dummypad.SetOrientation( pad->GetOrientation() );
|
|
||||||
dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ? PAD_SHAPE_OVAL
|
|
||||||
: PAD_SHAPE_CIRCLE );
|
|
||||||
dummypad.SetPosition( pad->GetPosition() );
|
|
||||||
|
|
||||||
if( !inflatedBB.Contains( pad->GetPosition() ) )
|
if( !inflatedBB.Contains( pad->GetPosition() ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( !( pad->GetLayerSet() & refLayerSet ).any() )
|
if( !( pad->IsOnLayer( aLayer ) ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// No need to check pads with the same net as the refSeg.
|
// No need to check pads with the same net as the refSeg.
|
||||||
|
@ -293,7 +302,7 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
{
|
{
|
||||||
const SHAPE_SEGMENT* slot = pad->GetEffectiveHoleShape();
|
const SHAPE_SEGMENT* slot = pad->GetEffectiveHoleShape();
|
||||||
const DRC_CONSTRAINT* constraint = GetConstraint( aRefSeg, pad,
|
const DRC_CONSTRAINT* constraint = GetConstraint( aRefSeg, pad,
|
||||||
DRC_RULE_ID_CLEARANCE, refLayer,
|
DRC_RULE_ID_CLEARANCE, aLayer,
|
||||||
&m_clearanceSource );
|
&m_clearanceSource );
|
||||||
int minClearance;
|
int minClearance;
|
||||||
int actual;
|
int actual;
|
||||||
|
@ -305,7 +314,7 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
minClearance = aRefSeg->GetClearance( refLayer, nullptr,
|
minClearance = aRefSeg->GetClearance( aLayer, nullptr,
|
||||||
&m_clearanceSource );
|
&m_clearanceSource );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,7 +339,7 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Skip checking pad copper when it has been removed
|
/// Skip checking pad copper when it has been removed
|
||||||
if( !pad->IsPadOnLayer( refLayer ) )
|
if( !pad->IsPadOnLayer( aLayer ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int minClearance = aRefSeg->GetClearance( aRefSeg->GetLayer(), pad,
|
int minClearance = aRefSeg->GetClearance( aRefSeg->GetLayer(), pad,
|
||||||
|
@ -371,27 +380,7 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
if( aRefSeg->GetNetCode() == track->GetNetCode() )
|
if( aRefSeg->GetNetCode() == track->GetNetCode() )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// No problem if tracks are on different layers:
|
if( !track->GetLayerSet().test( aLayer ) )
|
||||||
// Note that while the general case of GetLayerSet intersection always works,
|
|
||||||
// the others are much faster.
|
|
||||||
bool sameLayers;
|
|
||||||
|
|
||||||
if( aRefSeg->Type() == PCB_VIA_T )
|
|
||||||
{
|
|
||||||
if( track->Type() == PCB_VIA_T )
|
|
||||||
sameLayers = ( refLayerSet & track->GetLayerSet() ).any();
|
|
||||||
else
|
|
||||||
sameLayers = refLayerSet.test( track->GetLayer() );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if( track->Type() == PCB_VIA_T )
|
|
||||||
sameLayers = track->GetLayerSet().test( refLayer );
|
|
||||||
else
|
|
||||||
sameLayers = track->GetLayer() == refLayer;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !sameLayers )
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Preflight based on worst-case inflated bounding boxes:
|
// Preflight based on worst-case inflated bounding boxes:
|
||||||
|
@ -406,6 +395,15 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
int actual;
|
int actual;
|
||||||
SHAPE_SEGMENT trackSeg( track->GetStart(), track->GetEnd(), track->GetWidth() );
|
SHAPE_SEGMENT trackSeg( track->GetStart(), track->GetEnd(), track->GetWidth() );
|
||||||
|
|
||||||
|
/// Check to see if the via has a pad on this layer
|
||||||
|
if( track->Type() == PCB_VIA_T )
|
||||||
|
{
|
||||||
|
VIA* via = static_cast<VIA*>( track );
|
||||||
|
|
||||||
|
if( !via->IsPadOnLayer( aLayer ) )
|
||||||
|
trackSeg.SetWidth( via->GetDrillValue() );
|
||||||
|
}
|
||||||
|
|
||||||
// Check two tracks crossing first as it reports a DRCE without distances
|
// Check two tracks crossing first as it reports a DRCE without distances
|
||||||
if( OPT_VECTOR2I intersection = refSeg.GetSeg().Intersect( trackSeg.GetSeg() ) )
|
if( OPT_VECTOR2I intersection = refSeg.GetSeg().Intersect( trackSeg.GetSeg() ) )
|
||||||
{
|
{
|
||||||
|
@ -446,22 +444,16 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
// Can be *very* time consumming.
|
// Can be *very* time consumming.
|
||||||
if( aTestZones )
|
if( aTestZones )
|
||||||
{
|
{
|
||||||
SEG testSeg( aRefSeg->GetStart(), aRefSeg->GetEnd() );
|
|
||||||
|
|
||||||
for( ZONE_CONTAINER* zone : m_pcb->Zones() )
|
for( ZONE_CONTAINER* zone : m_pcb->Zones() )
|
||||||
{
|
{
|
||||||
if( zone->GetIsKeepout() )
|
if( !zone->GetLayerSet().test( aLayer ) || zone->GetIsKeepout() )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( zone->GetNetCode() && zone->GetNetCode() == aRefSeg->GetNetCode() )
|
if( zone->GetNetCode() && zone->GetNetCode() == aRefSeg->GetNetCode() )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
|
if( zone->GetFilledPolysList( aLayer ).IsEmpty() )
|
||||||
{
|
|
||||||
if( !refLayerSet.test( layer ) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if( zone->GetFilledPolysList( layer ).IsEmpty() )
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// to avoid false positive, due to rounding issues and approxiamtions
|
// to avoid false positive, due to rounding issues and approxiamtions
|
||||||
|
@ -469,14 +461,14 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
// (1 micron)
|
// (1 micron)
|
||||||
#define THRESHOLD_DIST Millimeter2iu( 0.001 )
|
#define THRESHOLD_DIST Millimeter2iu( 0.001 )
|
||||||
|
|
||||||
int minClearance = aRefSeg->GetClearance( layer, zone, &m_clearanceSource );
|
|
||||||
int widths = refSegWidth / 2;
|
int minClearance = aRefSeg->GetClearance( aLayer, zone, &m_clearanceSource );
|
||||||
int allowedDist = minClearance + widths + THRESHOLD_DIST;
|
int allowedDist = minClearance + halfWidth + THRESHOLD_DIST;
|
||||||
int actual;
|
int actual;
|
||||||
|
|
||||||
if( zone->GetFilledPolysList( layer ).Collide( testSeg, allowedDist, &actual ) )
|
if( zone->GetFilledPolysList( aLayer ).Collide( testSeg, allowedDist, &actual ) )
|
||||||
{
|
{
|
||||||
actual = std::max( 0, actual - widths );
|
actual = std::max( 0, actual - halfWidth );
|
||||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
|
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
|
||||||
|
|
||||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
|
m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
|
||||||
|
@ -492,7 +484,6 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************/
|
/***********************************************/
|
||||||
/* Phase 4: test DRC with to board edge */
|
/* Phase 4: test DRC with to board edge */
|
||||||
|
@ -508,8 +499,6 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
aRefSeg->GetRuleClearance( &dummyEdge, aRefSeg->GetLayer(), &minClearance,
|
aRefSeg->GetRuleClearance( &dummyEdge, aRefSeg->GetLayer(), &minClearance,
|
||||||
&m_clearanceSource );
|
&m_clearanceSource );
|
||||||
|
|
||||||
SEG testSeg( aRefSeg->GetStart(), aRefSeg->GetEnd() );
|
|
||||||
int halfWidth = refSegWidth / 2;
|
|
||||||
int center2centerAllowed = minClearance + halfWidth;
|
int center2centerAllowed = minClearance + halfWidth;
|
||||||
|
|
||||||
for( auto it = m_board_outlines.IterateSegmentsWithHoles(); it; it++ )
|
for( auto it = m_board_outlines.IterateSegmentsWithHoles(); it; it++ )
|
||||||
|
|
|
@ -625,7 +625,16 @@ void DRC::testTracks( BOARD_COMMIT& aCommit, wxWindow *aActiveWindow, bool aShow
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test new segment against tracks and pads, optionally against copper zones
|
// Test new segment against tracks and pads, optionally against copper zones
|
||||||
doTrackDrc( aCommit, *seg_it, seg_it + 1, m_pcb->Tracks().end(), m_testTracksAgainstZones );
|
LSEQ layer_seq = ( *seg_it )->GetLayerSet().Seq();
|
||||||
|
|
||||||
|
if( ( *seg_it )->Type() == PCB_VIA_T )
|
||||||
|
doSingleViaDRC( aCommit, static_cast<VIA*>( *seg_it ) );
|
||||||
|
else
|
||||||
|
doSingleTrackDRC( aCommit, *seg_it );
|
||||||
|
|
||||||
|
for( PCB_LAYER_ID layer : layer_seq )
|
||||||
|
doTrackDrc( aCommit, *seg_it, seg_it + 1, m_pcb->Tracks().end(), m_testTracksAgainstZones, layer );
|
||||||
|
|
||||||
|
|
||||||
// Test for dangling items
|
// Test for dangling items
|
||||||
int code = (*seg_it)->Type() == PCB_VIA_T ? DRCE_DANGLING_VIA : DRCE_DANGLING_TRACK;
|
int code = (*seg_it)->Type() == PCB_VIA_T ? DRCE_DANGLING_VIA : DRCE_DANGLING_TRACK;
|
||||||
|
|
|
@ -262,11 +262,28 @@ private:
|
||||||
* @param aStartIt the iterator to the first track to test
|
* @param aStartIt the iterator to the first track to test
|
||||||
* @param aEndIt the marker for the iterator end
|
* @param aEndIt the marker for the iterator end
|
||||||
* @param aTestZones true if should do copper zones test. This can be very time consumming
|
* @param aTestZones true if should do copper zones test. This can be very time consumming
|
||||||
|
* @param aLayer sets the layer to test against
|
||||||
* @return bool - true if no problems, else false and m_currentMarker is
|
* @return bool - true if no problems, else false and m_currentMarker is
|
||||||
* filled in with the problem information.
|
* filled in with the problem information.
|
||||||
*/
|
*/
|
||||||
void doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aStartIt,
|
void doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aStartIt,
|
||||||
TRACKS::iterator aEndIt, bool aTestZones );
|
TRACKS::iterator aEndIt, bool aTestZones, PCB_LAYER_ID aLayer );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test a single via for DRC errors
|
||||||
|
*
|
||||||
|
* @param aCommit The board commit to add DRC errors
|
||||||
|
* @param aRefVia The via to test against design settings
|
||||||
|
*/
|
||||||
|
void doSingleViaDRC( BOARD_COMMIT& aCommit, VIA* aRefVia );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test a single track segment for DRC errors
|
||||||
|
*
|
||||||
|
* @param aCommit The board commit to add DRC errors
|
||||||
|
* @param aRefSeg The track to test against design settings
|
||||||
|
*/
|
||||||
|
void doSingleTrackDRC( BOARD_COMMIT& aCommit, TRACK* aRefSeg );
|
||||||
|
|
||||||
//-----<single tests>----------------------------------------------
|
//-----<single tests>----------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -136,18 +136,178 @@ bool poly2segmentDRC( wxPoint* aTref, int aTrefCount, wxPoint aSegStart, wxPoint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aStartIt,
|
void DRC::doSingleViaDRC( BOARD_COMMIT& aCommit, VIA* aRefVia )
|
||||||
TRACKS::iterator aEndIt, bool aTestZones )
|
|
||||||
{
|
{
|
||||||
BOARD_DESIGN_SETTINGS& bds = m_pcb->GetDesignSettings();
|
BOARD_DESIGN_SETTINGS& bds = m_pcb->GetDesignSettings();
|
||||||
|
|
||||||
SEG refSeg( aRefSeg->GetStart(), aRefSeg->GetEnd() );
|
// test if the via size is smaller than minimum
|
||||||
PCB_LAYER_ID refLayer = aRefSeg->GetLayer();
|
if( aRefVia->GetViaType() == VIATYPE::MICROVIA )
|
||||||
LSET refLayerSet = aRefSeg->GetLayerSet();
|
{
|
||||||
|
if( aRefVia->GetWidth() < bds.m_MicroViasMinSize )
|
||||||
|
{
|
||||||
|
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_MICROVIA );
|
||||||
|
|
||||||
|
m_msg.Printf( drcItem->GetErrorText() + _( " (board minimum %s; actual %s)" ),
|
||||||
|
MessageTextFromValue( userUnits(), bds.m_MicroViasMinSize, true ),
|
||||||
|
MessageTextFromValue( userUnits(), aRefVia->GetWidth(), true ) );
|
||||||
|
|
||||||
|
drcItem->SetErrorMessage( m_msg );
|
||||||
|
drcItem->SetItems( aRefVia );
|
||||||
|
|
||||||
|
MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefVia->GetPosition() );
|
||||||
|
addMarkerToPcb( aCommit, marker );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( aRefVia->GetWidth() < bds.m_ViasMinSize )
|
||||||
|
{
|
||||||
|
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_VIA );
|
||||||
|
|
||||||
|
m_msg.Printf( drcItem->GetErrorText() + _( " (board minimum %s; actual %s)" ),
|
||||||
|
MessageTextFromValue( userUnits(), bds.m_ViasMinSize, true ),
|
||||||
|
MessageTextFromValue( userUnits(), aRefVia->GetWidth(), true ) );
|
||||||
|
|
||||||
|
drcItem->SetErrorMessage( m_msg );
|
||||||
|
drcItem->SetItems( aRefVia );
|
||||||
|
|
||||||
|
MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefVia->GetPosition() );
|
||||||
|
addMarkerToPcb( aCommit, marker );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// test if via's hole is bigger than its diameter
|
||||||
|
// This test is necessary since the via hole size and width can be modified
|
||||||
|
// and a default via hole can be bigger than some vias sizes
|
||||||
|
if( aRefVia->GetDrillValue() > aRefVia->GetWidth() )
|
||||||
|
{
|
||||||
|
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_VIA_HOLE_BIGGER );
|
||||||
|
|
||||||
|
m_msg.Printf( drcItem->GetErrorText() + _( " (diameter %s; drill %s)" ),
|
||||||
|
MessageTextFromValue( userUnits(), aRefVia->GetWidth(), true ),
|
||||||
|
MessageTextFromValue( userUnits(), aRefVia->GetDrillValue(), true ) );
|
||||||
|
|
||||||
|
drcItem->SetErrorMessage( m_msg );
|
||||||
|
drcItem->SetItems( aRefVia );
|
||||||
|
|
||||||
|
MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefVia->GetPosition() );
|
||||||
|
addMarkerToPcb( aCommit, marker );
|
||||||
|
}
|
||||||
|
|
||||||
|
// test if the type of via is allowed due to design rules
|
||||||
|
if( aRefVia->GetViaType() == VIATYPE::MICROVIA && !bds.m_MicroViasAllowed )
|
||||||
|
{
|
||||||
|
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_ALLOWED_ITEMS );
|
||||||
|
|
||||||
|
m_msg.Printf( _( "Microvia not allowed (board design rule constraints)" ) );
|
||||||
|
drcItem->SetErrorMessage( m_msg );
|
||||||
|
drcItem->SetItems( aRefVia );
|
||||||
|
|
||||||
|
MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefVia->GetPosition() );
|
||||||
|
addMarkerToPcb( aCommit, marker );
|
||||||
|
}
|
||||||
|
|
||||||
|
// test if the type of via is allowed due to design rules
|
||||||
|
if( aRefVia->GetViaType() == VIATYPE::BLIND_BURIED && !bds.m_BlindBuriedViaAllowed )
|
||||||
|
{
|
||||||
|
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_ALLOWED_ITEMS );
|
||||||
|
|
||||||
|
m_msg.Printf( _( "Blind/buried via not allowed (board design rule constraints)" ) );
|
||||||
|
drcItem->SetErrorMessage( m_msg );
|
||||||
|
drcItem->SetItems( aRefVia );
|
||||||
|
|
||||||
|
MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefVia->GetPosition() );
|
||||||
|
addMarkerToPcb( aCommit, marker );
|
||||||
|
}
|
||||||
|
|
||||||
|
// For microvias: test if they are blind vias and only between 2 layers
|
||||||
|
// because they are used for very small drill size and are drill by laser
|
||||||
|
// and **only one layer** can be drilled
|
||||||
|
if( aRefVia->GetViaType() == VIATYPE::MICROVIA )
|
||||||
|
{
|
||||||
|
PCB_LAYER_ID layer1, layer2;
|
||||||
|
bool err = true;
|
||||||
|
|
||||||
|
aRefVia->LayerPair( &layer1, &layer2 );
|
||||||
|
|
||||||
|
if( layer1 > layer2 )
|
||||||
|
std::swap( layer1, layer2 );
|
||||||
|
|
||||||
|
if( layer2 == B_Cu && layer1 == bds.GetCopperLayerCount() - 2 )
|
||||||
|
err = false;
|
||||||
|
else if( layer1 == F_Cu && layer2 == In1_Cu )
|
||||||
|
err = false;
|
||||||
|
|
||||||
|
if( err )
|
||||||
|
{
|
||||||
|
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_PADSTACK );
|
||||||
|
|
||||||
|
m_msg.Printf( _( "Microvia through too many layers (%s and %s not adjacent)" ),
|
||||||
|
m_pcb->GetLayerName( layer1 ),
|
||||||
|
m_pcb->GetLayerName( layer2 ) );
|
||||||
|
|
||||||
|
drcItem->SetErrorMessage( m_msg );
|
||||||
|
drcItem->SetItems( aRefVia );
|
||||||
|
|
||||||
|
MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefVia->GetPosition() );
|
||||||
|
addMarkerToPcb( aCommit, marker );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DRC::doSingleTrackDRC( BOARD_COMMIT& aCommit, TRACK* aRefSeg )
|
||||||
|
{
|
||||||
|
SHAPE_SEGMENT refSeg( aRefSeg->GetStart(), aRefSeg->GetEnd(), aRefSeg->GetWidth() );
|
||||||
EDA_RECT refSegBB = aRefSeg->GetBoundingBox();
|
EDA_RECT refSegBB = aRefSeg->GetBoundingBox();
|
||||||
int refSegWidth = aRefSeg->GetWidth();
|
int refSegWidth = aRefSeg->GetWidth();
|
||||||
|
|
||||||
|
int minWidth, maxWidth;
|
||||||
|
aRefSeg->GetWidthConstraints( &minWidth, &maxWidth, &m_clearanceSource );
|
||||||
|
|
||||||
|
int errorCode = 0;
|
||||||
|
int constraintWidth;
|
||||||
|
|
||||||
|
if( refSegWidth < minWidth )
|
||||||
|
{
|
||||||
|
errorCode = DRCE_TRACK_WIDTH;
|
||||||
|
constraintWidth = minWidth;
|
||||||
|
}
|
||||||
|
else if( refSegWidth > maxWidth )
|
||||||
|
{
|
||||||
|
errorCode = DRCE_TRACK_WIDTH;
|
||||||
|
constraintWidth = maxWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( errorCode )
|
||||||
|
{
|
||||||
|
wxPoint refsegMiddle = ( aRefSeg->GetStart() + aRefSeg->GetEnd() ) / 2;
|
||||||
|
|
||||||
|
DRC_ITEM* drcItem = DRC_ITEM::Create( errorCode );
|
||||||
|
|
||||||
|
m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ),
|
||||||
|
m_clearanceSource,
|
||||||
|
MessageTextFromValue( userUnits(), constraintWidth, true ),
|
||||||
|
MessageTextFromValue( userUnits(), refSegWidth, true ) );
|
||||||
|
|
||||||
|
drcItem->SetErrorMessage( m_msg );
|
||||||
|
drcItem->SetItems( aRefSeg );
|
||||||
|
|
||||||
|
MARKER_PCB* marker = new MARKER_PCB( drcItem, refsegMiddle );
|
||||||
|
addMarkerToPcb( aCommit, marker );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aStartIt,
|
||||||
|
TRACKS::iterator aEndIt, bool aTestZones, PCB_LAYER_ID aLayer )
|
||||||
|
{
|
||||||
|
BOARD_DESIGN_SETTINGS& bds = m_pcb->GetDesignSettings();
|
||||||
|
SHAPE_SEGMENT refSeg( aRefSeg->GetStart(), aRefSeg->GetEnd(), aRefSeg->GetWidth() );
|
||||||
|
|
||||||
|
EDA_RECT refSegBB = aRefSeg->GetBoundingBox();
|
||||||
|
SEG testSeg( aRefSeg->GetStart(), aRefSeg->GetEnd() );
|
||||||
|
int halfWidth = ( aRefSeg->GetWidth() + 1 ) / 2;
|
||||||
|
|
||||||
/******************************************/
|
/******************************************/
|
||||||
/* Phase 0 : via DRC tests : */
|
/* Phase 0 : via DRC tests : */
|
||||||
|
@ -157,16 +317,23 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
{
|
{
|
||||||
VIA* refvia = static_cast<VIA*>( aRefSeg );
|
VIA* refvia = static_cast<VIA*>( aRefSeg );
|
||||||
int viaAnnulus = ( refvia->GetWidth() - refvia->GetDrill() ) / 2;
|
int viaAnnulus = ( refvia->GetWidth() - refvia->GetDrill() ) / 2;
|
||||||
int minAnnulus = refvia->GetMinAnnulus( &m_clearanceSource );
|
int minAnnulus = refvia->GetMinAnnulus( aLayer, &m_clearanceSource );
|
||||||
|
|
||||||
|
if( !refvia->IsPadOnLayer( aLayer ) )
|
||||||
|
{
|
||||||
|
halfWidth = ( refvia->GetDrillValue() + 1 ) / 2;
|
||||||
|
refSegBB = EDA_RECT( refvia->GetStart(),
|
||||||
|
wxSize( refvia->GetDrillValue(), refvia->GetDrillValue() ) );
|
||||||
|
}
|
||||||
|
|
||||||
// test if the via size is smaller than minimum
|
// test if the via size is smaller than minimum
|
||||||
if( refvia->GetViaType() == VIATYPE::MICROVIA )
|
if( refvia->GetViaType() == VIATYPE::MICROVIA )
|
||||||
{
|
{
|
||||||
if( viaAnnulus < minAnnulus )
|
if( viaAnnulus < minAnnulus )
|
||||||
{
|
{
|
||||||
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TOO_SMALL_VIA_ANNULUS );
|
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_VIA_ANNULUS );
|
||||||
|
|
||||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ),
|
m_msg.Printf( _( "Via annulus too small (%s %s; actual %s)" ),
|
||||||
m_clearanceSource,
|
m_clearanceSource,
|
||||||
MessageTextFromValue( userUnits(), minAnnulus, true ),
|
MessageTextFromValue( userUnits(), minAnnulus, true ),
|
||||||
MessageTextFromValue( userUnits(), viaAnnulus, true ) );
|
MessageTextFromValue( userUnits(), viaAnnulus, true ) );
|
||||||
|
@ -177,21 +344,6 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
|
MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
|
||||||
addMarkerToPcb( aCommit, marker );
|
addMarkerToPcb( aCommit, marker );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( refvia->GetWidth() < bds.m_MicroViasMinSize )
|
|
||||||
{
|
|
||||||
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TOO_SMALL_MICROVIA );
|
|
||||||
|
|
||||||
m_msg.Printf( drcItem->GetErrorText() + _( " (board minimum %s; actual %s)" ),
|
|
||||||
MessageTextFromValue( userUnits(), bds.m_MicroViasMinSize, true ),
|
|
||||||
MessageTextFromValue( userUnits(), refvia->GetWidth(), true ) );
|
|
||||||
|
|
||||||
drcItem->SetErrorMessage( m_msg );
|
|
||||||
drcItem->SetItems( refvia );
|
|
||||||
|
|
||||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
|
|
||||||
addMarkerToPcb( aCommit, marker );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -203,9 +355,9 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
|
|
||||||
if( viaAnnulus < minAnnulus )
|
if( viaAnnulus < minAnnulus )
|
||||||
{
|
{
|
||||||
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TOO_SMALL_VIA_ANNULUS );
|
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_VIA_ANNULUS );
|
||||||
|
|
||||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ),
|
m_msg.Printf( _( "Via annulus too small (%s %s; actual %s)" ),
|
||||||
m_clearanceSource,
|
m_clearanceSource,
|
||||||
MessageTextFromValue( userUnits(), minAnnulus, true ),
|
MessageTextFromValue( userUnits(), minAnnulus, true ),
|
||||||
MessageTextFromValue( userUnits(), viaAnnulus, true ) );
|
MessageTextFromValue( userUnits(), viaAnnulus, true ) );
|
||||||
|
@ -216,138 +368,8 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
|
MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
|
||||||
addMarkerToPcb( aCommit, marker );
|
addMarkerToPcb( aCommit, marker );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( refvia->GetWidth() < bds.m_ViasMinSize )
|
|
||||||
{
|
|
||||||
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TOO_SMALL_VIA );
|
|
||||||
|
|
||||||
m_msg.Printf( drcItem->GetErrorText() + _( " (board minimum %s; actual %s)" ),
|
|
||||||
MessageTextFromValue( userUnits(), bds.m_ViasMinSize, true ),
|
|
||||||
MessageTextFromValue( userUnits(), refvia->GetWidth(), true ) );
|
|
||||||
|
|
||||||
drcItem->SetErrorMessage( m_msg );
|
|
||||||
drcItem->SetItems( refvia );
|
|
||||||
|
|
||||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
|
|
||||||
addMarkerToPcb( aCommit, marker );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// test if via's hole is bigger than its diameter
|
|
||||||
// This test is necessary since the via hole size and width can be modified
|
|
||||||
// and a default via hole can be bigger than some vias sizes
|
|
||||||
if( refvia->GetDrillValue() > refvia->GetWidth() )
|
|
||||||
{
|
|
||||||
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_VIA_HOLE_BIGGER );
|
|
||||||
|
|
||||||
m_msg.Printf( drcItem->GetErrorText() + _( " (diameter %s; drill %s)" ),
|
|
||||||
MessageTextFromValue( userUnits(), refvia->GetWidth(), true ),
|
|
||||||
MessageTextFromValue( userUnits(), refvia->GetDrillValue(), true ) );
|
|
||||||
|
|
||||||
drcItem->SetErrorMessage( m_msg );
|
|
||||||
drcItem->SetItems( refvia );
|
|
||||||
|
|
||||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
|
|
||||||
addMarkerToPcb( aCommit, marker );
|
|
||||||
}
|
|
||||||
|
|
||||||
// test if the type of via is allowed due to design rules
|
|
||||||
if( refvia->GetViaType() == VIATYPE::MICROVIA && !bds.m_MicroViasAllowed )
|
|
||||||
{
|
|
||||||
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_MICROVIA_NOT_ALLOWED );
|
|
||||||
|
|
||||||
m_msg.Printf( drcItem->GetErrorText() + _( " (board design rule constraints)" ) );
|
|
||||||
drcItem->SetErrorMessage( m_msg );
|
|
||||||
drcItem->SetItems( refvia );
|
|
||||||
|
|
||||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
|
|
||||||
addMarkerToPcb( aCommit, marker );
|
|
||||||
}
|
|
||||||
|
|
||||||
// test if the type of via is allowed due to design rules
|
|
||||||
if( refvia->GetViaType() == VIATYPE::BLIND_BURIED && !bds.m_BlindBuriedViaAllowed )
|
|
||||||
{
|
|
||||||
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_BURIED_VIA_NOT_ALLOWED );
|
|
||||||
|
|
||||||
m_msg.Printf( drcItem->GetErrorText() + _( " (board design rule constraints)" ) );
|
|
||||||
drcItem->SetErrorMessage( m_msg );
|
|
||||||
drcItem->SetItems( refvia );
|
|
||||||
|
|
||||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
|
|
||||||
addMarkerToPcb( aCommit, marker );
|
|
||||||
}
|
|
||||||
|
|
||||||
// For microvias: test if they are blind vias and only between 2 layers
|
|
||||||
// because they are used for very small drill size and are drill by laser
|
|
||||||
// and **only one layer** can be drilled
|
|
||||||
if( refvia->GetViaType() == VIATYPE::MICROVIA )
|
|
||||||
{
|
|
||||||
PCB_LAYER_ID layer1, layer2;
|
|
||||||
bool err = true;
|
|
||||||
|
|
||||||
refvia->LayerPair( &layer1, &layer2 );
|
|
||||||
|
|
||||||
if( layer1 > layer2 )
|
|
||||||
std::swap( layer1, layer2 );
|
|
||||||
|
|
||||||
if( layer2 == B_Cu && layer1 == bds.GetCopperLayerCount() - 2 )
|
|
||||||
err = false;
|
|
||||||
else if( layer1 == F_Cu && layer2 == In1_Cu )
|
|
||||||
err = false;
|
|
||||||
|
|
||||||
if( err )
|
|
||||||
{
|
|
||||||
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_MICROVIA_TOO_MANY_LAYERS );
|
|
||||||
|
|
||||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s and %s not adjacent)" ),
|
|
||||||
m_pcb->GetLayerName( layer1 ),
|
|
||||||
m_pcb->GetLayerName( layer2 ) );
|
|
||||||
|
|
||||||
drcItem->SetErrorMessage( m_msg );
|
|
||||||
drcItem->SetItems( refvia );
|
|
||||||
|
|
||||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, refvia->GetPosition() );
|
|
||||||
addMarkerToPcb( aCommit, marker );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else // This is a track segment
|
|
||||||
{
|
|
||||||
int minWidth, maxWidth;
|
|
||||||
aRefSeg->GetWidthConstraints( &minWidth, &maxWidth, &m_clearanceSource );
|
|
||||||
|
|
||||||
int errorCode = 0;
|
|
||||||
int constraintWidth;
|
|
||||||
|
|
||||||
if( refSegWidth < minWidth )
|
|
||||||
{
|
|
||||||
errorCode = DRCE_TOO_SMALL_TRACK_WIDTH;
|
|
||||||
constraintWidth = minWidth;
|
|
||||||
}
|
|
||||||
else if( refSegWidth > maxWidth )
|
|
||||||
{
|
|
||||||
errorCode = DRCE_TOO_LARGE_TRACK_WIDTH;
|
|
||||||
constraintWidth = maxWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( errorCode )
|
|
||||||
{
|
|
||||||
wxPoint refsegMiddle = ( aRefSeg->GetStart() + aRefSeg->GetEnd() ) / 2;
|
|
||||||
|
|
||||||
DRC_ITEM* drcItem = new DRC_ITEM( errorCode );
|
|
||||||
|
|
||||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ),
|
|
||||||
m_clearanceSource,
|
|
||||||
MessageTextFromValue( userUnits(), constraintWidth, true ),
|
|
||||||
MessageTextFromValue( userUnits(), refSegWidth, true ) );
|
|
||||||
|
|
||||||
drcItem->SetErrorMessage( m_msg );
|
|
||||||
drcItem->SetItems( aRefSeg );
|
|
||||||
|
|
||||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, refsegMiddle );
|
|
||||||
addMarkerToPcb( aCommit, marker );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -371,7 +393,7 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
if( !inflatedBB.Contains( pad->GetPosition() ) )
|
if( !inflatedBB.Contains( pad->GetPosition() ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( !( pad->GetLayerSet() & refLayerSet ).any() )
|
if( !pad->IsOnLayer( aLayer ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// No need to check pads with the same net as the refSeg.
|
// No need to check pads with the same net as the refSeg.
|
||||||
|
@ -415,15 +437,14 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
slotEnd += pad->GetPosition();
|
slotEnd += pad->GetPosition();
|
||||||
|
|
||||||
SEG slotSeg( slotStart, slotEnd );
|
SEG slotSeg( slotStart, slotEnd );
|
||||||
int widths = ( slotWidth + refSegWidth ) / 2;
|
int center2centerAllowed = minClearance + halfWidth + bds.GetDRCEpsilon();
|
||||||
int center2centerAllowed = minClearance + widths + bds.GetDRCEpsilon();
|
|
||||||
|
|
||||||
// Avoid square-roots if possible (for performance)
|
// Avoid square-roots if possible (for performance)
|
||||||
SEG::ecoord center2center_squared = refSeg.SquaredDistance( slotSeg );
|
SEG::ecoord center2center_squared = refSeg.SquaredDistance( slotSeg );
|
||||||
|
|
||||||
if( center2center_squared < SEG::Square( center2centerAllowed ) )
|
if( center2center_squared < SEG::Square( center2centerAllowed ) )
|
||||||
{
|
{
|
||||||
int actual = std::max( 0.0, sqrt( center2center_squared ) - widths );
|
int actual = std::max( 0.0, sqrt( center2center_squared ) - halfWidth );
|
||||||
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_HOLE );
|
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_HOLE );
|
||||||
|
|
||||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
|
m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
|
||||||
|
@ -442,11 +463,11 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int minClearance = aRefSeg->GetClearance( pad, &m_clearanceSource );
|
int minClearance = aRefSeg->GetClearance( aLayer, pad, &m_clearanceSource );
|
||||||
int clearanceAllowed = minClearance - bds.GetDRCEpsilon();
|
int clearanceAllowed = minClearance - bds.GetDRCEpsilon();
|
||||||
int actual;
|
int actual;
|
||||||
|
|
||||||
if( !checkClearanceSegmToPad( refSeg, refSegWidth, pad, clearanceAllowed, &actual ) )
|
if( !checkClearanceSegmToPad( refSeg, refSeg.GetWidth(), pad, clearanceAllowed, &actual ) )
|
||||||
{
|
{
|
||||||
actual = std::max( 0, actual );
|
actual = std::max( 0, actual );
|
||||||
SEG padSeg( pad->GetPosition(), pad->GetPosition() );
|
SEG padSeg( pad->GetPosition(), pad->GetPosition() );
|
||||||
|
@ -482,27 +503,7 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
if( aRefSeg->GetNetCode() == track->GetNetCode() )
|
if( aRefSeg->GetNetCode() == track->GetNetCode() )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// No problem if tracks are on different layers:
|
if( !track->GetLayerSet().test( aLayer ) )
|
||||||
// Note that while the general case of GetLayerSet intersection always works,
|
|
||||||
// the others are much faster.
|
|
||||||
bool sameLayers;
|
|
||||||
|
|
||||||
if( aRefSeg->Type() == PCB_VIA_T )
|
|
||||||
{
|
|
||||||
if( track->Type() == PCB_VIA_T )
|
|
||||||
sameLayers = ( refLayerSet & track->GetLayerSet() ).any();
|
|
||||||
else
|
|
||||||
sameLayers = refLayerSet.test( track->GetLayer() );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if( track->Type() == PCB_VIA_T )
|
|
||||||
sameLayers = track->GetLayerSet().test( refLayer );
|
|
||||||
else
|
|
||||||
sameLayers = track->GetLayer() == refLayer;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !sameLayers )
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Preflight based on worst-case inflated bounding boxes:
|
// Preflight based on worst-case inflated bounding boxes:
|
||||||
|
@ -512,9 +513,19 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
if( !trackBB.Intersects( refSegBB ) )
|
if( !trackBB.Intersects( refSegBB ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int minClearance = aRefSeg->GetClearance( track, &m_clearanceSource );
|
int minClearance = aRefSeg->GetClearance( aLayer, track, &m_clearanceSource );
|
||||||
SEG trackSeg( track->GetStart(), track->GetEnd() );
|
SEG trackSeg( track->GetStart(), track->GetEnd() );
|
||||||
int widths = ( refSegWidth + track->GetWidth() ) / 2;
|
int widths = ( track->GetWidth() / 2 ) + halfWidth;
|
||||||
|
|
||||||
|
/// Check to see if the via has a pad on this layer
|
||||||
|
if( track->Type() == PCB_VIA_T )
|
||||||
|
{
|
||||||
|
VIA* via = static_cast<VIA*>( track );
|
||||||
|
|
||||||
|
if( !via->IsPadOnLayer( aLayer ) )
|
||||||
|
widths = ( via->GetDrillValue() / 2 ) + halfWidth;
|
||||||
|
}
|
||||||
|
|
||||||
int center2centerAllowed = minClearance + widths;
|
int center2centerAllowed = minClearance + widths;
|
||||||
|
|
||||||
// Avoid square-roots if possible (for performance)
|
// Avoid square-roots if possible (for performance)
|
||||||
|
@ -574,19 +585,16 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
|
|
||||||
for( ZONE_CONTAINER* zone : m_pcb->Zones() )
|
for( ZONE_CONTAINER* zone : m_pcb->Zones() )
|
||||||
{
|
{
|
||||||
if( zone->GetFilledPolysList().IsEmpty() || zone->GetIsKeepout() )
|
if( !zone->GetLayerSet().test( aLayer ) || zone->GetFilledPolysList( aLayer ).IsEmpty()
|
||||||
continue;
|
|| zone->GetIsKeepout() )
|
||||||
|
|
||||||
if( !( refLayerSet & zone->GetLayerSet() ).any() )
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( zone->GetNetCode() && zone->GetNetCode() == aRefSeg->GetNetCode() )
|
if( zone->GetNetCode() && zone->GetNetCode() == aRefSeg->GetNetCode() )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int minClearance = aRefSeg->GetClearance( zone, &m_clearanceSource );
|
int minClearance = aRefSeg->GetClearance( aLayer, zone, &m_clearanceSource );
|
||||||
int widths = refSegWidth / 2;
|
int center2centerAllowed = minClearance + halfWidth;
|
||||||
int center2centerAllowed = minClearance + widths;
|
SHAPE_POLY_SET* outline = const_cast<SHAPE_POLY_SET*>( &zone->GetFilledPolysList( aLayer ) );
|
||||||
SHAPE_POLY_SET* outline = const_cast<SHAPE_POLY_SET*>( &zone->GetFilledPolysList() );
|
|
||||||
|
|
||||||
SEG::ecoord center2center_squared = outline->SquaredDistance( testSeg );
|
SEG::ecoord center2center_squared = outline->SquaredDistance( testSeg );
|
||||||
|
|
||||||
|
@ -597,7 +605,7 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
|
|
||||||
if( center2center_squared + THRESHOLD_DIST < SEG::Square( center2centerAllowed ) )
|
if( center2center_squared + THRESHOLD_DIST < SEG::Square( center2centerAllowed ) )
|
||||||
{
|
{
|
||||||
int actual = std::max( 0.0, sqrt( center2center_squared ) - widths );
|
int actual = std::max( 0.0, sqrt( center2center_squared ) - halfWidth );
|
||||||
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_ZONE );
|
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_ZONE );
|
||||||
|
|
||||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
|
m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
|
||||||
|
@ -625,11 +633,10 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
static DRAWSEGMENT dummyEdge;
|
static DRAWSEGMENT dummyEdge;
|
||||||
dummyEdge.SetLayer( Edge_Cuts );
|
dummyEdge.SetLayer( Edge_Cuts );
|
||||||
|
|
||||||
if( aRefSeg->GetRuleClearance( &dummyEdge, &minClearance, &m_clearanceSource ) )
|
if( aRefSeg->GetRuleClearance( &dummyEdge, aLayer, &minClearance, &m_clearanceSource ) )
|
||||||
/* minClearance and m_clearanceSource set in GetRuleClearance() */;
|
/* minClearance and m_clearanceSource set in GetRuleClearance() */;
|
||||||
|
|
||||||
SEG testSeg( aRefSeg->GetStart(), aRefSeg->GetEnd() );
|
SEG testSeg( aRefSeg->GetStart(), aRefSeg->GetEnd() );
|
||||||
int halfWidth = refSegWidth / 2;
|
|
||||||
int center2centerAllowed = minClearance + halfWidth;
|
int center2centerAllowed = minClearance + halfWidth;
|
||||||
|
|
||||||
for( auto it = m_board_outlines.IterateSegmentsWithHoles(); it; it++ )
|
for( auto it = m_board_outlines.IterateSegmentsWithHoles(); it; it++ )
|
||||||
|
|
Loading…
Reference in New Issue