From a59c1afa538f828b489e7d5d21bed0506c20dfd6 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sat, 4 Feb 2023 13:44:42 +0000 Subject: [PATCH] Fix two bugs in RTree polygon collions special case. 1) Special case doesn't work for polygons with holes 2) Fix special case to handle intersecting lines where neither end is in the polygon. Note that only (1) is required for the bug below. (2) was just discovered while implementing (1). Fixes https://gitlab.com/kicad/code/kicad/issues/13779 --- pcbnew/drc/drc_rtree.h | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/pcbnew/drc/drc_rtree.h b/pcbnew/drc/drc_rtree.h index 6a2cdc07bb..9568b34ced 100644 --- a/pcbnew/drc/drc_rtree.h +++ b/pcbnew/drc/drc_rtree.h @@ -345,7 +345,7 @@ public: // Special case the polygon case. Otherwise we'll call its Collide() method which will // triangulate it as well and then do triangle/triangle collisions. This ends up being - // *much* slower than 4 calls to PointInside(). + // *much* slower than 3 segment Collide()s and a PointInside(). auto polyVisitor = [&]( ITEM_WITH_SHAPE* aItem ) -> bool { @@ -355,10 +355,17 @@ public: const SHAPE_LINE_CHAIN& outline = poly->Outline( 0 ); - if( outline.PointInside( tri->GetPoint( 0 ) ) - || outline.PointInside( tri->GetPoint( 1 ) ) - || outline.PointInside( tri->GetPoint( 2 ) ) - || tri->PointInside( outline.CPoint( 0 ) ) ) + for( int ii = 0; ii < (int) tri->GetSegmentCount(); ++ii ) + { + if( outline.Collide( tri->GetSegment( ii ) ) ) + { + collision = true; + return false; + } + } + + // Also must check for poly being completely inside the triangle + if( tri->PointInside( outline.CPoint( 0 ) ) ) { collision = true; return false; @@ -379,7 +386,7 @@ public: return true; }; - if( poly && poly->OutlineCount() == 1 ) + if( poly && poly->OutlineCount() == 1 && poly->HoleCount( 0 ) == 0 ) this->m_tree[aLayer]->Search( min, max, polyVisitor ); else this->m_tree[aLayer]->Search( min, max, visitor );