From 17800b926fe2e82a1bde680c957bd8e56f3d84d8 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Wed, 23 Dec 2020 17:33:39 +0000 Subject: [PATCH] Honour couryard_clearance rules when checking for courtyard overlaps. --- .../drc_test_provider_courtyard_clearance.cpp | 92 ++++++++++++------- pcbnew/footprint.cpp | 8 +- 2 files changed, 64 insertions(+), 36 deletions(-) diff --git a/pcbnew/drc/drc_test_provider_courtyard_clearance.cpp b/pcbnew/drc/drc_test_provider_courtyard_clearance.cpp index 1dd34168c1..9cefa17d90 100644 --- a/pcbnew/drc/drc_test_provider_courtyard_clearance.cpp +++ b/pcbnew/drc/drc_test_provider_courtyard_clearance.cpp @@ -68,7 +68,7 @@ public: private: void testFootprintCourtyardDefinitions(); - void testOverlappingComponentCourtyards(); + void testCourtyardClearances(); }; @@ -123,7 +123,7 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testFootprintCourtyardDefinitions() } -void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testOverlappingComponentCourtyards() +void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testCourtyardClearances() { const int delta = 100; // This is the number of tests between 2 calls to the progress bar @@ -147,52 +147,74 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testOverlappingComponentCourtyards() if( footprintFront.OutlineCount() == 0 && footprintBack.OutlineCount() == 0 ) continue; // No courtyards defined + BOX2I frontBBox = footprintFront.BBoxFromCaches(); + BOX2I backBBox = footprintBack.BBoxFromCaches(); + + frontBBox.Inflate( m_largestClearance ); + backBBox.Inflate( m_largestClearance ); + for( auto it2 = it1 + 1; it2 != m_board->Footprints().end(); it2++ ) { FOOTPRINT* test = *it2; SHAPE_POLY_SET& testFront = test->GetPolyCourtyardFront(); SHAPE_POLY_SET& testBack = test->GetPolyCourtyardBack(); - SHAPE_POLY_SET intersection; - bool overlap = false; - wxPoint pos; + DRC_CONSTRAINT constraint; + int clearance; + int actual; + VECTOR2I pos; if( footprintFront.OutlineCount() > 0 && testFront.OutlineCount() > 0 - && footprintFront.BBoxFromCaches().Intersects( testFront.BBoxFromCaches() ) ) + && frontBBox.Intersects( testFront.BBoxFromCaches() ) ) { - intersection.RemoveAllContours(); - intersection.Append( footprintFront ); + constraint = m_drcEngine->EvalRulesForItems( COURTYARD_CLEARANCE_CONSTRAINT, + footprint, test, F_Cu ); + clearance = constraint.GetValue().Min(); - // Build the common area between footprint and the test: - intersection.BooleanIntersection( testFront, SHAPE_POLY_SET::PM_FAST ); - - // If the intersection exists then they overlap - if( intersection.OutlineCount() > 0 ) + if( footprintFront.Collide( &testFront, clearance, &actual, &pos ) ) { - overlap = true; - pos = (wxPoint) intersection.CVertex( 0, 0, -1 ); + std::shared_ptr drce = DRC_ITEM::Create( DRCE_OVERLAPPING_FOOTPRINTS ); + + if( clearance > 0 ) + { + m_msg.Printf( _( "(%s clearance %s; actual %s)" ), + constraint.GetName(), + MessageTextFromValue( userUnits(), clearance ), + MessageTextFromValue( userUnits(), actual ) ); + + drce->SetErrorMessage( drce->GetErrorText() + wxS( " " ) + m_msg ); + drce->SetViolatingRule( constraint.GetParentRule() ); + } + + drce->SetItems( footprint, test ); + reportViolation( drce, (wxPoint) pos ); } } if( footprintBack.OutlineCount() > 0 && testBack.OutlineCount() > 0 - && footprintBack.BBoxFromCaches().Intersects( testBack.BBoxFromCaches() ) ) + && backBBox.Intersects( testBack.BBoxFromCaches() ) ) { - intersection.RemoveAllContours(); - intersection.Append( footprintBack ); + constraint = m_drcEngine->EvalRulesForItems( COURTYARD_CLEARANCE_CONSTRAINT, + footprint, test, B_Cu ); + clearance = constraint.GetValue().Min(); - intersection.BooleanIntersection( testBack, SHAPE_POLY_SET::PM_FAST ); - - if( intersection.OutlineCount() > 0 ) + if( footprintBack.Collide( &testBack, clearance, &actual, &pos ) ) { - overlap = true; - pos = (wxPoint) intersection.CVertex( 0, 0, -1 ); - } - } + std::shared_ptr drce = DRC_ITEM::Create( DRCE_OVERLAPPING_FOOTPRINTS ); - if( overlap ) - { - std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_OVERLAPPING_FOOTPRINTS ); - drcItem->SetItems( footprint, test ); - reportViolation( drcItem, pos ); + if( clearance > 0 ) + { + m_msg.Printf( _( "(%s clearance %s; actual %s)" ), + constraint.GetName(), + MessageTextFromValue( userUnits(), clearance ), + MessageTextFromValue( userUnits(), actual ) ); + + drce->SetErrorMessage( drce->GetErrorText() + wxS( " " ) + m_msg ); + drce->SetViolatingRule( constraint.GetParentRule() ); + } + + drce->SetItems( footprint, test ); + reportViolation( drce, (wxPoint) pos ); + } } } } @@ -202,14 +224,16 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testOverlappingComponentCourtyards() bool DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::Run() { m_board = m_drcEngine->GetBoard(); + DRC_CONSTRAINT constraint; - // fixme: don't use polygon intersection but distance for clearance tests - //m_largestClearance = 0; - //ReportAux( "Worst courtyard clearance : %d nm", m_largestClearance ); + if( m_drcEngine->QueryWorstConstraint( COURTYARD_CLEARANCE_CONSTRAINT, constraint ) ) + m_largestClearance = constraint.GetValue().Min(); + + reportAux( "Worst courtyard clearance : %d nm", m_largestClearance ); testFootprintCourtyardDefinitions(); - testOverlappingComponentCourtyards(); + testCourtyardClearances(); return true; } diff --git a/pcbnew/footprint.cpp b/pcbnew/footprint.cpp index edc5ce4bb0..b23e1026d4 100644 --- a/pcbnew/footprint.cpp +++ b/pcbnew/footprint.cpp @@ -1803,10 +1803,14 @@ void FOOTPRINT::BuildPolyCourtyards( OUTLINE_ERROR_HANDLER* aErrorHandler ) constexpr int errorMax = Millimeter2iu( 0.02 ); /* error max for polygonization */ - if( !ConvertOutlineToPolygon( list_front, m_poly_courtyard_front, errorMax, aErrorHandler ) ) + if( ConvertOutlineToPolygon( list_front, m_poly_courtyard_front, errorMax, aErrorHandler ) ) + m_poly_courtyard_front.CacheTriangulation( false ); + else SetFlags( MALFORMED_F_COURTYARD ); - if( !ConvertOutlineToPolygon( list_back, m_poly_courtyard_back, errorMax, aErrorHandler ) ) + if( ConvertOutlineToPolygon( list_back, m_poly_courtyard_back, errorMax, aErrorHandler ) ) + m_poly_courtyard_back.CacheTriangulation( false ); + else SetFlags( MALFORMED_B_COURTYARD ); }