Simplify test for substantial nubs

Substantial elements following a divot should be at least as far in each
cardinal direction from the origin point in order to be considered
substantial.  This catches cases where the "substantial" element is
actually a straight segment away from the divot

Fixes https://gitlab.com/kicad/code/kicad/issues/14130
This commit is contained in:
Seth Hillbrand 2023-03-21 11:30:41 -07:00
parent b8cf7cc080
commit 914b5a4d21
2 changed files with 1915 additions and 291 deletions

View File

@ -114,8 +114,8 @@ private:
class POLYGON_TEST class POLYGON_TEST
{ {
public: public:
POLYGON_TEST( int aLimit, int aErrorLimit ) : POLYGON_TEST( int aLimit ) :
m_limit( aLimit ), m_max_error( aErrorLimit ) m_limit( aLimit )
{ {
}; };
@ -388,14 +388,8 @@ private:
*/ */
bool isSubstantial( const Vertex* aA, const Vertex* aB ) const bool isSubstantial( const Vertex* aA, const Vertex* aB ) const
{ {
// `directions` is a bitfield where bool x_change = false;
// bit 0 = pos y bool y_change = false;
// bit 1 = neg y
// bit 2 = pos x
// bit 3 = neg x
// So, once directions = 15, we have all directions
int directions = 0;
constexpr int all_dirs = 0b1111;
// This is a failsafe in case of invalid lists. Never check // This is a failsafe in case of invalid lists. Never check
// more than the total number of points in m_vertices // more than the total number of points in m_vertices
@ -405,8 +399,7 @@ private:
const Vertex* p0 = aA; const Vertex* p0 = aA;
const Vertex* p = getNextOutlineVertex( p0 ); const Vertex* p = getNextOutlineVertex( p0 );
while( !same_point( p, aB ) && checked < total_pts && !( x_change && y_change ) )
while( !same_point( p0, aB ) && checked < total_pts && directions != all_dirs )
{ {
double diff_x = std::abs( p->x - p0->x ); double diff_x = std::abs( p->x - p0->x );
double diff_y = std::abs( p->y - p0->y ); double diff_y = std::abs( p->y - p0->y );
@ -414,16 +407,11 @@ private:
// Floating point zeros can have a negative sign, so we need to // Floating point zeros can have a negative sign, so we need to
// ensure that only substantive diversions count for a direction // ensure that only substantive diversions count for a direction
// change // change
if( diff_x > m_max_error ) if( diff_x > m_limit )
directions |= ( 1 << ( 2 + std::signbit( p->x - p0->x ) ) ); x_change = true;
if( diff_y > m_max_error ) if( diff_y > m_limit )
directions |= ( 1 << std::signbit( p->y - p0->y ) ); y_change = true;
// In the case of a circle, we need to eventually get the direction
// so keep the p0 at the same point
if( diff_x > m_max_error || diff_y > m_max_error || p == aB )
p0 = p;
p = getNextOutlineVertex( p ); p = getNextOutlineVertex( p );
@ -432,16 +420,16 @@ private:
wxCHECK_MSG( checked < total_pts, false, wxT( "Invalid polygon detected. Missing points to check" ) ); wxCHECK_MSG( checked < total_pts, false, wxT( "Invalid polygon detected. Missing points to check" ) );
if( directions != all_dirs ) if( !x_change || !y_change )
return false; return false;
p0 = aA;
p = getPrevOutlineVertex( p0 ); p = getPrevOutlineVertex( p0 );
directions = 0; x_change = false;
y_change = false;
checked = 0; checked = 0;
while( !same_point( p0, aB ) && checked < total_pts && directions != all_dirs ) while( !same_point( p, aB ) && checked < total_pts && !( x_change && y_change ) )
{ {
double diff_x = std::abs( p->x - p0->x ); double diff_x = std::abs( p->x - p0->x );
double diff_y = std::abs( p->y - p0->y ); double diff_y = std::abs( p->y - p0->y );
@ -449,16 +437,11 @@ private:
// Floating point zeros can have a negative sign, so we need to // Floating point zeros can have a negative sign, so we need to
// ensure that only substantive diversions count for a direction // ensure that only substantive diversions count for a direction
// change // change
if( diff_x > m_max_error ) if( diff_x > m_limit )
directions |= ( 1 << ( 2 + std::signbit( p->x - p0->x ) ) ); x_change = true;
if( diff_y > m_max_error ) if( diff_y > m_limit )
directions |= ( 1 << std::signbit( p->y - p0->y ) ); y_change = true;
// In the case of a circle, we need to eventually get the direction
// so keep the p0 at the same point
if( diff_x > m_max_error || diff_y > m_max_error || p == aB )
p0 = p;
p = getPrevOutlineVertex( p ); p = getPrevOutlineVertex( p );
@ -467,7 +450,7 @@ private:
wxCHECK_MSG( checked < total_pts, false, wxT( "Invalid polygon detected. Missing points to check" ) ); wxCHECK_MSG( checked < total_pts, false, wxT( "Invalid polygon detected. Missing points to check" ) );
return ( directions == all_dirs ); return ( x_change && y_change );
} }
/** /**
@ -622,7 +605,6 @@ private:
private: private:
int m_limit; int m_limit;
double m_max_error;
BOX2I m_bbox; BOX2I m_bbox;
std::deque<Vertex> m_vertices; std::deque<Vertex> m_vertices;
std::set<std::pair<int, int>> m_hits; std::set<std::pair<int, int>> m_hits;
@ -722,7 +704,7 @@ bool DRC_TEST_PROVIDER_CONNECTION_WIDTH::Run()
if( m_drcEngine->IsCancelled() ) if( m_drcEngine->IsCancelled() )
return 0; return 0;
POLYGON_TEST test( aMinWidth, m_drcEngine->GetDesignSettings()->m_MaxError ); POLYGON_TEST test( aMinWidth );
for( int ii = 0; ii < aItemsPoly.Poly.OutlineCount(); ++ii ) for( int ii = 0; ii < aItemsPoly.Poly.OutlineCount(); ++ii )
{ {

File diff suppressed because it is too large Load Diff