Pcbnew: fix serious issues (broken files) when saving and loading .kicad_pcb files when zones have holes in outlines.

This commit is contained in:
jean-pierre charras 2017-04-07 08:02:26 +02:00
parent ba37d6fca3
commit 70c961fe6a
5 changed files with 55 additions and 26 deletions

View File

@ -819,9 +819,13 @@ void ZONE_CONTAINER::AddPolygon( std::vector< wxPoint >& aPolygon )
outline.SetClosed( true ); outline.SetClosed( true );
// Add the outline as a new polygon in the polygon set // 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 ZONE_CONTAINER::GetSelectMenuText() const
{ {
wxString text; wxString text;

View File

@ -620,8 +620,18 @@ public:
unsigned int GetCornerRadius() const { return m_cornerRadius; }; 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 ); 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 ) void AddFilledPolygon( SHAPE_POLY_SET& aPolygon )
{ {
m_FilledPolysList.Append( aPolygon ); m_FilledPolysList.Append( aPolygon );

View File

@ -1610,11 +1610,20 @@ void PCB_IO::format( ZONE_CONTAINER* aZone, int aNestLevel ) const
if( aZone->GetNumCorners() ) if( aZone->GetNumCorners() )
{ {
m_out->Print( aNestLevel+1, "(polygon\n"); bool new_polygon = true;
m_out->Print( aNestLevel+2, "(pts\n" ); bool is_closed = false;
for( auto iterator = aZone->IterateWithHoles(); iterator; iterator++ ) 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 ) if( newLine == 0 )
m_out->Print( aNestLevel+3, "(xy %s %s)", m_out->Print( aNestLevel+3, "(xy %s %s)",
FMT_IU( iterator->x ).c_str(), FMT_IU( iterator->y ).c_str() ); 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() ) if( iterator.IsEndContour() )
{ {
is_closed = true;
if( newLine != 0 ) if( newLine != 0 )
m_out->Print( 0, "\n" ); m_out->Print( 0, "\n" );
m_out->Print( aNestLevel+2, ")\n" ); m_out->Print( aNestLevel+2, ")\n" );
m_out->Print( aNestLevel+1, ")\n" );
if( !iterator.IsLastPolygon() ) new_polygon = true;
{
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" ); 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(); const SHAPE_POLY_SET& fv = aZone->GetFilledPolysList();
newLine = 0; newLine = 0;
if( !fv.IsEmpty() ) if( !fv.IsEmpty() )
{ {
m_out->Print( aNestLevel+1, "(filled_polygon\n" ); bool new_polygon = true;
m_out->Print( aNestLevel+2, "(pts\n" ); bool is_closed = false;
for( auto it = fv.CIterate(); it; ++it ) 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 ) if( newLine == 0 )
m_out->Print( aNestLevel+3, "(xy %s %s)", m_out->Print( aNestLevel+3, "(xy %s %s)",
FMT_IU( it->x ).c_str(), FMT_IU( it->y ).c_str() ); 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() ) if( it.IsEndContour() )
{ {
is_closed = true;
if( newLine != 0 ) if( newLine != 0 )
m_out->Print( 0, "\n" ); m_out->Print( 0, "\n" );
m_out->Print( aNestLevel+2, ")\n" ); m_out->Print( aNestLevel+2, ")\n" );
m_out->Print( aNestLevel+1, ")\n" );
if( !it.IsLastPolygon() ) new_polygon = true;
{
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" ); if( !is_closed ) // Should not happen, but...
m_out->Print( aNestLevel+1, ")\n" );
} }
// Save the filling segments list // Save the filling segments list

View File

@ -2888,12 +2888,15 @@ ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER() throw( IO_ERROR, PARSE_ERROR )
if( token != T_pts ) if( token != T_pts )
Expecting( 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() ); corners.push_back( parseXY() );
} }
NeedRIGHT(); NeedRIGHT();
// Remark: The first polygon is the main outline.
// Others are holes inside the main outline.
zone->AddPolygon( corners ); zone->AddPolygon( corners );
} }
break; break;

View File

@ -780,7 +780,6 @@ int POINT_EDITOR::addCorner( const TOOL_EVENT& aEvent )
commit.Modify( zone ); commit.Modify( zone );
// Handle the last segment, so other segments can be easily handled in a loop
unsigned int nearestIdx = 0; unsigned int nearestIdx = 0;
unsigned int nextNearestIdx = 0; unsigned int nextNearestIdx = 0;
unsigned int nearestDist = INT_MAX; unsigned int nearestDist = INT_MAX;