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-2012 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  // Combine zones if possible
105  GetBoard()->OnAreaPolygonModified( &deletedList, aZone );
106 
107  UpdateCopyOfZonesList( pickedList, deletedList, GetBoard() );
108 
109  // refill zones with the new properties applied
110  std::vector<ZONE*> zones_to_refill;
111 
112  for( unsigned i = 0; i < pickedList.GetCount(); ++i )
113  {
114  ZONE* zone = dyn_cast<ZONE*>( pickedList.GetPickedItem( i ) );
115 
116  if( zone == nullptr )
117  {
118  wxASSERT_MSG( false, "Expected a zone after zone properties edit" );
119  continue;
120  }
121 
122  // aZone won't be filled if the layer set was modified, but it needs to be updated
123  if( zone->IsFilled() || zone == aZone )
124  zones_to_refill.push_back( zone );
125  }
126 
127  commit.Stage( pickedList );
128 
129  // Only auto-refill zones here if in user preferences
130  if( Settings().m_AutoRefillZones )
131  {
132  std::lock_guard<KISPINLOCK> lock( GetBoard()->GetConnectivity()->GetLock() );
133 
134  if( zones_to_refill.size() )
135  {
136  ZONE_FILLER filler( GetBoard(), &commit );
137  wxString title = wxString::Format( _( "Refill %d Zones" ),
138  (int) zones_to_refill.size() );
139 
140  std::unique_ptr<WX_PROGRESS_REPORTER> reporter;
141  reporter = std::make_unique<WX_PROGRESS_REPORTER>( this, title, 4 );
142  filler.SetProgressReporter( reporter.get() );
143 
144  if( !filler.Fill( zones_to_refill ) )
145  {
146  // User has already OK'ed dialog so we're going to go ahead and commit even if the
147  // fill was cancelled.
148  }
149  }
150  }
151 
152  commit.Push( _( "Modify zone properties" ) );
153  GetBoard()->GetConnectivity()->RecalculateRatsnest();
154 
155  pickedList.ClearItemsList(); // s_ItemsListPicker is no longer owner of picked items
156 }
157 
158 
159 bool BOARD::OnAreaPolygonModified( PICKED_ITEMS_LIST* aModifiedZonesList, ZONE* modified_area )
160 {
161  // clip polygon against itself
162  bool modified = NormalizeAreaPolygon( aModifiedZonesList, modified_area );
163 
164  // Test for bad areas: all zones must have more than 2 corners:
165  // Note: should not happen, but just in case.
166  for( ZONE* zone : m_zones )
167  {
168  if( zone->GetNumCorners() < 3 )
169  {
170  ITEM_PICKER picker( nullptr, zone, UNDO_REDO::DELETED );
171  aModifiedZonesList->PushItem( picker );
172  zone->SetFlags( STRUCT_DELETED );
173  }
174  }
175 
176  return modified;
177 }
178 
179 
180 bool BOARD::TestZoneIntersection( ZONE* aZone1, ZONE* aZone2 )
181 {
182  // see if areas are on same layer
183  if( aZone1->GetLayer() != aZone2->GetLayer() )
184  return false;
185 
186  SHAPE_POLY_SET* poly1 = aZone1->Outline();
187  SHAPE_POLY_SET* poly2 = aZone2->Outline();
188 
189  // test bounding rects
190  BOX2I b1 = poly1->BBox();
191  BOX2I b2 = poly2->BBox();
192 
193  if( ! b1.Intersects( b2 ) )
194  return false;
195 
196  // Now test for intersecting segments
197  for( auto segIterator1 = poly1->IterateSegmentsWithHoles(); segIterator1; segIterator1++ )
198  {
199  // Build segment
200  SEG firstSegment = *segIterator1;
201 
202  for( auto segIterator2 = poly2->IterateSegmentsWithHoles(); segIterator2; segIterator2++ )
203  {
204  // Build second segment
205  SEG secondSegment = *segIterator2;
206 
207  // Check whether the two segments built collide
208  if( firstSegment.Collide( secondSegment, 0 ) )
209  return true;
210  }
211  }
212 
213  // If a contour is inside another contour, no segments intersects, but the zones
214  // can be combined if a corner is inside an outline (only one corner is enough)
215  for( auto iter = poly2->IterateWithHoles(); iter; iter++ )
216  {
217  if( poly1->Contains( *iter ) )
218  return true;
219  }
220 
221  for( auto iter = poly1->IterateWithHoles(); iter; iter++ )
222  {
223  if( poly2->Contains( *iter ) )
224  return true;
225  }
226 
227  return false;
228 }
229 
230 
231 
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1325
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:733
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.
void PushItem(const ITEM_PICKER &aItem)
Push aItem to the top of the list.
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:78
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
bool NormalizeAreaPolygon(PICKED_ITEMS_LIST *aNewZonesList, ZONE *aCurrArea)
Process an area that has been modified, by normalizing its polygon against itself.
Definition: board.cpp:1832
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.
ZONES m_zones
Definition: board.h:1124
bool OnAreaPolygonModified(PICKED_ITEMS_LIST *aModifiedZonesList, ZONE *modified_area)
Process an area that has been modified, by normalizing its polygon and merging the intersecting polyg...
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:344
EDA_ITEM * GetPickedItem(unsigned int aIdx) const
#define STRUCT_DELETED
flag indication structures to be erased
#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:796
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:115