From e89f9db438c91436737fccf42a15fbd9f4827e50 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sat, 20 Feb 2021 13:25:16 +0000 Subject: [PATCH] Footprint disallow layer checking needs to be based on courtyards. Fixes https://gitlab.com/kicad/code/kicad/issues/7620 --- .../include/geometry/shape_line_chain.h | 4 ++-- libs/kimath/include/geometry/shape_poly_set.h | 2 +- libs/kimath/src/geometry/shape_poly_set.cpp | 6 +++--- pcbnew/drc/drc_engine.cpp | 16 ++++++++++++++- .../drc_test_provider_courtyard_clearance.cpp | 20 +++++++++---------- pcbnew/exporters/gerber_placefile_writer.cpp | 4 ++-- pcbnew/footprint.h | 4 ++-- 7 files changed, 35 insertions(+), 21 deletions(-) diff --git a/libs/kimath/include/geometry/shape_line_chain.h b/libs/kimath/include/geometry/shape_line_chain.h index 4bb03c8500..5f884f11d0 100644 --- a/libs/kimath/include/geometry/shape_line_chain.h +++ b/libs/kimath/include/geometry/shape_line_chain.h @@ -380,7 +380,7 @@ public: return bbox; } - void GenerateBBoxCache() + void GenerateBBoxCache() const { m_bbox.Compute( m_points ); @@ -787,7 +787,7 @@ private: int m_width; /// cached bounding box - BOX2I m_bbox; + mutable BOX2I m_bbox; }; diff --git a/libs/kimath/include/geometry/shape_poly_set.h b/libs/kimath/include/geometry/shape_poly_set.h index c39580a8b5..708c90b43e 100644 --- a/libs/kimath/include/geometry/shape_poly_set.h +++ b/libs/kimath/include/geometry/shape_poly_set.h @@ -1141,7 +1141,7 @@ public: * @note These caches **must** be built before a group of calls to Contains(). They are * **not** kept up-to-date by editing actions. */ - void BuildBBoxCaches(); + void BuildBBoxCaches() const; const BOX2I BBoxFromCaches() const; diff --git a/libs/kimath/src/geometry/shape_poly_set.cpp b/libs/kimath/src/geometry/shape_poly_set.cpp index cce2e545a5..bf66c71549 100644 --- a/libs/kimath/src/geometry/shape_poly_set.cpp +++ b/libs/kimath/src/geometry/shape_poly_set.cpp @@ -1525,14 +1525,14 @@ bool SHAPE_POLY_SET::CollideEdge( const VECTOR2I& aPoint, } -void SHAPE_POLY_SET::BuildBBoxCaches() +void SHAPE_POLY_SET::BuildBBoxCaches() const { for( int polygonIdx = 0; polygonIdx < OutlineCount(); polygonIdx++ ) { - Outline( polygonIdx ).GenerateBBoxCache(); + COutline( polygonIdx ).GenerateBBoxCache(); for( int holeIdx = 0; holeIdx < HoleCount( polygonIdx ); holeIdx++ ) - Hole( polygonIdx, holeIdx ).GenerateBBoxCache(); + CHole( polygonIdx, holeIdx ).GenerateBBoxCache(); } } diff --git a/pcbnew/drc/drc_engine.cpp b/pcbnew/drc/drc_engine.cpp index 8130222f51..6a45aff2a3 100644 --- a/pcbnew/drc/drc_engine.cpp +++ b/pcbnew/drc/drc_engine.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -867,7 +868,20 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintId, const BOAR return false; } - if( !( c->layerTest & a->GetLayerSet() ).any() ) + LSET itemLayers = a->GetLayerSet(); + + if( a->Type() == PCB_FOOTPRINT_T ) + { + const FOOTPRINT* footprint = static_cast( a ); + + if( !footprint->GetPolyCourtyardFront().IsEmpty() ) + itemLayers |= LSET::FrontMask(); + + if( !footprint->GetPolyCourtyardBack().IsEmpty() ) + itemLayers |= LSET::BackMask(); + } + + if( !( c->layerTest & itemLayers ).any() ) { if( implicit ) { diff --git a/pcbnew/drc/drc_test_provider_courtyard_clearance.cpp b/pcbnew/drc/drc_test_provider_courtyard_clearance.cpp index 7feeab5580..4cef8b6c9b 100644 --- a/pcbnew/drc/drc_test_provider_courtyard_clearance.cpp +++ b/pcbnew/drc/drc_test_provider_courtyard_clearance.cpp @@ -140,9 +140,9 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testCourtyardClearances() if( m_drcEngine->IsErrorLimitExceeded( DRCE_OVERLAPPING_FOOTPRINTS) ) break; - FOOTPRINT* footprint = *it1; - SHAPE_POLY_SET& footprintFront = footprint->GetPolyCourtyardFront(); - SHAPE_POLY_SET& footprintBack = footprint->GetPolyCourtyardBack(); + FOOTPRINT* footprint = *it1; + const SHAPE_POLY_SET& footprintFront = footprint->GetPolyCourtyardFront(); + const SHAPE_POLY_SET& footprintBack = footprint->GetPolyCourtyardBack(); if( footprintFront.OutlineCount() == 0 && footprintBack.OutlineCount() == 0 ) continue; // No courtyards defined @@ -155,13 +155,13 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testCourtyardClearances() 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(); - DRC_CONSTRAINT constraint; - int clearance; - int actual; - VECTOR2I pos; + FOOTPRINT* test = *it2; + const SHAPE_POLY_SET& testFront = test->GetPolyCourtyardFront(); + const SHAPE_POLY_SET& testBack = test->GetPolyCourtyardBack(); + DRC_CONSTRAINT constraint; + int clearance; + int actual; + VECTOR2I pos; if( footprintFront.OutlineCount() > 0 && testFront.OutlineCount() > 0 && frontBBox.Intersects( testFront.BBoxFromCaches() ) ) diff --git a/pcbnew/exporters/gerber_placefile_writer.cpp b/pcbnew/exporters/gerber_placefile_writer.cpp index 6769460bcc..950cef4d30 100644 --- a/pcbnew/exporters/gerber_placefile_writer.cpp +++ b/pcbnew/exporters/gerber_placefile_writer.cpp @@ -184,8 +184,8 @@ int PLACEFILE_GERBER_WRITER::CreatePlaceFile( wxString& aFullFilename, PCB_LAYER { gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CMP_COURTYARD ); - SHAPE_POLY_SET& courtyard = onBack ? footprint->GetPolyCourtyardBack() - : footprint->GetPolyCourtyardFront(); + const SHAPE_POLY_SET& courtyard = onBack ? footprint->GetPolyCourtyardBack() + : footprint->GetPolyCourtyardFront(); for( int ii = 0; ii < courtyard.OutlineCount(); ii++ ) { diff --git a/pcbnew/footprint.h b/pcbnew/footprint.h index 59280a4f44..136215f48c 100644 --- a/pcbnew/footprint.h +++ b/pcbnew/footprint.h @@ -673,8 +673,8 @@ public: * * @return the courtyard polygon. */ - SHAPE_POLY_SET& GetPolyCourtyardFront() { return m_poly_courtyard_front; } - SHAPE_POLY_SET& GetPolyCourtyardBack() { return m_poly_courtyard_back; } + const SHAPE_POLY_SET& GetPolyCourtyardFront() const { return m_poly_courtyard_front; } + const SHAPE_POLY_SET& GetPolyCourtyardBack() const { return m_poly_courtyard_back; } /** * Build complex polygons of the courtyard areas from graphic items on the courtyard layers.