From 40309a17ef1598e5644799ea52c7ca6e0b78e1fc Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Fri, 1 Mar 2019 05:36:53 -0800 Subject: [PATCH] pcbnew: Check exact overlapping polygons Checks for polygon collisions in the outline when the polygon contains two or more segments that exactly overlap. This also places the DRC marker at the location where the collision happens. Fixes: lp:1818163 * https://bugs.launchpad.net/kicad/+bug/1818163 Fixes: lp:1818218 * https://bugs.launchpad.net/kicad/+bug/1818218 --- pcbnew/class_board.cpp | 4 +- .../convert_drawsegment_list_to_polygon.cpp | 48 +++++++++++++++++-- pcbnew/drc/drc_marker_factory.cpp | 4 +- 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index 87e604c6f7..6cbb2e7a32 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -10,7 +10,7 @@ * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck * Copyright (C) 2011 Wayne Stambaugh * - * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -2960,7 +2960,7 @@ extern bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines, bool BOARD::GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines, wxString* aErrorText, wxPoint* aErrorLocation ) { bool success = BuildBoardPolygonOutlines( this, aOutlines, aErrorText, - Millimeter2iu( 0.05 ), aErrorLocation ); + ARC_HIGH_DEF, aErrorLocation ); // Make polygon strictly simple to avoid issues (especially in 3D viewer) aOutlines.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); diff --git a/pcbnew/convert_drawsegment_list_to_polygon.cpp b/pcbnew/convert_drawsegment_list_to_polygon.cpp index e4c26134d5..8bff699c00 100644 --- a/pcbnew/convert_drawsegment_list_to_polygon.cpp +++ b/pcbnew/convert_drawsegment_list_to_polygon.cpp @@ -3,7 +3,7 @@ * * Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2015 SoftPLC Corporation, Dick Hollenbeck - * Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -32,10 +32,12 @@ #include #include +#include #include #include #include #include +#include #include @@ -322,7 +324,7 @@ bool ConvertOutlineToPolygon( std::vector& aSegList, SHAPE_POLY_SE // Output the Edge.Cuts perimeter as circle or polygon. if( graphic->GetShape() == S_CIRCLE ) { - int steps = GetArcToSegmentCount( graphic->GetRadius(), ARC_LOW_DEF, 360.0 ); + int steps = GetArcToSegmentCount( graphic->GetRadius(), aTolerance, 360.0 ); TransformCircleToPolygon( aPolygons, graphic->GetCenter(), graphic->GetRadius(), steps ); } else if( graphic->GetShape() == S_POLYGON ) @@ -386,7 +388,7 @@ bool ConvertOutlineToPolygon( std::vector& aSegList, SHAPE_POLY_SE wxPoint pcenter = graphic->GetCenter(); double angle = -graphic->GetAngle(); double radius = graphic->GetRadius(); - int steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 ); + int steps = GetArcToSegmentCount( radius, aTolerance, angle / 10.0 ); if( !close_enough( prevPt, pstart, aTolerance ) ) { @@ -528,7 +530,7 @@ bool ConvertOutlineToPolygon( std::vector& aSegList, SHAPE_POLY_SE double angle = 3600.0; wxPoint start = center; int radius = graphic->GetRadius(); - int steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, 360.0 ); + int steps = GetArcToSegmentCount( radius, aTolerance, 360.0 ); wxPoint nextPt; start.x += radius; @@ -587,7 +589,7 @@ bool ConvertOutlineToPolygon( std::vector& aSegList, SHAPE_POLY_SE wxPoint pcenter = graphic->GetCenter(); double angle = -graphic->GetAngle(); int radius = graphic->GetRadius(); - int steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 ); + int steps = GetArcToSegmentCount( radius, aTolerance, angle / 10.0 ); if( !close_enough( prevPt, pstart, aTolerance ) ) { @@ -699,6 +701,42 @@ bool ConvertOutlineToPolygon( std::vector& aSegList, SHAPE_POLY_SE } } + // All of the silliness that follows is to work around the segment iterator + // while checking for collisions. + // TODO: Implement proper segment and point iterators that follow std + for( auto seg1 = aPolygons.IterateSegmentsWithHoles(); seg1; seg1++ ) + { + auto seg2 = seg1; + + for( ++seg2; seg2; seg2++ ) + { + // Check for exact overlapping segments. This is not viewed + // as an intersection below + if( *seg1 == *seg2 || + ( ( *seg1 ).A == ( *seg2 ).B && ( *seg1 ).B == ( *seg2 ).A ) ) + { + if( aErrorLocation ) + { + aErrorLocation->x = ( *seg1 ).A.x; + aErrorLocation->y = ( *seg1 ).A.y; + } + + return false; + } + + if( auto pt = seg1.Get().Intersect( seg2.Get(), true ) ) + { + if( aErrorLocation ) + { + aErrorLocation->x = pt->x; + aErrorLocation->y = pt->y; + } + + return false; + } + } + } + return true; } diff --git a/pcbnew/drc/drc_marker_factory.cpp b/pcbnew/drc/drc_marker_factory.cpp index 0ffbf2f203..a8e69f875b 100644 --- a/pcbnew/drc/drc_marker_factory.cpp +++ b/pcbnew/drc/drc_marker_factory.cpp @@ -3,7 +3,7 @@ * * Copyright (C) 2010 Dick Hollenbeck, dick@softplc.com * Copyright (C) 2004-2017 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2018-2019 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -137,7 +137,7 @@ MARKER_PCB* DRC_MARKER_FACTORY::NewMarker( const wxPoint& aPos, BOARD_ITEM* aItem, int aErrorCode ) const { return new MARKER_PCB( - getCurrentUnits(), aErrorCode, aPos, aItem, aItem->GetPosition(), nullptr, wxPoint() ); + getCurrentUnits(), aErrorCode, aPos, aItem, aPos, nullptr, wxPoint() ); }