Pcbnew: fix serious issues (broken files) when saving and loading .kicad_pcb files when zones have holes in outlines.
This commit is contained in:
parent
ba37d6fca3
commit
70c961fe6a
|
@ -819,9 +819,13 @@ void ZONE_CONTAINER::AddPolygon( std::vector< wxPoint >& aPolygon )
|
|||
outline.SetClosed( true );
|
||||
|
||||
// Add the outline as a new polygon in the polygon set
|
||||
m_Poly->AddOutline( outline );
|
||||
if( m_Poly->OutlineCount() == 0 )
|
||||
m_Poly->AddOutline( outline );
|
||||
else
|
||||
m_Poly->AddHole( outline );
|
||||
}
|
||||
|
||||
|
||||
wxString ZONE_CONTAINER::GetSelectMenuText() const
|
||||
{
|
||||
wxString text;
|
||||
|
|
|
@ -620,8 +620,18 @@ public:
|
|||
|
||||
unsigned int GetCornerRadius() const { return m_cornerRadius; };
|
||||
|
||||
/**
|
||||
* add a polygon to the zone outline
|
||||
* if the zone outline is empty, this is the main outline
|
||||
* else it is a hole inside the main outline
|
||||
*/
|
||||
void AddPolygon( std::vector< wxPoint >& aPolygon );
|
||||
|
||||
/**
|
||||
* add a polygon to the zone filled areas list.
|
||||
* these polygons have no hole, therefore any added polygon is a new
|
||||
* filled area
|
||||
*/
|
||||
void AddFilledPolygon( SHAPE_POLY_SET& aPolygon )
|
||||
{
|
||||
m_FilledPolysList.Append( aPolygon );
|
||||
|
|
|
@ -1610,11 +1610,20 @@ void PCB_IO::format( ZONE_CONTAINER* aZone, int aNestLevel ) const
|
|||
|
||||
if( aZone->GetNumCorners() )
|
||||
{
|
||||
m_out->Print( aNestLevel+1, "(polygon\n");
|
||||
m_out->Print( aNestLevel+2, "(pts\n" );
|
||||
bool new_polygon = true;
|
||||
bool is_closed = false;
|
||||
|
||||
for( auto iterator = aZone->IterateWithHoles(); iterator; iterator++ )
|
||||
{
|
||||
if( new_polygon )
|
||||
{
|
||||
newLine = 0;
|
||||
m_out->Print( aNestLevel+1, "(polygon\n" );
|
||||
m_out->Print( aNestLevel+2, "(pts\n" );
|
||||
new_polygon = false;
|
||||
is_closed = false;
|
||||
}
|
||||
|
||||
if( newLine == 0 )
|
||||
m_out->Print( aNestLevel+3, "(xy %s %s)",
|
||||
FMT_IU( iterator->x ).c_str(), FMT_IU( iterator->y ).c_str() );
|
||||
|
@ -1634,35 +1643,42 @@ void PCB_IO::format( ZONE_CONTAINER* aZone, int aNestLevel ) const
|
|||
|
||||
if( iterator.IsEndContour() )
|
||||
{
|
||||
is_closed = true;
|
||||
|
||||
if( newLine != 0 )
|
||||
m_out->Print( 0, "\n" );
|
||||
|
||||
m_out->Print( aNestLevel+2, ")\n" );
|
||||
|
||||
if( !iterator.IsLastPolygon() )
|
||||
{
|
||||
newLine = 0;
|
||||
m_out->Print( aNestLevel+1, ")\n" );
|
||||
m_out->Print( aNestLevel+1, "(polygon\n" );
|
||||
m_out->Print( aNestLevel+2, "(pts" );
|
||||
}
|
||||
m_out->Print( aNestLevel+1, ")\n" );
|
||||
new_polygon = true;
|
||||
}
|
||||
}
|
||||
|
||||
m_out->Print( aNestLevel+1, ")\n" );
|
||||
if( !is_closed ) // Should not happen, but...
|
||||
m_out->Print( aNestLevel+1, ")\n" );
|
||||
|
||||
}
|
||||
|
||||
// Save the PolysList
|
||||
// Save the PolysList (filled areas)
|
||||
const SHAPE_POLY_SET& fv = aZone->GetFilledPolysList();
|
||||
newLine = 0;
|
||||
|
||||
if( !fv.IsEmpty() )
|
||||
{
|
||||
m_out->Print( aNestLevel+1, "(filled_polygon\n" );
|
||||
m_out->Print( aNestLevel+2, "(pts\n" );
|
||||
bool new_polygon = true;
|
||||
bool is_closed = false;
|
||||
|
||||
for( auto it = fv.CIterate(); it; ++it )
|
||||
{
|
||||
if( new_polygon )
|
||||
{
|
||||
newLine = 0;
|
||||
m_out->Print( aNestLevel+1, "(filled_polygon\n" );
|
||||
m_out->Print( aNestLevel+2, "(pts\n" );
|
||||
new_polygon = false;
|
||||
is_closed = false;
|
||||
}
|
||||
|
||||
if( newLine == 0 )
|
||||
m_out->Print( aNestLevel+3, "(xy %s %s)",
|
||||
FMT_IU( it->x ).c_str(), FMT_IU( it->y ).c_str() );
|
||||
|
@ -1682,22 +1698,19 @@ void PCB_IO::format( ZONE_CONTAINER* aZone, int aNestLevel ) const
|
|||
|
||||
if( it.IsEndContour() )
|
||||
{
|
||||
is_closed = true;
|
||||
|
||||
if( newLine != 0 )
|
||||
m_out->Print( 0, "\n" );
|
||||
|
||||
m_out->Print( aNestLevel+2, ")\n" );
|
||||
|
||||
if( !it.IsLastPolygon() )
|
||||
{
|
||||
newLine = 0;
|
||||
m_out->Print( aNestLevel+1, ")\n" );
|
||||
m_out->Print( aNestLevel+1, "(filled_polygon\n" );
|
||||
m_out->Print( aNestLevel+2, "(pts\n" );
|
||||
}
|
||||
m_out->Print( aNestLevel+1, ")\n" );
|
||||
new_polygon = true;
|
||||
}
|
||||
}
|
||||
|
||||
m_out->Print( aNestLevel+1, ")\n" );
|
||||
if( !is_closed ) // Should not happen, but...
|
||||
m_out->Print( aNestLevel+1, ")\n" );
|
||||
}
|
||||
|
||||
// Save the filling segments list
|
||||
|
|
|
@ -2888,12 +2888,15 @@ ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER() throw( IO_ERROR, PARSE_ERROR )
|
|||
if( token != T_pts )
|
||||
Expecting( T_pts );
|
||||
|
||||
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
|
||||
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
|
||||
{
|
||||
corners.push_back( parseXY() );
|
||||
}
|
||||
|
||||
NeedRIGHT();
|
||||
|
||||
// Remark: The first polygon is the main outline.
|
||||
// Others are holes inside the main outline.
|
||||
zone->AddPolygon( corners );
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -780,7 +780,6 @@ int POINT_EDITOR::addCorner( const TOOL_EVENT& aEvent )
|
|||
|
||||
commit.Modify( zone );
|
||||
|
||||
// Handle the last segment, so other segments can be easily handled in a loop
|
||||
unsigned int nearestIdx = 0;
|
||||
unsigned int nextNearestIdx = 0;
|
||||
unsigned int nearestDist = INT_MAX;
|
||||
|
|
Loading…
Reference in New Issue