53#define MULTICHANNEL_EXTRA_DEBUG
77 std::set<FOOTPRINT*>& aComponents )
83 auto reportError = [&](
const wxString& aMessage,
int aOffset )
99 case RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME:
105 case RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS:
111 auto ok = compiler.
Compile( ruleText, &ucode, &preflightCtx );
121 auto val = ucode.
Run( &ctx );
122 if( val->AsDouble() != 0.0 )
125 fp->GetSheetname() );
127 aComponents.insert( fp );
137 std::vector<BOARD_ITEM*> result;
143 auto reportError = [&](
const wxString& aMessage,
int aOffset )
152 bool restoreBlankName =
false;
156 restoreBlankName =
true;
160 wxString ruleText = wxString::Format( wxT(
"A.enclosedByArea('%s')" ), aRuleArea->
GetZoneName() );
162 if( !compiler.
Compile( ruleText, &ucode, &preflightCtx ) )
164 if( restoreBlankName )
174 auto val = ucode.
Run( &ctx );
176 if( val->AsDouble() != 0.0 )
177 aItems.insert( aItem );
182 if( zone == aRuleArea )
189 testAndAdd( drawing );
194 bool addGroup =
true;
196 group->RunOnDescendants(
199 if( aItem->
IsType( { PCB_ZONE_T, PCB_SHAPE_T, PCB_DIMENSION_T } ) )
201 ctx.SetItems( aItem, aItem );
202 auto val = ucode.Run( &ctx );
204 if( val->AsDouble() == 0.0 )
210 aItems.insert(
group );
213 if( restoreBlankName )
222 std::set<FOOTPRINT*> rv;
223 if( aSheetName.EndsWith( wxT(
"/" ) ) )
224 aSheetName.RemoveLast();
226 for(
auto& fp :
board()->Footprints() )
228 auto sn = fp->GetSheetname();
229 if( sn.EndsWith( wxT(
"/" ) ) )
232 if( sn == aSheetName )
245 std::set<FOOTPRINT*> rv;
247 for(
auto& fp :
board()->Footprints() )
249 if( fp->GetComponentClass()->ContainsClassName( aComponentClassName ) )
260 std::vector<VECTOR2I> bbCorners;
261 bbCorners.reserve( aFootprints.size() * 4 );
263 for(
auto fp : aFootprints )
269 std::vector<VECTOR2I> hullVertices;
281 using PathAndName = std::pair<wxString, wxString>;
282 std::set<PathAndName> uniqueSheets;
283 std::set<wxString> uniqueComponentClasses;
289 uniqueSheets.insert( PathAndName( fp->GetSheetname(), fp->GetSheetfile() ) );
294 uniqueComponentClasses.insert( singleClass->GetName() );
297 for(
const PathAndName& sheet : uniqueSheets )
301 ent.
m_sourceType = RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME;
312 for(
const wxString& compClass : uniqueComponentClasses )
316 ent.
m_sourceType = RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS;
334 if( !zone->GetIsRuleArea() )
336 if( !zone->GetRuleAreaPlacementEnabled() )
347 area.
m_center = zone->Outline()->COutline( 0 ).Centre();
377 std::vector<ZONE*> refRAs;
379 auto isSelectedItemAnRA = [](
EDA_ITEM* aItem ) ->
ZONE*
384 ZONE* zone =
static_cast<ZONE*
>( aItem );
397 if(
auto zone = isSelectedItemAnRA( item ) )
399 refRAs.push_back(zone);
407 if(
auto grpZone = isSelectedItemAnRA( grpItem ) )
409 refRAs.push_back( grpZone );
415 if( refRAs.size() != 1 )
420 _(
"Select a reference Rule Area to copy from..." ),
423 return isSelectedItemAnRA( aItem ) !=
nullptr;
439 frame()->ShowInfoBarError(
_(
"No Rule Areas to repeat layout to have been found." ),
460 if( ra.
m_area == aRefZone )
494 if( !targetArea.second.m_doCopy )
497 targetArea.first->m_ruleName );
501 if( !targetArea.second.m_isOk )
504 std::unordered_set<BOARD_ITEM*> affectedItems;
505 std::unordered_set<BOARD_ITEM*> groupableItems;
511 auto errMsg = wxString::Format(
512 _(
"Copy Rule Area contents failed between rule areas '%s' and '%s'." ),
514 targetArea.first->m_area->GetZoneName() );
520 frame()->ShowInfoBarError( errMsg,
true );
543 commit.
Push(
_(
"Repeat layout" ) );
547 frame()->ShowInfoBarMsg( wxString::Format(
_(
"Copied to %d Rule Areas." ), totalCopied ),
567 if( ( c >=
'a' && c <=
'z' ) || ( c >=
'A' && c <=
'Z' ) || ( c ==
'_' ) )
578 std::shared_ptr<CONNECTIVITY_DATA> aConnectivity,
583 std::set<BOARD_ITEM*> conns;
587 const std::vector<BOARD_CONNECTED_ITEM*> connItems = aConnectivity->GetConnectedItems(
591 conns.insert( item );
603 std::shared_ptr<SHAPE> effShape = item->GetEffectiveShape( item->GetLayer() );
605 if( effShape->Collide( &aRAPoly, 0 ) )
607 aOutput.insert( item );
619 auto reportError = [&](
const wxString& aMessage,
int aOffset )
628 bool restoreBlankName =
false;
632 restoreBlankName =
true;
636 wxString ruleText = wxString::Format( wxT(
"A.enclosedByArea('%s')" ),
642 if( aOutput.contains( aItem ) )
646 auto val = ucode.
Run( &ctx );
648 if( val->AsDouble() != 0.0 )
650 aOutput.insert( aItem );
655 if( compiler.
Compile( ruleText, &ucode, &preflightCtx ) )
661 if( restoreBlankName )
672 std::unordered_set<BOARD_ITEM*>& aAffectedItems,
673 std::unordered_set<BOARD_ITEM*>& aGroupableItems )
688 newTargetOutline.
Move( disp );
696 aAffectedItems.insert( aTargetArea->
m_area );
697 aGroupableItems.insert( aTargetArea->
m_area );
701 std::set<BOARD_ITEM*> refRouting;
702 std::set<BOARD_ITEM*> targetRouting;
706 for(
auto& fpPair : aMatches )
709 fpPair.second, aOpts );
727 aAffectedItems.insert( item );
742 copied->
Move( disp );
744 aGroupableItems.insert( copied );
745 aCommit->
Add( copied );
751 std::set<BOARD_ITEM*> sourceItems;
765 if( item->GetParentGroup() && sourceItems.contains( item->GetParentGroup() ) )
772 copied =
static_cast<PCB_GROUP*
>( item )->DeepClone();
776 copied =
static_cast<BOARD_ITEM*
>( item->Clone() );
781 copied->
Move( disp );
782 aGroupableItems.insert( copied );
783 aCommit->
Add( copied );
788 BOARD_ITEM* existingItem = static_cast<BOARD_ITEM*>( viewItem );
790 if( existingItem && existingItem->Similarity( *copied ) == 1.0 )
791 aCommit->Remove( existingItem );
805 for(
auto& fpPair : aMatches )
826 aCommit->
Modify( targetFP );
835 if( !refField->IsVisible() )
839 wxCHECK2( targetField,
continue );
842 targetField->
SetPosition( refField->GetPosition() + disp );
846 aAffectedItems.insert( targetFP );
847 aGroupableItems.insert( targetFP );
860 std::unique_ptr<CONNECTION_GRAPH> cgRef ( CONNECTION_GRAPH::BuildFromFootprintSet( aRefArea->
m_raFootprints ) );
861 std::unique_ptr<CONNECTION_GRAPH> cgTarget ( CONNECTION_GRAPH::BuildFromFootprintSet( aTargetArea->
m_raFootprints ) );
867 case CONNECTION_GRAPH::ST_OK:
871 case CONNECTION_GRAPH::ST_EMPTY:
873 aMatches.
m_errorMsg =
_(
"One or both of the areas has no components assigned.");
875 case CONNECTION_GRAPH::ST_COMPONENT_COUNT_MISMATCH:
877 aMatches.
m_errorMsg =
_(
"Component count mismatch");
879 case CONNECTION_GRAPH::ST_ITERATION_COUNT_EXCEEDED:
881 aMatches.
m_errorMsg =
_(
"Iteration count exceeded (timeout)");
883 case CONNECTION_GRAPH::ST_TOPOLOGY_MISMATCH:
896 const std::unordered_set<BOARD_ITEM*>& aItemsToRemove )
900 std::unordered_set<BOARD_ITEM*>& grpItems = grp->GetItems();
908 if( refItem->m_Uuid == testItem->m_Uuid )
916 if( n_erased == grpItems.size() )
936 frame()->ShowInfoBarError(
_(
"Cannot auto-generate any placement areas because the "
937 "schematic has only one or no hierarchical sheet(s) or "
938 "component classes." ),
952 if( !zone->GetIsRuleArea() )
954 if( !zone->GetRuleAreaPlacementEnabled() )
957 std::set<FOOTPRINT*> components;
960 if( components.empty() )
967 if( zone->GetRuleAreaPlacementSourceType()
968 == RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME )
972 wxT(
"Placement rule area for sheet '%s' already exists as '%s'\n" ),
978 wxT(
"Placement rule area for component class '%s' already exists "
990 wxT(
"%d placement areas found\n" ), (
int)
m_areas.
m_areas.size() );
1004 std::unique_ptr<ZONE> newZone(
new ZONE(
board() ) );
1006 if( ra.
m_sourceType == RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME )
1008 newZone->SetZoneName(
1009 wxString::Format( wxT(
"auto-placement-area-%s" ), ra.
m_sheetPath ) );
1013 newZone->SetZoneName(
1014 wxString::Format( wxT(
"auto-placement-area-%s" ), ra.
m_componentClass ) );
1018 newZone->GetZoneName(), (
int) ra.
m_components.size() );
1020 newZone->SetIsRuleArea(
true );
1022 newZone->SetRuleAreaPlacementEnabled(
true );
1023 newZone->SetDoNotAllowCopperPour(
false );
1024 newZone->SetDoNotAllowVias(
false );
1025 newZone->SetDoNotAllowTracks(
false );
1026 newZone->SetDoNotAllowPads(
false );
1027 newZone->SetDoNotAllowFootprints(
false );
1029 if( ra.
m_sourceType == RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME )
1031 newZone->SetRuleAreaPlacementSourceType( RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME );
1032 newZone->SetRuleAreaPlacementSource( ra.
m_sheetPath );
1036 newZone->SetRuleAreaPlacementSourceType(
1037 RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS );
1041 newZone->AddPolygon( raOutline );
1042 newZone->SetHatchStyle( ZONE_BORDER_DISPLAY_STYLE::NO_HATCH );
1049 ra.
m_area = newZone.get();
1050 commit.
Add( newZone.release() );
1054 commit.
Push(
_(
"Auto-generate placement rule areas" ) );
1072 std::unordered_set<BOARD_ITEM*> toPrune;
1075 std::inserter( toPrune, toPrune.begin() ) );
1078 toPrune.insert( ra.
m_area );
1084 grpCommit.
Add( grp );
1092 grpCommit.
Push(
_(
"Group components with their placement rule areas" ) );
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
COMMIT & Stage(EDA_ITEM *aItem, CHANGE_TYPE aChangeType, BASE_SCREEN *aScreen=nullptr) override
virtual void Revert() override
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
void SetParentGroup(PCB_GROUP *aGroup)
virtual void Move(const VECTOR2I &aMoveVector)
Move this object.
virtual void SetIsKnockout(bool aKnockout)
const ZONES & Zones() const
const TRACKS & Tracks() const
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
constexpr BOX2< Vec > GetInflated(coord_type aDx, coord_type aDy) const
Get a new rectangle that is this one, inflated by aDx and aDy.
Represent a set of changes (additions, deletions or modifications) of a data model (e....
COMMIT & Remove(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been removed.
virtual COMMIT & Stage(EDA_ITEM *aItem, CHANGE_TYPE aChangeType, BASE_SCREEN *aScreen=nullptr)
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Create an undo entry for an item that has been already modified.
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been added.
int GetStatus(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
const std::vector< COMPONENT_CLASS * > & GetConstituentClasses() const
Fetches a vector of the constituent classes for this (effective) class.
A base class for most all the KiCad significant classes used in schematics and boards.
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
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.
An abstract base class for deriving all objects that can be added to a VIEW.
int Query(const BOX2I &aRect, std::vector< LAYER_ITEM_PAIR > &aResult) const
Find all visible items that touch or are within the rectangle aRect.
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)
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
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.
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
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
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
Handle a list of polygons defining a copper zone.
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
wxString GetRuleAreaPlacementSource() const
void AddPolygon(std::vector< VECTOR2I > &aPolygon)
Add a polygon to the zone outline.
void HatchBorder()
Compute the hatch lines depending on the hatch parameters and stores it in the zone's attribute m_bor...
bool GetRuleAreaPlacementEnabled() const
SHAPE_POLY_SET * Outline()
const wxString & GetZoneName() const
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
RULE_AREA_PLACEMENT_SOURCE_TYPE GetRuleAreaPlacementSourceType() const
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.
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_includeLockedItems
std::unordered_map< RULE_AREA *, RULE_AREA_COMPAT_DATA > m_compatMap
REPEAT_LAYOUT_OPTIONS m_options
std::vector< RULE_AREA > m_areas
TMATCH::COMPONENT_MATCHES m_matchingComponents
RULE_AREA_PLACEMENT_SOURCE_TYPE m_sourceType
wxString m_componentClass
std::set< FOOTPRINT * > m_raFootprints
std::set< FOOTPRINT * > m_components
@ 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_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
@ PCB_ZONE_T
class ZONE, a copper pour area
@ 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)