KiCad PCB EDA Suite
zones_test_and_combine_areas.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 <board.h>
28 #include <zone.h>
29 
30 
31 bool BOARD::OnAreaPolygonModified( PICKED_ITEMS_LIST* aModifiedZonesList, ZONE* modified_area )
32 {
33  // clip polygon against itself
34  bool modified = NormalizeAreaPolygon( aModifiedZonesList, modified_area );
35 
36  // now see if we need to clip against other areas
37  if( TestZoneIntersections( modified_area ) )
38  {
39  modified = true;
40  CombineAllZonesInNet( aModifiedZonesList, modified_area->GetNetCode(), true );
41  }
42 
43  // Test for bad areas: all zones must have more than 2 corners:
44  // Note: should not happen, but just in case.
45  for( ZONE* zone : m_zones )
46  {
47  if( zone->GetNumCorners() < 3 )
48  RemoveZone( aModifiedZonesList, zone );
49  }
50 
51  return modified;
52 }
53 
54 
55 bool BOARD::CombineAllZonesInNet( PICKED_ITEMS_LIST* aDeletedList, int aNetCode,
56  bool aUseLocalFlags )
57 {
58  if( m_zones.size() <= 1 )
59  return false;
60 
61  bool modified = false;
62 
63  // Loop through all combinations
64  for( unsigned ia1 = 0; ia1 < m_zones.size() - 1; ia1++ )
65  {
66  ZONE* refZone = m_zones[ia1];
67 
68  if( refZone->GetNetCode() != aNetCode )
69  continue;
70 
71  // legal polygon
72  BOX2I b1 = refZone->Outline()->BBox();
73  bool mod_ia1 = false;
74 
75  for( unsigned ia2 = m_zones.size() - 1; ia2 > ia1; ia2-- )
76  {
77  ZONE* otherZone = m_zones[ia2];
78 
79  if( otherZone->GetNetCode() != aNetCode )
80  continue;
81 
82  if( refZone->GetPriority() != otherZone->GetPriority() )
83  continue;
84 
85  if( refZone->GetIsRuleArea() != otherZone->GetIsRuleArea() )
86  continue;
87 
88  if( refZone->GetLayerSet() != otherZone->GetLayerSet() )
89  continue;
90 
91  BOX2I b2 = otherZone->Outline()->BBox();
92 
93  if( b1.Intersects( b2 ) )
94  {
95  // check otherZone against refZone
96  if( refZone->GetLocalFlags() || otherZone->GetLocalFlags() || !aUseLocalFlags )
97  {
98  bool ret = TestZoneIntersection( refZone, otherZone );
99 
100  if( ret )
101  ret = CombineZones( aDeletedList, refZone, otherZone );
102 
103  if( ret )
104  {
105  mod_ia1 = true;
106  modified = true;
107  }
108  }
109  }
110  }
111 
112  if( mod_ia1 )
113  ia1--; // if modified, we need to check it again
114  }
115 
116  return modified;
117 }
118 
119 
121 {
122  for( ZONE* otherZone : m_zones )
123  {
124  if( aZone->GetNetCode() != otherZone->GetNetCode() )
125  continue;
126 
127  if( aZone == otherZone )
128  continue;
129 
130  // see if areas are on same layers
131  if( aZone->GetLayerSet() != otherZone->GetLayerSet() )
132  continue;
133 
134  // test for different priorities
135  if( aZone->GetPriority() != otherZone->GetPriority() )
136  continue;
137 
138  // test for different types
139  if( aZone->GetIsRuleArea() != otherZone->GetIsRuleArea() )
140  continue;
141 
142  // Keepout area-specific tests
143  if( aZone->GetIsRuleArea() )
144  {
145  if( aZone->GetDoNotAllowCopperPour() != otherZone->GetDoNotAllowCopperPour() )
146  continue;
147 
148  if( aZone->GetDoNotAllowTracks() != otherZone->GetDoNotAllowTracks() )
149  continue;
150 
151  if( aZone->GetDoNotAllowVias() != otherZone->GetDoNotAllowVias() )
152  continue;
153 
154  if( aZone->GetDoNotAllowPads() != otherZone->GetDoNotAllowPads() )
155  continue;
156 
157  if( aZone->GetDoNotAllowFootprints() != otherZone->GetDoNotAllowFootprints() )
158  continue;
159  }
160  // Filled zone specific tests
161  else
162  {
163  if( aZone->GetLocalClearance() != otherZone->GetLocalClearance() )
164  continue;
165 
166  if( aZone->GetThermalReliefGap() != otherZone->GetThermalReliefGap() )
167  continue;
168 
169  if( aZone->GetThermalReliefSpokeWidth() != otherZone->GetThermalReliefSpokeWidth() )
170  continue;
171 
172  if( aZone->GetLocalClearance() != otherZone->GetLocalClearance() )
173  continue;
174 
175  if( aZone->GetPadConnection() != otherZone->GetPadConnection() )
176  continue;
177 
178  if( aZone->GetMinThickness() != otherZone->GetMinThickness() )
179  continue;
180 
181  if( aZone->GetCornerSmoothingType() != otherZone->GetCornerSmoothingType() )
182  continue;
183 
184  if( aZone->GetCornerRadius() != otherZone->GetCornerRadius() )
185  continue;
186  }
187 
188  if( TestZoneIntersection( aZone, otherZone ) )
189  return true;
190  }
191 
192  return false;
193 }
194 
195 
196 bool BOARD::TestZoneIntersection( ZONE* aZone1, ZONE* aZone2 )
197 {
198  // see if areas are on same layer
199  if( aZone1->GetLayer() != aZone2->GetLayer() )
200  return false;
201 
202  SHAPE_POLY_SET* poly1 = aZone1->Outline();
203  SHAPE_POLY_SET* poly2 = aZone2->Outline();
204 
205  // test bounding rects
206  BOX2I b1 = poly1->BBox();
207  BOX2I b2 = poly2->BBox();
208 
209  if( ! b1.Intersects( b2 ) )
210  return false;
211 
212  // Now test for intersecting segments
213  for( auto segIterator1 = poly1->IterateSegmentsWithHoles(); segIterator1; segIterator1++ )
214  {
215  // Build segment
216  SEG firstSegment = *segIterator1;
217 
218  for( auto segIterator2 = poly2->IterateSegmentsWithHoles(); segIterator2; segIterator2++ )
219  {
220  // Build second segment
221  SEG secondSegment = *segIterator2;
222 
223  // Check whether the two segments built collide
224  if( firstSegment.Collide( secondSegment, 0 ) )
225  return true;
226  }
227  }
228 
229  // If a contour is inside another contour, no segments intersects, but the zones
230  // can be combined if a corner is inside an outline (only one corner is enough)
231  for( auto iter = poly2->IterateWithHoles(); iter; iter++ )
232  {
233  if( poly1->Contains( *iter ) )
234  return true;
235  }
236 
237  for( auto iter = poly1->IterateWithHoles(); iter; iter++ )
238  {
239  if( poly2->Contains( *iter ) )
240  return true;
241  }
242 
243  return false;
244 }
245 
246 
247 bool BOARD::CombineZones( PICKED_ITEMS_LIST* aDeletedList, ZONE* aRefZone, ZONE* aZoneToCombine )
248 {
249  if( aRefZone == aZoneToCombine )
250  {
251  wxASSERT( 0 );
252  return false;
253  }
254 
255  SHAPE_POLY_SET mergedOutlines = *aRefZone->Outline();
256  SHAPE_POLY_SET areaToMergePoly = *aZoneToCombine->Outline();
257 
258  mergedOutlines.BooleanAdd( areaToMergePoly, SHAPE_POLY_SET::PM_FAST );
259  mergedOutlines.Simplify( SHAPE_POLY_SET::PM_FAST );
260 
261  // We should have one polygon with hole
262  // We can have 2 polygons with hole, if the 2 initial polygons have only one common corner
263  // and therefore cannot be merged (they are dectected as intersecting)
264  // but we should never have more than 2 polys
265  if( mergedOutlines.OutlineCount() > 2 )
266  {
267  wxLogMessage( "BOARD::CombineZones error: more than 2 polys after merging" );
268  return false;
269  }
270 
271  if( mergedOutlines.OutlineCount() > 1 )
272  return false;
273 
274  // Update the area with the new merged outline
275  delete aRefZone->Outline();
276  aRefZone->SetOutline( new SHAPE_POLY_SET( mergedOutlines ) );
277 
278  RemoveZone( aDeletedList, aZoneToCombine );
279 
280  aRefZone->SetLocalFlags( 1 );
281  aRefZone->HatchBorder();
282 
283  return true;
284 }
285 
286 
int GetNetCode() const
Function GetNetCode.
int OutlineCount() const
Returns the number of outlines in the set
bool GetDoNotAllowFootprints() const
Definition: zone.h:752
SEGMENT_ITERATOR IterateSegmentsWithHoles()
Returns an iterator object, for all outlines in the set (with holes)
unsigned GetPriority() const
Function GetPriority.
Definition: zone.h:124
void BooleanAdd(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset union For aFastMode meaning, see function booleanOp
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition: zone.h:747
SHAPE_POLY_SET * Outline()
Definition: zone.h:318
bool GetDoNotAllowVias() const
Definition: zone.h:749
bool Collide(const SEG &aSeg, int aClearance, int *aActual=nullptr) const
Definition: seg.cpp:139
virtual LSET GetLayerSet() const override
Function GetLayerSet returns a std::bitset of all layers on which the item physically resides.
Definition: zone.cpp:288
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, int aAccuracy=0, bool aUseBBoxCaches=false) const
Returns true if a given subpolygon contains the point aP.
bool TestZoneIntersection(ZONE *aZone1, ZONE *aZone2)
Test for intersection of 2 copper areas.
int GetThermalReliefGap() const
Definition: zone.h:190
bool Intersects(const BOX2< Vec > &aRect) const
Function Intersects.
Definition: box2.h:236
bool GetDoNotAllowPads() const
Definition: zone.h:751
bool GetDoNotAllowCopperPour() const
Definition: zone.h:748
int GetMinThickness() const
Definition: zone.h:242
bool NormalizeAreaPolygon(PICKED_ITEMS_LIST *aNewZonesList, ZONE *aCurrArea)
Process an area that has been modified, by normalizing its polygon against itself.
Definition: board.cpp:1797
ZONES m_zones
Definition: board.h:200
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...
void HatchBorder()
Function HatchBorder computes the hatch lines depending on the hatch parameters and stores it in the ...
Definition: zone.cpp:924
ITERATOR IterateWithHoles(int aOutline)
Function IterateWithHoles.
SHAPE_POLY_SET.
int GetLocalClearance(wxString *aSource) const override
Function GetLocalClearance returns any local clearances set in the "classic" (ie: pre-rule) system.
Definition: zone.cpp:470
virtual PCB_LAYER_ID GetLayer() const override
Function GetLayer returns the primary layer this item is on.
Definition: zone.cpp:215
void SetOutline(SHAPE_POLY_SET *aOutline)
Definition: zone.h:321
bool CombineAllZonesInNet(PICKED_ITEMS_LIST *aDeletedList, int aNetCode, bool aUseLocalFlags)
Check all copper areas in net for intersections, combining them if found.
bool TestZoneIntersections(ZONE *aZone)
Check for intersection of a given copper area with other areas in same net.
int GetLocalFlags() const
Definition: zone.h:303
bool GetDoNotAllowTracks() const
Definition: zone.h:750
void Simplify(POLYGON_MODE aFastMode)
Simplifies the polyset (merges overlapping polys, eliminates degeneracy/self-intersections) For aFast...
ZONE handles a list of polygons defining a copper zone.
Definition: zone.h:57
PICKED_ITEMS_LIST is a holder to handle information on schematic or board items.
bool CombineZones(PICKED_ITEMS_LIST *aDeletedList, ZONE *aRefZone, ZONE *aZoneToCombine)
If possible, combine 2 copper areas.
Definition: seg.h:39
unsigned int GetCornerRadius() const
Definition: zone.h:702
void SetLocalFlags(int aFlags)
Definition: zone.h:304
void RemoveZone(PICKED_ITEMS_LIST *aDeletedList, ZONE *aZone)
Remove copper area from net, and put it in a deleted list (if exists).
Definition: board.cpp:1779
int GetThermalReliefSpokeWidth() const
Definition: zone.h:200
ZONE_CONNECTION GetPadConnection(PAD *aPad, wxString *aSource=nullptr) const
Definition: zone.cpp:771
const BOX2I BBox(int aClearance=0) const override
Function BBox()
int GetCornerSmoothingType() const
Definition: zone.h:698