From c4fff95078ab6fdd3718cbc159158843a0cfd1f9 Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Fri, 17 Jan 2020 06:19:27 -0800 Subject: [PATCH] PNS: Detect collisions including newline width The new line collision search uses BBox() to check for colliding objects. BBox in the SHAPE_LINE_CHAIN did not include width as the chains were assumed to be zero-width. This is not the case for PNS::LINE elements. We mostly don't notice this because DRC checks for SEGMENT collisions but it becomes obvious/annoying when we cannot place a track for unknown reasons and the snap-back doesn't take line width into account. Fixes #3776 | https://gitlab.com/kicad/code/kicad/issues/3776 --- .../include/geometry/shape_line_chain.h | 50 +++++++++++++++---- pcbnew/router/pns_line.h | 2 + 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/libs/kimath/include/geometry/shape_line_chain.h b/libs/kimath/include/geometry/shape_line_chain.h index 73fc0d8adb..30bf5150b4 100644 --- a/libs/kimath/include/geometry/shape_line_chain.h +++ b/libs/kimath/include/geometry/shape_line_chain.h @@ -79,19 +79,21 @@ public: * Constructor * Initializes an empty line chain. */ - SHAPE_LINE_CHAIN() : - SHAPE( SH_LINE_CHAIN ), m_closed( false ) + SHAPE_LINE_CHAIN() : SHAPE( SH_LINE_CHAIN ), m_closed( false ), m_width( 0 ) {} /** * Copy Constructor */ - SHAPE_LINE_CHAIN( const SHAPE_LINE_CHAIN& aShape ) : - SHAPE( SH_LINE_CHAIN ), m_points( aShape.m_points ), m_closed( aShape.m_closed ) + SHAPE_LINE_CHAIN( const SHAPE_LINE_CHAIN& aShape ) + : SHAPE( SH_LINE_CHAIN ), + m_points( aShape.m_points ), + m_closed( aShape.m_closed ), + m_width( aShape.m_width ) {} SHAPE_LINE_CHAIN( const std::vector& aV, bool aClosed = false ) - : SHAPE( SH_LINE_CHAIN ), m_closed( aClosed ) + : SHAPE( SH_LINE_CHAIN ), m_closed( aClosed ), m_width( 0 ) { m_points.reserve( aV.size() ); @@ -100,14 +102,13 @@ public: } SHAPE_LINE_CHAIN( const std::vector& aV, bool aClosed = false ) - : SHAPE( SH_LINE_CHAIN ), m_closed( aClosed ) + : SHAPE( SH_LINE_CHAIN ), m_closed( aClosed ), m_width( 0 ) { m_points = aV; } - SHAPE_LINE_CHAIN( const ClipperLib::Path& aPath ) : - SHAPE( SH_LINE_CHAIN ), - m_closed( true ) + SHAPE_LINE_CHAIN( const ClipperLib::Path& aPath ) + : SHAPE( SH_LINE_CHAIN ), m_closed( true ), m_width( 0 ) { m_points.reserve( aPath.size() ); @@ -154,6 +155,24 @@ public: return m_closed; } + /** + * Sets the width of all segments in the chain + * @param aWidth width in internal units + */ + void SetWidth( int aWidth ) + { + m_width = aWidth; + } + + /** + * Gets the current width of the segments in the chain + * @return width in internal units + */ + int Width() const + { + return m_width; + } + /** * Function SegmentCount() * @@ -271,8 +290,8 @@ public: BOX2I bbox; bbox.Compute( m_points ); - if( aClearance != 0 ) - bbox.Inflate( aClearance ); + if( aClearance != 0 || m_width != 0 ) + bbox.Inflate( aClearance + m_width ); return bbox; } @@ -280,6 +299,9 @@ public: void GenerateBBoxCache() { m_bbox.Compute( m_points ); + + if( m_width != 0 ) + m_bbox.Inflate( m_width ); } /** @@ -674,6 +696,12 @@ private: /// is the line chain closed? bool m_closed; + /// Width of the segments (for BBox calculations in RTree) + /// TODO Adjust usage of SHAPE_LINE_CHAIN to account for where we need a width and where not + /// Alternatively, we could split the class into a LINE_CHAIN (no width) and SHAPE_LINE_CHAIN that derives from + /// SHAPE as well that does have a width. Not sure yet on the correct path. + int m_width; + /// cached bounding box BOX2I m_bbox; }; diff --git a/pcbnew/router/pns_line.h b/pcbnew/router/pns_line.h index 66cf22deeb..452f12a617 100644 --- a/pcbnew/router/pns_line.h +++ b/pcbnew/router/pns_line.h @@ -122,6 +122,7 @@ public: void SetShape( const SHAPE_LINE_CHAIN& aLine ) { m_line = aLine; + m_line.SetWidth( m_width ); } ///> Returns the shape of the line @@ -170,6 +171,7 @@ public: void SetWidth( int aWidth ) { m_width = aWidth; + m_line.SetWidth( aWidth ); } ///> Returns line width