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