KiCad PCB EDA Suite
edit_zone_helpers.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2012 Jean-Pierre Charras, [email protected]
5  * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * Some code comes from FreePCB.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, you may find one here:
21  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22  * or you may search the http://www.gnu.org website for the version 2 license,
23  * or you may write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26 
27 #include <kiface_base.h>
28 #include <confirm.h>
29 #include <pcb_edit_frame.h>
30 #include <pcbnew_settings.h>
31 #include <board_commit.h>
32 #include <zone.h>
33 #include <zones.h>
37 #include <zone_filler.h>
38 
39 
41 {
42  int dialogResult;
43  ZONE_SETTINGS zoneInfo = GetZoneSettings();
44  PICKED_ITEMS_LIST pickedList; // zones for undo/redo command
45  PICKED_ITEMS_LIST deletedList; // zones that have been deleted when combined
46  BOARD_COMMIT commit( this );
47 
48  // Save initial zones configuration, for undo/redo, before adding new zone
49  // note the net name and the layer can be changed, so we must save all zones
50  deletedList.ClearListAndDeleteItems();
51  pickedList.ClearListAndDeleteItems();
52  SaveCopyOfZones( pickedList, GetBoard(), -1, UNDEFINED_LAYER );
53 
54  if( aZone->GetIsRuleArea() )
55  {
56  // edit a rule area on a copper layer
57  zoneInfo << *aZone;
58  dialogResult = InvokeRuleAreaEditor( this, &zoneInfo );
59  }
60  else if( IsCopperLayer( aZone->GetLayer() ) )
61  {
62  // edit a zone on a copper layer
63  zoneInfo << *aZone;
64  dialogResult = InvokeCopperZonesEditor( this, &zoneInfo );
65  }
66  else
67  {
68  zoneInfo << *aZone;
69  dialogResult = InvokeNonCopperZonesEditor( this, &zoneInfo );
70  }
71 
72  if( dialogResult == wxID_CANCEL )
73  {
74  deletedList.ClearListAndDeleteItems();
75  pickedList.ClearListAndDeleteItems();
76  return;
77  }
78 
79  SetZoneSettings( zoneInfo );
80  OnModify();
81 
82  if( dialogResult == ZONE_EXPORT_VALUES )
83  {
84  UpdateCopyOfZonesList( pickedList, deletedList, GetBoard() );
85  commit.Stage( pickedList );
86  commit.Push( _( "Modify zone properties" ) );
87  pickedList.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items
88  return;
89  }
90 
91  wxBusyCursor dummy;
92 
93  // Undraw old zone outlines
94  for( ZONE* zone : GetBoard()->Zones() )
95  GetCanvas()->GetView()->Update( zone );
96 
97  zoneInfo.ExportSetting( *aZone );
98 
99  NETINFO_ITEM* net = GetBoard()->FindNet( zoneInfo.m_NetcodeSelection );
100 
101  if( net ) // net == NULL should not occur
102  aZone->SetNetCode( net->GetNetCode() );
103 
104  UpdateCopyOfZonesList( pickedList, deletedList, GetBoard() );
105 
106  // refill zones with the new properties applied
107  std::vector<ZONE*> zones_to_refill;
108 
109  for( unsigned i = 0; i < pickedList.GetCount(); ++i )
110  {
111  ZONE* zone = dyn_cast<ZONE*>( pickedList.GetPickedItem( i ) );
112 
113  if( zone == nullptr )
114  {
115  wxASSERT_MSG( false, wxT( "Expected a zone after zone properties edit" ) );
116  continue;
117  }
118 
119  // aZone won't be filled if the layer set was modified, but it needs to be updated
120  if( zone->IsFilled() || zone == aZone )
121  zones_to_refill.push_back( zone );
122  }
123 
124  commit.Stage( pickedList );
125 
126  // Only auto-refill zones here if in user preferences
127  if( Settings().m_AutoRefillZones && zones_to_refill.size() )
128  {
129  ZONE_FILLER filler( GetBoard(), &commit );
130  wxString title = wxString::Format( _( "Refill %d Zones" ), (int) zones_to_refill.size() );
131 
132  std::unique_ptr<WX_PROGRESS_REPORTER> reporter;
133  reporter = std::make_unique<WX_PROGRESS_REPORTER>( this, title, 4 );
134  filler.SetProgressReporter( reporter.get() );
135 
136  filler.Fill( zones_to_refill );
137  }
138 
139  commit.Push( _( "Modify zone properties" ) );
140 
141  if( Settings().m_AutoRefillZones && zones_to_refill.size() )
142  GetBoard()->GetConnectivity()->Build( GetBoard() );
143 
144  GetBoard()->GetConnectivity()->RecalculateRatsnest();
145 
146  pickedList.ClearItemsList(); // s_ItemsListPicker is no longer owner of picked items
147 }
148 
149 
150 bool BOARD::TestZoneIntersection( ZONE* aZone1, ZONE* aZone2 )
151 {
152  // see if areas are on same layer
153  if( aZone1->GetLayer() != aZone2->GetLayer() )
154  return false;
155 
156  SHAPE_POLY_SET* poly1 = aZone1->Outline();
157  SHAPE_POLY_SET* poly2 = aZone2->Outline();
158 
159  // test bounding rects
160  BOX2I b1 = poly1->BBox();
161  BOX2I b2 = poly2->BBox();
162 
163  if( ! b1.Intersects( b2 ) )
164  return false;
165 
166  // Now test for intersecting segments
167  for( auto segIterator1 = poly1->IterateSegmentsWithHoles(); segIterator1; segIterator1++ )
168  {
169  // Build segment
170  SEG firstSegment = *segIterator1;
171 
172  for( auto segIterator2 = poly2->IterateSegmentsWithHoles(); segIterator2; segIterator2++ )
173  {
174  // Build second segment
175  SEG secondSegment = *segIterator2;
176 
177  // Check whether the two segments built collide
178  if( firstSegment.Collide( secondSegment, 0 ) )
179  return true;
180  }
181  }
182 
183  // If a contour is inside another contour, no segments intersects, but the zones
184  // can be combined if a corner is inside an outline (only one corner is enough)
185  for( auto iter = poly2->IterateWithHoles(); iter; iter++ )
186  {
187  if( poly1->Contains( *iter ) )
188  return true;
189  }
190 
191  for( auto iter = poly1->IterateWithHoles(); iter; iter++ )
192  {
193  if( poly2->Contains( *iter ) )
194  return true;
195  }
196 
197  return false;
198 }
199 
200 
201 
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1328
void OnModify() override
Must be called after a board change to set the modified flag.
SEGMENT_ITERATOR IterateSegmentsWithHoles()
Return an iterator object, for the aOutline-th outline in the set (with holes).
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition: zone.h:735
This file is part of the common library.
void UpdateCopyOfZonesList(PICKED_ITEMS_LIST &aPickList, PICKED_ITEMS_LIST &aAuxiliaryList, BOARD *aPcb)
Function UpdateCopyOfZonesList Check a pick list to remove zones identical to their copies and set th...
int InvokeNonCopperZonesEditor(PCB_BASE_FRAME *aParent, ZONE_SETTINGS *aSettings)
Function InvokeNonCopperZonesEditor invokes up a modal dialog window for non-copper zone editing.
SHAPE_POLY_SET * Outline()
Definition: zone.h:320
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
bool Collide(const SEG &aSeg, int aClearance, int *aActual=nullptr) const
Definition: seg.cpp:189
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
bool IsFilled() const
Definition: zone.h:234
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, int aAccuracy=0, bool aUseBBoxCaches=false) const
Return true if a given subpolygon contains the point aP.
#define ZONE_EXPORT_VALUES
Definition: zones.h:37
bool TestZoneIntersection(ZONE *aZone1, ZONE *aZone2)
Test for intersection of 2 copper areas.
unsigned GetCount() const
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:72
int SaveCopyOfZones(PICKED_ITEMS_LIST &aPickList, BOARD *aPcb, int aNetCode, LAYER_NUM aLayer)
Function SaveCopyOfZones creates a copy of zones having a given netcode on a given layer,...
int m_NetcodeSelection
Definition: zone_settings.h:93
bool Intersects(const BOX2< Vec > &aRect) const
Definition: box2.h:217
bool Fill(std::vector< ZONE * > &aZones, bool aCheck=false, wxWindow *aParent=nullptr)
Fills the given list of zones.
Definition: zone_filler.cpp:79
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const override
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: pcb_view.cpp:92
void SetProgressReporter(PROGRESS_REPORTER *aReporter)
Definition: zone_filler.cpp:71
void ExportSetting(ZONE &aTarget, bool aFullExport=true) const
Function ExportSetting copy settings to a given zone.
ITERATOR IterateWithHoles(int aOutline)
Represent a set of closed polygons.
virtual PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: zone.cpp:222
const ZONE_SETTINGS & GetZoneSettings() const
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:345
EDA_ITEM * GetPickedItem(unsigned int aIdx) const
#define _(s)
Handle a list of polygons defining a copper zone.
Definition: zone.h:56
A holder to handle information on schematic or board items.
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
int InvokeRuleAreaEditor(PCB_BASE_FRAME *aCaller, ZONE_SETTINGS *aSettings)
Function InvokeRuleAreaEditor invokes up a modal dialog window for copper zone editing.
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:808
ZONE_SETTINGS handles zones parameters.
Definition: zone_settings.h:67
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
Definition: seg.h:40
void Edit_Zone_Params(ZONE *zone_container)
Edit params (layer, clearance, ...) for a zone outline.
Handle the data for a net.
Definition: netinfo.h:66
PCBNEW_SETTINGS & Settings()
void ClearItemsList()
Delete only the list of pickers NOT the picked data itself.
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true) override
Revert the commit by restoring the modified items state.
int InvokeCopperZonesEditor(PCB_BASE_FRAME *aCaller, ZONE_SETTINGS *aSettings)
Function InvokeCopperZonesEditor invokes up a modal dialog window for copper zone editing.
void SetZoneSettings(const ZONE_SETTINGS &aSettings)
BOARD * GetBoard() const
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
void ClearListAndDeleteItems()
Delete the list of pickers AND the data pointed by #m_PickedItem or #m_PickedItemLink according to th...
COMMIT & Stage(EDA_ITEM *aItem, CHANGE_TYPE aChangeType) override
int GetNetCode() const
Definition: netinfo.h:120