Add mechanical copper clearance testing for shapes.
Also includes going from distance-based neighbor exclusion to angle- based. (Distance doesn't work when very short segments are followed by very long ones.) Fixes https://gitlab.com/kicad/code/kicad/issues/2512
This commit is contained in:
parent
1305c2177f
commit
4b6f2f0658
|
@ -222,8 +222,6 @@ public:
|
|||
|
||||
void SetPolyShape( const SHAPE_POLY_SET& aShape ) { m_poly = aShape; }
|
||||
|
||||
void SetBezierPoints( const std::vector<wxPoint>& aPoints ) { m_bezierPoints = aPoints; }
|
||||
|
||||
/**
|
||||
* Rebuild the m_BezierPoints vertex list that approximate the Bezier curve
|
||||
* by a list of segments.
|
||||
|
|
|
@ -629,7 +629,7 @@ void DRC_ENGINE::RunTests( EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aT
|
|||
zone->CacheBoundingBox();
|
||||
zone->CacheTriangulation();
|
||||
|
||||
if( !zone->GetIsRuleArea() )
|
||||
if( ( zone->GetLayerSet() & LSET::AllCuMask() ).any() && !zone->GetIsRuleArea() )
|
||||
copperZones.push_back( zone );
|
||||
}
|
||||
|
||||
|
@ -640,7 +640,7 @@ void DRC_ENGINE::RunTests( EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aT
|
|||
zone->CacheBoundingBox();
|
||||
zone->CacheTriangulation();
|
||||
|
||||
if( !zone->GetIsRuleArea() )
|
||||
if( ( zone->GetLayerSet() & LSET::AllCuMask() ).any() && !zone->GetIsRuleArea() )
|
||||
copperZones.push_back( zone );
|
||||
}
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ private:
|
|||
DRC_RTREE m_copperTree;
|
||||
int m_drcEpsilon;
|
||||
|
||||
std::vector<ZONE*> m_zones;
|
||||
std::vector<ZONE*> m_copperZones;
|
||||
};
|
||||
|
||||
|
||||
|
@ -121,13 +121,13 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::Run()
|
|||
|
||||
m_drcEpsilon = m_board->GetDesignSettings().GetDRCEpsilon();
|
||||
|
||||
m_zones.clear();
|
||||
m_copperZones.clear();
|
||||
|
||||
for( ZONE* zone : m_board->Zones() )
|
||||
{
|
||||
if( !zone->GetIsRuleArea() )
|
||||
if( ( zone->GetLayerSet() & LSET::AllCuMask() ).any() && !zone->GetIsRuleArea() )
|
||||
{
|
||||
m_zones.push_back( zone );
|
||||
m_copperZones.push_back( zone );
|
||||
m_largestClearance = std::max( m_largestClearance, zone->GetLocalClearance() );
|
||||
}
|
||||
}
|
||||
|
@ -139,9 +139,9 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::Run()
|
|||
|
||||
for( ZONE* zone : footprint->Zones() )
|
||||
{
|
||||
if( !zone->GetIsRuleArea() )
|
||||
if( ( zone->GetLayerSet() & LSET::AllCuMask() ).any() && !zone->GetIsRuleArea() )
|
||||
{
|
||||
m_zones.push_back( zone );
|
||||
m_copperZones.push_back( zone );
|
||||
m_largestClearance = std::max( m_largestClearance, zone->GetLocalClearance() );
|
||||
}
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::Run()
|
|||
forEachGeometryItem( itemTypes, LSET::AllCuMask(), countItems );
|
||||
forEachGeometryItem( itemTypes, LSET::AllCuMask(), addToCopperTree );
|
||||
|
||||
reportAux( "Testing %d copper items and %d zones...", count, m_zones.size() );
|
||||
reportAux( "Testing %d copper items and %d zones...", count, m_copperZones.size() );
|
||||
|
||||
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_CLEARANCE ) )
|
||||
{
|
||||
|
@ -377,7 +377,7 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackAgainstItem( PCB_TRACK* track,
|
|||
void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testItemAgainstZones( BOARD_ITEM* aItem,
|
||||
PCB_LAYER_ID aLayer )
|
||||
{
|
||||
for( ZONE* zone : m_zones )
|
||||
for( ZONE* zone : m_copperZones )
|
||||
{
|
||||
if( !zone->GetLayerSet().test( aLayer ) )
|
||||
continue;
|
||||
|
@ -840,34 +840,34 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZonesToZones()
|
|||
{
|
||||
PCB_LAYER_ID layer = static_cast<PCB_LAYER_ID>( layer_id );
|
||||
std::vector<SHAPE_POLY_SET> smoothed_polys;
|
||||
smoothed_polys.resize( m_zones.size() );
|
||||
smoothed_polys.resize( m_copperZones.size() );
|
||||
|
||||
// Skip over layers not used on the current board
|
||||
if( !m_board->IsLayerEnabled( layer ) )
|
||||
continue;
|
||||
|
||||
for( size_t ii = 0; ii < m_zones.size(); ii++ )
|
||||
for( size_t ii = 0; ii < m_copperZones.size(); ii++ )
|
||||
{
|
||||
if( m_zones[ii]->IsOnLayer( layer ) )
|
||||
m_zones[ii]->BuildSmoothedPoly( smoothed_polys[ii], layer, boardOutline );
|
||||
if( m_copperZones[ii]->IsOnLayer( layer ) )
|
||||
m_copperZones[ii]->BuildSmoothedPoly( smoothed_polys[ii], layer, boardOutline );
|
||||
}
|
||||
|
||||
// iterate through all areas
|
||||
for( size_t ia = 0; ia < m_zones.size(); ia++ )
|
||||
for( size_t ia = 0; ia < m_copperZones.size(); ia++ )
|
||||
{
|
||||
if( !reportProgress( layer_id * m_zones.size() + ia, B_Cu * m_zones.size(), delta ) )
|
||||
if( !reportProgress( layer_id * m_copperZones.size() + ia, B_Cu * m_copperZones.size(), delta ) )
|
||||
break;
|
||||
|
||||
ZONE* zoneRef = m_zones[ia];
|
||||
ZONE* zoneRef = m_copperZones[ia];
|
||||
|
||||
if( !zoneRef->IsOnLayer( layer ) )
|
||||
continue;
|
||||
|
||||
// If we are testing a single zone, then iterate through all other zones
|
||||
// Otherwise, we have already tested the zone combination
|
||||
for( size_t ia2 = ia + 1; ia2 < m_zones.size(); ia2++ )
|
||||
for( size_t ia2 = ia + 1; ia2 < m_copperZones.size(); ia2++ )
|
||||
{
|
||||
ZONE* zoneToTest = m_zones[ia2];
|
||||
ZONE* zoneToTest = m_copperZones[ia2];
|
||||
|
||||
if( zoneRef == zoneToTest )
|
||||
continue;
|
||||
|
|
|
@ -22,15 +22,16 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <macros.h>
|
||||
#include <board_design_settings.h>
|
||||
#include <footprint.h>
|
||||
#include <pad.h>
|
||||
#include <pcb_track.h>
|
||||
#include <pcb_shape.h>
|
||||
#include <zone.h>
|
||||
|
||||
#include <advanced_config.h>
|
||||
#include <geometry/seg.h>
|
||||
#include <geometry/shape_segment.h>
|
||||
|
||||
#include <drc/drc_engine.h>
|
||||
#include <drc/drc_rtree.h>
|
||||
#include <drc/drc_item.h>
|
||||
|
@ -77,7 +78,10 @@ private:
|
|||
|
||||
void testItemAgainstZones( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer );
|
||||
|
||||
void testZoneLayer( ZONE* aZone, PCB_LAYER_ID aLayer );
|
||||
void testShapeLineChain( const SHAPE_LINE_CHAIN& aOutline, int aLineWidth,
|
||||
BOARD_ITEM* aParentItem, DRC_CONSTRAINT& aConstraint );
|
||||
|
||||
void testZoneLayer( ZONE* aZone, PCB_LAYER_ID aLayer, DRC_CONSTRAINT& aConstraint );
|
||||
|
||||
private:
|
||||
DRC_RTREE m_itemTree;
|
||||
|
@ -93,6 +97,7 @@ bool DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::Run()
|
|||
m_zones.clear();
|
||||
m_items.clear();
|
||||
|
||||
int errorMax = m_board->GetDesignSettings().m_MaxError;
|
||||
DRC_CONSTRAINT worstConstraint;
|
||||
|
||||
if( m_drcEngine->QueryWorstConstraint( MECHANICAL_CLEARANCE_CONSTRAINT, worstConstraint ) )
|
||||
|
@ -231,7 +236,7 @@ bool DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::Run()
|
|||
|
||||
for( BOARD_ITEM* item : m_items )
|
||||
{
|
||||
if( !reportProgress( ii++, m_board->Tracks().size(), delta ) )
|
||||
if( !reportProgress( ii++, m_items.size(), delta ) )
|
||||
break;
|
||||
|
||||
for( PCB_LAYER_ID layer : item->GetLayerSet().Seq() )
|
||||
|
@ -240,20 +245,41 @@ bool DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::Run()
|
|||
}
|
||||
|
||||
count = 0;
|
||||
forEachGeometryItem( { PCB_ZONE_T, PCB_FP_ZONE_T }, LSET::AllCuMask(),
|
||||
forEachGeometryItem( { PCB_ZONE_T, PCB_FP_ZONE_T, PCB_SHAPE_T, PCB_FP_SHAPE_T },
|
||||
LSET::AllCuMask(),
|
||||
[&]( BOARD_ITEM* item ) -> bool
|
||||
{
|
||||
for( PCB_LAYER_ID layer : item->GetLayerSet().Seq() )
|
||||
PCB_SHAPE* shape = dynamic_cast<PCB_SHAPE*>( item );
|
||||
ZONE* zone = dynamic_cast<ZONE*>( item );
|
||||
|
||||
if( shape )
|
||||
{
|
||||
if( IsCopperLayer( layer ) )
|
||||
switch( shape->GetShape() )
|
||||
{
|
||||
case SHAPE_T::POLY:
|
||||
case SHAPE_T::BEZIER:
|
||||
case SHAPE_T::ARC:
|
||||
if( IsCopperLayer( shape->GetLayer() ) )
|
||||
count++;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( zone )
|
||||
{
|
||||
count += ( item->GetLayerSet() & LSET::AllCuMask() ).count();
|
||||
}
|
||||
|
||||
return true;
|
||||
} );
|
||||
|
||||
ii = 0;
|
||||
forEachGeometryItem( { PCB_ZONE_T, PCB_FP_ZONE_T }, LSET::AllCuMask(),
|
||||
forEachGeometryItem( { PCB_ZONE_T, PCB_FP_ZONE_T, PCB_SHAPE_T, PCB_FP_SHAPE_T },
|
||||
LSET::AllCuMask(),
|
||||
[&]( BOARD_ITEM* item ) -> bool
|
||||
{
|
||||
for( PCB_LAYER_ID layer : item->GetLayerSet().Seq() )
|
||||
|
@ -263,7 +289,66 @@ bool DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::Run()
|
|||
if( !reportProgress( ii++, count, delta ) )
|
||||
return false;
|
||||
|
||||
testZoneLayer( static_cast<ZONE*>( item ), layer );
|
||||
PCB_SHAPE* shape = dynamic_cast<PCB_SHAPE*>( item );
|
||||
ZONE* zone = dynamic_cast<ZONE*>( item );
|
||||
DRC_CONSTRAINT c = m_drcEngine->EvalRules( MECHANICAL_CLEARANCE_CONSTRAINT,
|
||||
item, nullptr, layer );
|
||||
|
||||
if( shape )
|
||||
{
|
||||
switch( shape->GetShape() )
|
||||
{
|
||||
case SHAPE_T::POLY:
|
||||
testShapeLineChain( shape->GetPolyShape().Outline( 0 ),
|
||||
shape->GetWidth(), item, c );
|
||||
break;
|
||||
|
||||
case SHAPE_T::BEZIER:
|
||||
{
|
||||
SHAPE_LINE_CHAIN asPoly;
|
||||
|
||||
shape->RebuildBezierToSegmentsPointsList( shape->GetWidth() );
|
||||
|
||||
for( const wxPoint& pt : shape->GetBezierPoints() )
|
||||
asPoly.Append( pt );
|
||||
|
||||
testShapeLineChain( asPoly, shape->GetWidth(), item, c );
|
||||
break;
|
||||
}
|
||||
|
||||
case SHAPE_T::ARC:
|
||||
{
|
||||
SHAPE_LINE_CHAIN asPoly;
|
||||
|
||||
wxPoint center = shape->GetCenter();
|
||||
double angle = -shape->GetArcAngle();
|
||||
double r = shape->GetRadius();
|
||||
int steps = GetArcToSegmentCount( r, errorMax, angle / 10.0 );
|
||||
|
||||
asPoly.Append( shape->GetStart() );
|
||||
|
||||
for( int step = 1; step <= steps; ++step )
|
||||
{
|
||||
double rotation = ( angle * step ) / steps;
|
||||
|
||||
wxPoint pt = shape->GetStart();
|
||||
RotatePoint( &pt, center, rotation );
|
||||
asPoly.Append( pt );
|
||||
}
|
||||
|
||||
testShapeLineChain( asPoly, shape->GetWidth(), item, c );
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() );
|
||||
}
|
||||
}
|
||||
|
||||
if( zone )
|
||||
{
|
||||
testZoneLayer( static_cast<ZONE*>( item ), layer, c );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,15 +361,154 @@ bool DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::Run()
|
|||
}
|
||||
|
||||
|
||||
void DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::testZoneLayer( ZONE* aZone, PCB_LAYER_ID aLayer )
|
||||
void DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::testShapeLineChain( const SHAPE_LINE_CHAIN& aOutline,
|
||||
int aLineWidth,
|
||||
BOARD_ITEM* aParentItem,
|
||||
DRC_CONSTRAINT& aConstraint )
|
||||
{
|
||||
// We don't want to collide with neighboring segments forming a curve until the concavity
|
||||
// approaches 180 degrees.
|
||||
double angleTolerance = DEG2RAD( 180.0 - ADVANCED_CFG::GetCfg().m_SliverAngleTolerance );
|
||||
int epsilon = m_board->GetDesignSettings().GetDRCEpsilon();
|
||||
int count = aOutline.SegmentCount();
|
||||
int clearance = aConstraint.GetValue().Min();
|
||||
|
||||
// Trigonometry is not cheap; cache seg angles
|
||||
std::vector<double> angles;
|
||||
angles.reserve( count );
|
||||
|
||||
auto angleDiff =
|
||||
[]( double a, double b ) -> double
|
||||
{
|
||||
if( a > b )
|
||||
std::swap( a, b );
|
||||
|
||||
double diff = b - a;
|
||||
|
||||
if( diff > M_PI )
|
||||
return 2 * M_PI - diff;
|
||||
else
|
||||
return diff;
|
||||
};
|
||||
|
||||
for( int ii = 0; ii < count; ++ii )
|
||||
{
|
||||
const SEG& seg = aOutline.CSegment( ii );
|
||||
|
||||
// NB: don't store angles of really short segments (which could point anywhere)
|
||||
|
||||
if( seg.SquaredLength() > SEG::Square( epsilon * 2 ) )
|
||||
{
|
||||
angles.push_back( ( seg.B - seg.A ).Angle() );
|
||||
}
|
||||
else if( ii > 0 )
|
||||
{
|
||||
angles.push_back( angles.back() );
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int jj = 1; jj < count; ++jj )
|
||||
{
|
||||
const SEG& following = aOutline.CSegment( jj );
|
||||
|
||||
if( following.SquaredLength() > SEG::Square( epsilon * 2 ) || jj == count - 1 )
|
||||
{
|
||||
angles.push_back( ( following.B - following.A ).Angle() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find collisions before reporting so that we can condense them into fewer reports.
|
||||
std::vector< std::pair<VECTOR2I, int> > collisions;
|
||||
|
||||
for( int ii = 0; ii < count; ++ii )
|
||||
{
|
||||
const SEG seg = aOutline.CSegment( ii );
|
||||
double segAngle = angles[ ii ];
|
||||
|
||||
// Exclude segments on either side of us until we reach the angle tolerance
|
||||
int firstCandidate = ii + 1;
|
||||
int lastCandidate = count - 1;
|
||||
|
||||
while( firstCandidate < count )
|
||||
{
|
||||
if( angleDiff( segAngle, angles[ firstCandidate ] ) < angleTolerance )
|
||||
firstCandidate++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if( aOutline.IsClosed() )
|
||||
{
|
||||
if( ii > 0 )
|
||||
lastCandidate = ii - 1;
|
||||
|
||||
while( lastCandidate != std::min( firstCandidate, count - 1 ) )
|
||||
{
|
||||
if( angleDiff( segAngle, angles[ lastCandidate ] ) < angleTolerance )
|
||||
lastCandidate = ( lastCandidate == 0 ) ? count - 1 : lastCandidate - 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Now run the collision between seg and each candidate seg in the candidate range.
|
||||
if( lastCandidate < ii )
|
||||
lastCandidate = count - 1;
|
||||
|
||||
for( int jj = firstCandidate; jj <= lastCandidate; ++jj )
|
||||
{
|
||||
const SEG candidate = aOutline.CSegment( jj );
|
||||
int actual;
|
||||
|
||||
if( seg.Collide( candidate, clearance + aLineWidth - epsilon, &actual ) )
|
||||
{
|
||||
VECTOR2I firstPoint = seg.NearestPoint( candidate );
|
||||
VECTOR2I secondPoint = candidate.NearestPoint( seg );
|
||||
VECTOR2I pos = ( firstPoint + secondPoint ) / 2;
|
||||
|
||||
if( !collisions.empty() &&
|
||||
( pos - collisions.back().first ).EuclideanNorm() < clearance * 2 )
|
||||
{
|
||||
if( actual < collisions.back().second )
|
||||
{
|
||||
collisions.back().first = pos;
|
||||
collisions.back().second = actual;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
collisions.push_back( { pos, actual } );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( std::pair<VECTOR2I, int> collision : collisions )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drce = DRC_ITEM::Create( DRCE_CLEARANCE );
|
||||
|
||||
m_msg.Printf( _( "(%s clearance %s; actual %s)" ),
|
||||
aConstraint.GetName(),
|
||||
MessageTextFromValue( userUnits(), clearance ),
|
||||
MessageTextFromValue( userUnits(), collision.second ) );
|
||||
|
||||
drce->SetErrorMessage( drce->GetErrorText() + wxS( " " ) + m_msg );
|
||||
drce->SetItems( aParentItem );
|
||||
drce->SetViolatingRule( aConstraint.GetParentRule() );
|
||||
|
||||
reportViolation( drce, (wxPoint) collision.first );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::testZoneLayer( ZONE* aZone, PCB_LAYER_ID aLayer,
|
||||
DRC_CONSTRAINT& aConstraint )
|
||||
{
|
||||
int epsilon = m_board->GetDesignSettings().GetDRCEpsilon();
|
||||
int clearance = aConstraint.GetValue().Min();
|
||||
SHAPE_POLY_SET fill = aZone->GetFilledPolysList( aLayer );
|
||||
DRC_CONSTRAINT constraint;
|
||||
int clearance;
|
||||
|
||||
constraint = m_drcEngine->EvalRules( MECHANICAL_CLEARANCE_CONSTRAINT, aZone, nullptr, aLayer );
|
||||
clearance = constraint.GetValue().Min();
|
||||
|
||||
if( clearance - epsilon <= 0 )
|
||||
return;
|
||||
|
@ -313,13 +537,13 @@ void DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::testZoneLayer( ZONE* aZone, PCB_LAY
|
|||
std::shared_ptr<DRC_ITEM> drce = DRC_ITEM::Create( DRCE_CLEARANCE );
|
||||
|
||||
m_msg.Printf( _( "(%s clearance %s; actual %s)" ),
|
||||
constraint.GetName(),
|
||||
aConstraint.GetName(),
|
||||
MessageTextFromValue( userUnits(), clearance ),
|
||||
MessageTextFromValue( userUnits(), actual ) );
|
||||
|
||||
drce->SetErrorMessage( drce->GetErrorText() + wxS( " " ) + m_msg );
|
||||
drce->SetItems( aZone );
|
||||
drce->SetViolatingRule( constraint.GetParentRule() );
|
||||
drce->SetViolatingRule( aConstraint.GetParentRule() );
|
||||
|
||||
reportViolation( drce, (wxPoint) pos );
|
||||
}
|
||||
|
@ -330,76 +554,7 @@ void DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::testZoneLayer( ZONE* aZone, PCB_LAY
|
|||
|
||||
for( int holeIdx = 0; holeIdx < fill.HoleCount( outlineIdx ); ++holeIdx )
|
||||
{
|
||||
SHAPE_LINE_CHAIN hole = fill.Hole( outlineIdx, holeIdx );
|
||||
int count = hole.SegmentCount();
|
||||
int distanceBackToStart = 0;
|
||||
|
||||
std::vector< std::pair<VECTOR2I, int> > collisions;
|
||||
|
||||
for( int ii = 0; ii < count; ++ii )
|
||||
{
|
||||
SEG seg = hole.Segment( ii );
|
||||
|
||||
// We don't want to collide with neighboring segments within clearance distance,
|
||||
// so we first need to set the firstCandidate and lastCandidate bounds of our
|
||||
// search.
|
||||
int firstCandidate = ii + 1;
|
||||
int lastCandidate = count - 1;
|
||||
int dist = 0;
|
||||
|
||||
while( firstCandidate < count && dist < clearance * 2 )
|
||||
dist += hole.Segment( firstCandidate++ ).Length();
|
||||
|
||||
dist = distanceBackToStart;
|
||||
|
||||
while( lastCandidate >= firstCandidate && dist < clearance * 2 )
|
||||
dist += hole.Segment( lastCandidate-- ).Length();
|
||||
|
||||
// Now run the collision between seg and each seg in the candidate range.
|
||||
for( int jj = firstCandidate; jj <= lastCandidate; ++jj )
|
||||
{
|
||||
SEG candidate = hole.Segment( jj );
|
||||
int actual;
|
||||
|
||||
if( seg.Collide( candidate, clearance - epsilon, &actual ) )
|
||||
{
|
||||
VECTOR2I firstPoint = seg.NearestPoint( candidate );
|
||||
VECTOR2I secondPoint = candidate.NearestPoint( seg );
|
||||
VECTOR2I pos = ( firstPoint + secondPoint ) / 2;
|
||||
|
||||
if( !collisions.empty() &&
|
||||
( pos - collisions.back().first ).EuclideanNorm() < clearance * 2 )
|
||||
{
|
||||
if( actual < collisions.back().second )
|
||||
{
|
||||
collisions.back().first = pos;
|
||||
collisions.back().second = actual;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
collisions.push_back( { pos, actual } );
|
||||
}
|
||||
}
|
||||
|
||||
distanceBackToStart += seg.Length();
|
||||
}
|
||||
|
||||
for( std::pair<VECTOR2I, int> collision : collisions )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drce = DRC_ITEM::Create( DRCE_CLEARANCE );
|
||||
|
||||
m_msg.Printf( _( "(%s clearance %s; actual %s)" ),
|
||||
constraint.GetName(),
|
||||
MessageTextFromValue( userUnits(), clearance ),
|
||||
MessageTextFromValue( userUnits(), collision.second ) );
|
||||
|
||||
drce->SetErrorMessage( drce->GetErrorText() + wxS( " " ) + m_msg );
|
||||
drce->SetItems( aZone );
|
||||
drce->SetViolatingRule( constraint.GetParentRule() );
|
||||
|
||||
reportViolation( drce, (wxPoint) collision.first );
|
||||
}
|
||||
testShapeLineChain( fill.Hole( outlineIdx, holeIdx ), 0, aZone, aConstraint );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -547,6 +702,7 @@ void DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::testItemAgainstZones( BOARD_ITEM* a
|
|||
DRC_RTREE* zoneTree = m_board->m_CopperZoneRTrees[ zone ].get();
|
||||
EDA_RECT itemBBox = aItem->GetBoundingBox();
|
||||
DRC_CONSTRAINT constraint;
|
||||
bool colliding;
|
||||
int clearance = -1;
|
||||
int actual;
|
||||
VECTOR2I pos;
|
||||
|
@ -583,8 +739,18 @@ void DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::testItemAgainstZones( BOARD_ITEM* a
|
|||
}
|
||||
}
|
||||
|
||||
if( zoneTree->QueryColliding( itemBBox, itemShape.get(), aLayer, clearance,
|
||||
&actual, &pos ) )
|
||||
if( zoneTree )
|
||||
{
|
||||
colliding = zoneTree->QueryColliding( itemBBox, itemShape.get(), aLayer,
|
||||
clearance, &actual, &pos );
|
||||
}
|
||||
else
|
||||
{
|
||||
colliding = zone->Outline()->Collide( itemShape.get(), clearance, &actual,
|
||||
&pos );
|
||||
}
|
||||
|
||||
if( colliding )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drce = DRC_ITEM::Create( DRCE_CLEARANCE );
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
(version 1)
|
||||
#(rule mine
|
||||
# (condition "A.NetName == 'GND'")
|
||||
# (constraint clearance (min 2mm)))
|
||||
|
||||
(rule "SilkZoneOverPads"
|
||||
(condition "A.Type == 'zone' && A.existsOnLayer('*.Silkscreen') && B.existsOnLayer('*.Mask')")
|
||||
(constraint silk_clearance (min -0.1mm)))
|
||||
|
||||
(rule mech
|
||||
(constraint mechanical_clearance (min 0.1mm)))
|
|
@ -0,0 +1,428 @@
|
|||
(kicad_pcb (version 20210812) (generator pcbnew)
|
||||
|
||||
(general
|
||||
(thickness 4.48)
|
||||
)
|
||||
|
||||
(paper "A4")
|
||||
(title_block
|
||||
(title "Demo Project showing SameNetSpacing problem caused by KiCads filling algorithm")
|
||||
(date "2019-10-07")
|
||||
(rev "0.1")
|
||||
)
|
||||
|
||||
(layers
|
||||
(0 "F.Cu" signal)
|
||||
(1 "In1.Cu" power)
|
||||
(2 "In2.Cu" power)
|
||||
(31 "B.Cu" signal)
|
||||
(32 "B.Adhes" user "B.Adhesive")
|
||||
(33 "F.Adhes" user "F.Adhesive")
|
||||
(34 "B.Paste" user)
|
||||
(35 "F.Paste" user)
|
||||
(36 "B.SilkS" user "B.Silkscreen")
|
||||
(37 "F.SilkS" user "F.Silkscreen")
|
||||
(38 "B.Mask" user)
|
||||
(39 "F.Mask" user)
|
||||
(40 "Dwgs.User" user "User.Drawings")
|
||||
(41 "Cmts.User" user "User.Comments")
|
||||
(42 "Eco1.User" user "User.Eco1")
|
||||
(43 "Eco2.User" user "User.Eco2")
|
||||
(44 "Edge.Cuts" user)
|
||||
(45 "Margin" user)
|
||||
(46 "B.CrtYd" user "B.Courtyard")
|
||||
(47 "F.CrtYd" user "F.Courtyard")
|
||||
(48 "B.Fab" user)
|
||||
(49 "F.Fab" user)
|
||||
)
|
||||
|
||||
(setup
|
||||
(stackup
|
||||
(layer "F.SilkS" (type "Top Silk Screen"))
|
||||
(layer "F.Paste" (type "Top Solder Paste"))
|
||||
(layer "F.Mask" (type "Top Solder Mask") (color "Green") (thickness 0.01))
|
||||
(layer "F.Cu" (type "copper") (thickness 0.035))
|
||||
(layer "dielectric 1" (type "core") (thickness 1.44) (material "FR4") (epsilon_r 4.5) (loss_tangent 0.02))
|
||||
(layer "In1.Cu" (type "copper") (thickness 0.035))
|
||||
(layer "dielectric 2" (type "prepreg") (thickness 1.44) (material "FR4") (epsilon_r 4.5) (loss_tangent 0.02))
|
||||
(layer "In2.Cu" (type "copper") (thickness 0.035))
|
||||
(layer "dielectric 3" (type "core") (thickness 1.44) (material "FR4") (epsilon_r 4.5) (loss_tangent 0.02))
|
||||
(layer "B.Cu" (type "copper") (thickness 0.035))
|
||||
(layer "B.Mask" (type "Bottom Solder Mask") (color "Green") (thickness 0.01))
|
||||
(layer "B.Paste" (type "Bottom Solder Paste"))
|
||||
(layer "B.SilkS" (type "Bottom Silk Screen"))
|
||||
(copper_finish "None")
|
||||
(dielectric_constraints no)
|
||||
)
|
||||
(pad_to_mask_clearance 0.05)
|
||||
(solder_mask_min_width 0.15)
|
||||
(aux_axis_origin 148.5 105)
|
||||
(pcbplotparams
|
||||
(layerselection 0x00010fc_ffffffff)
|
||||
(disableapertmacros false)
|
||||
(usegerberextensions false)
|
||||
(usegerberattributes false)
|
||||
(usegerberadvancedattributes false)
|
||||
(creategerberjobfile false)
|
||||
(svguseinch false)
|
||||
(svgprecision 6)
|
||||
(excludeedgelayer true)
|
||||
(plotframeref false)
|
||||
(viasonmask false)
|
||||
(mode 1)
|
||||
(useauxorigin false)
|
||||
(hpglpennumber 1)
|
||||
(hpglpenspeed 20)
|
||||
(hpglpendiameter 15.000000)
|
||||
(dxfpolygonmode true)
|
||||
(dxfimperialunits true)
|
||||
(dxfusepcbnewfont true)
|
||||
(psnegative false)
|
||||
(psa4output false)
|
||||
(plotreference true)
|
||||
(plotvalue true)
|
||||
(plotinvisibletext false)
|
||||
(sketchpadsonfab false)
|
||||
(subtractmaskfromsilk false)
|
||||
(outputformat 1)
|
||||
(mirror false)
|
||||
(drillshape 0)
|
||||
(scaleselection 1)
|
||||
(outputdirectory "gerber/")
|
||||
)
|
||||
)
|
||||
|
||||
(net 0 "")
|
||||
(net 1 "GND")
|
||||
(net 2 "VDD3V3")
|
||||
|
||||
(gr_arc (start 143.1036 129.9464) (end 142.240001 129.3876) (angle 350.9270568) (layer "In2.Cu") (width 0.1) (tstamp 6ba5cc1c-0aa9-403c-8c78-baeb88b53289))
|
||||
(gr_poly
|
||||
(pts
|
||||
|
||||
(xy 144.3736 127.3048)
|
||||
(xy 142.5956 127.3048)
|
||||
(xy 144.3736 128.27)
|
||||
(xy 144.3736 128.5748)
|
||||
(xy 142.0876 128.5748)
|
||||
(xy 142.0876 126.2888)
|
||||
(xy 144.3736 126.2888)
|
||||
) (layer "In2.Cu") (width 0.1) (fill solid) (tstamp abd486ea-b329-4192-afc3-c44eb6e87cea))
|
||||
(gr_poly
|
||||
(pts
|
||||
|
||||
(xy 147.4216 129.8956)
|
||||
(xy 145.3896 129.9464)
|
||||
(xy 145.3896 130.0988)
|
||||
(xy 147.4216 130.2512)
|
||||
(xy 147.4216 131.1656)
|
||||
(xy 144.8816 131.1656)
|
||||
(xy 144.8816 128.8796)
|
||||
(xy 147.4216 128.8796)
|
||||
) (layer "In2.Cu") (width 0.1) (fill solid) (tstamp b158edbd-63ca-41e4-8234-a443de3cf560))
|
||||
(gr_poly
|
||||
(pts
|
||||
|
||||
(xy 147.4216 127.3048)
|
||||
(xy 145.3896 127.3556)
|
||||
(xy 145.3896 127.4064)
|
||||
(xy 147.4216 127.6604)
|
||||
(xy 147.4216 128.5748)
|
||||
(xy 144.8816 128.5748)
|
||||
(xy 144.8816 126.2888)
|
||||
(xy 147.4216 126.2888)
|
||||
) (layer "In2.Cu") (width 0) (fill solid) (tstamp dda81f80-2a0f-4292-9d5e-54a02cef836f))
|
||||
(gr_rect (start 136.2456 125.5776) (end 147.864 131.7576) (layer "Edge.Cuts") (width 0.01) (fill none) (tstamp 2ff03438-48dd-4ff9-86ab-4aae55d6a1a4))
|
||||
|
||||
(via (at 138.2268 129.4445) (size 0.6096) (drill 0.3048) (layers "F.Cu" "B.Cu") (net 1) (tstamp 0a0bd538-0f11-4f77-8877-7ded1f64a1f5))
|
||||
(via (at 140.681801 128.8692) (size 0.6096) (drill 0.3048) (layers "F.Cu" "B.Cu") (net 1) (tstamp 278fe112-f2ff-479a-a63f-0a6506627139))
|
||||
(via (at 140.046801 129.4788) (size 0.6096) (drill 0.3048) (layers "F.Cu" "B.Cu") (net 1) (tstamp 6991baf3-a77e-489b-a4f3-31121be3dfdc))
|
||||
(via (at 137.5233 128.666) (size 0.6096) (drill 0.3048) (layers "F.Cu" "B.Cu") (net 1) (tstamp e48c293e-c06c-440a-8604-01ac35e3346f))
|
||||
|
||||
(zone (net 2) (net_name "VDD3V3") (layer "In2.Cu") (tstamp 00000000-0000-0000-0000-00005d9bbec6) (hatch none 0.508)
|
||||
(connect_pads (clearance 0.1524))
|
||||
(min_thickness 0.1524) (filled_areas_thickness no)
|
||||
(fill yes (thermal_gap 0.1524) (thermal_bridge_width 1.27) (island_removal_mode 1) (island_area_min 0))
|
||||
(polygon
|
||||
(pts
|
||||
(xy 136.7048 126.6)
|
||||
(xy 136.7048 130.8)
|
||||
(xy 141.5 130.8)
|
||||
(xy 141.5 126.6)
|
||||
)
|
||||
)
|
||||
(filled_polygon
|
||||
(layer "In2.Cu")
|
||||
(island)
|
||||
(pts
|
||||
(xy 141.473138 126.617593)
|
||||
(xy 141.498858 126.662142)
|
||||
(xy 141.5 126.6752)
|
||||
(xy 141.5 130.7248)
|
||||
(xy 141.482407 130.773138)
|
||||
(xy 141.437858 130.798858)
|
||||
(xy 141.4248 130.8)
|
||||
(xy 136.78 130.8)
|
||||
(xy 136.731662 130.782407)
|
||||
(xy 136.705942 130.737858)
|
||||
(xy 136.7048 130.7248)
|
||||
(xy 136.7048 128.660332)
|
||||
(xy 137.059413 128.660332)
|
||||
(xy 137.060107 128.66564)
|
||||
(xy 137.060107 128.665642)
|
||||
(xy 137.061636 128.677335)
|
||||
(xy 137.076468 128.790758)
|
||||
(xy 137.078626 128.795662)
|
||||
(xy 137.078626 128.795663)
|
||||
(xy 137.085758 128.811871)
|
||||
(xy 137.129443 128.911154)
|
||||
(xy 137.214081 129.011843)
|
||||
(xy 137.21854 129.014811)
|
||||
(xy 137.218541 129.014812)
|
||||
(xy 137.290203 129.062514)
|
||||
(xy 137.323576 129.084729)
|
||||
(xy 137.328688 129.086326)
|
||||
(xy 137.32869 129.086327)
|
||||
(xy 137.36913 129.098961)
|
||||
(xy 137.449128 129.123954)
|
||||
(xy 137.50373 129.124955)
|
||||
(xy 137.575279 129.126267)
|
||||
(xy 137.575281 129.126267)
|
||||
(xy 137.580641 129.126365)
|
||||
(xy 137.585812 129.124955)
|
||||
(xy 137.585814 129.124955)
|
||||
(xy 137.65404 129.106354)
|
||||
(xy 137.707546 129.091767)
|
||||
(xy 137.732892 129.076204)
|
||||
(xy 137.755189 129.062514)
|
||||
(xy 137.805587 129.052214)
|
||||
(xy 137.850815 129.07672)
|
||||
(xy 137.869709 129.124564)
|
||||
(xy 137.850901 129.176378)
|
||||
(xy 137.839051 129.189796)
|
||||
(xy 137.783149 129.308862)
|
||||
(xy 137.782325 129.314152)
|
||||
(xy 137.782325 129.314153)
|
||||
(xy 137.778563 129.338316)
|
||||
(xy 137.762913 129.438832)
|
||||
(xy 137.763607 129.44414)
|
||||
(xy 137.763607 129.444142)
|
||||
(xy 137.774841 129.530047)
|
||||
(xy 137.779968 129.569258)
|
||||
(xy 137.782126 129.574162)
|
||||
(xy 137.782126 129.574163)
|
||||
(xy 137.789258 129.590371)
|
||||
(xy 137.832943 129.689654)
|
||||
(xy 137.917581 129.790343)
|
||||
(xy 137.92204 129.793311)
|
||||
(xy 137.922041 129.793312)
|
||||
(xy 137.962947 129.820541)
|
||||
(xy 138.027076 129.863229)
|
||||
(xy 138.032188 129.864826)
|
||||
(xy 138.03219 129.864827)
|
||||
(xy 138.049603 129.870267)
|
||||
(xy 138.152628 129.902454)
|
||||
(xy 138.20723 129.903455)
|
||||
(xy 138.278779 129.904767)
|
||||
(xy 138.278781 129.904767)
|
||||
(xy 138.284141 129.904865)
|
||||
(xy 138.289312 129.903455)
|
||||
(xy 138.289314 129.903455)
|
||||
(xy 138.35754 129.884854)
|
||||
(xy 138.411046 129.870267)
|
||||
(xy 138.523138 129.801441)
|
||||
(xy 138.611409 129.703922)
|
||||
(xy 138.668761 129.585548)
|
||||
(xy 138.684331 129.493003)
|
||||
(xy 138.687674 129.473132)
|
||||
(xy 139.582914 129.473132)
|
||||
(xy 139.583608 129.47844)
|
||||
(xy 139.583608 129.478442)
|
||||
(xy 139.585137 129.490135)
|
||||
(xy 139.599969 129.603558)
|
||||
(xy 139.602127 129.608462)
|
||||
(xy 139.602127 129.608463)
|
||||
(xy 139.64413 129.703922)
|
||||
(xy 139.652944 129.723954)
|
||||
(xy 139.737582 129.824643)
|
||||
(xy 139.742041 129.827611)
|
||||
(xy 139.742042 129.827612)
|
||||
(xy 139.842615 129.894559)
|
||||
(xy 139.847077 129.897529)
|
||||
(xy 139.852189 129.899126)
|
||||
(xy 139.852191 129.899127)
|
||||
(xy 139.870558 129.904865)
|
||||
(xy 139.972629 129.936754)
|
||||
(xy 140.027231 129.937755)
|
||||
(xy 140.09878 129.939067)
|
||||
(xy 140.098782 129.939067)
|
||||
(xy 140.104142 129.939165)
|
||||
(xy 140.109313 129.937755)
|
||||
(xy 140.109315 129.937755)
|
||||
(xy 140.177541 129.919154)
|
||||
(xy 140.231047 129.904567)
|
||||
(xy 140.343139 129.835741)
|
||||
(xy 140.43141 129.738222)
|
||||
(xy 140.488762 129.619848)
|
||||
(xy 140.498168 129.563942)
|
||||
(xy 140.510103 129.493003)
|
||||
(xy 140.510104 129.492996)
|
||||
(xy 140.510585 129.490135)
|
||||
(xy 140.510723 129.4788)
|
||||
(xy 140.500346 129.406338)
|
||||
(xy 140.51091 129.355995)
|
||||
(xy 140.551362 129.32422)
|
||||
(xy 140.597214 129.3239)
|
||||
(xy 140.607629 129.327154)
|
||||
(xy 140.662231 129.328155)
|
||||
(xy 140.73378 129.329467)
|
||||
(xy 140.733782 129.329467)
|
||||
(xy 140.739142 129.329565)
|
||||
(xy 140.744313 129.328155)
|
||||
(xy 140.744315 129.328155)
|
||||
(xy 140.832855 129.304016)
|
||||
(xy 140.866047 129.294967)
|
||||
(xy 140.978139 129.226141)
|
||||
(xy 141.06641 129.128622)
|
||||
(xy 141.069446 129.122357)
|
||||
(xy 141.102639 129.053845)
|
||||
(xy 141.123762 129.010248)
|
||||
(xy 141.136223 128.936181)
|
||||
(xy 141.145103 128.883403)
|
||||
(xy 141.145104 128.883396)
|
||||
(xy 141.145585 128.880535)
|
||||
(xy 141.145723 128.8692)
|
||||
(xy 141.144912 128.863532)
|
||||
(xy 141.127835 128.74429)
|
||||
(xy 141.127834 128.744287)
|
||||
(xy 141.127076 128.738993)
|
||||
(xy 141.072633 128.619252)
|
||||
(xy 141.065076 128.610481)
|
||||
(xy 140.990267 128.523661)
|
||||
(xy 140.990266 128.523661)
|
||||
(xy 140.986772 128.519605)
|
||||
(xy 140.876394 128.448062)
|
||||
(xy 140.833494 128.435232)
|
||||
(xy 140.755507 128.411909)
|
||||
(xy 140.755504 128.411909)
|
||||
(xy 140.750373 128.410374)
|
||||
(xy 140.745018 128.410341)
|
||||
(xy 140.745016 128.410341)
|
||||
(xy 140.686019 128.409981)
|
||||
(xy 140.61884 128.40957)
|
||||
(xy 140.492368 128.445716)
|
||||
(xy 140.381124 128.515906)
|
||||
(xy 140.294052 128.614496)
|
||||
(xy 140.23815 128.733562)
|
||||
(xy 140.237326 128.738852)
|
||||
(xy 140.237326 128.738853)
|
||||
(xy 140.230593 128.7821)
|
||||
(xy 140.217914 128.863532)
|
||||
(xy 140.218608 128.868839)
|
||||
(xy 140.218608 128.868841)
|
||||
(xy 140.228334 128.943215)
|
||||
(xy 140.217157 128.993426)
|
||||
(xy 140.17632 129.024705)
|
||||
(xy 140.132222 129.025013)
|
||||
(xy 140.131193 129.024705)
|
||||
(xy 140.126702 129.023362)
|
||||
(xy 140.120507 129.021509)
|
||||
(xy 140.120504 129.021509)
|
||||
(xy 140.115373 129.019974)
|
||||
(xy 140.110018 129.019941)
|
||||
(xy 140.110016 129.019941)
|
||||
(xy 140.051019 129.019581)
|
||||
(xy 139.98384 129.01917)
|
||||
(xy 139.857368 129.055316)
|
||||
(xy 139.746124 129.125506)
|
||||
(xy 139.659052 129.224096)
|
||||
(xy 139.636962 129.271145)
|
||||
(xy 139.611416 129.325557)
|
||||
(xy 139.60315 129.343162)
|
||||
(xy 139.582914 129.473132)
|
||||
(xy 138.687674 129.473132)
|
||||
(xy 138.690102 129.458703)
|
||||
(xy 138.690103 129.458696)
|
||||
(xy 138.690584 129.455835)
|
||||
(xy 138.690722 129.4445)
|
||||
(xy 138.689911 129.438832)
|
||||
(xy 138.672834 129.31959)
|
||||
(xy 138.672833 129.319587)
|
||||
(xy 138.672075 129.314293)
|
||||
(xy 138.652457 129.271145)
|
||||
(xy 138.619851 129.199432)
|
||||
(xy 138.61985 129.199431)
|
||||
(xy 138.617632 129.194552)
|
||||
(xy 138.610075 129.185781)
|
||||
(xy 138.535266 129.098961)
|
||||
(xy 138.535265 129.098961)
|
||||
(xy 138.531771 129.094905)
|
||||
(xy 138.474312 129.057662)
|
||||
(xy 138.425886 129.026274)
|
||||
(xy 138.425885 129.026274)
|
||||
(xy 138.421393 129.023362)
|
||||
(xy 138.359874 129.004964)
|
||||
(xy 138.300506 128.987209)
|
||||
(xy 138.300503 128.987209)
|
||||
(xy 138.295372 128.985674)
|
||||
(xy 138.290017 128.985641)
|
||||
(xy 138.290015 128.985641)
|
||||
(xy 138.231018 128.985281)
|
||||
(xy 138.163839 128.98487)
|
||||
(xy 138.037367 129.021016)
|
||||
(xy 138.032841 129.023872)
|
||||
(xy 138.032836 129.023874)
|
||||
(xy 137.998055 129.045819)
|
||||
(xy 137.947787 129.056733)
|
||||
(xy 137.902263 129.032782)
|
||||
(xy 137.882786 128.985172)
|
||||
(xy 137.898468 128.936181)
|
||||
(xy 137.902162 128.931771)
|
||||
(xy 137.907909 128.925422)
|
||||
(xy 137.965261 128.807048)
|
||||
(xy 137.968896 128.785442)
|
||||
(xy 137.986602 128.680203)
|
||||
(xy 137.986603 128.680196)
|
||||
(xy 137.987084 128.677335)
|
||||
(xy 137.987222 128.666)
|
||||
(xy 137.986411 128.660332)
|
||||
(xy 137.969334 128.54109)
|
||||
(xy 137.969333 128.541087)
|
||||
(xy 137.968575 128.535793)
|
||||
(xy 137.93001 128.450974)
|
||||
(xy 137.916351 128.420932)
|
||||
(xy 137.91635 128.420931)
|
||||
(xy 137.914132 128.416052)
|
||||
(xy 137.906575 128.407281)
|
||||
(xy 137.831766 128.320461)
|
||||
(xy 137.831765 128.320461)
|
||||
(xy 137.828271 128.316405)
|
||||
(xy 137.717893 128.244862)
|
||||
(xy 137.674993 128.232032)
|
||||
(xy 137.597006 128.208709)
|
||||
(xy 137.597003 128.208709)
|
||||
(xy 137.591872 128.207174)
|
||||
(xy 137.586517 128.207141)
|
||||
(xy 137.586515 128.207141)
|
||||
(xy 137.527518 128.206781)
|
||||
(xy 137.460339 128.20637)
|
||||
(xy 137.333867 128.242516)
|
||||
(xy 137.222623 128.312706)
|
||||
(xy 137.135551 128.411296)
|
||||
(xy 137.133275 128.416144)
|
||||
(xy 137.087778 128.513049)
|
||||
(xy 137.079649 128.530362)
|
||||
(xy 137.078825 128.535652)
|
||||
(xy 137.078825 128.535653)
|
||||
(xy 137.072092 128.5789)
|
||||
(xy 137.059413 128.660332)
|
||||
(xy 136.7048 128.660332)
|
||||
(xy 136.7048 126.6752)
|
||||
(xy 136.722393 126.626862)
|
||||
(xy 136.766942 126.601142)
|
||||
(xy 136.78 126.6)
|
||||
(xy 141.4248 126.6)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
|
@ -0,0 +1,459 @@
|
|||
{
|
||||
"board": {
|
||||
"design_settings": {
|
||||
"defaults": {
|
||||
"board_outline_line_width": 0.09999999999999999,
|
||||
"copper_line_width": 0.09999999999999999,
|
||||
"copper_text_italic": false,
|
||||
"copper_text_size_h": 1.5,
|
||||
"copper_text_size_v": 1.5,
|
||||
"copper_text_thickness": 0.3,
|
||||
"copper_text_upright": false,
|
||||
"courtyard_line_width": 0.049999999999999996,
|
||||
"dimension_precision": 4,
|
||||
"dimension_units": 3,
|
||||
"dimensions": {
|
||||
"arrow_length": 1270000,
|
||||
"extension_offset": 500000,
|
||||
"keep_text_aligned": true,
|
||||
"suppress_zeroes": false,
|
||||
"text_position": 0,
|
||||
"units_format": 1
|
||||
},
|
||||
"fab_line_width": 0.09999999999999999,
|
||||
"fab_text_italic": false,
|
||||
"fab_text_size_h": 1.0,
|
||||
"fab_text_size_v": 1.0,
|
||||
"fab_text_thickness": 0.15,
|
||||
"fab_text_upright": false,
|
||||
"other_line_width": 0.09999999999999999,
|
||||
"other_text_italic": false,
|
||||
"other_text_size_h": 1.0,
|
||||
"other_text_size_v": 1.0,
|
||||
"other_text_thickness": 0.15,
|
||||
"other_text_upright": false,
|
||||
"pads": {
|
||||
"drill": 0.0,
|
||||
"height": 0.95,
|
||||
"width": 0.875
|
||||
},
|
||||
"silk_line_width": 0.15,
|
||||
"silk_text_italic": false,
|
||||
"silk_text_size_h": 0.7,
|
||||
"silk_text_size_v": 0.7,
|
||||
"silk_text_thickness": 0.15,
|
||||
"silk_text_upright": false,
|
||||
"zones": {
|
||||
"45_degree_only": false,
|
||||
"min_clearance": 0.15239999999999998
|
||||
}
|
||||
},
|
||||
"diff_pair_dimensions": [
|
||||
{
|
||||
"gap": 0.0,
|
||||
"via_gap": 0.0,
|
||||
"width": 0.0
|
||||
}
|
||||
],
|
||||
"drc_exclusions": [],
|
||||
"meta": {
|
||||
"filename": "board_design_settings.json",
|
||||
"version": 2
|
||||
},
|
||||
"rule_severities": {
|
||||
"annular_width": "error",
|
||||
"clearance": "error",
|
||||
"copper_edge_clearance": "error",
|
||||
"copper_sliver": "warning",
|
||||
"courtyards_overlap": "error",
|
||||
"diff_pair_gap_out_of_range": "error",
|
||||
"diff_pair_uncoupled_length_too_long": "error",
|
||||
"drill_out_of_range": "error",
|
||||
"duplicate_footprints": "warning",
|
||||
"extra_footprint": "warning",
|
||||
"hole_clearance": "error",
|
||||
"hole_near_hole": "error",
|
||||
"invalid_outline": "error",
|
||||
"item_on_disabled_layer": "error",
|
||||
"items_not_allowed": "error",
|
||||
"length_out_of_range": "error",
|
||||
"lib_footprint_issues": "error",
|
||||
"malformed_courtyard": "error",
|
||||
"microvia_drill_out_of_range": "error",
|
||||
"missing_courtyard": "ignore",
|
||||
"missing_footprint": "warning",
|
||||
"net_conflict": "warning",
|
||||
"npth_inside_courtyard": "ignore",
|
||||
"padstack": "error",
|
||||
"pth_inside_courtyard": "ignore",
|
||||
"shorting_items": "error",
|
||||
"silk_over_copper": "warning",
|
||||
"silk_overlap": "warning",
|
||||
"skew_out_of_range": "error",
|
||||
"solder_mask_bridge": "error",
|
||||
"starved_thermal": "error",
|
||||
"text_height": "warning",
|
||||
"text_thickness": "warning",
|
||||
"too_many_vias": "error",
|
||||
"track_dangling": "warning",
|
||||
"track_width": "error",
|
||||
"tracks_crossing": "error",
|
||||
"unconnected_items": "ignore",
|
||||
"unresolved_variable": "error",
|
||||
"via_dangling": "ignore",
|
||||
"zone_has_empty_net": "ignore",
|
||||
"zones_intersect": "error"
|
||||
},
|
||||
"rules": {
|
||||
"allow_blind_buried_vias": false,
|
||||
"allow_microvias": false,
|
||||
"max_error": 0.005,
|
||||
"min_clearance": 0.0,
|
||||
"min_copper_edge_clearance": 0.0,
|
||||
"min_hole_clearance": 0.0,
|
||||
"min_hole_to_hole": 0.25,
|
||||
"min_microvia_diameter": 0.19999999999999998,
|
||||
"min_microvia_drill": 0.09999999999999999,
|
||||
"min_resolved_spokes": 2,
|
||||
"min_silk_clearance": 0.0,
|
||||
"min_text_height": 0.7999999999999999,
|
||||
"min_text_thickness": 0.12,
|
||||
"min_through_hole_diameter": 0.3,
|
||||
"min_track_width": 0.19999999999999998,
|
||||
"min_via_annular_width": 0.049999999999999996,
|
||||
"min_via_diameter": 0.39999999999999997,
|
||||
"use_height_for_length_calcs": true
|
||||
},
|
||||
"track_widths": [
|
||||
0.0,
|
||||
0.1524,
|
||||
0.2032,
|
||||
0.254,
|
||||
0.3048,
|
||||
0.4064,
|
||||
0.508,
|
||||
0.6096,
|
||||
0.762,
|
||||
1.016,
|
||||
6.000001
|
||||
],
|
||||
"via_dimensions": [
|
||||
{
|
||||
"diameter": 0.0,
|
||||
"drill": 0.0
|
||||
},
|
||||
{
|
||||
"diameter": 0.6096,
|
||||
"drill": 0.3048
|
||||
}
|
||||
],
|
||||
"zones_allow_external_fillets": false,
|
||||
"zones_use_no_outline": true
|
||||
},
|
||||
"layer_presets": []
|
||||
},
|
||||
"boards": [],
|
||||
"cvpcb": {
|
||||
"equivalence_files": []
|
||||
},
|
||||
"erc": {
|
||||
"erc_exclusions": [],
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"pin_map": [
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
]
|
||||
],
|
||||
"rule_severities": {
|
||||
"bus_definition_conflict": "error",
|
||||
"bus_entry_needed": "error",
|
||||
"bus_label_syntax": "error",
|
||||
"bus_to_bus_conflict": "error",
|
||||
"bus_to_net_conflict": "error",
|
||||
"different_unit_footprint": "error",
|
||||
"different_unit_net": "error",
|
||||
"duplicate_reference": "error",
|
||||
"duplicate_sheet_names": "error",
|
||||
"extra_units": "error",
|
||||
"global_label_dangling": "warning",
|
||||
"hier_label_mismatch": "error",
|
||||
"label_dangling": "error",
|
||||
"lib_symbol_issues": "warning",
|
||||
"multiple_net_names": "warning",
|
||||
"net_not_bus_member": "warning",
|
||||
"no_connect_connected": "error",
|
||||
"no_connect_dangling": "error",
|
||||
"pin_not_connected": "error",
|
||||
"pin_not_driven": "error",
|
||||
"pin_to_pin": "error",
|
||||
"power_pin_not_driven": "error",
|
||||
"similar_labels": "warning",
|
||||
"unannotated": "error",
|
||||
"unit_value_mismatch": "error",
|
||||
"unresolved_variable": "error",
|
||||
"wire_dangling": "error"
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"pinned_footprint_libs": [],
|
||||
"pinned_symbol_libs": []
|
||||
},
|
||||
"meta": {
|
||||
"filename": "issue2512.kicad_pro",
|
||||
"version": 1
|
||||
},
|
||||
"net_settings": {
|
||||
"classes": [
|
||||
{
|
||||
"bus_width": 12.0,
|
||||
"clearance": 0.1524,
|
||||
"diff_pair_gap": 0.25,
|
||||
"diff_pair_via_gap": 0.25,
|
||||
"diff_pair_width": 0.2,
|
||||
"line_style": 0,
|
||||
"microvia_diameter": 0.3,
|
||||
"microvia_drill": 0.1,
|
||||
"name": "Default",
|
||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||
"track_width": 0.25,
|
||||
"via_diameter": 0.6,
|
||||
"via_drill": 0.4,
|
||||
"wire_width": 6.0
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"version": 1
|
||||
},
|
||||
"net_colors": null
|
||||
},
|
||||
"pcbnew": {
|
||||
"last_paths": {
|
||||
"gencad": "",
|
||||
"idf": "",
|
||||
"netlist": "",
|
||||
"specctra_dsn": "",
|
||||
"step": "",
|
||||
"vmrl": "",
|
||||
"vrml": ""
|
||||
},
|
||||
"page_layout_descr_file": ""
|
||||
},
|
||||
"schematic": {
|
||||
"annotate_start_num": 0,
|
||||
"drawing": {
|
||||
"dashed_lines_dash_length_ratio": 5.0,
|
||||
"dashed_lines_gap_length_ratio": 3.0,
|
||||
"default_bus_thickness": 12.0,
|
||||
"default_junction_size": 36.0,
|
||||
"default_line_thickness": 6.0,
|
||||
"default_text_size": 50.0,
|
||||
"default_wire_thickness": 6.0,
|
||||
"field_names": [],
|
||||
"intersheets_ref_own_page": false,
|
||||
"intersheets_ref_prefix": "",
|
||||
"intersheets_ref_short": false,
|
||||
"intersheets_ref_show": false,
|
||||
"intersheets_ref_suffix": "",
|
||||
"junction_size_choice": 3,
|
||||
"label_size_ratio": 0.3,
|
||||
"pin_symbol_size": 25.0,
|
||||
"text_offset_ratio": 0.3
|
||||
},
|
||||
"legacy_lib_dir": "",
|
||||
"legacy_lib_list": [],
|
||||
"meta": {
|
||||
"version": 1
|
||||
},
|
||||
"net_format_name": "",
|
||||
"ngspice": {
|
||||
"fix_include_paths": true,
|
||||
"fix_passive_vals": false,
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"model_mode": 0,
|
||||
"workbook_filename": ""
|
||||
},
|
||||
"page_layout_descr_file": "",
|
||||
"plot_directory": "",
|
||||
"spice_adjust_passive_values": false,
|
||||
"spice_external_command": "spice \"%I\"",
|
||||
"subpart_first_id": 65,
|
||||
"subpart_id_separator": 0
|
||||
},
|
||||
"sheets": [
|
||||
[
|
||||
"7ab16063-d1b0-49de-9b3e-10ea1f7e76a7",
|
||||
""
|
||||
]
|
||||
],
|
||||
"text_variables": {}
|
||||
}
|
|
@ -316,7 +316,7 @@
|
|||
"pinned_symbol_libs": []
|
||||
},
|
||||
"meta": {
|
||||
"filename": "hole_pad_clearance.kicad_pro",
|
||||
"filename": "issue5978.kicad_pro",
|
||||
"version": 1
|
||||
},
|
||||
"net_settings": {
|
||||
|
@ -376,7 +376,7 @@
|
|||
}
|
||||
],
|
||||
"meta": {
|
||||
"version": 0
|
||||
"version": 1
|
||||
},
|
||||
"net_colors": null
|
||||
},
|
||||
|
|
|
@ -57,16 +57,17 @@
|
|||
],
|
||||
"drc_exclusions": [],
|
||||
"meta": {
|
||||
"version": 1
|
||||
"version": 2
|
||||
},
|
||||
"rule_severities": {
|
||||
"annular_width": "error",
|
||||
"clearance": "error",
|
||||
"copper_edge_clearance": "error",
|
||||
"copper_sliver": "warning",
|
||||
"courtyards_overlap": "error",
|
||||
"diff_pair_gap_out_of_range": "error",
|
||||
"diff_pair_uncoupled_length_too_long": "error",
|
||||
"drill_too_small": "error",
|
||||
"drill_out_of_range": "error",
|
||||
"duplicate_footprints": "warning",
|
||||
"extra_footprint": "warning",
|
||||
"hole_clearance": "error",
|
||||
|
@ -74,11 +75,10 @@
|
|||
"invalid_outline": "error",
|
||||
"item_on_disabled_layer": "error",
|
||||
"items_not_allowed": "error",
|
||||
"keepout": "error",
|
||||
"length_out_of_range": "error",
|
||||
"lib_footprint_issues": "ignore",
|
||||
"malformed_courtyard": "error",
|
||||
"microvia_drill_too_small": "error",
|
||||
"microvia_drill_out_of_range": "error",
|
||||
"missing_courtyard": "ignore",
|
||||
"missing_footprint": "warning",
|
||||
"net_conflict": "warning",
|
||||
|
@ -90,6 +90,9 @@
|
|||
"silk_overlap": "error",
|
||||
"skew_out_of_range": "error",
|
||||
"solder_mask_bridge": "ignore",
|
||||
"starved_thermal": "error",
|
||||
"text_height": "warning",
|
||||
"text_thickness": "warning",
|
||||
"too_many_vias": "error",
|
||||
"track_dangling": "warning",
|
||||
"track_width": "error",
|
||||
|
@ -97,7 +100,6 @@
|
|||
"unconnected_items": "error",
|
||||
"unresolved_variable": "error",
|
||||
"via_dangling": "warning",
|
||||
"via_hole_larger_than_pad": "error",
|
||||
"zone_has_empty_net": "error",
|
||||
"zones_intersect": "error"
|
||||
},
|
||||
|
@ -107,19 +109,20 @@
|
|||
"max_error": 0.005,
|
||||
"min_clearance": 0.2032,
|
||||
"min_copper_edge_clearance": 0.3,
|
||||
"min_hole_clearance": 0.0,
|
||||
"min_hole_to_hole": 0.25,
|
||||
"min_microvia_diameter": 0.39877999999999997,
|
||||
"min_microvia_drill": 0.29972,
|
||||
"min_resolved_spokes": 2,
|
||||
"min_silk_clearance": 0.0,
|
||||
"min_text_height": 0.7999999999999999,
|
||||
"min_text_thickness": 0.12,
|
||||
"min_through_hole_diameter": 0.3,
|
||||
"min_track_width": 0.2032,
|
||||
"min_via_annular_width": 0.049999999999999996,
|
||||
"min_via_annulus": 0.15,
|
||||
"min_via_diameter": 0.6,
|
||||
"solder_mask_clearance": 0.15239999999999998,
|
||||
"solder_mask_min_width": 0.15239999999999998,
|
||||
"solder_paste_clearance": 0.0,
|
||||
"solder_paste_margin_ratio": -0.0
|
||||
"use_height_for_length_calcs": true
|
||||
},
|
||||
"track_widths": [
|
||||
0.0,
|
||||
|
@ -411,7 +414,7 @@
|
|||
],
|
||||
"hidden_nets": [],
|
||||
"meta": {
|
||||
"version": 0
|
||||
"version": 1
|
||||
},
|
||||
"net_colors": null
|
||||
},
|
||||
|
|
|
@ -104,6 +104,7 @@ BOOST_FIXTURE_TEST_CASE( DRCFalseNegativeRegressions, DRC_REGRESSION_TEST_FIXTUR
|
|||
// These documents at one time failed to catch DRC errors that they should have.
|
||||
|
||||
std::vector< std::pair<wxString, int> > tests = { { "issue1358", 2 },
|
||||
{ "issue2512", 4 },
|
||||
{ "issue2528", 1 },
|
||||
{ "issue5750", 4 },
|
||||
{ "issue5854", 3 },
|
||||
|
|
Loading…
Reference in New Issue