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 )
{
std::vector<wxPoint> points;
// If aPoly has holes, convert it to a polygon with no holes.
SHAPE_POLY_SET poly_no_hole;
poly_no_hole.Append( aPoly );
poly_no_hole.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
for( auto iter = poly_no_hole.CIterate(); iter; iter++ )
points.emplace_back( iter->x, iter->y );
AddPrimitivePoly( points, aThickness, aFilled );
PCB_SHAPE* item = new PCB_SHAPE();
item->SetShape( SHAPE_T::POLY );
item->SetFilled( 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 )
{
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.
nestLevel = aNestLevel + 2;
@ -864,11 +864,11 @@ void PCB_IO::format( const PCB_SHAPE* aShape, int aNestLevel ) const
else
{
const SHAPE_ARC& arc = outline.Arc( ind );
m_out->Print( aNestLevel, "%s(arc (start %s) (mid %s) (end %s))",
nestLevel ? "" : " ",
FormatInternalUnits( arc.GetP0() ).c_str(),
FormatInternalUnits( arc.GetArcMid() ).c_str(),
FormatInternalUnits( arc.GetP1() ).c_str() );
m_out->Print( nestLevel, "%s(arc (start %s) (mid %s) (end %s))",
nestLevel ? "" : " ",
FormatInternalUnits( arc.GetP0() ).c_str(),
FormatInternalUnits( arc.GetArcMid() ).c_str(),
FormatInternalUnits( arc.GetP1() ).c_str() );
need_newline = true;
do
@ -973,15 +973,18 @@ void PCB_IO::format( const FP_SHAPE* aFPShape, int aNestLevel ) const
m_out->Print( aNestLevel, "(fp_poly%s (pts",
locked.c_str() );
bool need_newline = false;
for( int ii = 0; ii < outline.PointCount(); ++ii )
{
int nestLevel = 0;
if( ii && ( !( ii%4 ) || !ADVANCED_CFG::GetCfg().m_CompactSave ) )
if( !( ii % 4 ) || !ADVANCED_CFG::GetCfg().m_CompactSave )
{
// newline every 4 pts.
nestLevel = aNestLevel + 1;
m_out->Print( 0, "\n" );
need_newline = false;
nestLevel = aNestLevel + 2;
}
int ind = outline.ArcIndex( ii );
@ -989,16 +992,19 @@ void PCB_IO::format( const FP_SHAPE* aFPShape, int aNestLevel ) const
if( ind < 0 )
{
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
{
auto& arc = outline.Arc( ind );
m_out->Print( aNestLevel, "%s(arc (start %s) (mid %s) (end %s))",
nestLevel ? "" : " ",
FormatInternalUnits( arc.GetP0() ).c_str(),
FormatInternalUnits( arc.GetArcMid() ).c_str(),
FormatInternalUnits( arc.GetP1() ).c_str() );
m_out->Print( nestLevel, "%s(arc (start %s) (mid %s) (end %s))",
nestLevel ? "" : " ",
FormatInternalUnits( arc.GetP0() ).c_str(),
FormatInternalUnits( arc.GetArcMid() ).c_str(),
FormatInternalUnits( arc.GetP1() ).c_str() );
need_newline = true;
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
{
@ -1646,33 +1655,60 @@ void PCB_IO::format( const PAD* aPad, int aNestLevel ) const
break;
case SHAPE_T::POLY:
if( primitive->GetPolyShape().COutline( 0 ).CPoints().size() < 2 )
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( primitive->IsPolyShapeValid() )
{
if( newLine == 0 )
m_out->Print( nested_level+1, "(xy %s)",
FormatInternalUnits( (wxPoint) pt ).c_str() );
else
m_out->Print( 0, " (xy %s)",
FormatInternalUnits( (wxPoint) pt ).c_str() );
const SHAPE_POLY_SET& poly = primitive->GetPolyShape();
const SHAPE_LINE_CHAIN& outline = poly.Outline( 0 );
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;
m_out->Print( 0, "\n" );
}
}
nested_level = 0;
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;
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
{
nestLevel = aNestLevel + 3;
m_out->Print( 0, "\n" );
need_newline = false;
nestLevel = aNestLevel + 3;
}
int ind = chain.ArcIndex( ii );
@ -2106,11 +2142,11 @@ void PCB_IO::format( const ZONE* aZone, int aNestLevel ) const
else
{
auto& arc = chain.Arc( ind );
m_out->Print( aNestLevel, "%s(arc (start %s) (mid %s) (end %s))",
nestLevel ? "" : " ",
FormatInternalUnits( arc.GetP0() ).c_str(),
FormatInternalUnits( arc.GetArcMid() ).c_str(),
FormatInternalUnits( arc.GetP1() ).c_str() );
m_out->Print( nestLevel, "%s(arc (start %s) (mid %s) (end %s))",
nestLevel ? "" : " ",
FormatInternalUnits( arc.GetP0() ).c_str(),
FormatInternalUnits( arc.GetArcMid() ).c_str(),
FormatInternalUnits( arc.GetP1() ).c_str() );
need_newline = true;
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 + 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 ) )
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
{
nestLevel = aNestLevel + 3;
m_out->Print( 0, "\n" );
need_newline = false;
nestLevel = aNestLevel + 3;
}
int ind = chain.ArcIndex( jj );
@ -2174,11 +2210,11 @@ void PCB_IO::format( const ZONE* aZone, int aNestLevel ) const
else
{
auto& arc = chain.Arc( ind );
m_out->Print( aNestLevel, "%s(arc (start %s) (mid %s) (end %s))",
nestLevel ? "" : " ",
FormatInternalUnits( arc.GetP0() ).c_str(),
FormatInternalUnits( arc.GetArcMid() ).c_str(),
FormatInternalUnits( arc.GetP1() ).c_str() );
m_out->Print( nestLevel, "%s(arc (start %s) (mid %s) (end %s))",
nestLevel ? "" : " ",
FormatInternalUnits( arc.GetP0() ).c_str(),
FormatInternalUnits( arc.GetArcMid() ).c_str(),
FormatInternalUnits( arc.GetP1() ).c_str() );
need_newline = true;
do

View File

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