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