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 
169 const wxPoint ZONE_CONTAINER::GetPosition() const
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 }
650 
651 
652 bool ZONE_CONTAINER::HitTest( const wxPoint& aPosition ) const
653 {
654  // Normally accuracy is zoom-relative, but for the generic HitTest we just use
655  // a fixed (small) value.
656  int accuracy = Millimeter2iu( 0.05 );
657 
658  return HitTestForCorner( aPosition, accuracy * 2 ) || HitTestForEdge( aPosition, accuracy );
659 }
660 
661 
662 void ZONE_CONTAINER::SetSelectedCorner( const wxPoint& aPosition, int aAccuracy )
663 {
665 
666  // If there is some corner to be selected, assign it to m_CornerSelection
667  if( HitTestForCorner( aPosition, aAccuracy * 2, corner )
668  || HitTestForEdge( aPosition, aAccuracy, corner ) )
669  {
670  if( m_CornerSelection == nullptr )
672 
673  *m_CornerSelection = corner;
674  }
675 }
676 
677 bool ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos, int aAccuracy,
678  SHAPE_POLY_SET::VERTEX_INDEX& aCornerHit ) const
679 {
680  return m_Poly->CollideVertex( VECTOR2I( refPos ), aCornerHit, aAccuracy );
681 }
682 
683 
684 bool ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos, int aAccuracy ) const
685 {
687  return HitTestForCorner( refPos, aAccuracy, dummy );
688 }
689 
690 
691 bool ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos, int aAccuracy,
692  SHAPE_POLY_SET::VERTEX_INDEX& aCornerHit ) const
693 {
694  return m_Poly->CollideEdge( VECTOR2I( refPos ), aCornerHit, aAccuracy );
695 }
696 
697 
698 bool ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos, int aAccuracy ) const
699 {
701  return HitTestForEdge( refPos, aAccuracy, dummy );
702 }
703 
704 
705 bool ZONE_CONTAINER::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
706 {
707  // Calculate bounding box for zone
708  EDA_RECT bbox = GetBoundingBox();
709  bbox.Normalize();
710 
711  EDA_RECT arect = aRect;
712  arect.Normalize();
713  arect.Inflate( aAccuracy );
714 
715  if( aContained )
716  {
717  return arect.Contains( bbox );
718  }
719  else // Test for intersection between aBox and the polygon
720  // For a polygon, using its bounding box has no sense here
721  {
722  // Fast test: if aBox is outside the polygon bounding box,
723  // rectangles cannot intersect
724  if( !arect.Intersects( bbox ) )
725  return false;
726 
727  // aBox is inside the polygon bounding box,
728  // and can intersect the polygon: use a fine test.
729  // aBox intersects the polygon if at least one aBox corner
730  // is inside the polygon
731 
732  /*
733  wxPoint origin = arect.GetOrigin();
734 
735  int w = arect.GetWidth();
736  int h = arect.GetHeight();
737 
738 
739  if ( HitTestInsideZone( origin ) ||
740  HitTestInsideZone( origin + wxPoint( w, 0 ) ) ||
741  HitTestInsideZone( origin + wxPoint( w, h ) ) ||
742  HitTestInsideZone( origin + wxPoint( 0, h ) ) )
743  {
744  return true;
745  }
746  */
747 
748  // No corner inside aBox, but outlines can intersect aBox
749  // if one of outline corners is inside aBox
750  int count = m_Poly->TotalVertices();
751  for( int ii =0; ii < count; ii++ )
752  {
753  auto vertex = m_Poly->Vertex( ii );
754  auto vertexNext = m_Poly->Vertex( ( ii + 1 ) % count );
755 
756  // Test if the point is within the rect
757  if( arect.Contains( ( wxPoint ) vertex ) )
758  {
759  return true;
760  }
761 
762  // Test if this edge intersects the rect
763  if( arect.Intersects( ( wxPoint ) vertex, ( wxPoint ) vertexNext ) )
764  {
765  return true;
766  }
767  }
768 
769  return false;
770  }
771 }
772 
773 
775 {
776  int myClearance = m_ZoneClearance;
777 
778 #if 1 // Maybe the netclass clearance should not come into play for a zone?
779  // At least the policy decision can be controlled by the zone
780  // itself, i.e. here. On reasons of insufficient documentation,
781  // the user will be less bewildered if we simply respect the
782  // "zone clearance" setting in the zone properties dialog. (At least
783  // until there is a UI boolean for this.)
784 
785  NETCLASSPTR myClass = GetNetClass();
786 
787  if( myClass )
788  myClearance = std::max( myClearance, myClass->GetClearance() );
789 #endif
790 
791  if( aItem )
792  {
793  int hisClearance = aItem->GetClearance( NULL );
794  myClearance = std::max( hisClearance, myClearance );
795  }
796 
797  return myClearance;
798 }
799 
800 
801 bool ZONE_CONTAINER::HitTestFilledArea( const wxPoint& aRefPos ) const
802 {
803  return m_FilledPolysList.Contains( VECTOR2I( aRefPos.x, aRefPos.y ) );
804 }
805 
806 
807 void ZONE_CONTAINER::GetMsgPanelInfo( EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM >& aList )
808 {
809  wxString msg;
810 
811  msg = _( "Zone Outline" );
812 
813  // Display Cutout instead of Outline for holes inside a zone
814  // i.e. when num contour !=0
815  // Check whether the selected corner is in a hole; i.e., in any contour but the first one.
816  if( m_CornerSelection != nullptr && m_CornerSelection->m_contour > 0 )
817  msg << wxT( " " ) << _( "(Cutout)" );
818 
819  aList.push_back( MSG_PANEL_ITEM( _( "Type" ), msg, DARKCYAN ) );
820 
821  if( GetIsKeepout() )
822  {
823  msg.Empty();
824 
825  if( GetDoNotAllowVias() )
826  AccumulateDescription( msg, _( "No via" ) );
827 
828  if( GetDoNotAllowTracks() )
829  AccumulateDescription( msg, _("No track") );
830 
832  AccumulateDescription( msg, _("No copper pour") );
833 
834  aList.push_back( MSG_PANEL_ITEM( _( "Keepout" ), msg, RED ) );
835  }
836  else if( IsOnCopperLayer() )
837  {
838  if( GetNetCode() >= 0 )
839  {
840  NETINFO_ITEM* net = GetNet();
841 
842  if( net )
843  msg = net->GetNetname();
844  else // Should not occur
845  msg = _( "<unknown>" );
846  }
847  else // a netcode < 0 is an error
848  msg = wxT( "<error>" );
849 
850  aList.push_back( MSG_PANEL_ITEM( _( "NetName" ), msg, RED ) );
851 
852  // Display net code : (useful in test or debug)
853  msg.Printf( wxT( "%d" ), GetNetCode() );
854  aList.push_back( MSG_PANEL_ITEM( _( "NetCode" ), msg, RED ) );
855 
856  // Display priority level
857  msg.Printf( wxT( "%d" ), GetPriority() );
858  aList.push_back( MSG_PANEL_ITEM( _( "Priority" ), msg, BLUE ) );
859  }
860  else
861  {
862  aList.push_back( MSG_PANEL_ITEM( _( "Non Copper Zone" ), wxEmptyString, RED ) );
863  }
864 
865  aList.push_back( MSG_PANEL_ITEM( _( "Layer" ), GetLayerName(), BROWN ) );
866 
867  msg.Printf( wxT( "%d" ), (int) m_Poly->TotalVertices() );
868  aList.push_back( MSG_PANEL_ITEM( _( "Corners" ), msg, BLUE ) );
869 
870  if( m_FillMode )
871  msg = _( "Segments" );
872  else
873  msg = _( "Polygons" );
874 
875  aList.push_back( MSG_PANEL_ITEM( _( "Fill Mode" ), msg, BROWN ) );
876 
877  // Useful for statistics :
878  msg.Printf( wxT( "%d" ), (int) m_HatchLines.size() );
879  aList.push_back( MSG_PANEL_ITEM( _( "Hatch Lines" ), msg, BLUE ) );
880 
881  if( !m_FilledPolysList.IsEmpty() )
882  {
883  msg.Printf( wxT( "%d" ), m_FilledPolysList.TotalVertices() );
884  aList.push_back( MSG_PANEL_ITEM( _( "Corner Count" ), msg, BLUE ) );
885  }
886 }
887 
888 
889 /* Geometric transforms: */
890 
891 void ZONE_CONTAINER::Move( const wxPoint& offset )
892 {
893  /* move outlines */
894  m_Poly->Move( VECTOR2I( offset ) );
895 
896  Hatch();
897 
898  m_FilledPolysList.Move( VECTOR2I( offset.x, offset.y ) );
899 
900  for( unsigned ic = 0; ic < m_FillSegmList.size(); ic++ )
901  {
902  m_FillSegmList[ic].A += VECTOR2I(offset);
903  m_FillSegmList[ic].B += VECTOR2I(offset);
904  }
905 }
906 
907 
908 void ZONE_CONTAINER::MoveEdge( const wxPoint& offset, int aEdge )
909 {
910  int next_corner;
911 
912  if( m_Poly->GetNeighbourIndexes( aEdge, nullptr, &next_corner ) )
913  {
914  m_Poly->Vertex( aEdge ) += VECTOR2I( offset );
915  m_Poly->Vertex( next_corner ) += VECTOR2I( offset );
916  Hatch();
917  }
918 }
919 
920 
921 void ZONE_CONTAINER::Rotate( const wxPoint& centre, double angle )
922 {
923  wxPoint pos;
924 
925  for( auto iterator = m_Poly->IterateWithHoles(); iterator; iterator++ )
926  {
927  pos = static_cast<wxPoint>( *iterator );
928  RotatePoint( &pos, centre, angle );
929  iterator->x = pos.x;
930  iterator->y = pos.y;
931  }
932 
933  Hatch();
934 
935  /* rotate filled areas: */
936  for( auto ic = m_FilledPolysList.Iterate(); ic; ++ic )
937  RotatePoint( &ic->x, &ic->y, centre.x, centre.y, angle );
938 
939  for( unsigned ic = 0; ic < m_FillSegmList.size(); ic++ )
940  {
941  wxPoint a( m_FillSegmList[ic].A );
942  RotatePoint( &a, centre, angle );
943  m_FillSegmList[ic].A = a;
944  wxPoint b( m_FillSegmList[ic].B );
945  RotatePoint( &b, centre, angle );
946  m_FillSegmList[ic].B = a;
947  }
948 }
949 
950 
951 void ZONE_CONTAINER::Flip( const wxPoint& aCentre )
952 {
953  Mirror( aCentre );
954  int copperLayerCount = GetBoard()->GetCopperLayerCount();
955 
956  if( GetIsKeepout() )
957  {
958  SetLayerSet( FlipLayerMask( GetLayerSet(), copperLayerCount ) );
959  }
960  else
961  {
962  SetLayer( FlipLayer( GetLayer(), copperLayerCount ) );
963  }
964 }
965 
966 
967 void ZONE_CONTAINER::Mirror( const wxPoint& mirror_ref )
968 {
969  for( auto iterator = m_Poly->IterateWithHoles(); iterator; iterator++ )
970  {
971  int py = mirror_ref.y - iterator->y;
972  iterator->y = py + mirror_ref.y;
973  }
974 
975  Hatch();
976 
977  for( auto ic = m_FilledPolysList.Iterate(); ic; ++ic )
978  {
979  int py = mirror_ref.y - ic->y;
980  ic->y = py + mirror_ref.y;
981  }
982 
983  for( unsigned ic = 0; ic < m_FillSegmList.size(); ic++ )
984  {
985  MIRROR( m_FillSegmList[ic].A.y, mirror_ref.y );
986  MIRROR( m_FillSegmList[ic].B.y, mirror_ref.y );
987  }
988 }
989 
990 
992 {
993  if( aPad == NULL || aPad->GetZoneConnection() == PAD_ZONE_CONN_INHERITED )
994  return m_PadConnection;
995  else
996  return aPad->GetZoneConnection();
997 }
998 
999 
1000 void ZONE_CONTAINER::AddPolygon( std::vector< wxPoint >& aPolygon )
1001 {
1002  if( aPolygon.empty() )
1003  return;
1004 
1005  SHAPE_LINE_CHAIN outline;
1006 
1007  // Create an outline and populate it with the points of aPolygon
1008  for( unsigned i = 0; i < aPolygon.size(); i++ )
1009  {
1010  outline.Append( VECTOR2I( aPolygon[i] ) );
1011  }
1012 
1013  outline.SetClosed( true );
1014 
1015  // Add the outline as a new polygon in the polygon set
1016  if( m_Poly->OutlineCount() == 0 )
1017  m_Poly->AddOutline( outline );
1018  else
1019  m_Poly->AddHole( outline );
1020 }
1021 
1022 
1023 bool ZONE_CONTAINER::AppendCorner( wxPoint aPosition, int aHoleIdx, bool aAllowDuplication )
1024 {
1025  // Ensure the main outline exists:
1026  if( m_Poly->OutlineCount() == 0 )
1027  m_Poly->NewOutline();
1028 
1029  // If aHoleIdx >= 0, the corner musty be added to the hole, index aHoleIdx.
1030  // (remember: the index of the first hole is 0)
1031  // Return error if if does dot exist.
1032  if( aHoleIdx >= m_Poly->HoleCount( 0 ) )
1033  return false;
1034 
1035  m_Poly->Append( aPosition.x, aPosition.y, -1, aHoleIdx, aAllowDuplication );
1036 
1037  return true;
1038 }
1039 
1040 
1042 {
1043  wxString text;
1044 
1045  // Check whether the selected contour is a hole (contour index > 0)
1046  if( m_CornerSelection != nullptr && m_CornerSelection->m_contour > 0 )
1047  text << wxT( " " ) << _( "(Cutout)" );
1048 
1049  if( GetIsKeepout() )
1050  text << wxT( " " ) << _( "(Keepout)" );
1051  else
1052  text << GetNetnameMsg();
1053 
1054  return wxString::Format( _( "Zone Outline %s on %s" ), text, GetLayerName() );
1055 }
1056 
1057 
1059 {
1060  return m_hatchPitch;
1061 }
1062 
1063 
1064 void ZONE_CONTAINER::SetHatch( int aHatchStyle, int aHatchPitch, bool aRebuildHatch )
1065 {
1066  SetHatchPitch( aHatchPitch );
1067  m_hatchStyle = (ZONE_CONTAINER::HATCH_STYLE) aHatchStyle;
1068 
1069  if( aRebuildHatch )
1070  Hatch();
1071 }
1072 
1073 
1075 {
1076  m_hatchPitch = aPitch;
1077 }
1078 
1079 
1081 {
1082  m_HatchLines.clear();
1083 }
1084 
1085 
1086 // Creates hatch lines inside the outline of the complex polygon
1087 // sort function used in ::Hatch to sort points by descending wxPoint.x values
1088 bool sortEndsByDescendingX( const VECTOR2I& ref, const VECTOR2I& tst )
1089 {
1090  return tst.x < ref.x;
1091 }
1092 
1093 
1095 {
1096  UnHatch();
1097 
1098  if( m_hatchStyle == NO_HATCH || m_hatchPitch == 0 || m_Poly->IsEmpty() )
1099  return;
1100 
1101  // define range for hatch lines
1102  int min_x = m_Poly->Vertex( 0 ).x;
1103  int max_x = m_Poly->Vertex( 0 ).x;
1104  int min_y = m_Poly->Vertex( 0 ).y;
1105  int max_y = m_Poly->Vertex( 0 ).y;
1106 
1107  for( auto iterator = m_Poly->IterateWithHoles(); iterator; iterator++ )
1108  {
1109  if( iterator->x < min_x )
1110  min_x = iterator->x;
1111 
1112  if( iterator->x > max_x )
1113  max_x = iterator->x;
1114 
1115  if( iterator->y < min_y )
1116  min_y = iterator->y;
1117 
1118  if( iterator->y > max_y )
1119  max_y = iterator->y;
1120  }
1121 
1122  // Calculate spacing between 2 hatch lines
1123  int spacing;
1124 
1125  if( m_hatchStyle == DIAGONAL_EDGE )
1126  spacing = m_hatchPitch;
1127  else
1128  spacing = m_hatchPitch * 2;
1129 
1130  // set the "length" of hatch lines (the length on horizontal axis)
1131  int hatch_line_len = m_hatchPitch;
1132 
1133  // To have a better look, give a slope depending on the layer
1134  LAYER_NUM layer = GetLayer();
1135  int slope_flag = (layer & 1) ? 1 : -1; // 1 or -1
1136  double slope = 0.707106 * slope_flag; // 45 degrees slope
1137  int max_a, min_a;
1138 
1139  if( slope_flag == 1 )
1140  {
1141  max_a = KiROUND( max_y - slope * min_x );
1142  min_a = KiROUND( min_y - slope * max_x );
1143  }
1144  else
1145  {
1146  max_a = KiROUND( max_y - slope * max_x );
1147  min_a = KiROUND( min_y - slope * min_x );
1148  }
1149 
1150  min_a = (min_a / spacing) * spacing;
1151 
1152  // calculate an offset depending on layer number,
1153  // for a better look of hatches on a multilayer board
1154  int offset = (layer * 7) / 8;
1155  min_a += offset;
1156 
1157  // loop through hatch lines
1158  #define MAXPTS 200 // Usually we store only few values per one hatch line
1159  // depending on the complexity of the zone outline
1160 
1161  static std::vector<VECTOR2I> pointbuffer;
1162  pointbuffer.clear();
1163  pointbuffer.reserve( MAXPTS + 2 );
1164 
1165  for( int a = min_a; a < max_a; a += spacing )
1166  {
1167  // get intersection points for this hatch line
1168 
1169  // Note: because we should have an even number of intersections with the
1170  // current hatch line and the zone outline (a closed polygon,
1171  // or a set of closed polygons), if an odd count is found
1172  // we skip this line (should not occur)
1173  pointbuffer.clear();
1174 
1175  // Iterate through all vertices
1176  for( auto iterator = m_Poly->IterateSegmentsWithHoles(); iterator; iterator++ )
1177  {
1178  double x, y, x2, y2;
1179  int ok;
1180 
1181  SEG segment = *iterator;
1182 
1183  ok = FindLineSegmentIntersection( a, slope,
1184  segment.A.x, segment.A.y,
1185  segment.B.x, segment.B.y,
1186  &x, &y, &x2, &y2 );
1187 
1188  if( ok )
1189  {
1190  VECTOR2I point( KiROUND( x ), KiROUND( y ) );
1191  pointbuffer.push_back( point );
1192  }
1193 
1194  if( ok == 2 )
1195  {
1196  VECTOR2I point( KiROUND( x2 ), KiROUND( y2 ) );
1197  pointbuffer.push_back( point );
1198  }
1199 
1200  if( pointbuffer.size() >= MAXPTS ) // overflow
1201  {
1202  wxASSERT( 0 );
1203  break;
1204  }
1205  }
1206 
1207  // ensure we have found an even intersection points count
1208  // because intersections are the ends of segments
1209  // inside the polygon(s) and a segment has 2 ends.
1210  // if not, this is a strange case (a bug ?) so skip this hatch
1211  if( pointbuffer.size() % 2 != 0 )
1212  continue;
1213 
1214  // sort points in order of descending x (if more than 2) to
1215  // ensure the starting point and the ending point of the same segment
1216  // are stored one just after the other.
1217  if( pointbuffer.size() > 2 )
1218  sort( pointbuffer.begin(), pointbuffer.end(), sortEndsByDescendingX );
1219 
1220  // creates lines or short segments inside the complex polygon
1221  for( unsigned ip = 0; ip < pointbuffer.size(); ip += 2 )
1222  {
1223  int dx = pointbuffer[ip + 1].x - pointbuffer[ip].x;
1224 
1225  // Push only one line for diagonal hatch,
1226  // or for small lines < twice the line length
1227  // else push 2 small lines
1228  if( m_hatchStyle == DIAGONAL_FULL || std::abs( dx ) < 2 * hatch_line_len )
1229  {
1230  m_HatchLines.push_back( SEG( pointbuffer[ip], pointbuffer[ip + 1] ) );
1231  }
1232  else
1233  {
1234  double dy = pointbuffer[ip + 1].y - pointbuffer[ip].y;
1235  slope = dy / dx;
1236 
1237  if( dx > 0 )
1238  dx = hatch_line_len;
1239  else
1240  dx = -hatch_line_len;
1241 
1242  int x1 = KiROUND( pointbuffer[ip].x + dx );
1243  int x2 = KiROUND( pointbuffer[ip + 1].x - dx );
1244  int y1 = KiROUND( pointbuffer[ip].y + dx * slope );
1245  int y2 = KiROUND( pointbuffer[ip + 1].y - dx * slope );
1246 
1247  m_HatchLines.push_back(SEG(pointbuffer[ip].x, pointbuffer[ip].y, x1, y1));
1248 
1249  m_HatchLines.push_back( SEG( pointbuffer[ip+1].x, pointbuffer[ip+1].y, x2, y2 ) );
1250  }
1251  }
1252  }
1253 }
1254 
1255 
1257 {
1258  return Mils2iu( 20 );
1259 }
1260 
1261 
1263 {
1264  return add_zone_xpm;
1265 }
1266 
1267 
1269 {
1270  assert( aImage->Type() == PCB_ZONE_AREA_T );
1271 
1272  std::swap( *((ZONE_CONTAINER*) this), *((ZONE_CONTAINER*) aImage) );
1273 }
1274 
1275 
1277 {
1279 }
1280 
1281 
1283 {
1284  if( GetNumCorners() <= 2 ) // malformed zone. polygon calculations do not like it ...
1285  return false;
1286 
1287  // Make a smoothed polygon out of the user-drawn polygon if required
1288  switch( m_cornerSmoothingType )
1289  {
1291  aSmoothedPoly = m_Poly->Chamfer( m_cornerRadius );
1292  break;
1293 
1295  // Note: we're now using m_ArcToSegmentsCount only as a hint to determine accuracy
1296  // vs. speed.
1298  aSmoothedPoly = m_Poly->Fillet( m_cornerRadius, ARC_HIGH_DEF );
1299  else
1300  aSmoothedPoly = m_Poly->Fillet( m_cornerRadius, ARC_LOW_DEF );
1301  break;
1302 
1303  default:
1304  // Acute angles between adjacent edges can create issues in calculations,
1305  // in inflate/deflate outlines transforms, especially when the angle is very small.
1306  // We can avoid issues by creating a very small chamfer which remove acute angles,
1307  // or left it without chamfer and use only CPOLYGONS_LIST::InflateOutline to create
1308  // clearance areas
1309  aSmoothedPoly = m_Poly->Chamfer( Millimeter2iu( 0.0 ) );
1310  break;
1311  }
1312 
1313  return true;
1314 };
1315 
1316 /* Function TransformOutlinesShapeWithClearanceToPolygon
1317  * Convert the zone filled areas polygons to polygons
1318  * inflated (optional) by max( aClearanceValue, the zone clearance)
1319  * and copy them in aCornerBuffer
1320  * param aClearanceValue = the clearance around polygons
1321  * param aAddClearance = true to add a clearance area to the polygon
1322  * false to create the outline polygon.
1323  */
1325  SHAPE_POLY_SET& aCornerBuffer, int aMinClearanceValue, bool aUseNetClearance ) const
1326 {
1327  // Creates the zone outline polygon (with holes if any)
1328  SHAPE_POLY_SET polybuffer;
1329  BuildSmoothedPoly( polybuffer );
1330 
1331  // add clearance to outline
1332  int clearance = aMinClearanceValue;
1333 
1334  if( aUseNetClearance && IsOnCopperLayer() )
1335  {
1336  clearance = GetClearance();
1337  if( aMinClearanceValue > clearance )
1338  clearance = aMinClearanceValue;
1339  }
1340 
1341  // Calculate the polygon with clearance
1342  // holes are linked to the main outline, so only one polygon is created.
1343  if( clearance )
1344  polybuffer.Inflate( clearance, ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF );
1345 
1346  polybuffer.Fracture( SHAPE_POLY_SET::PM_FAST );
1347  aCornerBuffer.Append( polybuffer );
1348 }
virtual BASE_SCREEN * GetScreen()=0
Definition: colors.h:57
void SetDoNotAllowTracks(bool aEnable)
Definition: class_zone.h:638
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:676
void MoveEdge(const wxPoint &offset, int aEdge)
Function MoveEdge Move the outline Edge.
Definition: class_zone.cpp:908
KICAD_T Type() const
Function Type()
Definition: base_struct.h:201
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:59
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:701
int m_ZoneClearance
Clearance value in internal units.
Definition: class_zone.h:725
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:521
const ZONE_SETTINGS & GetZoneSettings() const
Definition: class_board.h:563
int GetNumCorners(void) const
Access to m_Poly parameters.
Definition: class_zone.h:442
wxString GetNetnameMsg() const
Function GetNetnameMsg.
#define SEGMENT_COUNT_CROSSOVER
Definition: pcbnew.h:46
PNG memory record (file in memory).
Definition: bitmap_types.h:43
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:223
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:121
SEGMENT_ITERATOR IterateSegmentsWithHoles()
Returns an iterator object, for all outlines in the set (with holes)
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:631
bool m_doNotAllowTracks
Definition: class_zone.h:722
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:746
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:475
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:415
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.
virtual EDA_RECT * GetClipBox()
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:754
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:240
VECTOR2< int > VECTOR2I
Definition: vector2d.h:587
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:482
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:774
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:637
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:630
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:367
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
virtual EDA_DRAW_FRAME * GetParent() const =0
PCB_LAYER_ID m_Layer
void SetLayerSet(LSET aLayerSet)
Definition: class_zone.cpp:210
void MIRROR(T &aPoint, const T &aMirrorRef)
Definition: macros.h:114
#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:730
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:739
ZoneConnection GetPadConnection(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:991
std::vector< SEG > m_HatchLines
Definition: class_zone.h:769
ZoneConnection m_PadConnection
Definition: class_zone.h:724
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:518
bool m_IsFilled
True when a zone was filled, false after deleting the filled areas.
Definition: class_zone.h:733
virtual void Flip(const wxPoint &aCentre) override
Function Flip Flip this object, i.e.
Definition: class_zone.cpp:951
ZoneConnection GetZoneConnection() const
Definition: class_pad.cpp:686
SHAPE_POLY_SET * m_Poly
Outline of the zone.
Definition: class_zone.h:700
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:710
int GetThermalWidth() const
Definition: class_pad.cpp:697
void Rotate(const wxPoint &centre, double angle) override
Function Rotate Move the outlines.
Definition: class_zone.cpp:921
bool m_doNotAllowVias
Definition: class_zone.h:721
int GetThermalGap() const
Definition: class_pad.cpp:708
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:701
void CacheTriangulation()
(re)create a list of triangles that "fill" the solid areas.
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
HATCH_STYLE
Zone hatch styles.
Definition: class_zone.h:66
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:285
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:764
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:217
Class LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
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:677
unsigned int m_cornerRadius
Definition: class_zone.h:702
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:891
int GetNetCode() const
Function GetNetCode.
HATCH_STYLE m_hatchStyle
Definition: class_zone.h:767
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.
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:691
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:636
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:720
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:736
bool GetDoNotAllowTracks() const
Definition: class_zone.h:633
int m_ZoneMinThickness
Minimum thickness value in filled areas.
Definition: class_zone.h:726
ZONE_FILL_MODE m_FillMode
How to fill areas: ZFM_POLYGONS => use filled polygons, ZFM_SEGMENTS => fill with segments...
Definition: class_zone.h:743
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:237
bool GetDoNotAllowVias() const
Definition: class_zone.h:632
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:171
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:652
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:801
VECTOR2I A
Definition: seg.h:44
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
HATCH_STYLE GetHatchStyle() const
Definition: class_zone.h:526
void Hatch()
Function Hatch computes the hatch lines depending on the hatch parameters and stores it in the zone&#39;s...
void SetHatchStyle(HATCH_STYLE aStyle)
Definition: class_zone.h:531
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:154
void SetLocalFlags(int aFlags)
Definition: class_zone.h:238
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:361
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.
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:239
virtual void * GetDisplayOptions()
Function GetDisplayOptions A way to pass info to draw functions.
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:967
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:635
unsigned GetPriority() const
Function GetPriority.
Definition: class_zone.h:106
BITMAP_DEF GetMenuImage() const override
Function GetMenuImage returns a pointer to an image to be used in menus.
Message panel definition file.
#define FORCE_SKETCH
Definition: pcbnew.h:73
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
#define ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF
Definition: pcbnew.h:42
class PCB_BASE_FRAME basic PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer...
EDA_UNITS_T
Definition: common.h:160
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:458
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:807
VECTOR2I B
Definition: seg.h:45
Definition: colors.h:62