27#include <wx/statline.h>
28#include <wx/checkbox.h>
30#include <wx/radiobut.h>
60 bool aShowCopyLineWidth ) :
61 DIALOG_SHIM( aParent, wxID_ANY,
_(
"Conversion Settings" ), wxDefaultPosition,
62 wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ),
65 wxBoxSizer* mainSizer =
new wxBoxSizer( wxVERTICAL );
66 wxBoxSizer* topSizer =
new wxBoxSizer( wxVERTICAL );
67 SetSizer( mainSizer );
69 m_rbMimicLineWidth =
new wxRadioButton(
this, wxID_ANY,
_(
"Copy line width of first object" ) );
71 if( aShowCopyLineWidth )
76 topSizer->AddSpacer( 6 );
77 m_rbCenterline =
new wxRadioButton(
this, wxID_ANY,
_(
"Use centerlines" ) );
80 topSizer->AddSpacer( 6 );
81 m_rbEnvelope =
new wxRadioButton(
this, wxID_ANY,
_(
"Create bounding hull" ) );
84 m_gapLabel =
new wxStaticText(
this, wxID_ANY,
_(
"Gap:" ) );
85 m_gapCtrl =
new wxTextCtrl(
this, wxID_ANY );
86 m_gapUnits =
new wxStaticText(
this, wxID_ANY,
_(
"mm" ) );
89 m_widthLabel =
new wxStaticText(
this, wxID_ANY,
_(
"Line width:" ) );
94 wxBoxSizer* hullParamsSizer =
new wxBoxSizer( wxHORIZONTAL );
95 hullParamsSizer->Add(
m_gapLabel, 0, wxALIGN_CENTRE_VERTICAL, 5 );
96 hullParamsSizer->Add(
m_gapCtrl, 1, wxALIGN_CENTRE_VERTICAL|wxLEFT|wxRIGHT, 3 );
97 hullParamsSizer->Add(
m_gapUnits, 0, wxALIGN_CENTRE_VERTICAL, 5 );
98 hullParamsSizer->AddSpacer( 18 );
99 hullParamsSizer->Add(
m_widthLabel, 0, wxALIGN_CENTRE_VERTICAL, 5 );
100 hullParamsSizer->Add(
m_widthCtrl, 1, wxALIGN_CENTRE_VERTICAL|wxLEFT|wxRIGHT, 3 );
101 hullParamsSizer->Add(
m_widthUnits, 0, wxALIGN_CENTRE_VERTICAL, 5 );
103 topSizer->AddSpacer( 2 );
104 topSizer->Add( hullParamsSizer, 0, wxLEFT, 26 );
106 topSizer->AddSpacer( 15 );
107 m_cbDeleteOriginals =
new wxCheckBox(
this, wxID_ANY,
_(
"Delete source objects after conversion" ) );
110 wxStaticLine* line =
new wxStaticLine(
this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
112 topSizer->Add( line, 0, wxLEFT|wxRIGHT|wxTOP|wxEXPAND, 5 );
114 mainSizer->Add( topSizer, 1, wxALL|wxEXPAND, 10 );
116 wxBoxSizer* buttonsSizer =
new wxBoxSizer( wxHORIZONTAL );
117 buttonsSizer->AddStretchSpacer();
119 wxStdDialogButtonSizer* sdbSizer =
new wxStdDialogButtonSizer();
120 wxButton* sdbSizerOK =
new wxButton(
this, wxID_OK );
121 sdbSizer->AddButton( sdbSizerOK );
122 wxButton* sdbSizerCancel =
new wxButton(
this, wxID_CANCEL );
123 sdbSizer->AddButton( sdbSizerCancel );
126 buttonsSizer->Add( sdbSizer, 1, 0, 5 );
127 mainSizer->Add( buttonsSizer, 0, wxLEFT|wxRIGHT|wxBOTTOM|wxEXPAND, 5 );
137 m_rbEnvelope->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED,
211 m_selectionTool( nullptr ),
235 m_frame = getEditFrame<PCB_BASE_FRAME>();
260 auto canCreatePolyType = shapes || anyPolys || anyTracks;
263 canCreatePolyType = shapes || anyPolys || anyTracks || anyPads;
265 auto canCreateLines = anyPolys;
266 auto canCreateTracks = anyPolys || graphicToTrack;
267 auto canCreate = canCreatePolyType
280 m_menu->AppendSeparator();
289 m_menu->AppendSeparator();
301 std::vector<SHAPE_POLY_SET> polys;
310 if( selection.
Empty() )
319 item->ClearTempFlags();
343 for(
int jj = 0; jj < polySet.
HoleCount( ii ); ++jj )
344 polys.back().AddHole( polySet.
Hole( ii, jj ) );
354 if( !getPolys( preflightSettings ) )
366 bool showCopyLineWidth =
true;
369 if(
dynamic_cast<PAD*
>( selection.
Front() ) )
374 showCopyLineWidth =
false;
379 if( dlg.ShowModal() != wxID_OK )
392 if( resolvedSettings.
m_Gap > 0 )
396 if( !getPolys( resolvedSettings ) )
415 if( candidate->HasLineStroke() )
417 pos = candidate->GetPosition();
424 topLeftItem = candidate;
434 COLOR4D::UNSPECIFIED ) );
439 commit.
Add( graphic );
450 zoneInfo.
m_Layers.reset().set( destLayer );
475 if( ret == wxID_CANCEL )
499 for(
EDA_ITEM* item : selectionCopy )
509 commit.
Push(
_(
"Convert to Polygon" ) );
511 commit.
Push(
_(
"Create Polygon" ) );
516 commit.
Push(
_(
"Convert to Zone" ) );
518 commit.
Push(
_(
"Create Zone" ) );
535 int chainingEpsilon = 100;
541 std::map<VECTOR2I, std::vector<std::pair<int, EDA_ITEM*>>> connections;
542 std::deque<EDA_ITEM*> toCheck;
547 return ( aLeft - aRight ).SquaredEuclideanNorm() <=
SEG::Square( aLimit );
550 auto findInsertionPoint =
553 if( connections.count( aPoint ) )
556 for(
const auto& candidatePair : connections )
558 if( closeEnough( aPoint, candidatePair.first, chainingEpsilon ) )
559 return candidatePair.first;
569 toCheck.push_back( item );
570 connections[findInsertionPoint( seg->A )].emplace_back( std::make_pair( 0, item ) );
571 connections[findInsertionPoint( seg->B )].emplace_back( std::make_pair( 1, item ) );
575 while( !toCheck.empty() )
577 std::vector<BOARD_ITEM*> insertedItems;
579 EDA_ITEM* candidate = toCheck.front();
592 &&
static_cast<PCB_SHAPE*
>( aItem )->GetShape() == SHAPE_T::ARC ) )
613 insertedItems.push_back(
static_cast<BOARD_ITEM*
>( aItem ) );
615 else if( aItem->
IsType( { PCB_SHAPE_LOCATE_BEZIER_T } ) )
619 if( aAnchor == graphic->
GetStart() )
645 insertedItems.push_back(
static_cast<BOARD_ITEM*
>( aItem ) );
649 VECTOR2I& point = ( aAnchor == nextSeg->A ) ? nextSeg->B : nextSeg->A;
654 outline.
Insert( 0, point );
656 insertedItems.push_back(
static_cast<BOARD_ITEM*
>( aItem ) );
670 insert( aItem, aAnchor, aDirection );
675 VECTOR2I nextAnchor = ( aAnchor == anchors->A ) ? anchors->B : anchors->A;
677 for( std::pair<int, EDA_ITEM*> pair : connections[nextAnchor] )
679 if( pair.second == aItem )
682 process( pair.second, nextAnchor, aDirection );
696 insert( candidate, anchors->A,
true );
699 process( candidate, anchors->B,
true );
704 for( std::pair<int, EDA_ITEM*> possibleLeft : connections[anchors->A] )
706 if( possibleLeft.second != candidate )
708 left = possibleLeft.second;
717 || !closeEnough( outline.
GetPoint( 0 ), outline.
GetPoint( -1 ), chainingEpsilon ) )
719 for(
EDA_ITEM* item : insertedItems )
738 insertedItems.clear();
756 switch( item->Type() )
805 switch( item->Type() )
861 for(
int i = aCollector.
GetCount() - 1; i >= 0; --i )
863 BOARD_ITEM* item = aCollector[i];
865 switch( item->Type() )
868 switch( static_cast<PCB_SHAPE*>( item )->GetShape() )
870 case SHAPE_T::SEGMENT:
873 case SHAPE_T::RECTANGLE:
877 aCollector.Remove( item );
886 aCollector.Remove( item );
891 if( selection.Empty() )
899 switch( aItem->Type() )
902 set = *
static_cast<ZONE*
>( aItem )->Outline();
929 wxFAIL_MSG( wxT(
"Unhandled graphic shape type in PolyToLines - getPolySet" ) );
935 wxFAIL_MSG( wxT(
"Unhandled type in PolyToLines - getPolySet" ) );
945 std::vector<SEG> segs;
948 wxASSERT( aPoly.VertexCount() >= 2 );
950 for(
int i = 1; i < aPoly.VertexCount(); i++ )
951 segs.emplace_back(
SEG( aPoly.CVertex( i - 1 ), aPoly.CVertex( i ) ) );
953 segs.emplace_back(
SEG( aPoly.CVertex( aPoly.VertexCount() - 1 ),
954 aPoly.CVertex( 0 ) ) );
969 auto handleGraphicSeg =
1019 if( handleGraphicSeg( item ) )
1023 std::vector<SEG> segs = getSegList( polySet );
1027 for(
SEG& seg : segs )
1034 commit.Add( graphic );
1044 for(
SEG& seg : segs )
1050 commit.Add( graphic );
1056 for(
SEG& seg : segs )
1063 commit.Add( track );
1069 commit.Push(
_(
"Create Lines" ) );
1080 for(
int i = aCollector.
GetCount() - 1; i >= 0; --i )
1082 BOARD_ITEM* item = aCollector[i];
1084 if( !( item->Type() == PCB_SHAPE_T ||
1085 item->Type() == PCB_TRACE_T ) )
1087 aCollector.Remove( item );
1092 EDA_ITEM* source = selection.Front();
1096 const double offsetRatio = 0.1;
1098 if( std::optional<SEG> seg = getStartEndPoints( source ) )
1103 VECTOR2I normal = ( seg->B - seg->A ).Perpendicular().Resize( offsetRatio * seg->Length() );
1104 mid = seg->Center() +
normal;
1156 commit.Push(
_(
"Create Arc" ) );
1164 switch( aItem->
Type() )
1172 case SHAPE_T::SEGMENT:
1175 case SHAPE_T::BEZIER:
1177 return std::nullopt;
1183 return std::nullopt;
1200 return std::nullopt;
static PGM_BASE * process
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
Container for design settings for a BOARD object.
int GetLayerClass(PCB_LAYER_ID aLayer) const
int m_LineThickness[LAYER_CLASS_COUNT]
Abstract interface for BOARD_ITEMs capable of storing other items inside.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
virtual STROKE_PARAMS GetStroke() const
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
FOOTPRINT * GetParentFootprint() const
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
int GetCount() const
Return the number of objects in the list.
COMMIT & Remove(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been removed.
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been added.
wxRadioButton * m_rbEnvelope
CONVERT_SETTINGS * m_settings
bool TransferDataToWindow() override
CONVERT_SETTINGS_DIALOG(EDA_DRAW_FRAME *aParent, CONVERT_SETTINGS *aSettings, bool aShowCopyLineWidth)
wxStaticText * m_gapLabel
wxRadioButton * m_rbMimicLineWidth
wxRadioButton * m_rbCenterline
void onRadioButton(wxCommandEvent &aEvent)
wxStaticText * m_gapUnits
bool TransferDataFromWindow() override
wxCheckBox * m_cbDeleteOriginals
wxStaticText * m_widthLabel
~CONVERT_SETTINGS_DIALOG()
wxStaticText * m_widthUnits
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
void SetupStandardButtons(std::map< int, wxString > aLabels={})
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
bool IsType(FRAME_T aType) const
The base class for create windows for drawing purpose.
A base class for most all the KiCad significant classes used in schematics and boards.
virtual VECTOR2I GetPosition() const
void SetFlags(EDA_ITEM_FLAGS aMask)
KICAD_T Type() const
Returns the type of object.
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
EDA_ITEM_FLAGS GetFlags() const
void SetCenter(const VECTOR2I &aCenter)
FILL_T GetFillMode() const
SHAPE_POLY_SET & GetPolyShape()
void SetFilled(bool aFlag)
void SetPolyShape(const SHAPE_POLY_SET &aShape)
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
void SetStart(const VECTOR2I &aStart)
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
void SetShape(SHAPE_T aShape)
const std::vector< VECTOR2I > & GetBezierPoints() const
void SetEnd(const VECTOR2I &aEnd)
void SetFillMode(FILL_T aFill)
VECTOR2I GetArcMid() const
Used when the right click button is pressed, or when the select tool is in effect.
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
static TOOL_ACTION convertToKeepout
static TOOL_ACTION convertToTracks
static TOOL_ACTION convertToLines
static TOOL_ACTION convertToZone
static TOOL_ACTION convertToPoly
static TOOL_ACTION convertToArc
static TOOL_ACTION createArray
Tool for creating an array of objects.
void SetMid(const VECTOR2I &aMid)
std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
Common, abstract interface for edit frames.
PCB_LAYER_ID SelectOneLayer(PCB_LAYER_ID aDefaultLayer, LSET aNotAllowedLayersMask=LSET(), wxPoint aDlgPosition=wxDefaultPosition)
Show the dialog box for a layer selection.
virtual PCB_LAYER_ID GetActiveLayer() const
const ZONE_SETTINGS & GetZoneSettings() const
virtual BOARD_ITEM_CONTAINER * GetModel() const =0
static SELECTION_CONDITION SameLayer()
Creates a functor that tests if selection contains items that belong exclusively to the same layer.
int GetWidth() const override
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the shape to a closed polygon.
STROKE_PARAMS GetStroke() const override
void SetStroke(const STROKE_PARAMS &aStroke) override
void SetWidth(int aWidth)
void SetEnd(const VECTOR2I &aEnd)
void SetStart(const VECTOR2I &aStart)
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the track shape to a closed polygon.
const VECTOR2I & GetStart() const
const VECTOR2I & GetEnd() const
static SEG::ecoord Square(int a)
Class that groups generic conditions for selected items.
static SELECTION_CONDITION MoreThan(int aNumber)
Create a functor that tests if the number of selected items is greater than the value given as parame...
static SELECTION_CONDITION Count(int aNumber)
Create a functor that tests if the number of selected items is equal to the value given as parameter.
static SELECTION_CONDITION OnlyTypes(std::vector< KICAD_T > aTypes)
Create a functor that tests if the selected items are only of given types.
bool Empty() const
Checks if there is anything selected.
SHAPE_ARC Reversed() const
const VECTOR2I & GetP0() const
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
virtual const VECTOR2I GetPoint(int aIndex) const override
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
int PointCount() const
Return the number of points (vertices) in this line chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
void Insert(size_t aVertex, const VECTOR2I &aP)
Represent a set of closed polygons.
void ClearArcs()
Removes all arc references from all the outlines and holes in the polyset.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
int HoleCount(int aOutline) const
Returns the number of holes in a given outline.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
void Simplify(POLYGON_MODE aFastMode)
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections) For aFastMo...
SHAPE_LINE_CHAIN & Hole(int aOutline, int aHole)
Return the reference to aHole-th hole in the aIndex-th outline.
int OutlineCount() const
Return the number of outlines in the set.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
Simple container to manage line stroke parameters.
virtual long long int GetValue()
Return the current value in Internal Units.
void Enable(bool aEnable)
Enable/disable the label, widget and units label.
virtual void SetValue(long long int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
ZONE_SETTINGS handles zones parameters.
void SetIsRuleArea(bool aEnable)
void ExportSetting(ZONE &aTarget, bool aFullExport=true) const
Function ExportSetting copy settings to a given zone.
Handle a list of polygons defining a copper zone.
void HatchBorder()
Compute the hatch lines depending on the hatch parameters and stores it in the zone's attribute m_bor...
SHAPE_POLY_SET * Outline()
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
This file is part of the common library.
int InvokeCopperZonesEditor(PCB_BASE_FRAME *aCaller, ZONE_SETTINGS *aSettings, CONVERT_SETTINGS *aConvertSettings)
Function InvokeCopperZonesEditor invokes up a modal dialog window for copper zone editing.
int InvokeNonCopperZonesEditor(PCB_BASE_FRAME *aParent, ZONE_SETTINGS *aSettings, CONVERT_SETTINGS *aConvertSettings)
Function InvokeNonCopperZonesEditor invokes up a modal dialog window for non-copper zone editing.
int InvokeRuleAreaEditor(PCB_BASE_FRAME *aCaller, ZONE_SETTINGS *aZoneSettings, CONVERT_SETTINGS *aConvertSettings)
Function InvokeRuleAreaEditor invokes up a modal dialog window for copper zone editing.
#define SKIP_STRUCT
flag indicating that the structure should be ignored
@ ARC
use RECTANGLE instead of RECT to avoid collision in a Windows header
bool IsNonCopperLayer(int aLayerId)
Test whether a layer is a non copper layer.
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
This file contains miscellaneous commonly used macros and functions.
CONVERT_STRATEGY m_Strategy
const VECTOR2I CalcArcCenter(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Determine the center of an arc or circle given three points on its circumference.
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_ZONE_T
class ZONE, a copper pour area
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
@ PCB_SHAPE_LOCATE_CIRCLE_T
@ PCB_SHAPE_LOCATE_SEGMENT_T
@ PCB_SHAPE_LOCATE_RECT_T
@ PCB_SHAPE_LOCATE_BEZIER_T
@ PCB_PAD_T
class PAD, a pad in a footprint
@ PCB_SHAPE_LOCATE_POLY_T
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".