55#include <wx/richmsgdlg.h> 
   56#include <wx/choicdlg.h> 
   57#include <unordered_set> 
   58#include <unordered_map> 
   62                                        const std::vector<PAD*>& aPads,
 
   63                                        const wxString& aDialogTitle,
 
   64                                        bool& aIncludeConnectedPads )
 
   68        aIncludeConnectedPads = 
true;
 
   72    std::unordered_set<PAD*> uniquePads( aPads.begin(), aPads.end() );
 
   75    msg.Printf( 
_( 
"%zu unselected pad(s) are connected to these nets. How do you want to proceed?" ),
 
   79    details << 
_( 
"Connected tracks, vias, and other non-zone copper items will still swap nets" 
   80                  " even if you ignore the unselected pads." )
 
   82            << 
_( 
"Unselected pads:" ) << 
'\n';
 
   84    for( 
PAD* 
pad : uniquePads )
 
   87        details << wxS( 
"  • " ) << ( fp ? fp->
GetReference() : 
_( 
"<no reference designator>" ) ) << wxS( 
":" )
 
   88                << 
pad->GetNumber() << 
'\n';
 
   92    wxRichMessageDialog dlg( aFrame, msg, aDialogTitle, wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxICON_WARNING );
 
   93    dlg.SetYesNoLabels( 
_( 
"Ignore Unselected Pads" ), 
_( 
"Swap All Connected Pads" ) );
 
   94    dlg.SetExtendedMessage( details );
 
   96    int ret = dlg.ShowModal();
 
   98    if( ret == wxID_CANCEL )
 
  101    aIncludeConnectedPads = ( ret == wxID_NO );
 
 
  122                for( 
int i = aCollector.
GetCount() - 1; i >= 0; --i )
 
  127                        aCollector.
Remove( item );
 
  140        commit = &localCommit;
 
  142    std::vector<EDA_ITEM*> sorted = 
selection.GetItemsSortedBySelectionOrder();
 
  148    for( 
size_t i = 0; i < sorted.size() - 1; i++ )
 
  151        EDA_ITEM* edaItemB = sorted[( i + 1 ) % sorted.size()];
 
  161        std::swap( aPos, bPos );
 
  184            std::swap( aAngle, bAngle );
 
  194            std::swap( aLayer, bLayer );
 
  200    if( !localCommit.
Empty() )
 
  201        localCommit.
Push( 
_( 
"Swap" ) );
 
 
  224    std::vector<EDA_ITEM*> orderedPads = 
selection.GetItemsSortedBySelectionOrder();
 
  225    std::vector<PAD*>      pads;
 
  226    const size_t           padsCount = orderedPads.size();
 
  229        pads.push_back( 
static_cast<PAD*
>( 
static_cast<BOARD_ITEM*
>( it ) ) );
 
  233    std::vector<int>         originalNets( padsCount );
 
  234    std::unordered_set<PAD*> selectedPads;
 
  236    for( 
size_t i = 0; i < padsCount; ++i )
 
  238        originalNets[i] = pads[i]->GetNetCode();
 
  239        selectedPads.insert( pads[i] );
 
  244    for( 
size_t i = 1; i < padsCount; ++i )
 
  246        if( originalNets[i] != originalNets[0] )
 
  257    auto newNetForIndex = [&]( 
size_t i )
 
  259            return originalNets[( i + 1 ) % padsCount];
 
  267        commit = &localCommit;
 
  270    std::shared_ptr<CONNECTIVITY_DATA> connectivity = 
board()->GetConnectivity();
 
  273    std::unordered_map<BOARD_CONNECTED_ITEM*, int> itemNewNets;
 
  274    std::vector<PAD*>                              nonSelectedPadsToChange;
 
  276    for( 
size_t i = 0; i < padsCount; ++i )
 
  279        int  fromNet = originalNets[i];
 
  280        int  toNet = newNetForIndex( i );
 
  297            if( ci->GetNetCode() != fromNet )
 
  301            itemNewNets[ci] = toNet;
 
  305                PAD* otherPad = 
static_cast<PAD*
>( ci );
 
  307                if( !selectedPads.count( otherPad ) )
 
  308                    nonSelectedPadsToChange.push_back( otherPad );
 
  313    bool includeConnectedPads = 
true;
 
  322    for( 
size_t i = 0; i < padsCount; ++i )
 
  324        commit->
Modify( pads[i] );
 
  325        pads[i]->SetNetCode( newNetForIndex( i ) );
 
  329    for( 
const auto& itemNewNet : itemNewNets )
 
  332        int                   newNet = itemNewNet.second;
 
  336            PAD* p = 
static_cast<PAD*
>( item );
 
  338            if( selectedPads.count( p ) )
 
  341            if( !includeConnectedPads )
 
  349    if( !localCommit.
Empty() )
 
  350        localCommit.
Push( 
_( 
"Swap Pad Nets" ) );
 
 
  368    auto showError = [
this]()
 
  370            frame()->ShowInfoBarError( 
_( 
"Gate swapping must be performed on pads within one multi-gate footprint." ) );
 
  392        else if( fp && targetFp != fp )
 
  399    if( fail || !targetFp || targetFp->
GetUnitInfo().size() < 2 )
 
  409    std::vector<bool> unitHit( units.size(), 
false );
 
  410    std::vector<int>  unitOrder;
 
  412    std::vector<EDA_ITEM*> orderedPads = 
selection.GetItemsSortedBySelectionOrder();
 
  418        const wxString& padNum = 
pad->GetNumber();
 
  421        for( 
size_t i = 0; i < units.size(); ++i )
 
  423            for( 
const auto& p : units[i].m_pins )
 
  427                    unitIdx = 
static_cast<int>( i );
 
  430                        unitOrder.push_back( unitIdx );
 
  443    std::vector<int> activeUnitIdx;
 
  446    if( unitOrder.size() >= 2 )
 
  448        activeUnitIdx = unitOrder;
 
  449        sourceIdx = unitOrder.front();
 
  452    else if( unitOrder.size() == 1 && aEvent.
HasParameter() )
 
  454        sourceIdx = unitOrder.front();
 
  455        wxString targetUnitByName = aEvent.
Parameter<wxString>();
 
  459        for( 
size_t i = 0; i < units.size(); ++i )
 
  461            if( 
static_cast<int>( i ) == sourceIdx )
 
  464            if( units[i].m_pins.size() == units[sourceIdx].m_pins.size() && units[i].m_unitName == targetUnitByName )
 
  466                targetIdx = 
static_cast<int>( i );
 
  476        activeUnitIdx.push_back( sourceIdx );
 
  477        activeUnitIdx.push_back( targetIdx );
 
  486    const size_t pinCount = units[activeUnitIdx.front()].m_pins.size();
 
  488    for( 
int idx : activeUnitIdx )
 
  490        if( units[idx].m_pins.size() != pinCount )
 
  492            frame()->ShowInfoBarError( 
_( 
"Gate swapping must be performed on gates with equal pin counts." ) );
 
  498    const size_t                   unitCount = activeUnitIdx.size();
 
  499    std::vector<std::vector<PAD*>> unitPads( unitCount );
 
  500    std::vector<std::vector<int>>  unitNets( unitCount );
 
  502    for( 
size_t ui = 0; ui < unitCount; ++ui )
 
  504        int         uidx = activeUnitIdx[ui];
 
  505        const auto& pins = units[uidx].m_pins;
 
  507        for( 
size_t pi = 0; pi < pinCount; ++pi )
 
  513                frame()->ShowInfoBarError( 
_( 
"Gate swapping failed: pad in unit missing from footprint." ) );
 
  517            unitPads[ui].push_back( p );
 
  525    for( 
size_t pi = 0; pi < pinCount && allSame; ++pi )
 
  527        int refNet = unitNets[0][pi];
 
  529        for( 
size_t ui = 1; ui < unitCount; ++ui )
 
  531            if( unitNets[ui][pi] != refNet )
 
  541        frame()->ShowInfoBarError( 
_( 
"Gate swapping has no effect: all selected gates have identical nets." ) );
 
  550        commit = &localCommit;
 
  552    std::shared_ptr<CONNECTIVITY_DATA> connectivity = 
board()->GetConnectivity();
 
  555    std::unordered_map<BOARD_CONNECTED_ITEM*, int> itemNewNets;
 
  556    std::vector<PAD*>                              nonSelectedPadsToChange;
 
  559    std::unordered_set<PAD*> swapPads;
 
  561    for( 
const auto& v : unitPads )
 
  562        swapPads.insert( v.begin(), v.end() );
 
  565    auto scheduleForPad = [&]( 
PAD* 
pad, 
int fromNet, 
int toNet )
 
  581                if( ci->GetNetCode() != fromNet )
 
  584                itemNewNets[ ci ] = toNet;
 
  588                    PAD* other = 
static_cast<PAD*
>( ci );
 
  590                    if( !swapPads.count( other ) )
 
  591                        nonSelectedPadsToChange.push_back( other );
 
  597    for( 
size_t pi = 0; pi < pinCount; ++pi )
 
  599        for( 
size_t ui = 0; ui < unitCount; ++ui )
 
  602            size_t toIdx = ( ui + 1 ) % unitCount;
 
  604            PAD* padFrom = unitPads[fromIdx][pi];
 
  605            int  fromNet = unitNets[fromIdx][pi];
 
  606            int  toNet = unitNets[toIdx][pi];
 
  608            scheduleForPad( padFrom, fromNet, toNet );
 
  612    bool includeConnectedPads = 
true;
 
  620    for( 
size_t pi = 0; pi < pinCount; ++pi )
 
  623        for( 
size_t ui = 0; ui < unitCount; ++ui )
 
  625            size_t toIdx = ( ui + 1 ) % unitCount;
 
  626            PAD*   
pad = unitPads[ui][pi];
 
  627            int    newNet = unitNets[toIdx][pi];
 
  630            pad->SetNetCode( newNet );
 
  635    for( 
const auto& 
kv : itemNewNets )
 
  638        int                   newNet = 
kv.second;
 
  642            PAD* p = 
static_cast<PAD*
>( item );
 
  644            if( swapPads.count( p ) )
 
  647            if( !includeConnectedPads )
 
  655    if( !localCommit.
Empty() )
 
  656        localCommit.
Push( 
_( 
"Swap Gate Nets" ) );
 
 
  682                for( 
int i = aCollector.
GetCount() - 1; i >= 0; --i )
 
  687                        aCollector.
Remove( item );
 
  693    std::vector<FOOTPRINT*> footprintsToPack;
 
  696        footprintsToPack.push_back( 
static_cast<FOOTPRINT*
>( item ) );
 
  698    if( footprintsToPack.empty() )
 
  701    BOX2I footprintsBbox;
 
  707        footprintsBbox.
Merge( fp->GetBoundingBox( 
false ) );
 
  713        commit.
Push( 
_( 
"Pack Footprints" ) );
 
 
  750            localCommit.
Push( 
_( 
"Move" ) );
 
 
  767    typedef std::numeric_limits<int> coord_limits;
 
  769    static const double max = coord_limits::max() - (int) 
COORDS_PADDING;
 
  770    static const double min = -max;
 
  773    testBox.
Offset( aBBoxOffset );
 
  782    testBox.
Offset( aMovement );
 
  790    if( testBox.
GetTop() < min )
 
 
  811    std::unique_ptr<STATUS_TEXT_POPUP> statusPopup;
 
  837    controls->ForceCursorPosition( 
false );
 
  839    auto displayConstraintsMessage =
 
  847                    msg = 
_( 
"Angle snap lines: 45°" );
 
  851                    msg = 
_( 
"Angle snap lines: 90°" );
 
  862    auto updateStatusPopup =
 
  863            [&]( 
EDA_ITEM* item, 
size_t ii, 
size_t count )
 
  865                wxString popuptext = 
_( 
"Click to place %s (item %zu of %zu)\n" 
  866                                     "Press <esc> to cancel all; double-click to finish" );
 
  878                    msg = wxString::Format( 
_( 
"%s pad %s" ), fp->
GetReference(), 
pad->GetNumber() );
 
  886                    statusPopup = std::make_unique<STATUS_TEXT_POPUP>( 
frame() );
 
  888                statusPopup->SetText( wxString::Format( popuptext, msg, ii, count ) );
 
  891    std::vector<BOARD_ITEM*> sel_items;         
 
  892    std::vector<BOARD_ITEM*> orig_items;        
 
  901                orig_items.push_back( boardItem );
 
  903            sel_items.push_back( boardItem );
 
  911                sel_items.push_back( 
pad );
 
  921    if( moveWithReference && !
pickReferencePoint( 
_( 
"Select reference point for move..." ), 
"", 
"",
 
  922                                                  pickedReferencePoint ) )
 
  927        editFrame->
PopTool( pushedEvent );
 
  931    if( moveIndividually )
 
  938                orig_items.push_back( 
static_cast<BOARD_ITEM*
>( item ) );
 
  941        updateStatusPopup( orig_items[ itemIdx ], itemIdx + 1, orig_items.size() );
 
  942        statusPopup->Popup();
 
  944        canvas()->SetStatusPopup( statusPopup->GetPanel() );
 
  950        sel_items.push_back( orig_items[ itemIdx ] );
 
  953    bool            restore_state = 
false;
 
  954    VECTOR2I        originalPos = originalCursorPos;  
 
  957    bool            updateBBox = 
true;
 
  963    bool            enableLocalRatsnest = 
true;
 
  966    bool eatFirstMouseUp = 
true;
 
  972    AXIS_LOCK axisLock = AXIS_LOCK::NONE;
 
  973    long      lastArrowKeyAction = 0;
 
  976    std::unique_ptr<DRC_INTERACTIVE_COURTYARD_CLEARANCE> drc_on_move = 
nullptr;
 
  978    if( showCourtyardConflicts )
 
  980        std::shared_ptr<DRC_ENGINE> drcEngine = 
m_toolMgr->GetTool<
DRC_TOOL>()->GetDRCEngine();
 
  982        drc_on_move->Init( 
board );
 
  985    auto configureAngleSnap =
 
  988                std::vector<VECTOR2I> directions;
 
 1004                grid.SetSnapLineDirections( directions );
 
 1006                if( directions.empty() )
 
 1008                    grid.ClearSnapLine();
 
 1012                    grid.SetSnapLineOrigin( originalPos );
 
 1016    configureAngleSnap( angleSnapMode );
 
 1017    displayConstraintsMessage( angleSnapMode );
 
 1033            eatFirstMouseUp = 
false;
 
 1046                bool redraw3D = 
false;
 
 1055                    VECTOR2I keyboardPos( 
controls->GetSettings().m_lastKeyboardCursorPosition );
 
 1056                    long action = 
controls->GetSettings().m_lastKeyboardCursorCommand;
 
 1058                    grid.SetSnap( 
false );
 
 1064                        if( axisLock == AXIS_LOCK::HORIZONTAL )
 
 1070                                axisLock = AXIS_LOCK::NONE;
 
 1076                            axisLock = AXIS_LOCK::HORIZONTAL;
 
 1081                        if( axisLock == AXIS_LOCK::VERTICAL )
 
 1087                                axisLock = AXIS_LOCK::NONE;
 
 1093                            axisLock = AXIS_LOCK::VERTICAL;
 
 1097                    lastArrowKeyAction = action;
 
 1103                    m_cursor = 
grid.BestSnapAnchor( mousePos, layers, selectionGrid, sel_items );
 
 1106                if( axisLock == AXIS_LOCK::HORIZONTAL )
 
 1108                else if( axisLock == AXIS_LOCK::VERTICAL )
 
 1116                    originalBBox = 
BOX2I();
 
 1135                bboxMovement += movement;
 
 1142                        item->Move( movement );
 
 1154                if( redraw3D && allowRedraw3D )
 
 1157                if( showCourtyardConflicts && drc_on_move->m_FpInMove.size() )
 
 1160                    drc_on_move->UpdateConflicts( 
m_toolMgr->GetView(), 
true );
 
 1181                            enableLocalRatsnest = 
false;
 
 1194                            static_cast<PCB_SHAPE*
>( item )->UpdateHatching();
 
 1196                        item->RunOnChildren(
 
 1202                                        static_cast<PCB_SHAPE*
>( child )->UpdateHatching();
 
 1213                    grid.SetAuxAxes( 
false );
 
 1234                    if( showCourtyardConflicts )
 
 1236                        std::vector<FOOTPRINT*>& FPs = drc_on_move->m_FpInMove;
 
 1241                                FPs.push_back( 
static_cast<FOOTPRINT*
>( item ) );
 
 1243                            item->RunOnChildren(
 
 1247                                            FPs.push_back( 
static_cast<FOOTPRINT*
>( child ) );
 
 1260                    if( moveWithReference )
 
 1262                        selection.SetReferencePoint( pickedReferencePoint );
 
 1267                        controls->ForceCursorPosition( 
true, pickedReferencePoint );
 
 1280                        selection.SetReferencePoint( dragOrigin );
 
 1284                            grid.SetSnapLineOrigin( dragOrigin );
 
 1286                        grid.SetAuxAxes( 
true, dragOrigin );
 
 1299                    originalPos = 
selection.GetReferencePoint();
 
 1315            if( enableLocalRatsnest )
 
 1323            restore_state = 
true; 
 
 1332            restore_state = 
true; 
 
 1356            eatFirstMouseUp = 
false;
 
 1364                eatFirstMouseUp = 
false;
 
 1371                    orig_items[itemIdx]->SetPosition( originalPos );
 
 1373                view()->Update( orig_items[itemIdx] );
 
 1376                if( ++itemIdx < orig_items.size() )
 
 1384                    selection.SetReferencePoint( originalPos );
 
 1389                    sel_items.push_back( nextItem );
 
 1390                    updateStatusPopup( nextItem, itemIdx + 1, orig_items.size() );
 
 1405            if( moveIndividually )
 
 1406                orig_items[itemIdx]->SetPosition( originalPos );
 
 1413            configureAngleSnap( angleSnapMode );
 
 1414            displayConstraintsMessage( angleSnapMode );
 
 1439    } 
while( ( evt = 
Wait() ) ); 
 
 1442    if( showCourtyardConflicts )
 
 1443        drc_on_move->ClearConflicts( 
m_toolMgr->GetView() );
 
 1445    controls->ForceCursorPosition( 
false );
 
 1460        if( sel_items.size() == 1 && sel_items.back()->Type() == 
PCB_GENERATOR_T )
 
 1468        if( sel_items.size() == 1 && sel_items.back()->Type() == 
PCB_GENERATOR_T )
 
 1474        EDA_ITEMS oItems( orig_items.begin(), orig_items.end() );
 
 1481    editFrame->
PopTool( pushedEvent );
 
 1484    return !restore_state;
 
 
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
 
static TOOL_ACTION duplicate
 
static TOOL_ACTION doDelete
 
static TOOL_ACTION cursorClick
 
static TOOL_ACTION increment
 
static TOOL_ACTION selectionClear
Clear the current selection.
 
static TOOL_ACTION refreshPreview
 
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
 
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
 
virtual void Revert() override
Revert the commit by restoring the modified items state.
 
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
 
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
 
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 void Move(const VECTOR2I &aMoveVector)
Move this object.
 
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
 
Information pertinent to a Pcbnew printed circuit board.
 
constexpr const Vec & GetPosition() const
 
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
 
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
 
constexpr coord_type GetLeft() const
 
constexpr const Vec & GetOrigin() const
 
constexpr coord_type GetRight() const
 
constexpr const SizeVec & GetSize() const
 
constexpr coord_type GetTop() const
 
constexpr void Offset(coord_type dx, coord_type dy)
 
constexpr coord_type GetBottom() const
 
int GetCount() const
Return the number of objects in the list.
 
void Remove(int aIndex)
Remove the item at aIndex (first position is 0).
 
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
 
void DisplayConstraintsMsg(const wxString &msg)
 
void SetCurrentCursor(KICURSOR aCursor)
Set the current cursor shape for this panel.
 
A base class for most all the KiCad significant classes used in schematics and boards.
 
virtual VECTOR2I GetPosition() const
 
virtual void SetPosition(const VECTOR2I &aPos)
 
wxString GetTypeDesc() const
Return a translated description of the type for this EDA_ITEM for display in user facing messages.
 
void SetFlags(EDA_ITEM_FLAGS aMask)
 
KICAD_T Type() const
Returns the type of object.
 
EDA_ITEM * GetParent() const
 
virtual const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
 
static const TOOL_EVENT SelectedEvent
 
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
 
static const TOOL_EVENT SelectedItemsMoved
Used to inform tools that the selection should temporarily be non-editable.
 
Used when the right click button is pressed, or when the select tool is in effect.
 
An interface for classes handling user events controlling the view behavior such as zooming,...
 
bool IsBOARD_ITEM() const
 
LSET is a set of PCB_LAYER_IDs.
 
DISPLAY_OPTIONS m_Display
 
bool m_ShowCourtyardCollisions
 
static TOOL_ACTION mirrorH
Mirroring of selected items.
 
static TOOL_ACTION genFinishEdit
 
static TOOL_ACTION hideLocalRatsnest
 
static TOOL_ACTION genStartEdit
 
static TOOL_ACTION moveWithReference
move with a reference point
 
static TOOL_ACTION angleSnapModeChanged
Notification event when angle mode changes.
 
static TOOL_ACTION moveExact
Activation of the exact move tool.
 
static TOOL_ACTION copyWithReference
copy command with manual reference point selection
 
static TOOL_ACTION genCancelEdit
 
static TOOL_ACTION genUpdateEdit
 
static TOOL_ACTION updateLocalRatsnest
 
static TOOL_ACTION moveIndividually
move items one-by-one
 
static TOOL_ACTION interactiveOffsetTool
 
static TOOL_ACTION positionRelative
 
static TOOL_ACTION move
move or drag an item
 
static TOOL_ACTION mirrorV
 
static TOOL_ACTION flip
Flipping of selected objects.
 
static TOOL_ACTION rotateCw
Rotation of selected objects.
 
static TOOL_ACTION rotateCcw
 
Common, abstract interface for edit frames.
 
PCBNEW_SETTINGS * GetPcbNewSettings() const
 
virtual PCB_LAYER_ID GetActiveLayer() const
 
virtual MAGNETIC_SETTINGS * GetMagneticItemsSettings()
 
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
 
virtual void Update3DView(bool aMarkDirty, bool aRefresh, const wxString *aTitle=nullptr)
Update the 3D view, if the viewer is opened by this frame.
 
std::vector< EDA_ITEM * > EDA_ITEMS
Define list of drawing items for screens.
 
#define IS_MOVING
Item being moved.
 
a few functions useful in geometry calculations.
 
LEADER_MODE
The kind of the leader line.
 
@ DIRECT
Unconstrained point-to-point.
 
PCB_LAYER_ID
A quick note on layer IDs:
 
@ TOP_BOTTOM
Flip top to bottom (around the X axis)
 
Class to handle a set of BOARD_ITEMs.
 
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
 
@ PCB_GENERATOR_T
class PCB_GENERATOR, generator on a layer
 
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
 
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
 
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
 
@ PCB_PAD_T
class PAD, a pad in a footprint
 
@ 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)
 
VECTOR2< int32_t > VECTOR2I
 
VECTOR2< double > VECTOR2D