From ba9e9a2368aa3097e138d645fd3862736872368e Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Sun, 24 Aug 2025 14:24:51 -0700 Subject: [PATCH] Be more explicit in the board outline errors Show the two items that are closest to the gap and put the marker directly in the gap center. Then report the space between them to allow the designer more information about what to look for --- pcbnew/drc/drc_test_provider_misc.cpp | 100 +++++++++++++++++++++++++- 1 file changed, 98 insertions(+), 2 deletions(-) diff --git a/pcbnew/drc/drc_test_provider_misc.cpp b/pcbnew/drc/drc_test_provider_misc.cpp index 9d90d1c7cd..81e76cb70a 100644 --- a/pcbnew/drc/drc_test_provider_misc.cpp +++ b/pcbnew/drc/drc_test_provider_misc.cpp @@ -27,12 +27,16 @@ #include #include #include +#include +#include #include #include #include #include +#include + /* Miscellaneous tests: @@ -44,6 +48,64 @@ - DRCE_GENERIC_ERROR ///< user-defined errors */ +static void findClosestOutlineGap( BOARD* aBoard, PCB_SHAPE*& aItemA, PCB_SHAPE*& aItemB, + VECTOR2I& aMidpoint, int& aDistance ) +{ + PCB_TYPE_COLLECTOR items; + items.Collect( aBoard, { PCB_SHAPE_T } ); + + std::vector shapes; + + for( int ii = 0; ii < items.GetCount(); ++ii ) + { + PCB_SHAPE* shape = static_cast( items[ii] ); + + if( shape->GetLayer() == Edge_Cuts ) + shapes.push_back( shape ); + } + + int best = std::numeric_limits::max(); + VECTOR2I bestA; + VECTOR2I bestB; + + for( size_t ii = 0; ii < shapes.size(); ++ii ) + { + std::shared_ptr shapeA = shapes[ii]->GetEffectiveShape(); + + for( size_t jj = ii + 1; jj < shapes.size(); ++jj ) + { + std::shared_ptr shapeB = shapes[jj]->GetEffectiveShape(); + VECTOR2I ptA; + VECTOR2I ptB; + + if( shapeA && shapeB && shapeA->NearestPoints( shapeB.get(), ptA, ptB ) ) + { + int dist = ( ptA - ptB ).EuclideanNorm(); + + if( dist < best ) + { + best = dist; + bestA = ptA; + bestB = ptB; + aItemA = shapes[ii]; + aItemB = shapes[jj]; + } + } + } + } + + if( aItemA && aItemB ) + { + aDistance = best; + aMidpoint = ( bestA + bestB ) / 2; + } + else + { + aDistance = 0; + aMidpoint = VECTOR2I(); + } +} + class DRC_TEST_PROVIDER_MISC : public DRC_TEST_PROVIDER { public: @@ -85,12 +147,46 @@ void DRC_TEST_PROVIDER_MISC::testOutline() if( !itemA ) // If we only have a single item, make sure it's A std::swap( itemA, itemB ); + VECTOR2I markerPos = pt; + int gap = 0; + + if( itemA && itemB ) + { + std::shared_ptr shapeA = itemA->GetEffectiveShape(); + std::shared_ptr shapeB = itemB->GetEffectiveShape(); + VECTOR2I ptA; + VECTOR2I ptB; + + if( shapeA && shapeB && shapeA->NearestPoints( shapeB.get(), ptA, ptB ) ) + { + gap = ( ptA - ptB ).EuclideanNorm(); + markerPos = ( ptA + ptB ) / 2; + } + } + else + { + PCB_SHAPE* shapeA = nullptr; + PCB_SHAPE* shapeB = nullptr; + + findClosestOutlineGap( m_board, shapeA, shapeB, markerPos, gap ); + + itemA = shapeA; + itemB = shapeB; + } + std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_INVALID_OUTLINE ); - drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg ); + wxString msg2; + + if( itemA && itemB ) + msg2.Printf( _( "%s (gap %s)" ), msg, MessageTextFromValue( gap ) ); + else + msg2 = msg; + + drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg2 ); drcItem->SetItems( itemA, itemB ); - reportViolation( drcItem, pt, Edge_Cuts ); + reportViolation( drcItem, markerPos, Edge_Cuts ); }; // Test for very small graphic items (a few nm size) that can create issues