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 );
|
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;
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue