From 3c0b10b0226a6b6a3f3d11c6ded3dd8973532085 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Wed, 1 Dec 2021 19:43:10 +0000 Subject: [PATCH] Don't use approximated shapes for router hulls. We only do 45-degree routing anyway so we might as well build an octagonal-based hull from the get-go. Fixes https://gitlab.com/kicad/code/kicad/issues/7672 Fixes https://gitlab.com/kicad/code/kicad/issues/9544 Fixes https://gitlab.com/kicad/code/kicad/issues/9833 --- pcbnew/board_design_settings.cpp | 4 +-- pcbnew/router/pns_kicad_iface.cpp | 52 ++++++++++--------------------- pcbnew/router/pns_solid.cpp | 27 ++++++++++++---- 3 files changed, 39 insertions(+), 44 deletions(-) diff --git a/pcbnew/board_design_settings.cpp b/pcbnew/board_design_settings.cpp index d81e8e9487..fccf4ae0c3 100644 --- a/pcbnew/board_design_settings.cpp +++ b/pcbnew/board_design_settings.cpp @@ -1116,9 +1116,7 @@ int BOARD_DESIGN_SETTINGS::GetLayerClass( PCB_LAYER_ID aLayer ) const int BOARD_DESIGN_SETTINGS::GetDRCEpsilon() const { - // You can loosen the max epsilon manually but we cap it at the board's inherent - // accuracy given by the maximum error when approximating curves - return std::max( m_MaxError, Millimeter2iu( ADVANCED_CFG::GetCfg().m_DRCEpsilon ) ); + return Millimeter2iu( ADVANCED_CFG::GetCfg().m_DRCEpsilon ); } diff --git a/pcbnew/router/pns_kicad_iface.cpp b/pcbnew/router/pns_kicad_iface.cpp index 96d5e92f5f..bbd791f9d8 100644 --- a/pcbnew/router/pns_kicad_iface.cpp +++ b/pcbnew/router/pns_kicad_iface.cpp @@ -953,36 +953,18 @@ std::unique_ptr PNS_KICAD_IFACE_BASE::syncPad( PAD* aPad ) solid->SetHole( slot ); } - auto shapes = std::dynamic_pointer_cast( aPad->GetEffectiveShape() ); + std::shared_ptr shape = aPad->GetEffectiveShape(); - if( shapes && shapes->Size() == 1 ) + if( shape->HasIndexableSubshapes() && shape->GetIndexableSubshapeCount() == 1 ) { - solid->SetShape( shapes->Shapes()[0]->Clone() ); + std::vector subshapes; + shape->GetIndexableSubshapes( subshapes ); + + solid->SetShape( subshapes[0]->Clone() ); } else { - // TODO: Support PNS hull generation for compound shapes and use the actual shape here - - // NOTE: Because PNS hulls can't handle compound shapes yet, there will always be a - // discrepancy between the PNS and the DRC engine in some cases (such as custom shape pads - // that use polygons with nonzero width). No matter where you put the error, this causes - // issues, but the "lesser evil" is to allow routing in more cases (and have DRC errors that - // need to be cleaned up) vs. having situations that are valid to DRC but can't be routed - // because the extra error outside the pad is a clearance violation to the router. - // - // See https://gitlab.com/kicad/code/kicad/-/issues/9544 - // and https://gitlab.com/kicad/code/kicad/-/issues/7672 - - SHAPE_POLY_SET outline; - aPad->TransformShapeWithClearanceToPolygon( outline, UNDEFINED_LAYER, 0, ARC_HIGH_DEF, - ERROR_INSIDE ); - - SHAPE_SIMPLE* shape = new SHAPE_SIMPLE(); - - for( auto iter = outline.CIterate( 0 ); iter; iter++ ) - shape->Append( *iter ); - - solid->SetShape( shape ); + solid->SetShape( shape->Clone() ); } return solid; @@ -1434,30 +1416,30 @@ void PNS_KICAD_IFACE::DisplayItem( const PNS::ITEM* aItem, int aClearance, bool ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_view ); + static KICAD_T tracksOrVias[] = { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, EOT }; + static KICAD_T tracks[] = { PCB_TRACE_T, PCB_ARC_T, EOT }; + if( aClearance >= 0 ) { pitem->SetClearance( aClearance ); switch( m_dispOptions->m_ShowTrackClearanceMode ) { - case PCB_DISPLAY_OPTIONS::DO_NOT_SHOW_CLEARANCE: - pitem->ShowTrackClearance( false ); - pitem->ShowViaClearance( false ); - break; case PCB_DISPLAY_OPTIONS::SHOW_TRACK_CLEARANCE_WITH_VIA_ALWAYS: case PCB_DISPLAY_OPTIONS::SHOW_WHILE_ROUTING_OR_DRAGGING: - pitem->ShowTrackClearance( true ); - pitem->ShowViaClearance( true ); + pitem->ShowClearance( pitem->GetParent()->IsType( tracksOrVias ) ); break; case PCB_DISPLAY_OPTIONS::SHOW_TRACK_CLEARANCE_WITH_VIA_WHILE_ROUTING: - pitem->ShowTrackClearance( !aEdit ); - pitem->ShowViaClearance( !aEdit ); + pitem->ShowClearance( pitem->GetParent()->IsType( tracksOrVias ) && !aEdit ); break; case PCB_DISPLAY_OPTIONS::SHOW_TRACK_CLEARANCE_WHILE_ROUTING: - pitem->ShowTrackClearance( !aEdit ); - pitem->ShowViaClearance( false ); + pitem->ShowClearance( pitem->GetParent()->IsType( tracks ) && !aEdit ); + break; + + default: + pitem->ShowClearance( false ); break; } } diff --git a/pcbnew/router/pns_solid.cpp b/pcbnew/router/pns_solid.cpp index d11565dd67..ebfca9d649 100644 --- a/pcbnew/router/pns_solid.cpp +++ b/pcbnew/router/pns_solid.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -112,9 +113,16 @@ const SHAPE_LINE_CHAIN SOLID::Hull( int aClearance, int aWalkaroundThickness, in } else { - // fixme - shouldn't happen but one day we should move - // TransformShapeWithClearanceToPolygon() to the Geometry Library - return SHAPE_LINE_CHAIN(); + SHAPE_POLY_SET hullSet; + + for( SHAPE* shape : cmpnd->Shapes() ) + { + hullSet.AddOutline( buildHullForPrimitiveShape( shape, aClearance, + aWalkaroundThickness ) ); + } + + hullSet.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); + return hullSet.Outline( 0 ); } } else @@ -140,9 +148,16 @@ const SHAPE_LINE_CHAIN SOLID::HoleHull( int aClearance, int aWalkaroundThickness } else { - // fixme - shouldn't happen but one day we should move - // TransformShapeWithClearanceToPolygon() to the Geometry Library - return SHAPE_LINE_CHAIN(); + SHAPE_POLY_SET hullSet; + + for( SHAPE* shape : cmpnd->Shapes() ) + { + hullSet.AddOutline( buildHullForPrimitiveShape( shape, aClearance, + aWalkaroundThickness ) ); + } + + hullSet.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); + return hullSet.Outline( 0 ); } } else