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( 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  NETINFO_ITEM* net;
1051  BOARD* board = GetBoard();
1052 
1053  // Check whether the selected contour is a hole (contour index > 0)
1054  if( m_CornerSelection != nullptr && m_CornerSelection->m_contour > 0 )
1055  text << wxT( " " ) << _( "(Cutout)" );
1056 
1057  if( GetIsKeepout() )
1058  text << wxT( " " ) << _( "(Keepout)" );
1059 
1060  text << wxString::Format( wxT( " (%08lX)" ), m_TimeStamp );
1061 
1062  // Display net name for copper zones
1063  if( !GetIsKeepout() )
1064  {
1065  if( GetNetCode() >= 0 )
1066  {
1067  if( board )
1068  {
1069  net = GetNet();
1070 
1071  if( net )
1072  {
1073  text << wxT( " [" ) << net->GetNetname() << wxT( "]" );
1074  }
1075  }
1076  else
1077  {
1078  text << _( "** NO BOARD DEFINED **" );
1079  }
1080  }
1081  else
1082  { // A netcode < 0 is an error:
1083  // Netname not found or area not initialised
1084  text << wxT( " [" ) << GetNetname() << wxT( "]" );
1085  text << wxT( " <" ) << _( "Not Found" ) << wxT( ">" );
1086  }
1087  }
1088 
1089  wxString msg;
1090  msg.Printf( _( "Zone Outline %s on %s" ), GetChars( text ),
1091  GetChars( GetLayerName() ) );
1092 
1093  return msg;
1094 }
1095 
1096 
1098 {
1099  return m_hatchPitch;
1100 }
1101 
1102 
1103 void ZONE_CONTAINER::SetHatch( int aHatchStyle, int aHatchPitch, bool aRebuildHatch )
1104 {
1105  SetHatchPitch( aHatchPitch );
1106  m_hatchStyle = (ZONE_CONTAINER::HATCH_STYLE) aHatchStyle;
1107 
1108  if( aRebuildHatch )
1109  Hatch();
1110 }
1111 
1112 
1114 {
1115  m_hatchPitch = aPitch;
1116 }
1117 
1118 
1120 {
1121  m_HatchLines.clear();
1122 }
1123 
1124 
1125 // Creates hatch lines inside the outline of the complex polygon
1126 // sort function used in ::Hatch to sort points by descending wxPoint.x values
1127 bool sortEndsByDescendingX( const VECTOR2I& ref, const VECTOR2I& tst )
1128 {
1129  return tst.x < ref.x;
1130 }
1131 
1132 
1134 {
1135  UnHatch();
1136 
1137  if( m_hatchStyle == NO_HATCH || m_hatchPitch == 0 || m_Poly->IsEmpty() )
1138  return;
1139 
1140  // define range for hatch lines
1141  int min_x = m_Poly->Vertex( 0 ).x;
1142  int max_x = m_Poly->Vertex( 0 ).x;
1143  int min_y = m_Poly->Vertex( 0 ).y;
1144  int max_y = m_Poly->Vertex( 0 ).y;
1145 
1146  for( auto iterator = m_Poly->IterateWithHoles(); iterator; iterator++ )
1147  {
1148  if( iterator->x < min_x )
1149  min_x = iterator->x;
1150 
1151  if( iterator->x > max_x )
1152  max_x = iterator->x;
1153 
1154  if( iterator->y < min_y )
1155  min_y = iterator->y;
1156 
1157  if( iterator->y > max_y )
1158  max_y = iterator->y;
1159  }
1160 
1161  // Calculate spacing between 2 hatch lines
1162  int spacing;
1163 
1164  if( m_hatchStyle == DIAGONAL_EDGE )
1165  spacing = m_hatchPitch;
1166  else
1167  spacing = m_hatchPitch * 2;
1168 
1169  // set the "length" of hatch lines (the length on horizontal axis)
1170  int hatch_line_len = m_hatchPitch;
1171 
1172  // To have a better look, give a slope depending on the layer
1173  LAYER_NUM layer = GetLayer();
1174  int slope_flag = (layer & 1) ? 1 : -1; // 1 or -1
1175  double slope = 0.707106 * slope_flag; // 45 degrees slope
1176  int max_a, min_a;
1177 
1178  if( slope_flag == 1 )
1179  {
1180  max_a = KiROUND( max_y - slope * min_x );
1181  min_a = KiROUND( min_y - slope * max_x );
1182  }
1183  else
1184  {
1185  max_a = KiROUND( max_y - slope * max_x );
1186  min_a = KiROUND( min_y - slope * min_x );
1187  }
1188 
1189  min_a = (min_a / spacing) * spacing;
1190 
1191  // calculate an offset depending on layer number,
1192  // for a better look of hatches on a multilayer board
1193  int offset = (layer * 7) / 8;
1194  min_a += offset;
1195 
1196  // loop through hatch lines
1197  #define MAXPTS 200 // Usually we store only few values per one hatch line
1198  // depending on the complexity of the zone outline
1199 
1200  static std::vector<VECTOR2I> pointbuffer;
1201  pointbuffer.clear();
1202  pointbuffer.reserve( MAXPTS + 2 );
1203 
1204  for( int a = min_a; a < max_a; a += spacing )
1205  {
1206  // get intersection points for this hatch line
1207 
1208  // Note: because we should have an even number of intersections with the
1209  // current hatch line and the zone outline (a closed polygon,
1210  // or a set of closed polygons), if an odd count is found
1211  // we skip this line (should not occur)
1212  pointbuffer.clear();
1213 
1214  // Iterate through all vertices
1215  for( auto iterator = m_Poly->IterateSegmentsWithHoles(); iterator; iterator++ )
1216  {
1217  double x, y, x2, y2;
1218  int ok;
1219 
1220  SEG segment = *iterator;
1221 
1222  ok = FindLineSegmentIntersection( a, slope,
1223  segment.A.x, segment.A.y,
1224  segment.B.x, segment.B.y,
1225  &x, &y, &x2, &y2 );
1226 
1227  if( ok )
1228  {
1229  VECTOR2I point( KiROUND( x ), KiROUND( y ) );
1230  pointbuffer.push_back( point );
1231  }
1232 
1233  if( ok == 2 )
1234  {
1235  VECTOR2I point( KiROUND( x2 ), KiROUND( y2 ) );
1236  pointbuffer.push_back( point );
1237  }
1238 
1239  if( pointbuffer.size() >= MAXPTS ) // overflow
1240  {
1241  wxASSERT( 0 );
1242  break;
1243  }
1244  }
1245 
1246  // ensure we have found an even intersection points count
1247  // because intersections are the ends of segments
1248  // inside the polygon(s) and a segment has 2 ends.
1249  // if not, this is a strange case (a bug ?) so skip this hatch
1250  if( pointbuffer.size() % 2 != 0 )
1251  continue;
1252 
1253  // sort points in order of descending x (if more than 2) to
1254  // ensure the starting point and the ending point of the same segment
1255  // are stored one just after the other.
1256  if( pointbuffer.size() > 2 )
1257  sort( pointbuffer.begin(), pointbuffer.end(), sortEndsByDescendingX );
1258 
1259  // creates lines or short segments inside the complex polygon
1260  for( unsigned ip = 0; ip < pointbuffer.size(); ip += 2 )
1261  {
1262  int dx = pointbuffer[ip + 1].x - pointbuffer[ip].x;
1263 
1264  // Push only one line for diagonal hatch,
1265  // or for small lines < twice the line length
1266  // else push 2 small lines
1267  if( m_hatchStyle == DIAGONAL_FULL || std::abs( dx ) < 2 * hatch_line_len )
1268  {
1269  m_HatchLines.push_back( SEG( pointbuffer[ip], pointbuffer[ip + 1] ) );
1270  }
1271  else
1272  {
1273  double dy = pointbuffer[ip + 1].y - pointbuffer[ip].y;
1274  slope = dy / dx;
1275 
1276  if( dx > 0 )
1277  dx = hatch_line_len;
1278  else
1279  dx = -hatch_line_len;
1280 
1281  int x1 = KiROUND( pointbuffer[ip].x + dx );
1282  int x2 = KiROUND( pointbuffer[ip + 1].x - dx );
1283  int y1 = KiROUND( pointbuffer[ip].y + dx * slope );
1284  int y2 = KiROUND( pointbuffer[ip + 1].y - dx * slope );
1285 
1286  m_HatchLines.push_back(SEG(pointbuffer[ip].x, pointbuffer[ip].y, x1, y1));
1287 
1288  m_HatchLines.push_back( SEG( pointbuffer[ip+1].x, pointbuffer[ip+1].y, x2, y2 ) );
1289  }
1290  }
1291  }
1292 }
1293 
1294 
1296 {
1297  return Mils2iu( 20 );
1298 }
1299 
1300 
1302 {
1303  return add_zone_xpm;
1304 }
1305 
1307 {
1308  assert( aImage->Type() == PCB_ZONE_AREA_T );
1309 
1310  std::swap( *((ZONE_CONTAINER*) this), *((ZONE_CONTAINER*) aImage) );
1311 }
1312 
1314 {
1316 }
1317 
1319 {
1320  if( GetNumCorners() <= 2 ) // malformed zone. polygon calculations do not like it ...
1321  return false;
1322 
1323  // Make a smoothed polygon out of the user-drawn polygon if required
1324  switch( m_cornerSmoothingType )
1325  {
1327  aSmoothedPoly = m_Poly->Chamfer( m_cornerRadius );
1328  break;
1329 
1331  // Note: we're now using m_ArcToSegmentsCount only as a hint to determine accuracy
1332  // vs. speed.
1334  aSmoothedPoly = m_Poly->Fillet( m_cornerRadius, ARC_HIGH_DEF );
1335  else
1336  aSmoothedPoly = m_Poly->Fillet( m_cornerRadius, ARC_LOW_DEF );
1337  break;
1338 
1339  default:
1340  // Acute angles between adjacent edges can create issues in calculations,
1341  // in inflate/deflate outlines transforms, especially when the angle is very small.
1342  // We can avoid issues by creating a very small chamfer which remove acute angles,
1343  // or left it without chamfer and use only CPOLYGONS_LIST::InflateOutline to create
1344  // clearance areas
1345  aSmoothedPoly = m_Poly->Chamfer( Millimeter2iu( 0.0 ) );
1346  break;
1347  }
1348 
1349  return true;
1350 };
1351 
1352 /* Function TransformOutlinesShapeWithClearanceToPolygon
1353  * Convert the zone filled areas polygons to polygons
1354  * inflated (optional) by max( aClearanceValue, the zone clearance)
1355  * and copy them in aCornerBuffer
1356  * param aClearanceValue = the clearance around polygons
1357  * param aAddClearance = true to add a clearance area to the polygon
1358  * false to create the outline polygon.
1359  */
1361  SHAPE_POLY_SET& aCornerBuffer, int aMinClearanceValue, bool aUseNetClearance ) const
1362 {
1363  // Creates the zone outline polygon (with holes if any)
1364  SHAPE_POLY_SET polybuffer;
1365  BuildSmoothedPoly( polybuffer );
1366 
1367  // add clearance to outline
1368  int clearance = aMinClearanceValue;
1369 
1370  if( aUseNetClearance && IsOnCopperLayer() )
1371  {
1372  clearance = GetClearance();
1373  if( aMinClearanceValue > clearance )
1374  clearance = aMinClearanceValue;
1375  }
1376 
1377  // Calculate the polygon with clearance
1378  // holes are linked to the main outline, so only one polygon is created.
1379  if( clearance )
1380  polybuffer.Inflate( clearance, 16 );
1381 
1382  polybuffer.Fracture( SHAPE_POLY_SET::PM_FAST );
1383  aCornerBuffer.Append( polybuffer );
1384 }
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:209
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
void GetMsgPanelInfo(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
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:557
timestamp_t m_TimeStamp
Time stamp used for logical links.
Definition: base_struct.h:180
int GetNumCorners(void) const
Access to m_Poly parameters.
Definition: class_zone.h:414
wxString GetSelectMenuText() const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
#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:106
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
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:55
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:248
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:35
EDA_DRAW_FRAME * GetParent() const
Definition: draw_panel.cpp:180
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
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
SHAPE_POLY_SET Chamfer(int aDistance)
Function Chamfer returns a chamfered version of the polygon set.
const wxString & GetNetname() const
Function GetNetname.
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:193
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:162
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:187
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...
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:452
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
VECTOR2I B
Definition: seg.h:47
Definition: colors.h:62