From 35e45c59178561396a201df910a39594caba7628 Mon Sep 17 00:00:00 2001 From: Tomasz Wlostowski Date: Tue, 4 Aug 2020 00:12:11 +0200 Subject: [PATCH] drc_proto: edge clearance wip --- qa/drc_proto/CMakeLists.txt | 1 + qa/drc_proto/drc_engine.cpp | 1 + qa/drc_proto/drc_proto_test.cpp | 3 +- .../drc_test_provider_edge_clearance.cpp | 726 +----------------- .../test_cases/basic_hole_clearance/drc-rules | 2 +- 5 files changed, 39 insertions(+), 694 deletions(-) diff --git a/qa/drc_proto/CMakeLists.txt b/qa/drc_proto/CMakeLists.txt index 212116c6fa..64f6a27713 100644 --- a/qa/drc_proto/CMakeLists.txt +++ b/qa/drc_proto/CMakeLists.txt @@ -42,6 +42,7 @@ add_executable( drc_proto drc_test_provider_clearance_base.cpp drc_test_provider_copper_clearance.cpp drc_test_provider_hole_clearance.cpp + drc_test_provider_edge_clearance.cpp drc_test_provider_hole_size.cpp drc_engine.cpp drc_item.cpp diff --git a/qa/drc_proto/drc_engine.cpp b/qa/drc_proto/drc_engine.cpp index f1c61bc28c..00562e02cc 100644 --- a/qa/drc_proto/drc_engine.cpp +++ b/qa/drc_proto/drc_engine.cpp @@ -154,6 +154,7 @@ bool test::DRC_ENGINE::CompileRules() for( auto rule : m_rules ) { + drc_dbg(10, "Scan provider %s rule %s", (const char*) rule->GetTestProviderName().c_str(), (const char *)provider->GetName().c_str( ) ); if( rule->GetTestProviderName() == provider->GetName() ) { ReportAux( wxString::Format( " |- Rule: '%s' ", rule->m_Name.c_str() ) ); diff --git a/qa/drc_proto/drc_proto_test.cpp b/qa/drc_proto/drc_proto_test.cpp index 3a817d081c..ade7ef0676 100644 --- a/qa/drc_proto/drc_proto_test.cpp +++ b/qa/drc_proto/drc_proto_test.cpp @@ -47,13 +47,14 @@ int main( int argc, char *argv[] ) drcEngine.SetLogReporter( &msgReporter ); - try + try { drcEngine.LoadRules( wxString( argv[2] ) ); } catch( PARSE_ERROR& err ) { printf("Can't load DRC rules: %s\n", (const char*) err.What().c_str() ); + return -1; } drcEngine.RunTests(); diff --git a/qa/drc_proto/drc_test_provider_edge_clearance.cpp b/qa/drc_proto/drc_test_provider_edge_clearance.cpp index 1da512104b..6e1bcc3405 100644 --- a/qa/drc_proto/drc_test_provider_edge_clearance.cpp +++ b/qa/drc_proto/drc_test_provider_edge_clearance.cpp @@ -65,7 +65,7 @@ public: virtual const wxString GetName() const override { - return "clearance"; + return "edge_clearance"; }; virtual const wxString GetDescription() const override @@ -76,33 +76,23 @@ public: virtual std::set GetMatchingRuleIds() const override; private: - void testPadClearances(); - void testTrackClearances(); - void testCopperTextAndGraphics(); - void testZones(); - void testCopperDrawItem( BOARD_ITEM* aItem ); - void doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, - TRACKS::iterator aEndIt, bool aTestZones ); - bool doPadToPadsDrc( D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, int x_limit ); }; }; -bool test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::Run() +bool test::DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run() { auto bds = m_drcEngine->GetDesignSettings(); m_board = m_drcEngine->GetBoard(); m_largestClearance = 0; - for( auto rule : m_drcEngine->QueryRulesById( test::DRC_RULE_ID_T::DRC_RULE_ID_CLEARANCE ) ) + for( auto rule : m_drcEngine->QueryRulesById( test::DRC_RULE_ID_T::DRC_RULE_ID_EDGE_CLEARANCE ) ) { - drc_dbg(1, "process rule %p\n", rule ); if( rule->GetConstraint().m_Value.HasMin() ) { m_largestClearance = std::max( m_largestClearance, rule->GetConstraint().m_Value.Min() ); - drc_dbg(1, "min-copper-clearance %d\n", rule->GetConstraint().m_Value.Min() ); } } @@ -110,537 +100,59 @@ bool test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::Run() //m_largestClearance = - ReportStage( ("Testing pad copper clerances"), 0, 2 ); - testPadClearances(); - ReportStage( ("Testing track/via copper clerances"), 1, 2 ); - testTrackClearances(); - ReportStage( ("Testing copper drawing/text clerances"), 1, 2 ); - testCopperTextAndGraphics(); - ReportStage( ("Testing copper zone clearances"), 1, 2 ); - testZones(); + ReportStage( ("Testing all items <> Board Edge clearance"), 0, 2 ); + + std::vector boardOutline; + std::vector boardItems; - return true; -} - -void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testCopperTextAndGraphics() -{ - // Test copper items for clearance violations with vias, tracks and pads - - for( BOARD_ITEM* brdItem : m_board->Drawings() ) + for( auto item : m_board->Drawings() ) { - if( IsCopperLayer( brdItem->GetLayer() ) ) - testCopperDrawItem( brdItem ); - } - - for( MODULE* module : m_board->Modules() ) - { - TEXTE_MODULE& ref = module->Reference(); - TEXTE_MODULE& val = module->Value(); - - if( ref.IsVisible() && IsCopperLayer( ref.GetLayer() ) ) - testCopperDrawItem( &ref ); - - if( val.IsVisible() && IsCopperLayer( val.GetLayer() ) ) - testCopperDrawItem( &val ); - - if( module->IsNetTie() ) - continue; - - for( BOARD_ITEM* item : module->GraphicalItems() ) + if( auto dseg = dyn_cast( item ) ) { - if( IsCopperLayer( item->GetLayer() ) ) + drc_dbg(10,"L %d\n", dseg->GetLayer() ); + if( dseg->GetLayer() == Edge_Cuts ) { - if( item->Type() == PCB_MODULE_TEXT_T && ( (TEXTE_MODULE*) item )->IsVisible() ) - testCopperDrawItem( item ); - else if( item->Type() == PCB_MODULE_EDGE_T ) - testCopperDrawItem( item ); - } - } - } -} - - -void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testCopperDrawItem( BOARD_ITEM* aItem ) -{ - EDA_RECT bbox; - std::shared_ptr itemShape; - DRAWSEGMENT* drawItem = dynamic_cast( aItem ); - EDA_TEXT* textItem = dynamic_cast( aItem ); - - if( drawItem ) - { - bbox = drawItem->GetBoundingBox(); - itemShape = drawItem->GetEffectiveShape(); - } - else if( textItem ) - { - bbox = textItem->GetTextBox(); - itemShape = textItem->GetEffectiveShape(); - } - else - { - wxFAIL_MSG( "unknown item type in testCopperDrawItem()" ); - return; - } - - SHAPE_RECT bboxShape( bbox.GetX(), bbox.GetY(), bbox.GetWidth(), bbox.GetHeight() ); - - //if( itemShape->Empty() ) - // return; - - // Test tracks and vias - for( auto track : m_board->Tracks() ) - { - if( !track->IsOnLayer( aItem->GetLayer() ) ) - continue; - - auto rule = m_drcEngine->EvalRulesForItems( test::DRC_RULE_ID_T::DRC_RULE_ID_CLEARANCE, aItem, track ); - auto minClearance = rule->GetConstraint().GetValue().Min(); - int actual = INT_MAX; - wxPoint pos; - - SHAPE_SEGMENT trackSeg( track->GetStart(), track->GetEnd(), track->GetWidth() ); - - // Fast test to detect a track segment candidate inside the text bounding box - if( !bboxShape.Collide( &trackSeg, 0 ) ) - continue; - - if( !itemShape->Collide( &trackSeg, minClearance, &actual ) ) - continue; - - pos = (wxPoint) itemShape->Centre(); - - if( actual < INT_MAX ) - { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE ); - - wxString msg; - msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), - rule->GetName(), - MessageTextFromValue( userUnits(), minClearance, true ), - MessageTextFromValue( userUnits(), actual, true ) ); - - drcItem->SetErrorMessage( msg ); - drcItem->SetItems( track, aItem ); - drcItem->SetViolatingRule( rule ); - - ReportWithMarker( drcItem, pos ); - } - } - - // Test pads - for( auto pad : m_board->GetPads() ) - { - if( !pad->IsOnLayer( aItem->GetLayer() ) ) - continue; - - // Graphic items are allowed to act as net-ties within their own footprint - if( drawItem && pad->GetParent() == drawItem->GetParent() ) - continue; - - auto rule = m_drcEngine->EvalRulesForItems( test::DRC_RULE_ID_T::DRC_RULE_ID_CLEARANCE, aItem, pad ); - auto minClearance = rule->GetConstraint().GetValue().Min(); - - int actual = INT_MAX; - - int bb_radius = pad->GetBoundingRadius() + minClearance; - - // Fast test to detect a pad candidate inside the text bounding box - // Finer test (time consumming) is made only for pads near the text. - if( !bboxShape.Collide( SEG( pad->GetPosition(), pad->GetPosition() ), bb_radius ) ) - continue; - - if( !pad->GetEffectiveShape()->Collide( itemShape.get(), minClearance, &actual ) ) - continue; - - if( actual < INT_MAX ) - { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE ); - - - wxString msg; - - msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), - rule->GetName(), - MessageTextFromValue( userUnits(), minClearance, true ), - MessageTextFromValue( userUnits(), actual, true ) ); - - drcItem->SetErrorMessage( msg ); - drcItem->SetItems( pad, aItem ); - drcItem->SetViolatingRule( rule ); - - ReportWithMarker( drcItem, pad->GetPosition() ); - } - } -} - - -void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackClearances() -{ - const int delta = 500; // This is the number of tests between 2 calls to the - // progress bar - int count = m_board->Tracks().size(); - int deltamax = count/delta; - - ReportProgress(0.0); - ReportAux("Testing %d tracks...", count ); - - int ii = 0; - count = 0; - - for( auto seg_it = m_board->Tracks().begin(); seg_it != m_board->Tracks().end(); seg_it++ ) - { - if( ii++ > delta ) - { - ii = 0; - count++; - - ReportProgress( (double) ii / (double ) count ); - } - - // Test new segment against tracks and pads, optionally against copper zones - doTrackDrc( *seg_it, seg_it + 1, m_board->Tracks().end(), false /*fixme: control for copper zones*/ ); - } -} - -void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::doTrackDrc( TRACK* aRefSeg, TRACKS::iterator aStartIt, - TRACKS::iterator aEndIt, bool aTestZones ) -{ - BOARD_DESIGN_SETTINGS& bds = m_board->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 : */ - /******************************************/ - - // fixme: via annulus and other nin-coppper clearance tests moved elsewhere - - /******************************************/ - /* Phase 1 : test DRC track to pads : */ - /******************************************/ - - // Compute the min distance to pads - for( MODULE* mod : m_board->Modules() ) - { - // Don't preflight at the module level. Getting a module's bounding box goes - // through all its pads anyway (so it's no faster), and also all its drawings - // (so it's in fact slower). - - for( D_PAD* pad : mod->Pads() ) - { - // Preflight based on bounding boxes. - EDA_RECT inflatedBB = refSegBB; - inflatedBB.Inflate( pad->GetBoundingRadius() + m_largestClearance ); - - if( !inflatedBB.Contains( pad->GetPosition() ) ) - continue; - - if( !( pad->GetLayerSet() & refLayerSet ).any() ) - continue; - - // No need to check pads with the same net as the refSeg. - if( pad->GetNetCode() && aRefSeg->GetNetCode() == pad->GetNetCode() ) - continue; - - // fixme: hole to hole clearance moved elsewhere - - auto rule = m_drcEngine->EvalRulesForItems( test::DRC_RULE_ID_T::DRC_RULE_ID_CLEARANCE, aRefSeg, pad ); - auto minClearance = rule->GetConstraint().GetValue().Min(); - int clearanceAllowed = minClearance - bds.GetDRCEpsilon(); - int actual; - - auto padShape = pad->GetEffectiveShape(); - - if( padShape->Collide( &refSeg, minClearance - bds.GetDRCEpsilon(), &actual ) ) - { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE ); - wxString msg; - - msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), - /*m_clearanceSource fixme*/ "", - MessageTextFromValue( userUnits(), minClearance, true ), - MessageTextFromValue( userUnits(), actual, true ) ); - - drcItem->SetErrorMessage( msg ); - drcItem->SetItems( aRefSeg, pad ); - drcItem->SetViolatingRule( rule ); - - ReportWithMarker( drcItem, pad->GetPosition() ); - - if( isErrorLimitExceeded( DRCE_CLEARANCE ) ) - return; + drc_dbg(10, "dseg ec %p\n", dseg); + boardOutline.push_back( dseg ); } } } - /***********************************************/ - /* Phase 2: test DRC with other track segments */ - /***********************************************/ - - // Test the reference segment with other track segments - for( auto it = aStartIt; it != aEndIt; it++ ) + for ( auto trk : m_board->Tracks() ) { - TRACK* track = *it; - - // No problem if segments have the same net code: - if( aRefSeg->GetNetCode() == track->GetNetCode() ) - continue; - - // No problem if tracks are on different layers: - // 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; - - // Preflight based on worst-case inflated bounding boxes: - EDA_RECT trackBB = track->GetBoundingBox(); - trackBB.Inflate( m_largestClearance ); - - if( !trackBB.Intersects( refSegBB ) ) - continue; - - auto rule = m_drcEngine->EvalRulesForItems( test::DRC_RULE_ID_T::DRC_RULE_ID_CLEARANCE, aRefSeg, track ); - auto minClearance = rule->GetConstraint().GetValue().Min(); - - SHAPE_SEGMENT trackSeg( track->GetStart(), track->GetEnd(), track->GetWidth() ); - int actual; - - if( OPT_VECTOR2I intersection = refSeg.GetSeg().Intersect( trackSeg.GetSeg() ) ) - { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TRACKS_CROSSING ); - - // fixme - drcItem->SetErrorMessage( "FIXME" ); - drcItem->SetItems( aRefSeg, track ); - drcItem->SetViolatingRule( rule ); - - ReportWithMarker( drcItem, (wxPoint) intersection.get() ); - - if( isErrorLimitExceeded( DRCE_TRACKS_CROSSING ) ) - return; - } - else if( refSeg.Collide( &trackSeg, minClearance, &actual ) ) - { - wxPoint pos = getLocation( aRefSeg, trackSeg.GetSeg() ); - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE ); - - - wxString msg; - msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), - /*m_clearanceSource fixme*/"", - MessageTextFromValue( userUnits(), minClearance, true ), - MessageTextFromValue( userUnits(), actual, true ) ); - - drcItem->SetErrorMessage( msg ); - drcItem->SetItems( aRefSeg, track ); - drcItem->SetViolatingRule( rule ); - - ReportWithMarker( drcItem, pos ); - - if( isErrorLimitExceeded( DRCE_CLEARANCE ) ) - return; - } + boardItems.push_back( trk ); } - /***************************************/ - /* Phase 3: test DRC with copper zones */ - /***************************************/ - // Can be *very* time consumming. - if( aTestZones ) + for ( auto zone : m_board->Zones() ) { - SEG testSeg( aRefSeg->GetStart(), aRefSeg->GetEnd() ); - - for( ZONE_CONTAINER* zone : m_board->Zones() ) - { - if( !( refLayerSet & zone->GetLayerSet() ).any() || zone->GetIsKeepout() ) - continue; - - for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() ) - { - if( zone->GetFilledPolysList( layer ).IsEmpty() ) - continue; - - if( zone->GetNetCode() && zone->GetNetCode() == aRefSeg->GetNetCode() ) - continue; - - // fixme: per-layer onLayer() property - - auto rule = m_drcEngine->EvalRulesForItems( test::DRC_RULE_ID_T::DRC_RULE_ID_CLEARANCE, aRefSeg, zone ); - auto minClearance = rule->GetConstraint().GetValue().Min(); - int widths = refSegWidth / 2; - - // to avoid false positive, due to rounding issues and approxiamtions - // in distance and clearance calculations, use a small threshold for distance - // (1 micron) - #define THRESHOLD_DIST Millimeter2iu( 0.001 ) - - int allowedDist = minClearance + widths + THRESHOLD_DIST; - int actual = INT_MAX; - - if( zone->GetFilledPolysList( layer ).Collide( testSeg, allowedDist, &actual ) ) - { - actual = std::max( 0, actual - widths ); - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE ); - wxString msg; - - msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), - rule->GetName(), - MessageTextFromValue( userUnits(), minClearance, true ), - MessageTextFromValue( userUnits(), actual, true ) ); - - drcItem->SetErrorMessage( msg ); - drcItem->SetItems( aRefSeg, zone ); - drcItem->SetViolatingRule( rule ); - - ReportWithMarker( drcItem, getLocation( aRefSeg, zone ) ); - } - } - } + boardItems.push_back( zone ); } -// fixme: board edge clearance to another rule -} - - -void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadClearances( ) -{ - auto bds = m_drcEngine->GetDesignSettings(); - std::vector sortedPads; - - m_board->GetSortedPadListByXthenYCoord( sortedPads ); - - ReportAux("Testing %d pads...", sortedPads.size() ); - - for( auto p : sortedPads ) - - if( sortedPads.empty() ) - return; - - // find the max size of the pads (used to stop the pad-to-pad tests) - int max_size = 0; - - for( D_PAD* pad : sortedPads ) + for ( auto zone : m_board->Zones() ) { - // GetBoundingRadius() is the radius of the minimum sized circle fully containing the pad - int radius = pad->GetBoundingRadius(); - - if( radius > max_size ) - max_size = radius; + boardItems.push_back( zone ); } - // Better to be fast than accurate; this keeps us from having to look up / calculate the - // actual clearances - max_size += m_largestClearance; - - // Upper limit of pad list (limit not included) - D_PAD** listEnd = &sortedPads[0] + sortedPads.size(); - - int ii = 0; - // Test the pads - for( auto& pad : sortedPads ) + for ( auto mod : m_board->Modules() ) { - if( ii % 100 == 0 ) - ReportProgress( (double) ii / (double) sortedPads.size() ); - - ii++; - int x_limit = pad->GetPosition().x + pad->GetBoundingRadius() + max_size; - - doPadToPadsDrc( pad, &pad, listEnd, x_limit ); + for ( auto dwg : mod->GraphicalItems() ) + boardItems.push_back( dwg ); + for ( auto pad : mod->Pads() ) + boardItems.push_back( pad ); } -} -bool test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::doPadToPadsDrc( D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, - int x_limit ) -{ - const static LSET all_cu = LSET::AllCuMask(); + drc_dbg(2,"outline: %d items, board: %d items\n", boardOutline.size(), boardItems.size() ); - LSET layerMask = aRefPad->GetLayerSet() & all_cu; - - for( D_PAD** pad_list = aStart; pad_listGetEffectiveShape(); - if( pad == aRefPad ) - continue; - - // We can stop the test when pad->GetPosition().x > x_limit - // because the list is sorted by X values - if( pad->GetPosition().x > x_limit ) - break; - - // The pad must be in a net (i.e pt_pad->GetNet() != 0 ), - // But no problem if pads have the same netcode (same net) - if( pad->GetNetCode() && ( aRefPad->GetNetCode() == pad->GetNetCode() ) ) - continue; - - // if pads are from the same footprint - if( pad->GetParent() == aRefPad->GetParent() ) + for( auto boardItem : boardItems ) { - // and have the same pad number ( equivalent pads ) + auto shape = boardItem->GetEffectiveShape(); - // one can argue that this 2nd test is not necessary, that any - // two pads from a single module are acceptable. This 2nd test - // should eventually be a configuration option. - if( pad->PadNameEqual( aRefPad ) ) - continue; - } - - // if either pad has no drill and is only on technical layers, not a clearance violation - if( ( ( pad->GetLayerSet() & layerMask ) == 0 && !pad->GetDrillSize().x ) || - ( ( aRefPad->GetLayerSet() & layerMask ) == 0 && !aRefPad->GetDrillSize().x ) ) - { - continue; - } - - auto rule = m_drcEngine->EvalRulesForItems( test::DRC_RULE_ID_T::DRC_RULE_ID_CLEARANCE, aRefPad, pad ); - auto minClearance = rule->GetConstraint().GetValue().Min(); - - drc_dbg(4, "pad %p vs %p constraint %d\n", aRefPad, pad, minClearance ); - - int clearanceAllowed = minClearance - m_drcEngine->GetDesignSettings()->GetDRCEpsilon(); - int actual; - - auto refPadShape = aRefPad->GetEffectiveShape(); - - if( refPadShape->Collide( pad->GetEffectiveShape().get(), clearanceAllowed, &actual ) ) - { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE ); - wxString msg; - msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), - /*m_clearanceSource fixme*/ "", - MessageTextFromValue( userUnits(), minClearance, true ), - MessageTextFromValue( userUnits(), actual, true ) ); - - drcItem->SetErrorMessage( msg ); - drcItem->SetItems( aRefPad, pad ); - drcItem->SetViolatingRule( rule ); - - ReportWithMarker( drcItem, aRefPad->GetPosition() ); - return false; + (void) shape; + (void) refShape; } } @@ -648,183 +160,13 @@ bool test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::doPadToPadsDrc( D_PAD* aRefPad, D } -void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZones() +std::set test::DRC_TEST_PROVIDER_EDGE_CLEARANCE::GetMatchingRuleIds() const { - // Test copper areas for valid netcodes -> fixme, goes to connectivity checks - - std::vector smoothed_polys; - smoothed_polys.resize( m_board->GetAreaCount() ); - - for( int ii = 0; ii < m_board->GetAreaCount(); ii++ ) - { - ZONE_CONTAINER* zone = m_board->GetArea( ii ); - ZONE_CONTAINER* zoneRef = m_board->GetArea( ii ); - std::set colinearCorners; - - zoneRef->GetColinearCorners( m_board, colinearCorners ); - zoneRef->BuildSmoothedPoly( smoothed_polys[ii], &colinearCorners ); - } - - // iterate through all areas - for( int ia = 0; ia < m_board->GetAreaCount(); ia++ ) - { - ZONE_CONTAINER* zoneRef = m_board->GetArea( ia ); - - if( !zoneRef->IsOnCopperLayer() ) - continue; - - // If we are testing a single zone, then iterate through all other zones - // Otherwise, we have already tested the zone combination - for( int ia2 = ia + 1; ia2 < m_board->GetAreaCount(); ia2++ ) - { - ZONE_CONTAINER* zoneToTest = m_board->GetArea( ia2 ); - - if( zoneRef == zoneToTest ) - continue; - - // test for same layer - if( zoneRef->GetLayer() != zoneToTest->GetLayer() ) - continue; - - // Test for same net - if( zoneRef->GetNetCode() == zoneToTest->GetNetCode() && zoneRef->GetNetCode() >= 0 ) - continue; - - // test for different priorities - if( zoneRef->GetPriority() != zoneToTest->GetPriority() ) - continue; - - // test for different types - if( zoneRef->GetIsKeepout() != zoneToTest->GetIsKeepout() ) - continue; - - // Examine a candidate zone: compare zoneToTest to zoneRef - - // Get clearance used in zone to zone test. - auto rule = m_drcEngine->EvalRulesForItems( test::DRC_RULE_ID_T::DRC_RULE_ID_CLEARANCE, zoneRef, zoneToTest ); - auto zone2zoneClearance = rule->GetConstraint().GetValue().Min(); - - // Keepout areas have no clearance, so set zone2zoneClearance to 1 - // ( zone2zoneClearance = 0 can create problems in test functions) - if( zoneRef->GetIsKeepout() ) // fixme: really? - zone2zoneClearance = 1; - - // test for some corners of zoneRef inside zoneToTest - for( auto iterator = smoothed_polys[ia].IterateWithHoles(); iterator; iterator++ ) - { - VECTOR2I currentVertex = *iterator; - wxPoint pt( currentVertex.x, currentVertex.y ); - - if( smoothed_polys[ia2].Contains( currentVertex ) ) - { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_ZONES_INTERSECT ); - drcItem->SetItems( zoneRef, zoneToTest ); - drcItem->SetViolatingRule( rule ); - - ReportWithMarker( drcItem, pt ); - } - } - - // test for some corners of zoneToTest inside zoneRef - for( auto iterator = smoothed_polys[ia2].IterateWithHoles(); iterator; iterator++ ) - { - VECTOR2I currentVertex = *iterator; - wxPoint pt( currentVertex.x, currentVertex.y ); - - if( smoothed_polys[ia].Contains( currentVertex ) ) - { - DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_ZONES_INTERSECT ); - drcItem->SetItems( zoneToTest, zoneRef ); - drcItem->SetViolatingRule( rule ); - - ReportWithMarker( drcItem, pt ); - } - } - - // Iterate through all the segments of refSmoothedPoly - std::map conflictPoints; - - for( auto refIt = smoothed_polys[ia].IterateSegmentsWithHoles(); refIt; refIt++ ) - { - // Build ref segment - SEG refSegment = *refIt; - - // Iterate through all the segments in smoothed_polys[ia2] - for( auto testIt = smoothed_polys[ia2].IterateSegmentsWithHoles(); testIt; testIt++ ) - { - // Build test segment - SEG testSegment = *testIt; - wxPoint pt; - - int ax1, ay1, ax2, ay2; - ax1 = refSegment.A.x; - ay1 = refSegment.A.y; - ax2 = refSegment.B.x; - ay2 = refSegment.B.y; - - int bx1, by1, bx2, by2; - bx1 = testSegment.A.x; - by1 = testSegment.A.y; - bx2 = testSegment.B.x; - by2 = testSegment.B.y; - - int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2, - 0, - ax1, ay1, ax2, ay2, - 0, - zone2zoneClearance, - &pt.x, &pt.y ); - - if( d < zone2zoneClearance ) - { - if( conflictPoints.count( pt ) ) - conflictPoints[ pt ] = std::min( conflictPoints[ pt ], d ); - else - conflictPoints[ pt ] = d; - } - } - } - - for( const std::pair& conflict : conflictPoints ) - { - int actual = conflict.second; - DRC_ITEM* drcItem; - - if( actual <= 0 ) - { - drcItem = DRC_ITEM::Create( DRCE_ZONES_INTERSECT ); - } - else - { - drcItem = DRC_ITEM::Create( DRCE_CLEARANCE ); - wxString msg; - - msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), - /* fixme */"", - MessageTextFromValue( userUnits(), zone2zoneClearance, true ), - MessageTextFromValue( userUnits(), conflict.second, true ) ); - - drcItem->SetErrorMessage( msg ); - - } - - drcItem->SetViolatingRule( rule ); - drcItem->SetItems( zoneRef, zoneToTest ); - - ReportWithMarker( drcItem, conflict.first ); - } - } - } -} - - -std::set test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::GetMatchingRuleIds() const -{ - return { DRC_RULE_ID_T::DRC_RULE_ID_CLEARANCE }; + return { DRC_RULE_ID_T::DRC_RULE_ID_EDGE_CLEARANCE }; } namespace detail { - static test::DRC_REGISTER_TEST_PROVIDER dummy; + static test::DRC_REGISTER_TEST_PROVIDER dummy; } \ No newline at end of file diff --git a/qa/drc_proto/test_cases/basic_hole_clearance/drc-rules b/qa/drc_proto/test_cases/basic_hole_clearance/drc-rules index ce90874caa..883e7b655a 100644 --- a/qa/drc_proto/test_cases/basic_hole_clearance/drc-rules +++ b/qa/drc_proto/test_cases/basic_hole_clearance/drc-rules @@ -4,7 +4,7 @@ (condition (expression "A.type == 'Pad' && A.netname == 'Net2'") (rule "big_pad_hole_clearance") ) (rule "small_pad_hole_clearance" (type "hole_clearance") (priority 1) (severity error) (min "0.1mm") ) -(rule "big_pad_hole_clearance" (type "hole_clearance") (priority 1) (severity error) (min "5mm") ) +(rule "big_pad_hole_clearance" (type "hole_clearance") (priority 1) (severity error) (min "5mm" ) ) (rule "default" (type "hole_clearance") (priority 0) (severity error) (min "0.5mm") )