Beware of infinite recursion on colliding hatched shapes.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/20264
This commit is contained in:
Jeff Young
2025-03-08 21:23:14 +00:00
parent ab6ee168cf
commit 50174ec528
10 changed files with 52 additions and 20 deletions
@@ -656,7 +656,7 @@ void BOARD_ADAPTER::addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aConta
{
SHAPE_POLY_SET polyList;
aShape->TransformShapeToPolygon( polyList, UNDEFINED_LAYER, 0, ARC_HIGH_DEF,
aShape->TransformShapeToPolySet( polyList, UNDEFINED_LAYER, 0, ARC_HIGH_DEF,
ERROR_INSIDE );
polyList.Simplify();
+11 -9
View File
@@ -97,7 +97,7 @@ void transformFPShapesToPolySet( const FOOTPRINT* aFootprint, PCB_LAYER_ID aLaye
if( item->Type() == PCB_SHAPE_T || BaseType( item->Type() ) == PCB_DIMENSION_T )
{
if( item->GetLayer() == aLayer )
item->TransformShapeToPolygon( aBuffer, aLayer, 0, aMaxError, aErrorLoc );
item->TransformShapeToPolySet( aBuffer, aLayer, 0, aMaxError, aErrorLoc );
}
}
}
@@ -716,20 +716,22 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
{
PCB_TEXTBOX* text_box = static_cast<PCB_TEXTBOX*>( item );
text_box->TransformTextToPolySet( *platedCopperPolys,
0, maxError, ERROR_INSIDE );
0, maxError, ERROR_INSIDE );
// Add box outlines
text_box->PCB_SHAPE::TransformShapeToPolygon( *platedCopperPolys, layer,
0, maxError, ERROR_INSIDE );
}
else if( item->Type() == PCB_TEXT_T )
{
static_cast<PCB_TEXT*>( item )->TransformTextToPolySet(
*platedCopperPolys,
0, maxError, ERROR_INSIDE );
static_cast<PCB_TEXT*>( item )->TransformTextToPolySet( *platedCopperPolys,
0, maxError,
ERROR_INSIDE );
}
else
item->TransformShapeToPolygon( *platedCopperPolys, layer,
0, maxError, ERROR_INSIDE );
{
item->TransformShapeToPolySet( *platedCopperPolys, layer,
0, maxError, ERROR_INSIDE );
}
}
}
}
@@ -753,7 +755,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
switch( item->Type() )
{
case PCB_SHAPE_T:
item->TransformShapeToPolygon( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
item->TransformShapeToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
break;
case PCB_TEXT_T:
@@ -1026,7 +1028,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
switch( item->Type() )
{
case PCB_SHAPE_T:
item->TransformShapeToPolygon( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
item->TransformShapeToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
break;
case PCB_TEXT_T:
+3 -2
View File
@@ -2083,7 +2083,8 @@ int EDA_SHAPE::Compare( const EDA_SHAPE* aOther ) const
void EDA_SHAPE::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, int aClearance, int aError,
ERROR_LOC aErrorLoc, bool ignoreLineWidth ) const
ERROR_LOC aErrorLoc, bool ignoreLineWidth,
bool includeFill ) const
{
int width = ignoreLineWidth ? 0 : GetWidth();
@@ -2200,7 +2201,7 @@ void EDA_SHAPE::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, int aClearance
break;
}
if( IsHatchedFill() )
if( IsHatchedFill() && includeFill )
{
for( int ii = 0; ii < GetHatching().OutlineCount(); ++ii )
aBuffer.AddOutline( GetHatching().COutline( ii ) );
+17
View File
@@ -416,6 +416,23 @@ public:
int aClearance, int aError, ERROR_LOC aErrorLoc,
bool ignoreLineWidth = false ) const;
/**
* Convert the item shape to a polyset. Circles and arcs are approximated by segments; hatched
* fills will be included.
*
* @param aBuffer a buffer to store the polygon.
* @param aClearance the clearance around the pad.
* @param aError the maximum deviation from true circle.
* @param aErrorLoc should the approximation error be placed outside or inside the polygon?
* @param ignoreLineWidth used for edge cut items where the line width is only
* for visualization.
*/
virtual void TransformShapeToPolySet( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer,
int aClearance, int aError, ERROR_LOC aErrorLoc ) const
{
TransformShapeToPolygon( aBuffer, aLayer, aClearance, aError, aErrorLoc );
}
enum COMPARE_FLAGS : int
{
DRC = 0x01
+2 -1
View File
@@ -415,7 +415,8 @@ public:
* visualization
*/
void TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, int aClearance, int aError,
ERROR_LOC aErrorLoc, bool ignoreLineWidth = false ) const;
ERROR_LOC aErrorLoc, bool ignoreLineWidth = false,
bool includeFill = false ) const;
int Compare( const EDA_SHAPE* aOther ) const;
+1 -1
View File
@@ -519,7 +519,7 @@ bool EXPORTER_STEP::buildGraphic3DShape( BOARD_ITEM* aItem, VECTOR2D aOrigin )
return true;
}
graphic->TransformShapeToPolygon( m_poly_shapes[pcblayer], pcblayer, 0, maxError,
graphic->TransformShapeToPolySet( m_poly_shapes[pcblayer], pcblayer, 0, maxError,
ERROR_INSIDE );
break;
+3 -3
View File
@@ -3944,10 +3944,10 @@ void FOOTPRINT::TransformFPShapesToPolySet( SHAPE_POLY_SET& aBuffer, PCB_LAYER_I
if( item->Type() == PCB_SHAPE_T && aIncludeShapes )
{
const PCB_SHAPE* outline = static_cast<PCB_SHAPE*>( item );
const PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( item );
if( aLayer != UNDEFINED_LAYER && outline->GetLayer() == aLayer )
outline->TransformShapeToPolygon( aBuffer, aLayer, 0, aError, aErrorLoc );
if( aLayer != UNDEFINED_LAYER && shape->GetLayer() == aLayer )
shape->TransformShapeToPolySet( aBuffer, aLayer, 0, aError, aErrorLoc );
}
}
+9 -1
View File
@@ -838,7 +838,15 @@ void PCB_SHAPE::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID a
int aClearance, int aError, ERROR_LOC aErrorLoc,
bool ignoreLineWidth ) const
{
EDA_SHAPE::TransformShapeToPolygon( aBuffer, aClearance, aError, aErrorLoc, ignoreLineWidth );
EDA_SHAPE::TransformShapeToPolygon( aBuffer, aClearance, aError, aErrorLoc, ignoreLineWidth,
false );
}
void PCB_SHAPE::TransformShapeToPolySet( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer,
int aClearance, int aError, ERROR_LOC aErrorLoc ) const
{
EDA_SHAPE::TransformShapeToPolygon( aBuffer, aClearance, aError, aErrorLoc, false, true );
}
+3
View File
@@ -161,6 +161,9 @@ public:
int aError, ERROR_LOC aErrorLoc,
bool ignoreLineWidth = false ) const override;
void TransformShapeToPolySet( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance,
int aError, ERROR_LOC aErrorLoc ) const override;
wxString GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const override;
BITMAPS GetMenuImage() const override;
+2 -2
View File
@@ -1006,9 +1006,9 @@ void GenerateLayerPoly( SHAPE_POLY_SET* aResult, BOARD *aBoard, PCB_LAYER_ID aLa
else
{
if( inflate != 0 )
item->TransformShapeToPolygon( exactPolys, aLayer, 0, ERROR );
item->TransformShapeToPolySet( exactPolys, aLayer, 0, ERROR );
item->TransformShapeToPolygon( *aResult, aLayer, inflate, ERROR );
item->TransformShapeToPolySet( *aResult, aLayer, inflate, ERROR );
}
}
}