KiCad PCB EDA Suite
class_zone.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) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6  * Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors.
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 <bitmaps.h>
28 #include <geometry/shape_null.h>
29 #include <advanced_config.h>
30 #include <pcb_edit_frame.h>
31 #include <pcb_screen.h>
32 #include <class_board.h>
33 #include <class_zone.h>
34 #include <kicad_string.h>
35 #include <math_for_graphics.h>
38 #include <trigo.h>
39 #include <i18n_utility.h>
40 
43  m_area( 0.0 )
44 {
45  m_CornerSelection = nullptr; // no corner is selected
46  m_isFilled = false; // fill status : true when the zone is filled
50  m_hv45 = false;
51  m_hatchThickness = 0;
52  m_hatchGap = 0;
53  m_hatchOrientation = 0.0;
54  m_hatchSmoothingLevel = 0; // Grid pattern smoothing type. 0 = no smoothing
55  m_hatchSmoothingValue = 0.1; // Grid pattern chamfer value relative to the gap value
56  // used only if m_hatchSmoothingLevel > 0
57  m_hatchHoleMinArea = 0.3; // Min size before holes are dropped (ratio of hole size)
58  m_hatchBorderAlgorithm = 1; // 0 = use zone min thickness; 1 = use hatch width
59  m_priority = 0;
61  SetIsRuleArea( aInFP ); // Zones living in footprints have the rule area option
62  SetDoNotAllowCopperPour( false ); // has meaning only if m_isRuleArea == true
63  SetDoNotAllowVias( true ); // has meaning only if m_isRuleArea == true
64  SetDoNotAllowTracks( true ); // has meaning only if m_isRuleArea == true
65  SetDoNotAllowPads( true ); // has meaning only if m_isRuleArea == true
66  SetDoNotAllowFootprints( false ); // has meaning only if m_isRuleArea == true
67  m_cornerRadius = 0;
68  SetLocalFlags( 0 ); // flags tempoarry used in zone calculations
69  m_Poly = new SHAPE_POLY_SET(); // Outlines
70  m_fillVersion = 5; // set the "old" way to build filled polygon areas (< 6.0.x)
72  aParent->GetZoneSettings().ExportSetting( *this );
73 
74  m_needRefill = false; // True only after some edition.
75 }
76 
77 
79  : BOARD_CONNECTED_ITEM( aZone ),
80  m_Poly( nullptr ),
81  m_CornerSelection( nullptr )
82 {
84 }
85 
86 
88 {
90 
91  InitDataFromSrcInCopyCtor( aOther );
92 
93  return *this;
94 }
95 
96 
98 {
99  delete m_Poly;
100  delete m_CornerSelection;
101 }
102 
103 
105 {
106  // members are expected non initialize in this.
107  // InitDataFromSrcInCopyCtor() is expected to be called
108  // only from a copy constructor.
109 
110  // Copy only useful EDA_ITEM flags:
111  m_Flags = aZone.m_Flags;
113 
114  // Replace the outlines for aZone outlines.
115  delete m_Poly;
116  m_Poly = new SHAPE_POLY_SET( *aZone.m_Poly );
117 
120  m_zoneName = aZone.m_zoneName;
121  SetLayerSet( aZone.GetLayerSet() );
122  m_priority = aZone.m_priority;
123  m_isRuleArea = aZone.m_isRuleArea;
124 
130 
132  m_ZoneClearance = aZone.m_ZoneClearance; // clearance value
137 
138  m_isFilled = aZone.m_isFilled;
139  m_needRefill = aZone.m_needRefill;
140 
143 
144  m_fillMode = aZone.m_fillMode; // solid vs. hatched
146  m_hatchGap = aZone.m_hatchGap;
152 
153  // For corner moving, corner index to drag, or nullptr if no selection
154  delete m_CornerSelection;
155  m_CornerSelection = nullptr;
156 
157  for( PCB_LAYER_ID layer : aZone.GetLayerSet().Seq() )
158  {
159  m_FilledPolysList[layer] = aZone.m_FilledPolysList.at( layer );
160  m_RawPolysList[layer] = aZone.m_RawPolysList.at( layer );
161  m_filledPolysHash[layer] = aZone.m_filledPolysHash.at( layer );
162  m_FillSegmList[layer] = aZone.m_FillSegmList.at( layer ); // vector <> copy
163  m_insulatedIslands[layer] = aZone.m_insulatedIslands.at( layer );
164  }
165 
169 
170  SetLocalFlags( aZone.GetLocalFlags() );
171 
172  m_netinfo = aZone.m_netinfo;
173 
174  m_hv45 = aZone.m_hv45;
175  m_area = aZone.m_area;
176 }
177 
178 
180 {
181  return new ZONE_CONTAINER( *this );
182 }
183 
184 
186 {
187  bool change = false;
188 
189  for( std::pair<const PCB_LAYER_ID, SHAPE_POLY_SET>& pair : m_FilledPolysList )
190  {
191  change |= !pair.second.IsEmpty();
192  pair.second.RemoveAllContours();
193  }
194 
195  for( std::pair<const PCB_LAYER_ID, ZONE_SEGMENT_FILL>& pair : m_FillSegmList )
196  {
197  change |= !pair.second.empty();
198  pair.second.clear();
199  }
200 
201  m_isFilled = false;
202  m_fillFlags.clear();
203 
204  return change;
205 }
206 
207 
209 {
210  return (wxPoint) GetCornerPosition( 0 );
211 }
212 
213 
215 {
216  return BOARD_ITEM::GetLayer();
217 }
218 
219 
221 {
222  return ( m_layerSet & LSET::AllCuMask() ).count() > 0;
223 }
224 
225 
226 bool ZONE_CONTAINER::CommonLayerExists( const LSET aLayerSet ) const
227 {
228  LSET common = GetLayerSet() & aLayerSet;
229 
230  return common.count() > 0;
231 }
232 
233 
235 {
236  SetLayerSet( LSET( aLayer ) );
237 
238  m_Layer = aLayer;
239 }
240 
241 
243 {
244  if( GetIsRuleArea() )
245  {
246  // Rule areas can only exist on copper layers
247  aLayerSet &= LSET::AllCuMask();
248  }
249 
250  if( aLayerSet.count() == 0 )
251  return;
252 
253  if( m_layerSet != aLayerSet )
254  {
255  SetNeedRefill( true );
256 
257  UnFill();
258 
259  m_FillSegmList.clear();
260  m_FilledPolysList.clear();
261  m_RawPolysList.clear();
262  m_filledPolysHash.clear();
263  m_insulatedIslands.clear();
264 
265  for( PCB_LAYER_ID layer : aLayerSet.Seq() )
266  {
267  m_FillSegmList[layer] = {};
268  m_FilledPolysList[layer] = {};
269  m_RawPolysList[layer] = {};
270  m_filledPolysHash[layer] = {};
271  m_insulatedIslands[layer] = {};
272  }
273  }
274 
275  m_layerSet = aLayerSet;
276 
277  // Set the single layer parameter. For zones that can be on many layers, this parameter
278  // is arbitrary at best, but some code still uses it.
279  // Priority is F_Cu then B_Cu then to the first selected layer
280  m_Layer = aLayerSet.Seq()[0];
281 
282  if( m_Layer != F_Cu && aLayerSet[B_Cu] )
283  m_Layer = B_Cu;
284 }
285 
286 
288 {
289  return m_layerSet;
290 }
291 
292 
293 void ZONE_CONTAINER::ViewGetLayers( int aLayers[], int& aCount ) const
294 {
295  LSEQ layers = m_layerSet.Seq();
296 
297  for( unsigned int idx = 0; idx < layers.size(); idx++ )
298  aLayers[idx] = LAYER_ZONE_START + layers[idx];
299 
300  aCount = layers.size();
301 }
302 
303 
304 double ZONE_CONTAINER::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
305 {
306  constexpr double HIDE = std::numeric_limits<double>::max();
307 
308  return aView->IsLayerVisible( LAYER_ZONES ) ? 0.0 : HIDE;
309 }
310 
311 
313 {
314  return m_layerSet.test( aLayer );
315 }
316 
317 
319 {
320  auto bb = m_Poly->BBox();
321 
322  EDA_RECT ret( (wxPoint) bb.GetOrigin(), wxSize( bb.GetWidth(), bb.GetHeight() ) );
323 
324  return ret;
325 }
326 
327 
328 int ZONE_CONTAINER::GetThermalReliefGap( D_PAD* aPad, wxString* aSource ) const
329 {
330  if( aPad->GetEffectiveThermalGap() == 0 )
331  {
332  if( aSource )
333  *aSource = _( "zone" );
334 
335  return m_thermalReliefGap;
336  }
337 
338  return aPad->GetEffectiveThermalGap( aSource );
339 
340 }
341 
342 
343 int ZONE_CONTAINER::GetThermalReliefSpokeWidth( D_PAD* aPad, wxString* aSource ) const
344 {
345  if( aPad->GetEffectiveThermalSpokeWidth() == 0 )
346  {
347  if( aSource )
348  *aSource = _( "zone" );
349 
351  }
352 
353  return aPad->GetEffectiveThermalSpokeWidth( aSource );
354 }
355 
356 
357 void ZONE_CONTAINER::SetCornerRadius( unsigned int aRadius )
358 {
359  if( m_cornerRadius != aRadius )
360  SetNeedRefill( true );
361 
362  m_cornerRadius = aRadius;
363 }
364 
365 
367 {
368  if( ADVANCED_CFG::GetCfg().m_DebugZoneFiller && LSET::InternalCuMask().Contains( aLayer ) )
369  return false;
370 
372 }
373 
374 
375 bool ZONE_CONTAINER::HitTest( const wxPoint& aPosition, int aAccuracy ) const
376 {
377  // Normally accuracy is zoom-relative, but for the generic HitTest we just use
378  // a fixed (small) value.
379  int accuracy = std::max( aAccuracy, Millimeter2iu( 0.1 ) );
380 
381  return HitTestForCorner( aPosition, accuracy * 2 ) || HitTestForEdge( aPosition, accuracy );
382 }
383 
384 
385 void ZONE_CONTAINER::SetSelectedCorner( const wxPoint& aPosition, int aAccuracy )
386 {
388 
389  // If there is some corner to be selected, assign it to m_CornerSelection
390  if( HitTestForCorner( aPosition, aAccuracy * 2, corner )
391  || HitTestForEdge( aPosition, aAccuracy, corner ) )
392  {
393  if( m_CornerSelection == nullptr )
395 
396  *m_CornerSelection = corner;
397  }
398 }
399 
400 bool ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos, int aAccuracy,
401  SHAPE_POLY_SET::VERTEX_INDEX& aCornerHit ) const
402 {
403  return m_Poly->CollideVertex( VECTOR2I( refPos ), aCornerHit, aAccuracy );
404 }
405 
406 
407 bool ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos, int aAccuracy ) const
408 {
410  return HitTestForCorner( refPos, aAccuracy, dummy );
411 }
412 
413 
414 bool ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos, int aAccuracy,
415  SHAPE_POLY_SET::VERTEX_INDEX& aCornerHit ) const
416 {
417  return m_Poly->CollideEdge( VECTOR2I( refPos ), aCornerHit, aAccuracy );
418 }
419 
420 
421 bool ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos, int aAccuracy ) const
422 {
424  return HitTestForEdge( refPos, aAccuracy, dummy );
425 }
426 
427 
428 bool ZONE_CONTAINER::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
429 {
430  // Calculate bounding box for zone
431  EDA_RECT bbox = GetBoundingBox();
432  bbox.Normalize();
433 
434  EDA_RECT arect = aRect;
435  arect.Normalize();
436  arect.Inflate( aAccuracy );
437 
438  if( aContained )
439  {
440  return arect.Contains( bbox );
441  }
442  else
443  {
444  // Fast test: if aBox is outside the polygon bounding box, rectangles cannot intersect
445  if( !arect.Intersects( bbox ) )
446  return false;
447 
448  int count = m_Poly->TotalVertices();
449 
450  for( int ii = 0; ii < count; ii++ )
451  {
452  auto vertex = m_Poly->CVertex( ii );
453  auto vertexNext = m_Poly->CVertex( ( ii + 1 ) % count );
454 
455  // Test if the point is within the rect
456  if( arect.Contains( ( wxPoint ) vertex ) )
457  return true;
458 
459  // Test if this edge intersects the rect
460  if( arect.Intersects( ( wxPoint ) vertex, ( wxPoint ) vertexNext ) )
461  return true;
462  }
463 
464  return false;
465  }
466 }
467 
468 
469 int ZONE_CONTAINER::GetLocalClearance( wxString* aSource ) const
470 {
471  if( m_isRuleArea )
472  return 0;
473 
474  if( aSource )
475  *aSource = _( "zone" );
476 
477  return m_ZoneClearance;
478 }
479 
480 
481 bool ZONE_CONTAINER::HitTestFilledArea( PCB_LAYER_ID aLayer, const wxPoint &aRefPos,
482  int aAccuracy ) const
483 {
484  // Rule areas have no filled area, but it's generally nice to treat their interior as if it were
485  // filled so that people don't have to select them by their outline (which is min-width)
486  if( GetIsRuleArea() )
487  return m_Poly->Contains( VECTOR2I( aRefPos.x, aRefPos.y ), -1, aAccuracy );
488 
489  if( !m_FilledPolysList.count( aLayer ) )
490  return false;
491 
492  return m_FilledPolysList.at( aLayer ).Contains( VECTOR2I( aRefPos.x, aRefPos.y ), -1,
493  aAccuracy );
494 }
495 
496 
497 bool ZONE_CONTAINER::HitTestCutout( const VECTOR2I& aRefPos, int* aOutlineIdx, int* aHoleIdx ) const
498 {
499  // Iterate over each outline polygon in the zone and then iterate over
500  // each hole it has to see if the point is in it.
501  for( int i = 0; i < m_Poly->OutlineCount(); i++ )
502  {
503  for( int j = 0; j < m_Poly->HoleCount( i ); j++ )
504  {
505  if( m_Poly->Hole( i, j ).PointInside( aRefPos ) )
506  {
507  if( aOutlineIdx )
508  *aOutlineIdx = i;
509 
510  if( aHoleIdx )
511  *aHoleIdx = j;
512 
513  return true;
514  }
515  }
516  }
517 
518  return false;
519 }
520 
521 
522 void ZONE_CONTAINER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
523 {
524  EDA_UNITS units = aFrame->GetUserUnits();
525  wxString msg, msg2;
526 
527  if( GetIsRuleArea() )
528  msg = _( "Rule Area" );
529  else if( IsOnCopperLayer() )
530  msg = _( "Copper Zone" );
531  else
532  msg = _( "Non-copper Zone" );
533 
534  // Display Cutout instead of Outline for holes inside a zone (i.e. when num contour !=0).
535  // Check whether the selected corner is in a hole; i.e., in any contour but the first one.
536  if( m_CornerSelection != nullptr && m_CornerSelection->m_contour > 0 )
537  msg << wxT( " " ) << _( "Cutout" );
538 
539  aList.emplace_back( _( "Type" ), msg, DARKCYAN );
540 
541  if( GetIsRuleArea() )
542  {
543  msg.Empty();
544 
545  if( GetDoNotAllowVias() )
546  AccumulateDescription( msg, _( "No vias" ) );
547 
548  if( GetDoNotAllowTracks() )
549  AccumulateDescription( msg, _( "No tracks" ) );
550 
551  if( GetDoNotAllowPads() )
552  AccumulateDescription( msg, _( "No pads" ) );
553 
555  AccumulateDescription( msg, _( "No copper zones" ) );
556 
558  AccumulateDescription( msg, _( "No footprints" ) );
559 
560  if( !msg.IsEmpty() )
561  aList.emplace_back( MSG_PANEL_ITEM( _( "Restrictions" ), msg, RED ) );
562  }
563  else if( IsOnCopperLayer() )
564  {
565  if( GetNetCode() >= 0 )
566  {
567  NETINFO_ITEM* net = GetNet();
568  NETCLASS* netclass = nullptr;
569 
570  if( net )
571  {
572  if( net->GetNet() )
573  netclass = GetNetClass();
574  else
575  netclass = GetBoard()->GetDesignSettings().GetDefault();
576 
577  msg = UnescapeString( net->GetNetname() );
578  }
579  else
580  {
581  msg = wxT( "<no name>" );
582  }
583 
584  aList.emplace_back( _( "Net" ), msg, RED );
585 
586  if( netclass )
587  aList.emplace_back( _( "NetClass" ), netclass->GetName(), DARKMAGENTA );
588  }
589 
590  // Display priority level
591  msg.Printf( wxT( "%d" ), GetPriority() );
592  aList.emplace_back( _( "Priority" ), msg, BLUE );
593  }
594 
595  wxString layerDesc;
596  int count = 0;
597 
598  for( PCB_LAYER_ID layer : m_layerSet.Seq() )
599  {
600  if( count == 0 )
601  layerDesc = GetBoard()->GetLayerName( layer );
602 
603  count++;
604  }
605 
606  if( count > 1 )
607  layerDesc.Printf( _( "%s and %d more" ), layerDesc, count - 1 );
608 
609  aList.emplace_back( _( "Layer" ), layerDesc, DARKGREEN );
610 
611  if( !m_zoneName.empty() )
612  aList.emplace_back( _( "Name" ), m_zoneName, DARKMAGENTA );
613 
614  switch( m_fillMode )
615  {
616  case ZONE_FILL_MODE::POLYGONS: msg = _( "Solid" ); break;
617  case ZONE_FILL_MODE::HATCH_PATTERN: msg = _( "Hatched" ); break;
618  default: msg = _( "Unknown" ); break;
619  }
620 
621  aList.emplace_back( _( "Fill Mode" ), msg, BROWN );
622 
623  msg = MessageTextFromValue( units, m_area, true, EDA_DATA_TYPE::AREA );
624  aList.emplace_back( _( "Filled Area" ), msg, BLUE );
625 
626  wxString source;
627  int clearance = GetOwnClearance( GetLayer(), &source );
628 
629  msg.Printf( _( "Min Clearance: %s" ), MessageTextFromValue( units, clearance ) );
630  msg2.Printf( _( "(from %s)" ), source );
631  aList.emplace_back( msg, msg2, BLACK );
632 
633  // Useful for statistics, especially when zones are complex the number of hatches
634  // and filled polygons can explain the display and DRC calculation time:
635  msg.Printf( wxT( "%d" ), (int) m_borderHatchLines.size() );
636  aList.emplace_back( MSG_PANEL_ITEM( _( "HatchBorder Lines" ), msg, BLUE ) );
637 
638  PCB_LAYER_ID layer = m_Layer;
639 
640  // NOTE: This brings in dependence on PCB_EDIT_FRAME to the qa tests, which isn't ideal.
641  // TODO: Figure out a way for items to know the active layer without the whole edit frame?
642 #if 0
643  if( PCB_EDIT_FRAME* pcbframe = dynamic_cast<PCB_EDIT_FRAME*>( aFrame ) )
644  if( m_FilledPolysList.count( pcbframe->GetActiveLayer() ) )
645  layer = pcbframe->GetActiveLayer();
646 #endif
647 
648  if( !GetIsRuleArea() )
649  {
650  auto layer_it = m_FilledPolysList.find( layer );
651 
652  if( layer_it == m_FilledPolysList.end() )
653  layer_it = m_FilledPolysList.begin();
654 
655  if( layer_it != m_FilledPolysList.end() )
656  {
657  msg.Printf( wxT( "%d" ), layer_it->second.TotalVertices() );
658  aList.emplace_back( MSG_PANEL_ITEM( _( "Corner Count" ), msg, BLUE ) );
659  }
660  }
661 }
662 
663 
664 /* Geometric transforms: */
665 
666 void ZONE_CONTAINER::Move( const wxPoint& offset )
667 {
668  /* move outlines */
669  m_Poly->Move( offset );
670 
671  HatchBorder();
672 
673  for( std::pair<const PCB_LAYER_ID, SHAPE_POLY_SET>& pair : m_FilledPolysList )
674  pair.second.Move( offset );
675 
676  for( std::pair<const PCB_LAYER_ID, ZONE_SEGMENT_FILL>& pair : m_FillSegmList )
677  {
678  for( SEG& seg : pair.second )
679  {
680  seg.A += VECTOR2I( offset );
681  seg.B += VECTOR2I( offset );
682  }
683  }
684 }
685 
686 
687 void ZONE_CONTAINER::MoveEdge( const wxPoint& offset, int aEdge )
688 {
689  int next_corner;
690 
691  if( m_Poly->GetNeighbourIndexes( aEdge, nullptr, &next_corner ) )
692  {
693  m_Poly->SetVertex( aEdge, m_Poly->CVertex( aEdge ) + VECTOR2I( offset ) );
694  m_Poly->SetVertex( next_corner, m_Poly->CVertex( next_corner ) + VECTOR2I( offset ) );
695  HatchBorder();
696 
697  SetNeedRefill( true );
698  }
699 }
700 
701 
702 void ZONE_CONTAINER::Rotate( const wxPoint& aCentre, double aAngle )
703 {
704  aAngle = -DECIDEG2RAD( aAngle );
705 
706  m_Poly->Rotate( aAngle, VECTOR2I( aCentre ) );
707  HatchBorder();
708 
709  /* rotate filled areas: */
710  for( std::pair<const PCB_LAYER_ID, SHAPE_POLY_SET>& pair : m_FilledPolysList )
711  pair.second.Rotate( aAngle, VECTOR2I( aCentre ) );
712 
713  for( std::pair<const PCB_LAYER_ID, ZONE_SEGMENT_FILL>& pair : m_FillSegmList )
714  {
715  for( SEG& seg : pair.second )
716  {
717  wxPoint a( seg.A );
718  RotatePoint( &a, aCentre, aAngle );
719  seg.A = a;
720  wxPoint b( seg.B );
721  RotatePoint( &b, aCentre, aAngle );
722  seg.B = a;
723  }
724  }
725 }
726 
727 
728 void ZONE_CONTAINER::Flip( const wxPoint& aCentre, bool aFlipLeftRight )
729 {
730  Mirror( aCentre, aFlipLeftRight );
731  int copperLayerCount = GetBoard()->GetCopperLayerCount();
732 
733  if( GetIsRuleArea() )
734  SetLayerSet( FlipLayerMask( GetLayerSet(), copperLayerCount ) );
735  else
736  SetLayer( FlipLayer( GetLayer(), copperLayerCount ) );
737 }
738 
739 
740 void ZONE_CONTAINER::Mirror( const wxPoint& aMirrorRef, bool aMirrorLeftRight )
741 {
742  // ZONE_CONTAINERs mirror about the x-axis (why?!?)
743  m_Poly->Mirror( aMirrorLeftRight, !aMirrorLeftRight, VECTOR2I( aMirrorRef ) );
744 
745  HatchBorder();
746 
747  for( std::pair<const PCB_LAYER_ID, SHAPE_POLY_SET>& pair : m_FilledPolysList )
748  pair.second.Mirror( aMirrorLeftRight, !aMirrorLeftRight, VECTOR2I( aMirrorRef ) );
749 
750  for( std::pair<const PCB_LAYER_ID, ZONE_SEGMENT_FILL>& pair : m_FillSegmList )
751  {
752  for( SEG& seg : pair.second )
753  {
754  if( aMirrorLeftRight )
755  {
756  MIRROR( seg.A.x, aMirrorRef.x );
757  MIRROR( seg.B.x, aMirrorRef.x );
758  }
759  else
760  {
761  MIRROR( seg.A.y, aMirrorRef.y );
762  MIRROR( seg.B.y, aMirrorRef.y );
763  }
764  }
765  }
766 }
767 
768 
769 ZONE_CONNECTION ZONE_CONTAINER::GetPadConnection( D_PAD* aPad, wxString* aSource ) const
770 {
772  {
773  if( aSource )
774  *aSource = _( "zone" );
775 
776  return m_PadConnection;
777  }
778  else
779  {
780  return aPad->GetEffectiveZoneConnection( aSource );
781  }
782 }
783 
784 
785 void ZONE_CONTAINER::RemoveCutout( int aOutlineIdx, int aHoleIdx )
786 {
787  // Ensure the requested cutout is valid
788  if( m_Poly->OutlineCount() < aOutlineIdx || m_Poly->HoleCount( aOutlineIdx ) < aHoleIdx )
789  return;
790 
791  SHAPE_POLY_SET cutPoly( m_Poly->Hole( aOutlineIdx, aHoleIdx ) );
792 
793  // Add the cutout back to the zone
795 
796  SetNeedRefill( true );
797 }
798 
799 
801 {
802  wxASSERT( aPolygon.IsClosed() );
803 
804  // Add the outline as a new polygon in the polygon set
805  if( m_Poly->OutlineCount() == 0 )
806  m_Poly->AddOutline( aPolygon );
807  else
808  m_Poly->AddHole( aPolygon );
809 
810  SetNeedRefill( true );
811 }
812 
813 
814 void ZONE_CONTAINER::AddPolygon( std::vector< wxPoint >& aPolygon )
815 {
816  if( aPolygon.empty() )
817  return;
818 
819  SHAPE_LINE_CHAIN outline;
820 
821  // Create an outline and populate it with the points of aPolygon
822  for( const wxPoint& pt : aPolygon)
823  outline.Append( pt );
824 
825  outline.SetClosed( true );
826 
827  AddPolygon( outline );
828 }
829 
830 
831 bool ZONE_CONTAINER::AppendCorner( wxPoint aPosition, int aHoleIdx, bool aAllowDuplication )
832 {
833  // Ensure the main outline exists:
834  if( m_Poly->OutlineCount() == 0 )
835  m_Poly->NewOutline();
836 
837  // If aHoleIdx >= 0, the corner musty be added to the hole, index aHoleIdx.
838  // (remember: the index of the first hole is 0)
839  // Return error if if does dot exist.
840  if( aHoleIdx >= m_Poly->HoleCount( 0 ) )
841  return false;
842 
843  m_Poly->Append( aPosition.x, aPosition.y, -1, aHoleIdx, aAllowDuplication );
844 
845  SetNeedRefill( true );
846 
847  return true;
848 }
849 
850 
852 {
853  wxString text;
854 
855  // Check whether the selected contour is a hole (contour index > 0)
856  if( m_CornerSelection != nullptr && m_CornerSelection->m_contour > 0 )
857  text << wxT( " " ) << _( "(Cutout)" );
858 
859  if( GetIsRuleArea() )
860  text << wxT( " " ) << _( "(Rule Area)" );
861  else
862  text << GetNetnameMsg();
863 
864  wxString layerDesc;
865  int count = 0;
866 
867  for( PCB_LAYER_ID layer : m_layerSet.Seq() )
868  {
869  if( count == 0 )
870  layerDesc = GetBoard()->GetLayerName( layer );
871 
872  count++;
873  }
874 
875  if( count > 1 )
876  layerDesc.Printf( _( "%s and %d more" ), layerDesc, count - 1 );
877 
878  return wxString::Format( _( "Zone Outline %s on %s" ), text, layerDesc );
879 }
880 
881 
883 {
884  return m_borderHatchPitch;
885 }
886 
887 
889  bool aRebuildHatch )
890 {
891  SetHatchPitch( aHatchPitch );
892  m_borderStyle = aHatchStyle;
893 
894  if( aRebuildHatch )
895  HatchBorder();
896 }
897 
898 
900 {
901  m_borderHatchPitch = aPitch;
902 }
903 
904 
906 {
907  m_borderHatchLines.clear();
908 }
909 
910 
911 // Creates hatch lines inside the outline of the complex polygon
912 // sort function used in ::HatchBorder to sort points by descending wxPoint.x values
913 bool sortEndsByDescendingX( const VECTOR2I& ref, const VECTOR2I& tst )
914 {
915  return tst.x < ref.x;
916 }
917 
918 
920 {
921  UnHatchBorder();
922 
924  || m_borderHatchPitch == 0
925  || m_Poly->IsEmpty() )
926  {
927  return;
928  }
929 
930  // define range for hatch lines
931  int min_x = m_Poly->CVertex( 0 ).x;
932  int max_x = m_Poly->CVertex( 0 ).x;
933  int min_y = m_Poly->CVertex( 0 ).y;
934  int max_y = m_Poly->CVertex( 0 ).y;
935 
936  for( auto iterator = m_Poly->IterateWithHoles(); iterator; iterator++ )
937  {
938  if( iterator->x < min_x )
939  min_x = iterator->x;
940 
941  if( iterator->x > max_x )
942  max_x = iterator->x;
943 
944  if( iterator->y < min_y )
945  min_y = iterator->y;
946 
947  if( iterator->y > max_y )
948  max_y = iterator->y;
949  }
950 
951  // Calculate spacing between 2 hatch lines
952  int spacing;
953 
955  spacing = m_borderHatchPitch;
956  else
957  spacing = m_borderHatchPitch * 2;
958 
959  // set the "length" of hatch lines (the length on horizontal axis)
960  int hatch_line_len = m_borderHatchPitch;
961 
962  // To have a better look, give a slope depending on the layer
963  LAYER_NUM layer = GetLayer();
964  int slope_flag = (layer & 1) ? 1 : -1; // 1 or -1
965  double slope = 0.707106 * slope_flag; // 45 degrees slope
966  int max_a, min_a;
967 
968  if( slope_flag == 1 )
969  {
970  max_a = KiROUND( max_y - slope * min_x );
971  min_a = KiROUND( min_y - slope * max_x );
972  }
973  else
974  {
975  max_a = KiROUND( max_y - slope * max_x );
976  min_a = KiROUND( min_y - slope * min_x );
977  }
978 
979  min_a = (min_a / spacing) * spacing;
980 
981  // calculate an offset depending on layer number,
982  // for a better look of hatches on a multilayer board
983  int offset = (layer * 7) / 8;
984  min_a += offset;
985 
986  // loop through hatch lines
987  #define MAXPTS 200 // Usually we store only few values per one hatch line
988  // depending on the complexity of the zone outline
989 
990  static std::vector<VECTOR2I> pointbuffer;
991  pointbuffer.clear();
992  pointbuffer.reserve( MAXPTS + 2 );
993 
994  for( int a = min_a; a < max_a; a += spacing )
995  {
996  // get intersection points for this hatch line
997 
998  // Note: because we should have an even number of intersections with the
999  // current hatch line and the zone outline (a closed polygon,
1000  // or a set of closed polygons), if an odd count is found
1001  // we skip this line (should not occur)
1002  pointbuffer.clear();
1003 
1004  // Iterate through all vertices
1005  for( auto iterator = m_Poly->IterateSegmentsWithHoles(); iterator; iterator++ )
1006  {
1007  double x, y, x2, y2;
1008  int ok;
1009 
1010  SEG segment = *iterator;
1011 
1012  ok = FindLineSegmentIntersection( a, slope,
1013  segment.A.x, segment.A.y,
1014  segment.B.x, segment.B.y,
1015  &x, &y, &x2, &y2 );
1016 
1017  if( ok )
1018  {
1019  VECTOR2I point( KiROUND( x ), KiROUND( y ) );
1020  pointbuffer.push_back( point );
1021  }
1022 
1023  if( ok == 2 )
1024  {
1025  VECTOR2I point( KiROUND( x2 ), KiROUND( y2 ) );
1026  pointbuffer.push_back( point );
1027  }
1028 
1029  if( pointbuffer.size() >= MAXPTS ) // overflow
1030  {
1031  wxASSERT( 0 );
1032  break;
1033  }
1034  }
1035 
1036  // ensure we have found an even intersection points count
1037  // because intersections are the ends of segments
1038  // inside the polygon(s) and a segment has 2 ends.
1039  // if not, this is a strange case (a bug ?) so skip this hatch
1040  if( pointbuffer.size() % 2 != 0 )
1041  continue;
1042 
1043  // sort points in order of descending x (if more than 2) to
1044  // ensure the starting point and the ending point of the same segment
1045  // are stored one just after the other.
1046  if( pointbuffer.size() > 2 )
1047  sort( pointbuffer.begin(), pointbuffer.end(), sortEndsByDescendingX );
1048 
1049  // creates lines or short segments inside the complex polygon
1050  for( unsigned ip = 0; ip < pointbuffer.size(); ip += 2 )
1051  {
1052  int dx = pointbuffer[ip + 1].x - pointbuffer[ip].x;
1053 
1054  // Push only one line for diagonal hatch,
1055  // or for small lines < twice the line length
1056  // else push 2 small lines
1058  || std::abs( dx ) < 2 * hatch_line_len )
1059  {
1060  m_borderHatchLines.emplace_back( SEG( pointbuffer[ip], pointbuffer[ ip + 1] ) );
1061  }
1062  else
1063  {
1064  double dy = pointbuffer[ip + 1].y - pointbuffer[ip].y;
1065  slope = dy / dx;
1066 
1067  if( dx > 0 )
1068  dx = hatch_line_len;
1069  else
1070  dx = -hatch_line_len;
1071 
1072  int x1 = KiROUND( pointbuffer[ip].x + dx );
1073  int x2 = KiROUND( pointbuffer[ip + 1].x - dx );
1074  int y1 = KiROUND( pointbuffer[ip].y + dx * slope );
1075  int y2 = KiROUND( pointbuffer[ip + 1].y - dx * slope );
1076 
1077  m_borderHatchLines.emplace_back( SEG( pointbuffer[ip].x, pointbuffer[ip].y, x1, y1 ) );
1078 
1079  m_borderHatchLines.emplace_back( SEG( pointbuffer[ip+1].x, pointbuffer[ip+1].y, x2, y2 ) );
1080  }
1081  }
1082  }
1083 }
1084 
1085 
1087 {
1088  return Mils2iu( 20 );
1089 }
1090 
1091 
1093 {
1094  return add_zone_xpm;
1095 }
1096 
1097 
1099 {
1100  assert( aImage->Type() == PCB_ZONE_AREA_T );
1101 
1102  std::swap( *((ZONE_CONTAINER*) this), *((ZONE_CONTAINER*) aImage) );
1103 }
1104 
1105 
1107 {
1108  if( aLayer == UNDEFINED_LAYER )
1109  {
1110  for( std::pair<const PCB_LAYER_ID, SHAPE_POLY_SET>& pair : m_FilledPolysList )
1111  pair.second.CacheTriangulation();
1112  }
1113  else
1114  {
1115  if( m_FilledPolysList.count( aLayer ) )
1117  }
1118 }
1119 
1120 
1121 bool ZONE_CONTAINER::IsIsland( PCB_LAYER_ID aLayer, int aPolyIdx )
1122 {
1123  if( GetNetCode() < 1 )
1124  return true;
1125 
1126  if( !m_insulatedIslands.count( aLayer ) )
1127  return false;
1128 
1129  return m_insulatedIslands.at( aLayer ).count( aPolyIdx );
1130 }
1131 
1132 
1134  std::vector<ZONE_CONTAINER*>* aZones ) const
1135 {
1136  int epsilon = Millimeter2iu( 0.001 );
1137 
1138  for( ZONE_CONTAINER* candidate : GetBoard()->Zones() )
1139  {
1140  if( candidate == this )
1141  continue;
1142 
1143  if( !candidate->GetLayerSet().test( aLayer ) )
1144  continue;
1145 
1146  if( candidate->GetIsRuleArea() )
1147  continue;
1148 
1149  if( candidate->GetNetCode() != GetNetCode() )
1150  continue;
1151 
1152  for( auto iter = m_Poly->CIterate(); iter; iter++ )
1153  {
1154  if( candidate->m_Poly->Collide( iter.Get(), epsilon ) )
1155  {
1156  aZones->push_back( candidate );
1157  break;
1158  }
1159  }
1160  }
1161 }
1162 
1163 
1165  SHAPE_POLY_SET* aBoardOutline,
1166  SHAPE_POLY_SET* aSmoothedPolyWithApron ) const
1167 {
1168  if( GetNumCorners() <= 2 ) // malformed zone. polygon calculations will not like it ...
1169  return false;
1170 
1171  if( GetIsRuleArea() )
1172  {
1173  // We like keepouts just the way they are....
1174  aSmoothedPoly = *m_Poly;
1175  return true;
1176  }
1177 
1178  BOARD* board = GetBoard();
1179  int maxError = ARC_HIGH_DEF;
1180  bool keepExternalFillets = false;
1181 
1182  if( board )
1183  {
1184  maxError = board->GetDesignSettings().m_MaxError;
1185  keepExternalFillets = board->GetDesignSettings().m_ZoneKeepExternalFillets;
1186  }
1187 
1188  auto smooth = [&]( SHAPE_POLY_SET& aPoly )
1189  {
1190  switch( m_cornerSmoothingType )
1191  {
1193  aPoly = aPoly.Chamfer( (int) m_cornerRadius );
1194  break;
1195 
1197  {
1198  aPoly = aPoly.Fillet( (int) m_cornerRadius, maxError );
1199  break;
1200  }
1201 
1202  default:
1203  break;
1204  }
1205  };
1206 
1207  std::vector<ZONE_CONTAINER*> interactingZones;
1208  GetInteractingZones( aLayer, &interactingZones );
1209 
1210  SHAPE_POLY_SET* maxExtents = m_Poly;
1211  SHAPE_POLY_SET withFillets;
1212 
1213  aSmoothedPoly = *m_Poly;
1214 
1215  // Should external fillets (that is, those applied to concave corners) be kept? While it
1216  // seems safer to never have copper extend outside the zone outline, 5.1.x and prior did
1217  // indeed fill them so we leave the mode available.
1218  if( keepExternalFillets )
1219  {
1220  withFillets = *m_Poly;
1221  smooth( withFillets );
1222  withFillets.BooleanAdd( *m_Poly, SHAPE_POLY_SET::PM_FAST );
1223  maxExtents = &withFillets;
1224  }
1225 
1226  for( ZONE_CONTAINER* zone : interactingZones )
1227  aSmoothedPoly.BooleanAdd( *zone->Outline(), SHAPE_POLY_SET::PM_FAST );
1228 
1229  if( !GetIsRuleArea() && aBoardOutline )
1230  aSmoothedPoly.BooleanIntersection( *aBoardOutline, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
1231 
1232  smooth( aSmoothedPoly );
1233 
1234  if( aSmoothedPolyWithApron )
1235  {
1236  SHAPE_POLY_SET bufferedExtents = *maxExtents;
1237  bufferedExtents.Inflate( m_ZoneMinThickness, 8 );
1238  *aSmoothedPolyWithApron = aSmoothedPoly;
1239  aSmoothedPolyWithApron->BooleanIntersection( bufferedExtents, SHAPE_POLY_SET::PM_FAST );
1240  }
1241 
1242  aSmoothedPoly.BooleanIntersection( *maxExtents, SHAPE_POLY_SET::PM_FAST );
1243 
1244  return true;
1245 }
1246 
1247 
1249 {
1250  m_area = 0.0;
1251 
1252  // Iterate over each outline polygon in the zone and then iterate over
1253  // each hole it has to compute the total area.
1254  for( std::pair<const PCB_LAYER_ID, SHAPE_POLY_SET>& pair : m_FilledPolysList )
1255  {
1256  SHAPE_POLY_SET& poly = pair.second;
1257 
1258  for( int i = 0; i < poly.OutlineCount(); i++ )
1259  {
1260  m_area += poly.Outline( i ).Area();
1261 
1262  for( int j = 0; j < poly.HoleCount( i ); j++ )
1263  m_area -= poly.Hole( i, j ).Area();
1264  }
1265  }
1266 
1267  return m_area;
1268 }
1269 
1270 
1277  int aClearance,
1278  SHAPE_POLY_SET* aBoardOutline ) const
1279 {
1280  // Creates the zone outline polygon (with holes if any)
1281  SHAPE_POLY_SET polybuffer;
1282  BuildSmoothedPoly( polybuffer, GetLayer(), aBoardOutline );
1283 
1284  // Calculate the polygon with clearance
1285  // holes are linked to the main outline, so only one polygon is created.
1286  if( aClearance )
1287  {
1288  BOARD* board = GetBoard();
1289  int maxError = ARC_HIGH_DEF;
1290 
1291  if( board )
1292  maxError = board->GetDesignSettings().m_MaxError;
1293 
1294  int segCount = GetArcToSegmentCount( aClearance, maxError, 360.0 );
1295  polybuffer.Inflate( aClearance, segCount );
1296  }
1297 
1298  polybuffer.Fracture( SHAPE_POLY_SET::PM_FAST );
1299  aCornerBuffer.Append( polybuffer );
1300 }
1301 
1302 
1303 //
1304 /********* MODULE_ZONE_CONTAINER **************/
1305 //
1307  ZONE_CONTAINER( aParent, true )
1308 {
1309  // in a footprint, net classes are not managed.
1310  // so set the net to NETINFO_LIST::ORPHANED_ITEM
1311  SetNetCode( -1, true );
1312 }
1313 
1314 
1316  : ZONE_CONTAINER( aZone.GetParent(), true )
1317 {
1318  InitDataFromSrcInCopyCtor( aZone );
1319 }
1320 
1321 
1323 {
1324  ZONE_CONTAINER::operator=( aOther );
1325  return *this;
1326 }
1327 
1328 
1330 {
1331  return new MODULE_ZONE_CONTAINER( *this );
1332 }
1333 
1334 
1335 double MODULE_ZONE_CONTAINER::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
1336 {
1337  constexpr double HIDE = (double)std::numeric_limits<double>::max();
1338 
1339  if( !aView )
1340  return 0;
1341 
1342  if( !aView->IsLayerVisible( LAYER_ZONES ) )
1343  return HIDE;
1344 
1345  bool flipped = GetParent() && GetParent()->GetLayer() == B_Cu;
1346 
1347  // Handle Render tab switches
1348  if( !flipped && !aView->IsLayerVisible( LAYER_MOD_FR ) )
1349  return HIDE;
1350 
1351  if( flipped && !aView->IsLayerVisible( LAYER_MOD_BK ) )
1352  return HIDE;
1353 
1354  // Other layers are shown without any conditions
1355  return 0.0;
1356 }
1357 
1358 
1359 std::shared_ptr<SHAPE> ZONE_CONTAINER::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
1360 {
1361  std::shared_ptr<SHAPE> shape;
1362 
1363  if( m_FilledPolysList.find( aLayer ) == m_FilledPolysList.end() )
1364  {
1365  shape = std::make_shared<SHAPE_NULL>();
1366  }
1367  else
1368  {
1369  shape.reset( m_FilledPolysList.at( aLayer ).Clone() );
1370  }
1371 
1372  return shape;
1373 }
1374 
1375 
1376 static struct ZONE_CONTAINER_DESC
1377 {
1379  {
1381  .Map( ZONE_CONNECTION::INHERITED, _HKI( "Inherited" ) )
1382  .Map( ZONE_CONNECTION::NONE, _HKI( "None" ) )
1383  .Map( ZONE_CONNECTION::THERMAL, _HKI( "Thermal reliefs" ) )
1384  .Map( ZONE_CONNECTION::FULL, _HKI( "Solid" ) )
1385  .Map( ZONE_CONNECTION::THT_THERMAL, _HKI( "Reliefs for PTH" ) );
1386 
1390  propMgr.AddProperty( new PROPERTY<ZONE_CONTAINER, unsigned>( _HKI( "Priority" ),
1392  //propMgr.AddProperty( new PROPERTY<ZONE_CONTAINER, bool>( "Filled",
1393  //&ZONE_CONTAINER::SetIsFilled, &ZONE_CONTAINER::IsFilled ) );
1394  propMgr.AddProperty( new PROPERTY<ZONE_CONTAINER, wxString>( _HKI( "Name" ),
1396  propMgr.AddProperty( new PROPERTY<ZONE_CONTAINER, int>( _HKI( "Clearance" ),
1399  propMgr.AddProperty( new PROPERTY<ZONE_CONTAINER, int>( _HKI( "Min Width" ),
1402  propMgr.AddProperty( new PROPERTY_ENUM<ZONE_CONTAINER, ZONE_CONNECTION>( _HKI( "Pad Connections" ),
1404  propMgr.AddProperty( new PROPERTY<ZONE_CONTAINER, int>( _HKI( "Thermal Clearance" ),
1407  propMgr.AddProperty( new PROPERTY<ZONE_CONTAINER, int>( _HKI( "Thermal Spoke Width" ),
1410  }
1412 
bool m_isFilled
True when a zone was filled, false after deleting the filled areas.
Definition: class_zone.h:877
void SetDoNotAllowTracks(bool aEnable)
Definition: class_zone.h:739
int TotalVertices() const
Returns total number of vertices stored in the set.
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:749
void MoveEdge(const wxPoint &offset, int aEdge)
Function MoveEdge Move the outline Edge.
Definition: class_zone.cpp:687
Virtual layers for stacking zones and tracks on a given copper layer.
ZONE_CONNECTION
How pads are covered by copper in zone.
Definition: zones.h:41
void SetHatchPitch(int aPitch)
Function SetHatchPitch sets the hatch pitch parameter for the zone.
Definition: class_zone.cpp:899
void GetInteractingZones(PCB_LAYER_ID aLayer, std::vector< ZONE_CONTAINER * > *aZones) const
Some intersecting zones, despite being on the same layer with the same net, cannot be merged due to o...
bool GetDoNotAllowPads() const
Definition: class_zone.h:733
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:61
wxString MessageTextFromValue(EDA_UNITS aUnits, int aValue, bool aAddUnitLabel, EDA_DATA_TYPE aType)
Definition: base_units.cpp:123
int m_hatchBorderAlgorithm
Definition: class_zone.h:903
void HatchBorder()
Function HatchBorder computes the hatch lines depending on the hatch parameters and stores it in the ...
Definition: class_zone.cpp:919
virtual void SwapData(BOARD_ITEM *aImage) override
Swap data between aItem and aImage.
std::vector< SEG > m_borderHatchLines
Definition: class_zone.h:936
void Mirror(const wxPoint &aMirrorRef, bool aMirrorLeftRight)
Function Mirror Mirror the outlines , relative to a given horizontal axis the layer is not changed.
Definition: class_zone.cpp:740
static PROPERTY_MANAGER & Instance()
Definition: property_mgr.h:64
#define TYPE_HASH(x)
Macro to generate unique identifier for a type
Definition: property.h:55
LSET FlipLayerMask(LSET aMask, int aCopperLayersCount)
Calculate the mask layer when flipping a footprint.
Definition: lset.cpp:566
int GetNetCode() const
Function GetNetCode.
double m_hatchSmoothingValue
Definition: class_zone.h:901
class ZONE_CONTAINER, managed by a footprint
Definition: typeinfo.h:95
bool BuildSmoothedPoly(SHAPE_POLY_SET &aSmoothedPoly, PCB_LAYER_ID aLayer, SHAPE_POLY_SET *aBoardOutline, SHAPE_POLY_SET *aSmoothedPolyWithApron=nullptr) const
Function GetSmoothedPoly.
ISLAND_REMOVAL_MODE m_islandRemovalMode
Definition: class_zone.h:868
int OutlineCount() const
Returns the number of outlines in the set
void InitDataFromSrcInCopyCtor(const ZONE_CONTAINER &aZone)
Copy aZone data to me.
Definition: class_zone.cpp:104
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
PNG memory record (file in memory).
Definition: bitmap_def.h:29
bool m_doNotAllowPads
Definition: class_zone.h:860
void SetPadConnection(ZONE_CONNECTION aPadConnection)
Definition: class_zone.h:222
double ViewGetLOD(int aLayer, KIGFX::VIEW *aView) const override
Function ViewGetLOD() Returns the level of detail (LOD) of the item.
Definition: class_zone.cpp:304
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:226
double ViewGetLOD(int aLayer, KIGFX::VIEW *aView) const override
Function ViewGetLOD() Returns the level of detail (LOD) of the item.
SEGMENT_ITERATOR IterateSegmentsWithHoles()
Returns an iterator object, for all outlines in the set (with holes)
void BooleanAdd(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset union For aFastMode meaning, see function booleanOp
EDA_ITEM * Clone() const override
Function Clone creates a duplicate of this item with linked list members set to NULL.
Definition: class_zone.cpp:179
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
bool m_doNotAllowTracks
Definition: class_zone.h:859
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox (virtual)
Definition: class_zone.cpp:318
NETINFO_ITEM * GetNet() const
Function GetNet Returns NET_INFO object for a given item.
const wxString & GetName() const
Definition: netclass.h:96
void SetCornerRadius(unsigned int aRadius)
Definition: class_zone.cpp:357
SHAPE_POLY_SET::VERTEX_INDEX * m_CornerSelection
The index of the corner being moved or nullptr if no corner is selected.
Definition: class_zone.h:907
int m_thermalReliefGap
Definition: class_zone.h:885
Control for copper zone opacity/visibility (color ignored)
const VECTOR2I & CVertex(int aIndex, int aOutline, int aHole) const
Returns the index-th vertex in a given hole outline within a given outline
virtual bool IsOnLayer(PCB_LAYER_ID) const override
Function IsOnLayer tests to see if this object is on the given layer.
Definition: class_zone.cpp:312
NETCLASS * GetNetClass() const
Function GetNetClassPtr returns the NETCLASS for this item.
void SetDoNotAllowFootprints(bool aEnable)
Definition: class_zone.h:741
bool HitTestForCorner(const wxPoint &refPos, int aAccuracy, SHAPE_POLY_SET::VERTEX_INDEX &aCornerHit) const
Function HitTestForCorner tests if the given wxPoint is near a corner.
Definition: class_zone.cpp:400
std::map< PCB_LAYER_ID, bool > m_fillFlags
Definition: class_zone.h:929
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Definition: lset.cpp:520
bool IsEmpty() const
Returns true if the set is empty (no polygons at all)
class ZONE_CONTAINER, a zone area
Definition: typeinfo.h:106
virtual PCB_LAYER_ID GetLayer() const override
Function GetLayer returns the primary layer this item is on.
Definition: class_zone.cpp:214
show footprints on back
static ENUM_MAP< T > & Instance()
Definition: property.h:519
Definition: color4d.h:62
void SetZoneName(const wxString &aName)
Definition: class_zone.h:114
bool GetFilledPolysUseThickness() const
Definition: class_zone.h:686
bool SetNetCode(int aNetCode, bool aNoAssert)
Sets net using a net code.
long long int m_minIslandArea
When island removal mode is set to AREA, islands below this area will be removed.
Definition: class_zone.h:874
Struct VERTEX_INDEX.
SHAPE_LINE_CHAIN & Hole(int aOutline, int aHole)
Returns the reference to aHole-th hole in the aIndex-th outline
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: class_board.h:558
MODULE_ZONE_CONTAINER(BOARD_ITEM_CONTAINER *aParent)
int m_thermalReliefSpokeWidth
Definition: class_zone.h:886
void SetThermalReliefSpokeWidth(int aThermalReliefSpokeWidth)
Definition: class_zone.h:175
void Rotate(double aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Function Rotate rotates all vertices by a given angle.
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, int aAccuracy=0, bool aUseBBoxCaches=false) const
Returns true if a given subpolygon contains the point aP.
Definition: color4d.h:45
void RemoveCutout(int aOutlineIdx, int aHoleIdx)
Remove a cutout from the zone.
Definition: class_zone.cpp:785
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
void Inflate(int aAmount, int aCircleSegmentsCount, CORNER_STRATEGY aCornerStrategy=ROUND_ALL_CORNERS)
Performs outline inflation/deflation.
std::map< PCB_LAYER_ID, std::set< int > > m_insulatedIslands
For each layer, a set of insulated islands that were not removed.
Definition: class_zone.h:939
void CacheTriangulation(PCB_LAYER_ID aLayer=UNDEFINED_LAYER)
(re)create a list of triangles that "fill" the solid areas.
void SetIsRuleArea(bool aEnable)
Definition: class_zone.h:736
The base class for create windows for drawing purpose.
VECTOR2< int > VECTOR2I
Definition: vector2d.h:594
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:410
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER) const override
Function GetEffectiveShape Some pad shapes can be complex (rounded/chamfered rectangle),...
BOARD_CONNECTED_ITEM is a base class derived from BOARD_ITEM for items that can be connected and have...
#define REGISTER_TYPE(x)
Helper macro to map type hashes to names
Definition: property_mgr.h:247
bool Contains(const wxPoint &aPoint) const
Function Contains.
Definition: eda_rect.cpp:57
static int GetDefaultHatchPitch()
Function GetDefaultHatchPitchMils.
struct SHAPE_POLY_SET::VERTEX_INDEX VERTEX_INDEX
Struct VERTEX_INDEX.
bool m_doNotAllowFootprints
Definition: class_zone.h:861
void Mirror(bool aX=true, bool aY=false, const VECTOR2I &aRef={ 0, 0 })
Mirrors the line points about y or x (or both)
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
void SetDoNotAllowVias(bool aEnable)
Definition: class_zone.h:738
ZONE_BORDER_DISPLAY_STYLE m_borderStyle
Definition: class_zone.h:934
bool GetDoNotAllowVias() const
Definition: class_zone.h:731
ENUM_TO_WXANY(ZONE_CONNECTION)
ZONE_CONNECTION m_PadConnection
Definition: class_zone.h:863
void SetPriority(unsigned aPriority)
Function SetPriority.
Definition: class_zone.h:100
show footprints on front
bool GetNeighbourIndexes(int aGlobalIndex, int *aPrevious, int *aNext)
Returns the global indexes of the previous and the next corner of the aGlobalIndex-th corner of a con...
virtual LSET GetLayerSet() const override
Function GetLayerSet returns a std::bitset of all layers on which the item physically resides.
Definition: class_zone.cpp:287
void SetVertex(const VERTEX_INDEX &aIndex, const VECTOR2I &aPos)
Function SetVertex Accessor function to set the position of a specific point.
PCB_LAYER_ID m_Layer
wxString GetZoneName() const
Definition: class_zone.h:113
void AccumulateDescription(wxString &aDesc, const wxString &aItem)
Utility to build comma separated lists in messages.
Definition: kicad_string.h:295
void MIRROR(T &aPoint, const T &aMirrorRef)
Definition: macros.h:136
#define MAXPTS
void SetClosed(bool aClosed)
Function SetClosed()
bool sortEndsByDescendingX(const VECTOR2I &ref, const VECTOR2I &tst)
Definition: class_zone.cpp:913
wxString m_zoneName
An optional unique name for this zone, used for identifying it in DRC checking.
Definition: class_zone.h:839
PCB_LAYER_ID
A quick note on layer IDs:
Display value expressed in distance units (mm/inch)
Definition: property.h:49
LSET is a set of PCB_LAYER_IDs.
pads are covered by copper
double m_hatchOrientation
Definition: class_zone.h:896
#define NULL
void SetLayerSet(LSET aLayerSet) override
Definition: class_zone.cpp:242
void Move(const VECTOR2I &aVector) override
bool IsClosed() const override
Function IsClosed()
ZONE_CONTAINER & operator=(const ZONE_CONTAINER &aOther)
Definition: class_zone.cpp:87
ITERATOR IterateWithHoles(int aOutline)
Function IterateWithHoles.
SHAPE_POLY_SET.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Returns the reference to aIndex-th outline in the set
int GetLocalClearance() const
Definition: class_zone.h:137
NETCLASS handles a collection of nets and the parameters used to route or test these nets.
Definition: netclass.h:49
SHAPE_POLY_SET * m_Poly
Outline of the zone.
Definition: class_zone.h:834
bool HitTest(const wxPoint &aPosition, int aAccuracy=0) const override
Function HitTest tests if a point is near an outline edge or a corner of this zone.
Definition: class_zone.cpp:375
virtual BOARD * GetBoard() const
Function GetBoard returns the BOARD in which this BOARD_ITEM resides, or NULL if none.
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const
Function PointInside()
bool GetDoNotAllowCopperPour() const
Definition: class_zone.h:730
unsigned m_priority
Definition: class_zone.h:847
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declares an inheritance relationship between types.
int GetBorderHatchPitch() const
HatchBorder related methods.
Definition: class_zone.cpp:882
bool m_doNotAllowVias
Definition: class_zone.h:858
void Rotate(const wxPoint &aCentre, double aAngle) override
Function Rotate Move the outlines.
Definition: class_zone.cpp:702
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Function SetLayer sets the layer this item is on.
Definition: class_zone.cpp:234
static LSET InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
Definition: lset.cpp:709
bool UnFill()
Function UnFill Removes the zone filling.
Definition: class_zone.cpp:185
const wxString & GetNetname() const
Function GetNetname.
Definition: netinfo.h:231
int m_cornerSmoothingType
Definition: class_zone.h:835
std::map< PCB_LAYER_ID, SHAPE_POLY_SET > m_RawPolysList
Definition: class_zone.h:925
int GetNumCorners(void) const
Access to m_Poly parameters.
Definition: class_zone.h:506
a few functions useful in geometry calculations.
virtual void ViewGetLayers(int aLayers[], int &aCount) const override
Function ViewGetLayers() Returns the all the layers within the VIEW the object is painted on.
Definition: class_zone.cpp:293
std::map< PCB_LAYER_ID, MD5_HASH > m_filledPolysHash
A hash value used in zone filling calculations to see if the filled areas are up to date.
Definition: class_zone.h:932
void ExportSetting(ZONE_CONTAINER &aTarget, bool aFullExport=true) const
Function ExportSetting copy settings to a given zone.
ZONE_CONNECTION GetEffectiveZoneConnection(wxString *aSource=nullptr) const
Return the zone connection in effect (either locally overridden or overridden in the parent module).
Definition: class_pad.cpp:746
virtual const ZONE_SETTINGS & GetZoneSettings() const
Fetch the zone settings for this container.
void BooleanIntersection(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset intersection For aFastMode meaning, see function booleanOp
void SetDoNotAllowPads(bool aEnable)
Definition: class_zone.h:740
int NewOutline()
Creates a new empty polygon in the set and returns its index
EDA_ITEM * Clone() const override
Function Clone creates a duplicate of this item with linked list members set to NULL.
int HoleCount(int aOutline) const
Returns the number of holes in a given outline
Definition: color4d.h:60
CONST_ITERATOR CIterate(int aFirst, int aLast, bool aIterateHoles=false) const
void AddPolygon(std::vector< wxPoint > &aPolygon)
add a polygon to the zone outline if the zone outline is empty, this is the main outline else it is a...
Definition: class_zone.cpp:814
EDA_ITEM & operator=(const EDA_ITEM &aItem)
Operator assignment is used to assign the members of aItem to another object.
Definition: eda_item.cpp:193
void UnHatchBorder()
Function UnHatchBorder clears the zone's hatch.
Definition: class_zone.cpp:905
void SetBorderDisplayStyle(ZONE_BORDER_DISPLAY_STYLE aHatchStyle, int aHatchPitch, bool aRebuildHatch)
Function SetBorderDisplayStyle sets all hatch parameters for the zone.
Definition: class_zone.cpp:888
void Fracture(POLYGON_MODE aFastMode)
Converts a set of polygons with holes to a singe outline with "slits"/"fractures" connecting the oute...
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index
void SetSelectedCorner(int aCorner)
Definition: class_zone.h:265
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
wxPoint GetPosition() const override
Definition: class_zone.cpp:208
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition: class_zone.h:729
double m_hatchHoleMinArea
Definition: class_zone.h:902
unsigned int m_cornerRadius
Definition: class_zone.h:836
Thermal relief only for THT pads.
int LAYER_NUM
This can be replaced with int and removed.
wxString GetNetnameMsg() const
Function GetNetnameMsg.
void SetLocalClearance(int aClearance)
Definition: class_zone.h:138
void Move(const wxPoint &offset) override
Function Move Move the outlines.
Definition: class_zone.cpp:666
int GetThermalReliefGap() const
Definition: class_zone.h:172
Some functions to handle hotkeys in KiCad.
wxString GetSelectMenuText(EDA_UNITS aUnits) const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
Definition: class_zone.cpp:851
Definition: seg.h:39
EDA_UNITS
Definition: eda_units.h:38
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index
void Normalize()
Function Normalize ensures that the height ant width are positive.
Definition: eda_rect.cpp:35
void SetDoNotAllowCopperPour(bool aEnable)
Definition: class_zone.h:737
Use thermal relief for pads.
bool CollideEdge(const VECTOR2I &aPoint, VERTEX_INDEX &aClosestVertex, int aClearance=0) const
Function CollideEdge Checks whether aPoint collides with any edge of any of the contours of the polyg...
NETINFO_ITEM handles the data for a net.
Definition: netinfo.h:65
bool m_doNotAllowCopperPour
Definition: class_zone.h:857
std::map< PCB_LAYER_ID, ZONE_SEGMENT_FILL > m_FillSegmList
Segments used to fill the zone (#m_FillMode ==1 ), when fill zone by segment is used.
Definition: class_zone.h:914
Definition: color4d.h:57
double CalculateFilledArea()
Compute the area currently occupied by the zone fill.
int m_ZoneMinThickness
Definition: class_zone.h:865
unsigned GetPriority() const
Function GetPriority.
Definition: class_zone.h:106
MODULE_ZONE_CONTAINER & operator=(const MODULE_ZONE_CONTAINER &aOther)
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:201
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
int GetNet() const
Function GetNet.
Definition: netinfo.h:223
Information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:186
#define _(s)
Definition: 3d_actions.cpp:33
SHAPE_LINE_CHAIN.
NETINFO_ITEM * m_netinfo
Stores all informations about the net that item belongs to.
wxString UnescapeString(const wxString &aSource)
Definition: string.cpp:152
bool HitTestCutout(const VECTOR2I &aRefPos, int *aOutlineIdx=nullptr, int *aHoleIdx=nullptr) const
Tests if the given point is contained within a cutout of the zone.
Definition: class_zone.cpp:497
STATUS_FLAGS m_Flags
Definition: eda_item.h:165
void AddProperty(PROPERTY_BASE *aProperty)
Registers a property.
int GetCopperLayerCount() const
VECTOR2I A
Definition: seg.h:47
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
double DECIDEG2RAD(double deg)
Definition: trigo.h:224
NETCLASS * GetDefault() const
Function GetDefault.
PCB_EDIT_FRAME is the main frame for Pcbnew.
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boards.
Definition: eda_item.h:148
void SetLocalFlags(int aFlags)
Definition: class_zone.h:286
MODULE_ZONE_CONTAINER is the same item as ZONE_CONTAINER, but with a specific type id ZONE_CONTAINER ...
Definition: class_zone.h:958
int GetMinThickness() const
Definition: class_zone.h:224
bool HitTestFilledArea(PCB_LAYER_ID aLayer, const wxPoint &aRefPos, int aAccuracy=0) const
Function HitTestFilledArea tests if the given wxPoint is within the bounds of a filled area of this z...
Definition: class_zone.cpp:481
Pads are not covered.
virtual int GetOwnClearance(PCB_LAYER_ID aLayer, wxString *aSource=nullptr) const
Function GetClearance returns an item's "own" clearance in internal units.
bool Intersects(const EDA_RECT &aRect) const
Function Intersects tests for a common area between rectangles.
Definition: eda_rect.cpp:150
ZONE_CONNECTION GetPadConnection() const
Definition: class_zone.h:221
bool GetDoNotAllowTracks() const
Definition: class_zone.h:732
bool GetDoNotAllowFootprints() const
Definition: class_zone.h:734
const BITMAP_OPAQUE add_zone_xpm[1]
Definition: add_zone.cpp:59
bool AppendCorner(wxPoint aPosition, int aHoleIdx, bool aAllowDuplication=false)
Add a new corner to the zone outline (to the main outline or a hole)
Definition: class_zone.cpp:831
ZONE_BORDER_DISPLAY_STYLE
Zone border styles.
Definition: zone_settings.h:46
bool HitTestForEdge(const wxPoint &refPos, int aAccuracy, SHAPE_POLY_SET::VERTEX_INDEX &aCornerHit) const
Function HitTestForEdge tests if the given wxPoint is near a segment defined by 2 corners.
Definition: class_zone.cpp:414
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers of advanced config.
Provides class metadata.
Definition: property_mgr.h:61
bool m_needRefill
False when a zone was refilled, true after changes in zone params.
Definition: class_zone.h:883
int m_hatchSmoothingLevel
Definition: class_zone.h:897
void TransformSmoothedOutlineToPolygon(SHAPE_POLY_SET &aCornerBuffer, int aClearance, SHAPE_POLY_SET *aBoardOutline) const
Function TransformSmoothedOutlineToPolygon Convert the outlines shape to a polygon with no holes infl...
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Function GetMsgPanelInfo populates aList of MSG_PANEL_ITEM objects with it's internal state for displ...
Definition: class_zone.cpp:522
Abstract interface for BOARD_ITEMs capable of storing other items inside.
ZONE_CONTAINER(BOARD_ITEM_CONTAINER *parent, bool aInFP=false)
The ctor to build ZONE_CONTAINER, but comaptible with MODULE_ZONE_CONTAINER requirement.
Definition: class_zone.cpp:41
EDA_MSG_ITEM is used EDA_MSG_PANEL as the item type for displaying messages.
Definition: msgpanel.h:54
VIEW.
Definition: view.h:63
ZONE_FILL_MODE m_fillMode
How to fill areas: ZONE_FILL_MODE::POLYGONS => use solid polygons ZONE_FILL_MODE::HATCH_PATTERN => us...
Definition: class_zone.h:893
int m_hatchThickness
Definition: class_zone.h:894
BITMAP_DEF GetMenuImage() const override
Function GetMenuImage returns a pointer to an image to be used in menus.
static struct ZONE_CONTAINER_DESC _ZONE_CONTAINER_DESC
BOARD_ITEM_CONTAINER * GetParent() const
bool m_forceVisible
Definition: eda_item.h:164
int GetEffectiveThermalGap(wxString *aSource=nullptr) const
Return the effective thermal gap having resolved any inheritance.
Definition: class_pad.cpp:786
void SetMinThickness(int aMinThickness)
Definition: class_zone.h:225
static constexpr int Millimeter2iu(double mm)
#define _HKI(x)
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
const BOX2I BBox(int aClearance=0) const override
Function BBox()
int GetEffectiveThermalSpokeWidth(wxString *aSource=nullptr) const
Return the effective thermal spoke width having resolved any inheritance.
Definition: class_pad.cpp:767
const VECTOR2I & GetCornerPosition(int aCornerIndex) const
Definition: class_zone.h:546
int GetThermalReliefSpokeWidth() const
Definition: class_zone.h:182
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
virtual void Flip(const wxPoint &aCentre, bool aFlipLeftRight) override
Function Flip Flip this object, i.e.
Definition: class_zone.cpp:728
void SetThermalReliefGap(int aThermalReliefGap)
Definition: class_zone.h:165
bool IsIsland(PCB_LAYER_ID aLayer, int aPolyIdx)
Checks if a given filled polygon is an insulated island.
bool CollideVertex(const VECTOR2I &aPoint, VERTEX_INDEX &aClosestVertex, int aClearance=0) const
Function CollideVertex Checks whether aPoint collides with any vertex of any of the contours of the p...
bool IsOnCopperLayer() const override
Function IsOnCopperLayer.
Definition: class_zone.cpp:220
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
int GetLocalFlags() const
Definition: class_zone.h:285
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
Definition: eda_rect.cpp:363
int m_borderHatchPitch
Definition: class_zone.h:935
KICAD_T Type() const
Function Type()
Definition: eda_item.h:182
bool IsLayerVisible(int aLayer) const
Function IsLayerVisible() Returns information about visibility of a particular layer.
Definition: view.h:402
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)
std::map< PCB_LAYER_ID, SHAPE_POLY_SET > m_FilledPolysList
Definition: class_zone.h:924
VECTOR2I B
Definition: seg.h:48
void SetNeedRefill(bool aNeedRefill)
Definition: class_zone.h:218