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  if( !connectivity->TryLock() )
89  return false;
90 
91  for( auto zone : aZones )
92  {
93  // Keepout zones are not filled
94  if( zone->GetIsKeepout() )
95  continue;
96 
97  toFill.emplace_back( CN_ZONE_ISOLATED_ISLAND_LIST(zone) );
98  }
99 
100  for( unsigned i = 0; i < toFill.size(); i++ )
101  {
102  if( m_commit )
103  {
104  m_commit->Modify( toFill[i].m_zone );
105  }
106  }
107 
108  if( m_progressReporter )
109  {
110  m_progressReporter->Report( _( "Checking zone fills..." ) );
111  m_progressReporter->SetMaxProgress( toFill.size() );
112  }
113 
114  // Remove deprecaded segment zones (only found in very old boards)
116 
117  std::atomic<size_t> nextItem( 0 );
118  size_t parallelThreadCount = std::min<size_t>( std::thread::hardware_concurrency(), toFill.size() );
119  std::vector<std::future<size_t>> returns( parallelThreadCount );
120 
121  auto fill_lambda = [&] ( PROGRESS_REPORTER* aReporter ) -> size_t
122  {
123  size_t num = 0;
124 
125  for( size_t i = nextItem++; i < toFill.size(); i = nextItem++ )
126  {
127  ZONE_CONTAINER* zone = toFill[i].m_zone;
128 
129  if( zone->GetFillMode() == ZFM_SEGMENTS )
130  {
131  ZONE_SEGMENT_FILL segFill;
132  fillZoneWithSegments( zone, zone->GetFilledPolysList(), segFill );
133  zone->SetFillSegments( segFill );
134  }
135  else
136  {
137  SHAPE_POLY_SET rawPolys, finalPolys;
138  fillSingleZone( zone, rawPolys, finalPolys );
139 
140  zone->SetRawPolysList( rawPolys );
141  zone->SetFilledPolysList( finalPolys );
142  }
143 
144  zone->SetIsFilled( true );
145 
146  if( m_progressReporter )
148 
149  num++;
150  }
151 
152  return num;
153  };
154 
155  if( parallelThreadCount <= 1 )
156  fill_lambda( m_progressReporter );
157  else
158  {
159  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
160  returns[ii] = std::async( std::launch::async, fill_lambda, m_progressReporter );
161 
162  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
163  {
164  // Here we balance returns with a 100ms timeout to allow UI updating
165  std::future_status status;
166  do
167  {
168  if( m_progressReporter )
170 
171  status = returns[ii].wait_for( std::chrono::milliseconds( 100 ) );
172  } while( status != std::future_status::ready );
173  }
174  }
175 
176  // Now update the connectivity to check for copper islands
177  if( m_progressReporter )
178  {
180  m_progressReporter->Report( _( "Removing insulated copper islands..." ) );
182  }
183 
184  connectivity->SetProgressReporter( m_progressReporter );
185  connectivity->FindIsolatedCopperIslands( toFill );
186 
187  // Now remove insulated copper islands
188  bool outOfDate = false;
189 
190  for( auto& zone : toFill )
191  {
192  std::sort( zone.m_islands.begin(), zone.m_islands.end(), std::greater<int>() );
193  SHAPE_POLY_SET poly = zone.m_zone->GetFilledPolysList();
194 
195  for( auto idx : zone.m_islands )
196  {
197  poly.DeletePolygon( idx );
198  }
199 
200  zone.m_zone->SetFilledPolysList( poly );
201 
202  if( aCheck && zone.m_lastPolys.GetHash() != poly.GetHash() )
203  outOfDate = true;
204  }
205 
206  if( aCheck )
207  {
208  bool refill = false;
209  wxCHECK( m_progressReporter, false );
210 
211  if( outOfDate )
212  {
213  m_progressReporter->Hide();
214 
215  KIDIALOG dlg( m_progressReporter->GetParent(),
216  _( "Zone fills are out-of-date. Refill?" ),
217  _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
218  dlg.SetOKCancelLabels( _( "Refill" ), _( "Continue without Refill" ) );
219  dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
220 
221  refill = ( dlg.ShowModal() == wxID_OK );
222 
223  m_progressReporter->Show();
224  }
225 
226  if( !refill )
227  {
228  if( m_commit )
229  m_commit->Revert();
230 
231  connectivity->SetProgressReporter( nullptr );
232  connectivity->Unlock();
233  return false;
234  }
235  }
236 
237  if( m_progressReporter )
238  {
240  m_progressReporter->Report( _( "Performing polygon fills..." ) );
241  m_progressReporter->SetMaxProgress( toFill.size() );
242  }
243 
244 
245  nextItem = 0;
246 
247  auto tri_lambda = [&] ( PROGRESS_REPORTER* aReporter ) -> size_t
248  {
249  size_t num = 0;
250 
251  for( size_t i = nextItem++; i < toFill.size(); i = nextItem++ )
252  {
253  toFill[i].m_zone->CacheTriangulation();
254  num++;
255 
256  if( m_progressReporter )
258  }
259 
260  return num;
261  };
262 
263  if( parallelThreadCount <= 1 )
264  tri_lambda( m_progressReporter );
265  else
266  {
267  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
268  returns[ii] = std::async( std::launch::async, tri_lambda, m_progressReporter );
269 
270  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
271  {
272  // Here we balance returns with a 100ms timeout to allow UI updating
273  std::future_status status;
274  do
275  {
276  if( m_progressReporter )
278 
279  status = returns[ii].wait_for( std::chrono::milliseconds( 100 ) );
280  } while( status != std::future_status::ready );
281  }
282  }
283 
284  if( m_progressReporter )
285  {
287  m_progressReporter->Report( _( "Committing changes..." ) );
289  }
290 
291  connectivity->SetProgressReporter( nullptr );
292 
293  if( m_commit )
294  {
295  m_commit->Push( _( "Fill Zone(s)" ), false );
296  }
297  else
298  {
299  for( unsigned i = 0; i < toFill.size(); i++ )
300  {
301  connectivity->Update( toFill[i].m_zone );
302  }
303 
304  connectivity->RecalculateRatsnest();
305  }
306 
307  connectivity->Unlock();
308  return true;
309 }
310 
311 
313  SHAPE_POLY_SET& aFeatures ) const
314 {
315  int segsPerCircle;
316  double correctionFactor;
317 
318  // Set the number of segments in arc approximations
320  segsPerCircle = ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF;
321  else
322  segsPerCircle = ARC_APPROX_SEGMENTS_COUNT_LOW_DEF;
323 
324  /* calculates the coeff to compensate radius reduction of holes clearance
325  * due to the segment approx.
326  * For a circle the min radius is radius * cos( 2PI / segsPerCircle / 2)
327  * correctionFactor is 1 /cos( PI/segsPerCircle )
328  */
329  correctionFactor = GetCircletoPolyCorrectionFactor( segsPerCircle );
330 
331  aFeatures.RemoveAllContours();
332 
333  int outline_half_thickness = aZone->GetMinThickness() / 2;
334 
335  // When removing holes, the holes must be expanded by outline_half_thickness
336  // to take in account the thickness of the zone outlines
337  int zone_clearance = aZone->GetClearance() + outline_half_thickness;
338 
339  // When holes are created by non copper items (edge cut items), use only
340  // the m_ZoneClearance parameter (zone clearance with no netclass clearance)
341  int zone_to_edgecut_clearance = aZone->GetZoneClearance() + outline_half_thickness;
342 
343  /* store holes (i.e. tracks and pads areas as polygons outlines)
344  * in a polygon list
345  */
346 
347  /* items ouside the zone bounding box are skipped
348  * the bounding box is the zone bounding box + the biggest clearance found in Netclass list
349  */
350  EDA_RECT item_boundingbox;
351  EDA_RECT zone_boundingbox = aZone->GetBoundingBox();
352  int biggest_clearance = m_board->GetDesignSettings().GetBiggestClearanceValue();
353  biggest_clearance = std::max( biggest_clearance, zone_clearance );
354  zone_boundingbox.Inflate( biggest_clearance );
355 
356  /*
357  * First : Add pads. Note: pads having the same net as zone are left in zone.
358  * Thermal shapes will be created later if necessary
359  */
360 
361  /* Use a dummy pad to calculate hole clearance when a pad is not on all copper layers
362  * and this pad has a hole
363  * This dummy pad has the size and shape of the hole
364  * Therefore, this dummy pad is a circle or an oval.
365  * A pad must have a parent because some functions expect a non null parent
366  * to find the parent board, and some other data
367  */
368  MODULE dummymodule( m_board ); // Creates a dummy parent
369  D_PAD dummypad( &dummymodule );
370 
371  for( MODULE* module = m_board->m_Modules; module; module = module->Next() )
372  {
373  D_PAD* nextpad;
374 
375  for( D_PAD* pad = module->PadsList(); pad != NULL; pad = nextpad )
376  {
377  nextpad = pad->Next(); // pad pointer can be modified by next code, so
378  // calculate the next pad here
379 
380  if( !pad->IsOnLayer( aZone->GetLayer() ) )
381  {
382  /* Test for pads that are on top or bottom only and have a hole.
383  * There are curious pads but they can be used for some components that are
384  * inside the board (in fact inside the hole. Some photo diodes and Leds are
385  * like this)
386  */
387  if( pad->GetDrillSize().x == 0 && pad->GetDrillSize().y == 0 )
388  continue;
389 
390  // Use a dummy pad to calculate a hole shape that have the same dimension as
391  // the pad hole
392  dummypad.SetSize( pad->GetDrillSize() );
393  dummypad.SetOrientation( pad->GetOrientation() );
394  dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
396  dummypad.SetPosition( pad->GetPosition() );
397 
398  pad = &dummypad;
399  }
400 
401  // Note: netcode <=0 means not connected item
402  if( ( pad->GetNetCode() != aZone->GetNetCode() ) || ( pad->GetNetCode() <= 0 ) )
403  {
404  int item_clearance = pad->GetClearance() + outline_half_thickness;
405  item_boundingbox = pad->GetBoundingBox();
406  item_boundingbox.Inflate( item_clearance );
407 
408  if( item_boundingbox.Intersects( zone_boundingbox ) )
409  {
410  int clearance = std::max( zone_clearance, item_clearance );
411 
412  // PAD_SHAPE_CUSTOM can have a specific keepout, to avoid to break the shape
413  if( pad->GetShape() == PAD_SHAPE_CUSTOM
414  && pad->GetCustomShapeInZoneOpt() == CUST_PAD_SHAPE_IN_ZONE_CONVEXHULL )
415  {
416  // the pad shape in zone can be its convex hull or
417  // the shape itself
418  SHAPE_POLY_SET outline( pad->GetCustomShapeAsPolygon() );
419  outline.Inflate( KiROUND( clearance * correctionFactor ), segsPerCircle );
420  pad->CustomShapeAsPolygonToBoardPosition( &outline,
421  pad->GetPosition(), pad->GetOrientation() );
422 
423  if( pad->GetCustomShapeInZoneOpt() == CUST_PAD_SHAPE_IN_ZONE_CONVEXHULL )
424  {
425  std::vector<wxPoint> convex_hull;
426  BuildConvexHull( convex_hull, outline );
427 
428  aFeatures.NewOutline();
429 
430  for( unsigned ii = 0; ii < convex_hull.size(); ++ii )
431  aFeatures.Append( convex_hull[ii] );
432  }
433  else
434  aFeatures.Append( outline );
435  }
436  else
437  pad->TransformShapeWithClearanceToPolygon( aFeatures,
438  clearance,
439  segsPerCircle,
440  correctionFactor );
441  }
442 
443  continue;
444  }
445 
446  // Pads are removed from zone if the setup is PAD_ZONE_CONN_NONE
447  // or if they have a custom shape and not PAD_ZONE_CONN_FULL,
448  // because a thermal relief will break
449  // the shape
450  if( aZone->GetPadConnection( pad ) == PAD_ZONE_CONN_NONE
451  || ( pad->GetShape() == PAD_SHAPE_CUSTOM && aZone->GetPadConnection( pad ) != PAD_ZONE_CONN_FULL ) )
452  {
453  int gap = zone_clearance;
454  int thermalGap = aZone->GetThermalReliefGap( pad );
455  gap = std::max( gap, thermalGap );
456  item_boundingbox = pad->GetBoundingBox();
457  item_boundingbox.Inflate( gap );
458 
459  if( item_boundingbox.Intersects( zone_boundingbox ) )
460  {
461  // PAD_SHAPE_CUSTOM has a specific keepout, to avoid to break the shape
462  // the pad shape in zone can be its convex hull or the shape itself
463  if( pad->GetShape() == PAD_SHAPE_CUSTOM
464  && pad->GetCustomShapeInZoneOpt() == CUST_PAD_SHAPE_IN_ZONE_CONVEXHULL )
465  {
466  // the pad shape in zone can be its convex hull or
467  // the shape itself
468  SHAPE_POLY_SET outline( pad->GetCustomShapeAsPolygon() );
469  outline.Inflate( KiROUND( gap * correctionFactor ), segsPerCircle );
470  pad->CustomShapeAsPolygonToBoardPosition( &outline,
471  pad->GetPosition(), pad->GetOrientation() );
472 
473  std::vector<wxPoint> convex_hull;
474  BuildConvexHull( convex_hull, outline );
475 
476  aFeatures.NewOutline();
477 
478  for( unsigned ii = 0; ii < convex_hull.size(); ++ii )
479  aFeatures.Append( convex_hull[ii] );
480  }
481  else
482  pad->TransformShapeWithClearanceToPolygon( aFeatures,
483  gap, segsPerCircle, correctionFactor );
484  }
485  }
486  }
487  }
488 
489  /* Add holes (i.e. tracks and vias areas as polygons outlines)
490  * in cornerBufferPolysToSubstract
491  */
492  for( auto track : m_board->Tracks() )
493  {
494  if( !track->IsOnLayer( aZone->GetLayer() ) )
495  continue;
496 
497  if( track->GetNetCode() == aZone->GetNetCode() && ( aZone->GetNetCode() != 0) )
498  continue;
499 
500  int item_clearance = track->GetClearance() + outline_half_thickness;
501  item_boundingbox = track->GetBoundingBox();
502 
503  if( item_boundingbox.Intersects( zone_boundingbox ) )
504  {
505  int clearance = std::max( zone_clearance, item_clearance );
506  track->TransformShapeWithClearanceToPolygon( aFeatures,
507  clearance, segsPerCircle, correctionFactor );
508  }
509  }
510 
511  /* Add graphic items that are on copper layers. These have no net, so we just
512  * use the zone clearance (or edge clearance).
513  */
514  auto doGraphicItem = [&]( BOARD_ITEM* aItem )
515  {
516  // A item on the Edge_Cuts is always seen as on any layer:
517  if( !aItem->IsOnLayer( aZone->GetLayer() ) && !aItem->IsOnLayer( Edge_Cuts ) )
518  return;
519 
520  if( !aItem->GetBoundingBox().Intersects( zone_boundingbox ) )
521  return;
522 
523  bool ignoreLineWidth = false;
524  int zclearance = zone_clearance;
525 
526  if( aItem->IsOnLayer( Edge_Cuts ) )
527  {
528  // use only the m_ZoneClearance, not the clearance using
529  // the netclass value, because we do not have a copper item
530  zclearance = zone_to_edgecut_clearance;
531 
532  // edge cuts by definition don't have a width
533  ignoreLineWidth = true;
534  }
535 
536  switch( aItem->Type() )
537  {
538  case PCB_LINE_T:
539  ( (DRAWSEGMENT*) aItem )->TransformShapeWithClearanceToPolygon(
540  aFeatures, zclearance, segsPerCircle, correctionFactor, ignoreLineWidth );
541  break;
542 
543  case PCB_TEXT_T:
544  ( (TEXTE_PCB*) aItem )->TransformBoundingBoxWithClearanceToPolygon(
545  &aFeatures, zclearance );
546  break;
547 
548  case PCB_MODULE_EDGE_T:
549  ( (EDGE_MODULE*) aItem )->TransformShapeWithClearanceToPolygon(
550  aFeatures, zclearance, segsPerCircle, correctionFactor, ignoreLineWidth );
551  break;
552 
553  case PCB_MODULE_TEXT_T:
554  ( (TEXTE_PCB*) aItem )->TransformBoundingBoxWithClearanceToPolygon(
555  &aFeatures, zclearance );
556  break;
557 
558  default:
559  break;
560  }
561  };
562 
563  for( auto module : m_board->Modules() )
564  {
565  doGraphicItem( &module->Reference() );
566  doGraphicItem( &module->Value() );
567 
568  for( auto item : module->GraphicalItems() )
569  doGraphicItem( item );
570  }
571 
572  for( auto item : m_board->Drawings() )
573  doGraphicItem( item );
574 
575  /* Add zones outlines having an higher priority and keepout
576  */
577  for( int ii = 0; ii < m_board->GetAreaCount(); ii++ )
578  {
579  ZONE_CONTAINER* zone = m_board->GetArea( ii );
580 
581  // If the zones share no common layers
582  if( !aZone->CommonLayerExists( zone->GetLayerSet() ) )
583  continue;
584 
585  if( !zone->GetIsKeepout() && zone->GetPriority() <= aZone->GetPriority() )
586  continue;
587 
588  if( zone->GetIsKeepout() && !zone->GetDoNotAllowCopperPour() )
589  continue;
590 
591  // A highter priority zone or keepout area is found: remove this area
592  item_boundingbox = zone->GetBoundingBox();
593 
594  if( !item_boundingbox.Intersects( zone_boundingbox ) )
595  continue;
596 
597  // Add the zone outline area.
598  // However if the zone has the same net as the current zone,
599  // do not add any clearance.
600  // the zone will be connected to the current zone, but filled areas
601  // will use different parameters (clearance, thermal shapes )
602  bool same_net = aZone->GetNetCode() == zone->GetNetCode();
603  bool use_net_clearance = true;
604  int min_clearance = zone_clearance;
605 
606  // Do not forget to make room to draw the thick outlines
607  // of the hole created by the area of the zone to remove
608  int holeclearance = zone->GetClearance() + outline_half_thickness;
609 
610  // The final clearance is obviously the max value of each zone clearance
611  min_clearance = std::max( min_clearance, holeclearance );
612 
613  if( zone->GetIsKeepout() || same_net )
614  {
615  // Just take in account the fact the outline has a thickness, so
616  // the actual area to substract is inflated to take in account this fact
617  min_clearance = outline_half_thickness;
618  use_net_clearance = false;
619  }
620 
622  aFeatures, min_clearance, use_net_clearance );
623  }
624 
625  /* Remove thermal symbols
626  */
627  for( auto module : m_board->Modules() )
628  {
629  for( auto pad : module->Pads() )
630  {
631  // Rejects non-standard pads with tht-only thermal reliefs
632  if( aZone->GetPadConnection( pad ) == PAD_ZONE_CONN_THT_THERMAL
633  && pad->GetAttribute() != PAD_ATTRIB_STANDARD )
634  continue;
635 
636  if( aZone->GetPadConnection( pad ) != PAD_ZONE_CONN_THERMAL
637  && aZone->GetPadConnection( pad ) != PAD_ZONE_CONN_THT_THERMAL )
638  continue;
639 
640  if( !pad->IsOnLayer( aZone->GetLayer() ) )
641  continue;
642 
643  if( pad->GetNetCode() != aZone->GetNetCode() )
644  continue;
645 
646  item_boundingbox = pad->GetBoundingBox();
647  int thermalGap = aZone->GetThermalReliefGap( pad );
648  item_boundingbox.Inflate( thermalGap, thermalGap );
649 
650  if( item_boundingbox.Intersects( zone_boundingbox ) )
651  {
653  *pad, thermalGap,
654  aZone->GetThermalReliefCopperBridge( pad ),
655  aZone->GetMinThickness(),
656  segsPerCircle,
657  correctionFactor, s_thermalRot );
658  }
659  }
660  }
661 }
662 
693  const SHAPE_POLY_SET& aSmoothedOutline,
694  SHAPE_POLY_SET& aRawPolys,
695  SHAPE_POLY_SET& aFinalPolys ) const
696 {
697  int segsPerCircle;
698  double correctionFactor;
699  int outline_half_thickness = aZone->GetMinThickness() / 2;
700 
701  std::unique_ptr<SHAPE_FILE_IO> dumper( new SHAPE_FILE_IO(
702  s_DumpZonesWhenFilling ? "zones_dump.txt" : "", SHAPE_FILE_IO::IOM_APPEND ) );
703 
704  // Set the number of segments in arc approximations
706  segsPerCircle = ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF;
707  else
708  segsPerCircle = ARC_APPROX_SEGMENTS_COUNT_LOW_DEF;
709 
710  /* calculates the coeff to compensate radius reduction of holes clearance
711  */
712  correctionFactor = GetCircletoPolyCorrectionFactor( segsPerCircle );
713 
715  dumper->BeginGroup( "clipper-zone" );
716 
717  SHAPE_POLY_SET solidAreas = aSmoothedOutline;
718 
719  solidAreas.Inflate( -outline_half_thickness, segsPerCircle );
720  solidAreas.Simplify( SHAPE_POLY_SET::PM_FAST );
721 
722  SHAPE_POLY_SET holes;
723 
725  dumper->Write( &solidAreas, "solid-areas" );
726 
727  buildZoneFeatureHoleList( aZone, holes );
728 
730  dumper->Write( &holes, "feature-holes" );
731 
733 
735  dumper->Write( &holes, "feature-holes-postsimplify" );
736 
737  // Generate the filled areas (currently, without thermal shapes, which will
738  // be created later).
739  // Use SHAPE_POLY_SET::PM_STRICTLY_SIMPLE to generate strictly simple polygons
740  // needed by Gerber files and Fracture()
742 
744  dumper->Write( &solidAreas, "solid-areas-minus-holes" );
745 
746  SHAPE_POLY_SET areas_fractured = solidAreas;
747  areas_fractured.Fracture( SHAPE_POLY_SET::PM_FAST );
748 
750  dumper->Write( &areas_fractured, "areas_fractured" );
751 
752  aFinalPolys = areas_fractured;
753 
754  SHAPE_POLY_SET thermalHoles;
755 
756  // Test thermal stubs connections and add polygons to remove unconnected stubs.
757  // (this is a refinement for thermal relief shapes)
758  if( aZone->GetNetCode() > 0 )
759  {
760  buildUnconnectedThermalStubsPolygonList( thermalHoles, aZone, aFinalPolys,
761  correctionFactor, s_thermalRot );
762 
763  }
764 
765  // remove copper areas corresponding to not connected stubs
766  if( !thermalHoles.IsEmpty() )
767  {
768  thermalHoles.Simplify( SHAPE_POLY_SET::PM_FAST );
769  // Remove unconnected stubs. Use SHAPE_POLY_SET::PM_STRICTLY_SIMPLE to
770  // generate strictly simple polygons
771  // needed by Gerber files and Fracture()
772  solidAreas.BooleanSubtract( thermalHoles, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
773 
775  dumper->Write( &thermalHoles, "thermal-holes" );
776 
777  // put these areas in m_FilledPolysList
778  SHAPE_POLY_SET th_fractured = solidAreas;
779  th_fractured.Fracture( SHAPE_POLY_SET::PM_FAST );
780 
782  dumper->Write( &th_fractured, "th_fractured" );
783 
784  aFinalPolys = th_fractured;
785  }
786 
787  aRawPolys = aFinalPolys;
788 
790  dumper->EndGroup();
791 }
792 
793 /* Build the filled solid areas data from real outlines (stored in m_Poly)
794  * The solid areas can be more than one on copper layers, and do not have holes
795  * ( holes are linked by overlapping segments to the main outline)
796  */
798  SHAPE_POLY_SET& aFinalPolys ) const
799 {
800  SHAPE_POLY_SET smoothedPoly;
801 
802  /* convert outlines + holes to outlines without holes (adding extra segments if necessary)
803  * m_Poly data is expected normalized, i.e. NormalizeAreaOutlines was used after building
804  * this zone
805  */
806  if ( !aZone->BuildSmoothedPoly( smoothedPoly ) )
807  return false;
808 
809  if( aZone->IsOnCopperLayer() )
810  {
811  computeRawFilledAreas( aZone, smoothedPoly, aRawPolys, aFinalPolys );
812  }
813  else
814  {
815  aRawPolys = smoothedPoly;
816  aFinalPolys = smoothedPoly;
817  aFinalPolys.Inflate( -aZone->GetMinThickness() / 2, 16 );
818  aFinalPolys.Fracture( SHAPE_POLY_SET::PM_FAST );
819  }
820 
821  return true;
822 }
823 
825  const SHAPE_POLY_SET& aFilledPolys,
826  ZONE_SEGMENT_FILL& aFillSegs ) const
827 {
828  bool success = true;
829  // segments are on something like a grid. Give it a minimal size
830  // to avoid too many segments, and use the m_ZoneMinThickness when (this is usually the case)
831  // the size is > mingrid_size.
832  // This is not perfect, but the actual purpose of this code
833  // is to allow filling zones on a grid, with grid size > m_ZoneMinThickness,
834  // in order to have really a grid.
835  //
836  // Using a user selectable grid size is for future Kicad versions.
837  // For now the area is fully filled.
838  int mingrid_size = Millimeter2iu( 0.05 );
839  int grid_size = std::max( mingrid_size, aZone->GetMinThickness() );
840  // Make segments slightly overlapping to ensure a good full filling
841  grid_size -= grid_size/20;
842 
843  // Creates the horizontal segments
844  for ( int index = 0; index < aFilledPolys.OutlineCount(); index++ )
845  {
846  const SHAPE_LINE_CHAIN& outline0 = aFilledPolys.COutline( index );
847  success = fillPolygonWithHorizontalSegments( outline0, aFillSegs, grid_size );
848 
849  if( !success )
850  break;
851 
852  // Creates the vertical segments. Because the filling algo creates horizontal segments,
853  // to reuse the fillPolygonWithHorizontalSegments function, we rotate the polygons to fill
854  // then fill them, then inverse rotate the result
855  SHAPE_LINE_CHAIN outline90;
856  outline90.Append( outline0 );
857 
858  // Rotate 90 degrees the outline:
859  for( int ii = 0; ii < outline90.PointCount(); ii++ )
860  {
861  VECTOR2I& point = outline90.Point( ii );
862  std::swap( point.x, point.y );
863  point.y = -point.y;
864  }
865 
866  int first_point = aFillSegs.size();
867  success = fillPolygonWithHorizontalSegments( outline90, aFillSegs, grid_size );
868 
869  if( !success )
870  break;
871 
872  // Rotate -90 degrees the segments:
873  for( unsigned ii = first_point; ii < aFillSegs.size(); ii++ )
874  {
875  SEG& segm = aFillSegs[ii];
876  std::swap( segm.A.x, segm.A.y );
877  std::swap( segm.B.x, segm.B.y );
878  segm.A.x = - segm.A.x;
879  segm.B.x = - segm.B.x;
880  }
881  }
882 
883  return success;
884 }
885 
895  ZONE_SEGMENT_FILL& aFillSegmList, int aStep ) const
896 {
897  std::vector <int> x_coordinates;
898  bool success = true;
899 
900  // Creates the horizontal segments
901  const SHAPE_LINE_CHAIN& outline = aPolygon;
902  const BOX2I& rect = outline.BBox();
903 
904  // Calculate the y limits of the zone
905  for( int refy = rect.GetY(), endy = rect.GetBottom(); refy < endy; refy += aStep )
906  {
907  // find all intersection points of an infinite line with polyline sides
908  x_coordinates.clear();
909 
910  for( int v = 0; v < outline.PointCount(); v++ )
911  {
912 
913  int seg_startX = outline.CPoint( v ).x;
914  int seg_startY = outline.CPoint( v ).y;
915  int seg_endX = outline.CPoint( v + 1 ).x;
916  int seg_endY = outline.CPoint( v + 1 ).y;
917 
918  /* Trivial cases: skip if ref above or below the segment to test */
919  if( ( seg_startY > refy ) && ( seg_endY > refy ) )
920  continue;
921 
922  // segment below ref point, or its Y end pos on Y coordinate ref point: skip
923  if( ( seg_startY <= refy ) && (seg_endY <= refy ) )
924  continue;
925 
926  /* at this point refy is between seg_startY and seg_endY
927  * see if an horizontal line at Y = refy is intersecting this segment
928  */
929  // calculate the x position of the intersection of this segment and the
930  // infinite line this is more easier if we move the X,Y axis origin to
931  // the segment start point:
932 
933  seg_endX -= seg_startX;
934  seg_endY -= seg_startY;
935  double newrefy = (double) ( refy - seg_startY );
936  double intersec_x;
937 
938  if ( seg_endY == 0 ) // horizontal segment on the same line: skip
939  continue;
940 
941  // Now calculate the x intersection coordinate of the horizontal line at
942  // y = newrefy and the segment from (0,0) to (seg_endX,seg_endY) with the
943  // horizontal line at the new refy position the line slope is:
944  // slope = seg_endY/seg_endX; and inv_slope = seg_endX/seg_endY
945  // and the x pos relative to the new origin is:
946  // intersec_x = refy/slope = refy * inv_slope
947  // Note: because horizontal segments are already tested and skipped, slope
948  // exists (seg_end_y not O)
949  double inv_slope = (double) seg_endX / seg_endY;
950  intersec_x = newrefy * inv_slope;
951  x_coordinates.push_back( (int) intersec_x + seg_startX );
952  }
953 
954  // A line scan is finished: build list of segments
955 
956  // Sort intersection points by increasing x value:
957  // So 2 consecutive points are the ends of a segment
958  std::sort( x_coordinates.begin(), x_coordinates.end() );
959 
960  // An even number of coordinates is expected, because a segment has 2 ends.
961  // An if this algorithm always works, it must always find an even count.
962  if( ( x_coordinates.size() & 1 ) != 0 )
963  {
964  success = false;
965  break;
966  }
967 
968  // Create segments having the same Y coordinate
969  int iimax = x_coordinates.size() - 1;
970 
971  for( int ii = 0; ii < iimax; ii += 2 )
972  {
973  VECTOR2I seg_start, seg_end;
974  seg_start.x = x_coordinates[ii];
975  seg_start.y = refy;
976  seg_end.x = x_coordinates[ii + 1];
977  seg_end.y = refy;
978  SEG segment( seg_start, seg_end );
979  aFillSegmList.push_back( segment );
980  }
981  } // End examine segments in one area
982 
983  return success;
984 }
985 
986 
998  const ZONE_CONTAINER* aZone,
999  const SHAPE_POLY_SET& aRawFilledArea,
1000  double aArcCorrection,
1001  double aRoundPadThermalRotation ) const
1002 {
1003  SHAPE_LINE_CHAIN spokes;
1004  BOX2I itemBB;
1005  VECTOR2I ptTest[4];
1006  auto zoneBB = aRawFilledArea.BBox();
1007 
1008 
1009  int zone_clearance = aZone->GetZoneClearance();
1010 
1011  int biggest_clearance = m_board->GetDesignSettings().GetBiggestClearanceValue();
1012  biggest_clearance = std::max( biggest_clearance, zone_clearance );
1013  zoneBB.Inflate( biggest_clearance );
1014 
1015  // half size of the pen used to draw/plot zones outlines
1016  int pen_radius = aZone->GetMinThickness() / 2;
1017 
1018  for( auto module : m_board->Modules() )
1019  {
1020  for( auto pad : module->Pads() )
1021  {
1022  // Rejects non-standard pads with tht-only thermal reliefs
1023  if( aZone->GetPadConnection( pad ) == PAD_ZONE_CONN_THT_THERMAL
1024  && pad->GetAttribute() != PAD_ATTRIB_STANDARD )
1025  continue;
1026 
1027  if( aZone->GetPadConnection( pad ) != PAD_ZONE_CONN_THERMAL
1028  && aZone->GetPadConnection( pad ) != PAD_ZONE_CONN_THT_THERMAL )
1029  continue;
1030 
1031  if( !pad->IsOnLayer( aZone->GetLayer() ) )
1032  continue;
1033 
1034  if( pad->GetNetCode() != aZone->GetNetCode() )
1035  continue;
1036 
1037  // Calculate thermal bridge half width
1038  int thermalBridgeWidth = aZone->GetThermalReliefCopperBridge( pad )
1039  - aZone->GetMinThickness();
1040  if( thermalBridgeWidth <= 0 )
1041  continue;
1042 
1043  // we need the thermal bridge half width
1044  // with a small extra size to be sure we create a stub
1045  // slightly larger than the actual stub
1046  thermalBridgeWidth = ( thermalBridgeWidth + 4 ) / 2;
1047 
1048  int thermalReliefGap = aZone->GetThermalReliefGap( pad );
1049 
1050  itemBB = pad->GetBoundingBox();
1051  itemBB.Inflate( thermalReliefGap );
1052  if( !( itemBB.Intersects( zoneBB ) ) )
1053  continue;
1054 
1055  // Thermal bridges are like a segment from a starting point inside the pad
1056  // to an ending point outside the pad
1057 
1058  // calculate the ending point of the thermal pad, outside the pad
1059  VECTOR2I endpoint;
1060  endpoint.x = ( pad->GetSize().x / 2 ) + thermalReliefGap;
1061  endpoint.y = ( pad->GetSize().y / 2 ) + thermalReliefGap;
1062 
1063  // Calculate the starting point of the thermal stub
1064  // inside the pad
1065  VECTOR2I startpoint;
1066  int copperThickness = aZone->GetThermalReliefCopperBridge( pad )
1067  - aZone->GetMinThickness();
1068 
1069  if( copperThickness < 0 )
1070  copperThickness = 0;
1071 
1072  // Leave a small extra size to the copper area inside to pad
1073  copperThickness += KiROUND( IU_PER_MM * 0.04 );
1074 
1075  startpoint.x = std::min( pad->GetSize().x, copperThickness );
1076  startpoint.y = std::min( pad->GetSize().y, copperThickness );
1077 
1078  startpoint.x /= 2;
1079  startpoint.y /= 2;
1080 
1081  // This is a CIRCLE pad tweak
1082  // for circle pads, the thermal stubs orientation is 45 deg
1083  double fAngle = pad->GetOrientation();
1084  if( pad->GetShape() == PAD_SHAPE_CIRCLE )
1085  {
1086  endpoint.x = KiROUND( endpoint.x * aArcCorrection );
1087  endpoint.y = endpoint.x;
1088  fAngle = aRoundPadThermalRotation;
1089  }
1090 
1091  // contour line width has to be taken into calculation to avoid "thermal stub bleed"
1092  endpoint.x += pen_radius;
1093  endpoint.y += pen_radius;
1094  // compute north, south, west and east points for zone connection.
1095  ptTest[0] = VECTOR2I( 0, endpoint.y ); // lower point
1096  ptTest[1] = VECTOR2I( 0, -endpoint.y ); // upper point
1097  ptTest[2] = VECTOR2I( endpoint.x, 0 ); // right point
1098  ptTest[3] = VECTOR2I( -endpoint.x, 0 ); // left point
1099 
1100  // Test all sides
1101  for( int i = 0; i < 4; i++ )
1102  {
1103  // rotate point
1104  RotatePoint( ptTest[i], fAngle );
1105 
1106  // translate point
1107  ptTest[i] += pad->ShapePos();
1108 
1109  if( aRawFilledArea.Contains( ptTest[i] ) )
1110  continue;
1111 
1112  spokes.Clear();
1113 
1114  // polygons are rectangles with width of copper bridge value
1115  switch( i )
1116  {
1117  case 0: // lower stub
1118  spokes.Append( -thermalBridgeWidth, endpoint.y );
1119  spokes.Append( +thermalBridgeWidth, endpoint.y );
1120  spokes.Append( +thermalBridgeWidth, startpoint.y );
1121  spokes.Append( -thermalBridgeWidth, startpoint.y );
1122  break;
1123 
1124  case 1: // upper stub
1125  spokes.Append( -thermalBridgeWidth, -endpoint.y );
1126  spokes.Append( +thermalBridgeWidth, -endpoint.y );
1127  spokes.Append( +thermalBridgeWidth, -startpoint.y );
1128  spokes.Append( -thermalBridgeWidth, -startpoint.y );
1129  break;
1130 
1131  case 2: // right stub
1132  spokes.Append( endpoint.x, -thermalBridgeWidth );
1133  spokes.Append( endpoint.x, thermalBridgeWidth );
1134  spokes.Append( +startpoint.x, thermalBridgeWidth );
1135  spokes.Append( +startpoint.x, -thermalBridgeWidth );
1136  break;
1137 
1138  case 3: // left stub
1139  spokes.Append( -endpoint.x, -thermalBridgeWidth );
1140  spokes.Append( -endpoint.x, thermalBridgeWidth );
1141  spokes.Append( -startpoint.x, thermalBridgeWidth );
1142  spokes.Append( -startpoint.x, -thermalBridgeWidth );
1143  break;
1144  }
1145 
1146  aCornerBuffer.NewOutline();
1147 
1148  // add computed polygon to list
1149  for( int ic = 0; ic < spokes.PointCount(); ic++ )
1150  {
1151  auto cpos = spokes.CPoint( ic );
1152  RotatePoint( cpos, fAngle ); // Rotate according to module orientation
1153  cpos += pad->ShapePos(); // Shift origin to position
1154  aCornerBuffer.Append( cpos );
1155  }
1156  }
1157  }
1158  }
1159 }
void SetFilledPolysList(SHAPE_POLY_SET &aPolysList)
Function SetFilledPolysList sets the list of filled polygons.
Definition: class_zone.h:566
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:60
#define ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF
Definition: pcbnew.h:42
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:50
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
#define SEGMENT_COUNT_CROSSOVER
Definition: pcbnew.h:46
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:120
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:204
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:624
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:193
#define ARC_APPROX_SEGMENTS_COUNT_LOW_DEF
Definition: pcbnew.h:41
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:123
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:604
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:196
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:778
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:623
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:995
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:254
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:250
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:181
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:538
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:1020
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:555
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:575
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:991
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:170
DLIST< MODULE > m_Modules
Definition: class_board.h:248
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:46
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:563
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:418
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:253
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:107
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()
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:296
int GetZoneClearance() const
Definition: class_zone.h:198
DLIST_ITERATOR_WRAPPER< BOARD_ITEM > Drawings()
Definition: class_board.h:255
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:47
double GetCircletoPolyCorrectionFactor(int aSegCountforCircle)