48#define MULTICHANNEL_EXTRA_DEBUG
72 std::set<FOOTPRINT*>& aComponents )
78 auto reportError = [&](
const wxString& aMessage,
int aOffset )
94 case RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME:
100 case RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS:
106 auto ok = compiler.
Compile( ruleText, &ucode, &preflightCtx );
116 auto val = ucode.
Run( &ctx );
117 if( val->AsDouble() != 0.0 )
120 fp->GetSheetname() );
122 aComponents.insert( fp );
132 std::set<FOOTPRINT*> rv;
133 if( aSheetName.EndsWith( wxT(
"/" ) ) )
134 aSheetName.RemoveLast();
136 for(
auto& fp :
board()->Footprints() )
138 auto sn = fp->GetSheetname();
139 if( sn.EndsWith( wxT(
"/" ) ) )
142 if( sn == aSheetName )
155 std::vector<VECTOR2I> bbCorners, hullVertices;
157 for(
auto fp : aFootprints )
159 auto bb = fp->GetBoundingBox(
false );
160 bb.Inflate( aMargin );
162 bbCorners.push_back(
VECTOR2I( bb.GetX(), bb.GetY() ) );
163 bbCorners.push_back(
VECTOR2I( bb.GetX() + bb.GetWidth(), bb.GetY() ) );
164 bbCorners.push_back(
VECTOR2I( bb.GetX() + bb.GetWidth(), bb.GetY() + bb.GetHeight() ) );
165 bbCorners.push_back(
VECTOR2I( bb.GetX(), bb.GetY() + bb.GetHeight() ) );
177 const auto& seg = hull.
CSegment( i );
178 const VECTOR2I p0( seg.A.x, seg.B.y );
179 const VECTOR2I p1( seg.B.x, seg.A.y );
181 raOutline.
Append( seg.A );
197 using PathAndName = std::pair<wxString, wxString>;
198 std::set<PathAndName> uniqueSheets;
204 uniqueSheets.insert( PathAndName( fp->GetSheetname(), fp->GetSheetfile() ) );
207 for(
const PathAndName& sheet : uniqueSheets )
229 if( !zone->GetIsRuleArea() )
231 if( !zone->GetRuleAreaPlacementEnabled() )
242 area.
m_center = zone->Outline()->COutline( 0 ).Centre();
266 std::vector<ZONE*> refRAs;
268 auto isSelectedItemAnRA = [] (
EDA_ITEM* aItem ) ->
ZONE*
272 ZONE* zone =
static_cast<ZONE*
>( aItem );
282 if(
auto zone = isSelectedItemAnRA( item ) )
284 refRAs.push_back(zone);
291 if(
auto grpZone = isSelectedItemAnRA( grpItem ) )
293 refRAs.push_back( grpZone );
299 if( refRAs.size() != 1 )
301 frame()->ShowInfoBarError(
_(
"Please select a single reference Rule Area to copy from." ),
315 frame()->ShowInfoBarError(
_(
"No Rule Areas to repeat layout to have been found." ),
322 int ret = dialog.ShowModal();
337 if( ra.
m_area == aRefZone )
368 if( !targetArea.second.m_doCopy )
371 targetArea.first->m_ruleName );
375 if( !targetArea.second.m_isOk )
380 std::unordered_set<BOARD_ITEM*> affectedItems;
381 std::unordered_set<BOARD_ITEM*> groupableItems;
386 auto errMsg = wxString::Format(
387 _(
"Copy Rule Area contents failed between rule areas '%s' and '%s'." ),
389 targetArea.first->m_area->GetZoneName() );
394 frame()->ShowInfoBarError( errMsg,
true );
400 commit.
Push(
_(
"Repeat layout" ) );
411 grpCommit.
Add( grp );
413 for(
auto item : groupableItems )
418 grpCommit.
Push(
_(
"Group components with their placement rule areas" ) );
426 frame()->ShowInfoBarMsg( wxString::Format(
_(
"Copied to %d Rule Areas." ), totalCopied ),
446 if( ( c >=
'a' && c <=
'z' ) || ( c >=
'A' && c <=
'Z' ) || ( c ==
'_' ) )
457 std::shared_ptr<CONNECTIVITY_DATA> aConnectivity,
462 std::set<BOARD_ITEM*> conns;
466 const std::vector<BOARD_CONNECTED_ITEM*> connItems = aConnectivity->GetConnectedItems(
470 conns.insert( item );
482 std::shared_ptr<SHAPE> effShape = item->GetEffectiveShape( item->GetLayer() );
484 if( effShape->Collide( &aRAPoly, 0 ) )
486 aOutput.insert( item );
498 std::unordered_set<BOARD_ITEM*>& aAffectedItems,
499 std::unordered_set<BOARD_ITEM*>& aGroupableItems )
514 newTargetOutline.
Move( disp );
522 aAffectedItems.insert( aTargetArea->
m_area );
523 aGroupableItems.insert( aTargetArea->
m_area );
527 std::set<BOARD_ITEM*> refRouting;
528 std::set<BOARD_ITEM*> targetRouting;
532 for(
auto& fpPair : aMatches )
535 fpPair.second, aOpts );
553 aAffectedItems.insert( item );
567 copied->
Move( disp );
568 aGroupableItems.insert( copied );
569 aCommit->
Add( copied );
581 for(
auto& fpPair : aMatches )
602 aCommit->
Modify( targetFP );
613 aAffectedItems.insert( targetFP );
614 aGroupableItems.insert( targetFP );
626 std::unique_ptr<CONNECTION_GRAPH> cgRef ( CONNECTION_GRAPH::BuildFromFootprintSet( aRefArea->
m_raFootprints ) );
627 std::unique_ptr<CONNECTION_GRAPH> cgTarget ( CONNECTION_GRAPH::BuildFromFootprintSet( aTargetArea->
m_raFootprints ) );
633 case CONNECTION_GRAPH::ST_OK:
637 case CONNECTION_GRAPH::ST_EMPTY:
639 aMatches.
m_errorMsg =
_(
"One or both of the areas has no components assigned.");
641 case CONNECTION_GRAPH::ST_COMPONENT_COUNT_MISMATCH:
643 aMatches.
m_errorMsg =
_(
"Component count mismatch");
645 case CONNECTION_GRAPH::ST_ITERATION_COUNT_EXCEEDED:
647 aMatches.
m_errorMsg =
_(
"Iteration count exceeded (timeout)");
649 case CONNECTION_GRAPH::ST_TOPOLOGY_MISMATCH:
665 std::unordered_set<BOARD_ITEM*>& grpItems = grp->GetItems();
668 for(
auto refItem : grpItems )
671 for (
auto& testItem : aItemsToRemove )
674 if( refItem->m_Uuid == testItem->m_Uuid )
682 if( n_erased == grpItems.size() )
701 frame()->ShowInfoBarError(
_(
"Cannot auto-generate any placement areas because the "
702 "schematic has only one or no hierarchical sheet(s)." ),
709 int ret = dialog.ShowModal();
717 if( !zone->GetIsRuleArea() )
719 if( !zone->GetRuleAreaPlacementEnabled() )
722 std::set<FOOTPRINT*> components;
725 if( components.empty() )
730 if( components == ra.m_sheetComponents )
733 wxT(
"Placement rule area for sheet '%s' already exists as '%s'\n" ),
734 ra.m_sheetPath, zone->GetZoneName() );
737 ra.m_existsAlready =
true;
743 wxT(
"%d placement areas found\n" ), (
int)
m_areas.
m_areas.size() );
756 std::unique_ptr<ZONE> newZone(
new ZONE(
board() ) );
758 newZone->SetZoneName( wxString::Format( wxT(
"auto-placement-area-%s" ), ra.
m_sheetPath ) );
761 wxT(
"Generated rule area '%s' (%d components)\n" ),
762 newZone->GetZoneName(),
765 newZone->SetIsRuleArea(
true );
767 newZone->SetRuleAreaPlacementEnabled(
true );
768 newZone->SetDoNotAllowCopperPour(
false );
769 newZone->SetDoNotAllowVias(
false );
770 newZone->SetDoNotAllowTracks(
false );
771 newZone->SetDoNotAllowPads(
false );
772 newZone->SetDoNotAllowFootprints(
false );
773 newZone->SetRuleAreaPlacementSourceType( RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME );
774 newZone->SetRuleAreaPlacementSource( ra.
m_sheetPath );
775 newZone->AddPolygon( raOutline );
776 newZone->SetHatchStyle( ZONE_BORDER_DISPLAY_STYLE::NO_HATCH );
783 ra.
m_area = newZone.get();
784 commit.
Add( newZone.release() );
788 commit.
Push(
_(
"Auto-generate placement rule areas" ) );
805 std::unordered_set<BOARD_ITEM*> toPrune;
808 std::inserter( toPrune, toPrune.begin() ) );
811 toPrune.insert( ra.
m_area );
817 grpCommit.
Add( grp );
825 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...
virtual void Move(const VECTOR2I &aMoveVector)
Move this object.
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)
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)
A base class for most all the KiCad significant classes used in schematics and boards.
const EDA_ANGLE & GetTextAngle() const
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
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
A set of BOARD_ITEMs (i.e., without duplicates).
virtual VECTOR2I GetPosition() const override
virtual void SetPosition(const VECTOR2I &aPos) override
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const override
Check if point aP lies inside a closed shape.
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 SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
void Simplify(int aMaxError=0)
Simplify the line chain by removing colinear adjacent segments and duplicate vertices.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
int SegmentCount() const
Return the number of segments in this line chain.
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
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 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.
std::map< FOOTPRINT *, FOOTPRINT * > COMPONENT_MATCHES
Class to handle a set of BOARD_ITEMs.
PGM_BASE & Pgm()
The global Program "get" accessor.
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
std::set< FOOTPRINT * > m_sheetComponents
std::set< FOOTPRINT * > m_raFootprints
@ 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)
VECTOR2< int32_t > VECTOR2I