Make sure zones are triangulated for DRC.

Normally this happens as a side-effect of rendering them but if done
from a script (or test case) this won't happen.

Fixes https://gitlab.com/kicad/code/kicad/issues/6635
This commit is contained in:
Jeff Young 2020-12-12 15:14:41 +00:00
parent 7186a0c621
commit bc484784fc
3 changed files with 28 additions and 16 deletions

View File

@ -1609,7 +1609,7 @@ void SHAPE_POLY_SET::Move( const VECTOR2I& aVector )
path.Move( aVector );
}
for( auto& tri : m_triangulatedPolys )
for( std::unique_ptr<TRIANGULATED_POLYGON>& tri : m_triangulatedPolys )
tri->Move( aVector );
m_hash = checksum();
@ -1621,9 +1621,7 @@ void SHAPE_POLY_SET::Mirror( bool aX, bool aY, const VECTOR2I& aRef )
for( POLYGON& poly : m_polys )
{
for( SHAPE_LINE_CHAIN& path : poly )
{
path.Mirror( aX, aY, aRef );
}
}
}
@ -1745,7 +1743,7 @@ SEG::ecoord SHAPE_POLY_SET::SquaredDistance( VECTOR2I aPoint, VECTOR2I* aNearest
{
SEG::ecoord currentDistance_sq;
SEG::ecoord minDistance_sq = VECTOR2I::ECOORD_MAX;
VECTOR2I nearest;
VECTOR2I nearest;
// Iterate through all the polygons and get the minimum distance.
for( unsigned int polygonIdx = 0; polygonIdx < m_polys.size(); polygonIdx++ )
@ -1770,13 +1768,13 @@ SEG::ecoord SHAPE_POLY_SET::SquaredDistance( const SEG& aSegment, VECTOR2I* aNea
{
SEG::ecoord currentDistance_sq;
SEG::ecoord minDistance_sq = VECTOR2I::ECOORD_MAX;
VECTOR2I nearest;
VECTOR2I nearest;
// Iterate through all the polygons and get the minimum distance.
for( unsigned int polygonIdx = 0; polygonIdx < m_polys.size(); polygonIdx++ )
{
currentDistance_sq = SquaredDistanceToPolygon( aSegment, polygonIdx,
aNearest ? &nearest : nullptr );
aNearest ? &nearest : nullptr );
if( currentDistance_sq < minDistance_sq )
{
@ -1997,8 +1995,10 @@ SHAPE_POLY_SET &SHAPE_POLY_SET::operator=( const SHAPE_POLY_SET& aOther )
if( aOther.IsTriangulationUpToDate() )
{
for( unsigned i = 0; i < aOther.TriangulatedPolyCount(); i++ )
m_triangulatedPolys.push_back(
std::make_unique<TRIANGULATED_POLYGON>( *aOther.TriangulatedPolygon( i ) ) );
{
const TRIANGULATED_POLYGON* poly = aOther.TriangulatedPolygon( i );
m_triangulatedPolys.push_back( std::make_unique<TRIANGULATED_POLYGON>( *poly ) );
}
m_hash = aOther.GetHash();
m_triangulationValid = true;
@ -2024,14 +2024,14 @@ bool SHAPE_POLY_SET::IsTriangulationUpToDate() const
if( !m_hash.IsValid() )
return false;
auto hash = checksum();
MD5_HASH hash = checksum();
return hash == m_hash;
}
static void partitionPolyIntoRegularCellGrid(
const SHAPE_POLY_SET& aPoly, int aSize, SHAPE_POLY_SET& aOut )
static void partitionPolyIntoRegularCellGrid( const SHAPE_POLY_SET& aPoly, int aSize,
SHAPE_POLY_SET& aOut )
{
BOX2I bb = aPoly.BBox();
@ -2057,6 +2057,7 @@ static void partitionPolyIntoRegularCellGrid(
SHAPE_POLY_SET ps1( aPoly ), ps2( aPoly ), maskSetOdd, maskSetEven;
for( int yy = 0; yy < n_cells_y; yy++ )
{
for( int xx = 0; xx < n_cells_x; xx++ )
{
VECTOR2I p;
@ -2082,6 +2083,7 @@ static void partitionPolyIntoRegularCellGrid(
else
maskSetEven.AddOutline( mask );
}
}
ps1.BooleanIntersection( maskSetOdd, SHAPE_POLY_SET::PM_FAST );
ps2.BooleanIntersection( maskSetEven, SHAPE_POLY_SET::PM_FAST );
@ -2089,10 +2091,9 @@ static void partitionPolyIntoRegularCellGrid(
ps2.Fracture( SHAPE_POLY_SET::PM_FAST );
aOut = ps1;
for( int i = 0; i < ps2.OutlineCount(); i++ )
{
aOut.AddOutline( ps2.COutline( i ) );
}
if( !aOut.OutlineCount() )
aOut = aPoly;
@ -2124,8 +2125,10 @@ void SHAPE_POLY_SET::CacheTriangulation( bool aPartition )
SHAPE_POLY_SET tmpSet;
if( aPartition )
{
// This partitions into regularly-sized grids (1cm in pcbnew)
partitionPolyIntoRegularCellGrid( *this, 1e7, tmpSet );
}
else
{
tmpSet = *this;

View File

@ -677,12 +677,18 @@ void DRC_ENGINE::RunTests( EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aT
}
for( ZONE* zone : m_board->Zones() )
{
zone->CacheBoundingBox();
zone->CacheTriangulation();
}
for( FOOTPRINT* footprint : m_board->Footprints() )
{
for( ZONE* zone : footprint->Zones() )
{
zone->CacheBoundingBox();
zone->CacheTriangulation();
}
footprint->BuildPolyCourtyards();
}

View File

@ -321,7 +321,8 @@ public:
void SetOutline( SHAPE_POLY_SET* aOutline ) { m_Poly = aOutline; }
// @copydoc BOARD_ITEM::GetEffectiveShape
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override;
virtual std::shared_ptr<SHAPE>
GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override;
/**
* Function HitTest
@ -350,10 +351,10 @@ public:
* @return true if aRefPos is inside a zone cutout
*/
bool HitTestCutout( const VECTOR2I& aRefPos, int* aOutlineIdx = nullptr,
int* aHoleIdx = nullptr ) const;
int* aHoleIdx = nullptr ) const;
bool HitTestCutout( const wxPoint& aRefPos, int* aOutlineIdx = nullptr,
int* aHoleIdx = nullptr ) const
int* aHoleIdx = nullptr ) const
{
return HitTestCutout( VECTOR2I( aRefPos.x, aRefPos.y ), aOutlineIdx, aHoleIdx );
}
@ -587,7 +588,9 @@ public:
}
}
else
{
throw( std::out_of_range( "aCornerIndex-th vertex does not exist" ) );
}
}
/**