55#define MULTICHANNEL_EXTRA_DEBUG 
   79                                                  std::set<FOOTPRINT*>& aComponents )
 
   81    if( !aRuleArea || !aRuleArea->
m_zone )
 
   92                aComponents.insert( 
static_cast<FOOTPRINT*
>( item ) );
 
   95        return (
int) aComponents.size();
 
  104            [&]( 
const wxString& aMessage, 
int aOffset )
 
  134    auto ok = compiler.
Compile( ruleText, &ucode, &preflightCtx );
 
  148                        fp->GetSheetname() );
 
  150            aComponents.insert( fp );
 
 
  160    if( !aRuleArea || !aRuleArea->
m_zone )
 
  178                aItems.insert( 
static_cast<BOARD_ITEM*
>( item ) );
 
  181        return (
int) aItems.size();
 
  184    std::vector<BOARD_ITEM*> 
result;
 
  191            [&]( 
const wxString& aMessage, 
int aOffset )
 
  200    bool restoreBlankName = 
false;
 
  204        restoreBlankName = 
true;
 
  208    wxString ruleText = wxString::Format( wxT( 
"A.enclosedByArea('%s')" ), aRuleArea->
m_zone->
GetZoneName() );
 
  210    if( !compiler.
Compile( ruleText, &ucode, &preflightCtx ) )
 
  212        if( restoreBlankName )
 
  222                auto val = ucode.
Run( &ctx );
 
  224                if( val->AsDouble() != 0.0 )
 
  225                    aItems.insert( aItem );
 
  230        if( zone == aRuleArea->
m_zone )
 
  237        testAndAdd( drawing );
 
  242        bool addGroup = 
true;
 
  244        group->RunOnChildren(
 
  247                    if( aItem->
IsType( { PCB_ZONE_T, PCB_SHAPE_T, PCB_BARCODE_T, PCB_DIMENSION_T } ) )
 
  259            aItems.insert( 
group );
 
  262    if( restoreBlankName )
 
 
  271    std::set<FOOTPRINT*> rv;
 
  273    if( aSheetName.EndsWith( wxT( 
"/" ) ) )
 
  274        aSheetName.RemoveLast();
 
  278        auto sn = fp->GetSheetname();
 
  279        if( sn.EndsWith( wxT( 
"/" ) ) )
 
  282        if( sn == aSheetName )
 
 
  293    std::set<FOOTPRINT*> rv;
 
  297        if( fp->GetComponentClass()->ContainsClassName( aComponentClassName ) )
 
 
  307    std::set<FOOTPRINT*> rv;
 
  311        if( 
group->GetName() == aGroupName )
 
  316                    rv.insert( 
static_cast<FOOTPRINT*
>( item ) );
 
 
  328    std::vector<VECTOR2I> bbCorners;
 
  329    bbCorners.reserve( aFootprints.size() * 4 );
 
  333        const BOX2I bb = fp->GetBoundingBox( 
false ).GetInflated( aMargin );
 
  337    std::vector<VECTOR2I> hullVertices;
 
 
  349    using PathAndName = std::pair<wxString, wxString>;
 
  350    std::set<PathAndName> uniqueSheets;
 
  351    std::set<wxString>    uniqueComponentClasses;
 
  352    std::set<wxString>    uniqueGroups;
 
  358        uniqueSheets.insert( PathAndName( fp->GetSheetname(), fp->GetSheetfile() ) );
 
  363            uniqueComponentClasses.insert( singleClass->GetName() );
 
  365        if( fp->GetParentGroup() && !fp->GetParentGroup()->GetName().IsEmpty() )
 
  366            uniqueGroups.insert( fp->GetParentGroup()->GetName() );
 
  369    for( 
const PathAndName& sheet : uniqueSheets )
 
  378        m_areas.m_areas.push_back( ent );
 
  383                    (
int) 
m_areas.m_areas.size() );
 
  386    for( 
const wxString& compClass : uniqueComponentClasses )
 
  394        m_areas.m_areas.push_back( ent );
 
  398                    static_cast<int>( 
m_areas.m_areas.size() ) );
 
  401    for( 
const wxString& groupName : uniqueGroups )
 
  409        m_areas.m_areas.push_back( ent );
 
  413                    static_cast<int>( 
m_areas.m_areas.size() ) );
 
 
  424        if( !zone->GetIsRuleArea() )
 
  427        if( !zone->GetPlacementAreaEnabled() )
 
  435        area.
m_center = zone->Outline()->COutline( 0 ).Centre();
 
  439        m_areas.m_areas.push_back( area );
 
 
  469    std::vector<ZONE*> refRAs;
 
  471    auto isSelectedItemAnRA =
 
  477                ZONE* zone = 
static_cast<ZONE*
>( aItem );
 
  490        if( 
auto zone = isSelectedItemAnRA( item ) )
 
  492            refRAs.push_back(zone);
 
  500                if( 
auto grpZone = isSelectedItemAnRA( grpItem ) )
 
  501                    refRAs.push_back( grpZone );
 
  506    if( refRAs.size() != 1 )
 
  511                                  _( 
"Select a reference Rule Area to copy from..." ),
 
  514                                      return isSelectedItemAnRA( aItem ) != 
nullptr;
 
  528    if( 
m_areas.m_areas.size() <= 1 )
 
  530        frame()->ShowInfoBarError( 
_( 
"No Rule Areas to repeat layout to have been found." ), 
true );
 
 
  550        if( ra.
m_zone == aRefZone )
 
 
  584            auto errMsg = wxString::Format( 
_( 
"Rule Area topologies do not match: %s" ), compat.
m_errorMsg );
 
  585            frame()->ShowInfoBarError( errMsg, 
true );
 
  594        auto errMsg = wxString::Format( 
_( 
"Copy Rule Area contents failed between rule areas '%s' and '%s'." ),
 
  601            frame()->ShowInfoBarError( errMsg, 
true );
 
  615                frame()->ShowInfoBarError( 
_( 
"Target group does not have a group." ), 
true );
 
  628            group->AddItem( item );
 
  632    commit.
Push( 
_( 
"Repeat layout" ) );
 
 
  643    for( 
auto& targetArea : 
m_areas.m_compatMap )
 
  645        if( !targetArea.second.m_doCopy )
 
  648                        targetArea.first->m_ruleName );
 
  652        if( !targetArea.second.m_isOk )
 
  657            auto errMsg = wxString::Format(
 
  658                    _( 
"Copy Rule Area contents failed between rule areas '%s' and '%s'." ),
 
  659                    m_areas.m_refRA->m_zone->GetZoneName(),
 
  660                    targetArea.first->m_zone->GetZoneName() );
 
  665                frame()->ShowInfoBarError( errMsg, 
true );
 
  673    if( 
m_areas.m_options.m_groupItems )
 
  675        for( 
const auto& [targetArea, compatData] : 
m_areas.m_compatMap )
 
  683            for( 
BOARD_ITEM* item : compatData.m_groupableItems )
 
  686                group->AddItem( item );
 
  691    commit.
Push( 
_( 
"Repeat layout" ) );
 
  694        frame()->ShowInfoBarMsg( wxString::Format( 
_( 
"Copied to %d Rule Areas." ), totalCopied ), 
true );
 
 
  714        if( ( c >= 
'a' && c <= 
'z' ) || ( c >= 
'A' && c <= 
'Z' ) || ( c == 
'_' ) )
 
 
  725                                              std::shared_ptr<CONNECTIVITY_DATA> aConnectivity,
 
  728    if( !aRuleArea || !aRuleArea->
m_zone )
 
  749                aOutput.insert( bci );
 
  752        return (
int) aOutput.size();
 
  759    auto reportError = [&]( 
const wxString& aMessage, 
int aOffset )
 
  768    bool restoreBlankName = 
false;
 
  772        restoreBlankName = 
true;
 
  776    wxString ruleText = wxString::Format( wxT( 
"A.enclosedByArea('%s')" ), aRuleArea->
m_zone->
GetZoneName() );
 
  781                if( aOutput.contains( aItem ) )
 
  789                    aOutput.insert( aItem );
 
  794    if( compiler.
Compile( ruleText, &ucode, &preflightCtx ) )
 
  800    if( restoreBlankName )
 
 
  824                targetAnchorFp = targetFP;
 
  834            disp = newpos - oldpos;
 
  847    newTargetOutline.
Move( disp );
 
  856    bool targetZoneOnBoard = 
false;
 
  862            if( z == aTargetArea->
m_zone )
 
  864                targetZoneOnBoard = 
true;
 
  870    if( targetZoneOnBoard )
 
  879        std::set<BOARD_CONNECTED_ITEM*> refRouting;
 
  880        std::set<BOARD_CONNECTED_ITEM*> targetRouting;
 
  890            for( 
PAD* 
pad : refFP->Pads() )
 
  891                refc.insert( 
pad->GetNetCode() );
 
  893            for( 
PAD* 
pad : targetFP->Pads() )
 
  894                targc.insert( 
pad->GetNetCode() );
 
  954        std::set<BOARD_ITEM*> sourceItems;
 
  955        std::set<BOARD_ITEM*> targetItems;
 
  982                ZONE* zone = 
static_cast<ZONE*
>( item );
 
  985                bool layerMismatch = 
false;
 
  991                        layerMismatch = 
true;
 
 1027                ZONE* zone = 
static_cast<ZONE*
>( item );
 
 1030                bool layerMismatch = 
false;
 
 1038                        layerMismatch = 
true;
 
 1045                ZONE* targetZone = 
static_cast<ZONE*
>( item->Duplicate( 
false ) );
 
 1069                            refFP->GetReference() );
 
 1075                            refFP->GetReference() );
 
 1080            if( !refFP->GetEffectiveShape( refFP->GetLayer() )->Collide( &refPoly, 0 ) )
 
 1086            aCommit->
Modify( targetFP );
 
 1088            targetFP->SetLayerAndFlip( refFP->GetLayer() );
 
 1089            targetFP->SetOrientation( refFP->GetOrientation() );
 
 1090            targetFP->SetPosition( refFP->GetPosition() );
 
 1091            targetFP->Rotate( 
VECTOR2( 0, 0 ), rot );
 
 1092            targetFP->Move( disp );
 
 1093            for( 
PCB_FIELD* refField : refFP->GetFields() )
 
 1095                if( !refField->IsVisible() )
 
 1098                PCB_FIELD* targetField = targetFP->GetField( refField->GetName() );
 
 1099                wxCHECK2( targetField, 
continue );
 
 1102                targetField->
SetPosition( refField->GetPosition() );
 
 1104                targetField->
Move( disp );
 
 
 1129    const std::vector<BOARD_CONNECTED_ITEM*> refConnectedPads = connectivity->
GetNetItems( aRef->
GetNetCode(),
 
 1137        const PAD* refPad = 
static_cast<const PAD*
>( refConItem );
 
 1140        if( aComponentMatches.contains( sourceFootprint ) )
 
 1142            const FOOTPRINT*        targetFootprint = aComponentMatches[sourceFootprint];
 
 1143            std::vector<const PAD*> targetFpPads = targetFootprint->
GetPads( refPad->
GetNumber() );
 
 1145            if( !targetFpPads.empty() )
 
 1147                int targetNetCode = targetFpPads[0]->GetNet()->GetNetCode();
 
 
 1175            aMatches.
m_errorMsg = 
_( 
"One or both of the areas has no components assigned." );
 
 1179            aMatches.
m_errorMsg = 
_( 
"Component count mismatch" );
 
 1183            aMatches.
m_errorMsg = 
_( 
"Iteration count exceeded (timeout)" );
 
 
 1198                                             const std::unordered_set<BOARD_ITEM*>& aItemsToRemove )
 
 1204        std::vector<EDA_ITEM*> pruneList;
 
 1210                if( refItem->m_Uuid == testItem->m_Uuid )
 
 1211                    pruneList.push_back( refItem );
 
 1215        if( !pruneList.empty() )
 
 1220                group->RemoveItem( item );
 
 1222            if( 
group->GetItems().empty() )
 
 
 1237        if( 
m_areas.m_areas.size() <= 1 )
 
 1239            frame()->ShowInfoBarError( 
_( 
"Cannot auto-generate any placement areas because the " 
 1240                                          "schematic has only one or no hierarchical sheets, " 
 1241                                          "groups, or component classes." ),
 
 1249        if( ret != wxID_OK )
 
 1255        if( !zone->GetIsRuleArea() )
 
 1258        if( !zone->GetPlacementAreaEnabled() )
 
 1261        std::set<FOOTPRINT*> components;
 
 1264        zoneRA.
m_sourceType = zone->GetPlacementAreaSourceType();
 
 1267        if( components.empty() )
 
 1277                                wxT( 
"Placement rule area for sheet '%s' already exists as '%s'\n" ),
 
 1283                                wxT( 
"Placement rule area for component class '%s' already exists as '%s'\n" ),
 
 1289                                wxT( 
"Placement rule area for group '%s' already exists as '%s'\n" ),
 
 1316        std::unique_ptr<ZONE> newZone( 
new ZONE( 
board() ) );
 
 1319            newZone->SetZoneName( wxString::Format( wxT( 
"auto-placement-area-%s" ), ra.
m_sheetPath ) );
 
 1321            newZone->SetZoneName( wxString::Format( wxT( 
"auto-placement-area-%s" ), ra.
m_componentClass ) );
 
 1323            newZone->SetZoneName( wxString::Format( wxT( 
"auto-placement-area-%s" ), ra.
m_groupName ) );
 
 1326                    newZone->GetZoneName(),
 
 1329        newZone->SetIsRuleArea( 
true );
 
 1331        newZone->SetPlacementAreaEnabled( 
true );
 
 1332        newZone->SetDoNotAllowZoneFills( 
false );
 
 1333        newZone->SetDoNotAllowVias( 
false );
 
 1334        newZone->SetDoNotAllowTracks( 
false );
 
 1335        newZone->SetDoNotAllowPads( 
false );
 
 1336        newZone->SetDoNotAllowFootprints( 
false );
 
 1341            newZone->SetPlacementAreaSource( ra.
m_sheetPath );
 
 1351            newZone->SetPlacementAreaSource( ra.
m_groupName );
 
 1354        newZone->AddPolygon( raOutline );
 
 1362        ra.
m_zone = newZone.release();
 
 1369    if( 
m_areas.m_options.m_groupItems )
 
 1379            std::unordered_set<BOARD_ITEM*> toPrune;
 
 1384                toPrune.insert( ra.
m_zone );
 
 1398                group->AddItem( fp );
 
 1403    commit.
Push( 
_( 
"Auto-generate placement rule areas" ) );
 
 
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 void SetIsKnockout(bool aKnockout)
 
FOOTPRINT * GetParentFootprint() const
 
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
 
Represent a set of changes (additions, deletions or modifications) of a data model (e....
 
COMMIT & Remove(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Remove a new item from the model.
 
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
 
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
 
int GetStatus(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Returns status of an item.
 
A lightweight representation of a component class.
 
const std::vector< COMPONENT_CLASS * > & GetConstituentClasses() const
Fetches a vector of the constituent classes for this (effective) class.
 
const std::vector< BOARD_CONNECTED_ITEM * > GetNetItems(int aNetCode, const std::vector< KICAD_T > &aTypes) const
Function GetNetItems() Returns the list of items that belong to a certain net.
 
A set of EDA_ITEMs (i.e., without duplicates).
 
A base class for most all the KiCad significant classes used in schematics and boards.
 
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.
 
void SetAttributes(const EDA_TEXT &aSrc, bool aSetPosition=true)
Set the text attributes from another instance.
 
bool IsBOARD_ITEM() const
 
wxString AsString() const
 
void SetErrorCallback(std::function< void(const wxString &aMessage, int aOffset)> aCallback)
 
bool Compile(const wxString &aString, UCODE *aCode, CONTEXT *aPreflightContext)
 
void SetErrorCallback(std::function< void(const wxString &aMessage, int aOffset)> aCallback)
 
VALUE * Run(CONTEXT *ctx)
 
virtual double AsDouble() const
 
LSET is a set of PCB_LAYER_IDs.
 
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
 
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
 
const wxString & GetNumber() const
 
void SetItems(BOARD_ITEM *a, BOARD_ITEM *b=nullptr)
 
static TOOL_ACTION repeatLayout
 
static TOOL_ACTION generatePlacementRuleAreas
 
static TOOL_ACTION selectItemInteractively
Selection of reference points/items.
 
A set of BOARD_ITEMs (i.e., without duplicates).
 
virtual void SetPosition(const VECTOR2I &aPos) override
 
void Move(const VECTOR2I &aMoveVector) override
Move this object.
 
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
 
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
 
void Move(const VECTOR2I &aVector) override
 
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
 
Represent a set of closed polygons.
 
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
 
virtual void CacheTriangulation(bool aPartition=true, bool aSimplify=false)
Build a polygon triangulation, needed to draw a polygon on OpenGL and in some other calculations.
 
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
 
@ ST_COMPONENT_COUNT_MISMATCH
 
@ ST_ITERATION_COUNT_EXCEEDED
 
static std::unique_ptr< CONNECTION_GRAPH > BuildFromFootprintSet(const std::set< FOOTPRINT * > &aFps)
 
Define a general 2D-vector/point.
 
Handle a list of polygons defining a copper zone.
 
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
 
void AddPolygon(std::vector< VECTOR2I > &aPolygon)
Add a polygon to the zone outline.
 
wxString GetPlacementAreaSource() const
 
void HatchBorder()
Compute the hatch lines depending on the hatch parameters and stores it in the zone's attribute m_bor...
 
PLACEMENT_SOURCE_T GetPlacementAreaSourceType() const
 
SHAPE_POLY_SET * Outline()
 
const wxString & GetZoneName() const
 
bool GetPlacementAreaEnabled() const
 
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
 
void SetZoneName(const wxString &aName)
 
void UnHatchBorder()
Clear the zone's hatch.
 
void RemoveAllContours(void)
 
void BuildConvexHull(std::vector< VECTOR2I > &aResult, const std::vector< VECTOR2I > &aPoly)
Calculate the convex hull of a list of points in counter-clockwise order.
 
PCB_LAYER_ID
A quick note on layer IDs:
 
SHAPE_LINE_CHAIN RectifyPolygon(const SHAPE_LINE_CHAIN &aPoly)
 
void CollectBoxCorners(const BOX2I &aBox, std::vector< VECTOR2I > &aCorners)
Add the 4 corners of a BOX2I to a vector.
 
std::map< FOOTPRINT *, FOOTPRINT * > COMPONENT_MATCHES
 
Class to handle a set of BOARD_ITEMs.
 
PGM_BASE & Pgm()
The global program "get" accessor.
 
Utility functions for working with shapes.
 
bool m_connectedRoutingOnly
 
bool m_includeLockedItems
 
std::unordered_set< BOARD_ITEM * > m_affectedItems
Filled in by copyRuleAreaContents with items that were affected by the copy operation.
 
TMATCH::COMPONENT_MATCHES m_matchingComponents
 
std::unordered_set< BOARD_ITEM * > m_groupableItems
Filled in by copyRuleAreaContents with affected items that can be grouped together.
 
std::unordered_set< EDA_ITEM * > m_designBlockItems
 
PLACEMENT_SOURCE_T m_sourceType
 
wxString m_componentClass
 
std::set< FOOTPRINT * > m_components
 
wxString result
Test unit parsing edge cases and error handling.
 
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
 
@ PCB_ZONE_T
class ZONE, a copper pour area
 
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
 
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
 
@ PCB_PAD_T
class PAD, a pad in a footprint
 
VECTOR2< int32_t > VECTOR2I