KiCad PCB EDA Suite
zone_filler.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) 2014-2017 CERN
5  * Copyright (C) 2014-2018 KiCad Developers, see AUTHORS.txt for contributors.
6  * @author Tomasz W┼éostowski <tomasz.wlostowski@cern.ch>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 #include <cstdint>
27 #include <thread>
28 #include <mutex>
29 #include <algorithm>
30 #include <future>
31 
32 #include <class_board.h>
33 #include <class_zone.h>
34 #include <class_module.h>
35 #include <class_edge_mod.h>
36 #include <class_drawsegment.h>
37 #include <class_track.h>
38 #include <class_pcb_text.h>
39 #include <class_pcb_target.h>
40 
42 #include <board_commit.h>
43 
45 
47 #include <geometry/shape_file_io.h>
48 #include <geometry/convex_hull.h>
50 #include <confirm.h>
51 
52 #include "zone_filler.h"
53 
54 
55 extern void CreateThermalReliefPadPolygon( SHAPE_POLY_SET& aCornerBuffer,
56  const D_PAD& aPad,
57  int aThermalGap,
58  int aCopperThickness,
59  int aMinThicknessValue,
60  int aCircleToSegmentsCount,
61  double aCorrectionFactor,
62  double aThermalRot );
63 
64 static double s_thermalRot = 450; // angle of stubs in thermal reliefs for round pads
65 static const bool s_DumpZonesWhenFilling = false;
66 
67 ZONE_FILLER::ZONE_FILLER( BOARD* aBoard, COMMIT* aCommit ) :
68  m_board( aBoard ), m_commit( aCommit ), m_progressReporter( nullptr )
69 {
70 }
71 
72 
74 {
75 }
76 
77 
79 {
80  m_progressReporter = aReporter;
81 }
82 
83 bool ZONE_FILLER::Fill( std::vector<ZONE_CONTAINER*> aZones, bool aCheck )
84 {
85  std::vector<CN_ZONE_ISOLATED_ISLAND_LIST> toFill;
86  auto connectivity = m_board->GetConnectivity();
87 
88  std::unique_lock<std::mutex> lock( connectivity->GetLock(), std::try_to_lock );
89 
90  if( !lock )
91  return false;
92 
93  for( auto zone : aZones )
94  {
95  // Keepout zones are not filled
96  if( zone->GetIsKeepout() )
97  continue;
98 
99  toFill.emplace_back( CN_ZONE_ISOLATED_ISLAND_LIST(zone) );
100  }
101 
102  for( unsigned i = 0; i < toFill.size(); i++ )
103  {
104  if( m_commit )
105  {
106  m_commit->Modify( toFill[i].m_zone );
107  }
108  }
109 
110  if( m_progressReporter )
111  {
112  m_progressReporter->Report( _( "Checking zone fills..." ) );
113  m_progressReporter->SetMaxProgress( toFill.size() );
114  }
115 
116  // Remove deprecaded segment zones (only found in very old boards)
118 
119  std::atomic<size_t> nextItem( 0 );
120  size_t parallelThreadCount = std::min<size_t>( std::thread::hardware_concurrency(), toFill.size() );
121  std::vector<std::future<size_t>> returns( parallelThreadCount );
122 
123  auto fill_lambda = [&] ( PROGRESS_REPORTER* aReporter ) -> size_t
124  {
125  size_t num = 0;
126 
127  for( size_t i = nextItem++; i < toFill.size(); i = nextItem++ )
128  {
129  ZONE_CONTAINER* zone = toFill[i].m_zone;
130 
131  if( zone->GetFillMode() == ZFM_SEGMENTS )
132  {
133  ZONE_SEGMENT_FILL segFill;
134  fillZoneWithSegments( zone, zone->GetFilledPolysList(), segFill );
135  zone->SetFillSegments( segFill );
136  }
137  else
138  {
139  SHAPE_POLY_SET rawPolys, finalPolys;
140  fillSingleZone( zone, rawPolys, finalPolys );
141 
142  zone->SetRawPolysList( rawPolys );
143  zone->SetFilledPolysList( finalPolys );
144  }
145 
146  zone->SetIsFilled( true );
147 
148  if( m_progressReporter )
150 
151  num++;
152  }
153 
154  return num;
155  };
156 
157  if( parallelThreadCount <= 1 )
158  fill_lambda( m_progressReporter );
159  else
160  {
161  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
162  returns[ii] = std::async( std::launch::async, fill_lambda, m_progressReporter );
163 
164  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
165  {
166  // Here we balance returns with a 100ms timeout to allow UI updating
167  std::future_status status;
168  do
169  {
170  if( m_progressReporter )
172 
173  status = returns[ii].wait_for( std::chrono::milliseconds( 100 ) );
174  } while( status != std::future_status::ready );
175  }
176  }
177 
178  // Now update the connectivity to check for copper islands
179  if( m_progressReporter )
180  {
182  m_progressReporter->Report( _( "Removing insulated copper islands..." ) );
184  }
185 
186  connectivity->SetProgressReporter( m_progressReporter );
187  connectivity->FindIsolatedCopperIslands( toFill );
188 
189  // Now remove insulated copper islands
190  bool outOfDate = false;
191 
192  for( auto& zone : toFill )
193  {
194  std::sort( zone.m_islands.begin(), zone.m_islands.end(), std::greater<int>() );
195  SHAPE_POLY_SET poly = zone.m_zone->GetFilledPolysList();
196 
197  for( auto idx : zone.m_islands )
198  {
199  poly.DeletePolygon( idx );
200  }
201 
202  zone.m_zone->SetFilledPolysList( poly );
203 
204  if( aCheck && zone.m_lastPolys.GetHash() != poly.GetHash() )
205  outOfDate = true;
206  }
207 
208  if( aCheck )
209  {
210  bool refill = false;
211  wxCHECK( m_progressReporter, false );
212 
213  if( outOfDate )
214  {
215  m_progressReporter->Hide();
216 
217  KIDIALOG dlg( m_progressReporter->GetParent(),
218  _( "Zone fills are out-of-date. Refill?" ),
219  _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
220  dlg.SetOKCancelLabels( _( "Refill" ), _( "Continue without Refill" ) );
221  dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
222 
223  refill = ( dlg.ShowModal() == wxID_OK );
224 
225  m_progressReporter->Show();
226  }
227 
228  if( !refill )
229  {
230  if( m_commit )
231  m_commit->Revert();
232 
233  connectivity->SetProgressReporter( nullptr );
234  return false;
235  }
236  }
237 
238  if( m_progressReporter )
239  {
241  m_progressReporter->Report( _( "Performing polygon fills..." ) );
242  m_progressReporter->SetMaxProgress( toFill.size() );
243  }
244 
245 
246  nextItem = 0;
247 
248  auto tri_lambda = [&] ( PROGRESS_REPORTER* aReporter ) -> size_t
249  {
250  size_t num = 0;
251 
252  for( size_t i = nextItem++; i < toFill.size(); i = nextItem++ )
253  {
254  toFill[i].m_zone->CacheTriangulation();
255  num++;
256 
257  if( m_progressReporter )
259  }
260 
261  return num;
262  };
263 
264  if( parallelThreadCount <= 1 )
265  tri_lambda( m_progressReporter );
266  else
267  {
268  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
269  returns[ii] = std::async( std::launch::async, tri_lambda, m_progressReporter );
270 
271  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
272  {
273  // Here we balance returns with a 100ms timeout to allow UI updating
274  std::future_status status;
275  do
276  {
277  if( m_progressReporter )
279 
280  status = returns[ii].wait_for( std::chrono::milliseconds( 100 ) );
281  } while( status != std::future_status::ready );
282  }
283  }
284 
285  if( m_progressReporter )
286  {
288  m_progressReporter->Report( _( "Committing changes..." ) );
290  }
291 
292  connectivity->SetProgressReporter( nullptr );
293 
294  if( m_commit )
295  {
296  m_commit->Push( _( "Fill Zone(s)" ), false );
297  }
298  else
299  {
300  for( unsigned i = 0; i < toFill.size(); i++ )
301  {
302  connectivity->Update( toFill[i].m_zone );
303  }
304 
305  connectivity->RecalculateRatsnest();
306  }
307 
308  return true;
309 }
310 
311 
313  SHAPE_POLY_SET& aFeatures ) const
314 {
315  // Set the number of segments in arc approximations
316  // Since we can no longer edit the segment count in pcbnew, we set
317  // the fill to our high-def count to avoid jagged knock-outs
318  // However, if the user has edited their zone to increase the segment count,
319  // we keep this preference
320  int segsPerCircle = std::max( aZone->GetArcSegmentCount(), ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF );
321 
322  /* calculates the coeff to compensate radius reduction of holes clearance
323  * due to the segment approx.
324  * For a circle the min radius is radius * cos( 2PI / segsPerCircle / 2)
325  * correctionFactor is 1 /cos( PI/segsPerCircle )
326  */
327  double correctionFactor = GetCircletoPolyCorrectionFactor( segsPerCircle );
328 
329  aFeatures.RemoveAllContours();
330 
331  int outline_half_thickness = aZone->GetMinThickness() / 2;
332 
333  // When removing holes, the holes must be expanded by outline_half_thickness
334  // to take in account the thickness of the zone outlines
335  int zone_clearance = aZone->GetClearance() + outline_half_thickness;
336 
337  // When holes are created by non copper items (edge cut items), use only
338  // the m_ZoneClearance parameter (zone clearance with no netclass clearance)
339  int zone_to_edgecut_clearance = aZone->GetZoneClearance() + outline_half_thickness;
340 
341  /* store holes (i.e. tracks and pads areas as polygons outlines)
342  * in a polygon list
343  */
344 
345  /* items ouside the zone bounding box are skipped
346  * the bounding box is the zone bounding box + the biggest clearance found in Netclass list
347  */
348  EDA_RECT item_boundingbox;
349  EDA_RECT zone_boundingbox = aZone->GetBoundingBox();
350  int biggest_clearance = m_board->GetDesignSettings().GetBiggestClearanceValue();
351  biggest_clearance = std::max( biggest_clearance, zone_clearance );
352  zone_boundingbox.Inflate( biggest_clearance );
353 
354  /*
355  * First : Add pads. Note: pads having the same net as zone are left in zone.
356  * Thermal shapes will be created later if necessary
357  */
358 
359  /* Use a dummy pad to calculate hole clearance when a pad is not on all copper layers
360  * and this pad has a hole
361  * This dummy pad has the size and shape of the hole
362  * Therefore, this dummy pad is a circle or an oval.
363  * A pad must have a parent because some functions expect a non null parent
364  * to find the parent board, and some other data
365  */
366  MODULE dummymodule( m_board ); // Creates a dummy parent
367  D_PAD dummypad( &dummymodule );
368 
369  for( MODULE* module = m_board->m_Modules; module; module = module->Next() )
370  {
371  D_PAD* nextpad;
372 
373  for( D_PAD* pad = module->PadsList(); pad != NULL; pad = nextpad )
374  {
375  nextpad = pad->Next(); // pad pointer can be modified by next code, so
376  // calculate the next pad here
377 
378  if( !pad->IsOnLayer( aZone->GetLayer() ) )
379  {
380  /* Test for pads that are on top or bottom only and have a hole.
381  * There are curious pads but they can be used for some components that are
382  * inside the board (in fact inside the hole. Some photo diodes and Leds are
383  * like this)
384  */
385  if( pad->GetDrillSize().x == 0 && pad->GetDrillSize().y == 0 )
386  continue;
387 
388  // Use a dummy pad to calculate a hole shape that have the same dimension as
389  // the pad hole
390  dummypad.SetSize( pad->GetDrillSize() );
391  dummypad.SetOrientation( pad->GetOrientation() );
392  dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
394  dummypad.SetPosition( pad->GetPosition() );
395 
396  pad = &dummypad;
397  }
398 
399  // Note: netcode <=0 means not connected item
400  if( ( pad->GetNetCode() != aZone->GetNetCode() ) || ( pad->GetNetCode() <= 0 ) )
401  {
402  int item_clearance = pad->GetClearance() + outline_half_thickness;
403  item_boundingbox = pad->GetBoundingBox();
404  item_boundingbox.Inflate( item_clearance );
405 
406  if( item_boundingbox.Intersects( zone_boundingbox ) )
407  {
408  int clearance = std::max( zone_clearance, item_clearance );
409 
410  // PAD_SHAPE_CUSTOM can have a specific keepout, to avoid to break the shape
411  if( pad->GetShape() == PAD_SHAPE_CUSTOM
412  && pad->GetCustomShapeInZoneOpt() == CUST_PAD_SHAPE_IN_ZONE_CONVEXHULL )
413  {
414  // the pad shape in zone can be its convex hull or
415  // the shape itself
416  SHAPE_POLY_SET outline( pad->GetCustomShapeAsPolygon() );
417  outline.Inflate( KiROUND( clearance * correctionFactor ), segsPerCircle );
418  pad->CustomShapeAsPolygonToBoardPosition( &outline,
419  pad->GetPosition(), pad->GetOrientation() );
420 
421  if( pad->GetCustomShapeInZoneOpt() == CUST_PAD_SHAPE_IN_ZONE_CONVEXHULL )
422  {
423  std::vector<wxPoint> convex_hull;
424  BuildConvexHull( convex_hull, outline );
425 
426  aFeatures.NewOutline();
427 
428  for( unsigned ii = 0; ii < convex_hull.size(); ++ii )
429  aFeatures.Append( convex_hull[ii] );
430  }
431  else
432  aFeatures.Append( outline );
433  }
434  else
435  pad->TransformShapeWithClearanceToPolygon( aFeatures,
436  clearance,
437  segsPerCircle,
438  correctionFactor );
439  }
440 
441  continue;
442  }
443 
444  // Pads are removed from zone if the setup is PAD_ZONE_CONN_NONE
445  // or if they have a custom shape and not PAD_ZONE_CONN_FULL,
446  // because a thermal relief will break
447  // the shape
448  if( aZone->GetPadConnection( pad ) == PAD_ZONE_CONN_NONE
449  || ( pad->GetShape() == PAD_SHAPE_CUSTOM && aZone->GetPadConnection( pad ) != PAD_ZONE_CONN_FULL ) )
450  {
451  int gap = zone_clearance;
452  int thermalGap = aZone->GetThermalReliefGap( pad );
453  gap = std::max( gap, thermalGap );
454  item_boundingbox = pad->GetBoundingBox();
455  item_boundingbox.Inflate( gap );
456 
457  if( item_boundingbox.Intersects( zone_boundingbox ) )
458  {
459  // PAD_SHAPE_CUSTOM has a specific keepout, to avoid to break the shape
460  // the pad shape in zone can be its convex hull or the shape itself
461  if( pad->GetShape() == PAD_SHAPE_CUSTOM
462  && pad->GetCustomShapeInZoneOpt() == CUST_PAD_SHAPE_IN_ZONE_CONVEXHULL )
463  {
464  // the pad shape in zone can be its convex hull or
465  // the shape itself
466  SHAPE_POLY_SET outline( pad->GetCustomShapeAsPolygon() );
467  outline.Inflate( KiROUND( gap * correctionFactor ), segsPerCircle );
468  pad->CustomShapeAsPolygonToBoardPosition( &outline,
469  pad->GetPosition(), pad->GetOrientation() );
470 
471  std::vector<wxPoint> convex_hull;
472  BuildConvexHull( convex_hull, outline );
473 
474  aFeatures.NewOutline();
475 
476  for( unsigned ii = 0; ii < convex_hull.size(); ++ii )
477  aFeatures.Append( convex_hull[ii] );
478  }
479  else
480  pad->TransformShapeWithClearanceToPolygon( aFeatures,
481  gap, segsPerCircle, correctionFactor );
482  }
483  }
484  }
485  }
486 
487  /* Add holes (i.e. tracks and vias areas as polygons outlines)
488  * in cornerBufferPolysToSubstract
489  */
490  for( auto track : m_board->Tracks() )
491  {
492  if( !track->IsOnLayer( aZone->GetLayer() ) )
493  continue;
494 
495  if( track->GetNetCode() == aZone->GetNetCode() && ( aZone->GetNetCode() != 0) )
496  continue;
497 
498  int item_clearance = track->GetClearance() + outline_half_thickness;
499  item_boundingbox = track->GetBoundingBox();
500 
501  if( item_boundingbox.Intersects( zone_boundingbox ) )
502  {
503  int clearance = std::max( zone_clearance, item_clearance );
504  track->TransformShapeWithClearanceToPolygon( aFeatures,
505  clearance, segsPerCircle, correctionFactor );
506  }
507  }
508 
509  /* Add graphic items that are on copper layers. These have no net, so we just
510  * use the zone clearance (or edge clearance).
511  */
512  auto doGraphicItem = [&]( BOARD_ITEM* aItem )
513  {
514  // A item on the Edge_Cuts is always seen as on any layer:
515  if( !aItem->IsOnLayer( aZone->GetLayer() ) && !aItem->IsOnLayer( Edge_Cuts ) )
516  return;
517 
518  if( !aItem->GetBoundingBox().Intersects( zone_boundingbox ) )
519  return;
520 
521  bool ignoreLineWidth = false;
522  int zclearance = zone_clearance;
523 
524  if( aItem->IsOnLayer( Edge_Cuts ) )
525  {
526  // use only the m_ZoneClearance, not the clearance using
527  // the netclass value, because we do not have a copper item
528  zclearance = zone_to_edgecut_clearance;
529 
530 #if 0
531 // 6.0 TODO: we're leaving this off for 5.1 so that people can continue to use the board
532 // edge width as a hack for edge clearance.
533  // edge cuts by definition don't have a width
534  ignoreLineWidth = true;
535 #endif
536  }
537 
538  switch( aItem->Type() )
539  {
540  case PCB_LINE_T:
541  ( (DRAWSEGMENT*) aItem )->TransformShapeWithClearanceToPolygon(
542  aFeatures, zclearance, segsPerCircle, correctionFactor, ignoreLineWidth );
543  break;
544 
545  case PCB_TEXT_T:
546  ( (TEXTE_PCB*) aItem )->TransformBoundingBoxWithClearanceToPolygon(
547  &aFeatures, zclearance );
548  break;
549 
550  case PCB_MODULE_EDGE_T:
551  ( (EDGE_MODULE*) aItem )->TransformShapeWithClearanceToPolygon(
552  aFeatures, zclearance, segsPerCircle, correctionFactor, ignoreLineWidth );
553  break;
554 
555  case PCB_MODULE_TEXT_T:
556  if( ( (TEXTE_MODULE*) aItem )->IsVisible() )
557  {
558  ( (TEXTE_MODULE*) aItem )->TransformBoundingBoxWithClearanceToPolygon(
559  &aFeatures, zclearance );
560  }
561  break;
562 
563  default:
564  break;
565  }
566  };
567 
568  for( auto module : m_board->Modules() )
569  {
570  doGraphicItem( &module->Reference() );
571  doGraphicItem( &module->Value() );
572 
573  for( auto item : module->GraphicalItems() )
574  doGraphicItem( item );
575  }
576 
577  for( auto item : m_board->Drawings() )
578  doGraphicItem( item );
579 
580  /* Add zones outlines having an higher priority and keepout
581  */
582  for( int ii = 0; ii < m_board->GetAreaCount(); ii++ )
583  {
584  ZONE_CONTAINER* zone = m_board->GetArea( ii );
585 
586  // If the zones share no common layers
587  if( !aZone->CommonLayerExists( zone->GetLayerSet() ) )
588  continue;
589 
590  if( !zone->GetIsKeepout() && zone->GetPriority() <= aZone->GetPriority() )
591  continue;
592 
593  if( zone->GetIsKeepout() && !zone->GetDoNotAllowCopperPour() )
594  continue;
595 
596  // A highter priority zone or keepout area is found: remove this area
597  item_boundingbox = zone->GetBoundingBox();
598 
599  if( !item_boundingbox.Intersects( zone_boundingbox ) )
600  continue;
601 
602  // Add the zone outline area.
603  // However if the zone has the same net as the current zone,
604  // do not add any clearance.
605  // the zone will be connected to the current zone, but filled areas
606  // will use different parameters (clearance, thermal shapes )
607  bool same_net = aZone->GetNetCode() == zone->GetNetCode();
608  bool use_net_clearance = true;
609  int min_clearance = zone_clearance;
610 
611  // Do not forget to make room to draw the thick outlines
612  // of the hole created by the area of the zone to remove
613  int holeclearance = zone->GetClearance() + outline_half_thickness;
614 
615  // The final clearance is obviously the max value of each zone clearance
616  min_clearance = std::max( min_clearance, holeclearance );
617 
618  if( zone->GetIsKeepout() || same_net )
619  {
620  // Just take in account the fact the outline has a thickness, so
621  // the actual area to substract is inflated to take in account this fact
622  min_clearance = outline_half_thickness;
623  use_net_clearance = false;
624  }
625 
627  aFeatures, min_clearance, use_net_clearance );
628  }
629 
630  /* Remove thermal symbols
631  */
632  for( auto module : m_board->Modules() )
633  {
634  for( auto pad : module->Pads() )
635  {
636  // Rejects non-standard pads with tht-only thermal reliefs
637  if( aZone->GetPadConnection( pad ) == PAD_ZONE_CONN_THT_THERMAL
638  && pad->GetAttribute() != PAD_ATTRIB_STANDARD )
639  continue;
640 
641  if( aZone->GetPadConnection( pad ) != PAD_ZONE_CONN_THERMAL
642  && aZone->GetPadConnection( pad ) != PAD_ZONE_CONN_THT_THERMAL )
643  continue;
644 
645  if( !pad->IsOnLayer( aZone->GetLayer() ) )
646  continue;
647 
648  if( pad->GetNetCode() != aZone->GetNetCode() )
649  continue;
650 
651  if( pad->GetNetCode() <= 0 )
652  continue;
653 
654  item_boundingbox = pad->GetBoundingBox();
655  int thermalGap = aZone->GetThermalReliefGap( pad );
656  item_boundingbox.Inflate( thermalGap, thermalGap );
657 
658  if( item_boundingbox.Intersects( zone_boundingbox ) )
659  {
661  *pad, thermalGap,
662  aZone->GetThermalReliefCopperBridge( pad ),
663  aZone->GetMinThickness(),
664  segsPerCircle,
665  correctionFactor, s_thermalRot );
666  }
667  }
668  }
669 }
670 
701  const SHAPE_POLY_SET& aSmoothedOutline,
702  SHAPE_POLY_SET& aRawPolys,
703  SHAPE_POLY_SET& aFinalPolys ) const
704 {
705  int outline_half_thickness = aZone->GetMinThickness() / 2;
706 
707  std::unique_ptr<SHAPE_FILE_IO> dumper( new SHAPE_FILE_IO(
708  s_DumpZonesWhenFilling ? "zones_dump.txt" : "", SHAPE_FILE_IO::IOM_APPEND ) );
709 
710  // Set the number of segments in arc approximations
711  int segsPerCircle = std::max( aZone->GetArcSegmentCount(), ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF );
712 
713  /* calculates the coeff to compensate radius reduction of holes clearance
714  */
715  double correctionFactor = GetCircletoPolyCorrectionFactor( segsPerCircle );
716 
718  dumper->BeginGroup( "clipper-zone" );
719 
720  SHAPE_POLY_SET solidAreas = aSmoothedOutline;
721 
722  solidAreas.Inflate( -outline_half_thickness, segsPerCircle );
723  solidAreas.Simplify( SHAPE_POLY_SET::PM_FAST );
724 
725  SHAPE_POLY_SET holes;
726 
728  dumper->Write( &solidAreas, "solid-areas" );
729 
730  buildZoneFeatureHoleList( aZone, holes );
731 
733  dumper->Write( &holes, "feature-holes" );
734 
736 
738  dumper->Write( &holes, "feature-holes-postsimplify" );
739 
740  // Generate the filled areas (currently, without thermal shapes, which will
741  // be created later).
742  // Use SHAPE_POLY_SET::PM_STRICTLY_SIMPLE to generate strictly simple polygons
743  // needed by Gerber files and Fracture()
745 
747  dumper->Write( &solidAreas, "solid-areas-minus-holes" );
748 
749  SHAPE_POLY_SET areas_fractured = solidAreas;
750  areas_fractured.Fracture( SHAPE_POLY_SET::PM_FAST );
751 
753  dumper->Write( &areas_fractured, "areas_fractured" );
754 
755  aFinalPolys = areas_fractured;
756 
757  SHAPE_POLY_SET thermalHoles;
758 
759  // Test thermal stubs connections and add polygons to remove unconnected stubs.
760  // (this is a refinement for thermal relief shapes)
761  if( aZone->GetNetCode() > 0 )
762  {
763  buildUnconnectedThermalStubsPolygonList( thermalHoles, aZone, aFinalPolys,
764  correctionFactor, s_thermalRot );
765 
766  }
767 
768  // remove copper areas corresponding to not connected stubs
769  if( !thermalHoles.IsEmpty() )
770  {
771  thermalHoles.Simplify( SHAPE_POLY_SET::PM_FAST );
772  // Remove unconnected stubs. Use SHAPE_POLY_SET::PM_STRICTLY_SIMPLE to
773  // generate strictly simple polygons
774  // needed by Gerber files and Fracture()
775  solidAreas.BooleanSubtract( thermalHoles, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
776 
778  dumper->Write( &thermalHoles, "thermal-holes" );
779 
780  // put these areas in m_FilledPolysList
781  SHAPE_POLY_SET th_fractured = solidAreas;
782  th_fractured.Fracture( SHAPE_POLY_SET::PM_FAST );
783 
785  dumper->Write( &th_fractured, "th_fractured" );
786 
787  aFinalPolys = th_fractured;
788  }
789 
790  aRawPolys = aFinalPolys;
791 
793  dumper->EndGroup();
794 }
795 
796 /* Build the filled solid areas data from real outlines (stored in m_Poly)
797  * The solid areas can be more than one on copper layers, and do not have holes
798  * ( holes are linked by overlapping segments to the main outline)
799  */
801  SHAPE_POLY_SET& aFinalPolys ) const
802 {
803  SHAPE_POLY_SET smoothedPoly;
804 
805  /* convert outlines + holes to outlines without holes (adding extra segments if necessary)
806  * m_Poly data is expected normalized, i.e. NormalizeAreaOutlines was used after building
807  * this zone
808  */
809  if ( !aZone->BuildSmoothedPoly( smoothedPoly ) )
810  return false;
811 
812  if( aZone->IsOnCopperLayer() )
813  {
814  computeRawFilledAreas( aZone, smoothedPoly, aRawPolys, aFinalPolys );
815  }
816  else
817  {
818  aRawPolys = smoothedPoly;
819  aFinalPolys = smoothedPoly;
820  aFinalPolys.Inflate( -aZone->GetMinThickness() / 2, ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF );
821  aFinalPolys.Fracture( SHAPE_POLY_SET::PM_FAST );
822  }
823 
824  return true;
825 }
826 
828  const SHAPE_POLY_SET& aFilledPolys,
829  ZONE_SEGMENT_FILL& aFillSegs ) const
830 {
831  bool success = true;
832  // segments are on something like a grid. Give it a minimal size
833  // to avoid too many segments, and use the m_ZoneMinThickness when (this is usually the case)
834  // the size is > mingrid_size.
835  // This is not perfect, but the actual purpose of this code
836  // is to allow filling zones on a grid, with grid size > m_ZoneMinThickness,
837  // in order to have really a grid.
838  //
839  // Using a user selectable grid size is for future Kicad versions.
840  // For now the area is fully filled.
841  int mingrid_size = Millimeter2iu( 0.05 );
842  int grid_size = std::max( mingrid_size, aZone->GetMinThickness() );
843  // Make segments slightly overlapping to ensure a good full filling
844  grid_size -= grid_size/20;
845 
846  // Creates the horizontal segments
847  for ( int index = 0; index < aFilledPolys.OutlineCount(); index++ )
848  {
849  const SHAPE_LINE_CHAIN& outline0 = aFilledPolys.COutline( index );
850  success = fillPolygonWithHorizontalSegments( outline0, aFillSegs, grid_size );
851 
852  if( !success )
853  break;
854 
855  // Creates the vertical segments. Because the filling algo creates horizontal segments,
856  // to reuse the fillPolygonWithHorizontalSegments function, we rotate the polygons to fill
857  // then fill them, then inverse rotate the result
858  SHAPE_LINE_CHAIN outline90;
859  outline90.Append( outline0 );
860 
861  // Rotate 90 degrees the outline:
862  for( int ii = 0; ii < outline90.PointCount(); ii++ )
863  {
864  VECTOR2I& point = outline90.Point( ii );
865  std::swap( point.x, point.y );
866  point.y = -point.y;
867  }
868 
869  int first_point = aFillSegs.size();
870  success = fillPolygonWithHorizontalSegments( outline90, aFillSegs, grid_size );
871 
872  if( !success )
873  break;
874 
875  // Rotate -90 degrees the segments:
876  for( unsigned ii = first_point; ii < aFillSegs.size(); ii++ )
877  {
878  SEG& segm = aFillSegs[ii];
879  std::swap( segm.A.x, segm.A.y );
880  std::swap( segm.B.x, segm.B.y );
881  segm.A.x = - segm.A.x;
882  segm.B.x = - segm.B.x;
883  }
884  }
885 
886  return success;
887 }
888 
898  ZONE_SEGMENT_FILL& aFillSegmList, int aStep ) const
899 {
900  std::vector <int> x_coordinates;
901  bool success = true;
902 
903  // Creates the horizontal segments
904  const SHAPE_LINE_CHAIN& outline = aPolygon;
905  const BOX2I& rect = outline.BBox();
906 
907  // Calculate the y limits of the zone
908  for( int refy = rect.GetY(), endy = rect.GetBottom(); refy < endy; refy += aStep )
909  {
910  // find all intersection points of an infinite line with polyline sides
911  x_coordinates.clear();
912 
913  for( int v = 0; v < outline.PointCount(); v++ )
914  {
915 
916  int seg_startX = outline.CPoint( v ).x;
917  int seg_startY = outline.CPoint( v ).y;
918  int seg_endX = outline.CPoint( v + 1 ).x;
919  int seg_endY = outline.CPoint( v + 1 ).y;
920 
921  /* Trivial cases: skip if ref above or below the segment to test */
922  if( ( seg_startY > refy ) && ( seg_endY > refy ) )
923  continue;
924 
925  // segment below ref point, or its Y end pos on Y coordinate ref point: skip
926  if( ( seg_startY <= refy ) && (seg_endY <= refy ) )
927  continue;
928 
929  /* at this point refy is between seg_startY and seg_endY
930  * see if an horizontal line at Y = refy is intersecting this segment
931  */
932  // calculate the x position of the intersection of this segment and the
933  // infinite line this is more easier if we move the X,Y axis origin to
934  // the segment start point:
935 
936  seg_endX -= seg_startX;
937  seg_endY -= seg_startY;
938  double newrefy = (double) ( refy - seg_startY );
939  double intersec_x;
940 
941  if ( seg_endY == 0 ) // horizontal segment on the same line: skip
942  continue;
943 
944  // Now calculate the x intersection coordinate of the horizontal line at
945  // y = newrefy and the segment from (0,0) to (seg_endX,seg_endY) with the
946  // horizontal line at the new refy position the line slope is:
947  // slope = seg_endY/seg_endX; and inv_slope = seg_endX/seg_endY
948  // and the x pos relative to the new origin is:
949  // intersec_x = refy/slope = refy * inv_slope
950  // Note: because horizontal segments are already tested and skipped, slope
951  // exists (seg_end_y not O)
952  double inv_slope = (double) seg_endX / seg_endY;
953  intersec_x = newrefy * inv_slope;
954  x_coordinates.push_back( (int) intersec_x + seg_startX );
955  }
956 
957  // A line scan is finished: build list of segments
958 
959  // Sort intersection points by increasing x value:
960  // So 2 consecutive points are the ends of a segment
961  std::sort( x_coordinates.begin(), x_coordinates.end() );
962 
963  // An even number of coordinates is expected, because a segment has 2 ends.
964  // An if this algorithm always works, it must always find an even count.
965  if( ( x_coordinates.size() & 1 ) != 0 )
966  {
967  success = false;
968  break;
969  }
970 
971  // Create segments having the same Y coordinate
972  int iimax = x_coordinates.size() - 1;
973 
974  for( int ii = 0; ii < iimax; ii += 2 )
975  {
976  VECTOR2I seg_start, seg_end;
977  seg_start.x = x_coordinates[ii];
978  seg_start.y = refy;
979  seg_end.x = x_coordinates[ii + 1];
980  seg_end.y = refy;
981  SEG segment( seg_start, seg_end );
982  aFillSegmList.push_back( segment );
983  }
984  } // End examine segments in one area
985 
986  return success;
987 }
988 
989 
1001  const ZONE_CONTAINER* aZone,
1002  const SHAPE_POLY_SET& aRawFilledArea,
1003  double aArcCorrection,
1004  double aRoundPadThermalRotation ) const
1005 {
1006  SHAPE_LINE_CHAIN spokes;
1007  BOX2I itemBB;
1008  VECTOR2I ptTest[4];
1009  auto zoneBB = aRawFilledArea.BBox();
1010 
1011 
1012  int zone_clearance = aZone->GetZoneClearance();
1013 
1014  int biggest_clearance = m_board->GetDesignSettings().GetBiggestClearanceValue();
1015  biggest_clearance = std::max( biggest_clearance, zone_clearance );
1016  zoneBB.Inflate( biggest_clearance );
1017 
1018  // half size of the pen used to draw/plot zones outlines
1019  int pen_radius = aZone->GetMinThickness() / 2;
1020 
1021  for( auto module : m_board->Modules() )
1022  {
1023  for( auto pad : module->Pads() )
1024  {
1025  // Rejects non-standard pads with tht-only thermal reliefs
1026  if( aZone->GetPadConnection( pad ) == PAD_ZONE_CONN_THT_THERMAL
1027  && pad->GetAttribute() != PAD_ATTRIB_STANDARD )
1028  continue;
1029 
1030  if( aZone->GetPadConnection( pad ) != PAD_ZONE_CONN_THERMAL
1031  && aZone->GetPadConnection( pad ) != PAD_ZONE_CONN_THT_THERMAL )
1032  continue;
1033 
1034  if( !pad->IsOnLayer( aZone->GetLayer() ) )
1035  continue;
1036 
1037  if( pad->GetNetCode() != aZone->GetNetCode() )
1038  continue;
1039 
1040  // Calculate thermal bridge half width
1041  int thermalBridgeWidth = aZone->GetThermalReliefCopperBridge( pad )
1042  - aZone->GetMinThickness();
1043  if( thermalBridgeWidth <= 0 )
1044  continue;
1045 
1046  // we need the thermal bridge half width
1047  // with a small extra size to be sure we create a stub
1048  // slightly larger than the actual stub
1049  thermalBridgeWidth = ( thermalBridgeWidth + 4 ) / 2;
1050 
1051  int thermalReliefGap = aZone->GetThermalReliefGap( pad );
1052 
1053  itemBB = pad->GetBoundingBox();
1054  itemBB.Inflate( thermalReliefGap );
1055  if( !( itemBB.Intersects( zoneBB ) ) )
1056  continue;
1057 
1058  // Thermal bridges are like a segment from a starting point inside the pad
1059  // to an ending point outside the pad
1060 
1061  // calculate the ending point of the thermal pad, outside the pad
1062  VECTOR2I endpoint;
1063  endpoint.x = ( pad->GetSize().x / 2 ) + thermalReliefGap;
1064  endpoint.y = ( pad->GetSize().y / 2 ) + thermalReliefGap;
1065 
1066  // Calculate the starting point of the thermal stub
1067  // inside the pad
1068  VECTOR2I startpoint;
1069  int copperThickness = aZone->GetThermalReliefCopperBridge( pad )
1070  - aZone->GetMinThickness();
1071 
1072  if( copperThickness < 0 )
1073  copperThickness = 0;
1074 
1075  // Leave a small extra size to the copper area inside to pad
1076  copperThickness += KiROUND( IU_PER_MM * 0.04 );
1077 
1078  startpoint.x = std::min( pad->GetSize().x, copperThickness );
1079  startpoint.y = std::min( pad->GetSize().y, copperThickness );
1080 
1081  startpoint.x /= 2;
1082  startpoint.y /= 2;
1083 
1084  // This is a CIRCLE pad tweak
1085  // for circle pads, the thermal stubs orientation is 45 deg
1086  double fAngle = pad->GetOrientation();
1087  if( pad->GetShape() == PAD_SHAPE_CIRCLE )
1088  {
1089  endpoint.x = KiROUND( endpoint.x * aArcCorrection );
1090  endpoint.y = endpoint.x;
1091  fAngle = aRoundPadThermalRotation;
1092  }
1093 
1094  // contour line width has to be taken into calculation to avoid "thermal stub bleed"
1095  endpoint.x += pen_radius;
1096  endpoint.y += pen_radius;
1097  // compute north, south, west and east points for zone connection.
1098  ptTest[0] = VECTOR2I( 0, endpoint.y ); // lower point
1099  ptTest[1] = VECTOR2I( 0, -endpoint.y ); // upper point
1100  ptTest[2] = VECTOR2I( endpoint.x, 0 ); // right point
1101  ptTest[3] = VECTOR2I( -endpoint.x, 0 ); // left point
1102 
1103  // Test all sides
1104  for( int i = 0; i < 4; i++ )
1105  {
1106  // rotate point
1107  RotatePoint( ptTest[i], fAngle );
1108 
1109  // translate point
1110  ptTest[i] += pad->ShapePos();
1111 
1112  if( aRawFilledArea.Contains( ptTest[i] ) )
1113  continue;
1114 
1115  spokes.Clear();
1116 
1117  // polygons are rectangles with width of copper bridge value
1118  switch( i )
1119  {
1120  case 0: // lower stub
1121  spokes.Append( -thermalBridgeWidth, endpoint.y );
1122  spokes.Append( +thermalBridgeWidth, endpoint.y );
1123  spokes.Append( +thermalBridgeWidth, startpoint.y );
1124  spokes.Append( -thermalBridgeWidth, startpoint.y );
1125  break;
1126 
1127  case 1: // upper stub
1128  spokes.Append( -thermalBridgeWidth, -endpoint.y );
1129  spokes.Append( +thermalBridgeWidth, -endpoint.y );
1130  spokes.Append( +thermalBridgeWidth, -startpoint.y );
1131  spokes.Append( -thermalBridgeWidth, -startpoint.y );
1132  break;
1133 
1134  case 2: // right stub
1135  spokes.Append( endpoint.x, -thermalBridgeWidth );
1136  spokes.Append( endpoint.x, thermalBridgeWidth );
1137  spokes.Append( +startpoint.x, thermalBridgeWidth );
1138  spokes.Append( +startpoint.x, -thermalBridgeWidth );
1139  break;
1140 
1141  case 3: // left stub
1142  spokes.Append( -endpoint.x, -thermalBridgeWidth );
1143  spokes.Append( -endpoint.x, thermalBridgeWidth );
1144  spokes.Append( -startpoint.x, thermalBridgeWidth );
1145  spokes.Append( -startpoint.x, -thermalBridgeWidth );
1146  break;
1147  }
1148 
1149  aCornerBuffer.NewOutline();
1150 
1151  // add computed polygon to list
1152  for( int ic = 0; ic < spokes.PointCount(); ic++ )
1153  {
1154  auto cpos = spokes.CPoint( ic );
1155  RotatePoint( cpos, fAngle ); // Rotate according to module orientation
1156  cpos += pad->ShapePos(); // Shift origin to position
1157  aCornerBuffer.Append( cpos );
1158  }
1159  }
1160  }
1161  }
1162 }
void SetFilledPolysList(SHAPE_POLY_SET &aPolysList)
Function SetFilledPolysList sets the list of filled polygons.
Definition: class_zone.h:573
virtual void Revert()=0
Revertes the commit by restoring the modifed items state.
void AdvancePhase()
Uses the next vailable virtual zone of the dialog progress bar.
coord_type GetY() const
Definition: box2.h:189
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:59
COMMIT & Modify(EDA_ITEM *aItem)
Modifies a given item in the model.
Definition: commit.h:103
std::vector< SEG > ZONE_SEGMENT_FILL
Definition: class_zone.h:49
void DoNotShowCheckbox(wxString file, int line)
Shows the &#39;do not show again&#39; checkbox
Definition: confirm.cpp:60
Class SHAPE_FILE_IO.
Definition: shape_file_io.h:38
TEXTE_PCB class definition.
bool CommonLayerExists(const LSET aLayerSet) const
Function CommonLayerExist Test if this zone shares a common layer with the given layer set...
Definition: class_zone.cpp:194
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:121
Helper class to create more flexible dialogs, including &#39;do not show again&#39; checkbox handling...
Definition: confirm.h:44
int GetMinThickness() const
Definition: class_zone.h:203
This file is part of the common library.
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class...
bool GetDoNotAllowCopperPour() const
Definition: class_zone.h:631
BOARD * m_board
Definition: zone_filler.h:118
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox (virtual)
Definition: class_zone.cpp:518
int GetBiggestClearanceValue()
Function GetBiggestClearanceValue.
int PointCount() const
Function PointCount()
int GetArcSegmentCount() const
Definition: class_zone.h:192
A progress reporter for use in multi-threaded environments.
Class BOARD to handle a board.
MD5_HASH GetHash() const
WX_PROGRESS_REPORTER * m_progressReporter
Definition: zone_filler.h:120
MODULE * Next() const
Definition: class_module.h:122
virtual PCB_LAYER_ID GetLayer() const override
Function GetLayer returns the primary layer this item is on.
Definition: class_zone.cpp:175
bool BuildSmoothedPoly(SHAPE_POLY_SET &aSmoothedPoly) const
Function GetSmoothedPoly returns a pointer to the corner-smoothed version of m_Poly if it exists...
void Report(const wxString &aMessage)
Display aMessage in the progress bar dialog.
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, bool aIgnoreHoles=false) const
Returns true if a given subpolygon contains the point aP.
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:92
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:219
Classes to handle copper zones.
Class COMMIT.
Definition: commit.h:71
void SetFillSegments(const ZONE_SEGMENT_FILL &aSegments)
Definition: class_zone.h:611
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:216
int OutlineCount() const
Returns the number of outlines in the set
void buildZoneFeatureHoleList(const ZONE_CONTAINER *aZone, SHAPE_POLY_SET &aFeatures) const
void DeleteAll()
Function DeleteAll deletes all items on the list and leaves the list empty.
Definition: dlist.cpp:44
VECTOR2< int > VECTOR2I
Definition: vector2d.h:587
int GetThermalReliefCopperBridge(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:637
void SetIsFilled(bool isFilled)
Definition: class_zone.h:195
void BuildConvexHull(std::vector< wxPoint > &aResult, const std::vector< wxPoint > &aPoly)
Calculate the convex hull of a list of points in counter-clockwise order.
Definition: convex_hull.cpp:87
static const bool s_DumpZonesWhenFilling
Definition: zone_filler.cpp:65
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_zone.cpp:774
Functions relatives to tracks, vias and segments used to fill zones.
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
void DeletePolygon(int aIdx)
Deletes aIdx-th polygon from the set
Pads are not covered.
Definition: zones.h:52
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:630
virtual LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
Definition: class_zone.cpp:230
void SetProgressReporter(WX_PROGRESS_REPORTER *aReporter)
Definition: zone_filler.cpp:78
ZoneConnection GetPadConnection(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:991
const BOX2I BBox(int aClearance=0) const override
Function BBox()
void Inflate(int aFactor, int aCircleSegmentsCount)
Performs outline inflation/deflation, using round corners.
DLIST_ITERATOR_WRAPPER< MODULE > Modules()
Definition: class_board.h:255
COMMIT * m_commit
Definition: zone_filler.h:119
Class SHAPE_POLY_SET.
ZONE_FILLER(BOARD *aBoard, COMMIT *aCommit=nullptr)
Definition: zone_filler.cpp:67
DLIST< SEGZONE > m_SegZoneDeprecated
Definition: class_board.h:251
void CreateThermalReliefPadPolygon(SHAPE_POLY_SET &aCornerBuffer, const D_PAD &aPad, int aThermalGap, int aCopperThickness, int aMinThicknessValue, int aCircleToSegmentsCount, double aCorrectionFactor, double aThermalRot)
Function CreateThermalReliefPadPolygon Add holes around a pad to create a thermal relief copper thick...
int GetThermalReliefGap(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:628
bool Fill(std::vector< ZONE_CONTAINER * > aZones, bool aCheck=false)
Definition: zone_filler.cpp:83
bool fillZoneWithSegments(const ZONE_CONTAINER *aZone, const SHAPE_POLY_SET &aFilledPolys, ZONE_SEGMENT_FILL &aFillSegs) const
Function fillZoneWithSegments Fill sub areas in a zone with segments with m_ZoneMinThickness width A ...
coord_type GetBottom() const
Definition: box2.h:198
D_PAD * Next() const
Definition: class_pad.h:160
ZONE_FILL_MODE GetFillMode() const
Definition: class_zone.h:180
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:539
void SetSize(const wxSize &aSize)
Definition: class_pad.h:268
bool Intersects(const BOX2< Vec > &aRect) const
Function Intersects.
Definition: box2.h:234
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
a few functions useful in geometry calculations.
void Simplify(POLYGON_MODE aFastMode)
Simplifies the polyset (merges overlapping polys, eliminates degeneracy/self-intersections) For aFast...
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1026
int NewOutline()
Creates a new empty polygon in the set and returns its index
const SHAPE_POLY_SET & GetFilledPolysList() const
Function GetFilledPolysList returns a reference to the list of filled polygons.
Definition: class_zone.h:559
Thermal relief only for THT pads.
Definition: zones.h:55
void Fracture(POLYGON_MODE aFastMode)
Converts a set of polygons with holes to a singe outline with "slits"/"fractures" connecting the oute...
void SetRawPolysList(SHAPE_POLY_SET &aPolysList)
Function SetFilledPolysList sets the list of filled polygons.
Definition: class_zone.h:582
static double s_thermalRot
Definition: zone_filler.cpp:64
int GetNetCode() const
Function GetNetCode.
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:93
Definition: seg.h:36
bool fillSingleZone(const ZONE_CONTAINER *aZone, SHAPE_POLY_SET &aRawPolys, SHAPE_POLY_SET &aFinalPolys) const
Build the filled solid areas polygons from zone outlines (stored in m_Poly) The solid areas can be mo...
bool fillPolygonWithHorizontalSegments(const SHAPE_LINE_CHAIN &aPolygon, ZONE_SEGMENT_FILL &aFillSegmList, int aStep) const
Helper function fillPolygonWithHorizontalSegments fills a polygon with horizontal segments...
void TransformOutlinesShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, int aMinClearanceValue, bool aUseNetClearance) const
Function TransformOutlinesShapeWithClearanceToPolygon Convert the outlines shape to a polygon with no...
bool Intersects(const EDA_RECT &aRect) const
Function Intersects tests for a common area between rectangles.
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:300
bool IsOnCopperLayer() const
Function IsOnCopperLayer.
Definition: class_zone.cpp:181
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true)=0
Executes the changes.
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:997
Class to handle a graphic segment.
#define max(a, b)
Definition: auxiliary.h:86
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:171
DLIST< MODULE > m_Modules
Definition: class_board.h:249
Class SHAPE_LINE_CHAIN.
size_t i
Definition: json11.cpp:597
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
bool KeepRefreshing(bool aWait=false)
Update the UI dialog.
VECTOR2I A
Definition: seg.h:44
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
Usual pad.
Definition: pad_shapes.h:60
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_pad.cpp:562
void SetShape(PAD_SHAPE_T aShape)
Definition: class_pad.h:217
void SetOrientation(double aAngle)
Function SetOrientation sets the rotation angle of the pad.
Definition: class_pad.cpp:417
void Clear()
Function Clear() Removes all points from the line chain.
VECTOR2I & Point(int aIndex)
Function Point()
PCB_TARGET class definition.
DLIST_ITERATOR_WRAPPER< TRACK > Tracks()
Definition: class_board.h:254
void computeRawFilledAreas(const ZONE_CONTAINER *aZone, const SHAPE_POLY_SET &aSmoothedOutline, SHAPE_POLY_SET &aRawPolys, SHAPE_POLY_SET &aFinalPolys) const
Function computeRawFilledAreas Add non copper areas polygons (pads and tracks with clearance) to a fi...
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset difference For aFastMode meaning, see function booleanOp ...
Module description (excepted pads)
bool IsEmpty() const
Returns true if the set is empty (no polygons at all)
unsigned GetPriority() const
Function GetPriority.
Definition: class_zone.h:106
EDGE_MODULE class definition.
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:91
void SetMaxProgress(int aMaxProgress)
Fix the value thar gives the 100 precent progress bar length (inside the current virtual zone) ...
void AdvanceProgress()
Increment the progress bar length (inside the current virtual zone)
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
#define ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF
Definition: pcbnew.h:42
const BOX2I BBox(int aClearance=0) const override
Function BBox()
void buildUnconnectedThermalStubsPolygonList(SHAPE_POLY_SET &aCornerBuffer, const ZONE_CONTAINER *aZone, const SHAPE_POLY_SET &aRawFilledArea, double aArcCorrection, double aRoundPadThermalRotation) const
Function buildUnconnectedThermalStubsPolygonList Creates a set of polygons corresponding to stubs cre...
Use thermal relief for pads.
Definition: zones.h:53
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:297
int GetZoneClearance() const
Definition: class_zone.h:197
DLIST_ITERATOR_WRAPPER< BOARD_ITEM > Drawings()
Definition: class_board.h:256
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
#define min(a, b)
Definition: auxiliary.h:85
pads are covered by copper
Definition: zones.h:54
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline) ...
VECTOR2I B
Definition: seg.h:45
double GetCircletoPolyCorrectionFactor(int aSegCountforCircle)