pcbnew: Allow curves in custom pads

Updates custom pad functions to permit adding arbitrary curves to the
primitives
This commit is contained in:
Seth Hillbrand 2019-04-14 10:58:35 -07:00
parent b56ca3f09c
commit f7c042a357
15 changed files with 269 additions and 23 deletions

View File

@ -259,10 +259,26 @@ void UNIT_BINDER::Enable( bool aEnable )
}
void UNIT_BINDER::Show( bool aShow )
void UNIT_BINDER::Show( bool aShow, bool aResize )
{
m_label->Show( aShow );
m_value->Show( aShow );
m_unitLabel->Show( aShow );
if( aResize )
{
if( aShow )
{
m_label->SetSize( -1, -1 );
m_value->SetSize( -1, -1 );
m_unitLabel->SetSize( -1, -1 );
}
else
{
m_label->SetSize( 0, 0 );
m_value->SetSize( 0, 0 );
m_unitLabel->SetSize( 0, 0 );
}
}
}

View File

@ -115,8 +115,11 @@ public:
/**
* Function Show
* Shows/hides the label, widget and units label.
*
* @param aShow called for the Show() routine in wx
* @param aResize if true, the element will be sized to 0 on hide and -1 on show
*/
void Show( bool aShow );
void Show( bool aShow, bool aResize = false );
protected:

View File

@ -64,11 +64,13 @@ DRAWSEGMENT::~DRAWSEGMENT()
{
}
void DRAWSEGMENT::SetPosition( const wxPoint& aPos )
{
m_Start = aPos;
}
const wxPoint DRAWSEGMENT::GetPosition() const
{
if( m_Shape == S_POLYGON )
@ -77,6 +79,28 @@ const wxPoint DRAWSEGMENT::GetPosition() const
return m_Start;
}
double DRAWSEGMENT::GetLength() const
{
double length = 0.0;
switch( m_Shape )
{
case S_CURVE:
for( size_t ii = 1; ii < m_BezierPoints.size(); ++ii )
length += GetLineLength( m_BezierPoints[ii - 1], m_BezierPoints[ii] );
break;
default:
length = GetLineLength( GetStart(), GetEnd() );
break;
}
return length;
}
void DRAWSEGMENT::Move( const wxPoint& aMoveVector )
{
m_Start += aMoveVector;
@ -148,6 +172,7 @@ void DRAWSEGMENT::Rotate( const wxPoint& aRotCentre, double aAngle )
}
}
void DRAWSEGMENT::Flip( const wxPoint& aCentre )
{
m_Start.y = aCentre.y - (m_Start.y - aCentre.y);
@ -234,6 +259,7 @@ const wxPoint DRAWSEGMENT::GetCenter() const
return c;
}
const wxPoint DRAWSEGMENT::GetArcEnd() const
{
wxPoint endPoint( m_End ); // start of arc
@ -255,6 +281,7 @@ const wxPoint DRAWSEGMENT::GetArcEnd() const
return endPoint; // after rotation, the end of the arc.
}
const wxPoint DRAWSEGMENT::GetArcMid() const
{
wxPoint endPoint( m_End );
@ -276,6 +303,7 @@ const wxPoint DRAWSEGMENT::GetArcMid() const
return endPoint; // after rotation, the end of the arc.
}
double DRAWSEGMENT::GetArcAngleStart() const
{
// due to the Y axis orient atan2 needs - y value
@ -454,6 +482,7 @@ void DRAWSEGMENT::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, GR_DRAWMODE draw_mode,
}
}
void DRAWSEGMENT::GetMsgPanelInfo( EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM >& aList )
{
wxString msg;
@ -484,6 +513,9 @@ void DRAWSEGMENT::GetMsgPanelInfo( EDA_UNITS_T aUnits, std::vector< MSG_PANEL_IT
case S_CURVE:
aList.push_back( MSG_PANEL_ITEM( shape, _( "Curve" ), RED ) );
msg = MessageTextFromValue( aUnits, GetLength() );
aList.push_back( MSG_PANEL_ITEM( _( "Length" ), msg, DARKGREEN ) );
break;
default:
@ -931,6 +963,7 @@ void DRAWSEGMENT::computeArcBBox( EDA_RECT& aBBox ) const
}
}
void DRAWSEGMENT::SetPolyPoints( const std::vector<wxPoint>& aPoints )
{
m_Poly.RemoveAllContours();

View File

@ -231,10 +231,7 @@ public:
* returns the length of the track using the hypotenuse calculation.
* @return double - the length of the track
*/
double GetLength() const
{
return GetLineLength( GetStart(), GetEnd() );
}
double GetLength() const;
virtual void Move( const wxPoint& aMoveVector ) override;

View File

@ -99,6 +99,8 @@ public:
double m_ArcAngle; /// angle of an arc, from its starting point, in 0.1 deg
wxPoint m_Start; /// is also the center of the circle and arc
wxPoint m_End; /// is also the start point of the arc
wxPoint m_Ctrl1; /// Bezier Control point 1
wxPoint m_Ctrl2; /// Bezier Control point 2
std::vector<wxPoint> m_Poly;
PAD_CS_PRIMITIVE( STROKE_T aShape ):
@ -285,6 +287,7 @@ public:
* a thick segment
* a filled circle or ring ( if thickness == 0, this is a filled circle, else a ring)
* a arc
* a curve
*/
void AddPrimitive( const SHAPE_POLY_SET& aPoly, int aThickness ); ///< add a polygonal basic shape
void AddPrimitive( const std::vector<wxPoint>& aPoly, int aThickness ); ///< add a polygonal basic shape
@ -292,6 +295,8 @@ public:
void AddPrimitive( wxPoint aCenter, int aRadius, int aThickness ); ///< ring or circle basic shape
void AddPrimitive( wxPoint aCenter, wxPoint aStart,
int aArcAngle, int aThickness ); ///< arc basic shape
void AddPrimitive( wxPoint aStart, wxPoint aEnd, wxPoint aCtrl1,
wxPoint aCtrl2, int aThickness ); ///< curve basic shape
bool GetBestAnchorPosition( VECTOR2I& aPos );

View File

@ -51,6 +51,10 @@ DIALOG_PAD_PRIMITIVES_PROPERTIES::DIALOG_PAD_PRIMITIVES_PROPERTIES( wxWindow* aP
m_shape( aShape ),
m_startX( aFrame, m_startXLabel, m_startXCtrl, m_startXUnits, true ),
m_startY( aFrame, m_startYLabel, m_startYCtrl, m_startYUnits, true ),
m_ctrl1X( aFrame, m_ctrl1XLabel, m_ctrl1XCtrl, m_ctrl1XUnits, true ),
m_ctrl1Y( aFrame, m_ctrl1YLabel, m_ctrl1YCtrl, m_ctrl1YUnits, true ),
m_ctrl2X( aFrame, m_ctrl2XLabel, m_ctrl2XCtrl, m_ctrl2XUnits, true ),
m_ctrl2Y( aFrame, m_ctrl2YLabel, m_ctrl2YCtrl, m_ctrl2YUnits, true ),
m_endX( aFrame, m_endXLabel, m_endXCtrl, m_endXUnits, true ),
m_endY( aFrame, m_endYLabel, m_endYCtrl, m_endYUnits, true ),
m_radius( aFrame, m_radiusLabel, m_radiusCtrl, m_radiusUnits, true ),
@ -58,6 +62,8 @@ DIALOG_PAD_PRIMITIVES_PROPERTIES::DIALOG_PAD_PRIMITIVES_PROPERTIES( wxWindow* aP
{
SetInitialFocus( m_startXCtrl );
TransferDataToWindow();
m_sdbSizerOK->SetDefault();
FinishDialogSettings();
@ -82,6 +88,27 @@ bool DIALOG_PAD_PRIMITIVES_PROPERTIES::TransferDataToWindow()
m_startY.SetValue( m_shape->m_Start.y );
m_endX.SetValue( m_shape->m_End.x );
m_endY.SetValue( m_shape->m_End.y );
m_ctrl1X.Show( false, true );
m_ctrl1Y.Show( false, true );
m_ctrl2X.Show( false, true );
m_ctrl2Y.Show( false, true );
m_staticTextPosCtrl1->Show( false );
m_staticTextPosCtrl1->SetSize( 0, 0 );
m_staticTextPosCtrl2->Show( false );
m_staticTextPosCtrl2->SetSize( 0, 0 );
m_radius.Show( false );
break;
case S_CURVE: // Bezier line
SetTitle( _( "Bezier" ) );
m_startX.SetValue( m_shape->m_Start.x );
m_startY.SetValue( m_shape->m_Start.y );
m_endX.SetValue( m_shape->m_End.x );
m_endY.SetValue( m_shape->m_End.y );
m_ctrl1X.SetValue( m_shape->m_Ctrl1.x );
m_ctrl1Y.SetValue( m_shape->m_Ctrl1.y );
m_ctrl2X.SetValue( m_shape->m_Ctrl2.x );
m_ctrl2Y.SetValue( m_shape->m_Ctrl2.y );
m_radius.Show( false );
break;
@ -95,6 +122,14 @@ bool DIALOG_PAD_PRIMITIVES_PROPERTIES::TransferDataToWindow()
m_radiusLabel->SetLabel( _( "Angle:" ) );
m_radius.SetUnits( DEGREES );
m_radius.SetValue( m_shape->m_ArcAngle );
m_ctrl1X.Show( false, true );
m_ctrl1Y.Show( false, true );
m_ctrl2X.Show( false, true );
m_ctrl2Y.Show( false, true );
m_staticTextPosCtrl1->Show( false );
m_staticTextPosCtrl1->SetSize( 0, 0 );
m_staticTextPosCtrl2->Show( false );
m_staticTextPosCtrl2->SetSize( 0, 0 );
break;
case S_CIRCLE: // ring or circle
@ -113,6 +148,14 @@ bool DIALOG_PAD_PRIMITIVES_PROPERTIES::TransferDataToWindow()
m_startX.SetValue( m_shape->m_Start.x );
m_startY.SetValue( m_shape->m_Start.y );
m_radius.SetValue( m_shape->m_Radius );
m_ctrl1X.Show( false, true );
m_ctrl1Y.Show( false, true );
m_ctrl2X.Show( false, true );
m_ctrl2Y.Show( false, true );
m_staticTextPosCtrl1->Show( false );
m_staticTextPosCtrl1->SetSize( 0, 0 );
m_staticTextPosCtrl2->Show( false );
m_staticTextPosCtrl2->SetSize( 0, 0 );
break;
case S_POLYGON: // polygon
@ -141,6 +184,17 @@ bool DIALOG_PAD_PRIMITIVES_PROPERTIES::TransferDataFromWindow()
m_shape->m_End.y = m_endY.GetValue();
break;
case S_CURVE: // Segment with rounded ends
m_shape->m_Start.x = m_startX.GetValue();
m_shape->m_Start.y = m_startY.GetValue();
m_shape->m_End.x = m_endX.GetValue();
m_shape->m_End.y = m_endY.GetValue();
m_shape->m_Ctrl1.x = m_ctrl1X.GetValue();
m_shape->m_Ctrl1.y = m_ctrl1Y.GetValue();
m_shape->m_Ctrl2.x = m_ctrl2X.GetValue();
m_shape->m_Ctrl2.y = m_ctrl2Y.GetValue();
break;
case S_ARC: // Arc with rounded ends
// Start point of arc
m_shape->m_Start.x = m_startX.GetValue();
@ -194,6 +248,9 @@ DIALOG_PAD_PRIMITIVE_POLY_PROPS::DIALOG_PAD_PRIMITIVE_POLY_PROPS( wxWindow* aPar
// TODO: move wxEVT_GRID_CELL_CHANGING in wxFormbuilder, when it support it
m_gridCornersList->Connect( wxEVT_GRID_CELL_CHANGING, wxGridEventHandler( DIALOG_PAD_PRIMITIVE_POLY_PROPS::onCellChanging ), NULL, this );
// Now all widgets have the size fixed, call FinishDialogSettings
FinishDialogSettings();
}
@ -535,7 +592,7 @@ inline void geom_transf( wxPoint& aCoord, wxPoint& aMove, double aScale, double
void DIALOG_PAD_PRIMITIVES_TRANSFORM::Transform( std::vector<PAD_CS_PRIMITIVE>* aList, int aDuplicateCount )
{
wxPoint move_vect( m_vectorX.GetValue(), m_vectorY.GetValue() );
double rotation = m_rotation.GetValue() / 10.0;
double rotation = m_rotation.GetValue();
double scale = DoubleValueFromString( UNSCALED_UNITS, m_scaleCtrl->GetValue() );
// Avoid too small / too large scale, which could create issues:
@ -581,6 +638,11 @@ void DIALOG_PAD_PRIMITIVES_TRANSFORM::Transform( std::vector<PAD_CS_PRIMITIVE>*
case S_ARC: // Arc with rounded ends
break;
case S_CURVE: // Bezier with rounded ends
geom_transf( shape->m_Ctrl1, currMoveVect, scale, curr_rotation );
geom_transf( shape->m_Ctrl2, currMoveVect, scale, curr_rotation );
break;
case S_CIRCLE: // ring or circle
shape->m_Radius = KiROUND( shape->m_Radius * scale );
break;

View File

@ -843,6 +843,12 @@ void DIALOG_PAD_PROPERTIES::displayPrimitivesList()
bs_info[2] = _( "to " ) + formatCoord( m_units, primitive.m_End );
break;
case S_CURVE: // Bezier segment
bs_info[0] = _( "Bezier" );
bs_info[1] = _( "from " ) + formatCoord( m_units, primitive.m_Start );
bs_info[2] = _( "to " ) + formatCoord( m_units, primitive.m_End );
break;
case S_ARC: // Arc with rounded ends
bs_info[0] = _( "Arc" );
bs_info[1] = _( "center " ) + formatCoord( m_units, primitive.m_Start );// Center
@ -1355,11 +1361,12 @@ void DIALOG_PAD_PROPERTIES::redraw()
dummySegment->Rotate( wxPoint( 0, 0), m_dummyPad->GetOrientation() );
dummySegment->Move( m_dummyPad->GetPosition() );
// Update selected primitive (highligth selected)
// Update selected primitive (highlight selected)
switch( primitive.m_Shape )
{
case S_SEGMENT:
case S_ARC:
case S_CURVE:
break;
case S_CIRCLE: // ring or circle
@ -1368,7 +1375,7 @@ void DIALOG_PAD_PROPERTIES::redraw()
// but it is easy to create it with a circle having the
// right radius and outline width
wxPoint end = dummySegment->GetCenter();
end.x += primitive.m_Radius/2;
end.x += primitive.m_Radius / 2;
dummySegment->SetEnd( end );
dummySegment->SetWidth( primitive.m_Radius );
}
@ -1399,7 +1406,7 @@ void DIALOG_PAD_PROPERTIES::redraw()
// gives a size to the full drawable area
BOX2I drawbox;
drawbox.Move( m_dummyPad->GetPosition() );
drawbox.Inflate( bbox.GetSize().x*2, bbox.GetSize().y*2 );
drawbox.Inflate( bbox.GetSize().x * 2, bbox.GetSize().y * 2 );
view->SetBoundary( drawbox );
@ -1987,14 +1994,20 @@ void DIALOG_PAD_PROPERTIES::onDeletePrimitive( wxCommandEvent& event )
void DIALOG_PAD_PROPERTIES::onAddPrimitive( wxCommandEvent& event )
{
// Ask user for shape type
wxString shapelist[] = { _( "Segment" ), _( "Arc" ), _( "Ring/Circle" ), _( "Polygon" ) };
wxString shapelist[] = { _( "Segment" ), _( "Arc" ), _( "Bezier" ),
_( "Ring/Circle" ), _( "Polygon" ) };
int type = wxGetSingleChoiceIndex( _( "Shape type:" ), _( "Add Primitive" ),
arrayDim( shapelist ), shapelist, 0, this );
STROKE_T listtype[] = { S_SEGMENT, S_ARC, S_CIRCLE, S_POLYGON };
// User pressed cancel
if( type == -1 )
return;
STROKE_T listtype[] = { S_SEGMENT, S_ARC, S_CURVE, S_CIRCLE, S_POLYGON };
PAD_CS_PRIMITIVE primitive( listtype[type] );
primitive.m_Thickness = m_board->GetDesignSettings().GetLineThickness( F_Cu );
if( listtype[type] == S_POLYGON )
{

View File

@ -191,6 +191,10 @@ private:
UNIT_BINDER m_startX;
UNIT_BINDER m_startY;
UNIT_BINDER m_ctrl1X;
UNIT_BINDER m_ctrl1Y;
UNIT_BINDER m_ctrl2X;
UNIT_BINDER m_ctrl2Y;
UNIT_BINDER m_endX;
UNIT_BINDER m_endY;
UNIT_BINDER m_radius;

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Dec 1 2018)
// C++ code generated with wxFormBuilder (version Jan 17 2019)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -890,6 +890,58 @@ DIALOG_PAD_PRIMITIVES_PROPERTIES_BASE::DIALOG_PAD_PRIMITIVES_PROPERTIES_BASE( wx
m_startYUnits->Wrap( -1 );
fgSizerShapeProperties->Add( m_startYUnits, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
m_staticTextPosCtrl1 = new wxStaticText( this, wxID_ANY, _("Control Point 1"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextPosCtrl1->Wrap( -1 );
fgSizerShapeProperties->Add( m_staticTextPosCtrl1, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
m_ctrl1XLabel = new wxStaticText( this, wxID_ANY, _("X:"), wxDefaultPosition, wxDefaultSize, 0 );
m_ctrl1XLabel->Wrap( -1 );
fgSizerShapeProperties->Add( m_ctrl1XLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxLEFT, 5 );
m_ctrl1XCtrl = new TEXT_CTRL_EVAL( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgSizerShapeProperties->Add( m_ctrl1XCtrl, 0, wxALL, 5 );
m_ctrl1XUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
m_ctrl1XUnits->Wrap( -1 );
fgSizerShapeProperties->Add( m_ctrl1XUnits, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
m_ctrl1YLabel = new wxStaticText( this, wxID_ANY, _("Y:"), wxDefaultPosition, wxDefaultSize, 0 );
m_ctrl1YLabel->Wrap( -1 );
fgSizerShapeProperties->Add( m_ctrl1YLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxLEFT, 5 );
m_ctrl1YCtrl = new TEXT_CTRL_EVAL( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgSizerShapeProperties->Add( m_ctrl1YCtrl, 0, wxALL, 5 );
m_ctrl1YUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
m_ctrl1YUnits->Wrap( -1 );
fgSizerShapeProperties->Add( m_ctrl1YUnits, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
m_staticTextPosCtrl2 = new wxStaticText( this, wxID_ANY, _("Control Point 2"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextPosCtrl2->Wrap( -1 );
fgSizerShapeProperties->Add( m_staticTextPosCtrl2, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
m_ctrl2XLabel = new wxStaticText( this, wxID_ANY, _("X:"), wxDefaultPosition, wxDefaultSize, 0 );
m_ctrl2XLabel->Wrap( -1 );
fgSizerShapeProperties->Add( m_ctrl2XLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxLEFT, 5 );
m_ctrl2XCtrl = new TEXT_CTRL_EVAL( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgSizerShapeProperties->Add( m_ctrl2XCtrl, 0, wxALL, 5 );
m_ctrl2XUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
m_ctrl2XUnits->Wrap( -1 );
fgSizerShapeProperties->Add( m_ctrl2XUnits, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
m_ctrl2YLabel = new wxStaticText( this, wxID_ANY, _("Y:"), wxDefaultPosition, wxDefaultSize, 0 );
m_ctrl2YLabel->Wrap( -1 );
fgSizerShapeProperties->Add( m_ctrl2YLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxLEFT, 5 );
m_ctrl2YCtrl = new TEXT_CTRL_EVAL( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgSizerShapeProperties->Add( m_ctrl2YCtrl, 0, wxALL, 5 );
m_ctrl2YUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
m_ctrl2YUnits->Wrap( -1 );
fgSizerShapeProperties->Add( m_ctrl2YUnits, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
m_staticTextPosEnd = new wxStaticText( this, wxID_ANY, _("End point"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextPosEnd->Wrap( -1 );
fgSizerShapeProperties->Add( m_staticTextPosEnd, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Dec 1 2018)
// C++ code generated with wxFormBuilder (version Jan 17 2019)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -239,6 +239,20 @@ class DIALOG_PAD_PRIMITIVES_PROPERTIES_BASE : public DIALOG_SHIM
wxStaticText* m_startYLabel;
TEXT_CTRL_EVAL* m_startYCtrl;
wxStaticText* m_startYUnits;
wxStaticText* m_staticTextPosCtrl1;
wxStaticText* m_ctrl1XLabel;
TEXT_CTRL_EVAL* m_ctrl1XCtrl;
wxStaticText* m_ctrl1XUnits;
wxStaticText* m_ctrl1YLabel;
TEXT_CTRL_EVAL* m_ctrl1YCtrl;
wxStaticText* m_ctrl1YUnits;
wxStaticText* m_staticTextPosCtrl2;
wxStaticText* m_ctrl2XLabel;
TEXT_CTRL_EVAL* m_ctrl2XCtrl;
wxStaticText* m_ctrl2XUnits;
wxStaticText* m_ctrl2YLabel;
TEXT_CTRL_EVAL* m_ctrl2YCtrl;
wxStaticText* m_ctrl2YUnits;
wxStaticText* m_staticTextPosEnd;
wxStaticText* m_endXLabel;
TEXT_CTRL_EVAL* m_endXCtrl;

View File

@ -1441,6 +1441,15 @@ void PCB_IO::format( D_PAD* aPad, int aNestLevel ) const
FormatInternalUnits( primitive.m_Thickness ).c_str() );
break;
case S_CURVE: // Bezier Curve
m_out->Print( aNestLevel, "(gr_curve (pts (xy %s) (xy %s) (xy %s) (xy %s)) (width %s))",
FormatInternalUnits( primitive.m_Start ).c_str(),
FormatInternalUnits( primitive.m_Ctrl1 ).c_str(),
FormatInternalUnits( primitive.m_Ctrl2 ).c_str(),
FormatInternalUnits( primitive.m_End ).c_str(),
FormatInternalUnits( primitive.m_Thickness ).c_str() );
break;
case S_POLYGON: // polygon
if( primitive.m_Poly.size() < 2 )
break; // Malformed polygon.

View File

@ -48,7 +48,8 @@ class NETINFO_MAPPING;
//#define SEXPR_BOARD_FILE_VERSION 20171114 // Save 3D model offset in mm, instead of inches
//#define SEXPR_BOARD_FILE_VERSION 20171125 // Locked/unlocked TEXTE_MODULE
//#define SEXPR_BOARD_FILE_VERSION 20171130 // 3D model offset written using "offset" parameter
#define SEXPR_BOARD_FILE_VERSION 20190331 // hatched zones and chamfered round rect pads
//#define SEXPR_BOARD_FILE_VERSION 20190331 // hatched zones and chamfered round rect pads
#define SEXPR_BOARD_FILE_VERSION 20190421 // curves in custom pads
#define CTL_STD_LAYER_NAMES (1 << 0) ///< Use English Standard layer names
#define CTL_OMIT_NETS (1 << 1) ///< Omit pads net names (useless in library)

View File

@ -38,6 +38,8 @@
#include <convert_basic_shapes_to_polygon.h>
#include <geometry/shape_rect.h>
#include <geometry/convex_hull.h>
#include <geometry/geometry_utils.h>
#include <bezier_curves.h>
void PAD_CS_PRIMITIVE::ExportTo( DRAWSEGMENT* aTarget )
@ -46,6 +48,8 @@ void PAD_CS_PRIMITIVE::ExportTo( DRAWSEGMENT* aTarget )
aTarget->SetWidth( m_Thickness );
aTarget->SetStart( m_Start );
aTarget->SetEnd( m_End );
aTarget->SetBezControl1( m_Ctrl1 );
aTarget->SetBezControl2( m_Ctrl2 );
// in a DRAWSEGMENT the radius of a circle is calculated from the
// center and one point on the circle outline (stored in m_End)
@ -73,6 +77,8 @@ void PAD_CS_PRIMITIVE::Move( wxPoint aMoveVector )
{
m_Start += aMoveVector;
m_End += aMoveVector;
m_Ctrl1 += aMoveVector;
m_Ctrl2 += aMoveVector;
for( auto& corner : m_Poly )
{
@ -138,6 +144,20 @@ void D_PAD::AddPrimitive( wxPoint aCenter, wxPoint aStart, int aArcAngle, int aT
}
void D_PAD::AddPrimitive( wxPoint aStart, wxPoint aEnd, wxPoint aCtrl1, wxPoint aCtrl2, int aThickness )
{
PAD_CS_PRIMITIVE shape( S_CURVE );
shape.m_Start = aStart;
shape.m_End = aEnd;
shape.m_Ctrl1 = aCtrl1;
shape.m_Ctrl2 = aCtrl2;
shape.m_Thickness = aThickness;
m_basicShapes.push_back( shape );
MergePrimitivesAsPolygon();
}
void D_PAD::AddPrimitive( wxPoint aCenter, int aRadius, int aThickness )
{
PAD_CS_PRIMITIVE shape( S_CIRCLE );
@ -192,6 +212,21 @@ bool D_PAD::buildCustomPadPolygon( SHAPE_POLY_SET* aMergedPolygon,
switch( bshape.m_Shape )
{
case S_CURVE:
{
std::vector<wxPoint> ctrlPoints = { bshape.m_Start, bshape.m_Ctrl1, bshape.m_Ctrl2, bshape.m_End };
BEZIER_POLY converter( ctrlPoints );
std::vector< wxPoint> poly;
converter.GetPoly( poly, bshape.m_Thickness );
for( unsigned ii = 1; ii < poly.size(); ii++ )
{
TransformRoundedEndsSegmentToPolygon( aux_polyset,
poly[ii-1], poly[ii], aCircleToSegmentsCount, bshape.m_Thickness );
}
break;
}
case S_SEGMENT: // usual segment : line with rounded ends
TransformRoundedEndsSegmentToPolygon( aux_polyset,
bshape.m_Start, bshape.m_End, aCircleToSegmentsCount, bshape.m_Thickness );

View File

@ -2792,8 +2792,15 @@ D_PAD* PCB_PARSER::parseD_PAD( MODULE* aParent )
pad->AddPrimitive( dummysegm->BuildPolyPointsList(), dummysegm->GetWidth() );
break;
case T_gr_curve:
dummysegm = parseDRAWSEGMENT();
pad->AddPrimitive( dummysegm->GetStart(), dummysegm->GetEnd(),
dummysegm->GetBezControl1(), dummysegm->GetBezControl2(),
dummysegm->GetWidth() );
break;
default:
Expecting( "gr_line, gr_arc, gr_circle or gr_poly" );
Expecting( "gr_line, gr_arc, gr_circle, gr_curve or gr_poly" );
break;
}

View File

@ -410,19 +410,14 @@ int MODULE_EDITOR_TOOLS::CreatePadFromShapes( const TOOL_EVENT& aEvent )
{
auto em = static_cast<EDGE_MODULE*> ( item );
// Currently, S_CURVE shape is not supported. so warn the user
if( em->GetShape() == S_CURVE )
{
illegalItemsFound = true;
break;
}
PAD_CS_PRIMITIVE shape( em->GetShape() );
shape.m_Start = em->GetStart();
shape.m_End = em->GetEnd();
shape.m_Radius = em->GetRadius();
shape.m_Thickness = em->GetWidth();
shape.m_ArcAngle = em->GetAngle();
shape.m_Ctrl1 = em->GetBezControl1();
shape.m_Ctrl2 = em->GetBezControl2();
shape.m_Poly = em->BuildPolyPointsList();
shapes.push_back(shape);