Attempt to support Bezier curves in STEP export. First code.

The bezier curves are in this code replaced by a segm between
the 2 ends curves
This commit is contained in:
jean-pierre charras 2020-10-20 14:28:43 +02:00
parent 07f5428951
commit 12b106aba4
5 changed files with 113 additions and 23 deletions

View File

@ -47,7 +47,8 @@ enum CURVE_TYPE
CURVE_NONE = 0, // invalid curve
CURVE_LINE,
CURVE_ARC,
CURVE_CIRCLE
CURVE_CIRCLE,
CURVE_BEZIER
};
/*

View File

@ -50,14 +50,14 @@ KICADCURVE::~KICADCURVE()
return;
}
#include <sexpr/sexpr_parser.h>
bool KICADCURVE::Read( SEXPR::SEXPR* aEntry, CURVE_TYPE aCurveType )
{
if( CURVE_LINE != aCurveType && CURVE_ARC != aCurveType && CURVE_CIRCLE != aCurveType )
if( CURVE_LINE != aCurveType && CURVE_ARC != aCurveType
&& CURVE_CIRCLE != aCurveType && CURVE_BEZIER != aCurveType )
{
std::ostringstream ostr;
ostr << "* Unsupported curve type: " << aCurveType;
wxLogMessage( "%s\n", ostr.str().c_str() );
wxLogMessage( "* Unsupported curve type: %d\n", aCurveType );
return false;
}
@ -67,11 +67,10 @@ bool KICADCURVE::Read( SEXPR::SEXPR* aEntry, CURVE_TYPE aCurveType )
if( ( CURVE_CIRCLE == aCurveType && nchild < 5 )
|| ( CURVE_ARC == aCurveType && nchild < 6 )
|| ( CURVE_LINE == aCurveType && nchild < 5 ) )
|| ( CURVE_LINE == aCurveType && nchild < 5 )
|| ( CURVE_BEZIER == aCurveType && nchild < 5 ) )
{
std::ostringstream ostr;
ostr << "* bad curve data; not enough parameters";
wxLogMessage( "%s\n", ostr.str().c_str() );
wxLogMessage( "* bad curve data; not enough parameters\n" );
return false;
}
@ -87,7 +86,45 @@ bool KICADCURVE::Read( SEXPR::SEXPR* aEntry, CURVE_TYPE aCurveType )
text = child->GetChild( 0 )->GetSymbol();
if( text == "start" || text == "center" )
if( text == "pts" )
{
// Parse and extract the list of xy coordinates
SEXPR::PARSER parser;
std::unique_ptr<SEXPR::SEXPR> prms = parser.Parse( child->AsString() );
// We need 4 XY parametres (and "pts" that is the firast parameter)
if( prms->GetNumberOfChildren() != 5 )
return false;
// Extract xy coordintes from pts list
SEXPR::SEXPR_VECTOR const* list = prms->GetChildren();
int ii = 0;
// The first parameter is "pts", so skip it.
for( std::vector<SEXPR::SEXPR*>::const_iterator it = list->begin()+1;
it != list->end(); ++it, ++ii )
{
SEXPR::SEXPR* sub_child = (*it);
text = sub_child->GetChild( 0 )->GetSymbol();
if( text == "xy" )
{
DOUBLET coord;
if( !Get2DCoordinate( sub_child, coord ) )
return false;
switch( ii )
{
case 0: m_start = coord; break;
case 1: m_bezierctrl1 = coord; break;
case 2: m_bezierctrl2 = coord; break;
case 3: m_end = coord; break;
}
}
}
}
else if( text == "start" || text == "center" )
{
if( !Get2DCoordinate( child, m_start ) )
return false;
@ -103,9 +140,7 @@ bool KICADCURVE::Read( SEXPR::SEXPR* aEntry, CURVE_TYPE aCurveType )
|| ( !child->GetChild( 1 )->IsDouble()
&& !child->GetChild( 1 )->IsInteger() ) )
{
std::ostringstream ostr;
ostr << "* bad angle data";
wxLogMessage( "%s\n", ostr.str().c_str() );
wxLogMessage( "* bad angle data\n" );
return false;
}
@ -158,6 +193,11 @@ std::string KICADCURVE::Describe() const
desc << "circle center: " << m_start << " radius: " << m_radius;
break;
case CURVE_BEZIER:
desc << "bezier start: " << m_start << " end: " << m_end
<< " ctrl1: " << m_bezierctrl1 << " ctrl2: " << m_bezierctrl2 ;
break;
default:
desc << "<invalid curve type>";
break;

View File

@ -50,13 +50,15 @@ public:
///> Returns human-readable description of the curve.
std::string Describe() const;
CURVE_TYPE m_form; // form of curve: line, arc, circle
LAYERS m_layer; // layer of the glyph
DOUBLET m_start; // start point of line or center for arc and circle
DOUBLET m_end; // end point of line, first point on arc or circle
DOUBLET m_ep; // actual endpoint, to be computed in the case of arcs
double m_radius;// radius; to be computed in the case of arcs and circles
double m_angle; // subtended angle of arc
CURVE_TYPE m_form; // form of curve: line, arc, circle
LAYERS m_layer; // layer of the glyph
DOUBLET m_start; // start point of line or center for arc and circle
DOUBLET m_end; // end point of line, first point on arc or circle
DOUBLET m_ep; // actual endpoint, to be computed in the case of arcs
DOUBLET m_bezierctrl1; // for bezier curve only first control point
DOUBLET m_bezierctrl2; // for bezier curve only second control point
double m_radius; // radius; to be computed in the case of arcs and circles
double m_angle; // subtended angle of arc
double m_startangle;
double m_endangle;
};

View File

@ -230,6 +230,8 @@ bool KICADPCB::parsePCB( SEXPR::SEXPR* data )
result = result && parseRect( child );
else if( symname == "gr_circle" )
result = result && parseCurve( child, CURVE_CIRCLE );
else if( symname == "gr_curve" )
result = result && parseCurve( child, CURVE_BEZIER );
}
return result;

View File

@ -136,12 +136,19 @@ static void reverseCurve( KICADCURVE& aCurve )
if( CURVE_NONE == aCurve.m_form || CURVE_CIRCLE == aCurve.m_form )
return;
if( CURVE_LINE == aCurve.m_form )
if( CURVE_LINE == aCurve.m_form )
{
std::swap( aCurve.m_start, aCurve.m_end );
return;
}
if( CURVE_BEZIER == aCurve.m_form )
{
std::swap( aCurve.m_start, aCurve.m_end );
std::swap( aCurve.m_bezierctrl1, aCurve.m_bezierctrl2 );
return;
}
std::swap( aCurve.m_end, aCurve.m_ep );
std::swap( aCurve.m_endangle, aCurve.m_startangle );
aCurve.m_angle = -aCurve.m_angle;
@ -259,7 +266,7 @@ bool PCBMODEL::AddOutlineSegment( KICADCURVE* aCurve )
if( NULL == aCurve || LAYER_EDGE != aCurve->m_layer || CURVE_NONE == aCurve->m_form )
return false;
if( CURVE_LINE == aCurve->m_form )
if( CURVE_LINE == aCurve->m_form || CURVE_BEZIER == aCurve->m_form )
{
// reject zero - length lines
double dx = aCurve->m_end.x - aCurve->m_start.x;
@ -419,12 +426,27 @@ bool PCBMODEL::AddOutlineSegment( KICADCURVE* aCurve )
break;
case CURVE_BEZIER:
if( aCurve->m_start.x < m_minx )
{
m_minx = aCurve->m_start.x;
m_mincurve = --(m_curves.end());
}
if( aCurve->m_end.x < m_minx )
{
m_minx = aCurve->m_end.x;
m_mincurve = --(m_curves.end());
}
break;
default:
// unexpected curve type
do
{
wxString msg;
msg.Printf( " * AddOutlineSegment() unsupported curve type: %s\n",
msg.Printf( " * AddOutlineSegment() unsupported curve type: %d\n",
aCurve->m_form );
ReportMessage( msg );
} while( 0 );
@ -1528,6 +1550,7 @@ bool OUTLINE::MakeShape( TopoDS_Shape& aShape, double aThickness )
return true;
}
#include <Geom_BezierCurve.hxx>
bool OUTLINE::addEdge( BRepBuilderAPI_MakeWire* aWire, KICADCURVE& aCurve, DOUBLET& aLastPoint )
{
@ -1562,6 +1585,28 @@ bool OUTLINE::addEdge( BRepBuilderAPI_MakeWire* aWire, KICADCURVE& aCurve, DOUBL
gp_Dir( 0.0, 0.0, 1.0 ) ), aCurve.m_radius ) );
break;
case CURVE_BEZIER:
{
#if 0 // TODO: this code is not working. so fix it or replace the curve by a set of segments
TColgp_Array1OfPnt poles(0, 3);
gp_Pnt pt = gp_Pnt( aCurve.m_start.x, aCurve.m_start.y, 0.0 );
poles(0) = pt;
pt = gp_Pnt( aCurve.m_bezierctrl1.x, aCurve.m_bezierctrl1.y, 0.0 );
poles(1) = pt;
pt = gp_Pnt( aCurve.m_bezierctrl2.x, aCurve.m_bezierctrl2.y, 0.0 );
poles(2) = pt;
pt = gp_Pnt( endPoint.x, endPoint.y, 0.0 );
poles(3) = pt;
Geom_BezierCurve* bezier_curve = new Geom_BezierCurve( poles );
edge = BRepBuilderAPI_MakeEdge( bezier_curve );
#else // Generate a segment between ends
edge = BRepBuilderAPI_MakeEdge( gp_Pnt( aLastPoint.x, aLastPoint.y, 0.0 ),
gp_Pnt( endPoint.x, endPoint.y, 0.0 ) );
#endif
}
break;
default:
ReportMessage( wxString::Format( "unsupported curve type: %d\n", aCurve.m_form ) );
return false;