Pcbnew: Use a better (i.e. more suitable to calculate clearance areas) algorithm to inflate/deflate zones outlines. It fixes bug#1459734.
Previously, acute angles (especially small angles) in zone outlines create incorrect shapes and sometimes strange shapes for clearance areas, when using generic algorithms. This happens when zones outlines have "spikes", but not usually for smooth outlines.
This commit is contained in:
parent
2500976e31
commit
ba37f33bbb
|
@ -304,8 +304,8 @@ bool ReadSchemaDescr( LINE_READER* aLine, wxString& aMsgDiag, SCH_SCREEN* aScree
|
|||
|
||||
if( !pageInfo.SetType( pagename ) )
|
||||
{
|
||||
aMsgDiag.Printf( _( "Eeschema file dimension definition error \
|
||||
line %d,\nAbort reading file.\n" ),
|
||||
aMsgDiag.Printf( _( "Eeschema file dimension definition error line %d,"
|
||||
"\nAbort reading file.\n" ),
|
||||
aLine->LineNumber() );
|
||||
aMsgDiag << FROM_UTF8( line );
|
||||
}
|
||||
|
|
|
@ -82,8 +82,12 @@ bool ZONE_CONTAINER::BuildFilledSolidAreasPolygons( BOARD* aPcb, CPOLYGONS_LIST*
|
|||
break;
|
||||
|
||||
default:
|
||||
m_smoothedPoly = new CPolyLine;
|
||||
m_smoothedPoly->Copy( m_Poly );
|
||||
// Acute angles between adjacent edges can create issues in calculations,
|
||||
// in inflate/deflate outlines transforms, especially when the angle is very small.
|
||||
// We can avoid issues by creating a very small chamfer which remove acute angles,
|
||||
// or left it without chamfer and use only CPOLYGONS_LIST::InflateOutline to create
|
||||
// clearance areas
|
||||
m_smoothedPoly = m_Poly->Chamfer( Millimeter2iu( 0.0 ) );
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -154,7 +154,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
|
|||
* so m_ZoneMinThickness is the min thickness of the filled zones areas
|
||||
* the main polygon is stored in polyset_zone_solid_areas
|
||||
*/
|
||||
#if 1
|
||||
#if 0
|
||||
m_smoothedPoly->m_CornersList.ExportTo( polyset_zone_solid_areas );
|
||||
|
||||
if( polyset_zone_solid_areas.size() == 0 )
|
||||
|
@ -181,6 +181,9 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
|
|||
CPOLYGONS_LIST tmp;
|
||||
m_smoothedPoly->m_CornersList.InflateOutline( tmp, -outline_half_thickness, true );
|
||||
tmp.ExportTo( polyset_zone_solid_areas );
|
||||
|
||||
if( polyset_zone_solid_areas.size() == 0 )
|
||||
return;
|
||||
#endif
|
||||
|
||||
/* Calculates the clearance value that meet DRC requirements
|
||||
|
|
|
@ -1440,7 +1440,23 @@ void CPOLYGONS_LIST::ImportFrom( ClipperLib::Paths& aPolygons )
|
|||
* aInflateValue = the Inflate value. when < 0, this is a deflate transform
|
||||
* aLinkHoles = if true, aResult contains only one polygon,
|
||||
* with holes linked by overlapping segments
|
||||
*
|
||||
* Important Note:
|
||||
* Inflating a polygon with acute angles or a non convex polygon gives non optimal shapes
|
||||
* for your purposes (creating a clearance area from zones).
|
||||
* So when inflating a polygon, we combine it with a "thick outline"
|
||||
* with a thickness = aInflateValue*2.
|
||||
* the inflated polygon shape is much better to build a polygon
|
||||
* from a polygon + clearance area
|
||||
*
|
||||
* Generic algos (Clipper, Boost Polygon) can inflate polygons, but the result is
|
||||
* not always suitable (they work fine only for polygons with non acute angle)
|
||||
*
|
||||
* To deflate polygons, the same calculation is made, but instead of adding the "thick outline"
|
||||
* we substract it.
|
||||
*/
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
|
||||
void CPOLYGONS_LIST::InflateOutline( CPOLYGONS_LIST& aResult, int aInflateValue, bool aLinkHoles )
|
||||
{
|
||||
KI_POLYGON_SET polyset_outline;
|
||||
|
@ -1456,12 +1472,68 @@ void CPOLYGONS_LIST::InflateOutline( CPOLYGONS_LIST& aResult, int aInflateValue,
|
|||
}
|
||||
|
||||
// inflate main outline
|
||||
unsigned icnt = 0;
|
||||
int width = std::abs( aInflateValue * 2 );
|
||||
|
||||
if( polyset_outline.size() )
|
||||
polyset_outline += aInflateValue;
|
||||
{
|
||||
CPOLYGONS_LIST outlines;
|
||||
|
||||
for( ; icnt < GetCornersCount(); icnt++ )
|
||||
{
|
||||
unsigned ii = icnt+1;
|
||||
|
||||
if( IsEndContour( icnt ) )
|
||||
ii = 0;
|
||||
|
||||
TransformRoundedEndsSegmentToPolygon( outlines,
|
||||
GetPos( icnt ), GetPos( ii ), 16, width );
|
||||
|
||||
if( IsEndContour( icnt ) )
|
||||
break;
|
||||
}
|
||||
|
||||
KI_POLYGON_SET thicklines;
|
||||
outlines.ExportTo( thicklines );
|
||||
|
||||
if( aInflateValue > 0 ) // Inflate main outline
|
||||
polyset_outline += thicklines;
|
||||
else if( aInflateValue < 0 ) // Actually a deflate transform
|
||||
polyset_outline -= thicklines; // deflate main outline
|
||||
|
||||
}
|
||||
|
||||
// deflate outline holes
|
||||
if( outlineHoles.size() )
|
||||
outlineHoles -= aInflateValue;
|
||||
{
|
||||
int deflateValue = -aInflateValue;
|
||||
|
||||
CPOLYGONS_LIST outlines;
|
||||
icnt += 1; // points the first point of the first hole
|
||||
unsigned firstpoint = icnt;
|
||||
|
||||
for( ; icnt < GetCornersCount(); icnt++ )
|
||||
{
|
||||
unsigned ii = icnt+1;
|
||||
|
||||
if( IsEndContour( icnt ) || ii >= GetCornersCount() )
|
||||
{
|
||||
ii = firstpoint;
|
||||
firstpoint = icnt+1;
|
||||
}
|
||||
|
||||
TransformRoundedEndsSegmentToPolygon( outlines,
|
||||
GetPos( icnt ), GetPos( ii ), 16, width );
|
||||
}
|
||||
|
||||
KI_POLYGON_SET thicklines;
|
||||
outlines.ExportTo( thicklines );
|
||||
|
||||
if( deflateValue > 0 ) // Inflate holes
|
||||
outlineHoles += thicklines;
|
||||
else if( deflateValue < 0 ) // deflate holes
|
||||
outlineHoles -= thicklines;
|
||||
}
|
||||
|
||||
// Copy modified polygons
|
||||
if( !aLinkHoles )
|
||||
|
@ -1478,6 +1550,7 @@ void CPOLYGONS_LIST::InflateOutline( CPOLYGONS_LIST& aResult, int aInflateValue,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function ConvertPolysListWithHolesToOnePolygon
|
||||
* converts the outline contours aPolysListWithHoles with holes to one polygon
|
||||
|
|
Loading…
Reference in New Issue