diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index 208139039f..5308264428 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -195,6 +195,14 @@ bool ZONE_CONTAINER::IsOnCopperLayer() const } +bool ZONE_CONTAINER::CommonLayerExists( const LSET aLayerSet ) const +{ + auto common = GetLayerSet() & aLayerSet; + + return common.size() > 0; +} + + void ZONE_CONTAINER::SetLayer( PCB_LAYER_ID aLayer ) { SetLayerSet( LSET( aLayer ) ); diff --git a/pcbnew/class_zone.h b/pcbnew/class_zone.h index 7b7915a516..b80c0c07ce 100644 --- a/pcbnew/class_zone.h +++ b/pcbnew/class_zone.h @@ -182,6 +182,12 @@ public: */ bool IsOnCopperLayer() const; + /** + * Function CommonLayerExist + * Test if this zone shares a common layer with the given layer set + */ + bool CommonLayerExists( const LSET aLayerSet ) const; + virtual void SetLayer( PCB_LAYER_ID aLayer ) override; virtual PCB_LAYER_ID GetLayer() const override; diff --git a/pcbnew/drc.cpp b/pcbnew/drc.cpp index 6213be96ac..6abcbd0c00 100644 --- a/pcbnew/drc.cpp +++ b/pcbnew/drc.cpp @@ -621,7 +621,9 @@ void DRC::testKeepoutAreas() ZONE_CONTAINER* area = m_pcb->GetArea( ii ); if( !area->GetIsKeepout() ) + { continue; + } for( TRACK* segm = m_pcb->m_Track; segm != NULL; segm = segm->Next() ) { @@ -630,7 +632,8 @@ void DRC::testKeepoutAreas() if( ! area->GetDoNotAllowTracks() ) continue; - if( segm->GetLayer() != area->GetLayer() ) + // Ignore if the keepout zone is not on the same layer + if( !area->IsOnLayer( segm->GetLayer() ) ) continue; if( area->Outline()->Distance( SEG( segm->GetStart(), segm->GetEnd() ), @@ -646,7 +649,9 @@ void DRC::testKeepoutAreas() if( ! area->GetDoNotAllowVias() ) continue; - if( ! ((VIA*)segm)->IsOnLayer( area->GetLayer() ) ) + auto viaLayers = segm->GetLayerSet(); + + if( !area->CommonLayerExists( viaLayers ) ) continue; if( area->Outline()->Distance( segm->GetPosition() ) < segm->GetWidth()/2 ) @@ -801,7 +806,7 @@ bool DRC::doTrackKeepoutDrc( TRACK* aRefSeg ) if( ! area->GetDoNotAllowTracks() ) continue; - if( aRefSeg->GetLayer() != area->GetLayer() ) + if( !area->IsOnLayer( aRefSeg->GetLayer() ) ) continue; if( area->Outline()->Distance( SEG( aRefSeg->GetStart(), aRefSeg->GetEnd() ), @@ -817,7 +822,9 @@ bool DRC::doTrackKeepoutDrc( TRACK* aRefSeg ) if( ! area->GetDoNotAllowVias() ) continue; - if( ! ((VIA*)aRefSeg)->IsOnLayer( area->GetLayer() ) ) + auto viaLayers = aRefSeg->GetLayerSet(); + + if( !area->CommonLayerExists( viaLayers ) ) continue; if( area->Outline()->Distance( aRefSeg->GetPosition() ) < aRefSeg->GetWidth()/2 ) diff --git a/pcbnew/zones_by_polygon.cpp b/pcbnew/zones_by_polygon.cpp index d8e462386f..72c70ab2dd 100644 --- a/pcbnew/zones_by_polygon.cpp +++ b/pcbnew/zones_by_polygon.cpp @@ -127,11 +127,20 @@ void PCB_EDIT_FRAME::duplicateZone( wxDC* aDC, ZONE_CONTAINER* aZone ) // If the new zone is on the same layer as the the initial zone, // do nothing - if( success && ( aZone->GetLayer() == zoneSettings.m_CurrentZone_Layer ) ) + if( success ) { - DisplayErrorMessage( this, - _( "The duplicated zone cannot be on the same layer as the original zone." ) ); - success = false; + if( aZone->GetIsKeepout() && ( aZone->GetLayerSet() == zoneSettings.m_Layers ) ) + { + DisplayErrorMessage( + this, _( "The duplicated zone cannot be on the same layers as the original zone." ) ); + success = false; + } + else if( !aZone->GetIsKeepout() && ( aZone->GetLayer() == zoneSettings.m_CurrentZone_Layer ) ) + { + DisplayErrorMessage( + this, _( "The duplicated zone cannot be on the same layer as the original zone." ) ); + success = false; + } } if( success )