Add writing of pad primitive polys with arcs, and fix a bug in reading.

Fixes https://gitlab.com/kicad/code/kicad/issues/8827
This commit is contained in:
Jeff Young 2021-08-01 01:14:02 +01:00
parent b1fd462d28
commit 0f5a8f87d3
3 changed files with 97 additions and 59 deletions

View File

@ -39,17 +39,19 @@
void PAD::AddPrimitivePoly( const SHAPE_POLY_SET& aPoly, int aThickness, bool aFilled ) void PAD::AddPrimitivePoly( const SHAPE_POLY_SET& aPoly, int aThickness, bool aFilled )
{ {
std::vector<wxPoint> points;
// If aPoly has holes, convert it to a polygon with no holes. // If aPoly has holes, convert it to a polygon with no holes.
SHAPE_POLY_SET poly_no_hole; SHAPE_POLY_SET poly_no_hole;
poly_no_hole.Append( aPoly ); poly_no_hole.Append( aPoly );
poly_no_hole.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); poly_no_hole.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
for( auto iter = poly_no_hole.CIterate(); iter; iter++ ) PCB_SHAPE* item = new PCB_SHAPE();
points.emplace_back( iter->x, iter->y ); item->SetShape( SHAPE_T::POLY );
item->SetFilled( aFilled );
AddPrimitivePoly( points, aThickness, aFilled ); item->SetPolyShape( poly_no_hole );
item->SetWidth( aThickness );
item->SetParent( this );
m_editPrimitives.emplace_back( item );
SetDirty();
} }

View File

@ -842,9 +842,9 @@ void PCB_IO::format( const PCB_SHAPE* aShape, int aNestLevel ) const
for( int ii = 0; ii < outline.PointCount(); ++ii ) for( int ii = 0; ii < outline.PointCount(); ++ii )
{ {
int nestLevel = ii == 0 ? aNestLevel + 2 : 0; int nestLevel = 0;
if( ii && ( !( ii % 4 ) || !ADVANCED_CFG::GetCfg().m_CompactSave ) ) if( !( ii % 4 ) || !ADVANCED_CFG::GetCfg().m_CompactSave )
{ {
// newline every 4 pts. // newline every 4 pts.
nestLevel = aNestLevel + 2; nestLevel = aNestLevel + 2;
@ -864,11 +864,11 @@ void PCB_IO::format( const PCB_SHAPE* aShape, int aNestLevel ) const
else else
{ {
const SHAPE_ARC& arc = outline.Arc( ind ); const SHAPE_ARC& arc = outline.Arc( ind );
m_out->Print( aNestLevel, "%s(arc (start %s) (mid %s) (end %s))", m_out->Print( nestLevel, "%s(arc (start %s) (mid %s) (end %s))",
nestLevel ? "" : " ", nestLevel ? "" : " ",
FormatInternalUnits( arc.GetP0() ).c_str(), FormatInternalUnits( arc.GetP0() ).c_str(),
FormatInternalUnits( arc.GetArcMid() ).c_str(), FormatInternalUnits( arc.GetArcMid() ).c_str(),
FormatInternalUnits( arc.GetP1() ).c_str() ); FormatInternalUnits( arc.GetP1() ).c_str() );
need_newline = true; need_newline = true;
do do
@ -973,15 +973,18 @@ void PCB_IO::format( const FP_SHAPE* aFPShape, int aNestLevel ) const
m_out->Print( aNestLevel, "(fp_poly%s (pts", m_out->Print( aNestLevel, "(fp_poly%s (pts",
locked.c_str() ); locked.c_str() );
bool need_newline = false;
for( int ii = 0; ii < outline.PointCount(); ++ii ) for( int ii = 0; ii < outline.PointCount(); ++ii )
{ {
int nestLevel = 0; int nestLevel = 0;
if( ii && ( !( ii%4 ) || !ADVANCED_CFG::GetCfg().m_CompactSave ) ) if( !( ii % 4 ) || !ADVANCED_CFG::GetCfg().m_CompactSave )
{ {
// newline every 4 pts. // newline every 4 pts.
nestLevel = aNestLevel + 1;
m_out->Print( 0, "\n" ); m_out->Print( 0, "\n" );
need_newline = false;
nestLevel = aNestLevel + 2;
} }
int ind = outline.ArcIndex( ii ); int ind = outline.ArcIndex( ii );
@ -989,16 +992,19 @@ void PCB_IO::format( const FP_SHAPE* aFPShape, int aNestLevel ) const
if( ind < 0 ) if( ind < 0 )
{ {
m_out->Print( nestLevel, "%s(xy %s)", m_out->Print( nestLevel, "%s(xy %s)",
nestLevel ? "" : " ", FormatInternalUnits( outline.CPoint( ii ) ).c_str() ); nestLevel ? "" : " ",
FormatInternalUnits( outline.CPoint( ii ) ).c_str() );
need_newline = true;
} }
else else
{ {
auto& arc = outline.Arc( ind ); auto& arc = outline.Arc( ind );
m_out->Print( aNestLevel, "%s(arc (start %s) (mid %s) (end %s))", m_out->Print( nestLevel, "%s(arc (start %s) (mid %s) (end %s))",
nestLevel ? "" : " ", nestLevel ? "" : " ",
FormatInternalUnits( arc.GetP0() ).c_str(), FormatInternalUnits( arc.GetP0() ).c_str(),
FormatInternalUnits( arc.GetArcMid() ).c_str(), FormatInternalUnits( arc.GetArcMid() ).c_str(),
FormatInternalUnits( arc.GetP1() ).c_str() ); FormatInternalUnits( arc.GetP1() ).c_str() );
need_newline = true;
do do
{ {
@ -1009,7 +1015,10 @@ void PCB_IO::format( const FP_SHAPE* aFPShape, int aNestLevel ) const
} }
} }
m_out->Print( 0, ")" ); if( need_newline )
m_out->Print( 0, "\n" );
m_out->Print( aNestLevel + 1, ")" );
} }
else else
{ {
@ -1646,33 +1655,60 @@ void PCB_IO::format( const PAD* aPad, int aNestLevel ) const
break; break;
case SHAPE_T::POLY: case SHAPE_T::POLY:
if( primitive->GetPolyShape().COutline( 0 ).CPoints().size() < 2 ) if( primitive->IsPolyShapeValid() )
break; // Malformed polygon.
{
m_out->Print( nested_level, "(gr_poly (pts\n");
// Write the polygon corners coordinates:
int newLine = 0;
for( const VECTOR2I &pt : primitive->GetPolyShape().COutline( 0 ).CPoints() )
{ {
if( newLine == 0 ) const SHAPE_POLY_SET& poly = primitive->GetPolyShape();
m_out->Print( nested_level+1, "(xy %s)", const SHAPE_LINE_CHAIN& outline = poly.Outline( 0 );
FormatInternalUnits( (wxPoint) pt ).c_str() );
else
m_out->Print( 0, " (xy %s)",
FormatInternalUnits( (wxPoint) pt ).c_str() );
if( ++newLine > 4 || !ADVANCED_CFG::GetCfg().m_CompactSave ) m_out->Print( nested_level, "(gr_poly (pts" );
bool need_newline = false;
for( int ii = 0; ii < outline.PointCount(); ++ii )
{ {
newLine = 0; nested_level = 0;
m_out->Print( 0, "\n" );
}
}
m_out->Print( newLine ? 0 : nested_level, ")" ); if( !( ii % 4 ) || !ADVANCED_CFG::GetCfg().m_CompactSave )
} {
// newline every 4 pts.
m_out->Print( 0, "\n" );
need_newline = false;
nested_level = aNestLevel + 4;
}
int ind = outline.ArcIndex( ii );
if( ind < 0 )
{
m_out->Print( nested_level, "%s(xy %s)",
nested_level ? "" : " ",
FormatInternalUnits( outline.CPoint( ii ) ).c_str() );
need_newline = true;
}
else
{
const SHAPE_ARC& arc = outline.Arc( ind );
m_out->Print( nested_level, "%s(arc (start %s) (mid %s) (end %s))",
nested_level ? "" : " ",
FormatInternalUnits( arc.GetP0() ).c_str(),
FormatInternalUnits( arc.GetArcMid() ).c_str(),
FormatInternalUnits( arc.GetP1() ).c_str() );
need_newline = true;
do
{
++ii;
} while( ii < outline.PointCount() && outline.ArcIndex( ii ) == ind );
--ii;
}
}
if( need_newline )
m_out->Print( 0, "\n" );
m_out->Print( aNestLevel + 3, ")" );
}
break; break;
default: default:
@ -2089,9 +2125,9 @@ void PCB_IO::format( const ZONE* aZone, int aNestLevel ) const
if( !( ii % 4 ) || !ADVANCED_CFG::GetCfg().m_CompactSave ) // newline every 4 pts if( !( ii % 4 ) || !ADVANCED_CFG::GetCfg().m_CompactSave ) // newline every 4 pts
{ {
nestLevel = aNestLevel + 3;
m_out->Print( 0, "\n" ); m_out->Print( 0, "\n" );
need_newline = false; need_newline = false;
nestLevel = aNestLevel + 3;
} }
int ind = chain.ArcIndex( ii ); int ind = chain.ArcIndex( ii );
@ -2106,11 +2142,11 @@ void PCB_IO::format( const ZONE* aZone, int aNestLevel ) const
else else
{ {
auto& arc = chain.Arc( ind ); auto& arc = chain.Arc( ind );
m_out->Print( aNestLevel, "%s(arc (start %s) (mid %s) (end %s))", m_out->Print( nestLevel, "%s(arc (start %s) (mid %s) (end %s))",
nestLevel ? "" : " ", nestLevel ? "" : " ",
FormatInternalUnits( arc.GetP0() ).c_str(), FormatInternalUnits( arc.GetP0() ).c_str(),
FormatInternalUnits( arc.GetArcMid() ).c_str(), FormatInternalUnits( arc.GetArcMid() ).c_str(),
FormatInternalUnits( arc.GetP1() ).c_str() ); FormatInternalUnits( arc.GetP1() ).c_str() );
need_newline = true; need_newline = true;
do do
@ -2140,7 +2176,7 @@ void PCB_IO::format( const ZONE* aZone, int aNestLevel ) const
{ {
m_out->Print( aNestLevel + 1, "(filled_polygon\n" ); m_out->Print( aNestLevel + 1, "(filled_polygon\n" );
m_out->Print( aNestLevel + 2, "(layer %s)\n", m_out->Print( aNestLevel + 2, "(layer %s)\n",
m_out->Quotew( LSET::Name( layer ) ).c_str() ); m_out->Quotew( LSET::Name( layer ) ).c_str() );
if( aZone->IsIsland( layer, ii ) ) if( aZone->IsIsland( layer, ii ) )
m_out->Print( aNestLevel + 2, "(island)\n" ); m_out->Print( aNestLevel + 2, "(island)\n" );
@ -2157,9 +2193,9 @@ void PCB_IO::format( const ZONE* aZone, int aNestLevel ) const
if( !( jj%4 ) || !ADVANCED_CFG::GetCfg().m_CompactSave ) // newline every 4 pts if( !( jj%4 ) || !ADVANCED_CFG::GetCfg().m_CompactSave ) // newline every 4 pts
{ {
nestLevel = aNestLevel + 3;
m_out->Print( 0, "\n" ); m_out->Print( 0, "\n" );
need_newline = false; need_newline = false;
nestLevel = aNestLevel + 3;
} }
int ind = chain.ArcIndex( jj ); int ind = chain.ArcIndex( jj );
@ -2174,11 +2210,11 @@ void PCB_IO::format( const ZONE* aZone, int aNestLevel ) const
else else
{ {
auto& arc = chain.Arc( ind ); auto& arc = chain.Arc( ind );
m_out->Print( aNestLevel, "%s(arc (start %s) (mid %s) (end %s))", m_out->Print( nestLevel, "%s(arc (start %s) (mid %s) (end %s))",
nestLevel ? "" : " ", nestLevel ? "" : " ",
FormatInternalUnits( arc.GetP0() ).c_str(), FormatInternalUnits( arc.GetP0() ).c_str(),
FormatInternalUnits( arc.GetArcMid() ).c_str(), FormatInternalUnits( arc.GetArcMid() ).c_str(),
FormatInternalUnits( arc.GetP1() ).c_str() ); FormatInternalUnits( arc.GetP1() ).c_str() );
need_newline = true; need_newline = true;
do do

View File

@ -4334,7 +4334,7 @@ PAD* PCB_PARSER::parsePAD( FOOTPRINT* aParent )
case T_gr_poly: case T_gr_poly:
dummyShape = parsePCB_SHAPE(); dummyShape = parsePCB_SHAPE();
pad->AddPrimitivePoly( dummyShape->BuildPolyPointsList(), dummyShape->GetWidth(), pad->AddPrimitivePoly( dummyShape->GetPolyShape(), dummyShape->GetWidth(),
dummyShape->IsFilled() ); dummyShape->IsFilled() );
break; break;