Flatten CS_PAD_PRIMITIVE out in favour of reusing DRAWSEGMENT.
(In prep for the eventual replacement of DRAWSEGMENT internals with SHAPE.)
This commit is contained in:
parent
5ee806c3a3
commit
e376750f62
|
@ -131,6 +131,52 @@ void DRAWSEGMENT::Move( const wxPoint& aMoveVector )
|
|||
}
|
||||
|
||||
|
||||
void DRAWSEGMENT::Scale( double aScale )
|
||||
{
|
||||
auto scalePt = [&]( wxPoint& pt )
|
||||
{
|
||||
pt.x = KiROUND( pt.x * aScale );
|
||||
pt.y = KiROUND( pt.y * aScale );
|
||||
};
|
||||
|
||||
int radius = GetRadius();
|
||||
|
||||
scalePt( m_Start );
|
||||
scalePt( m_End );
|
||||
|
||||
// specific parameters:
|
||||
switch( m_Shape )
|
||||
{
|
||||
case S_CURVE:
|
||||
scalePt( m_BezierC1 );
|
||||
scalePt( m_BezierC2 );
|
||||
break;
|
||||
|
||||
case S_CIRCLE: // ring or circle
|
||||
m_End.x = m_Start.x + KiROUND( radius * aScale );
|
||||
m_End.y = m_Start.y;
|
||||
break;
|
||||
|
||||
case S_POLYGON: // polygon
|
||||
{
|
||||
std::vector<wxPoint> pts;
|
||||
|
||||
for( const VECTOR2I& pt : m_Poly.Outline( 0 ).CPoints() )
|
||||
{
|
||||
pts.emplace_back( pt );
|
||||
scalePt( pts.back() );
|
||||
}
|
||||
|
||||
SetPolyPoints( pts );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DRAWSEGMENT::Rotate( const wxPoint& aRotCentre, double aAngle )
|
||||
{
|
||||
switch( m_Shape )
|
||||
|
@ -138,12 +184,30 @@ void DRAWSEGMENT::Rotate( const wxPoint& aRotCentre, double aAngle )
|
|||
case S_ARC:
|
||||
case S_SEGMENT:
|
||||
case S_CIRCLE:
|
||||
case S_RECT:
|
||||
// these can all be done by just rotating the start and end points
|
||||
RotatePoint( &m_Start, aRotCentre, aAngle);
|
||||
RotatePoint( &m_End, aRotCentre, aAngle);
|
||||
break;
|
||||
|
||||
case S_RECT:
|
||||
if( KiROUND( aAngle ) % 900 == 0 )
|
||||
{
|
||||
RotatePoint( &m_Start, aRotCentre, aAngle );
|
||||
RotatePoint( &m_End, aRotCentre, aAngle );
|
||||
break;
|
||||
}
|
||||
|
||||
// Convert non-cartesian-rotated rect to a diamond
|
||||
m_Shape = S_POLYGON;
|
||||
m_Poly.RemoveAllContours();
|
||||
m_Poly.NewOutline();
|
||||
m_Poly.Append( m_Start );
|
||||
m_Poly.Append( m_End.x, m_Start.y );
|
||||
m_Poly.Append( m_End );
|
||||
m_Poly.Append( m_Start.x, m_End.y );
|
||||
|
||||
KI_FALLTHROUGH;
|
||||
|
||||
case S_POLYGON:
|
||||
m_Poly.Rotate( -DECIDEG2RAD( aAngle ), VECTOR2I( aRotCentre ) );
|
||||
break;
|
||||
|
|
|
@ -262,6 +262,8 @@ public:
|
|||
|
||||
virtual void Flip( const wxPoint& aCentre, bool aFlipLeftRight ) override;
|
||||
|
||||
void Scale( double aScale );
|
||||
|
||||
/**
|
||||
* Function TransformShapeWithClearanceToPolygon
|
||||
* Convert the draw segment to a closed polygon
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include <view/view.h>
|
||||
#include <class_board.h>
|
||||
#include <class_module.h>
|
||||
#include <class_drawsegment.h>
|
||||
#include <geometry/polygon_test_point_inside.h>
|
||||
#include <convert_to_biu.h>
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
|
@ -309,24 +310,11 @@ void D_PAD::buildEffectiveShapes() const
|
|||
|
||||
if( GetShape() == PAD_SHAPE_CUSTOM )
|
||||
{
|
||||
#if 1
|
||||
// For now we add these in as a single SHAPE_POLY_SET, but once we've moved them
|
||||
// over to shapes themselves then we can just copy them across (with the requisite
|
||||
// rotating and offsetting).
|
||||
SHAPE_POLY_SET* poly = new SHAPE_POLY_SET();
|
||||
MergePrimitivesAsPolygon( poly );
|
||||
poly->Rotate( -DECIDEG2RAD( m_Orient ) );
|
||||
poly->Move( shapePos );
|
||||
add( poly );
|
||||
#else
|
||||
for( const std::shared_ptr<SHAPE>& primitive : m_basicShapes )
|
||||
{
|
||||
SHAPE* copy = primitive->Clone();
|
||||
copy->Rotate( -DECIDEG2RAD( m_Orient ) );
|
||||
copy->Move( shapePos );
|
||||
add( copy );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Bounding radius
|
||||
|
@ -458,24 +446,8 @@ void D_PAD::Flip( const wxPoint& aCentre, bool aFlipLeftRight )
|
|||
// Flip the basic shapes, in custom pads
|
||||
void D_PAD::FlipPrimitives()
|
||||
{
|
||||
// Flip custom shapes
|
||||
for( PAD_CS_PRIMITIVE& primitive : m_basicShapes )
|
||||
{
|
||||
MIRROR( primitive.m_Start.y, 0 );
|
||||
MIRROR( primitive.m_End.y, 0 );
|
||||
primitive.m_ArcAngle = -primitive.m_ArcAngle;
|
||||
|
||||
switch( primitive.m_Shape )
|
||||
{
|
||||
case S_POLYGON:
|
||||
for( wxPoint& pt : primitive.m_Poly )
|
||||
MIRROR( pt.y, 0 );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
for( std::shared_ptr<DRAWSEGMENT>& primitive : m_editPrimitives )
|
||||
primitive->Flip( wxPoint( 0, 0 ), false );
|
||||
|
||||
m_shapesDirty = true;
|
||||
}
|
||||
|
@ -483,24 +455,8 @@ void D_PAD::FlipPrimitives()
|
|||
|
||||
void D_PAD::MirrorXPrimitives( int aX )
|
||||
{
|
||||
// Mirror custom shapes
|
||||
for( PAD_CS_PRIMITIVE& primitive : m_basicShapes )
|
||||
{
|
||||
MIRROR( primitive.m_Start.x, aX );
|
||||
MIRROR( primitive.m_End.x, aX );
|
||||
primitive.m_ArcAngle = -primitive.m_ArcAngle;
|
||||
|
||||
switch( primitive.m_Shape )
|
||||
{
|
||||
case S_POLYGON: // polygon
|
||||
for( wxPoint& pt : primitive.m_Poly )
|
||||
MIRROR( pt.x, 0 );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
for( std::shared_ptr<DRAWSEGMENT>& primitive : m_editPrimitives )
|
||||
primitive->Flip( wxPoint( aX, 0 ), true );
|
||||
|
||||
m_shapesDirty = true;
|
||||
}
|
||||
|
|
|
@ -60,60 +60,6 @@ namespace KIGFX
|
|||
class VIEW;
|
||||
}
|
||||
|
||||
/** Helper class to handle a primitive (basic shape: polygon, segment, circle or arc)
|
||||
* to build a custom pad full shape from a set of primitives
|
||||
*/
|
||||
class PAD_CS_PRIMITIVE
|
||||
{
|
||||
public:
|
||||
STROKE_T m_Shape; /// S_SEGMENT, S_RECT, S_ARC, S_CIRCLE, S_POLYGON only (same as DRAWSEGMENT)
|
||||
int m_Thickness; /// thickness of segment or outline
|
||||
/// For filled S_CIRCLE shape, thickness = 0.
|
||||
// if thickness is not = 0 S_CIRCLE shape is a ring
|
||||
int m_Radius; /// radius of a circle
|
||||
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 ):
|
||||
m_Shape( aShape ), m_Thickness( 0 ), m_Radius( 0 ), m_ArcAngle( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
// Accessors (helpers for arc and circle shapes)
|
||||
wxPoint GetCenter() { return m_Start; } /// returns the center of a circle or arc
|
||||
wxPoint GetArcStart() { return m_End; } /// returns the start point of an arc
|
||||
|
||||
// Geometric transform
|
||||
/** Move the primitive
|
||||
* @param aMoveVector is the deplacement vector
|
||||
*/
|
||||
void Move( wxPoint aMoveVector );
|
||||
|
||||
/**
|
||||
* Rotates the primitive about a point
|
||||
* @param aRotCentre center of rotation
|
||||
* @param aAngle angle in tenths of degree
|
||||
*/
|
||||
void Rotate( const wxPoint& aRotCentre, double aAngle );
|
||||
|
||||
/** Export the PAD_CS_PRIMITIVE parameters to a DRAWSEGMENT
|
||||
* useful to draw a primitive shape
|
||||
* @param aTarget is the DRAWSEGMENT to initialize
|
||||
*/
|
||||
void ExportTo( DRAWSEGMENT* aTarget );
|
||||
|
||||
/** Export the PAD_CS_PRIMITIVE parameters to a EDGE_MODULE
|
||||
* useful to convert a primitive shape to a EDGE_MODULE shape for editing in footprint editor
|
||||
* @param aTarget is the EDGE_MODULE to initialize
|
||||
*/
|
||||
void ExportTo( EDGE_MODULE* aTarget );
|
||||
};
|
||||
|
||||
|
||||
class D_PAD : public BOARD_CONNECTED_ITEM
|
||||
{
|
||||
public:
|
||||
|
@ -307,7 +253,10 @@ public:
|
|||
/**
|
||||
* Accessor to the basic shape list
|
||||
*/
|
||||
const std::vector<PAD_CS_PRIMITIVE>& GetPrimitives() const { return m_basicShapes; }
|
||||
const std::vector<std::shared_ptr<DRAWSEGMENT>>& GetPrimitives() const
|
||||
{
|
||||
return m_editPrimitives;
|
||||
}
|
||||
|
||||
void Flip( const wxPoint& aCentre, bool aFlipLeftRight ) override;
|
||||
|
||||
|
@ -324,12 +273,12 @@ public:
|
|||
/**
|
||||
* Import to the basic shape list
|
||||
*/
|
||||
void SetPrimitives( const std::vector<PAD_CS_PRIMITIVE>& aPrimitivesList );
|
||||
void SetPrimitives( const std::vector<std::shared_ptr<DRAWSEGMENT>>& aPrimitivesList );
|
||||
|
||||
/**
|
||||
* Add to the basic shape list
|
||||
*/
|
||||
void AddPrimitives( const std::vector<PAD_CS_PRIMITIVE>& aPrimitivesList );
|
||||
void AddPrimitives( const std::vector<std::shared_ptr<DRAWSEGMENT>>& aPrimitivesList );
|
||||
|
||||
|
||||
/**
|
||||
|
@ -633,7 +582,7 @@ private:
|
|||
*/
|
||||
int calcBoundingRadius() const;
|
||||
|
||||
void addCustomPadPrimitivesToPolygon( SHAPE_POLY_SET* aMergedPolygon, int aError ) const;
|
||||
void addPadPrimitivesToPolygon( SHAPE_POLY_SET* aMergedPolygon, int aError ) const;
|
||||
|
||||
void buildEffectiveShapes() const;
|
||||
|
||||
|
@ -647,17 +596,15 @@ private:
|
|||
///< PAD_SHAPE_OVAL, PAD_SHAPE_TRAPEZOID,
|
||||
///< PAD_SHAPE_ROUNDRECT, PAD_SHAPE_POLYGON
|
||||
|
||||
// Edit definitions of primitives for custom pad shapes. In local coordinates relative
|
||||
// to m_Pos (NOT shapePos) at orient 0.
|
||||
std::vector<std::shared_ptr<DRAWSEGMENT>> m_editPrimitives;
|
||||
|
||||
mutable bool m_shapesDirty;
|
||||
mutable int m_effectiveBoundingRadius;
|
||||
mutable std::vector<std::shared_ptr<SHAPE>> m_effectiveShapes;
|
||||
mutable std::shared_ptr<SHAPE_SEGMENT> m_effectiveHoleShape;
|
||||
|
||||
/** for free shape pads: a list of basic shapes,
|
||||
* in local coordinates, orient 0, coordinates relative to m_Pos
|
||||
* They are expected to define only one copper area.
|
||||
*/
|
||||
std::vector<PAD_CS_PRIMITIVE> m_basicShapes;
|
||||
|
||||
/**
|
||||
* How to build the custom shape in zone, to create the clearance area:
|
||||
* CUST_PAD_SHAPE_IN_ZONE_OUTLINE = use pad shape
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
DIALOG_PAD_PRIMITIVES_PROPERTIES::DIALOG_PAD_PRIMITIVES_PROPERTIES( wxWindow* aParent,
|
||||
PCB_BASE_FRAME* aFrame,
|
||||
PAD_CS_PRIMITIVE * aShape ) :
|
||||
DRAWSEGMENT* aShape ) :
|
||||
DIALOG_PAD_PRIMITIVES_PROPERTIES_BASE( aParent ),
|
||||
m_shape( aShape ),
|
||||
m_startX( aFrame, m_startXLabel, m_startXCtrl, m_startXUnits, true ),
|
||||
|
@ -76,19 +76,19 @@ bool DIALOG_PAD_PRIMITIVES_PROPERTIES::TransferDataToWindow()
|
|||
return false;
|
||||
|
||||
// Shows the text info about circle or ring only for S_CIRCLE shape
|
||||
if( m_shape->m_Shape != S_CIRCLE )
|
||||
if( m_shape->GetShape() != S_CIRCLE )
|
||||
m_staticTextInfo->Show( false );
|
||||
|
||||
m_thickness.SetValue( m_shape->m_Thickness );
|
||||
m_thickness.SetValue( m_shape->GetWidth() );
|
||||
|
||||
switch( m_shape->m_Shape )
|
||||
switch( m_shape->GetShape() )
|
||||
{
|
||||
case S_SEGMENT: // Segment with rounded ends
|
||||
SetTitle( _( "Segment" ) );
|
||||
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_startX.SetValue( m_shape->GetStart().x );
|
||||
m_startY.SetValue( m_shape->GetStart().y );
|
||||
m_endX.SetValue( m_shape->GetEnd().x );
|
||||
m_endY.SetValue( m_shape->GetEnd().y );
|
||||
m_ctrl1X.Show( false, true );
|
||||
m_ctrl1Y.Show( false, true );
|
||||
m_ctrl2X.Show( false, true );
|
||||
|
@ -102,27 +102,27 @@ bool DIALOG_PAD_PRIMITIVES_PROPERTIES::TransferDataToWindow()
|
|||
|
||||
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_startX.SetValue( m_shape->GetStart().x );
|
||||
m_startY.SetValue( m_shape->GetStart().y );
|
||||
m_endX.SetValue( m_shape->GetEnd().x );
|
||||
m_endY.SetValue( m_shape->GetEnd().y );
|
||||
m_ctrl1X.SetValue( m_shape->GetBezControl1().x );
|
||||
m_ctrl1Y.SetValue( m_shape->GetBezControl1().y );
|
||||
m_ctrl2X.SetValue( m_shape->GetBezControl2().x );
|
||||
m_ctrl2Y.SetValue( m_shape->GetBezControl2().y );
|
||||
m_radius.Show( false );
|
||||
break;
|
||||
|
||||
case S_ARC: // Arc with rounded ends
|
||||
SetTitle( _( "Arc" ) );
|
||||
m_startX.SetValue( m_shape->m_End.x ); // confusingly, the start point of the arc
|
||||
m_startY.SetValue( m_shape->m_End.y );
|
||||
m_startX.SetValue( m_shape->GetEnd().x ); // confusingly, the start point of the arc
|
||||
m_startY.SetValue( m_shape->GetEnd().y );
|
||||
m_staticTextPosEnd->SetLabel( _( "Center" ) );
|
||||
m_endX.SetValue( m_shape->m_Start.x ); // arc center
|
||||
m_endY.SetValue( m_shape->m_Start.y );
|
||||
m_endX.SetValue( m_shape->GetStart().x ); // arc center
|
||||
m_endY.SetValue( m_shape->GetStart().y );
|
||||
m_radiusLabel->SetLabel( _( "Angle:" ) );
|
||||
m_radius.SetUnits( EDA_UNITS::DEGREES );
|
||||
m_radius.SetValue( m_shape->m_ArcAngle );
|
||||
m_radius.SetValue( m_shape->GetAngle() );
|
||||
m_ctrl1X.Show( false, true );
|
||||
m_ctrl1Y.Show( false, true );
|
||||
m_ctrl2X.Show( false, true );
|
||||
|
@ -134,7 +134,7 @@ bool DIALOG_PAD_PRIMITIVES_PROPERTIES::TransferDataToWindow()
|
|||
break;
|
||||
|
||||
case S_CIRCLE: // ring or circle
|
||||
if( m_shape->m_Thickness )
|
||||
if( m_shape->GetWidth() )
|
||||
SetTitle( _( "Ring" ) );
|
||||
else
|
||||
SetTitle( _( "Circle" ) );
|
||||
|
@ -146,9 +146,9 @@ bool DIALOG_PAD_PRIMITIVES_PROPERTIES::TransferDataToWindow()
|
|||
|
||||
// Circle center uses position controls:
|
||||
m_staticTextPosStart->SetLabel( _( "Center:" ) );
|
||||
m_startX.SetValue( m_shape->m_Start.x );
|
||||
m_startY.SetValue( m_shape->m_Start.y );
|
||||
m_radius.SetValue( m_shape->m_Radius );
|
||||
m_startX.SetValue( m_shape->GetStart().x );
|
||||
m_startY.SetValue( m_shape->GetStart().y );
|
||||
m_radius.SetValue( m_shape->GetRadius() );
|
||||
m_ctrl1X.Show( false, true );
|
||||
m_ctrl1Y.Show( false, true );
|
||||
m_ctrl2X.Show( false, true );
|
||||
|
@ -174,43 +174,34 @@ bool DIALOG_PAD_PRIMITIVES_PROPERTIES::TransferDataToWindow()
|
|||
bool DIALOG_PAD_PRIMITIVES_PROPERTIES::TransferDataFromWindow()
|
||||
{
|
||||
// Transfer data out of the GUI.
|
||||
m_shape->m_Thickness = m_thickness.GetValue();
|
||||
m_shape->SetWidth( m_thickness.GetValue() );
|
||||
|
||||
switch( m_shape->m_Shape )
|
||||
switch( m_shape->GetShape() )
|
||||
{
|
||||
case S_SEGMENT: // 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->SetStart( wxPoint( m_startX.GetValue(), m_startY.GetValue() ) );
|
||||
m_shape->SetEnd( wxPoint( m_endX.GetValue(), 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();
|
||||
m_shape->SetStart( wxPoint( m_startX.GetValue(), m_startY.GetValue() ) );
|
||||
m_shape->SetEnd( wxPoint( m_endX.GetValue(), m_endY.GetValue() ) );
|
||||
m_shape->SetBezControl1( wxPoint( m_ctrl1X.GetValue(), m_ctrl1Y.GetValue() ) );
|
||||
m_shape->SetBezControl1( wxPoint( m_ctrl2X.GetValue(), m_ctrl2Y.GetValue() ) );
|
||||
break;
|
||||
|
||||
case S_ARC: // Arc with rounded ends
|
||||
// NB: we store the center of the arc in m_Start, and, confusingly,
|
||||
// the start point in m_End
|
||||
m_shape->m_Start.x = m_endX.GetValue();
|
||||
m_shape->m_Start.y = m_endY.GetValue();
|
||||
m_shape->m_End.x = m_startX.GetValue();
|
||||
m_shape->m_End.y = m_startY.GetValue();
|
||||
m_shape->SetStart( wxPoint( m_endX.GetValue(), m_endY.GetValue() ) );
|
||||
m_shape->SetEnd( wxPoint( m_startX.GetValue(), m_startY.GetValue() ) );
|
||||
// arc angle
|
||||
m_shape->m_ArcAngle = m_radius.GetValue();
|
||||
m_shape->SetAngle( m_radius.GetValue() );
|
||||
break;
|
||||
|
||||
case S_CIRCLE: // ring or circle
|
||||
m_shape->m_Start.x = m_startX.GetValue();
|
||||
m_shape->m_Start.y = m_startY.GetValue();
|
||||
m_shape->m_Radius = m_radius.GetValue();
|
||||
m_shape->SetStart( wxPoint( m_startX.GetValue(), m_startY.GetValue() ) );
|
||||
m_shape->SetEnd( m_shape->GetStart() + wxPoint( m_radius.GetValue(), 0 ) );
|
||||
break;
|
||||
|
||||
case S_POLYGON: // polygon
|
||||
|
@ -228,12 +219,14 @@ bool DIALOG_PAD_PRIMITIVES_PROPERTIES::TransferDataFromWindow()
|
|||
|
||||
DIALOG_PAD_PRIMITIVE_POLY_PROPS::DIALOG_PAD_PRIMITIVE_POLY_PROPS( wxWindow* aParent,
|
||||
PCB_BASE_FRAME* aFrame,
|
||||
PAD_CS_PRIMITIVE * aShape ) :
|
||||
DRAWSEGMENT* aShape ) :
|
||||
DIALOG_PAD_PRIMITIVE_POLY_PROPS_BASE( aParent ),
|
||||
m_shape( aShape ),
|
||||
m_currshape( *m_shape ),
|
||||
m_thickness( aFrame, m_thicknessLabel, m_thicknessCtrl, m_thicknessUnits, true )
|
||||
{
|
||||
for( const VECTOR2I& pt : m_shape->GetPolyShape().Outline( 0 ).CPoints() )
|
||||
m_currPoints.emplace_back( pt );
|
||||
|
||||
m_addButton->SetBitmap( KiBitmap( small_plus_xpm ) );
|
||||
m_deleteButton->SetBitmap( KiBitmap( trash_xpm ) );
|
||||
m_warningIcon->SetBitmap( KiBitmap( dialog_warning_xpm ) );
|
||||
|
@ -265,10 +258,10 @@ bool DIALOG_PAD_PRIMITIVE_POLY_PROPS::TransferDataToWindow()
|
|||
if( m_shape == NULL )
|
||||
return false;
|
||||
|
||||
m_thickness.SetValue( m_currshape.m_Thickness );
|
||||
m_thickness.SetValue( m_shape->GetWidth() );
|
||||
|
||||
// Populates the list of corners
|
||||
int extra_rows = m_currshape.m_Poly.size() - m_gridCornersList->GetNumberRows();
|
||||
int extra_rows = m_currPoints.size() - m_gridCornersList->GetNumberRows();
|
||||
|
||||
if( extra_rows > 0 )
|
||||
{
|
||||
|
@ -282,16 +275,16 @@ bool DIALOG_PAD_PRIMITIVE_POLY_PROPS::TransferDataToWindow()
|
|||
|
||||
// enter others corner coordinates
|
||||
wxString msg;
|
||||
for( unsigned row = 0; row < m_currshape.m_Poly.size(); ++row )
|
||||
for( unsigned row = 0; row < m_currPoints.size(); ++row )
|
||||
{
|
||||
// Row label is "Corner x"
|
||||
msg.Printf( "Corner %d", row+1 );
|
||||
m_gridCornersList->SetRowLabelValue( row, msg );
|
||||
|
||||
msg = StringFromValue( GetUserUnits(), m_currshape.m_Poly[row].x, true, true );
|
||||
msg = StringFromValue( GetUserUnits(), m_currPoints[row].x, true, true );
|
||||
m_gridCornersList->SetCellValue( row, 0, msg );
|
||||
|
||||
msg = StringFromValue( GetUserUnits(), m_currshape.m_Poly[row].y, true, true );
|
||||
msg = StringFromValue( GetUserUnits(), m_currPoints[row].y, true, true );
|
||||
m_gridCornersList->SetCellValue( row, 1, msg );
|
||||
}
|
||||
|
||||
|
@ -303,9 +296,8 @@ bool DIALOG_PAD_PRIMITIVE_POLY_PROPS::TransferDataFromWindow()
|
|||
if( !Validate() )
|
||||
return false;
|
||||
|
||||
m_currshape.m_Thickness = m_thickness.GetValue();
|
||||
|
||||
*m_shape = m_currshape;
|
||||
m_shape->SetPolyPoints( m_currPoints );
|
||||
m_shape->SetWidth( m_thickness.GetValue() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -324,7 +316,7 @@ bool DIALOG_PAD_PRIMITIVE_POLY_PROPS::doValidate( bool aRemoveRedundantCorners )
|
|||
if( !m_gridCornersList->CommitPendingChanges() )
|
||||
return false;
|
||||
|
||||
if( m_currshape.m_Poly.size() < 3 )
|
||||
if( m_currPoints.size() < 3 )
|
||||
{
|
||||
m_warningText->SetLabel( _("Polygon must have at least 3 corners" ) );
|
||||
m_warningText->Show( true );
|
||||
|
@ -334,13 +326,7 @@ bool DIALOG_PAD_PRIMITIVE_POLY_PROPS::doValidate( bool aRemoveRedundantCorners )
|
|||
|
||||
bool valid = true;
|
||||
|
||||
SHAPE_LINE_CHAIN polyline;
|
||||
|
||||
for( unsigned ii = 0; ii < m_currshape.m_Poly.size(); ++ii )
|
||||
polyline.Append( m_currshape.m_Poly[ii].x, m_currshape.m_Poly[ii].y );
|
||||
|
||||
// The polyline describes a polygon: close it.
|
||||
polyline.SetClosed( true );
|
||||
SHAPE_LINE_CHAIN polyline( m_currPoints, true );
|
||||
|
||||
// Remove redundant corners:
|
||||
polyline.Simplify();
|
||||
|
@ -362,12 +348,12 @@ bool DIALOG_PAD_PRIMITIVE_POLY_PROPS::doValidate( bool aRemoveRedundantCorners )
|
|||
|
||||
if( aRemoveRedundantCorners )
|
||||
{
|
||||
if( polyline.PointCount() != (int)m_currshape.m_Poly.size() )
|
||||
if( polyline.PointCount() != (int) m_currPoints.size() )
|
||||
{ // Happens after simplification
|
||||
m_currshape.m_Poly.clear();
|
||||
m_currPoints.clear();
|
||||
|
||||
for( int ii = 0; ii < polyline.PointCount(); ++ii )
|
||||
m_currshape.m_Poly.emplace_back( polyline.CPoint( ii ).x, polyline.CPoint( ii ).y );
|
||||
for( const VECTOR2I& pt : polyline.CPoints() )
|
||||
m_currPoints.emplace_back( pt );
|
||||
|
||||
m_warningIcon->Show( true );
|
||||
m_warningText->Show( true );
|
||||
|
@ -401,10 +387,10 @@ void DIALOG_PAD_PRIMITIVE_POLY_PROPS::OnButtonAdd( wxCommandEvent& event )
|
|||
return;
|
||||
}
|
||||
|
||||
if( m_currshape.m_Poly.size() == 0 || row >= (int) m_currshape.m_Poly.size() )
|
||||
m_currshape.m_Poly.emplace_back( 0, 0 );
|
||||
if( m_currPoints.size() == 0 || row >= (int) m_currPoints.size() )
|
||||
m_currPoints.emplace_back( 0, 0 );
|
||||
else
|
||||
m_currshape.m_Poly.insert( m_currshape.m_Poly.begin() + row, wxPoint( 0, 0 ) );
|
||||
m_currPoints.insert( m_currPoints.begin() + row, wxPoint( 0, 0 ) );
|
||||
|
||||
Validate();
|
||||
TransferDataToWindow();
|
||||
|
@ -439,7 +425,7 @@ void DIALOG_PAD_PRIMITIVE_POLY_PROPS::OnButtonDelete( wxCommandEvent& event )
|
|||
std::sort( selections.begin(), selections.end() );
|
||||
|
||||
for( int ii = selections.size()-1; ii >= 0 ; --ii )
|
||||
m_currshape.m_Poly.erase( m_currshape.m_Poly.begin() + selections[ii] );
|
||||
m_currPoints.erase( m_currPoints.begin() + selections[ii] );
|
||||
|
||||
Validate();
|
||||
TransferDataToWindow();
|
||||
|
@ -460,16 +446,16 @@ void DIALOG_PAD_PRIMITIVE_POLY_PROPS::onPaintPolyPanel( wxPaintEvent& event )
|
|||
// Calculate a suitable scale to fit the available draw area
|
||||
int minsize( Millimeter2iu( 0.5 ) );
|
||||
|
||||
for( unsigned ii = 0; ii < m_currshape.m_Poly.size(); ++ii )
|
||||
for( unsigned ii = 0; ii < m_currPoints.size(); ++ii )
|
||||
{
|
||||
minsize = std::max( minsize, std::abs( m_currshape.m_Poly[ii].x ) );
|
||||
minsize = std::max( minsize, std::abs( m_currshape.m_Poly[ii].y ) );
|
||||
minsize = std::max( minsize, std::abs( m_currPoints[ii].x ) );
|
||||
minsize = std::max( minsize, std::abs( m_currPoints[ii].y ) );
|
||||
}
|
||||
|
||||
// The draw origin is the center of the window.
|
||||
// Therefore the window size is twice the minsize just calculated
|
||||
minsize *= 2;
|
||||
minsize += m_currshape.m_Thickness;
|
||||
minsize += m_thickness.GetValue();
|
||||
|
||||
// Give a margin
|
||||
double scale = std::min( double( dc_size.x ) / minsize, double( dc_size.y ) / minsize ) * 0.9;
|
||||
|
@ -487,7 +473,7 @@ void DIALOG_PAD_PRIMITIVE_POLY_PROPS::onPaintPolyPanel( wxPaintEvent& event )
|
|||
EDA_COLOR_T normalcolor = WHITE;
|
||||
EDA_COLOR_T selectcolor = RED;
|
||||
|
||||
for( unsigned ii = 0; ii < m_currshape.m_Poly.size(); ++ii )
|
||||
for( unsigned ii = 0; ii < m_currPoints.size(); ++ii )
|
||||
{
|
||||
EDA_COLOR_T color = normalcolor;
|
||||
|
||||
|
@ -498,10 +484,10 @@ void DIALOG_PAD_PRIMITIVE_POLY_PROPS::onPaintPolyPanel( wxPaintEvent& event )
|
|||
|
||||
unsigned jj = ii + 1;
|
||||
|
||||
if( jj >= m_currshape.m_Poly.size() )
|
||||
if( jj >= m_currPoints.size() )
|
||||
jj = 0;
|
||||
|
||||
GRLine( NULL, &dc, m_currshape.m_Poly[ii] * scale, m_currshape.m_Poly[jj] * scale, m_currshape.m_Thickness * scale, color );
|
||||
GRLine( NULL, &dc, m_currPoints[ii] * scale, m_currPoints[jj] * scale, m_thickness.GetValue() * scale, color );
|
||||
}
|
||||
|
||||
event.Skip();
|
||||
|
@ -528,11 +514,9 @@ void DIALOG_PAD_PRIMITIVE_POLY_PROPS::onCellChanging( wxGridEvent& event )
|
|||
return;
|
||||
|
||||
if( col == 0 ) // Set the X value
|
||||
m_currshape.m_Poly[row].x = ValueFromString( GetUserUnits(), msg, true );
|
||||
m_currPoints[row].x = ValueFromString( GetUserUnits(), msg, true );
|
||||
else // Set the Y value
|
||||
m_currshape.m_Poly[row].y = ValueFromString( GetUserUnits(), msg, true );
|
||||
|
||||
m_currshape.m_Thickness = m_thickness.GetValue();
|
||||
m_currPoints[row].y = ValueFromString( GetUserUnits(), msg, true );
|
||||
|
||||
Validate();
|
||||
|
||||
|
@ -544,7 +528,7 @@ void DIALOG_PAD_PRIMITIVE_POLY_PROPS::onCellChanging( wxGridEvent& event )
|
|||
// (move, rotate around origin, scaling factor, duplication).
|
||||
DIALOG_PAD_PRIMITIVES_TRANSFORM::DIALOG_PAD_PRIMITIVES_TRANSFORM( wxWindow* aParent,
|
||||
PCB_BASE_FRAME* aFrame,
|
||||
std::vector<PAD_CS_PRIMITIVE*>& aList,
|
||||
std::vector<std::shared_ptr<DRAWSEGMENT>>& aList,
|
||||
bool aShowDuplicate ) :
|
||||
DIALOG_PAD_PRIMITIVES_TRANSFORM_BASE( aParent ),
|
||||
m_list( aList ),
|
||||
|
@ -575,7 +559,8 @@ 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 )
|
||||
void DIALOG_PAD_PRIMITIVES_TRANSFORM::Transform( std::vector<std::shared_ptr<DRAWSEGMENT>>* aList,
|
||||
int aDuplicateCount )
|
||||
{
|
||||
wxPoint move_vect( m_vectorX.GetValue(), m_vectorY.GetValue() );
|
||||
double rotation = m_rotation.GetValue();
|
||||
|
@ -599,48 +584,21 @@ void DIALOG_PAD_PRIMITIVES_TRANSFORM::Transform( std::vector<PAD_CS_PRIMITIVE>*
|
|||
do {
|
||||
for( unsigned idx = 0; idx < m_list.size(); ++idx )
|
||||
{
|
||||
PAD_CS_PRIMITIVE* shape;
|
||||
std::shared_ptr<DRAWSEGMENT> shape;
|
||||
|
||||
if( aList == NULL )
|
||||
shape = m_list[idx];
|
||||
else
|
||||
{
|
||||
PAD_CS_PRIMITIVE new_shape( *m_list[idx] );
|
||||
aList->push_back( new_shape );
|
||||
shape = &aList->back();
|
||||
aList->emplace_back( std::make_shared<DRAWSEGMENT>( *m_list[idx] ) );
|
||||
shape = aList->back();
|
||||
}
|
||||
|
||||
// Transform parameters common to all shape types (some can be unused)
|
||||
shape->m_Thickness = KiROUND( shape->m_Thickness * scale );
|
||||
geom_transf( shape->m_Start, currMoveVect, scale, curr_rotation );
|
||||
geom_transf( shape->m_End, currMoveVect, scale, curr_rotation );
|
||||
|
||||
// specific parameters:
|
||||
switch( shape->m_Shape )
|
||||
{
|
||||
case S_SEGMENT: // Segment with rounded ends
|
||||
break;
|
||||
|
||||
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;
|
||||
|
||||
case S_POLYGON: // polygon
|
||||
for( unsigned ii = 0; ii < shape->m_Poly.size(); ++ii )
|
||||
geom_transf( shape->m_Poly[ii], currMoveVect, scale, curr_rotation );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
shape->SetWidth( KiROUND( shape->GetWidth() * scale ) );
|
||||
shape->Move( currMoveVect );
|
||||
shape->Scale( scale );
|
||||
shape->Rotate( wxPoint( 0, 0 ), curr_rotation );
|
||||
}
|
||||
|
||||
// Prepare new transform on duplication:
|
||||
|
|
|
@ -700,49 +700,48 @@ void DIALOG_PAD_PROPERTIES::displayPrimitivesList()
|
|||
|
||||
for( unsigned ii = 0; ii < m_primitives.size(); ++ii )
|
||||
{
|
||||
const PAD_CS_PRIMITIVE& primitive = m_primitives[ii];
|
||||
const std::shared_ptr<DRAWSEGMENT>& primitive = m_primitives[ii];
|
||||
|
||||
for( unsigned jj = 0; jj < 5; ++jj )
|
||||
bs_info[jj].Empty();
|
||||
|
||||
bs_info[4] = wxString::Format( _( "width %s" ),
|
||||
MessageTextFromValue( m_units, primitive.m_Thickness, true ) );
|
||||
bs_info[4] = _( "width " ) + MessageTextFromValue( m_units, primitive->GetWidth(), true );
|
||||
|
||||
switch( primitive.m_Shape )
|
||||
switch( primitive->GetShape() )
|
||||
{
|
||||
case S_SEGMENT: // usual segment : line with rounded ends
|
||||
bs_info[0] = _( "Segment" );
|
||||
bs_info[1] = _( "from " ) + formatCoord( m_units, primitive.m_Start );
|
||||
bs_info[2] = _( "to " ) + formatCoord( m_units, primitive.m_End );
|
||||
bs_info[1] = _( "from " ) + formatCoord( m_units, primitive->GetStart() );
|
||||
bs_info[2] = _( "to " ) + formatCoord( m_units, primitive->GetEnd() );
|
||||
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 );
|
||||
bs_info[1] = _( "from " ) + formatCoord( m_units, primitive->GetStart() );
|
||||
bs_info[2] = _( "to " ) + formatCoord( m_units, primitive->GetEnd() );
|
||||
break;
|
||||
|
||||
case S_ARC: // Arc with rounded ends
|
||||
bs_info[0] = _( "Arc" );
|
||||
bs_info[1] = _( "center " ) + formatCoord( m_units, primitive.m_Start );// Center
|
||||
bs_info[2] = _( "start " ) + formatCoord( m_units, primitive.m_End ); // Start point
|
||||
bs_info[3] = wxString::Format( _( "angle %s" ), FormatAngle( primitive.m_ArcAngle ) );
|
||||
bs_info[1] = _( "center " ) + formatCoord( m_units, primitive->GetCenter() );
|
||||
bs_info[2] = _( "start " ) + formatCoord( m_units, primitive->GetArcStart() );
|
||||
bs_info[3] = _( "angle " ) + FormatAngle( primitive->GetAngle() );
|
||||
break;
|
||||
|
||||
case S_CIRCLE: // ring or circle
|
||||
if( primitive.m_Thickness )
|
||||
if( primitive->GetWidth() )
|
||||
bs_info[0] = _( "ring" );
|
||||
else
|
||||
bs_info[0] = _( "circle" );
|
||||
|
||||
bs_info[1] = formatCoord( m_units, primitive.m_Start );
|
||||
bs_info[2] = wxString::Format( _( "radius %s" ),
|
||||
MessageTextFromValue( m_units, primitive.m_Radius, true ) );
|
||||
bs_info[1] = formatCoord( m_units, primitive->GetStart() );
|
||||
bs_info[2] = _( "radius " ) + MessageTextFromValue( m_units, primitive->GetRadius(), true );
|
||||
break;
|
||||
|
||||
case S_POLYGON: // polygon
|
||||
bs_info[0] = "Polygon";
|
||||
bs_info[1] = wxString::Format( _( "corners count %d" ), (int) primitive.m_Poly.size() );
|
||||
bs_info[1] = wxString::Format( _( "corners count %d" ),
|
||||
(int) primitive->GetPolyShape().Outline( 0 ).PointCount() );
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1249,48 +1248,13 @@ void DIALOG_PAD_PROPERTIES::redraw()
|
|||
|
||||
while( select >= 0 )
|
||||
{
|
||||
PAD_CS_PRIMITIVE& primitive = m_primitives[select];
|
||||
|
||||
DRAWSEGMENT* dummySegment = new DRAWSEGMENT;
|
||||
DRAWSEGMENT* dummySegment = (DRAWSEGMENT*) m_primitives[select]->Clone();
|
||||
dummySegment->SetLayer( SELECTED_ITEMS_LAYER );
|
||||
primitive.ExportTo( dummySegment );
|
||||
dummySegment->Rotate( wxPoint( 0, 0), m_dummyPad->GetOrientation() );
|
||||
dummySegment->Move( m_dummyPad->GetPosition() );
|
||||
|
||||
// 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
|
||||
if( primitive.m_Thickness == 0 ) // filled circle
|
||||
{ // the filled circle option does not exist in a DRAWSEGMENT
|
||||
// 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;
|
||||
dummySegment->SetEnd( end );
|
||||
dummySegment->SetWidth( primitive.m_Radius );
|
||||
}
|
||||
break;
|
||||
|
||||
case S_POLYGON:
|
||||
break;
|
||||
|
||||
default:
|
||||
delete dummySegment;
|
||||
dummySegment = nullptr;
|
||||
break;
|
||||
}
|
||||
|
||||
if( dummySegment )
|
||||
{
|
||||
view->Add( dummySegment );
|
||||
m_highlight.push_back( dummySegment );
|
||||
}
|
||||
|
||||
select = m_listCtrlPrimitives->GetNextSelected( select );
|
||||
}
|
||||
|
@ -1825,11 +1789,11 @@ void DIALOG_PAD_PROPERTIES::editPrimitive()
|
|||
return;
|
||||
}
|
||||
|
||||
PAD_CS_PRIMITIVE& shape = m_primitives[select];
|
||||
std::shared_ptr<DRAWSEGMENT>& shape = m_primitives[select];
|
||||
|
||||
if( shape.m_Shape == S_POLYGON )
|
||||
if( shape->GetShape() == S_POLYGON )
|
||||
{
|
||||
DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, m_parent, &shape );
|
||||
DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, m_parent, shape.get() );
|
||||
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
return;
|
||||
|
@ -1839,7 +1803,7 @@ void DIALOG_PAD_PROPERTIES::editPrimitive()
|
|||
|
||||
else
|
||||
{
|
||||
DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, m_parent, &shape );
|
||||
DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, m_parent, shape.get() );
|
||||
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
return;
|
||||
|
@ -1922,25 +1886,26 @@ void DIALOG_PAD_PROPERTIES::onAddPrimitive( wxCommandEvent& event )
|
|||
|
||||
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 );
|
||||
DRAWSEGMENT* primitive = new DRAWSEGMENT();
|
||||
primitive->SetShape( listtype[type] );
|
||||
primitive->SetWidth( m_board->GetDesignSettings().GetLineThickness( F_Cu ) );
|
||||
|
||||
if( listtype[type] == S_POLYGON )
|
||||
{
|
||||
DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, m_parent, &primitive );
|
||||
DIALOG_PAD_PRIMITIVE_POLY_PROPS dlg( this, m_parent, primitive );
|
||||
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, m_parent, &primitive );
|
||||
DIALOG_PAD_PRIMITIVES_PROPERTIES dlg( this, m_parent, primitive );
|
||||
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
return;
|
||||
}
|
||||
|
||||
m_primitives.push_back( primitive );
|
||||
m_primitives.emplace_back( primitive );
|
||||
|
||||
displayPrimitivesList();
|
||||
|
||||
|
@ -1963,18 +1928,17 @@ void DIALOG_PAD_PROPERTIES::onGeometryTransform( wxCommandEvent& event )
|
|||
}
|
||||
|
||||
// Multiple selections are allowed. Build selected shapes list
|
||||
std::vector<PAD_CS_PRIMITIVE*> shapeList;
|
||||
shapeList.push_back( &m_primitives[select] );
|
||||
std::vector<std::shared_ptr<DRAWSEGMENT>> shapeList;
|
||||
shapeList.emplace_back( m_primitives[select] );
|
||||
|
||||
while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
|
||||
shapeList.push_back( &m_primitives[select] );
|
||||
shapeList.emplace_back( m_primitives[select] );
|
||||
|
||||
DIALOG_PAD_PRIMITIVES_TRANSFORM dlg( this, m_parent, shapeList, false );
|
||||
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
return;
|
||||
|
||||
// Transfert new settings:
|
||||
dlg.Transform();
|
||||
|
||||
displayPrimitivesList();
|
||||
|
@ -1998,11 +1962,11 @@ void DIALOG_PAD_PROPERTIES::onDuplicatePrimitive( wxCommandEvent& event )
|
|||
}
|
||||
|
||||
// Multiple selections are allowed. Build selected shapes list
|
||||
std::vector<PAD_CS_PRIMITIVE*> shapeList;
|
||||
shapeList.push_back( &m_primitives[select] );
|
||||
std::vector<std::shared_ptr<DRAWSEGMENT>> shapeList;
|
||||
shapeList.emplace_back( m_primitives[select] );
|
||||
|
||||
while( ( select = m_listCtrlPrimitives->GetNextSelected( select ) ) >= 0 )
|
||||
shapeList.push_back( &m_primitives[select] );
|
||||
shapeList.emplace_back( m_primitives[select] );
|
||||
|
||||
DIALOG_PAD_PRIMITIVES_TRANSFORM dlg( this, m_parent, shapeList, true );
|
||||
|
||||
|
@ -2012,7 +1976,7 @@ void DIALOG_PAD_PROPERTIES::onDuplicatePrimitive( wxCommandEvent& event )
|
|||
// Transfer new settings
|
||||
// save duplicates to a separate vector to avoid m_primitives reallocation,
|
||||
// as shapeList contains pointers to its elements
|
||||
std::vector<PAD_CS_PRIMITIVE> duplicates;
|
||||
std::vector<std::shared_ptr<DRAWSEGMENT>> duplicates;
|
||||
dlg.Transform( &duplicates, dlg.GetDuplicateCount() );
|
||||
std::move( duplicates.begin(), duplicates.end(), std::back_inserter( m_primitives ) );
|
||||
|
||||
|
|
|
@ -62,8 +62,8 @@ private:
|
|||
bool m_canUpdate;
|
||||
bool m_canEditNetName; // true only if the caller is the board editor
|
||||
|
||||
std::vector<PAD_CS_PRIMITIVE> m_primitives; // the list of custom shape primitives (basic
|
||||
// shapes), in local coords, orient 0
|
||||
std::vector<std::shared_ptr<DRAWSEGMENT>> m_primitives; // the custom shape primitives in
|
||||
// local coords, orient 0
|
||||
// must define a single copper area
|
||||
COLOR4D m_selectedColor; // color used to draw selected primitives when
|
||||
// editing a custom pad shape
|
||||
|
@ -167,7 +167,7 @@ class DIALOG_PAD_PRIMITIVES_PROPERTIES: public DIALOG_PAD_PRIMITIVES_PROPERTIES_
|
|||
{
|
||||
public:
|
||||
DIALOG_PAD_PRIMITIVES_PROPERTIES( wxWindow* aParent, PCB_BASE_FRAME* aFrame,
|
||||
PAD_CS_PRIMITIVE * aShape );
|
||||
DRAWSEGMENT* aShape );
|
||||
|
||||
/**
|
||||
* Function TransferDataFromWindow
|
||||
|
@ -183,7 +183,7 @@ private:
|
|||
bool TransferDataToWindow() override;
|
||||
|
||||
// The basic shape currently edited
|
||||
PAD_CS_PRIMITIVE * m_shape;
|
||||
DRAWSEGMENT* m_shape;
|
||||
|
||||
UNIT_BINDER m_startX;
|
||||
UNIT_BINDER m_startY;
|
||||
|
@ -204,16 +204,16 @@ private:
|
|||
class DIALOG_PAD_PRIMITIVE_POLY_PROPS: public DIALOG_PAD_PRIMITIVE_POLY_PROPS_BASE
|
||||
{
|
||||
// The basic shape currently edited
|
||||
PAD_CS_PRIMITIVE * m_shape;
|
||||
DRAWSEGMENT* m_shape;
|
||||
|
||||
// The working copy of the basic shape currently edited
|
||||
PAD_CS_PRIMITIVE m_currshape;
|
||||
std::vector<wxPoint> m_currPoints;
|
||||
|
||||
UNIT_BINDER m_thickness;
|
||||
|
||||
public:
|
||||
DIALOG_PAD_PRIMITIVE_POLY_PROPS( wxWindow* aParent, PCB_BASE_FRAME* aFrame,
|
||||
PAD_CS_PRIMITIVE * aShape );
|
||||
DRAWSEGMENT* aShape );
|
||||
~DIALOG_PAD_PRIMITIVE_POLY_PROPS();
|
||||
|
||||
/**
|
||||
|
@ -235,7 +235,6 @@ private:
|
|||
bool Validate() override;
|
||||
|
||||
// Events handlers:
|
||||
void OnValidateButton( wxCommandEvent& event );
|
||||
void OnButtonAdd( wxCommandEvent& event ) override;
|
||||
void OnButtonDelete( wxCommandEvent& event ) override;
|
||||
void onPaintPolyPanel( wxPaintEvent& event ) override;
|
||||
|
@ -263,7 +262,8 @@ class DIALOG_PAD_PRIMITIVES_TRANSFORM : public DIALOG_PAD_PRIMITIVES_TRANSFORM_B
|
|||
{
|
||||
public:
|
||||
DIALOG_PAD_PRIMITIVES_TRANSFORM( wxWindow* aParent, PCB_BASE_FRAME* aFrame,
|
||||
std::vector<PAD_CS_PRIMITIVE*>& aList, bool aShowDuplicate );
|
||||
std::vector<std::shared_ptr<DRAWSEGMENT>>& aList,
|
||||
bool aShowDuplicate );
|
||||
|
||||
/**
|
||||
* Apply geometric transform (rotation, move, scale) defined in dialog
|
||||
|
@ -272,7 +272,8 @@ public:
|
|||
* The duplicated items are transformed, but the initial shpes are not modified.
|
||||
* The duplicated items are added to aList
|
||||
*/
|
||||
void Transform( std::vector<PAD_CS_PRIMITIVE>* aList = NULL, int aDuplicateCount = 0 );
|
||||
void Transform( std::vector<std::shared_ptr<DRAWSEGMENT>>* aList = NULL,
|
||||
int aDuplicateCount = 0 );
|
||||
|
||||
/**
|
||||
* @return the number of duplicate, chosen by user
|
||||
|
@ -280,7 +281,7 @@ public:
|
|||
int GetDuplicateCount() { return m_spinCtrlDuplicateCount->GetValue(); }
|
||||
|
||||
private:
|
||||
std::vector<PAD_CS_PRIMITIVE*>& m_list;
|
||||
std::vector<std::shared_ptr<DRAWSEGMENT>>& m_list;
|
||||
|
||||
UNIT_BINDER m_vectorX;
|
||||
UNIT_BINDER m_vectorY;
|
||||
|
|
|
@ -1523,72 +1523,68 @@ void PCB_IO::format( D_PAD* aPad, int aNestLevel ) const
|
|||
int nested_level = aNestLevel+2;
|
||||
|
||||
// Output all basic shapes
|
||||
for( unsigned icnt = 0; icnt < aPad->GetPrimitives().size(); ++icnt )
|
||||
for( const std::shared_ptr<DRAWSEGMENT> primitive : aPad->GetPrimitives() )
|
||||
{
|
||||
m_out->Print( 0, "\n");
|
||||
|
||||
const PAD_CS_PRIMITIVE& primitive = aPad->GetPrimitives()[icnt];
|
||||
|
||||
switch( primitive.m_Shape )
|
||||
switch( primitive->GetShape() )
|
||||
{
|
||||
case S_SEGMENT: // usual segment : line with rounded ends
|
||||
m_out->Print( nested_level, "(gr_line (start %s) (end %s) (width %s))",
|
||||
FormatInternalUnits( primitive.m_Start ).c_str(),
|
||||
FormatInternalUnits( primitive.m_End ).c_str(),
|
||||
FormatInternalUnits( primitive.m_Thickness ).c_str() );
|
||||
FormatInternalUnits( primitive->GetStart() ).c_str(),
|
||||
FormatInternalUnits( primitive->GetEnd() ).c_str(),
|
||||
FormatInternalUnits( primitive->GetWidth() ).c_str() );
|
||||
break;
|
||||
|
||||
case S_RECT:
|
||||
m_out->Print( nested_level, "(gr_rect (start %s) (end %s) (width %s))",
|
||||
FormatInternalUnits( primitive.m_Start ).c_str(),
|
||||
FormatInternalUnits( primitive.m_End ).c_str(),
|
||||
FormatInternalUnits( primitive.m_Thickness ).c_str() );
|
||||
FormatInternalUnits( primitive->GetStart() ).c_str(),
|
||||
FormatInternalUnits( primitive->GetEnd() ).c_str(),
|
||||
FormatInternalUnits( primitive->GetWidth() ).c_str() );
|
||||
break;
|
||||
|
||||
case S_ARC: // Arc with rounded ends
|
||||
m_out->Print( nested_level, "(gr_arc (start %s) (end %s) (angle %s) (width %s))",
|
||||
FormatInternalUnits( primitive.m_Start ).c_str(),
|
||||
FormatInternalUnits( primitive.m_End ).c_str(),
|
||||
FormatAngle( primitive.m_ArcAngle ).c_str(),
|
||||
FormatInternalUnits( primitive.m_Thickness ).c_str() );
|
||||
FormatInternalUnits( primitive->GetStart() ).c_str(),
|
||||
FormatInternalUnits( primitive->GetEnd() ).c_str(),
|
||||
FormatAngle( primitive->GetAngle() ).c_str(),
|
||||
FormatInternalUnits( primitive->GetWidth() ).c_str() );
|
||||
break;
|
||||
|
||||
case S_CIRCLE: // ring or circle (circle if width == 0
|
||||
m_out->Print( nested_level, "(gr_circle (center %s) (end %s %s) (width %s))",
|
||||
FormatInternalUnits( primitive.m_Start ).c_str(),
|
||||
FormatInternalUnits( primitive.m_Start.x + primitive.m_Radius ).c_str(),
|
||||
FormatInternalUnits( primitive.m_Start.y ).c_str(),
|
||||
FormatInternalUnits( primitive.m_Thickness ).c_str() );
|
||||
m_out->Print( nested_level, "(gr_circle (center %s) (end %s) (width %s))",
|
||||
FormatInternalUnits( primitive->GetStart() ).c_str(),
|
||||
FormatInternalUnits( primitive->GetEnd() ).c_str(),
|
||||
FormatInternalUnits( primitive->GetWidth() ).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() );
|
||||
FormatInternalUnits( primitive->GetStart() ).c_str(),
|
||||
FormatInternalUnits( primitive->GetBezControl1() ).c_str(),
|
||||
FormatInternalUnits( primitive->GetBezControl2() ).c_str(),
|
||||
FormatInternalUnits( primitive->GetEnd() ).c_str(),
|
||||
FormatInternalUnits( primitive->GetWidth() ).c_str() );
|
||||
break;
|
||||
|
||||
case S_POLYGON: // polygon
|
||||
if( primitive.m_Poly.size() < 2 )
|
||||
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:
|
||||
const std::vector< wxPoint>& poly = primitive.m_Poly;
|
||||
int newLine = 0;
|
||||
|
||||
for( unsigned ii = 0; ii < poly.size(); ii++ )
|
||||
for( const VECTOR2I &pt : primitive->GetPolyShape().COutline( 0 ).CPoints() )
|
||||
{
|
||||
if( newLine == 0 )
|
||||
m_out->Print( nested_level+1, " (xy %s)",
|
||||
FormatInternalUnits( wxPoint( poly[ii].x, poly[ii].y ) ).c_str() );
|
||||
FormatInternalUnits( (wxPoint) pt ).c_str() );
|
||||
else
|
||||
m_out->Print( 0, " (xy %s)",
|
||||
FormatInternalUnits( wxPoint( poly[ii].x, poly[ii].y ) ).c_str() );
|
||||
FormatInternalUnits( (wxPoint) pt ).c_str() );
|
||||
|
||||
if( ++newLine > 4 )
|
||||
{
|
||||
|
@ -1597,7 +1593,7 @@ void PCB_IO::format( D_PAD* aPad, int aNestLevel ) const
|
|||
}
|
||||
}
|
||||
|
||||
m_out->Print( 0, ") (width %s))", FormatInternalUnits( primitive.m_Thickness ).c_str() );
|
||||
m_out->Print( 0, ") (width %s))", FormatInternalUnits( primitive->GetWidth() ).c_str() );
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -44,102 +44,6 @@
|
|||
#include <geometry/shape_rect.h>
|
||||
|
||||
|
||||
void PAD_CS_PRIMITIVE::ExportTo( DRAWSEGMENT* aTarget )
|
||||
{
|
||||
aTarget->SetShape( m_Shape );
|
||||
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)
|
||||
if( m_Shape == S_CIRCLE )
|
||||
{
|
||||
wxPoint end = m_Start;
|
||||
end.x += m_Radius;
|
||||
aTarget->SetEnd( end );
|
||||
}
|
||||
|
||||
aTarget->SetAngle( m_ArcAngle );
|
||||
aTarget->SetPolyPoints( m_Poly );
|
||||
}
|
||||
|
||||
|
||||
void PAD_CS_PRIMITIVE::ExportTo( EDGE_MODULE* aTarget )
|
||||
{
|
||||
ExportTo( static_cast<DRAWSEGMENT*>( aTarget ) );
|
||||
// Initialize coordinates specific to the EDGE_MODULE (m_Start0 and m_End0)
|
||||
aTarget->SetLocalCoord();
|
||||
}
|
||||
|
||||
|
||||
void PAD_CS_PRIMITIVE::Move( wxPoint aMoveVector )
|
||||
{
|
||||
m_Start += aMoveVector;
|
||||
m_End += aMoveVector;
|
||||
m_Ctrl1 += aMoveVector;
|
||||
m_Ctrl2 += aMoveVector;
|
||||
|
||||
for( auto& corner : m_Poly )
|
||||
corner += aMoveVector;
|
||||
}
|
||||
|
||||
|
||||
void PAD_CS_PRIMITIVE::Rotate( const wxPoint& aRotCentre, double aAngle )
|
||||
{
|
||||
switch( m_Shape )
|
||||
{
|
||||
case S_ARC:
|
||||
case S_SEGMENT:
|
||||
case S_CIRCLE:
|
||||
// these can all be done by just rotating the start and end points
|
||||
RotatePoint( &m_Start, aRotCentre, aAngle );
|
||||
RotatePoint( &m_End, aRotCentre, aAngle );
|
||||
break;
|
||||
|
||||
case S_RECT:
|
||||
if( KiROUND( aAngle ) % 900 == 0 )
|
||||
{
|
||||
RotatePoint( &m_Start, aRotCentre, aAngle );
|
||||
RotatePoint( &m_End, aRotCentre, aAngle );
|
||||
break;
|
||||
}
|
||||
|
||||
// Convert non-cartesian-rotated rect to a diamond
|
||||
m_Shape = S_POLYGON;
|
||||
|
||||
m_Poly.clear();
|
||||
m_Poly.emplace_back( m_Start );
|
||||
m_Poly.emplace_back( m_End.x, m_Start.y );
|
||||
m_Poly.emplace_back( m_End );
|
||||
m_Poly.emplace_back( m_Start.x, m_End.y );
|
||||
|
||||
KI_FALLTHROUGH;
|
||||
|
||||
case S_POLYGON:
|
||||
for( auto& pt : m_Poly )
|
||||
RotatePoint( &pt, aRotCentre, aAngle );
|
||||
|
||||
break;
|
||||
|
||||
case S_CURVE:
|
||||
RotatePoint( &m_Start, aRotCentre, aAngle );
|
||||
RotatePoint( &m_End, aRotCentre, aAngle );
|
||||
RotatePoint( &m_Ctrl1, aRotCentre, aAngle );
|
||||
RotatePoint( &m_Ctrl2, aRotCentre, aAngle );
|
||||
break;
|
||||
|
||||
default:
|
||||
// un-handled edge transform
|
||||
wxASSERT_MSG( false, wxT( "PAD_CS_PRIMITIVE::Rotate not implemented for "
|
||||
+ BOARD_ITEM::ShowShape( m_Shape ) ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Has meaning only for free shape pads.
|
||||
* add a free shape to the shape list.
|
||||
|
@ -164,21 +68,22 @@ void D_PAD::AddPrimitivePoly( const SHAPE_POLY_SET& aPoly, int aThickness )
|
|||
|
||||
void D_PAD::AddPrimitivePoly( const std::vector<wxPoint>& aPoly, int aThickness )
|
||||
{
|
||||
PAD_CS_PRIMITIVE shape( S_POLYGON );
|
||||
shape.m_Poly = aPoly;
|
||||
shape.m_Thickness = aThickness;
|
||||
m_basicShapes.push_back( shape );
|
||||
DRAWSEGMENT* item = new DRAWSEGMENT();
|
||||
item->SetShape( S_POLYGON );
|
||||
item->SetPolyPoints( aPoly );
|
||||
item->SetWidth( aThickness );
|
||||
m_editPrimitives.emplace_back( item );
|
||||
m_shapesDirty = true;
|
||||
}
|
||||
|
||||
|
||||
void D_PAD::AddPrimitiveSegment( const wxPoint& aStart, const wxPoint& aEnd, int aThickness )
|
||||
{
|
||||
PAD_CS_PRIMITIVE shape( S_SEGMENT );
|
||||
shape.m_Start = aStart;
|
||||
shape.m_End = aEnd;
|
||||
shape.m_Thickness = aThickness;
|
||||
m_basicShapes.push_back( shape );
|
||||
DRAWSEGMENT* item = new DRAWSEGMENT();
|
||||
item->SetStart( aStart );
|
||||
item->SetEnd( aEnd );
|
||||
item->SetWidth( aThickness );
|
||||
m_editPrimitives.emplace_back( item );
|
||||
m_shapesDirty = true;
|
||||
}
|
||||
|
||||
|
@ -186,12 +91,13 @@ void D_PAD::AddPrimitiveSegment( const wxPoint& aStart, const wxPoint& aEnd, int
|
|||
void D_PAD::AddPrimitiveArc( const wxPoint& aCenter, const wxPoint& aStart, int aArcAngle,
|
||||
int aThickness )
|
||||
{
|
||||
PAD_CS_PRIMITIVE shape( S_ARC );
|
||||
shape.m_Start = aCenter;
|
||||
shape.m_End = aStart;
|
||||
shape.m_ArcAngle = aArcAngle;
|
||||
shape.m_Thickness = aThickness;
|
||||
m_basicShapes.push_back( shape );
|
||||
DRAWSEGMENT* item = new DRAWSEGMENT();
|
||||
item->SetShape( S_ARC );
|
||||
item->SetCenter( aCenter );
|
||||
item->SetArcStart( aStart );
|
||||
item->SetAngle( aArcAngle );
|
||||
item->SetWidth( aThickness );
|
||||
m_editPrimitives.emplace_back( item );
|
||||
m_shapesDirty = true;
|
||||
}
|
||||
|
||||
|
@ -199,56 +105,59 @@ void D_PAD::AddPrimitiveArc( const wxPoint& aCenter, const wxPoint& aStart, int
|
|||
void D_PAD::AddPrimitiveCurve( const wxPoint& aStart, const wxPoint& aEnd, const wxPoint& aCtrl1,
|
||||
const 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 );
|
||||
DRAWSEGMENT* item = new DRAWSEGMENT();
|
||||
item->SetShape( S_CURVE );
|
||||
item->SetStart( aStart );
|
||||
item->SetEnd( aEnd );
|
||||
item->SetBezControl1( aCtrl1 );
|
||||
item->SetBezControl2( aCtrl2 );
|
||||
item->SetWidth( aThickness );
|
||||
m_editPrimitives.emplace_back( item );
|
||||
m_shapesDirty = true;
|
||||
}
|
||||
|
||||
|
||||
void D_PAD::AddPrimitiveCircle( const wxPoint& aCenter, int aRadius, int aThickness )
|
||||
{
|
||||
PAD_CS_PRIMITIVE shape( S_CIRCLE );
|
||||
shape.m_Start = aCenter;
|
||||
shape.m_Radius = aRadius;
|
||||
shape.m_Thickness = aThickness;
|
||||
m_basicShapes.push_back( shape );
|
||||
DRAWSEGMENT* item = new DRAWSEGMENT();
|
||||
item->SetShape( S_CIRCLE );
|
||||
item->SetStart( aCenter );
|
||||
item->SetEnd( wxPoint( aCenter.x + aRadius, aCenter.y ) );
|
||||
item->SetWidth( aThickness );
|
||||
m_editPrimitives.emplace_back( item );
|
||||
m_shapesDirty = true;
|
||||
}
|
||||
|
||||
|
||||
void D_PAD::AddPrimitiveRect( const wxPoint& aStart, const wxPoint& aEnd, int aThickness )
|
||||
{
|
||||
PAD_CS_PRIMITIVE shape( S_RECT );
|
||||
shape.m_Start = aStart;
|
||||
shape.m_End = aEnd;
|
||||
shape.m_Thickness = aThickness;
|
||||
m_basicShapes.push_back( shape );
|
||||
DRAWSEGMENT* item = new DRAWSEGMENT();
|
||||
item->SetShape( S_RECT );
|
||||
item->SetStart( aStart );
|
||||
item->SetEnd( aEnd );
|
||||
item->SetWidth( aThickness );
|
||||
m_editPrimitives.emplace_back( item );
|
||||
m_shapesDirty = true;
|
||||
}
|
||||
|
||||
|
||||
void D_PAD::SetPrimitives( const std::vector<PAD_CS_PRIMITIVE>& aPrimitivesList )
|
||||
void D_PAD::SetPrimitives( const std::vector<std::shared_ptr<DRAWSEGMENT>>& aPrimitivesList )
|
||||
{
|
||||
// clear old list
|
||||
m_basicShapes.clear();
|
||||
m_editPrimitives.clear();
|
||||
|
||||
// Import to the basic shape list
|
||||
if( aPrimitivesList.size() )
|
||||
m_basicShapes = aPrimitivesList;
|
||||
m_editPrimitives = aPrimitivesList;
|
||||
|
||||
m_shapesDirty = true;
|
||||
}
|
||||
|
||||
|
||||
void D_PAD::AddPrimitives( const std::vector<PAD_CS_PRIMITIVE>& aPrimitivesList )
|
||||
void D_PAD::AddPrimitives( const std::vector<std::shared_ptr<DRAWSEGMENT>>& aPrimitivesList )
|
||||
{
|
||||
for( const auto& prim : aPrimitivesList )
|
||||
m_basicShapes.push_back( prim );
|
||||
for( const std::shared_ptr<DRAWSEGMENT>& prim : aPrimitivesList )
|
||||
m_editPrimitives.push_back( prim );
|
||||
|
||||
m_shapesDirty = true;
|
||||
}
|
||||
|
@ -257,56 +166,62 @@ void D_PAD::AddPrimitives( const std::vector<PAD_CS_PRIMITIVE>& aPrimitivesList
|
|||
// clear the basic shapes list and associated data
|
||||
void D_PAD::DeletePrimitivesList()
|
||||
{
|
||||
m_basicShapes.clear();
|
||||
m_editPrimitives.clear();
|
||||
m_shapesDirty = true;
|
||||
}
|
||||
|
||||
|
||||
void D_PAD::addCustomPadPrimitivesToPolygon( SHAPE_POLY_SET* aMergedPolygon, int aError ) const
|
||||
void D_PAD::addPadPrimitivesToPolygon( SHAPE_POLY_SET* aMergedPolygon, int aError ) const
|
||||
{
|
||||
SHAPE_POLY_SET polyset;
|
||||
|
||||
for( const PAD_CS_PRIMITIVE& bshape : m_basicShapes )
|
||||
for( const std::shared_ptr<DRAWSEGMENT>& primitive : m_editPrimitives )
|
||||
{
|
||||
switch( bshape.m_Shape )
|
||||
int lineWidth = primitive->GetWidth();
|
||||
|
||||
switch( primitive->GetShape() )
|
||||
{
|
||||
case S_CURVE:
|
||||
{
|
||||
std::vector<wxPoint> ctrlPoints = { bshape.m_Start, bshape.m_Ctrl1, bshape.m_Ctrl2,
|
||||
bshape.m_End };
|
||||
std::vector<wxPoint> ctrlPoints = { primitive->GetStart(), primitive->GetBezControl1(),
|
||||
primitive->GetBezControl2(), primitive->GetEnd() };
|
||||
BEZIER_POLY converter( ctrlPoints );
|
||||
std::vector< wxPoint> poly;
|
||||
converter.GetPoly( poly, bshape.m_Thickness );
|
||||
converter.GetPoly( poly, lineWidth );
|
||||
|
||||
for( unsigned ii = 1; ii < poly.size(); ii++ )
|
||||
{
|
||||
TransformSegmentToPolygon( polyset, poly[ ii - 1 ], poly[ ii ], aError,
|
||||
bshape.m_Thickness );
|
||||
TransformSegmentToPolygon( polyset, poly[ ii - 1 ], poly[ ii ], aError, lineWidth );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case S_SEGMENT: // usual segment : line with rounded ends
|
||||
{
|
||||
TransformSegmentToPolygon( polyset, bshape.m_Start, bshape.m_End, aError,
|
||||
bshape.m_Thickness );
|
||||
TransformSegmentToPolygon( polyset, primitive->GetStart(), primitive->GetEnd(),
|
||||
aError, lineWidth );
|
||||
break;
|
||||
}
|
||||
|
||||
case S_ARC: // Arc with rounded ends
|
||||
{
|
||||
TransformArcToPolygon( polyset, bshape.m_Start, bshape.m_End, bshape.m_ArcAngle,
|
||||
aError, bshape.m_Thickness );
|
||||
TransformArcToPolygon( polyset, primitive->GetStart(), primitive->GetEnd(),
|
||||
primitive->GetAngle(), aError, lineWidth );
|
||||
break;
|
||||
}
|
||||
|
||||
case S_CIRCLE: // ring or circle
|
||||
{
|
||||
if( bshape.m_Thickness ) // ring
|
||||
TransformRingToPolygon( polyset, bshape.m_Start, bshape.m_Radius, aError,
|
||||
bshape.m_Thickness );
|
||||
if( primitive->GetWidth() ) // ring
|
||||
{
|
||||
TransformRingToPolygon( polyset, primitive->GetStart(), primitive->GetRadius(),
|
||||
aError, lineWidth );
|
||||
}
|
||||
else // Filled circle
|
||||
TransformCircleToPolygon( polyset, bshape.m_Start, bshape.m_Radius, aError );
|
||||
{
|
||||
TransformCircleToPolygon( polyset, primitive->GetStart(), primitive->GetRadius(),
|
||||
aError );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -316,23 +231,23 @@ void D_PAD::addCustomPadPrimitivesToPolygon( SHAPE_POLY_SET* aMergedPolygon, int
|
|||
SHAPE_POLY_SET poly;
|
||||
poly.NewOutline();
|
||||
|
||||
if( bshape.m_Shape == S_RECT )
|
||||
if( primitive->GetShape() == S_RECT )
|
||||
{
|
||||
poly.Append( bshape.m_Start );
|
||||
poly.Append( bshape.m_End.x, bshape.m_Start.y );
|
||||
poly.Append( bshape.m_End );
|
||||
poly.Append( bshape.m_Start.x, bshape.m_End.y );
|
||||
poly.Append( primitive->GetStart() );
|
||||
poly.Append( primitive->GetEnd().x, primitive->GetStart().y );
|
||||
poly.Append( primitive->GetEnd() );
|
||||
poly.Append( primitive->GetStart().x, primitive->GetEnd().y );
|
||||
}
|
||||
else
|
||||
{
|
||||
for( const wxPoint& pt : bshape.m_Poly )
|
||||
for( const VECTOR2I& pt : primitive->GetPolyShape().Outline( 0 ).CPoints() )
|
||||
poly.Append( pt );
|
||||
}
|
||||
|
||||
if( bshape.m_Thickness )
|
||||
if( primitive->GetWidth() > 0 )
|
||||
{
|
||||
int numSegs = std::max( GetArcToSegmentCount( bshape.m_Thickness / 2, aError, 360.0 ), 6 );
|
||||
poly.Inflate( bshape.m_Thickness / 2, numSegs );
|
||||
int numSegs = std::max( GetArcToSegmentCount( lineWidth / 2, aError, 360.0 ), 6 );
|
||||
poly.Inflate( lineWidth / 2, numSegs );
|
||||
}
|
||||
|
||||
// Insert the polygon:
|
||||
|
@ -343,8 +258,8 @@ void D_PAD::addCustomPadPrimitivesToPolygon( SHAPE_POLY_SET* aMergedPolygon, int
|
|||
|
||||
default:
|
||||
// un-handled primitive
|
||||
wxASSERT_MSG( false, "D_PAD::addCustomPadPrimitivesToPolygon not implemented for "
|
||||
+ BOARD_ITEM::ShowShape( bshape.m_Shape ) );
|
||||
wxASSERT_MSG( false, "D_PAD::addPadPrimitivesToPolygon not implemented for "
|
||||
+ BOARD_ITEM::ShowShape( primitive->GetShape() ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -386,14 +301,14 @@ void D_PAD::MergePrimitivesAsPolygon( SHAPE_POLY_SET* aMergedPolygon ) const
|
|||
break;
|
||||
}
|
||||
|
||||
addCustomPadPrimitivesToPolygon( aMergedPolygon, maxError );
|
||||
addPadPrimitivesToPolygon( aMergedPolygon, maxError );
|
||||
}
|
||||
|
||||
|
||||
bool D_PAD::GetBestAnchorPosition( VECTOR2I& aPos )
|
||||
{
|
||||
SHAPE_POLY_SET poly;
|
||||
addCustomPadPrimitivesToPolygon( &poly, ARC_LOW_DEF );
|
||||
addPadPrimitivesToPolygon( &poly, ARC_LOW_DEF );
|
||||
|
||||
if( poly.OutlineCount() > 1 )
|
||||
return false;
|
||||
|
|
|
@ -659,7 +659,6 @@ void PCB_PAINTER::draw( const VIA* aVia, int aLayer )
|
|||
|
||||
void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer )
|
||||
{
|
||||
double m, n;
|
||||
double orientation = aPad->GetOrientation();
|
||||
|
||||
// Draw description layer
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
|
||||
%ignore std::vector<PAD_CS_PRIMITIVE>::resize;
|
||||
%ignore std::vector<PAD_CS_PRIMITIVE>::vector(size_type);
|
||||
%template(PAD_CS_PRIMITIVE_Vector) std::vector<PAD_CS_PRIMITIVE>;
|
||||
|
||||
%include pad_shapes.h
|
||||
%include class_pad.h
|
||||
|
|
|
@ -396,11 +396,20 @@ int FOOTPRINT_EDITOR_TOOLS::ExplodePadToShapes( const TOOL_EVENT& aEvent )
|
|||
|
||||
wxPoint anchor = pad->GetPosition();
|
||||
|
||||
for( auto prim : pad->GetPrimitives() )
|
||||
for( const std::shared_ptr<DRAWSEGMENT>& primitive : pad->GetPrimitives() )
|
||||
{
|
||||
auto ds = new EDGE_MODULE( board()->GetFirstModule() );
|
||||
EDGE_MODULE* ds = new EDGE_MODULE( board()->GetFirstModule() );
|
||||
|
||||
ds->SetShape( primitive->GetShape() );
|
||||
ds->SetWidth( primitive->GetWidth() );
|
||||
ds->SetStart( primitive->GetStart() );
|
||||
ds->SetEnd( primitive->GetEnd() );
|
||||
ds->SetBezControl1( primitive->GetBezControl1() );
|
||||
ds->SetBezControl2( primitive->GetBezControl2() );
|
||||
ds->SetAngle( primitive->GetAngle() );
|
||||
ds->SetPolyShape( primitive->GetPolyShape() );
|
||||
ds->SetLocalCoord();
|
||||
|
||||
prim.ExportTo( ds ); // ExportTo exports to a DRAWSEGMENT
|
||||
// Fix an arbitray draw layer for this EDGE_MODULE
|
||||
ds->SetLayer( Dwgs_User ); //pad->GetLayer() );
|
||||
ds->Move( anchor );
|
||||
|
@ -435,11 +444,11 @@ int FOOTPRINT_EDITOR_TOOLS::CreatePadFromShapes( const TOOL_EVENT& aEvent )
|
|||
bool multipleRefPadsFound = false;
|
||||
bool illegalItemsFound = false;
|
||||
|
||||
std::vector<PAD_CS_PRIMITIVE> shapes;
|
||||
std::vector<std::shared_ptr<DRAWSEGMENT>> shapes;
|
||||
|
||||
BOARD_COMMIT commit( m_frame );
|
||||
|
||||
for( auto item : selection )
|
||||
for( EDA_ITEM* item : selection )
|
||||
{
|
||||
switch( item->Type() )
|
||||
{
|
||||
|
@ -454,19 +463,18 @@ int FOOTPRINT_EDITOR_TOOLS::CreatePadFromShapes( const TOOL_EVENT& aEvent )
|
|||
|
||||
case PCB_MODULE_EDGE_T:
|
||||
{
|
||||
auto em = static_cast<EDGE_MODULE*> ( item );
|
||||
EDGE_MODULE* em = static_cast<EDGE_MODULE*>( item );
|
||||
DRAWSEGMENT* ds = new DRAWSEGMENT;
|
||||
|
||||
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 );
|
||||
ds->SetShape( em->GetShape() );
|
||||
ds->SetWidth( em->GetWidth() );
|
||||
ds->SetStart( em->GetStart() );
|
||||
ds->SetEnd( em->GetEnd() );
|
||||
ds->SetBezControl1( em->GetBezControl1() );
|
||||
ds->SetBezControl2( em->GetBezControl2() );
|
||||
ds->SetAngle( em->GetAngle() );
|
||||
ds->SetPolyShape( em->GetPolyShape() );
|
||||
shapes.emplace_back( ds );
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -534,12 +542,11 @@ int FOOTPRINT_EDITOR_TOOLS::CreatePadFromShapes( const TOOL_EVENT& aEvent )
|
|||
int maxError = board()->GetDesignSettings().m_MaxError;
|
||||
refPad->TransformShapeWithClearanceToPolygon( existingOutline, 0, maxError );
|
||||
|
||||
PAD_CS_PRIMITIVE shape( S_POLYGON );
|
||||
DRAWSEGMENT* shape = new DRAWSEGMENT;
|
||||
shape->SetShape( S_POLYGON );
|
||||
shape->SetPolyShape( existingOutline );
|
||||
|
||||
for( auto ii = existingOutline.Iterate(); ii; ii++ )
|
||||
shape.m_Poly.emplace_back( ii->x, ii->y );
|
||||
|
||||
shapes.push_back( shape );
|
||||
shapes.emplace_back( shape );
|
||||
|
||||
deltaAngle = refPad->GetOrientation();
|
||||
pad->SetOrientation( 0.0 );
|
||||
|
@ -589,10 +596,10 @@ int FOOTPRINT_EDITOR_TOOLS::CreatePadFromShapes( const TOOL_EVENT& aEvent )
|
|||
|
||||
|
||||
// relocate the shapes, they are relative to the anchor pad position
|
||||
for( auto& shape : shapes )
|
||||
for( std::shared_ptr<DRAWSEGMENT>& shape : shapes )
|
||||
{
|
||||
shape.Move( wxPoint( -anchor->x, -anchor->y ) );
|
||||
shape.Rotate( wxPoint( 0, 0 ), -deltaAngle );
|
||||
shape->Move( wxPoint( -anchor->x, -anchor->y ) );
|
||||
shape->Rotate( wxPoint( 0, 0 ), -deltaAngle );
|
||||
}
|
||||
|
||||
pad->SetPosition( wxPoint( anchor->x, anchor->y ) );
|
||||
|
@ -610,13 +617,12 @@ int FOOTPRINT_EDITOR_TOOLS::CreatePadFromShapes( const TOOL_EVENT& aEvent )
|
|||
return 0;
|
||||
}
|
||||
|
||||
auto padPtr = pad.release();
|
||||
D_PAD* padPtr = pad.release();
|
||||
|
||||
commit.Add( padPtr );
|
||||
for ( auto item : selection )
|
||||
{
|
||||
|
||||
for ( EDA_ITEM* item : selection )
|
||||
commit.Remove( item );
|
||||
}
|
||||
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
|
||||
commit.Push(_("Create Pad from Selected Shapes") );
|
||||
|
|
Loading…
Reference in New Issue