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, jean-pierre.charras@ujf-grenoble.fr
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_i.h>
28 #include <confirm.h>
29 #include <pcb_edit_frame.h>
30 #include <board_commit.h>
31 #include <zone.h>
32 #include <zones.h>
36 #include <zone_filler.h>
37 
38 
40 {
41  int dialogResult;
42  ZONE_SETTINGS zoneInfo = GetZoneSettings();
43  PICKED_ITEMS_LIST pickedList; // zones for undo/redo command
44  PICKED_ITEMS_LIST deletedList; // zones that have been deleted when combined
45  BOARD_COMMIT commit( this );
46 
47  // Save initial zones configuration, for undo/redo, before adding new zone
48  // note the net name and the layer can be changed, so we must save all zones
49  deletedList.ClearListAndDeleteItems();
50  pickedList.ClearListAndDeleteItems();
51  SaveCopyOfZones( pickedList, GetBoard(), -1, UNDEFINED_LAYER );
52 
53  if( aZone->GetIsRuleArea() )
54  {
55  // edit a rule area on a copper layer
56  zoneInfo << *aZone;
57  dialogResult = InvokeRuleAreaEditor( this, &zoneInfo );
58  }
59  else if( IsCopperLayer( aZone->GetLayer() ) )
60  {
61  // edit a zone on a copper layer
62  zoneInfo << *aZone;
63  dialogResult = InvokeCopperZonesEditor( this, &zoneInfo );
64  }
65  else
66  {
67  zoneInfo << *aZone;
68  dialogResult = InvokeNonCopperZonesEditor( this, &zoneInfo );
69  }
70 
71  if( dialogResult == wxID_CANCEL )
72  {
73  deletedList.ClearListAndDeleteItems();
74  pickedList.ClearListAndDeleteItems();
75  return;
76  }
77 
78  SetZoneSettings( zoneInfo );
79  OnModify();
80 
81  if( dialogResult == ZONE_EXPORT_VALUES )
82  {
83  UpdateCopyOfZonesList( pickedList, deletedList, GetBoard() );
84  commit.Stage( pickedList );
85  commit.Push( _( "Modify zone properties" ) );
86  pickedList.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items
87  return;
88  }
89 
90  wxBusyCursor dummy;
91 
92  // Undraw old zone outlines
93  for( ZONE* zone : GetBoard()->Zones() )
94  GetCanvas()->GetView()->Update( zone );
95 
96  zoneInfo.ExportSetting( *aZone );
97 
98  NETINFO_ITEM* net = GetBoard()->FindNet( zoneInfo.m_NetcodeSelection );
99 
100  if( net ) // net == NULL should not occur
101  aZone->SetNetCode( net->GetNetCode() );
102 
103  // Combine zones if possible
104  GetBoard()->OnAreaPolygonModified( &deletedList, aZone );
105 
106  UpdateCopyOfZonesList( pickedList, deletedList, GetBoard() );
107 
108  // refill zones with the new properties applied
109  std::vector<ZONE*> zones_to_refill;
110 
111  for( unsigned i = 0; i < pickedList.GetCount(); ++i )
112  {
113  ZONE* zone = dyn_cast<ZONE*>( pickedList.GetPickedItem( i ) );
114 
115  if( zone == nullptr )
116  {
117  wxASSERT_MSG( false, "Expected a zone after zone properties edit" );
118  continue;
119  }
120 
121  // aZone won't be filled if the layer set was modified, but it needs to be updated
122  if( zone->IsFilled() || zone == aZone )
123  zones_to_refill.push_back( zone );
124  }
125 
126  commit.Stage( pickedList );
127 
128  std::lock_guard<KISPINLOCK> lock( GetBoard()->GetConnectivity()->GetLock() );
129 
130  if( zones_to_refill.size() )
131  {
132  ZONE_FILLER filler( GetBoard(), &commit );
133  wxString title = wxString::Format( _( "Refill %d Zones" ), (int) zones_to_refill.size() );
134  filler.InstallNewProgressReporter( this, title, 4 );
135 
136  if( !filler.Fill( zones_to_refill ) )
137  {
138  commit.Revert();
139  return;
140  }
141  }
142 
143  commit.Push( _( "Modify zone properties" ) );
144  GetBoard()->GetConnectivity()->RecalculateRatsnest();
145 
146  pickedList.ClearItemsList(); // s_ItemsListPicker is no longer owner of picked items
147 }
148 
149 
150 bool BOARD::OnAreaPolygonModified( PICKED_ITEMS_LIST* aModifiedZonesList, ZONE* modified_area )
151 {
152  // clip polygon against itself
153  bool modified = NormalizeAreaPolygon( aModifiedZonesList, modified_area );
154 
155  // Test for bad areas: all zones must have more than 2 corners:
156  // Note: should not happen, but just in case.
157  for( ZONE* zone : m_zones )
158  {
159  if( zone->GetNumCorners() < 3 )
160  {
161  ITEM_PICKER picker( nullptr, zone, UNDO_REDO::DELETED );
162  aModifiedZonesList->PushItem( picker );
163  zone->SetFlags( STRUCT_DELETED );
164  }
165  }
166 
167  return modified;
168 }
169 
170 
171 bool BOARD::TestZoneIntersection( ZONE* aZone1, ZONE* aZone2 )
172 {
173  // see if areas are on same layer
174  if( aZone1->GetLayer() != aZone2->GetLayer() )
175  return false;
176 
177  SHAPE_POLY_SET* poly1 = aZone1->Outline();
178  SHAPE_POLY_SET* poly2 = aZone2->Outline();
179 
180  // test bounding rects
181  BOX2I b1 = poly1->BBox();
182  BOX2I b2 = poly2->BBox();
183 
184  if( ! b1.Intersects( b2 ) )
185  return false;
186 
187  // Now test for intersecting segments
188  for( auto segIterator1 = poly1->IterateSegmentsWithHoles(); segIterator1; segIterator1++ )
189  {
190  // Build segment
191  SEG firstSegment = *segIterator1;
192 
193  for( auto segIterator2 = poly2->IterateSegmentsWithHoles(); segIterator2; segIterator2++ )
194  {
195  // Build second segment
196  SEG secondSegment = *segIterator2;
197 
198  // Check whether the two segments built collide
199  if( firstSegment.Collide( secondSegment, 0 ) )
200  return true;
201  }
202  }
203 
204  // If a contour is inside another contour, no segments intersects, but the zones
205  // can be combined if a corner is inside an outline (only one corner is enough)
206  for( auto iter = poly2->IterateWithHoles(); iter; iter++ )
207  {
208  if( poly1->Contains( *iter ) )
209  return true;
210  }
211 
212  for( auto iter = poly1->IterateWithHoles(); iter; iter++ )
213  {
214  if( poly2->Contains( *iter ) )
215  return true;
216  }
217 
218  return false;
219 }
220 
221 
222 
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1268
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:755
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:323
virtual void Revert() override
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:158
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
Definition: sch_symbol.cpp:69
void PushItem(const ITEM_PICKER &aItem)
Push aItem to the top of the list.
bool IsFilled() const
Definition: zone.h:237
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
void InstallNewProgressReporter(wxWindow *aParent, const wxString &aTitle, int aNumPhases)
Definition: zone_filler.cpp:70
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
Function Intersects.
Definition: box2.h:236
bool Fill(std::vector< ZONE * > &aZones, bool aCheck=false, wxWindow *aParent=nullptr)
Fills the given list of zones.
Definition: zone_filler.cpp:85
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:1814
void ExportSetting(ZONE &aTarget, bool aFullExport=true) const
Function ExportSetting copy settings to a given zone.
ZONES m_zones
Definition: board.h:205
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:215
const ZONE_SETTINGS & GetZoneSettings() const
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:414
EDA_ITEM * GetPickedItem(unsigned int aIdx) const
ZONE handles a list of polygons defining a copper zone.
Definition: zone.h:57
#define STRUCT_DELETED
flag indication structures to be erased
Definition: eda_item.h:115
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.
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:41
void Edit_Zone_Params(ZONE *zone_container)
Edit params (layer, clearance, ...) for a zone outline.
Handle the data for a net.
Definition: netinfo.h:64
#define _(s)
Definition: 3d_actions.cpp:33
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.
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
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:113