KiCad PCB EDA Suite
zones_functions_for_undo_redo.cpp
Go to the documentation of this file.
1 
5 /*
6  * This program source code file is part of KiCad, a free EDA CAD application.
7  *
8  * Copyright (C) 2009 Jean-Pierre Charras <jp.charras@wanadoo.fr>
9  * Copyright (C) 2007-2015 KiCad Developers, see change_log.txt for contributors.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, you may find one here:
23  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
24  * or you may search the http://www.gnu.org website for the version 2 license,
25  * or you may write to the Free Software Foundation, Inc.,
26  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
27  */
28 
29 
30 /* These functions are relative to undo redo function, when zones are involved.
31  *
32  * When a zone outline is modified (or created) this zone, or others zones on the same layer
33  * and with the same netcode can change or can be deleted due to the fact overlapping zones are
34  * merged. Also, when a zone outline is modified by adding a cutout area, this zone can be
35  * converted to more than one area, if the outline is break to 2 or more outlines and therefore
36  * new zones are created
37  *
38  * Due to the complexity of potential changes, and the fact there are only few zones in a board,
39  * and a zone has only few segments outlines, the more easy way to undo redo changes is to make
40  * a copy of all zones that can be changed and see after zone editing or creation what zones that
41  * are really modified, and ones they are modified (changes, deletion or addition)
42  */
43 
44 #include <pcb_edit_frame.h>
45 
46 #include <board.h>
47 #include <zone.h>
48 
49 #include <pcbnew.h>
50 #include <zones.h>
52 
60 bool ZONE::IsSame( const ZONE& aZoneToCompare )
61 {
62  // compare basic parameters:
63  if( GetLayerSet() != aZoneToCompare.GetLayerSet() )
64  return false;
65 
66  if( GetNetCode() != aZoneToCompare.GetNetCode() )
67  return false;
68 
69  if( GetPriority() != aZoneToCompare.GetPriority() )
70  return false;
71 
72  // Compare zone specific parameters
73  if( GetIsRuleArea() != aZoneToCompare.GetIsRuleArea() )
74  return false;
75 
76  if( GetIsRuleArea() )
77  {
78  if( GetDoNotAllowCopperPour() != aZoneToCompare.GetDoNotAllowCopperPour() )
79  return false;
80 
81  if( GetDoNotAllowVias() != aZoneToCompare.GetDoNotAllowVias() )
82  return false;
83 
84  if( GetDoNotAllowTracks() != aZoneToCompare.GetDoNotAllowTracks() )
85  return false;
86 
87  if( GetDoNotAllowPads() != aZoneToCompare.GetDoNotAllowPads() )
88  return false;
89 
90  if( GetDoNotAllowFootprints() != aZoneToCompare.GetDoNotAllowFootprints() )
91  return false;
92  }
93 
94  if( m_ZoneClearance != aZoneToCompare.m_ZoneClearance )
95  return false;
96 
97  if( m_ZoneMinThickness != aZoneToCompare.GetMinThickness() )
98  return false;
99 
100  if( m_fillMode != aZoneToCompare.GetFillMode() )
101  return false;
102 
103  if( m_PadConnection != aZoneToCompare.m_PadConnection )
104  return false;
105 
106  if( m_thermalReliefGap != aZoneToCompare.m_thermalReliefGap )
107  return false;
108 
110  return false;
111 
112  if( m_zoneName != aZoneToCompare.m_zoneName )
113  return false;
114 
115  if( m_islandRemovalMode != aZoneToCompare.m_islandRemovalMode )
116  return false;
117 
118  if( m_minIslandArea != aZoneToCompare.m_minIslandArea )
119  return false;
120 
121 
122  // Compare outlines
123  wxASSERT( m_Poly ); // m_Poly == NULL Should never happen
124  wxASSERT( aZoneToCompare.Outline() );
125 
126  if( Outline() != aZoneToCompare.Outline() ) // Compare vector
127  return false;
128 
129  return true;
130 }
131 
132 
145 int SaveCopyOfZones( PICKED_ITEMS_LIST& aPickList, BOARD* aPcb, int aNetCode, LAYER_NUM aLayer )
146 {
147  int copyCount = 0;
148 
149  for( unsigned ii = 0; ; ii++ )
150  {
151  ZONE* zone = aPcb->GetArea( ii );
152 
153  if( zone == nullptr ) // End of list
154  break;
155 
156  if( aNetCode >= 0 && aNetCode != zone->GetNetCode() )
157  continue;
158 
159  if( aLayer >= 0 && !zone->GetLayerSet().test( aLayer ) )
160  continue;
161 
162  ZONE* zoneDup = new ZONE( *zone );
163  zoneDup->SetParent( aPcb );
164  ITEM_PICKER picker( nullptr, zone, UNDO_REDO::CHANGED );
165  picker.SetLink( zoneDup );
166  aPickList.PushItem( picker );
167  copyCount++;
168  }
169 
170  return copyCount;
171 }
172 
173 
210  PICKED_ITEMS_LIST& aAuxiliaryList,
211  BOARD* aPcb )
212 {
213  for( unsigned kk = 0; kk < aPickList.GetCount(); kk++ )
214  {
215  UNDO_REDO status = aPickList.GetPickedItemStatus( kk );
216 
217  ZONE* ref = (ZONE*) aPickList.GetPickedItem( kk );
218 
219  for( unsigned ii = 0; ; ii++ ) // analyse the main picked list
220  {
221  ZONE* zone = aPcb->GetArea( ii );
222 
223  if( zone == nullptr )
224  {
225  /* End of list: the stored item is not found:
226  * it must be in aDeletedList:
227  * search it and restore initial values
228  * or
229  * if flagged NEWITEM: remove it definitively
230  */
231  if( status == UNDO_REDO::NEWITEM )
232  {
233  delete ref;
234  ref = nullptr;
235  aPickList.RemovePicker( kk );
236  kk--;
237  }
238  else
239  {
240  ZONE* zcopy = (ZONE*) aPickList.GetPickedItemLink( kk );
241  aPickList.SetPickedItemStatus( UNDO_REDO::DELETED, kk );
242 
243  wxASSERT_MSG( zcopy != nullptr,
244  wxT( "UpdateCopyOfZonesList() error: link = NULL" ) );
245 
246  *ref = *zcopy;
247 
248  // the copy was deleted; the link does not exists now.
249  aPickList.SetPickedItemLink( nullptr, kk );
250  delete zcopy;
251  }
252 
253  // Remove this item from aAuxiliaryList, mainly for tests purpose
254  bool notfound = true;
255 
256  for( unsigned nn = 0; nn < aAuxiliaryList.GetCount(); nn++ )
257  {
258  if( ref != nullptr && aAuxiliaryList.GetPickedItem( nn ) == ref )
259  {
260  aAuxiliaryList.RemovePicker( nn );
261  notfound = false;
262  break;
263  }
264  }
265 
266  if( notfound ) // happens when the new zone overlaps an existing zone
267  // and these zones are combined
268  {
269  #if defined(DEBUG)
270  printf( "UpdateCopyOfZonesList(): item not found in aAuxiliaryList,"
271  "combined with another zone\n" );
272  fflush(nullptr);
273  #endif
274  }
275  break;
276  }
277 
278  if( zone == ref ) // picked zone found
279  {
280  if( aPickList.GetPickedItemStatus( kk ) != UNDO_REDO::NEWITEM )
281  {
282  ZONE* zcopy = (ZONE*) aPickList.GetPickedItemLink( kk );
283 
284  if( zone->IsSame( *zcopy ) ) // Remove picked, because no changes
285  {
286  delete zcopy; // Delete copy
287  aPickList.RemovePicker( kk );
288  kk--;
289  }
290  }
291 
292  break;
293  }
294  }
295  }
296 
297  // Add new zones in main pick list, and remove pickers from Auxiliary List
298  for( unsigned ii = 0; ii < aAuxiliaryList.GetCount(); )
299  {
300  if( aAuxiliaryList.GetPickedItemStatus( ii ) == UNDO_REDO::NEWITEM )
301  {
302  ITEM_PICKER picker = aAuxiliaryList.GetItemWrapper( ii );
303  aPickList.PushItem( picker );
304  aAuxiliaryList.RemovePicker( ii );
305  }
306  else if( aAuxiliaryList.GetPickedItemStatus( ii ) == UNDO_REDO::DELETED )
307  {
308  delete aAuxiliaryList.GetPickedItemLink( ii );
309  aAuxiliaryList.RemovePicker( ii );
310  }
311  else
312  ii++;
313  }
314 
315  // Should not occur:
316  wxASSERT_MSG( aAuxiliaryList.GetCount() == 0,
317  wxT( "UpdateCopyOfZonesList() error: aAuxiliaryList not empty." ) );
318 }
EDA_ITEM * GetPickedItemLink(unsigned int aIdx) const
bool GetDoNotAllowFootprints() const
Definition: zone.h:738
ZONE_FILL_MODE m_fillMode
How to fill areas:
Definition: zone.h:885
int m_ZoneClearance
Definition: zone.h:853
unsigned GetPriority() const
Definition: zone.h:122
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition: zone.h:733
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...
SHAPE_POLY_SET * m_Poly
Outline of the zone.
Definition: zone.h:823
wxString m_zoneName
An optional unique name for this zone, used for identifying it in DRC checking.
Definition: zone.h:828
ZONE_CONNECTION m_PadConnection
Definition: zone.h:852
SHAPE_POLY_SET * Outline()
Definition: zone.h:320
bool GetDoNotAllowVias() const
Definition: zone.h:735
long long int m_minIslandArea
When island removal mode is set to AREA, islands below this area will be removed.
Definition: zone.h:863
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: zone.cpp:291
int LAYER_NUM
This can be replaced with int and removed.
Definition: layer_ids.h:40
void PushItem(const ITEM_PICKER &aItem)
Push aItem to the top of the list.
bool IsSame(const ZONE &aZoneToCompare)
Test if 2 zones are equivalent.
ZONE * GetArea(int index) const
Return the Zone at a given index.
Definition: board.h:834
void SetLink(EDA_ITEM *aItem)
UNDO_REDO
Undo Redo considerations: Basically we have 3 cases New item Deleted item Modified item there is also...
unsigned GetCount() const
ZONE_FILL_MODE GetFillMode() const
Definition: zone.h:181
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:116
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,...
bool GetDoNotAllowPads() const
Definition: zone.h:737
bool GetDoNotAllowCopperPour() const
Definition: zone.h:734
int GetMinThickness() const
Definition: zone.h:244
bool GetDoNotAllowTracks() const
Definition: zone.h:736
int m_thermalReliefGap
Definition: zone.h:875
EDA_ITEM * GetPickedItem(unsigned int aIdx) const
ISLAND_REMOVAL_MODE m_islandRemovalMode
Definition: zone.h:857
Handle a list of polygons defining a copper zone.
Definition: zone.h:56
bool RemovePicker(unsigned aIdx)
Remove one entry (one picker) from the list of picked items.
A holder to handle information on schematic or board items.
int m_ZoneMinThickness
Definition: zone.h:854
ITEM_PICKER GetItemWrapper(unsigned int aIdx) const
bool SetPickedItemStatus(UNDO_REDO aStatus, unsigned aIdx)
Set the type of undo/redo operation for a given picked item.
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
bool SetPickedItemLink(EDA_ITEM *aLink, unsigned aIdx)
Set the link associated to a given picked item.
UNDO_REDO GetPickedItemStatus(unsigned int aIdx) const
int m_thermalReliefSpokeWidth
Definition: zone.h:876