From 4b6f2f0658cf4685e3260426eed122730d3bf93a Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Thu, 19 Aug 2021 22:28:54 +0100 Subject: [PATCH] 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 --- include/eda_shape.h | 2 - pcbnew/drc/drc_engine.cpp | 4 +- .../drc_test_provider_copper_clearance.cpp | 34 +- ...drc_test_provider_mechanical_clearance.cpp | 348 +++++++++---- qa/data/issue2512.kicad_dru | 11 + qa/data/issue2512.kicad_pcb | 428 ++++++++++++++++ qa/data/issue2512.kicad_pro | 459 ++++++++++++++++++ qa/data/issue5978.kicad_pro | 4 +- qa/data/issue5990.kicad_pro | 23 +- qa/pcbnew/drc/test_drc_regressions.cpp | 1 + 10 files changed, 1190 insertions(+), 124 deletions(-) create mode 100644 qa/data/issue2512.kicad_dru create mode 100644 qa/data/issue2512.kicad_pcb create mode 100644 qa/data/issue2512.kicad_pro diff --git a/include/eda_shape.h b/include/eda_shape.h index 24b007fff6..bbd498022b 100644 --- a/include/eda_shape.h +++ b/include/eda_shape.h @@ -222,8 +222,6 @@ public: void SetPolyShape( const SHAPE_POLY_SET& aShape ) { m_poly = aShape; } - void SetBezierPoints( const std::vector& aPoints ) { m_bezierPoints = aPoints; } - /** * Rebuild the m_BezierPoints vertex list that approximate the Bezier curve * by a list of segments. diff --git a/pcbnew/drc/drc_engine.cpp b/pcbnew/drc/drc_engine.cpp index 2f95712ba0..e49693192d 100644 --- a/pcbnew/drc/drc_engine.cpp +++ b/pcbnew/drc/drc_engine.cpp @@ -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 ); } diff --git a/pcbnew/drc/drc_test_provider_copper_clearance.cpp b/pcbnew/drc/drc_test_provider_copper_clearance.cpp index 91e73e545d..7505e65e86 100644 --- a/pcbnew/drc/drc_test_provider_copper_clearance.cpp +++ b/pcbnew/drc/drc_test_provider_copper_clearance.cpp @@ -98,7 +98,7 @@ private: DRC_RTREE m_copperTree; int m_drcEpsilon; - std::vector m_zones; + std::vector 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( layer_id ); std::vector 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; diff --git a/pcbnew/drc/drc_test_provider_mechanical_clearance.cpp b/pcbnew/drc/drc_test_provider_mechanical_clearance.cpp index bafb03c8db..b3d17253af 100644 --- a/pcbnew/drc/drc_test_provider_mechanical_clearance.cpp +++ b/pcbnew/drc/drc_test_provider_mechanical_clearance.cpp @@ -22,15 +22,16 @@ */ #include +#include #include #include #include #include +#include #include - +#include #include #include - #include #include #include @@ -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( item ); + ZONE* zone = dynamic_cast( item ); + + if( shape ) { - if( IsCopperLayer( layer ) ) - count++; + 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( item ), layer ); + PCB_SHAPE* shape = dynamic_cast( item ); + ZONE* zone = dynamic_cast( 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( 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 ) { - int epsilon = m_board->GetDesignSettings().GetDRCEpsilon(); - SHAPE_POLY_SET fill = aZone->GetFilledPolysList( aLayer ); - DRC_CONSTRAINT constraint; - int clearance; + // 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(); - constraint = m_drcEngine->EvalRules( MECHANICAL_CLEARANCE_CONSTRAINT, aZone, nullptr, aLayer ); - clearance = constraint.GetValue().Min(); + // Trigonometry is not cheap; cache seg angles + std::vector 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 > 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 collision : collisions ) + { + std::shared_ptr 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 ); if( clearance - epsilon <= 0 ) return; @@ -313,13 +537,13 @@ void DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::testZoneLayer( ZONE* aZone, PCB_LAY std::shared_ptr 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 > 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 collision : collisions ) - { - std::shared_ptr 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 drce = DRC_ITEM::Create( DRCE_CLEARANCE ); diff --git a/qa/data/issue2512.kicad_dru b/qa/data/issue2512.kicad_dru new file mode 100644 index 0000000000..3e0b6188d2 --- /dev/null +++ b/qa/data/issue2512.kicad_dru @@ -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))) diff --git a/qa/data/issue2512.kicad_pcb b/qa/data/issue2512.kicad_pcb new file mode 100644 index 0000000000..046bdcab03 --- /dev/null +++ b/qa/data/issue2512.kicad_pcb @@ -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) + ) + ) + ) +) diff --git a/qa/data/issue2512.kicad_pro b/qa/data/issue2512.kicad_pro new file mode 100644 index 0000000000..9af023de64 --- /dev/null +++ b/qa/data/issue2512.kicad_pro @@ -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": {} +} diff --git a/qa/data/issue5978.kicad_pro b/qa/data/issue5978.kicad_pro index 7ca859b753..9c4121a2fc 100644 --- a/qa/data/issue5978.kicad_pro +++ b/qa/data/issue5978.kicad_pro @@ -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 }, diff --git a/qa/data/issue5990.kicad_pro b/qa/data/issue5990.kicad_pro index 3619c3af06..9550db745d 100755 --- a/qa/data/issue5990.kicad_pro +++ b/qa/data/issue5990.kicad_pro @@ -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 }, diff --git a/qa/pcbnew/drc/test_drc_regressions.cpp b/qa/pcbnew/drc/test_drc_regressions.cpp index 7e6fca05b7..d876cd32cf 100644 --- a/qa/pcbnew/drc/test_drc_regressions.cpp +++ b/qa/pcbnew/drc/test_drc_regressions.cpp @@ -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 > tests = { { "issue1358", 2 }, + { "issue2512", 4 }, { "issue2528", 1 }, { "issue5750", 4 }, { "issue5854", 3 },