From 16e3d40552df936fb6b1ec24d1deb1b10b366a7d Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Thu, 21 Jul 2022 15:01:50 -0700 Subject: [PATCH] ADDED: Display calculated clearance in status bar In addition to showing resolved clearance, we also show the calculated clearance in the same method as is used for DRC. This will allow users to better examine their system while working. Fixes https://gitlab.com/kicad/code/kicad/issues/7934 --- libs/kimath/include/geometry/shape.h | 9 ++++- libs/kimath/include/geometry/shape_compound.h | 10 +++-- libs/kimath/include/geometry/shape_poly_set.h | 2 +- libs/kimath/src/geometry/shape.cpp | 39 +++++++++++++++++++ libs/kimath/src/geometry/shape_poly_set.cpp | 2 +- pcbnew/drc/drc_rtree.h | 16 ++++---- pcbnew/router/pns_kicad_iface.cpp | 2 +- pcbnew/router/router_preview_item.cpp | 4 +- pcbnew/tools/pcb_control.cpp | 12 ++++++ 9 files changed, 78 insertions(+), 18 deletions(-) diff --git a/libs/kimath/include/geometry/shape.h b/libs/kimath/include/geometry/shape.h index 129e742b9e..056ceb3b9c 100644 --- a/libs/kimath/include/geometry/shape.h +++ b/libs/kimath/include/geometry/shape.h @@ -104,7 +104,7 @@ public: virtual size_t GetIndexableSubshapeCount() const { return 0; } - virtual void GetIndexableSubshapes( std::vector& aSubshapes ) { } + virtual void GetIndexableSubshapes( std::vector& aSubshapes ) const { } protected: ///< type of our shape @@ -143,6 +143,13 @@ public: return nullptr; }; + /** + * Return the actual minimum distance between two shapes + * + * @retval distance in IU + */ + int GetClearance( const SHAPE* aOther ) const; + /** * Return true if the shape is a null shape. * diff --git a/libs/kimath/include/geometry/shape_compound.h b/libs/kimath/include/geometry/shape_compound.h index 337632403b..7f80b0e7a2 100644 --- a/libs/kimath/include/geometry/shape_compound.h +++ b/libs/kimath/include/geometry/shape_compound.h @@ -82,10 +82,10 @@ public: // Don't make clients deal with nested SHAPE_COMPOUNDs if( aShape->HasIndexableSubshapes() ) { - std::vector subshapes; + std::vector subshapes; aShape->GetIndexableSubshapes( subshapes ); - for( SHAPE* subshape : subshapes ) + for( const SHAPE* subshape : subshapes ) m_shapes.push_back( subshape->Clone() ); delete aShape; @@ -127,9 +127,11 @@ public: return m_shapes.size(); } - virtual void GetIndexableSubshapes( std::vector& aSubshapes ) override + virtual void GetIndexableSubshapes( std::vector& aSubshapes ) const override { - aSubshapes = m_shapes; + aSubshapes.clear(); + aSubshapes.reserve( m_shapes.size() ); + std::copy( m_shapes.begin(), m_shapes.end(), std::back_inserter( aSubshapes ) ); } bool ConvertToSimplePolygon( SHAPE_SIMPLE* aOut ) const; diff --git a/libs/kimath/include/geometry/shape_poly_set.h b/libs/kimath/include/geometry/shape_poly_set.h index 7b6e826762..7e2c695d47 100644 --- a/libs/kimath/include/geometry/shape_poly_set.h +++ b/libs/kimath/include/geometry/shape_poly_set.h @@ -517,7 +517,7 @@ public: virtual size_t GetIndexableSubshapeCount() const override; - virtual void GetIndexableSubshapes( std::vector& aSubshapes ) override; + virtual void GetIndexableSubshapes( std::vector& aSubshapes ) const override; /** * Convert a global vertex index ---i.e., a number that globally identifies a vertex in a diff --git a/libs/kimath/src/geometry/shape.cpp b/libs/kimath/src/geometry/shape.cpp index e40c0beaa6..fa50bfea73 100644 --- a/libs/kimath/src/geometry/shape.cpp +++ b/libs/kimath/src/geometry/shape.cpp @@ -24,6 +24,12 @@ #include +#include +#include +#include +#include +#include +#include bool SHAPE::Parse( std::stringstream& aStream ) { @@ -37,3 +43,36 @@ const std::string SHAPE::Format() const assert( false ); return std::string( "" ); } + + +int SHAPE::GetClearance( const SHAPE* aOther ) const +{ + int actual_clearance = std::numeric_limits::max(); + std::vector a_shapes; + std::vector b_shapes; + + GetIndexableSubshapes( a_shapes ); + aOther->GetIndexableSubshapes( b_shapes ); + + if( GetIndexableSubshapeCount() == 0 ) + a_shapes.push_back( this ); + + if( aOther->GetIndexableSubshapeCount() == 0 ) + b_shapes.push_back( aOther ); + + // Clearance gets the distance to the centerline. We add in the additional size + // after to get the true clearance + for( const SHAPE* a : a_shapes ) + { + for( const SHAPE* b : b_shapes ) + { + int temp_dist = 0; + a->Collide( b, std::numeric_limits::max() / 2, &temp_dist ); + + if( temp_dist < actual_clearance ) + actual_clearance = temp_dist; + } + } + + return actual_clearance; +} diff --git a/libs/kimath/src/geometry/shape_poly_set.cpp b/libs/kimath/src/geometry/shape_poly_set.cpp index 1d9a756b23..7a290c278f 100644 --- a/libs/kimath/src/geometry/shape_poly_set.cpp +++ b/libs/kimath/src/geometry/shape_poly_set.cpp @@ -2526,7 +2526,7 @@ size_t SHAPE_POLY_SET::GetIndexableSubshapeCount() const } -void SHAPE_POLY_SET::GetIndexableSubshapes( std::vector& aSubshapes ) +void SHAPE_POLY_SET::GetIndexableSubshapes( std::vector& aSubshapes ) const { aSubshapes.reserve( GetIndexableSubshapeCount() ); diff --git a/pcbnew/drc/drc_rtree.h b/pcbnew/drc/drc_rtree.h index cb6f721eef..4aea5c6464 100644 --- a/pcbnew/drc/drc_rtree.h +++ b/pcbnew/drc/drc_rtree.h @@ -51,7 +51,7 @@ public: struct ITEM_WITH_SHAPE { - ITEM_WITH_SHAPE( BOARD_ITEM *aParent, SHAPE* aShape, + ITEM_WITH_SHAPE( BOARD_ITEM *aParent, const SHAPE* aShape, std::shared_ptr aParentShape = nullptr ) : parent ( aParent ), shape ( aShape ), @@ -59,7 +59,7 @@ public: {}; BOARD_ITEM* parent; - SHAPE* shape; + const SHAPE* shape; std::shared_ptr parentShape; }; @@ -108,7 +108,7 @@ public: if( aItem->Type() == PCB_FP_TEXT_T && !static_cast( aItem )->IsVisible() ) return; - std::vector subshapes; + std::vector subshapes; std::shared_ptr shape = aItem->GetEffectiveShape( aRefLayer ); subshapes.clear(); @@ -128,9 +128,9 @@ public: } } - for( SHAPE* subshape : subshapes ) + for( const SHAPE* subshape : subshapes ) { - if( dynamic_cast( subshape ) ) + if( dynamic_cast( subshape ) ) continue; BOX2I bbox = subshape->BBox(); @@ -336,9 +336,9 @@ public: auto polyVisitor = [&]( ITEM_WITH_SHAPE* aItem ) -> bool { - SHAPE* shape = aItem->shape; - wxASSERT( dynamic_cast( shape ) ); - auto tri = static_cast( shape ); + const SHAPE* shape = aItem->shape; + wxASSERT( dynamic_cast( shape ) ); + auto tri = static_cast( shape ); const SHAPE_LINE_CHAIN& outline = poly->Outline( 0 ); diff --git a/pcbnew/router/pns_kicad_iface.cpp b/pcbnew/router/pns_kicad_iface.cpp index 93454fcc35..c8d0e36fe1 100644 --- a/pcbnew/router/pns_kicad_iface.cpp +++ b/pcbnew/router/pns_kicad_iface.cpp @@ -937,7 +937,7 @@ std::unique_ptr PNS_KICAD_IFACE_BASE::syncPad( PAD* aPad ) if( shape->HasIndexableSubshapes() && shape->GetIndexableSubshapeCount() == 1 ) { - std::vector subshapes; + std::vector subshapes; shape->GetIndexableSubshapes( subshapes ); solid->SetShape( subshapes[0]->Clone() ); diff --git a/pcbnew/router/router_preview_item.cpp b/pcbnew/router/router_preview_item.cpp index db5f17511a..c247ffe5a4 100644 --- a/pcbnew/router/router_preview_item.cpp +++ b/pcbnew/router/router_preview_item.cpp @@ -450,10 +450,10 @@ void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const if( m_shape->HasIndexableSubshapes() ) { - std::vector subshapes; + std::vector subshapes; m_shape->GetIndexableSubshapes( subshapes ); - for( SHAPE* shape : subshapes ) + for( const SHAPE* shape : subshapes ) drawShape( shape, gal ); } else diff --git a/pcbnew/tools/pcb_control.cpp b/pcbnew/tools/pcb_control.cpp index 099a9685cb..4888e4e802 100644 --- a/pcbnew/tools/pcb_control.cpp +++ b/pcbnew/tools/pcb_control.cpp @@ -1276,8 +1276,20 @@ int PCB_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent ) constraint = drcEngine->EvalRules( CLEARANCE_CONSTRAINT, a, b, overlap.CuStack().front() ); + std::shared_ptr a_shape( a_conn->GetEffectiveShape( overlap.CuStack().front() ) ); + std::shared_ptr b_shape( b_conn->GetEffectiveShape( overlap.CuStack().front() ) ); + + int actual_clearance = a_shape->GetClearance( b_shape.get() ); + msgItems.emplace_back( MSG_PANEL_ITEM( _( "Resolved clearance" ), clearanceString( constraint ) ) ); + + if( actual_clearance > -1 && actual_clearance < std::numeric_limits::max() ) + { + msgItems.emplace_back( + MSG_PANEL_ITEM( _( "Actual clearance" ), + StringFromValue( units, actual_clearance, true ) ) ); + } } }