Add logging and area check to tesselation

Logging is useful when we find an area that cannot be triangulated.
This will be used to generated test cases.

Skipping minor untesselated areas means that the polygon will still be
considered fully tesselated (and not sent back again and again) even if
the tesselation misses an area less than the configured limit.
Currently, this is 31^2nm.

(cherry picked from commit 7e7fec69f6)
This commit is contained in:
Seth Hillbrand 2024-03-21 02:00:42 +01:00
parent 3d4a7c7c3f
commit d2db96886d
3 changed files with 48 additions and 5 deletions

View File

@ -107,6 +107,7 @@ static const wxChar MinimumSegmentLength[] = wxT( "MinimumSegmentLength" );
static const wxChar OcePluginLinearDeflection[] = wxT( "OcePluginLinearDeflection" );
static const wxChar OcePluginAngularDeflection[] = wxT( "OcePluginAngularDeflection" );
static const wxChar TriangulateSimplificationLevel[] = wxT( "TriangulateSimplificationLevel" );
static const wxChar TriangulateMinimumArea[] = wxT( "TriangulateMinimumArea" );
} // namespace KEYS
@ -255,6 +256,7 @@ ADVANCED_CFG::ADVANCED_CFG()
m_OcePluginAngularDeflection = 30;
m_TriangulateSimplificationLevel = 50;
m_TriangulateMinimumArea = 1000;
loadFromConfigFile();
}
@ -464,6 +466,10 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg )
&m_TriangulateSimplificationLevel,
m_TriangulateSimplificationLevel, 0, 1000 ) );
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::TriangulateMinimumArea,
&m_TriangulateMinimumArea,
m_TriangulateMinimumArea, 0, 100000 ) );
// Special case for trace mask setting...we just grab them and set them immediately
// Because we even use wxLogTrace inside of advanced config
wxString traceMasks;

View File

@ -546,6 +546,17 @@ public:
*/
int m_TriangulateSimplificationLevel;
/**
* The minimum area of a polygon that can be left over after triangulation and
* still consider the triangulation successful. This is internal units, so
* it is square nm in pcbnew.
*
* Setting name: "TriangulateMinimumArea"
* Valid values: 0 to 100000
* Default value: 1000
*/
int m_TriangulateMinimumArea;
///@}

View File

@ -50,6 +50,7 @@
#include <deque>
#include <cmath>
#include <advanced_config.h>
#include <clipper.hpp>
#include <geometry/shape_line_chain.h>
#include <geometry/shape_poly_set.h>
@ -93,6 +94,10 @@ public:
else
{
auto retval = earcutList( firstVertex );
if( !retval )
logRemaining();
m_vertices.clear();
return retval;
}
@ -324,7 +329,7 @@ private:
void logRemaining()
{
std::set<VERTEX*> seen;
wxLog::EnableLogging();
for( VERTEX& p : m_vertices )
{
if( !p.next || p.next == &p || seen.find( &p ) != seen.end() )
@ -332,15 +337,27 @@ private:
seen.insert( &p );
wxString msg = wxString::Format( "Remaining: %d,%d,", p.x, p.y );
// Don't both logging tiny areas
if( std::abs( p.area() ) < 10 )
continue;
int count = 1;
wxString msg = wxString::Format( "Remaining: %d,%d,", static_cast<int>( p.x ),
static_cast<int>( p.y ) );
VERTEX* q = p.next;
do
{
msg += wxString::Format( "%d,%d,", q->x, q->y );
msg += wxString::Format( "%d,%d,", static_cast<int>( q->x ),
static_cast<int>( q->y ) );
seen.insert( q );
q = q->next;
} while ( q != &p );
count++;
} while( q != &p );
// Don't log anything that only has 2 or fewer points
if( count < 3 )
continue;
msg.RemoveLast();
wxLogTrace( TRIANGULATE_TRACE, msg );
@ -362,12 +379,18 @@ private:
{
if( *p == *( p->next ) || area( p->prev, p, p->next ) == 0.0 )
{
// This is a spike, remove it, leaving only one point
if( *( p->next ) == *( p->prev ) )
p->next->remove();
p = p->prev;
p->next->remove();
retval = aStart;
if( p == p->next )
break;
continue;
}
p = p->next;
@ -551,7 +574,10 @@ private:
/*
* At this point, our polygon should be fully tessellated.
*/
return( aPoint->prev == aPoint->next );
if( aPoint->prev != aPoint->next )
return std::abs( aPoint->area() > ADVANCED_CFG::GetCfg().m_TriangulateMinimumArea );
return true;
}
/**