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>
27 #include <fctsys.h>
29 #include <pcb_base_frame.h>
30 #include <pcb_screen.h>
31 #include <class_board.h>
32 #include <class_zone.h>
33 #include <pcb_edit_frame.h> // current layer for msgpanel
34 #include <math_for_graphics.h>
37 
38 
41  m_area( 0.0 )
42 {
43  m_CornerSelection = nullptr; // no corner is selected
44  m_IsFilled = false; // fill status : true when the zone is filled
48  m_hv45 = false;
52  m_HatchFillTypeSmoothingLevel = 0; // Grid pattern smoothing type. 0 = no smoothing
53  m_HatchFillTypeSmoothingValue = 0.1; // Grid pattern chamfer value relative to the gap value
54  // used only if m_HatchFillTypeSmoothingLevel > 0
55  m_priority = 0;
57  SetIsKeepout( aInModule ? true : false ); // Zones living in modules have the keepout option.
58  SetDoNotAllowCopperPour( false ); // has meaning only if m_isKeepout == true
59  SetDoNotAllowVias( true ); // has meaning only if m_isKeepout == true
60  SetDoNotAllowTracks( true ); // has meaning only if m_isKeepout == true
61  SetDoNotAllowPads( true ); // has meaning only if m_isKeepout == true
62  SetDoNotAllowFootprints( false ); // has meaning only if m_isKeepout == true
63  m_cornerRadius = 0;
64  SetLocalFlags( 0 ); // flags tempoarry used in zone calculations
65  m_Poly = new SHAPE_POLY_SET(); // Outlines
66  m_FilledPolysUseThickness = true; // set the "old" way to build filled polygon areas (before 6.0.x)
68  aParent->GetZoneSettings().ExportSetting( *this );
69 
70  m_needRefill = false; // True only after some edition.
71 }
72 
73 
75  : BOARD_CONNECTED_ITEM( aZone.GetParent(), PCB_ZONE_AREA_T ),
76  m_Poly( nullptr ),
77  m_CornerSelection( nullptr )
78 {
80 }
81 
82 
84 {
86 
87  InitDataFromSrcInCopyCtor( aOther );
88 
89  return *this;
90 }
91 
92 
94 {
95  delete m_Poly;
96  delete m_CornerSelection;
97 }
98 
99 
101 {
102  // members are expected non initialize in this.
103  // InitDataFromSrcInCopyCtor() is expected to be called
104  // only from a copy constructor.
105 
106  // Copy only useful EDA_ITEM flags:
107  m_Flags = aZone.m_Flags;
109 
110  // Replace the outlines for aZone outlines.
111  delete m_Poly;
112  m_Poly = new SHAPE_POLY_SET( *aZone.m_Poly );
113 
116  m_zoneName = aZone.m_zoneName;
117  SetLayerSet( aZone.GetLayerSet() );
118  m_priority = aZone.m_priority;
119  m_isKeepout = aZone.m_isKeepout;
120 
126 
128  m_ZoneClearance = aZone.m_ZoneClearance; // clearance value
133 
134  m_IsFilled = aZone.m_IsFilled;
135  m_needRefill = aZone.m_needRefill;
136 
139 
140  m_FillMode = aZone.m_FillMode; // Filling mode (segments/polygons)
146 
147  // For corner moving, corner index to drag, or nullptr if no selection
148  delete m_CornerSelection;
149  m_CornerSelection = nullptr;
150 
151  for( PCB_LAYER_ID layer : aZone.GetLayerSet().Seq() )
152  {
153  m_FilledPolysList[layer] = aZone.m_FilledPolysList.at( layer );
154  m_RawPolysList[layer] = aZone.m_RawPolysList.at( layer );
155  m_filledPolysHash[layer] = aZone.m_filledPolysHash.at( layer );
156  m_FillSegmList[layer] = aZone.m_FillSegmList.at( layer ); // vector <> copy
157  m_insulatedIslands[layer] = aZone.m_insulatedIslands.at( layer );
158  }
159 
160  m_hatchStyle = aZone.m_hatchStyle;
161  m_hatchPitch = aZone.m_hatchPitch;
162  m_HatchLines = aZone.m_HatchLines;
163 
164  SetLocalFlags( aZone.GetLocalFlags() );
165 
166  m_netinfo = aZone.m_netinfo;
167 
168  m_hv45 = aZone.m_hv45;
169  m_area = aZone.m_area;
170 
171 }
172 
173 
175 {
176  return new ZONE_CONTAINER( *this );
177 }
178 
179 
181 {
182  bool change = false;
183 
184  for( std::pair<const PCB_LAYER_ID, SHAPE_POLY_SET>& pair : m_FilledPolysList )
185  {
186  change |= !pair.second.IsEmpty();
187  pair.second.RemoveAllContours();
188  }
189 
190  for( std::pair<const PCB_LAYER_ID, ZONE_SEGMENT_FILL>& pair : m_FillSegmList )
191  {
192  change |= !pair.second.empty();
193  pair.second.clear();
194  }
195 
196  m_IsFilled = false;
197 
198  return change;
199 }
200 
201 
203 {
204  return (wxPoint) GetCornerPosition( 0 );
205 }
206 
207 
209 {
210  return BOARD_ITEM::GetLayer();
211 }
212 
213 
215 {
216  return ( m_layerSet & LSET::AllCuMask() ).count() > 0;
217 }
218 
219 
220 bool ZONE_CONTAINER::CommonLayerExists( const LSET aLayerSet ) const
221 {
222  LSET common = GetLayerSet() & aLayerSet;
223 
224  return common.count() > 0;
225 }
226 
227 
229 {
230  SetLayerSet( LSET( aLayer ) );
231 
232  m_Layer = aLayer;
233 }
234 
235 
237 {
238  if( GetIsKeepout() )
239  {
240  // Keepouts can only exist on copper layers
241  aLayerSet &= LSET::AllCuMask();
242  }
243 
244  if( aLayerSet.count() == 0 )
245  return;
246 
247  if( m_layerSet != aLayerSet )
248  {
249  SetNeedRefill( true );
250 
251  UnFill();
252 
253  m_FillSegmList.clear();
254  m_FilledPolysList.clear();
255  m_RawPolysList.clear();
256  m_filledPolysHash.clear();
257  m_insulatedIslands.clear();
258 
259  for( PCB_LAYER_ID layer : aLayerSet.Seq() )
260  {
261  m_FillSegmList[layer] = {};
262  m_FilledPolysList[layer] = {};
263  m_RawPolysList[layer] = {};
264  m_filledPolysHash[layer] = {};
265  m_insulatedIslands[layer] = {};
266  }
267  }
268 
269  m_layerSet = aLayerSet;
270 
271  // Set the single layer parameter.
272  // For zones that can be on many layers, this parameter does not have
273  // really meaning and is a bit arbitrary if more than one layer is set.
274  // But many functions are using it.
275  // So we need to initialize it to a reasonable value.
276  // Priority is F_Cu then B_Cu then to the first selected layer
277  m_Layer = aLayerSet.Seq()[0];
278 
279  if( m_Layer != F_Cu && aLayerSet[B_Cu] )
280  m_Layer = B_Cu;
281 }
282 
283 
285 {
286  return m_layerSet;
287 }
288 
289 
290 void ZONE_CONTAINER::ViewGetLayers( int aLayers[], int& aCount ) const
291 {
292  LSEQ layers = m_layerSet.Seq();
293 
294  for( unsigned int idx = 0; idx < layers.size(); idx++ )
295  aLayers[idx] = layers[idx];
296 
297  aCount = layers.size();
298 }
299 
300 
302 {
303  return m_layerSet.test( aLayer );
304 }
305 
306 
308 {
309  auto bb = m_Poly->BBox();
310 
311  EDA_RECT ret( (wxPoint) bb.GetOrigin(), wxSize( bb.GetWidth(), bb.GetHeight() ) );
312 
313  return ret;
314 }
315 
316 
318 {
319  if( aPad == NULL || aPad->GetThermalGap() == 0 )
320  return m_ThermalReliefGap;
321  else
322  return aPad->GetThermalGap();
323 }
324 
325 
327 {
328  if( aPad == NULL || aPad->GetThermalWidth() == 0 )
330  else
331  return aPad->GetThermalWidth();
332 }
333 
334 
335 int ZONE_CONTAINER::GetKeepouts( std::map<int, wxString>* aSources ) const
336 {
337  wxString source;
338  int keepouts = 0;
339 
340  auto setFlag = [&]( int aFlag )
341  {
342  keepouts |= aFlag;
343 
344  if( aSources )
345  (*aSources)[ aFlag ] = source;
346  };
347 
348  if( m_isKeepout )
349  {
350  if( aSources )
351  source = _( "zone properties" );
352 
353  if( m_doNotAllowTracks )
354  setFlag( DISALLOW_TRACKS );
355 
356  if( m_doNotAllowVias )
357  setFlag( DISALLOW_VIAS );
358 
359  if( m_doNotAllowPads )
360  setFlag( DISALLOW_PADS );
361 
363  setFlag( DISALLOW_FOOTPRINTS );
364 
366  setFlag( DISALLOW_ZONES );
367  }
368 
369  DRC_RULE* rule = GetRule( this, nullptr, DISALLOW_CONSTRAINT );
370 
371  if( rule )
372  {
373  if( aSources )
374  source = wxString::Format( _( "'%s' rule" ), rule->m_Name );
375 
376  if( ( rule->m_DisallowFlags & DISALLOW_VIAS ) > 0 )
377  setFlag( DISALLOW_VIAS );
378 
379  if( ( rule->m_DisallowFlags & DISALLOW_MICRO_VIAS ) > 0 )
380  setFlag( DISALLOW_MICRO_VIAS );
381 
382  if( ( rule->m_DisallowFlags & DISALLOW_BB_VIAS ) > 0 )
383  setFlag( DISALLOW_BB_VIAS );
384 
385  if( ( rule->m_DisallowFlags & DISALLOW_TRACKS ) > 0 )
386  setFlag( DISALLOW_TRACKS );
387 
388  if( ( rule->m_DisallowFlags & DISALLOW_PADS ) > 0 )
389  setFlag( DISALLOW_PADS );
390 
391  if( ( rule->m_DisallowFlags & DISALLOW_ZONES ) > 0 )
392  setFlag( DISALLOW_ZONES );
393 
394  if( ( rule->m_DisallowFlags & DISALLOW_TEXTS ) > 0 )
395  setFlag( DISALLOW_TEXTS );
396 
397  if( ( rule->m_DisallowFlags & DISALLOW_GRAPHICS ) > 0 )
398  setFlag( DISALLOW_GRAPHICS );
399 
400  if( ( rule->m_DisallowFlags & DISALLOW_HOLES ) > 0 )
401  setFlag( DISALLOW_HOLES );
402 
403  if( ( rule->m_DisallowFlags & DISALLOW_FOOTPRINTS ) > 0 )
404  setFlag( DISALLOW_FOOTPRINTS );
405  }
406 
407  return keepouts;
408 }
409 
410 
411 void ZONE_CONTAINER::SetCornerRadius( unsigned int aRadius )
412 {
413  if( m_cornerRadius != aRadius )
414  SetNeedRefill( true );
415 
416  m_cornerRadius = aRadius;
417 }
418 
419 
420 bool ZONE_CONTAINER::HitTest( const wxPoint& aPosition, int aAccuracy ) const
421 {
422  // Normally accuracy is zoom-relative, but for the generic HitTest we just use
423  // a fixed (small) value.
424  int accuracy = std::max( aAccuracy, Millimeter2iu( 0.1 ) );
425 
426  return HitTestForCorner( aPosition, accuracy * 2 ) || HitTestForEdge( aPosition, accuracy );
427 }
428 
429 
430 void ZONE_CONTAINER::SetSelectedCorner( const wxPoint& aPosition, int aAccuracy )
431 {
433 
434  // If there is some corner to be selected, assign it to m_CornerSelection
435  if( HitTestForCorner( aPosition, aAccuracy * 2, corner )
436  || HitTestForEdge( aPosition, aAccuracy, corner ) )
437  {
438  if( m_CornerSelection == nullptr )
440 
441  *m_CornerSelection = corner;
442  }
443 }
444 
445 bool ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos, int aAccuracy,
446  SHAPE_POLY_SET::VERTEX_INDEX& aCornerHit ) const
447 {
448  return m_Poly->CollideVertex( VECTOR2I( refPos ), aCornerHit, aAccuracy );
449 }
450 
451 
452 bool ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos, int aAccuracy ) const
453 {
455  return HitTestForCorner( refPos, aAccuracy, dummy );
456 }
457 
458 
459 bool ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos, int aAccuracy,
460  SHAPE_POLY_SET::VERTEX_INDEX& aCornerHit ) const
461 {
462  return m_Poly->CollideEdge( VECTOR2I( refPos ), aCornerHit, aAccuracy );
463 }
464 
465 
466 bool ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos, int aAccuracy ) const
467 {
469  return HitTestForEdge( refPos, aAccuracy, dummy );
470 }
471 
472 
473 bool ZONE_CONTAINER::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
474 {
475  // Calculate bounding box for zone
476  EDA_RECT bbox = GetBoundingBox();
477  bbox.Normalize();
478 
479  EDA_RECT arect = aRect;
480  arect.Normalize();
481  arect.Inflate( aAccuracy );
482 
483  if( aContained )
484  {
485  return arect.Contains( bbox );
486  }
487  else // Test for intersection between aBox and the polygon
488  // For a polygon, using its bounding box has no sense here
489  {
490  // Fast test: if aBox is outside the polygon bounding box, rectangles cannot intersect
491  if( !arect.Intersects( bbox ) )
492  return false;
493 
494  int count = m_Poly->TotalVertices();
495 
496  for( int ii = 0; ii < count; ii++ )
497  {
498  auto vertex = m_Poly->CVertex( ii );
499  auto vertexNext = m_Poly->CVertex( ( ii + 1 ) % count );
500 
501  // Test if the point is within the rect
502  if( arect.Contains( ( wxPoint ) vertex ) )
503  {
504  return true;
505  }
506 
507  // Test if this edge intersects the rect
508  if( arect.Intersects( ( wxPoint ) vertex, ( wxPoint ) vertexNext ) )
509  {
510  return true;
511  }
512  }
513 
514  return false;
515  }
516 }
517 
518 
519 int ZONE_CONTAINER::GetLocalClearance( wxString* aSource ) const
520 {
521  if( m_isKeepout )
522  return 0;
523 
524  if( aSource )
525  *aSource = _( "zone" );
526 
527  return m_ZoneClearance;
528 }
529 
530 
532  int aAccuracy ) const
533 {
534  // Keepouts have no filled area, but it's generally nice to treat their interior as if it were
535  // filled so that people don't have to select keepouts by their outline (which is min-width)
536  if( GetIsKeepout() )
537  return m_Poly->Contains( VECTOR2I( aRefPos.x, aRefPos.y ), -1, aAccuracy );
538 
539  if( !m_FilledPolysList.count( aLayer ) )
540  return false;
541 
542  return m_FilledPolysList.at( aLayer ).Contains( VECTOR2I( aRefPos.x, aRefPos.y ), -1,
543  aAccuracy );
544 }
545 
546 
547 bool ZONE_CONTAINER::HitTestCutout( const VECTOR2I& aRefPos, int* aOutlineIdx, int* aHoleIdx ) const
548 {
549  // Iterate over each outline polygon in the zone and then iterate over
550  // each hole it has to see if the point is in it.
551  for( int i = 0; i < m_Poly->OutlineCount(); i++ )
552  {
553  for( int j = 0; j < m_Poly->HoleCount( i ); j++ )
554  {
555  if( m_Poly->Hole( i, j ).PointInside( aRefPos ) )
556  {
557  if( aOutlineIdx )
558  *aOutlineIdx = i;
559 
560  if( aHoleIdx )
561  *aHoleIdx = j;
562 
563  return true;
564  }
565  }
566  }
567 
568  return false;
569 }
570 
571 
572 void ZONE_CONTAINER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
573 {
574  EDA_UNITS units = aFrame->GetUserUnits();
575  wxString msg, msg2;
576 
577  if( GetIsKeepout() )
578  msg = _( "Keepout Area" );
579  else if( IsOnCopperLayer() )
580  msg = _( "Copper Zone" );
581  else
582  msg = _( "Non-copper Zone" );
583 
584  // Display Cutout instead of Outline for holes inside a zone
585  // i.e. when num contour !=0
586  // Check whether the selected corner is in a hole; i.e., in any contour but the first one.
587  if( m_CornerSelection != nullptr && m_CornerSelection->m_contour > 0 )
588  msg << wxT( " " ) << _( "Cutout" );
589 
590  aList.emplace_back( _( "Type" ), msg, DARKCYAN );
591 
592  if( GetIsKeepout() )
593  {
594  msg.Empty();
595 
596  if( GetDoNotAllowVias() )
597  AccumulateDescription( msg, _( "No vias" ) );
598 
599  if( GetDoNotAllowTracks() )
600  AccumulateDescription( msg, _( "No tracks" ) );
601 
602  if( GetDoNotAllowPads() )
603  AccumulateDescription( msg, _( "No pads" ) );
604 
606  AccumulateDescription( msg, _( "No copper zones" ) );
607 
609  AccumulateDescription( msg, _( "No footprints" ) );
610 
611  aList.emplace_back( MSG_PANEL_ITEM( _( "Keepout" ), msg, RED ) );
612  }
613  else if( IsOnCopperLayer() )
614  {
615  if( GetNetCode() >= 0 )
616  {
617  NETINFO_ITEM* net = GetNet();
618  NETCLASS* netclass = nullptr;
619 
620  if( net )
621  {
622  if( net->GetNet() )
623  netclass = GetNetClass();
624  else
625  netclass = GetBoard()->GetDesignSettings().GetDefault();
626 
627  msg = UnescapeString( net->GetNetname() );
628  }
629  else
630  {
631  msg = wxT( "<no name>" );
632  }
633 
634  aList.emplace_back( _( "Net" ), msg, RED );
635 
636  if( netclass )
637  aList.emplace_back( _( "NetClass" ), netclass->GetName(), DARKMAGENTA );
638  }
639 
640  // Display priority level
641  msg.Printf( wxT( "%d" ), GetPriority() );
642  aList.emplace_back( _( "Priority" ), msg, BLUE );
643  }
644 
645  wxString layerDesc;
646  int count = 0;
647 
648  for( PCB_LAYER_ID layer : m_layerSet.Seq() )
649  {
650  if( count == 0 )
651  layerDesc = GetBoard()->GetLayerName( layer );
652 
653  count++;
654  }
655 
656  if( count > 1 )
657  layerDesc.Printf( _( "%s and %d more" ), layerDesc, count - 1 );
658 
659  aList.emplace_back( _( "Layer" ), layerDesc, DARKGREEN );
660 
661  if( !m_zoneName.empty() )
662  aList.emplace_back( _( "Name" ), m_zoneName, DARKMAGENTA );
663 
664  switch( m_FillMode )
665  {
666  case ZONE_FILL_MODE::POLYGONS: msg = _( "Solid" ); break;
667  case ZONE_FILL_MODE::HATCH_PATTERN: msg = _( "Hatched" ); break;
668  default: msg = _( "Unknown" ); break;
669  }
670 
671  aList.emplace_back( _( "Fill Mode" ), msg, BROWN );
672 
673  msg = MessageTextFromValue( units, m_area, false, EDA_DATA_TYPE::AREA );
674  aList.emplace_back( _( "Filled Area" ), msg, BLUE );
675 
676  wxString source;
677  int clearance = GetClearance( nullptr, &source );
678 
679  msg.Printf( _( "Min Clearance: %s" ), MessageTextFromValue( units, clearance, true ) );
680  msg2.Printf( _( "(from %s)" ), source );
681  aList.emplace_back( msg, msg2, BLACK );
682 
683  // Useful for statistics, especially when zones are complex the number of hatches
684  // and filled polygons can explain the display and DRC calculation time:
685  msg.Printf( wxT( "%d" ), (int) m_HatchLines.size() );
686  aList.emplace_back( MSG_PANEL_ITEM( _( "Hatch Lines" ), msg, BLUE ) );
687 
688  PCB_LAYER_ID layer = m_Layer;
689 
690  // NOTE: This brings in dependence on PCB_EDIT_FRAME to the qa tests, which isn't ideal.
691  // TODO: Figure out a way for items to know the active layer without the whole edit frame?
692 #if 0
693  if( PCB_EDIT_FRAME* pcbframe = dynamic_cast<PCB_EDIT_FRAME*>( aFrame ) )
694  if( m_FilledPolysList.count( pcbframe->GetActiveLayer() ) )
695  layer = pcbframe->GetActiveLayer();
696 #endif
697 
698  if( !m_FilledPolysList.at( layer ).IsEmpty() )
699  {
700  msg.Printf( wxT( "%d" ), m_FilledPolysList.at( layer ).TotalVertices() );
701  aList.emplace_back( MSG_PANEL_ITEM( _( "Corner Count" ), msg, BLUE ) );
702  }
703 }
704 
705 
706 /* Geometric transforms: */
707 
708 void ZONE_CONTAINER::Move( const wxPoint& offset )
709 {
710  /* move outlines */
711  m_Poly->Move( offset );
712 
713  Hatch();
714 
715  for( std::pair<const PCB_LAYER_ID, SHAPE_POLY_SET>& pair : m_FilledPolysList )
716  pair.second.Move( offset );
717 
718  for( std::pair<const PCB_LAYER_ID, ZONE_SEGMENT_FILL>& pair : m_FillSegmList )
719  {
720  for( SEG& seg : pair.second )
721  {
722  seg.A += VECTOR2I( offset );
723  seg.B += VECTOR2I( offset );
724  }
725  }
726 }
727 
728 
729 void ZONE_CONTAINER::MoveEdge( const wxPoint& offset, int aEdge )
730 {
731  int next_corner;
732 
733  if( m_Poly->GetNeighbourIndexes( aEdge, nullptr, &next_corner ) )
734  {
735  m_Poly->SetVertex( aEdge, m_Poly->CVertex( aEdge ) + VECTOR2I( offset ) );
736  m_Poly->SetVertex( next_corner, m_Poly->CVertex( next_corner ) + VECTOR2I( offset ) );
737  Hatch();
738 
739  SetNeedRefill( true );
740  }
741 }
742 
743 
744 void ZONE_CONTAINER::Rotate( const wxPoint& centre, double angle )
745 {
746  wxPoint pos;
747 
748  angle = -DECIDEG2RAD( angle );
749 
750  m_Poly->Rotate( angle, VECTOR2I( centre ) );
751  Hatch();
752 
753  /* rotate filled areas: */
754  for( std::pair<const PCB_LAYER_ID, SHAPE_POLY_SET>& pair : m_FilledPolysList )
755  pair.second.Rotate( angle, VECTOR2I( centre ) );
756 
757  for( std::pair<const PCB_LAYER_ID, ZONE_SEGMENT_FILL>& pair : m_FillSegmList )
758  {
759  for( SEG& seg : pair.second )
760  {
761  wxPoint a( seg.A );
762  RotatePoint( &a, centre, angle );
763  seg.A = a;
764  wxPoint b( seg.B );
765  RotatePoint( &b, centre, angle );
766  seg.B = a;
767  }
768  }
769 }
770 
771 
772 void ZONE_CONTAINER::Flip( const wxPoint& aCentre, bool aFlipLeftRight )
773 {
774  Mirror( aCentre, aFlipLeftRight );
775  int copperLayerCount = GetBoard()->GetCopperLayerCount();
776 
777  if( GetIsKeepout() )
778  SetLayerSet( FlipLayerMask( GetLayerSet(), copperLayerCount ) );
779  else
780  SetLayer( FlipLayer( GetLayer(), copperLayerCount ) );
781 }
782 
783 
784 void ZONE_CONTAINER::Mirror( const wxPoint& aMirrorRef, bool aMirrorLeftRight )
785 {
786  // ZONE_CONTAINERs mirror about the x-axis (why?!?)
787  m_Poly->Mirror( aMirrorLeftRight, !aMirrorLeftRight, VECTOR2I( aMirrorRef ) );
788 
789  Hatch();
790 
791  for( std::pair<const PCB_LAYER_ID, SHAPE_POLY_SET>& pair : m_FilledPolysList )
792  pair.second.Mirror( aMirrorLeftRight, !aMirrorLeftRight, VECTOR2I( aMirrorRef ) );
793 
794  for( std::pair<const PCB_LAYER_ID, ZONE_SEGMENT_FILL>& pair : m_FillSegmList )
795  {
796  for( SEG& seg : pair.second )
797  {
798  if( aMirrorLeftRight )
799  {
800  MIRROR( seg.A.x, aMirrorRef.x );
801  MIRROR( seg.B.x, aMirrorRef.x );
802  }
803  else
804  {
805  MIRROR( seg.A.y, aMirrorRef.y );
806  MIRROR( seg.B.y, aMirrorRef.y );
807  }
808  }
809  }
810 }
811 
812 
814 {
816  return m_PadConnection;
817  else
818  return aPad->GetEffectiveZoneConnection();
819 }
820 
821 
822 void ZONE_CONTAINER::RemoveCutout( int aOutlineIdx, int aHoleIdx )
823 {
824  // Ensure the requested cutout is valid
825  if( m_Poly->OutlineCount() < aOutlineIdx || m_Poly->HoleCount( aOutlineIdx ) < aHoleIdx )
826  return;
827 
828  SHAPE_POLY_SET cutPoly( m_Poly->Hole( aOutlineIdx, aHoleIdx ) );
829 
830  // Add the cutout back to the zone
832 
833  SetNeedRefill( true );
834 }
835 
836 
838 {
839  wxASSERT( aPolygon.IsClosed() );
840 
841  // Add the outline as a new polygon in the polygon set
842  if( m_Poly->OutlineCount() == 0 )
843  m_Poly->AddOutline( aPolygon );
844  else
845  m_Poly->AddHole( aPolygon );
846 
847  SetNeedRefill( true );
848 }
849 
850 
851 void ZONE_CONTAINER::AddPolygon( std::vector< wxPoint >& aPolygon )
852 {
853  if( aPolygon.empty() )
854  return;
855 
856  SHAPE_LINE_CHAIN outline;
857 
858  // Create an outline and populate it with the points of aPolygon
859  for( const wxPoint& pt : aPolygon)
860  outline.Append( pt );
861 
862  outline.SetClosed( true );
863 
864  AddPolygon( outline );
865 }
866 
867 
868 bool ZONE_CONTAINER::AppendCorner( wxPoint aPosition, int aHoleIdx, bool aAllowDuplication )
869 {
870  // Ensure the main outline exists:
871  if( m_Poly->OutlineCount() == 0 )
872  m_Poly->NewOutline();
873 
874  // If aHoleIdx >= 0, the corner musty be added to the hole, index aHoleIdx.
875  // (remember: the index of the first hole is 0)
876  // Return error if if does dot exist.
877  if( aHoleIdx >= m_Poly->HoleCount( 0 ) )
878  return false;
879 
880  m_Poly->Append( aPosition.x, aPosition.y, -1, aHoleIdx, aAllowDuplication );
881 
882  SetNeedRefill( true );
883 
884  return true;
885 }
886 
887 
889 {
890  wxString text;
891 
892  // Check whether the selected contour is a hole (contour index > 0)
893  if( m_CornerSelection != nullptr && m_CornerSelection->m_contour > 0 )
894  text << wxT( " " ) << _( "(Cutout)" );
895 
896  if( GetIsKeepout() )
897  text << wxT( " " ) << _( "(Keepout)" );
898  else
899  text << GetNetnameMsg();
900 
901  wxString layerDesc;
902  int count = 0;
903 
904  for( PCB_LAYER_ID layer : m_layerSet.Seq() )
905  {
906  if( count == 0 )
907  layerDesc = GetBoard()->GetLayerName( layer );
908 
909  count++;
910  }
911 
912  if( count > 1 )
913  layerDesc.Printf( _( "%s and %d more" ), layerDesc, count - 1 );
914 
915  return wxString::Format( _( "Zone Outline %s on %s" ), text, layerDesc );
916 }
917 
918 
920 {
921  return m_hatchPitch;
922 }
923 
924 
925 void ZONE_CONTAINER::SetHatch( ZONE_HATCH_STYLE aHatchStyle, int aHatchPitch, bool aRebuildHatch )
926 {
927  SetHatchPitch( aHatchPitch );
928  m_hatchStyle = aHatchStyle;
929 
930  if( aRebuildHatch )
931  Hatch();
932 }
933 
934 
936 {
937  m_hatchPitch = aPitch;
938 }
939 
940 
942 {
943  m_HatchLines.clear();
944 }
945 
946 
947 // Creates hatch lines inside the outline of the complex polygon
948 // sort function used in ::Hatch to sort points by descending wxPoint.x values
949 bool sortEndsByDescendingX( const VECTOR2I& ref, const VECTOR2I& tst )
950 {
951  return tst.x < ref.x;
952 }
953 
954 
956 {
957  UnHatch();
958 
960  return;
961 
962  // define range for hatch lines
963  int min_x = m_Poly->CVertex( 0 ).x;
964  int max_x = m_Poly->CVertex( 0 ).x;
965  int min_y = m_Poly->CVertex( 0 ).y;
966  int max_y = m_Poly->CVertex( 0 ).y;
967 
968  for( auto iterator = m_Poly->IterateWithHoles(); iterator; iterator++ )
969  {
970  if( iterator->x < min_x )
971  min_x = iterator->x;
972 
973  if( iterator->x > max_x )
974  max_x = iterator->x;
975 
976  if( iterator->y < min_y )
977  min_y = iterator->y;
978 
979  if( iterator->y > max_y )
980  max_y = iterator->y;
981  }
982 
983  // Calculate spacing between 2 hatch lines
984  int spacing;
985 
987  spacing = m_hatchPitch;
988  else
989  spacing = m_hatchPitch * 2;
990 
991  // set the "length" of hatch lines (the length on horizontal axis)
992  int hatch_line_len = m_hatchPitch;
993 
994  // To have a better look, give a slope depending on the layer
995  LAYER_NUM layer = GetLayer();
996  int slope_flag = (layer & 1) ? 1 : -1; // 1 or -1
997  double slope = 0.707106 * slope_flag; // 45 degrees slope
998  int max_a, min_a;
999 
1000  if( slope_flag == 1 )
1001  {
1002  max_a = KiROUND( max_y - slope * min_x );
1003  min_a = KiROUND( min_y - slope * max_x );
1004  }
1005  else
1006  {
1007  max_a = KiROUND( max_y - slope * max_x );
1008  min_a = KiROUND( min_y - slope * min_x );
1009  }
1010 
1011  min_a = (min_a / spacing) * spacing;
1012 
1013  // calculate an offset depending on layer number,
1014  // for a better look of hatches on a multilayer board
1015  int offset = (layer * 7) / 8;
1016  min_a += offset;
1017 
1018  // loop through hatch lines
1019  #define MAXPTS 200 // Usually we store only few values per one hatch line
1020  // depending on the complexity of the zone outline
1021 
1022  static std::vector<VECTOR2I> pointbuffer;
1023  pointbuffer.clear();
1024  pointbuffer.reserve( MAXPTS + 2 );
1025 
1026  for( int a = min_a; a < max_a; a += spacing )
1027  {
1028  // get intersection points for this hatch line
1029 
1030  // Note: because we should have an even number of intersections with the
1031  // current hatch line and the zone outline (a closed polygon,
1032  // or a set of closed polygons), if an odd count is found
1033  // we skip this line (should not occur)
1034  pointbuffer.clear();
1035 
1036  // Iterate through all vertices
1037  for( auto iterator = m_Poly->IterateSegmentsWithHoles(); iterator; iterator++ )
1038  {
1039  double x, y, x2, y2;
1040  int ok;
1041 
1042  SEG segment = *iterator;
1043 
1044  ok = FindLineSegmentIntersection( a, slope,
1045  segment.A.x, segment.A.y,
1046  segment.B.x, segment.B.y,
1047  &x, &y, &x2, &y2 );
1048 
1049  if( ok )
1050  {
1051  VECTOR2I point( KiROUND( x ), KiROUND( y ) );
1052  pointbuffer.push_back( point );
1053  }
1054 
1055  if( ok == 2 )
1056  {
1057  VECTOR2I point( KiROUND( x2 ), KiROUND( y2 ) );
1058  pointbuffer.push_back( point );
1059  }
1060 
1061  if( pointbuffer.size() >= MAXPTS ) // overflow
1062  {
1063  wxASSERT( 0 );
1064  break;
1065  }
1066  }
1067 
1068  // ensure we have found an even intersection points count
1069  // because intersections are the ends of segments
1070  // inside the polygon(s) and a segment has 2 ends.
1071  // if not, this is a strange case (a bug ?) so skip this hatch
1072  if( pointbuffer.size() % 2 != 0 )
1073  continue;
1074 
1075  // sort points in order of descending x (if more than 2) to
1076  // ensure the starting point and the ending point of the same segment
1077  // are stored one just after the other.
1078  if( pointbuffer.size() > 2 )
1079  sort( pointbuffer.begin(), pointbuffer.end(), sortEndsByDescendingX );
1080 
1081  // creates lines or short segments inside the complex polygon
1082  for( unsigned ip = 0; ip < pointbuffer.size(); ip += 2 )
1083  {
1084  int dx = pointbuffer[ip + 1].x - pointbuffer[ip].x;
1085 
1086  // Push only one line for diagonal hatch,
1087  // or for small lines < twice the line length
1088  // else push 2 small lines
1090  || std::abs( dx ) < 2 * hatch_line_len )
1091  {
1092  m_HatchLines.emplace_back( SEG( pointbuffer[ip], pointbuffer[ip + 1] ) );
1093  }
1094  else
1095  {
1096  double dy = pointbuffer[ip + 1].y - pointbuffer[ip].y;
1097  slope = dy / dx;
1098 
1099  if( dx > 0 )
1100  dx = hatch_line_len;
1101  else
1102  dx = -hatch_line_len;
1103 
1104  int x1 = KiROUND( pointbuffer[ip].x + dx );
1105  int x2 = KiROUND( pointbuffer[ip + 1].x - dx );
1106  int y1 = KiROUND( pointbuffer[ip].y + dx * slope );
1107  int y2 = KiROUND( pointbuffer[ip + 1].y - dx * slope );
1108 
1109  m_HatchLines.emplace_back( SEG( pointbuffer[ip].x, pointbuffer[ip].y, x1, y1 ) );
1110 
1111  m_HatchLines.emplace_back( SEG( pointbuffer[ip+1].x, pointbuffer[ip+1].y, x2, y2 ) );
1112  }
1113  }
1114  }
1115 }
1116 
1117 
1119 {
1120  return Mils2iu( 20 );
1121 }
1122 
1123 
1125 {
1126  return add_zone_xpm;
1127 }
1128 
1129 
1131 {
1132  assert( aImage->Type() == PCB_ZONE_AREA_T );
1133 
1134  std::swap( *((ZONE_CONTAINER*) this), *((ZONE_CONTAINER*) aImage) );
1135 }
1136 
1137 
1139 {
1140  for( std::pair<const PCB_LAYER_ID, SHAPE_POLY_SET>& pair : m_FilledPolysList )
1141  pair.second.CacheTriangulation();
1142 }
1143 
1144 
1145 bool ZONE_CONTAINER::IsIsland( PCB_LAYER_ID aLayer, int aPolyIdx )
1146 {
1147  if( GetNetCode() < 1 )
1148  return true;
1149 
1150  if( !m_insulatedIslands.count( aLayer ) )
1151  return false;
1152 
1153  return m_insulatedIslands.at( aLayer ).count( aPolyIdx );
1154 }
1155 
1156 
1157 /*
1158  * Some intersecting zones, despite being on the same layer with the same net, cannot be
1159  * merged due to other parameters such as fillet radius. The copper pour will end up
1160  * effectively merged though, so we want to keep the corners of such intersections sharp.
1161  */
1162 void ZONE_CONTAINER::GetColinearCorners( BOARD* aBoard, std::set<VECTOR2I>& aCorners )
1163 {
1164  int epsilon = Millimeter2iu( 0.001 );
1165 
1166  // Things get messy when zone of different nets intersect. To do it right we'd need to
1167  // run our colinear test with the final filled regions rather than the outline regions.
1168  // However, since there's no order dependance the only way to do that is to iterate
1169  // through successive zone fills until the results are no longer changing -- and that's
1170  // not going to happen. So we punt and ignore any "messy" corners.
1171  std::set<VECTOR2I> colinearCorners;
1172  std::set<VECTOR2I> messyCorners;
1173 
1174  for( ZONE_CONTAINER* candidate : aBoard->Zones() )
1175  {
1176  if( candidate == this )
1177  continue;
1178 
1179  if( candidate->GetLayerSet() != GetLayerSet() )
1180  continue;
1181 
1182  if( candidate->GetIsKeepout() != GetIsKeepout() )
1183  continue;
1184 
1185  for( auto iter = m_Poly->CIterate(); iter; iter++ )
1186  {
1187  if( candidate->m_Poly->Collide( iter.Get(), epsilon ) )
1188  {
1189  if( candidate->GetNetCode() == GetNetCode() )
1190  colinearCorners.insert( VECTOR2I( iter.Get() ) );
1191  else
1192  messyCorners.insert( VECTOR2I( iter.Get() ) );
1193  }
1194  }
1195  }
1196 
1197  for( VECTOR2I corner : colinearCorners )
1198  {
1199  if( messyCorners.count( corner ) == 0 )
1200  aCorners.insert( corner );
1201  }
1202 }
1203 
1204 
1206  std::set<VECTOR2I>* aPreserveCorners ) const
1207 {
1208  if( GetNumCorners() <= 2 ) // malformed zone. polygon calculations do not like it ...
1209  return false;
1210 
1211  // Make a smoothed polygon out of the user-drawn polygon if required
1212  switch( m_cornerSmoothingType )
1213  {
1215  aSmoothedPoly = m_Poly->Chamfer( m_cornerRadius, aPreserveCorners );
1216  break;
1217 
1219  {
1220  auto board = GetBoard();
1221  int maxError = ARC_HIGH_DEF;
1222 
1223  if( board )
1224  maxError = board->GetDesignSettings().m_MaxError;
1225 
1226  aSmoothedPoly = m_Poly->Fillet( m_cornerRadius, maxError, aPreserveCorners );
1227  break;
1228  }
1229  default:
1230  // Acute angles between adjacent edges can create issues in calculations,
1231  // in inflate/deflate outlines transforms, especially when the angle is very small.
1232  // We can avoid issues by creating a very small chamfer which remove acute angles,
1233  // or left it without chamfer and use only CPOLYGONS_LIST::InflateOutline to create
1234  // clearance areas
1235  aSmoothedPoly = m_Poly->Chamfer( Millimeter2iu( 0.0 ), aPreserveCorners );
1236  break;
1237  }
1238 
1239  return true;
1240 };
1241 
1242 
1244 {
1245  m_area = 0.0;
1246 
1247  // Iterate over each outline polygon in the zone and then iterate over
1248  // each hole it has to compute the total area.
1249  for( std::pair<const PCB_LAYER_ID, SHAPE_POLY_SET>& pair : m_FilledPolysList )
1250  {
1251  SHAPE_POLY_SET& poly = pair.second;
1252 
1253  for( int i = 0; i < poly.OutlineCount(); i++ )
1254  {
1255  m_area += poly.Outline( i ).Area();
1256 
1257  for( int j = 0; j < poly.HoleCount( i ); j++ )
1258  {
1259  m_area -= poly.Hole( i, j ).Area();
1260  }
1261  }
1262  }
1263 
1264  return m_area;
1265 }
1266 
1267 
1268 /* Function TransformOutlinesShapeWithClearanceToPolygon
1269  * Convert the zone filled areas polygons to polygons
1270  * inflated (optional) by max( aClearanceValue, the zone clearance)
1271  * and copy them in aCornerBuffer
1272  * @param aClearance the clearance around outlines
1273  * @param aPreserveCorners an optional set of corners which should not be chamfered/filleted
1274  */
1276  int aClearance, std::set<VECTOR2I>* aPreserveCorners ) const
1277 {
1278  // Creates the zone outline polygon (with holes if any)
1279  SHAPE_POLY_SET polybuffer;
1280  BuildSmoothedPoly( polybuffer, aPreserveCorners );
1281 
1282  // Calculate the polygon with clearance
1283  // holes are linked to the main outline, so only one polygon is created.
1284  if( aClearance )
1285  {
1286  BOARD* board = GetBoard();
1287  int maxError = ARC_HIGH_DEF;
1288 
1289  if( board )
1290  maxError = board->GetDesignSettings().m_MaxError;
1291 
1292  int segCount = std::max( GetArcToSegmentCount( aClearance, maxError, 360.0 ), 3 );
1293  polybuffer.Inflate( aClearance, segCount );
1294  }
1295 
1296  polybuffer.Fracture( SHAPE_POLY_SET::PM_FAST );
1297  aCornerBuffer.Append( polybuffer );
1298 }
1299 
1300 //
1301 /********* MODULE_ZONE_CONTAINER **************/
1302 //
1304  ZONE_CONTAINER( aParent, true )
1305 {
1306  // in a footprint, net classes are not managed.
1307  // so set the net to NETINFO_LIST::ORPHANED_ITEM
1308  SetNetCode( -1, true );
1309 }
1310 
1311 
1313  : ZONE_CONTAINER( aZone.GetParent(), true )
1314 {
1315  InitDataFromSrcInCopyCtor( aZone );
1316 }
1317 
1318 
1320 {
1321  ZONE_CONTAINER::operator=( aOther );
1322  return *this;
1323 }
1324 
1325 
1327 {
1328  return new MODULE_ZONE_CONTAINER( *this );
1329 }
1330 
1331 
1332 unsigned int MODULE_ZONE_CONTAINER::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
1333 {
1334  const int HIDE = std::numeric_limits<unsigned int>::max();
1335 
1336  if( !aView )
1337  return 0;
1338 
1339  bool flipped = GetParent() && GetParent()->GetLayer() == B_Cu;
1340 
1341  // Handle Render tab switches
1342  if( !flipped && !aView->IsLayerVisible( LAYER_MOD_FR ) )
1343  return HIDE;
1344 
1345  if( flipped && !aView->IsLayerVisible( LAYER_MOD_BK ) )
1346  return HIDE;
1347 
1348  // Other layers are shown without any conditions
1349  return 0;
1350 }
1351 
1352 
1353 static struct ZONE_CONTAINER_DESC
1354 {
1356  {
1360  propMgr.AddProperty( new PROPERTY<ZONE_CONTAINER, int>( _( "Clearance" ),
1362  propMgr.AddProperty( new PROPERTY<ZONE_CONTAINER, unsigned>( _( "Priority" ),
1364  //propMgr.AddProperty( new PROPERTY<ZONE_CONTAINER, bool>( "Filled",
1365  //&ZONE_CONTAINER::SetIsFilled, &ZONE_CONTAINER::IsFilled ) );
1366  propMgr.AddProperty( new PROPERTY<ZONE_CONTAINER, int>( _( "Min Thickness" ),
1368  // TODO pad connection, thermal relief gap, thermal relief copper bridge
1369  }
void SetDoNotAllowTracks(bool aEnable)
Definition: class_zone.h:732
int TotalVertices() const
Returns total number of vertices stored in the set.
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:712
void MoveEdge(const wxPoint &offset, int aEdge)
Function MoveEdge Move the outline Edge.
Definition: class_zone.cpp:729
EDA_UNITS
Definition: common.h:198
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:935
bool GetDoNotAllowPads() const
Definition: class_zone.h:717
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:61
void SetHatch(ZONE_HATCH_STYLE aHatchStyle, int aHatchPitch, bool aRebuildHatch)
Function SetHatch sets all hatch parameters for the zone.
Definition: class_zone.cpp:925
virtual void SwapData(BOARD_ITEM *aImage) override
Swap data between aItem and aImage.
int m_ZoneClearance
Clearance value in internal units.
Definition: class_zone.h:857
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:784
static PROPERTY_MANAGER & Instance()
Definition: property_mgr.h:61
#define TYPE_HASH(x)
Macro to generate unique identifier for a type
Definition: property.h:53
LSET FlipLayerMask(LSET aMask, int aCopperLayersCount)
Calculate the mask layer when flipping a footprint BACK and FRONT copper layers, mask,...
Definition: lset.cpp:531
int GetNetCode() const
Function GetNetCode.
ISLAND_REMOVAL_MODE m_islandRemovalMode
Definition: class_zone.h:861
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:100
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Function GetLayerName returns the name of a layer.
PNG memory record (file in memory).
Definition: bitmap_def.h:29
bool m_doNotAllowPads
Definition: class_zone.h:853
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:220
int GetThermalReliefCopperBridge(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:326
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:174
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:852
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox (virtual)
Definition: class_zone.cpp:307
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:411
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:909
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:301
NETCLASS * GetNetClass() const
Function GetNetClassPtr returns the NETCLASS for this item.
void SetDoNotAllowFootprints(bool aEnable)
Definition: class_zone.h:734
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:445
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Function FlippedLayerNumber.
Definition: lset.cpp:485
bool IsEmpty() const
Returns true if the set is empty (no polygons at all)
class ZONE_CONTAINER, a zone area
Definition: typeinfo.h:102
ZONE_CONTAINER(BOARD_ITEM_CONTAINER *parent, bool aInModule=false)
The ctor to build ZONE_CONTAINER, but comaptible with MODULE_ZONE_CONTAINER requirement.
Definition: class_zone.cpp:39
virtual PCB_LAYER_ID GetLayer() const override
Function GetLayer returns the primary layer this item is on.
Definition: class_zone.cpp:208
Definition: color4d.h:61
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:867
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
Function GetDesignSettings.
Definition: class_board.h:553
MODULE_ZONE_CONTAINER(BOARD_ITEM_CONTAINER *aParent)
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:44
void RemoveCutout(int aOutlineIdx, int aHoleIdx)
Remove a cutout from the zone.
Definition: class_zone.cpp:822
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:938
int GetThermalReliefGap(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:317
The base class for create windows for drawing purpose.
VECTOR2< int > VECTOR2I
Definition: vector2d.h:594
int GetThermalGap() const
Definition: class_pad.cpp:722
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Function Seq returns an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:377
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:244
bool Contains(const wxPoint &aPoint) const
Function Contains.
static int GetDefaultHatchPitch()
Function GetDefaultHatchPitchMils.
struct SHAPE_POLY_SET::VERTEX_INDEX VERTEX_INDEX
Struct VERTEX_INDEX.
bool m_doNotAllowFootprints
Definition: class_zone.h:854
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:731
bool GetDoNotAllowVias() const
Definition: class_zone.h:715
Classes used in Pcbnew, CvPcb and GerbView.
ZONE_CONNECTION m_PadConnection
Definition: class_zone.h:856
void SetPriority(unsigned aPriority)
Function SetPriority.
Definition: class_zone.h:100
show modules 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 "layer mask", which is a bitmap of all layers on which the TRACK segme...
Definition: class_zone.cpp:284
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
void SetLayerSet(LSET aLayerSet)
Definition: class_zone.cpp:236
void MIRROR(T &aPoint, const T &aMirrorRef)
Definition: macros.h:175
void GetColinearCorners(BOARD *aBoard, std::set< VECTOR2I > &colinearCorners)
Some intersecting zones, despite being on the same layer with the same net, cannot be merged due to o...
#define MAXPTS
void SetClosed(bool aClosed)
Function SetClosed()
bool sortEndsByDescendingX(const VECTOR2I &ref, const VECTOR2I &tst)
Definition: class_zone.cpp:949
int m_HatchFillTypeSmoothingLevel
Grid pattern smoothing type, similar to corner smoothing type 0 = no smoothing, 1 = fillet,...
Definition: class_zone.h:902
wxString m_zoneName
An optional unique name for this zone, used for identifying it in DRC checking.
Definition: class_zone.h:832
#define DISALLOW_MICRO_VIAS
PCB_LAYER_ID
A quick note on layer IDs:
Display value expressed in distance units (mm/inch)
Definition: property.h:47
LSET is a set of PCB_LAYER_IDs.
int m_ThermalReliefCopperBridge
Definition: class_zone.h:882
std::vector< SEG > m_HatchLines
Definition: class_zone.h:935
#define NULL
void Move(const VECTOR2I &aVector) override
ZONE_CONTAINER & operator=(const ZONE_CONTAINER &aOther)
Definition: class_zone.cpp:83
unsigned int ViewGetLOD(int aLayer, KIGFX::VIEW *aView) const override
Function ViewGetLOD() Returns the level of detail (LOD) of the item.
ITERATOR IterateWithHoles(int aOutline)
Function IterateWithHoles.
SHAPE_POLY_SET.
double m_HatchFillTypeOrientation
Grid style shape: orientation in degrees of the grid lines.
Definition: class_zone.h:898
SHAPE_LINE_CHAIN & Outline(int aIndex)
Returns the reference to aIndex-th outline in the set
bool BuildSmoothedPoly(SHAPE_POLY_SET &aSmoothedPoly, std::set< VECTOR2I > *aPreserveCorners) const
Function GetSmoothedPoly returns a pointer to the corner-smoothed version of m_Poly.
bool m_IsFilled
True when a zone was filled, false after deleting the filled areas.
Definition: class_zone.h:870
DRC_RULE * GetRule(const BOARD_ITEM *aItem, const BOARD_ITEM *bItem, int aConstraint)
int GetThermalWidth() const
Definition: class_pad.cpp:711
ZONE_HATCH_STYLE m_hatchStyle
Definition: class_zone.h:933
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:827
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:420
virtual BOARD * GetBoard() const
Function GetBoard returns the BOARD in which this BOARD_ITEM resides, or NULL if none.
#define DISALLOW_ZONES
bool GetDoNotAllowCopperPour() const
Definition: class_zone.h:714
unsigned m_priority
Definition: class_zone.h:840
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declares an inheritance relationship between types.
void Rotate(const wxPoint &centre, double angle) override
Function Rotate Move the outlines.
Definition: class_zone.cpp:744
bool m_doNotAllowVias
Definition: class_zone.h:851
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Function SetLayer sets the layer this item is on.
Definition: class_zone.cpp:228
bool UnFill()
Function UnFill Removes the zone filling.
Definition: class_zone.cpp:180
const wxString & GetNetname() const
Function GetNetname.
Definition: netinfo.h:231
int m_cornerSmoothingType
Definition: class_zone.h:828
std::map< PCB_LAYER_ID, SHAPE_POLY_SET > m_RawPolysList
Definition: class_zone.h:928
int GetNumCorners(void) const
Access to m_Poly parameters.
Definition: class_zone.h:483
void CacheTriangulation()
(re)create a list of triangles that "fill" the solid areas.
void TransformOutlinesShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, int aMinClearanceValue, std::set< VECTOR2I > *aPreserveCorners=nullptr) const
Function TransformOutlinesShapeWithClearanceToPolygon Convert the outlines shape to a polygon with no...
double m_HatchFillTypeSmoothingValue
Grid pattern smoothing value for smoothing shape size calculations this is the ratio between the gap ...
Definition: class_zone.h:906
a few functions useful in geometry calculations.
int GetLocalClearance(wxString *aSource=nullptr) const override
Function GetLocalClearance returns any local clearances set in the "classic" (ie: pre-rule) system.
Definition: class_zone.cpp:519
void SetZoneClearance(int aZoneClearance)
Definition: class_zone.h:197
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:290
ZONE_CONNECTION GetPadConnection(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:813
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:931
void ExportSetting(ZONE_CONTAINER &aTarget, bool aFullExport=true) const
Function ExportSetting copy settings to a given zone.
virtual const ZONE_SETTINGS & GetZoneSettings() const
Fetch the zone settings for this container.
void SetDoNotAllowPads(bool aEnable)
Definition: class_zone.h:733
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:59
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:851
EDA_ITEM & operator=(const EDA_ITEM &aItem)
Operator assignment is used to assign the members of aItem to another object.
#define DISALLOW_VIAS
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:241
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
wxPoint GetPosition() const override
Definition: class_zone.cpp:202
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:713
unsigned int m_cornerRadius
Definition: class_zone.h:829
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
wxString GetNetnameMsg() const
Function GetNetnameMsg.
ZONE_CONNECTION GetEffectiveZoneConnection() const
Return the zone connection in effect (either locally overridden or overridden in the parent module).
Definition: class_pad.cpp:700
void Move(const wxPoint &offset) override
Function Move Move the outlines.
Definition: class_zone.cpp:708
int GetKeepouts(std::map< int, wxString > *aSources=nullptr) const
Return a bitset of flags for keepouts.
Definition: class_zone.cpp:335
virtual int GetClearance(BOARD_ITEM *aItem=nullptr, wxString *aSource=nullptr) const
Function GetClearance returns the clearance in internal units.
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:888
SHAPE_POLY_SET Fillet(int aRadius, int aErrorMax, std::set< VECTOR2I > *aPreserveCorners=nullptr)
Function Fillet returns a filleted version of the polygon set.
Definition: seg.h:39
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.
wxString MessageTextFromValue(EDA_UNITS aUnits, int aValue, bool aUseMils, EDA_DATA_TYPE aType)
Definition: base_units.cpp:124
void AccumulateDescription(wxString &aDesc, const wxString &aItem)
Utility to build comma separated lists in messages.
Definition: macros.h:126
void SetDoNotAllowCopperPour(bool aEnable)
Definition: class_zone.h:730
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
#define DISALLOW_CONSTRAINT
bool m_doNotAllowCopperPour
Definition: class_zone.h:850
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:917
Definition: color4d.h:56
double CalculateFilledArea()
Compute the area currently occupied by the zone fill.
int m_ThermalReliefGap
Width of the copper bridge in thermal reliefs.
Definition: class_zone.h:879
int m_ZoneMinThickness
Minimum thickness value in filled areas.
Definition: class_zone.h:858
ZONE_CONTAINERS & Zones()
Definition: class_board.h:280
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:889
unsigned GetPriority() const
Function GetPriority.
Definition: class_zone.h:106
#define DISALLOW_PADS
MODULE_ZONE_CONTAINER & operator=(const MODULE_ZONE_CONTAINER &aOther)
void UnHatch()
Function UnHatch clears the zone's hatch.
Definition: class_zone.cpp:941
ZONE_HATCH_STYLE
Zone hatch styles.
Definition: zone_settings.h:46
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:205
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
BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:180
#define _(s)
Definition: 3d_actions.cpp:33
SHAPE_LINE_CHAIN.
int m_HatchFillTypeThickness
Grid style shape: thickness of lines (if 0 -> solid shape)
Definition: class_zone.h:892
NETINFO_ITEM * m_netinfo
Stores all informations about the net that item belongs to.
wxString UnescapeString(const wxString &aSource)
Definition: string.cpp:125
#define DISALLOW_FOOTPRINTS
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:547
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
STATUS_FLAGS m_Flags
Definition: base_struct.h:176
void AddProperty(PROPERTY_BASE *aProperty)
Registers a property.
int GetCopperLayerCount() const
Function GetCopperLayerCount.
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:218
SHAPE_POLY_SET Chamfer(int aDistance, std::set< VECTOR2I > *aPreserveCorners=nullptr)
Function Chamfer returns a chamfered version of the polygon set.
NETCLASS * GetDefault() const
Function GetDefault.
PCB_EDIT_FRAME is the main frame for Pcbnew.
void Hatch()
Function Hatch computes the hatch lines depending on the hatch parameters and stores it in the zone's...
Definition: class_zone.cpp:955
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
int GetHatchPitch() const
Hatch related methods.
Definition: class_zone.cpp:919
EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boards.
Definition: base_struct.h:159
void SetLocalFlags(int aFlags)
Definition: class_zone.h:262
MODULE_ZONE_CONTAINER is the same item as ZONE_CONTAINER, but with a specific type id ZONE_CONTAINER ...
Definition: class_zone.h:957
int GetMinThickness() const
Definition: class_zone.h:206
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:531
bool Intersects(const EDA_RECT &aRect) const
Function Intersects tests for a common area between rectangles.
bool GetDoNotAllowTracks() const
Definition: class_zone.h:716
#define DISALLOW_BB_VIAS
bool GetDoNotAllowFootprints() const
Definition: class_zone.h:718
const BITMAP_OPAQUE add_zone_xpm[1]
Definition: add_zone.cpp:74
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:868
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const
Function PointInside()
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:459
Provides class metadata.
Definition: property_mgr.h:58
bool m_needRefill
False when a zone was refilled, true after changes in zone params.
Definition: class_zone.h:876
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:572
bool IsClosed() const
Function IsClosed()
Abstract interface for BOARD_ITEMs capable of storing other items inside.
int GetZoneClearance() const
Definition: class_zone.h:196
class ZONE_CONTAINER, managed by a footprint
Definition: typeinfo.h:95
EDA_MSG_ITEM is used EDA_MSG_PANEL as the item type for displaying messages.
Definition: msgpanel.h:53
int m_HatchFillTypeGap
Grid style shape: dist between center of lines (grid size) (0 -> solid shape)
Definition: class_zone.h:895
VIEW.
Definition: view.h:61
void SetIsKeepout(bool aEnable)
Definition: class_zone.h:729
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: base_struct.h:175
void SetMinThickness(int aMinThickness)
Definition: class_zone.h:207
static constexpr int Millimeter2iu(double mm)
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
#define DISALLOW_HOLES
const BOX2I BBox(int aClearance=0) const override
Function BBox()
#define DISALLOW_GRAPHICS
const VECTOR2I & GetCornerPosition(int aCornerIndex) const
Definition: class_zone.h:523
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
#define DISALLOW_TRACKS
virtual void Flip(const wxPoint &aCentre, bool aFlipLeftRight) override
Function Flip Flip this object, i.e.
Definition: class_zone.cpp:772
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:214
#define DISALLOW_TEXTS
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
int GetLocalFlags() const
Definition: class_zone.h:261
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
bool m_FilledPolysUseThickness
outline of filled polygons have thickness.
Definition: class_zone.h:859
KICAD_T Type() const
Function Type()
Definition: base_struct.h:193
bool IsLayerVisible(int aLayer) const
Function IsLayerVisible() Returns information about visibility of a particular layer.
Definition: view.h:416
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:927
VECTOR2I B
Definition: seg.h:48
void SetNeedRefill(bool aNeedRefill)
Definition: class_zone.h:194