7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-18 14:49:18 +00:00

STEP export: handle polygons with arcs (and convert arcs to segments).

Fixes 
https://gitlab.com/kicad/code/kicad/issues/11389
This commit is contained in:
jean-pierre charras 2022-04-14 14:53:13 +02:00
parent 034b57d9c0
commit b154acccdc

View File

@ -2,6 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com> * Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -53,6 +54,7 @@ KICADCURVE::~KICADCURVE()
} }
#include <sexpr/sexpr_parser.h> #include <sexpr/sexpr_parser.h>
#include <geometry/shape_line_chain.h>
bool KICADCURVE::Read( SEXPR::SEXPR* aEntry, CURVE_TYPE aCurveType ) bool KICADCURVE::Read( SEXPR::SEXPR* aEntry, CURVE_TYPE aCurveType )
{ {
@ -60,7 +62,7 @@ bool KICADCURVE::Read( SEXPR::SEXPR* aEntry, CURVE_TYPE aCurveType )
&& CURVE_CIRCLE != aCurveType && CURVE_BEZIER != aCurveType && CURVE_CIRCLE != aCurveType && CURVE_BEZIER != aCurveType
&& CURVE_POLYGON != aCurveType ) && CURVE_POLYGON != aCurveType )
{ {
wxLogMessage( wxT( "* Unsupported curve type: %d\n" ), aCurveType ); wxLogMessage( "* Unsupported curve type: %d\n", aCurveType );
return false; return false;
} }
@ -74,7 +76,7 @@ bool KICADCURVE::Read( SEXPR::SEXPR* aEntry, CURVE_TYPE aCurveType )
|| ( CURVE_BEZIER == aCurveType && nchild < 5 ) || ( CURVE_BEZIER == aCurveType && nchild < 5 )
|| ( CURVE_POLYGON == aCurveType && nchild < 5 ) ) || ( CURVE_POLYGON == aCurveType && nchild < 5 ) )
{ {
wxLogMessage( wxT( "* bad curve data; not enough parameters\n" ) ); wxLogMessage( "* bad curve data; not enough parameters\n" );
return false; return false;
} }
@ -110,6 +112,8 @@ bool KICADCURVE::Read( SEXPR::SEXPR* aEntry, CURVE_TYPE aCurveType )
SEXPR::SEXPR* sub_child = ( *list )[ii]; SEXPR::SEXPR* sub_child = ( *list )[ii];
text = sub_child->GetChild( 0 )->GetSymbol(); text = sub_child->GetChild( 0 )->GetSymbol();
// inside pts list, parmeters are xy point coord
// or a arc (start, middle, end) points
if( text == "xy" ) if( text == "xy" )
{ {
DOUBLET coord; DOUBLET coord;
@ -132,6 +136,49 @@ bool KICADCURVE::Read( SEXPR::SEXPR* aEntry, CURVE_TYPE aCurveType )
else else
m_poly.push_back( coord ); m_poly.push_back( coord );
} }
else if( text == "arc" )
{
int arc_child = sub_child->GetNumberOfChildren();
DOUBLET arc_start, arc_middle, arc_end;
for( int jj = 1; jj < arc_child; jj++ )
{
SEXPR::SEXPR* curr_child = sub_child->GetChild( jj );
text = curr_child->GetChild( 0 )->GetSymbol();
if( text == "start" )
{
if( !Get2DCoordinate( curr_child, arc_start ) )
return false;
}
else if( text == "end" )
{
if( !Get2DCoordinate( curr_child, arc_end ) )
return false;
}
else if( text == "mid" )
{
if( !Get2DCoordinate( curr_child, arc_middle ) )
return false;
}
}
// To convert arc edge to segments, we are using SHAPE_ARC, but SHAPE_ARC use
// integer coords. So to avoid truncations, use a scaling factor.
// 1e5 is enough.
const double scale = 1e5;
SHAPE_ARC new_arc( VECTOR2I( arc_start.x*scale, arc_start.y*scale ),
VECTOR2I( arc_middle.x*scale, arc_middle.y*scale ),
VECTOR2I( arc_end.x*scale, arc_end.y*scale ), 0 );
double accuracy = 0.005*scale; // Approx accuracy is 5 microns
SHAPE_LINE_CHAIN segs_from_arc = new_arc.ConvertToPolyline( accuracy );
// Add segments to STEP polygon
for( int ll = 0; ll < segs_from_arc.PointCount(); ll++ )
m_poly.emplace_back( segs_from_arc.CPoint(ll).x/scale,
segs_from_arc.CPoint(ll).y/scale );
}
} }
} }
else if( text == "start" || text == "center" ) else if( text == "start" || text == "center" )
@ -154,9 +201,10 @@ bool KICADCURVE::Read( SEXPR::SEXPR* aEntry, CURVE_TYPE aCurveType )
else if( text == "angle" ) else if( text == "angle" )
{ {
if( child->GetNumberOfChildren() < 2 if( child->GetNumberOfChildren() < 2
|| ( !child->GetChild( 1 )->IsDouble() && !child->GetChild( 1 )->IsInteger() ) ) || ( !child->GetChild( 1 )->IsDouble()
&& !child->GetChild( 1 )->IsInteger() ) )
{ {
wxLogMessage( wxT( "* bad angle data\n" ) ); wxLogMessage( "* bad angle data\n" );
return false; return false;
} }
@ -175,7 +223,7 @@ bool KICADCURVE::Read( SEXPR::SEXPR* aEntry, CURVE_TYPE aCurveType )
{ {
std::ostringstream ostr; std::ostringstream ostr;
ostr << "* bad layer data: " << child->AsString(); ostr << "* bad layer data: " << child->AsString();
wxLogMessage( wxT( "%s\n" ), ostr.str().c_str() ); wxLogMessage( "%s\n", ostr.str().c_str() );
return false; return false;
} }
@ -205,7 +253,7 @@ bool KICADCURVE::Read( SEXPR::SEXPR* aEntry, CURVE_TYPE aCurveType )
m_end.y = new_arc.GetP0().y/scale; m_end.y = new_arc.GetP0().y/scale;
m_ep.x = new_arc.GetP1().x/scale; m_ep.x = new_arc.GetP1().x/scale;
m_ep.y = new_arc.GetP1().y/scale; m_ep.y = new_arc.GetP1().y/scale;
m_angle = new_arc.GetCentralAngle().AsRadians(); m_angle = new_arc.GetCentralAngle() / 180.0 * M_PI;
} }
return true; return true;