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-2017 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 
31 #include <fctsys.h>
32 #include <trigo.h>
33 #include <pcb_screen.h>
34 #include <class_drawpanel.h>
35 #include <kicad_string.h>
36 #include <richio.h>
37 #include <macros.h>
38 #include <pcb_base_frame.h>
39 #include <msgpanel.h>
40 #include <bitmaps.h>
41 
42 #include <convert_to_biu.h>
43 #include <class_board.h>
44 #include <class_zone.h>
45 
46 #include <pcbnew.h>
47 #include <zones.h>
48 #include <math_for_graphics.h>
50 
51 
54 {
55  m_CornerSelection = nullptr; // no corner is selected
56  m_IsFilled = false; // fill status : true when the zone is filled
60  m_hv45 = false;
61  m_priority = 0;
63  SetIsKeepout( false );
64  SetDoNotAllowCopperPour( false ); // has meaning only if m_isKeepout == true
65  SetDoNotAllowVias( true ); // has meaning only if m_isKeepout == true
66  SetDoNotAllowTracks( true ); // has meaning only if m_isKeepout == true
67  m_cornerRadius = 0;
68  SetLocalFlags( 0 ); // flags tempoarry used in zone calculations
69  m_Poly = new SHAPE_POLY_SET(); // Outlines
70  aBoard->GetZoneSettings().ExportSetting( *this );
71 }
72 
73 
75  BOARD_CONNECTED_ITEM( aZone )
76 {
77  // Should the copy be on the same net?
78  SetNetCode( aZone.GetNetCode() );
79  m_Poly = new SHAPE_POLY_SET( *aZone.m_Poly );
80 
81  // For corner moving, corner index to drag, or nullptr if no selection
82  m_CornerSelection = nullptr;
83  m_IsFilled = aZone.m_IsFilled;
84  m_ZoneClearance = aZone.m_ZoneClearance; // clearance value
86  m_FillMode = aZone.m_FillMode; // Filling mode (segments/polygons)
87  m_hv45 = aZone.m_hv45;
88  m_priority = aZone.m_priority;
94  m_FillSegmList = aZone.m_FillSegmList; // vector <> copy
95 
96  m_isKeepout = aZone.m_isKeepout;
100 
103 
104  m_hatchStyle = aZone.m_hatchStyle;
105  m_hatchPitch = aZone.m_hatchPitch;
106  m_HatchLines = aZone.m_HatchLines;
107 
108  SetLayerSet( aZone.GetLayerSet() );
109  SetLocalFlags( aZone.GetLocalFlags() );
110 }
111 
112 
114 {
116 
117  // Replace the outlines for aOther outlines.
118  delete m_Poly;
119  m_Poly = new SHAPE_POLY_SET( *aOther.m_Poly );
120 
121  m_CornerSelection = nullptr; // for corner moving, corner index to (null if no selection)
122  m_ZoneClearance = aOther.m_ZoneClearance; // clearance value
124  m_FillMode = aOther.m_FillMode; // filling mode (segments/polygons)
129  SetHatchStyle( aOther.GetHatchStyle() );
130  SetHatchPitch( aOther.GetHatchPitch() );
131  m_HatchLines = aOther.m_HatchLines; // copy vector <SEG>
134  m_FillSegmList.clear();
136 
137  SetLayerSet( aOther.GetLayerSet() );
138 
139  return *this;
140 }
141 
142 
144 {
145  delete m_Poly;
146  delete m_CornerSelection;
147 }
148 
149 
151 {
152  return new ZONE_CONTAINER( *this );
153 }
154 
155 
157 {
158  bool change = ( !m_FilledPolysList.IsEmpty() ) ||
159  ( m_FillSegmList.size() > 0 );
160 
162  m_FillSegmList.clear();
163  m_IsFilled = false;
164 
165  return change;
166 }
167 
168 
170 {
171  return (wxPoint) GetCornerPosition( 0 );
172 }
173 
174 
176 {
177  return BOARD_ITEM::GetLayer();
178 }
179 
180 
182 {
183  if( GetIsKeepout() )
184  {
185  return ( m_layerSet & LSET::AllCuMask() ).count() > 0;
186  }
187  else
188  {
189  return IsCopperLayer( GetLayer() );
190  }
191 }
192 
193 
194 bool ZONE_CONTAINER::CommonLayerExists( const LSET aLayerSet ) const
195 {
196  LSET common = GetLayerSet() & aLayerSet;
197 
198  return common.count() > 0;
199 }
200 
201 
203 {
204  SetLayerSet( LSET( aLayer ) );
205 
206  m_Layer = aLayer;
207 }
208 
209 
211 {
212  if( GetIsKeepout() )
213  {
214  // Keepouts can only exist on copper layers
215  aLayerSet &= LSET::AllCuMask();
216  }
217 
218  if( aLayerSet.count() == 0 )
219  {
220  return;
221  }
222 
223  m_layerSet = aLayerSet;
224 
225  // Set the single layer to the first selected layer
226  m_Layer = aLayerSet.Seq()[0];
227 }
228 
229 
231 {
232  // TODO - Enable multi-layer zones for all zone types
233  // not just keepout zones
234  if( GetIsKeepout() )
235  {
236  return m_layerSet;
237  }
238  else
239  {
240  return LSET( m_Layer );
241  }
242 }
243 
244 void ZONE_CONTAINER::ViewGetLayers( int aLayers[], int& aCount ) const
245 {
246  if( GetIsKeepout() )
247  {
248  LSEQ layers = m_layerSet.Seq();
249 
250  for( unsigned int idx = 0; idx < layers.size(); idx++ )
251  {
252  aLayers[idx] = layers[idx];
253  }
254 
255  aCount = layers.size();
256  }
257  else
258  {
259  aLayers[0] = m_Layer;
260  aCount = 1;
261  }
262 }
263 
264 
266 {
267  if( GetIsKeepout() )
268  {
269  return m_layerSet.test( aLayer );
270  }
271 
272  return BOARD_ITEM::IsOnLayer( aLayer );
273 }
274 
275 
276 void ZONE_CONTAINER::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, GR_DRAWMODE aDrawMode,
277  const wxPoint& offset )
278 {
279  if( !DC )
280  return;
281 
282  wxPoint seg_start, seg_end;
283  PCB_LAYER_ID curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer;
284  BOARD* brd = GetBoard();
285 
286  auto frame = static_cast<PCB_BASE_FRAME*> ( panel->GetParent() );
287 
288  PCB_LAYER_ID draw_layer = UNDEFINED_LAYER;
289 
290  LSET layers = GetLayerSet() & brd->GetVisibleLayers();
291 
292  // If there are no visible layers and the zone is not highlighted, return
293  if( layers.count() == 0 && !( aDrawMode & GR_HIGHLIGHT ) )
294  {
295  return;
296  }
297 
298  /* Keepout zones can exist on multiple layers
299  * Thus, determining which color to use to render them is a bit tricky.
300  * In descending order of priority:
301  *
302  * 1. If in GR_HIGHLIGHT mode:
303  * a. If zone is on selected layer, use layer color!
304  * b. Else, use grey
305  * 1. Not in GR_HIGHLIGHT mode
306  * a. If zone is on selected layer, use layer color
307  * b. Else, use color of top-most (visible) layer
308  *
309  */
310  if( GetIsKeepout() )
311  {
312  // At least one layer must be provided!
313  assert( GetLayerSet().count() > 0 );
314 
315  // Not on any visible layer?
316  if( layers.count() == 0 && !( aDrawMode & GR_HIGHLIGHT ) )
317  {
318  return;
319  }
320 
321  // Is keepout zone present on the selected layer?
322  if( layers.test( curr_layer ) )
323  {
324  draw_layer = curr_layer;
325  }
326  else
327  {
328  // Select the first (top) visible layer
329  if( layers.count() > 0 )
330  {
331  draw_layer = layers.Seq()[0];
332  }
333  else
334  {
335  draw_layer = GetLayerSet().Seq()[0];
336  }
337  }
338 
339  }
340  /* Non-keepout zones are easier to deal with
341  */
342  else
343  {
344  if( brd->IsLayerVisible( GetLayer() ) == false && !( aDrawMode & GR_HIGHLIGHT ) )
345  {
346  return;
347  }
348 
349  draw_layer = GetLayer();
350  }
351 
352  assert( draw_layer != UNDEFINED_LAYER );
353 
354  auto color = frame->Settings().Colors().GetLayerColor( draw_layer );
355 
356  GRSetDrawMode( DC, aDrawMode );
357  auto displ_opts = (PCB_DISPLAY_OPTIONS*)( panel->GetDisplayOptions() );
358 
359  if( displ_opts->m_ContrastModeDisplay )
360  {
361  if( !IsOnLayer( curr_layer ) )
362  {
364  }
365  }
366 
367  if( ( aDrawMode & GR_HIGHLIGHT ) && !( aDrawMode & GR_AND ) )
368  {
369  color.SetToLegacyHighlightColor();
370  }
371 
372  color.a = 0.588;
373 
374  // draw the lines
375  std::vector<wxPoint> lines;
376  lines.reserve( (GetNumCorners() * 2) + 2 );
377 
378  // Iterate through the segments of the outline
379  for( auto iterator = m_Poly->IterateSegmentsWithHoles(); iterator; iterator++ )
380  {
381  // Create the segment
382  SEG segment = *iterator;
383 
384  lines.push_back( static_cast<wxPoint>( segment.A ) + offset );
385  lines.push_back( static_cast<wxPoint>( segment.B ) + offset );
386  }
387 
388  GRLineArray( panel->GetClipBox(), DC, lines, 0, color );
389 
390  // draw hatches
391  lines.clear();
392  lines.reserve( (m_HatchLines.size() * 2) + 2 );
393 
394  for( unsigned ic = 0; ic < m_HatchLines.size(); ic++ )
395  {
396  seg_start = static_cast<wxPoint>( m_HatchLines[ic].A ) + offset;
397  seg_end = static_cast<wxPoint>( m_HatchLines[ic].B ) + offset;
398  lines.push_back( seg_start );
399  lines.push_back( seg_end );
400  }
401 
402  GRLineArray( panel->GetClipBox(), DC, lines, 0, color );
403 }
404 
405 
407  wxDC* DC, GR_DRAWMODE aDrawMode, const wxPoint& offset )
408 {
409 
410  static std::vector <wxPoint> CornersBuffer;
411  auto displ_opts = (PCB_DISPLAY_OPTIONS*)( panel->GetDisplayOptions() );
412 
413  // outline_mode is false to show filled polys,
414  // and true to show polygons outlines only (test and debug purposes)
415  bool outline_mode = displ_opts->m_DisplayZonesMode == 2 ? true : false;
416 
417  if( DC == NULL )
418  return;
419 
420  if( displ_opts->m_DisplayZonesMode == 1 ) // Do not show filled areas
421  return;
422 
423  if( m_FilledPolysList.IsEmpty() ) // Nothing to draw
424  return;
425 
426  BOARD* brd = GetBoard();
427  PCB_LAYER_ID curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer;
428 
429  auto frame = static_cast<PCB_BASE_FRAME*> ( panel->GetParent() );
430  auto color = frame->Settings().Colors().GetLayerColor( GetLayer() );
431 
432  if( brd->IsLayerVisible( GetLayer() ) == false && !( aDrawMode & GR_HIGHLIGHT ) )
433  return;
434 
435  GRSetDrawMode( DC, aDrawMode );
436 
437  if( displ_opts->m_ContrastModeDisplay )
438  {
439  if( !IsOnLayer( curr_layer ) )
441  }
442 
443  if( ( aDrawMode & GR_HIGHLIGHT ) && !( aDrawMode & GR_AND ) )
444  color.SetToLegacyHighlightColor();
445 
446  color.a = 0.588;
447 
448 
449  for ( int ic = 0; ic < m_FilledPolysList.OutlineCount(); ic++ )
450  {
451  const SHAPE_LINE_CHAIN& path = m_FilledPolysList.COutline( ic );
452 
453  CornersBuffer.clear();
454 
455  wxPoint p0;
456 
457  for( int j = 0; j < path.PointCount(); j++ )
458  {
459  const VECTOR2I& corner = path.CPoint( j );
460 
461  wxPoint coord( corner.x + offset.x, corner.y + offset.y );
462 
463  if( j == 0 )
464  p0 = coord;
465 
466  CornersBuffer.push_back( coord );
467  }
468 
469  CornersBuffer.push_back( p0 );
470 
471  // Draw outlines:
472  if( ( m_ZoneMinThickness > 1 ) || outline_mode )
473  {
474  int ilim = CornersBuffer.size() - 1;
475 
476  for( int is = 0, ie = ilim; is <= ilim; ie = is, is++ )
477  {
478  int x0 = CornersBuffer[is].x;
479  int y0 = CornersBuffer[is].y;
480  int x1 = CornersBuffer[ie].x;
481  int y1 = CornersBuffer[ie].y;
482 
483  // Draw only basic outlines, not extra segments.
484  if( !displ_opts->m_DisplayPcbTrackFill || GetState( FORCE_SKETCH ) )
485  GRCSegm( panel->GetClipBox(), DC,
486  x0, y0, x1, y1,
488  else
489  GRFillCSegm( panel->GetClipBox(), DC,
490  x0, y0, x1, y1, m_ZoneMinThickness, color );
491  }
492  }
493 
494  // Draw areas:
495  if( m_FillMode == ZFM_POLYGONS && !outline_mode )
496  GRPoly( panel->GetClipBox(), DC, CornersBuffer.size(), &CornersBuffer[0],
497  true, 0, color, color );
498  }
499 
500  if( m_FillMode == 1 && !outline_mode ) // filled with segments
501  {
502  for( unsigned ic = 0; ic < m_FillSegmList.size(); ic++ )
503  {
504  wxPoint start = (wxPoint) ( m_FillSegmList[ic].A + VECTOR2I(offset) );
505  wxPoint end = (wxPoint) ( m_FillSegmList[ic].B + VECTOR2I(offset) );
506 
507  if( !displ_opts->m_DisplayPcbTrackFill || GetState( FORCE_SKETCH ) )
508  GRCSegm( panel->GetClipBox(), DC, start.x, start.y, end.x, end.y,
510  else
511  GRFillCSegm( panel->GetClipBox(), DC, start.x, start.y, end.x, end.y,
513  }
514  }
515 }
516 
517 
519 {
520  const int PRELOAD = 0x7FFFFFFF; // Biggest integer (32 bits)
521 
522  int ymax = -PRELOAD;
523  int ymin = PRELOAD;
524  int xmin = PRELOAD;
525  int xmax = -PRELOAD;
526 
527  int count = GetNumCorners();
528 
529  for( int i = 0; i<count; ++i )
530  {
531  wxPoint corner = static_cast<wxPoint>( GetCornerPosition( i ) );
532 
533  ymax = std::max( ymax, corner.y );
534  xmax = std::max( xmax, corner.x );
535  ymin = std::min( ymin, corner.y );
536  xmin = std::min( xmin, corner.x );
537  }
538 
539  EDA_RECT ret( wxPoint( xmin, ymin ), wxSize( xmax - xmin + 1, ymax - ymin + 1 ) );
540 
541  return ret;
542 }
543 
544 
546  GR_DRAWMODE draw_mode )
547 {
548  GR_DRAWMODE current_gr_mode = draw_mode;
549  bool is_close_segment = false;
550 
551  if( !DC )
552  return;
553 
554  PCB_LAYER_ID curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer;
555 
556  auto frame = static_cast<PCB_BASE_FRAME*> ( panel->GetParent() );
557  auto color = frame->Settings().Colors().GetLayerColor( GetLayer() );
558 
559  auto displ_opts = (PCB_DISPLAY_OPTIONS*)( panel->GetDisplayOptions() );
560 
561  if( displ_opts->m_ContrastModeDisplay )
562  {
563  if( !IsOnLayer( curr_layer ) )
565  }
566 
567  // Object to iterate through the corners of the outlines
569 
570  // Segment start and end
571  VECTOR2I seg_start, seg_end;
572 
573  // Remember the first point of this contour
574  VECTOR2I contour_first_point = *iterator;
575 
576  // Iterate through all the corners of the outlines and build the segments to draw
577  while( iterator )
578  {
579  // Get the first point of the current segment
580  seg_start = *iterator;
581 
582  // Get the last point of the current segment, handling the case where the end of the
583  // contour is reached, when the last point of the segment is the first point of the
584  // contour
585  if( !iterator.IsEndContour() )
586  {
587  // Set GR mode to default
588  current_gr_mode = draw_mode;
589 
590  SHAPE_POLY_SET::ITERATOR iterator_copy = iterator;
591  iterator_copy++;
592  if( iterator_copy.IsEndContour() )
593  current_gr_mode = GR_XOR;
594 
595  is_close_segment = false;
596 
597  iterator++;
598  seg_end = *iterator;
599  }
600  else
601  {
602  is_close_segment = true;
603 
604  seg_end = contour_first_point;
605 
606  // Reassign first point of the contour to the next contour start
607  iterator++;
608 
609  if( iterator )
610  contour_first_point = *iterator;
611 
612  // Set GR mode to XOR
613  current_gr_mode = GR_XOR;
614  }
615 
616  GRSetDrawMode( DC, current_gr_mode );
617 
618  if( is_close_segment )
619  GRLine( panel->GetClipBox(), DC, seg_start.x, seg_start.y, seg_end.x, seg_end.y, 0,
620  WHITE );
621  else
622  GRLine( panel->GetClipBox(), DC, seg_start.x, seg_start.y, seg_end.x, seg_end.y, 0,
623  color );
624  }
625 }
626 
627 
629 {
630  if( aPad == NULL || aPad->GetThermalGap() == 0 )
631  return m_ThermalReliefGap;
632  else
633  return aPad->GetThermalGap();
634 }
635 
636 
638 {
639  if( aPad == NULL || aPad->GetThermalWidth() == 0 )
641  else
642  return aPad->GetThermalWidth();
643 }
644 
645 
646 void ZONE_CONTAINER::SetCornerRadius( unsigned int aRadius )
647 {
648  m_cornerRadius = aRadius;
649  if( m_cornerRadius > (unsigned int) Mils2iu( MAX_ZONE_CORNER_RADIUS_MILS ) )
651 }
652 
653 
654 bool ZONE_CONTAINER::HitTest( const wxPoint& aPosition ) const
655 {
656  return HitTestForCorner( aPosition ) || HitTestForEdge( aPosition );
657 }
658 
659 
661 {
663 
664  // If there is some corner to be selected, assign it to m_CornerSelection
665  if( HitTestForCorner( aPosition, corner ) || HitTestForEdge( aPosition, corner ) )
666  {
667  if( m_CornerSelection == nullptr )
669 
670  *m_CornerSelection = corner;
671  }
672 }
673 
674 // Zones outlines have no thickness, so it Hit Test functions
675 // we must have a default distance between the test point
676 // and a corner or a zone edge:
677 #define MAX_DIST_IN_MM 0.25
678 
680  SHAPE_POLY_SET::VERTEX_INDEX& aCornerHit ) const
681 {
682  int distmax = Millimeter2iu( MAX_DIST_IN_MM );
683 
684  return m_Poly->CollideVertex( VECTOR2I( refPos ), aCornerHit, distmax );
685 }
686 
687 
688 bool ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos ) const
689 {
691  return HitTestForCorner( refPos, dummy );
692 }
693 
694 
696  SHAPE_POLY_SET::VERTEX_INDEX& aCornerHit ) const
697 {
698  int distmax = Millimeter2iu( MAX_DIST_IN_MM );
699 
700  return m_Poly->CollideEdge( VECTOR2I( refPos ), aCornerHit, distmax );
701 }
702 
703 
704 bool ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos ) const
705 {
707  return HitTestForEdge( refPos, dummy );
708 }
709 
710 
711 bool ZONE_CONTAINER::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
712 {
713  // Calculate bounding box for zone
714  EDA_RECT bbox = GetBoundingBox();
715  bbox.Normalize();
716 
717  EDA_RECT arect = aRect;
718  arect.Normalize();
719  arect.Inflate( aAccuracy );
720 
721  if( aContained )
722  {
723  return arect.Contains( bbox );
724  }
725  else // Test for intersection between aBox and the polygon
726  // For a polygon, using its bounding box has no sense here
727  {
728  // Fast test: if aBox is outside the polygon bounding box,
729  // rectangles cannot intersect
730  if( !arect.Intersects( bbox ) )
731  return false;
732 
733  // aBox is inside the polygon bounding box,
734  // and can intersect the polygon: use a fine test.
735  // aBox intersects the polygon if at least one aBox corner
736  // is inside the polygon
737 
738  /*
739  wxPoint origin = arect.GetOrigin();
740 
741  int w = arect.GetWidth();
742  int h = arect.GetHeight();
743 
744 
745  if ( HitTestInsideZone( origin ) ||
746  HitTestInsideZone( origin + wxPoint( w, 0 ) ) ||
747  HitTestInsideZone( origin + wxPoint( w, h ) ) ||
748  HitTestInsideZone( origin + wxPoint( 0, h ) ) )
749  {
750  return true;
751  }
752  */
753 
754  // No corner inside aBox, but outlines can intersect aBox
755  // if one of outline corners is inside aBox
756  int count = m_Poly->TotalVertices();
757  for( int ii =0; ii < count; ii++ )
758  {
759  auto vertex = m_Poly->Vertex( ii );
760  auto vertexNext = m_Poly->Vertex( ( ii + 1 ) % count );
761 
762  // Test if the point is within the rect
763  if( arect.Contains( ( wxPoint ) vertex ) )
764  {
765  return true;
766  }
767 
768  // Test if this edge intersects the rect
769  if( arect.Intersects( ( wxPoint ) vertex, ( wxPoint ) vertexNext ) )
770  {
771  return true;
772  }
773  }
774 
775  return false;
776  }
777 }
778 
779 
781 {
782  int myClearance = m_ZoneClearance;
783 
784 #if 1 // Maybe the netclass clearance should not come into play for a zone?
785  // At least the policy decision can be controlled by the zone
786  // itself, i.e. here. On reasons of insufficient documentation,
787  // the user will be less bewildered if we simply respect the
788  // "zone clearance" setting in the zone properties dialog. (At least
789  // until there is a UI boolean for this.)
790 
791  NETCLASSPTR myClass = GetNetClass();
792 
793  if( myClass )
794  myClearance = std::max( myClearance, myClass->GetClearance() );
795 #endif
796 
797  if( aItem )
798  {
799  int hisClearance = aItem->GetClearance( NULL );
800  myClearance = std::max( hisClearance, myClearance );
801  }
802 
803  return myClearance;
804 }
805 
806 
807 bool ZONE_CONTAINER::HitTestFilledArea( const wxPoint& aRefPos ) const
808 {
809  return m_FilledPolysList.Contains( VECTOR2I( aRefPos.x, aRefPos.y ) );
810 }
811 
812 
813 void ZONE_CONTAINER::GetMsgPanelInfo( EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM >& aList )
814 {
815  wxString msg;
816 
817  msg = _( "Zone Outline" );
818 
819  // Display Cutout instead of Outline for holes inside a zone
820  // i.e. when num contour !=0
821  // Check whether the selected corner is in a hole; i.e., in any contour but the first one.
822  if( m_CornerSelection != nullptr && m_CornerSelection->m_contour > 0 )
823  msg << wxT( " " ) << _( "(Cutout)" );
824 
825  aList.push_back( MSG_PANEL_ITEM( _( "Type" ), msg, DARKCYAN ) );
826 
827  if( GetIsKeepout() )
828  {
829  msg.Empty();
830 
831  if( GetDoNotAllowVias() )
832  AccumulateDescription( msg, _( "No via" ) );
833 
834  if( GetDoNotAllowTracks() )
835  AccumulateDescription( msg, _("No track") );
836 
838  AccumulateDescription( msg, _("No copper pour") );
839 
840  aList.push_back( MSG_PANEL_ITEM( _( "Keepout" ), msg, RED ) );
841  }
842  else if( IsOnCopperLayer() )
843  {
844  if( GetNetCode() >= 0 )
845  {
846  NETINFO_ITEM* net = GetNet();
847 
848  if( net )
849  msg = net->GetNetname();
850  else // Should not occur
851  msg = _( "<unknown>" );
852  }
853  else // a netcode < 0 is an error
854  msg = wxT( "<error>" );
855 
856  aList.push_back( MSG_PANEL_ITEM( _( "NetName" ), msg, RED ) );
857 
858  // Display net code : (useful in test or debug)
859  msg.Printf( wxT( "%d" ), GetNetCode() );
860  aList.push_back( MSG_PANEL_ITEM( _( "NetCode" ), msg, RED ) );
861 
862  // Display priority level
863  msg.Printf( wxT( "%d" ), GetPriority() );
864  aList.push_back( MSG_PANEL_ITEM( _( "Priority" ), msg, BLUE ) );
865  }
866  else
867  {
868  aList.push_back( MSG_PANEL_ITEM( _( "Non Copper Zone" ), wxEmptyString, RED ) );
869  }
870 
871  aList.push_back( MSG_PANEL_ITEM( _( "Layer" ), GetLayerName(), BROWN ) );
872 
873  msg.Printf( wxT( "%d" ), (int) m_Poly->TotalVertices() );
874  aList.push_back( MSG_PANEL_ITEM( _( "Corners" ), msg, BLUE ) );
875 
876  if( m_FillMode )
877  msg = _( "Segments" );
878  else
879  msg = _( "Polygons" );
880 
881  aList.push_back( MSG_PANEL_ITEM( _( "Fill Mode" ), msg, BROWN ) );
882 
883  // Useful for statistics :
884  msg.Printf( wxT( "%d" ), (int) m_HatchLines.size() );
885  aList.push_back( MSG_PANEL_ITEM( _( "Hatch Lines" ), msg, BLUE ) );
886 
887  if( !m_FilledPolysList.IsEmpty() )
888  {
889  msg.Printf( wxT( "%d" ), m_FilledPolysList.TotalVertices() );
890  aList.push_back( MSG_PANEL_ITEM( _( "Corner Count" ), msg, BLUE ) );
891  }
892 }
893 
894 
895 /* Geometric transforms: */
896 
897 void ZONE_CONTAINER::Move( const wxPoint& offset )
898 {
899  /* move outlines */
900  m_Poly->Move( VECTOR2I( offset ) );
901 
902  Hatch();
903 
904  m_FilledPolysList.Move( VECTOR2I( offset.x, offset.y ) );
905 
906  for( unsigned ic = 0; ic < m_FillSegmList.size(); ic++ )
907  {
908  m_FillSegmList[ic].A += VECTOR2I(offset);
909  m_FillSegmList[ic].B += VECTOR2I(offset);
910  }
911 }
912 
913 
914 void ZONE_CONTAINER::MoveEdge( const wxPoint& offset, int aEdge )
915 {
916  int next_corner;
917 
918  if( m_Poly->GetNeighbourIndexes( aEdge, nullptr, &next_corner ) )
919  {
920  m_Poly->Vertex( aEdge ) += VECTOR2I( offset );
921  m_Poly->Vertex( next_corner ) += VECTOR2I( offset );
922  Hatch();
923  }
924 }
925 
926 
927 void ZONE_CONTAINER::Rotate( const wxPoint& centre, double angle )
928 {
929  wxPoint pos;
930 
931  for( auto iterator = m_Poly->IterateWithHoles(); iterator; iterator++ )
932  {
933  pos = static_cast<wxPoint>( *iterator );
934  RotatePoint( &pos, centre, angle );
935  iterator->x = pos.x;
936  iterator->y = pos.y;
937  }
938 
939  Hatch();
940 
941  /* rotate filled areas: */
942  for( auto ic = m_FilledPolysList.Iterate(); ic; ++ic )
943  RotatePoint( &ic->x, &ic->y, centre.x, centre.y, angle );
944 
945  for( unsigned ic = 0; ic < m_FillSegmList.size(); ic++ )
946  {
947  wxPoint a( m_FillSegmList[ic].A );
948  RotatePoint( &a, centre, angle );
949  m_FillSegmList[ic].A = a;
950  wxPoint b( m_FillSegmList[ic].B );
951  RotatePoint( &b, centre, angle );
952  m_FillSegmList[ic].B = a;
953  }
954 }
955 
956 
957 void ZONE_CONTAINER::Flip( const wxPoint& aCentre )
958 {
959  Mirror( aCentre );
960  int copperLayerCount = GetBoard()->GetCopperLayerCount();
961 
962  if( GetIsKeepout() )
963  {
964  SetLayerSet( FlipLayerMask( GetLayerSet(), copperLayerCount ) );
965  }
966  else
967  {
968  SetLayer( FlipLayer( GetLayer(), copperLayerCount ) );
969  }
970 }
971 
972 
973 void ZONE_CONTAINER::Mirror( const wxPoint& mirror_ref )
974 {
975  for( auto iterator = m_Poly->IterateWithHoles(); iterator; iterator++ )
976  {
977  int py = mirror_ref.y - iterator->y;
978  iterator->y = py + mirror_ref.y;
979  }
980 
981  Hatch();
982 
983  for( auto ic = m_FilledPolysList.Iterate(); ic; ++ic )
984  {
985  int py = mirror_ref.y - ic->y;
986  ic->y = py + mirror_ref.y;
987  }
988 
989  for( unsigned ic = 0; ic < m_FillSegmList.size(); ic++ )
990  {
991  MIRROR( m_FillSegmList[ic].A.y, mirror_ref.y );
992  MIRROR( m_FillSegmList[ic].B.y, mirror_ref.y );
993  }
994 }
995 
996 
998 {
999  if( aPad == NULL || aPad->GetZoneConnection() == PAD_ZONE_CONN_INHERITED )
1000  return m_PadConnection;
1001  else
1002  return aPad->GetZoneConnection();
1003 }
1004 
1005 
1006 void ZONE_CONTAINER::AddPolygon( std::vector< wxPoint >& aPolygon )
1007 {
1008  if( aPolygon.empty() )
1009  return;
1010 
1011  SHAPE_LINE_CHAIN outline;
1012 
1013  // Create an outline and populate it with the points of aPolygon
1014  for( unsigned i = 0; i < aPolygon.size(); i++ )
1015  {
1016  outline.Append( VECTOR2I( aPolygon[i] ) );
1017  }
1018 
1019  outline.SetClosed( true );
1020 
1021  // Add the outline as a new polygon in the polygon set
1022  if( m_Poly->OutlineCount() == 0 )
1023  m_Poly->AddOutline( outline );
1024  else
1025  m_Poly->AddHole( outline );
1026 }
1027 
1028 
1029 bool ZONE_CONTAINER::AppendCorner( wxPoint aPosition, int aHoleIdx, bool aAllowDuplication )
1030 {
1031  // Ensure the main outline exists:
1032  if( m_Poly->OutlineCount() == 0 )
1033  m_Poly->NewOutline();
1034 
1035  // If aHoleIdx >= 0, the corner musty be added to the hole, index aHoleIdx.
1036  // (remember: the index of the first hole is 0)
1037  // Return error if if does dot exist.
1038  if( aHoleIdx >= m_Poly->HoleCount( 0 ) )
1039  return false;
1040 
1041  m_Poly->Append( aPosition.x, aPosition.y, -1, aHoleIdx, aAllowDuplication );
1042 
1043  return true;
1044 }
1045 
1046 
1048 {
1049  wxString text;
1050 
1051  // Check whether the selected contour is a hole (contour index > 0)
1052  if( m_CornerSelection != nullptr && m_CornerSelection->m_contour > 0 )
1053  text << wxT( " " ) << _( "(Cutout)" );
1054 
1055  if( GetIsKeepout() )
1056  text << wxT( " " ) << _( "(Keepout)" );
1057  else
1058  text << GetNetnameMsg();
1059 
1060  return wxString::Format( _( "Zone Outline %s on %s" ), text, GetLayerName() );
1061 }
1062 
1063 
1065 {
1066  return m_hatchPitch;
1067 }
1068 
1069 
1070 void ZONE_CONTAINER::SetHatch( int aHatchStyle, int aHatchPitch, bool aRebuildHatch )
1071 {
1072  SetHatchPitch( aHatchPitch );
1073  m_hatchStyle = (ZONE_CONTAINER::HATCH_STYLE) aHatchStyle;
1074 
1075  if( aRebuildHatch )
1076  Hatch();
1077 }
1078 
1079 
1081 {
1082  m_hatchPitch = aPitch;
1083 }
1084 
1085 
1087 {
1088  m_HatchLines.clear();
1089 }
1090 
1091 
1092 // Creates hatch lines inside the outline of the complex polygon
1093 // sort function used in ::Hatch to sort points by descending wxPoint.x values
1094 bool sortEndsByDescendingX( const VECTOR2I& ref, const VECTOR2I& tst )
1095 {
1096  return tst.x < ref.x;
1097 }
1098 
1099 
1101 {
1102  UnHatch();
1103 
1104  if( m_hatchStyle == NO_HATCH || m_hatchPitch == 0 || m_Poly->IsEmpty() )
1105  return;
1106 
1107  // define range for hatch lines
1108  int min_x = m_Poly->Vertex( 0 ).x;
1109  int max_x = m_Poly->Vertex( 0 ).x;
1110  int min_y = m_Poly->Vertex( 0 ).y;
1111  int max_y = m_Poly->Vertex( 0 ).y;
1112 
1113  for( auto iterator = m_Poly->IterateWithHoles(); iterator; iterator++ )
1114  {
1115  if( iterator->x < min_x )
1116  min_x = iterator->x;
1117 
1118  if( iterator->x > max_x )
1119  max_x = iterator->x;
1120 
1121  if( iterator->y < min_y )
1122  min_y = iterator->y;
1123 
1124  if( iterator->y > max_y )
1125  max_y = iterator->y;
1126  }
1127 
1128  // Calculate spacing between 2 hatch lines
1129  int spacing;
1130 
1131  if( m_hatchStyle == DIAGONAL_EDGE )
1132  spacing = m_hatchPitch;
1133  else
1134  spacing = m_hatchPitch * 2;
1135 
1136  // set the "length" of hatch lines (the length on horizontal axis)
1137  int hatch_line_len = m_hatchPitch;
1138 
1139  // To have a better look, give a slope depending on the layer
1140  LAYER_NUM layer = GetLayer();
1141  int slope_flag = (layer & 1) ? 1 : -1; // 1 or -1
1142  double slope = 0.707106 * slope_flag; // 45 degrees slope
1143  int max_a, min_a;
1144 
1145  if( slope_flag == 1 )
1146  {
1147  max_a = KiROUND( max_y - slope * min_x );
1148  min_a = KiROUND( min_y - slope * max_x );
1149  }
1150  else
1151  {
1152  max_a = KiROUND( max_y - slope * max_x );
1153  min_a = KiROUND( min_y - slope * min_x );
1154  }
1155 
1156  min_a = (min_a / spacing) * spacing;
1157 
1158  // calculate an offset depending on layer number,
1159  // for a better look of hatches on a multilayer board
1160  int offset = (layer * 7) / 8;
1161  min_a += offset;
1162 
1163  // loop through hatch lines
1164  #define MAXPTS 200 // Usually we store only few values per one hatch line
1165  // depending on the complexity of the zone outline
1166 
1167  static std::vector<VECTOR2I> pointbuffer;
1168  pointbuffer.clear();
1169  pointbuffer.reserve( MAXPTS + 2 );
1170 
1171  for( int a = min_a; a < max_a; a += spacing )
1172  {
1173  // get intersection points for this hatch line
1174 
1175  // Note: because we should have an even number of intersections with the
1176  // current hatch line and the zone outline (a closed polygon,
1177  // or a set of closed polygons), if an odd count is found
1178  // we skip this line (should not occur)
1179  pointbuffer.clear();
1180 
1181  // Iterate through all vertices
1182  for( auto iterator = m_Poly->IterateSegmentsWithHoles(); iterator; iterator++ )
1183  {
1184  double x, y, x2, y2;
1185  int ok;
1186 
1187  SEG segment = *iterator;
1188 
1189  ok = FindLineSegmentIntersection( a, slope,
1190  segment.A.x, segment.A.y,
1191  segment.B.x, segment.B.y,
1192  &x, &y, &x2, &y2 );
1193 
1194  if( ok )
1195  {
1196  VECTOR2I point( KiROUND( x ), KiROUND( y ) );
1197  pointbuffer.push_back( point );
1198  }
1199 
1200  if( ok == 2 )
1201  {
1202  VECTOR2I point( KiROUND( x2 ), KiROUND( y2 ) );
1203  pointbuffer.push_back( point );
1204  }
1205 
1206  if( pointbuffer.size() >= MAXPTS ) // overflow
1207  {
1208  wxASSERT( 0 );
1209  break;
1210  }
1211  }
1212 
1213  // ensure we have found an even intersection points count
1214  // because intersections are the ends of segments
1215  // inside the polygon(s) and a segment has 2 ends.
1216  // if not, this is a strange case (a bug ?) so skip this hatch
1217  if( pointbuffer.size() % 2 != 0 )
1218  continue;
1219 
1220  // sort points in order of descending x (if more than 2) to
1221  // ensure the starting point and the ending point of the same segment
1222  // are stored one just after the other.
1223  if( pointbuffer.size() > 2 )
1224  sort( pointbuffer.begin(), pointbuffer.end(), sortEndsByDescendingX );
1225 
1226  // creates lines or short segments inside the complex polygon
1227  for( unsigned ip = 0; ip < pointbuffer.size(); ip += 2 )
1228  {
1229  int dx = pointbuffer[ip + 1].x - pointbuffer[ip].x;
1230 
1231  // Push only one line for diagonal hatch,
1232  // or for small lines < twice the line length
1233  // else push 2 small lines
1234  if( m_hatchStyle == DIAGONAL_FULL || std::abs( dx ) < 2 * hatch_line_len )
1235  {
1236  m_HatchLines.push_back( SEG( pointbuffer[ip], pointbuffer[ip + 1] ) );
1237  }
1238  else
1239  {
1240  double dy = pointbuffer[ip + 1].y - pointbuffer[ip].y;
1241  slope = dy / dx;
1242 
1243  if( dx > 0 )
1244  dx = hatch_line_len;
1245  else
1246  dx = -hatch_line_len;
1247 
1248  int x1 = KiROUND( pointbuffer[ip].x + dx );
1249  int x2 = KiROUND( pointbuffer[ip + 1].x - dx );
1250  int y1 = KiROUND( pointbuffer[ip].y + dx * slope );
1251  int y2 = KiROUND( pointbuffer[ip + 1].y - dx * slope );
1252 
1253  m_HatchLines.push_back(SEG(pointbuffer[ip].x, pointbuffer[ip].y, x1, y1));
1254 
1255  m_HatchLines.push_back( SEG( pointbuffer[ip+1].x, pointbuffer[ip+1].y, x2, y2 ) );
1256  }
1257  }
1258  }
1259 }
1260 
1261 
1263 {
1264  return Mils2iu( 20 );
1265 }
1266 
1267 
1269 {
1270  return add_zone_xpm;
1271 }
1272 
1273 
1275 {
1276  assert( aImage->Type() == PCB_ZONE_AREA_T );
1277 
1278  std::swap( *((ZONE_CONTAINER*) this), *((ZONE_CONTAINER*) aImage) );
1279 }
1280 
1281 
1283 {
1285 }
1286 
1287 
1289 {
1290  if( GetNumCorners() <= 2 ) // malformed zone. polygon calculations do not like it ...
1291  return false;
1292 
1293  // Make a smoothed polygon out of the user-drawn polygon if required
1294  switch( m_cornerSmoothingType )
1295  {
1297  aSmoothedPoly = m_Poly->Chamfer( m_cornerRadius );
1298  break;
1299 
1301  // Note: we're now using m_ArcToSegmentsCount only as a hint to determine accuracy
1302  // vs. speed.
1304  aSmoothedPoly = m_Poly->Fillet( m_cornerRadius, ARC_HIGH_DEF );
1305  else
1306  aSmoothedPoly = m_Poly->Fillet( m_cornerRadius, ARC_LOW_DEF );
1307  break;
1308 
1309  default:
1310  // Acute angles between adjacent edges can create issues in calculations,
1311  // in inflate/deflate outlines transforms, especially when the angle is very small.
1312  // We can avoid issues by creating a very small chamfer which remove acute angles,
1313  // or left it without chamfer and use only CPOLYGONS_LIST::InflateOutline to create
1314  // clearance areas
1315  aSmoothedPoly = m_Poly->Chamfer( Millimeter2iu( 0.0 ) );
1316  break;
1317  }
1318 
1319  return true;
1320 };
1321 
1322 /* Function TransformOutlinesShapeWithClearanceToPolygon
1323  * Convert the zone filled areas polygons to polygons
1324  * inflated (optional) by max( aClearanceValue, the zone clearance)
1325  * and copy them in aCornerBuffer
1326  * param aClearanceValue = the clearance around polygons
1327  * param aAddClearance = true to add a clearance area to the polygon
1328  * false to create the outline polygon.
1329  */
1331  SHAPE_POLY_SET& aCornerBuffer, int aMinClearanceValue, bool aUseNetClearance ) const
1332 {
1333  // Creates the zone outline polygon (with holes if any)
1334  SHAPE_POLY_SET polybuffer;
1335  BuildSmoothedPoly( polybuffer );
1336 
1337  // add clearance to outline
1338  int clearance = aMinClearanceValue;
1339 
1340  if( aUseNetClearance && IsOnCopperLayer() )
1341  {
1342  clearance = GetClearance();
1343  if( aMinClearanceValue > clearance )
1344  clearance = aMinClearanceValue;
1345  }
1346 
1347  // Calculate the polygon with clearance
1348  // holes are linked to the main outline, so only one polygon is created.
1349  if( clearance )
1350  polybuffer.Inflate( clearance, 16 );
1351 
1352  polybuffer.Fracture( SHAPE_POLY_SET::PM_FAST );
1353  aCornerBuffer.Append( polybuffer );
1354 }
Definition: colors.h:57
void SetDoNotAllowTracks(bool aEnable)
Definition: class_zone.h:610
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:673
void MoveEdge(const wxPoint &offset, int aEdge)
Function MoveEdge Move the outline Edge.
Definition: class_zone.cpp:914
KICAD_T Type() const
Function Type()
Definition: base_struct.h:198
void SetHatchPitch(int aPitch)
Function SetHatchPitch sets the hatch pitch parameter for the zone.
void Draw(EDA_DRAW_PANEL *panel, wxDC *DC, GR_DRAWMODE aDrawMode, const wxPoint &offset=ZeroOffset) override
Function Draw Draws the zone outline.
Definition: class_zone.cpp:276
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:60
virtual void SwapData(BOARD_ITEM *aImage) override
Swap data between aItem and aImage.
void GRPoly(EDA_RECT *ClipBox, wxDC *DC, int n, wxPoint Points[], bool Fill, int width, COLOR4D Color, COLOR4D BgColor)
Definition: gr_basic.cpp:796
int m_ZoneClearance
Clearance value in internal units.
Definition: class_zone.h:697
void DrawWhileCreateOutline(EDA_DRAW_PANEL *panel, wxDC *DC, GR_DRAWMODE draw_mode=GR_OR)
Function DrawWhileCreateOutline Draws the zone outline when it is created.
Definition: class_zone.cpp:545
LSET FlipLayerMask(LSET aMask, int aCopperLayersCount)
Calculate the mask layer when flipping a footprint BACK and FRONT copper layers, mask, paste, solder layers are swapped internal layers are flipped only if the copper layers count is known.
Definition: lset.cpp:518
const ZONE_SETTINGS & GetZoneSettings() const
Definition: class_board.h:561
int GetNumCorners(void) const
Access to m_Poly parameters.
Definition: class_zone.h:414
wxString GetNetnameMsg() const
Function GetNetnameMsg.
#define SEGMENT_COUNT_CROSSOVER
Definition: pcbnew.h:46
PNG memory record (file in memory).
Definition: bitmap_types.h:41
bool CommonLayerExists(const LSET aLayerSet) const
Function CommonLayerExist Test if this zone shares a common layer with the given layer set...
Definition: class_zone.cpp:194
void GRSetDrawMode(wxDC *DC, GR_DRAWMODE draw_mode)
Definition: gr_basic.cpp:318
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:119
SEGMENT_ITERATOR IterateSegmentsWithHoles()
Returns an iterator object, for all outlines in the set (with holes)
bool HitTestForEdge(const wxPoint &refPos, 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:695
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Function IsOnLayer tests to see if this object is on the given layer.
EDA_ITEM * Clone() const override
Function Clone creates a duplicate of this item with linked list members set to NULL.
Definition: class_zone.cpp:150
bool CollideEdge(const VECTOR2I &aPoint, VERTEX_INDEX &aClosestVertex, int aClearance=0)
Function CollideEdge Checks whether aPoint collides with any edge of any of the contours of the polyg...
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class...
bool GetDoNotAllowCopperPour() const
Definition: class_zone.h:603
bool m_doNotAllowTracks
Definition: class_zone.h:694
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox (virtual)
Definition: class_zone.cpp:518
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
int PointCount() const
Function PointCount()
bool Contains(const wxPoint &aPoint) const
Function Contains.
void SetCornerRadius(unsigned int aRadius)
Definition: class_zone.cpp:646
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:718
wxString GetSelectMenuText(EDA_UNITS_T aUnits) const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
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:265
Class BOARD to handle a board.
void DrawFilledArea(EDA_DRAW_PANEL *panel, wxDC *DC, GR_DRAWMODE aDrawMode, const wxPoint &offset=ZeroOffset)
Function DrawDrawFilledArea Draws the filled area for this zone (polygon list .m_FilledPolysList) ...
Definition: class_zone.cpp:406
ZoneConnection
How pads are covered by copper in zone.
Definition: zones.h:50
int color
Definition: DXF_plotter.cpp:62
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Function FlippedLayerNumber.
Definition: lset.cpp:472
int GetCopperLayerCount() const
Function GetCopperLayerCount.
class ZONE_CONTAINER, a zone area
Definition: typeinfo.h:102
int HoleCount(int aOutline) const
Returns the number of holes in a given outline
virtual PCB_LAYER_ID GetLayer() const override
Function GetLayer returns the primary layer this item is on.
Definition: class_zone.cpp:175
bool BuildSmoothedPoly(SHAPE_POLY_SET &aSmoothedPoly) const
Function GetSmoothedPoly returns a pointer to the corner-smoothed version of m_Poly if it exists...
int TotalVertices() const
Returns total number of vertices stored in the set.
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, bool aIgnoreHoles=false) const
Returns true if a given subpolygon contains the point aP.
Struct VERTEX_INDEX.
void GRCSegm(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, int aPenSize, COLOR4D Color)
Definition: gr_basic.cpp:510
Classes to handle copper zones.
void SetHatch(int aHatchStyle, int aHatchPitch, bool aRebuildHatch)
Function SetHatch sets all hatch parameters for the zone.
SHAPE_POLY_SET Fillet(int aRadius, int aErrorMax)
Function Fillet returns a filleted version of the polygon set.
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:216
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:726
ITERATOR Iterate(int aFirst, int aLast, bool aIterateHoles=false)
Function Iterate returns an object to iterate through the points of the polygons between aFirst and a...
int OutlineCount() const
Returns the number of outlines in the set
int GetState(int type) const
Definition: base_struct.h:237
VECTOR2< int > VECTOR2I
Definition: vector2d.h:589
int GetThermalReliefCopperBridge(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:637
const wxPoint GetPosition() const override
Function GetPosition.
Definition: class_zone.cpp:169
#define abs(a)
Definition: auxiliary.h:84
Class BOARD_CONNECTED_ITEM is a base class derived from BOARD_ITEM for items that can be connected an...
const VECTOR2I & GetCornerPosition(int aCornerIndex) const
Definition: class_zone.h:454
wxString GetLayerName() const
Function GetLayerName returns the name of the PCB layer on which the item resides.
static int GetDefaultHatchPitch()
Function GetDefaultHatchPitchMils.
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_zone.cpp:780
struct SHAPE_POLY_SET::VERTEX_INDEX VERTEX_INDEX
Struct VERTEX_INDEX.
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
void SetDoNotAllowVias(bool aEnable)
Definition: class_zone.h:609
bool IsEndContour() const
Function IsEndContour.
This file contains miscellaneous commonly used macros and functions.
Classes used in Pcbnew, CvPcb and GerbView.
VECTOR2I & Vertex(int aIndex, int aOutline, int aHole)
Returns the index-th vertex in a given hole outline within a given outline
void ExportSetting(ZONE_CONTAINER &aTarget, bool aFullExport=true) const
Function ExportSetting copy settings to a given zone.
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:602
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:364
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:230
PCB_LAYER_ID m_Layer
void SetLayerSet(LSET aLayerSet)
Definition: class_zone.cpp:210
void MIRROR(T &aPoint, const T &aMirrorRef)
Definition: macros.h:111
#define MAXPTS
void SetClosed(bool aClosed)
Function SetClosed()
bool sortEndsByDescendingX(const VECTOR2I &ref, const VECTOR2I &tst)
int m_ArcToSegmentsCount
The number of segments to convert a circle to a polygon.
Definition: class_zone.h:702
Class PCB_DISPLAY_OPTIONS handles display options like enable/disable some optional drawings...
PCB_LAYER_ID
A quick note on layer IDs:
Class LSET is a set of PCB_LAYER_IDs.
int m_ThermalReliefCopperBridge
Definition: class_zone.h:711
ZoneConnection GetPadConnection(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:997
std::vector< SEG > m_HatchLines
Definition: class_zone.h:741
ZoneConnection m_PadConnection
Definition: class_zone.h:696
void Inflate(int aFactor, int aCircleSegmentsCount)
Performs outline inflation/deflation, using round corners.
void Move(const VECTOR2I &aVector) override
std::shared_ptr< NETCLASS > GetNetClass() const
Function GetNetClass returns the NETCLASS for this item.
ZONE_CONTAINER & operator=(const ZONE_CONTAINER &aOther)
Definition: class_zone.cpp:113
GR_DRAWMODE
Drawmode. Compositing mode plus a flag or two.
Definition: gr_basic.h:37
ITERATOR IterateWithHoles(int aOutline)
Function IterateWithHoles.
Class SHAPE_POLY_SET.
void GRFillCSegm(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, COLOR4D Color)
Definition: gr_basic.cpp:613
bool m_IsFilled
True when a zone was filled, false after deleting the filled areas.
Definition: class_zone.h:705
virtual void Flip(const wxPoint &aCentre) override
Function Flip Flip this object, i.e.
Definition: class_zone.cpp:957
ZoneConnection GetZoneConnection() const
Definition: class_pad.cpp:670
SHAPE_POLY_SET * m_Poly
Outline of the zone.
Definition: class_zone.h:672
int GetThermalReliefGap(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:628
ZONE_CONTAINER(BOARD *parent)
Definition: class_zone.cpp:52
unsigned m_priority
Definition: class_zone.h:682
int GetThermalWidth() const
Definition: class_pad.cpp:681
void Rotate(const wxPoint &centre, double angle) override
Function Rotate Move the outlines.
Definition: class_zone.cpp:927
bool m_doNotAllowVias
Definition: class_zone.h:693
int GetThermalGap() const
Definition: class_pad.cpp:692
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Function SetLayer sets the layer this item is on.
Definition: class_zone.cpp:202
bool CollideVertex(const VECTOR2I &aPoint, VERTEX_INDEX &aClosestVertex, int aClearance=0)
Function CollideVertex Checks whether aPoint collides with any vertex of any of the contours of the p...
bool UnFill()
Function UnFill Removes the zone filling.
Definition: class_zone.cpp:156
int m_cornerSmoothingType
Definition: class_zone.h:673
void CacheTriangulation()
EDA_RECT * GetClipBox()
bool SetNetCode(int aNetCode, bool aNoAssert=false)
Function SetNetCode sets net using a net code.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
Definition: colors.h:60
#define MAX_ZONE_CORNER_RADIUS_MILS
Definition: zone_settings.h:36
EDA_DRAW_FRAME * GetParent() const
Definition: draw_panel.cpp:163
HATCH_STYLE
Zone hatch styles.
Definition: class_zone.h:67
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:244
virtual int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const
Function GetClearance returns the clearance in internal units.
bool FindLineSegmentIntersection(double a, double b, int xi, int yi, int xf, int yf, double *x1, double *y1, double *x2, double *y2, double *dist)
void GRLine(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, COLOR4D Color, wxPenStyle aStyle)
Definition: gr_basic.cpp:380
int NewOutline()
Creates a new empty polygon in the set and returns its index
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...
EDA_ITEM & operator=(const EDA_ITEM &aItem)
Operator assignment is used to assign the members of aItem to another object.
SHAPE_POLY_SET m_FilledPolysList
Definition: class_zone.h:736
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:210
Class LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
unsigned int m_cornerRadius
Definition: class_zone.h:674
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
void Move(const wxPoint &offset) override
Function Move Move the outlines.
Definition: class_zone.cpp:897
int GetNetCode() const
Function GetNetCode.
HATCH_STYLE m_hatchStyle
Definition: class_zone.h:739
Definition: seg.h:36
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.
void AccumulateDescription(wxString &aDesc, const wxString &aItem)
Utility to build comma separated lists in messages.
Definition: macros.h:65
void SetDoNotAllowCopperPour(bool aEnable)
Definition: class_zone.h:608
void TransformOutlinesShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, int aMinClearanceValue, bool aUseNetClearance) const
Function TransformOutlinesShapeWithClearanceToPolygon Convert the outlines shape to a polygon with no...
bool Intersects(const EDA_RECT &aRect) const
Function Intersects tests for a common area between rectangles.
Class NETINFO_ITEM handles the data for a net.
Definition: netinfo.h:69
bool m_doNotAllowCopperPour
Definition: class_zone.h:692
bool IsOnCopperLayer() const
Function IsOnCopperLayer.
Definition: class_zone.cpp:181
int m_ThermalReliefGap
Width of the copper bridge in thermal reliefs.
Definition: class_zone.h:708
bool GetDoNotAllowTracks() const
Definition: class_zone.h:605
int m_ZoneMinThickness
Minimum thickness value in filled areas.
Definition: class_zone.h:698
ZONE_FILL_MODE m_FillMode
How to fill areas: ZFM_POLYGONS => use filled polygons, ZFM_SEGMENTS => fill with segments...
Definition: class_zone.h:715
SHAPE_POLY_SET Chamfer(int aDistance)
Function Chamfer returns a chamfered version of the polygon set.
void UnHatch()
Function UnHatch clears the zone&#39;s hatch.
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
int GetLocalFlags() const
Definition: class_zone.h:230
bool GetDoNotAllowVias() const
Definition: class_zone.h:604
static LIB_PART * dummy()
Used when a LIB_PART is not found in library to draw a dummy shape This component is a 400 mils squar...
#define max(a, b)
Definition: auxiliary.h:86
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:169
Class SHAPE_LINE_CHAIN.
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
LSET GetVisibleLayers() const
Function GetVisibleLayers is a proxy function that calls the correspondent function in m_BoardSetting...
Class ITERATOR_TEMPLATE.
virtual bool HitTest(const wxPoint &aPosition) const override
Function HitTest tests if a point is near an outline edge or a corner of this zone.
Definition: class_zone.cpp:654
size_t i
Definition: json11.cpp:597
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
bool HitTestFilledArea(const wxPoint &aRefPos) const
Function HitTestFilledArea tests if the given wxPoint is within the bounds of a filled area of this z...
Definition: class_zone.cpp:807
VECTOR2I A
Definition: seg.h:46
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
HATCH_STYLE GetHatchStyle() const
Definition: class_zone.h:498
void Hatch()
Function Hatch computes the hatch lines depending on the hatch parameters and stores it in the zone&#39;s...
BASE_SCREEN * GetScreen()
Definition: draw_panel.cpp:176
void SetHatchStyle(HATCH_STYLE aStyle)
Definition: class_zone.h:503
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:151
void SetLocalFlags(int aFlags)
Definition: class_zone.h:231
void GRLineArray(EDA_RECT *aClipBox, wxDC *aDC, std::vector< wxPoint > &aLines, int aWidth, COLOR4D aColor)
Function GRLineArray draws an array of lines (not a polygon).
Definition: gr_basic.cpp:456
Definition: colors.h:49
virtual BOARD * GetBoard() const
Function GetBoard returns the BOARD in which this BOARD_ITEM resides, or NULL if none.
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
#define MAX_DIST_IN_MM
Definition: class_zone.cpp:677
bool AppendCorner(wxPoint aPosition, int aHoleIdx, bool aAllowDuplication=false)
Add a new corner to the zone outline (to the main outline or a hole)
int GetHatchPitch() const
Hatch related methods.
bool IsEmpty() const
Returns true if the set is empty (no polygons at all)
const wxString & GetNetname() const
Function GetNetname.
Definition: netinfo.h:235
void * GetDisplayOptions()
Function GetDisplayOptions A way to pass info to draw functions.
Definition: draw_panel.cpp:170
void Mirror(const wxPoint &mirror_ref)
Function Mirror Mirror the outlines , relative to a given horizontal axis the layer is not changed...
Definition: class_zone.cpp:973
Class EDA_MSG_ITEM is used EDA_MSG_PANEL as the item type for displaying messages.
Definition: msgpanel.h:53
void SetIsKeepout(bool aEnable)
Definition: class_zone.h:607
unsigned GetPriority() const
Function GetPriority.
Definition: class_zone.h:101
BITMAP_DEF GetMenuImage() const override
Function GetMenuImage returns a pointer to an image to be used in menus.
Message panel definition file.
bool HitTestForCorner(const wxPoint &refPos, SHAPE_POLY_SET::VERTEX_INDEX &aCornerHit) const
Function HitTestForCorner tests if the given wxPoint is near a corner.
Definition: class_zone.cpp:679
#define FORCE_SKETCH
Definition: pcbnew.h:72
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
class PCB_BASE_FRAME basic PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer...
EDA_UNITS_T
Definition: common.h:158
NETINFO_ITEM * GetNet() const
Function GetNet Returns NET_INFO object for a given item.
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
#define min(a, b)
Definition: auxiliary.h:85
bool IsLayerVisible(PCB_LAYER_ID aLayer) const
Function IsLayerVisible is a proxy function that calls the correspondent function in m_BoardSettings ...
Definition: class_board.h:456
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) ...
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39
void GetMsgPanelInfo(EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM > &aList) override
Function GetMsgPanelInfo populates aList of MSG_PANEL_ITEM objects with it&#39;s internal state for displ...
Definition: class_zone.cpp:813
VECTOR2I B
Definition: seg.h:47
Definition: colors.h:62