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
58  m_FillMode = 0; // How to fill areas: 0 = use filled polygons, != 0 fill with segments
59  m_priority = 0;
60  m_smoothedPoly = NULL;
62  SetIsKeepout( false );
63  SetDoNotAllowCopperPour( false ); // has meaning only if m_isKeepout == true
64  SetDoNotAllowVias( true ); // has meaning only if m_isKeepout == true
65  SetDoNotAllowTracks( true ); // has meaning only if m_isKeepout == true
66  m_cornerRadius = 0;
67  SetLocalFlags( 0 ); // flags tempoarry used in zone calculations
68  m_Poly = new SHAPE_POLY_SET(); // Outlines
69  aBoard->GetZoneSettings().ExportSetting( *this );
70 }
71 
72 
74  BOARD_CONNECTED_ITEM( aZone )
75 {
76  m_smoothedPoly = NULL;
77 
78  // Should the copy be on the same net?
79  SetNetCode( aZone.GetNetCode() );
80  m_Poly = new SHAPE_POLY_SET( *aZone.m_Poly );
81 
82  // For corner moving, corner index to drag, or nullptr if no selection
83  m_CornerSelection = nullptr;
84  m_IsFilled = aZone.m_IsFilled;
85  m_ZoneClearance = aZone.m_ZoneClearance; // clearance value
87  m_FillMode = aZone.m_FillMode; // Filling mode (segments/polygons)
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_smoothedPoly;
147  delete m_CornerSelection;
148 }
149 
150 
152 {
153  return new ZONE_CONTAINER( *this );
154 }
155 
156 
158 {
159  bool change = ( !m_FilledPolysList.IsEmpty() ) ||
160  ( m_FillSegmList.size() > 0 );
161 
163  m_FillSegmList.clear();
164  m_IsFilled = false;
165 
166  return change;
167 }
168 
169 
171 {
172  const WX_VECTOR_CONVERTER* pos;
173 
174  // The retrieved vertex is a VECTOR2I. Casting it to a union WX_VECTOR_CONVERTER, we can later
175  // return the object shaped as a wxPoint. See the definition of the union in class_zone.h for
176  // more information on this hack.
177  pos = reinterpret_cast<const WX_VECTOR_CONVERTER*>( &GetCornerPosition( 0 ) );
178  return pos->wx;
179 }
180 
181 
183 {
184  return BOARD_ITEM::GetLayer();
185 }
186 
187 
189 {
190  if( GetIsKeepout() )
191  {
192  return ( m_layerSet & LSET::AllCuMask() ).count() > 0;
193  }
194  else
195  {
196  return IsCopperLayer( GetLayer() );
197  }
198 }
199 
200 
201 bool ZONE_CONTAINER::CommonLayerExists( const LSET aLayerSet ) const
202 {
203  LSET common = GetLayerSet() & aLayerSet;
204 
205  return common.count() > 0;
206 }
207 
208 
210 {
211  SetLayerSet( LSET( aLayer ) );
212 
213  m_Layer = aLayer;
214 }
215 
216 
218 {
219  if( GetIsKeepout() )
220  {
221  // Keepouts can only exist on copper layers
222  aLayerSet &= LSET::AllCuMask();
223  }
224 
225  if( aLayerSet.count() == 0 )
226  {
227  return;
228  }
229 
230  m_layerSet = aLayerSet;
231 
232  // Set the single layer to the first selected layer
233  m_Layer = aLayerSet.Seq()[0];
234 }
235 
236 
238 {
239  // TODO - Enable multi-layer zones for all zone types
240  // not just keepout zones
241  if( GetIsKeepout() )
242  {
243  return m_layerSet;
244  }
245  else
246  {
247  return LSET( m_Layer );
248  }
249 }
250 
251 void ZONE_CONTAINER::ViewGetLayers( int aLayers[], int& aCount ) const
252 {
253  if( GetIsKeepout() )
254  {
255  LSEQ layers = m_layerSet.Seq();
256 
257  for( unsigned int idx = 0; idx < layers.size(); idx++ )
258  {
259  aLayers[idx] = layers[idx];
260  }
261 
262  aCount = layers.size();
263  }
264  else
265  {
266  aLayers[0] = m_Layer;
267  aCount = 1;
268  }
269 }
270 
271 
273 {
274  if( GetIsKeepout() )
275  {
276  return m_layerSet.test( aLayer );
277  }
278 
279  return BOARD_ITEM::IsOnLayer( aLayer );
280 }
281 
282 
283 void ZONE_CONTAINER::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, GR_DRAWMODE aDrawMode,
284  const wxPoint& offset )
285 {
286  if( !DC )
287  return;
288 
289  wxPoint seg_start, seg_end;
290  PCB_LAYER_ID curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer;
291  BOARD* brd = GetBoard();
292 
293  auto frame = static_cast<PCB_BASE_FRAME*> ( panel->GetParent() );
294 
295  PCB_LAYER_ID draw_layer = UNDEFINED_LAYER;
296 
297  LSET layers = GetLayerSet() & brd->GetVisibleLayers();
298 
299  // If there are no visible layers and the zone is not highlighted, return
300  if( layers.count() == 0 && !( aDrawMode & GR_HIGHLIGHT ) )
301  {
302  return;
303  }
304 
305  /* Keepout zones can exist on multiple layers
306  * Thus, determining which color to use to render them is a bit tricky.
307  * In descending order of priority:
308  *
309  * 1. If in GR_HIGHLIGHT mode:
310  * a. If zone is on selected layer, use layer color!
311  * b. Else, use grey
312  * 1. Not in GR_HIGHLIGHT mode
313  * a. If zone is on selected layer, use layer color
314  * b. Else, use color of top-most (visible) layer
315  *
316  */
317  if( GetIsKeepout() )
318  {
319  // At least one layer must be provided!
320  assert( GetLayerSet().count() > 0 );
321 
322  // Not on any visible layer?
323  if( layers.count() == 0 && !( aDrawMode & GR_HIGHLIGHT ) )
324  {
325  return;
326  }
327 
328  // Is keepout zone present on the selected layer?
329  if( layers.test( curr_layer ) )
330  {
331  draw_layer = curr_layer;
332  }
333  else
334  {
335  // Select the first (top) visible layer
336  if( layers.count() > 0 )
337  {
338  draw_layer = layers.Seq()[0];
339  }
340  else
341  {
342  draw_layer = GetLayerSet().Seq()[0];
343  }
344  }
345 
346  }
347  /* Non-keepout zones are easier to deal with
348  */
349  else
350  {
351  if( brd->IsLayerVisible( GetLayer() ) == false && !( aDrawMode & GR_HIGHLIGHT ) )
352  {
353  return;
354  }
355 
356  draw_layer = GetLayer();
357  }
358 
359  assert( draw_layer != UNDEFINED_LAYER );
360 
361  auto color = frame->Settings().Colors().GetLayerColor( draw_layer );
362 
363  GRSetDrawMode( DC, aDrawMode );
364  DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)panel->GetDisplayOptions();
365 
366  if( displ_opts->m_ContrastModeDisplay )
367  {
368  if( !IsOnLayer( curr_layer ) )
369  {
371  }
372  }
373 
374  if( ( aDrawMode & GR_HIGHLIGHT ) && !( aDrawMode & GR_AND ) )
375  {
376  color.SetToLegacyHighlightColor();
377  }
378 
379  color.a = 0.588;
380 
381  // draw the lines
382  std::vector<wxPoint> lines;
383  lines.reserve( (GetNumCorners() * 2) + 2 );
384 
385  // Iterate through the segments of the outline
386  for( auto iterator = m_Poly->IterateSegmentsWithHoles(); iterator; iterator++ )
387  {
388  // Create the segment
389  SEG segment = *iterator;
390 
391  lines.push_back( static_cast<wxPoint>( segment.A ) + offset );
392  lines.push_back( static_cast<wxPoint>( segment.B ) + offset );
393  }
394 
395  GRLineArray( panel->GetClipBox(), DC, lines, 0, color );
396 
397  // draw hatches
398  lines.clear();
399  lines.reserve( (m_HatchLines.size() * 2) + 2 );
400 
401  for( unsigned ic = 0; ic < m_HatchLines.size(); ic++ )
402  {
403  seg_start = static_cast<wxPoint>( m_HatchLines[ic].A ) + offset;
404  seg_end = static_cast<wxPoint>( m_HatchLines[ic].B ) + offset;
405  lines.push_back( seg_start );
406  lines.push_back( seg_end );
407  }
408 
409  GRLineArray( panel->GetClipBox(), DC, lines, 0, color );
410 }
411 
412 
414  wxDC* DC, GR_DRAWMODE aDrawMode, const wxPoint& offset )
415 {
416 
417  static std::vector <wxPoint> CornersBuffer;
418  DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)panel->GetDisplayOptions();
419 
420  // outline_mode is false to show filled polys,
421  // and true to show polygons outlines only (test and debug purposes)
422  bool outline_mode = displ_opts->m_DisplayZonesMode == 2 ? true : false;
423 
424  if( DC == NULL )
425  return;
426 
427  if( displ_opts->m_DisplayZonesMode == 1 ) // Do not show filled areas
428  return;
429 
430  if( m_FilledPolysList.IsEmpty() ) // Nothing to draw
431  return;
432 
433  BOARD* brd = GetBoard();
434  PCB_LAYER_ID curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer;
435 
436  auto frame = static_cast<PCB_BASE_FRAME*> ( panel->GetParent() );
437  auto color = frame->Settings().Colors().GetLayerColor( GetLayer() );
438 
439  if( brd->IsLayerVisible( GetLayer() ) == false && !( aDrawMode & GR_HIGHLIGHT ) )
440  return;
441 
442  GRSetDrawMode( DC, aDrawMode );
443 
444  if( displ_opts->m_ContrastModeDisplay )
445  {
446  if( !IsOnLayer( curr_layer ) )
448  }
449 
450  if( ( aDrawMode & GR_HIGHLIGHT ) && !( aDrawMode & GR_AND ) )
451  color.SetToLegacyHighlightColor();
452 
453  color.a = 0.588;
454 
455 
456  for ( int ic = 0; ic < m_FilledPolysList.OutlineCount(); ic++ )
457  {
458  const SHAPE_LINE_CHAIN& path = m_FilledPolysList.COutline( ic );
459 
460  CornersBuffer.clear();
461 
462  wxPoint p0;
463 
464  for( int j = 0; j < path.PointCount(); j++ )
465  {
466  const VECTOR2I& corner = path.CPoint( j );
467 
468  wxPoint coord( corner.x + offset.x, corner.y + offset.y );
469 
470  if( j == 0 )
471  p0 = coord;
472 
473  CornersBuffer.push_back( coord );
474  }
475 
476  CornersBuffer.push_back( p0 );
477 
478  // Draw outlines:
479  if( ( m_ZoneMinThickness > 1 ) || outline_mode )
480  {
481  int ilim = CornersBuffer.size() - 1;
482 
483  for( int is = 0, ie = ilim; is <= ilim; ie = is, is++ )
484  {
485  int x0 = CornersBuffer[is].x;
486  int y0 = CornersBuffer[is].y;
487  int x1 = CornersBuffer[ie].x;
488  int y1 = CornersBuffer[ie].y;
489 
490  // Draw only basic outlines, not extra segments.
491  if( !displ_opts->m_DisplayPcbTrackFill || GetState( FORCE_SKETCH ) )
492  GRCSegm( panel->GetClipBox(), DC,
493  x0, y0, x1, y1,
495  else
496  GRFillCSegm( panel->GetClipBox(), DC,
497  x0, y0, x1, y1, m_ZoneMinThickness, color );
498  }
499  }
500 
501  // Draw areas:
502  if( m_FillMode == 0 && !outline_mode )
503  GRPoly( panel->GetClipBox(), DC, CornersBuffer.size(), &CornersBuffer[0],
504  true, 0, color, color );
505  }
506 
507  if( m_FillMode == 1 && !outline_mode ) // filled with segments
508  {
509  for( unsigned ic = 0; ic < m_FillSegmList.size(); ic++ )
510  {
511  wxPoint start = m_FillSegmList[ic].m_Start + offset;
512  wxPoint end = m_FillSegmList[ic].m_End + offset;
513 
514  if( !displ_opts->m_DisplayPcbTrackFill || GetState( FORCE_SKETCH ) )
515  GRCSegm( panel->GetClipBox(), DC, start.x, start.y, end.x, end.y,
517  else
518  GRFillCSegm( panel->GetClipBox(), DC, start.x, start.y, end.x, end.y,
520  }
521  }
522 }
523 
524 
526 {
527  const int PRELOAD = 0x7FFFFFFF; // Biggest integer (32 bits)
528 
529  int ymax = -PRELOAD;
530  int ymin = PRELOAD;
531  int xmin = PRELOAD;
532  int xmax = -PRELOAD;
533 
534  int count = GetNumCorners();
535 
536  for( int i = 0; i<count; ++i )
537  {
538  wxPoint corner = static_cast<wxPoint>( GetCornerPosition( i ) );
539 
540  ymax = std::max( ymax, corner.y );
541  xmax = std::max( xmax, corner.x );
542  ymin = std::min( ymin, corner.y );
543  xmin = std::min( xmin, corner.x );
544  }
545 
546  EDA_RECT ret( wxPoint( xmin, ymin ), wxSize( xmax - xmin + 1, ymax - ymin + 1 ) );
547 
548  return ret;
549 }
550 
551 
553  GR_DRAWMODE draw_mode )
554 {
555  GR_DRAWMODE current_gr_mode = draw_mode;
556  bool is_close_segment = false;
557 
558  if( !DC )
559  return;
560 
561  PCB_LAYER_ID curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer;
562 
563  auto frame = static_cast<PCB_BASE_FRAME*> ( panel->GetParent() );
564  auto color = frame->Settings().Colors().GetLayerColor( GetLayer() );
565 
566  DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)panel->GetDisplayOptions();
567 
568  if( displ_opts->m_ContrastModeDisplay )
569  {
570  if( !IsOnLayer( curr_layer ) )
572  }
573 
574  // Object to iterate through the corners of the outlines
576 
577  // Segment start and end
578  VECTOR2I seg_start, seg_end;
579 
580  // Remember the first point of this contour
581  VECTOR2I contour_first_point = *iterator;
582 
583  // Iterate through all the corners of the outlines and build the segments to draw
584  while( iterator )
585  {
586  // Get the first point of the current segment
587  seg_start = *iterator;
588 
589  // Get the last point of the current segment, handling the case where the end of the
590  // contour is reached, when the last point of the segment is the first point of the
591  // contour
592  if( !iterator.IsEndContour() )
593  {
594  // Set GR mode to default
595  current_gr_mode = draw_mode;
596 
597  SHAPE_POLY_SET::ITERATOR iterator_copy = iterator;
598  iterator_copy++;
599  if( iterator_copy.IsEndContour() )
600  current_gr_mode = GR_XOR;
601 
602  is_close_segment = false;
603 
604  iterator++;
605  seg_end = *iterator;
606  }
607  else
608  {
609  is_close_segment = true;
610 
611  seg_end = contour_first_point;
612 
613  // Reassign first point of the contour to the next contour start
614  iterator++;
615 
616  if( iterator )
617  contour_first_point = *iterator;
618 
619  // Set GR mode to XOR
620  current_gr_mode = GR_XOR;
621  }
622 
623  GRSetDrawMode( DC, current_gr_mode );
624 
625  if( is_close_segment )
626  GRLine( panel->GetClipBox(), DC, seg_start.x, seg_start.y, seg_end.x, seg_end.y, 0,
627  WHITE );
628  else
629  GRLine( panel->GetClipBox(), DC, seg_start.x, seg_start.y, seg_end.x, seg_end.y, 0,
630  color );
631  }
632 }
633 
634 
636 {
637  if( aPad == NULL || aPad->GetThermalGap() == 0 )
638  return m_ThermalReliefGap;
639  else
640  return aPad->GetThermalGap();
641 }
642 
643 
645 {
646  if( aPad == NULL || aPad->GetThermalWidth() == 0 )
648  else
649  return aPad->GetThermalWidth();
650 }
651 
652 
653 void ZONE_CONTAINER::SetCornerRadius( unsigned int aRadius )
654 {
655  m_cornerRadius = aRadius;
656  if( m_cornerRadius > (unsigned int) Mils2iu( MAX_ZONE_CORNER_RADIUS_MILS ) )
658 };
659 
660 
661 bool ZONE_CONTAINER::HitTest( const wxPoint& aPosition ) const
662 {
663  return HitTestForCorner( aPosition ) || HitTestForEdge( aPosition );
664 }
665 
666 
668 {
670 
671  // If there is some corner to be selected, assign it to m_CornerSelection
672  if( HitTestForCorner( aPosition, corner ) || HitTestForEdge( aPosition, corner ) )
673  {
674  if( m_CornerSelection == nullptr )
676 
677  *m_CornerSelection = corner;
678  }
679 }
680 
681 // Zones outlines have no thickness, so it Hit Test functions
682 // we must have a default distance between the test point
683 // and a corner or a zone edge:
684 #define MAX_DIST_IN_MM 0.25
685 
687  SHAPE_POLY_SET::VERTEX_INDEX& aCornerHit ) const
688 {
689  int distmax = Millimeter2iu( MAX_DIST_IN_MM );
690 
691  return m_Poly->CollideVertex( VECTOR2I( refPos ), aCornerHit, distmax );
692 }
693 
694 
695 bool ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos ) const
696 {
698  return HitTestForCorner( refPos, dummy );
699 }
700 
701 
703  SHAPE_POLY_SET::VERTEX_INDEX& aCornerHit ) const
704 {
705  int distmax = Millimeter2iu( MAX_DIST_IN_MM );
706 
707  return m_Poly->CollideEdge( VECTOR2I( refPos ), aCornerHit, distmax );
708 }
709 
710 
711 bool ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos ) const
712 {
714  return HitTestForEdge( refPos, dummy );
715 }
716 
717 
718 bool ZONE_CONTAINER::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
719 {
720  // Calculate bounding box for zone
721  EDA_RECT bbox = GetBoundingBox();
722  bbox.Normalize();
723 
724  EDA_RECT arect = aRect;
725  arect.Normalize();
726  arect.Inflate( aAccuracy );
727 
728  if( aContained )
729  {
730  return arect.Contains( bbox );
731  }
732  else // Test for intersection between aBox and the polygon
733  // For a polygon, using its bounding box has no sense here
734  {
735  // Fast test: if aBox is outside the polygon bounding box,
736  // rectangles cannot intersect
737  if( !arect.Intersects( bbox ) )
738  return false;
739 
740  // aBox is inside the polygon bounding box,
741  // and can intersect the polygon: use a fine test.
742  // aBox intersects the polygon if at least one aBox corner
743  // is inside the polygon
744 
745  /*
746  wxPoint origin = arect.GetOrigin();
747 
748  int w = arect.GetWidth();
749  int h = arect.GetHeight();
750 
751 
752  if ( HitTestInsideZone( origin ) ||
753  HitTestInsideZone( origin + wxPoint( w, 0 ) ) ||
754  HitTestInsideZone( origin + wxPoint( w, h ) ) ||
755  HitTestInsideZone( origin + wxPoint( 0, h ) ) )
756  {
757  return true;
758  }
759  */
760 
761  // No corner inside aBox, but outlines can intersect aBox
762  // if one of outline corners is inside aBox
763  int count = m_Poly->TotalVertices();
764  for( int ii =0; ii < count; ii++ )
765  {
766  auto vertex = m_Poly->Vertex( ii );
767  auto vertexNext = m_Poly->Vertex( ( ii + 1 ) % count );
768 
769  // Test if the point is within the rect
770  if( arect.Contains( ( wxPoint ) vertex ) )
771  {
772  return true;
773  }
774 
775  // Test if this edge intersects the rect
776  if( arect.Intersects( ( wxPoint ) vertex, ( wxPoint ) vertexNext ) )
777  {
778  return true;
779  }
780  }
781 
782  return false;
783  }
784 }
785 
786 
788 {
789  int myClearance = m_ZoneClearance;
790 
791 #if 1 // Maybe the netclass clearance should not come into play for a zone?
792  // At least the policy decision can be controlled by the zone
793  // itself, i.e. here. On reasons of insufficient documentation,
794  // the user will be less bewildered if we simply respect the
795  // "zone clearance" setting in the zone properties dialog. (At least
796  // until there is a UI boolean for this.)
797 
798  NETCLASSPTR myClass = GetNetClass();
799 
800  if( myClass )
801  myClearance = std::max( myClearance, myClass->GetClearance() );
802 #endif
803 
804  if( aItem )
805  {
806  int hisClearance = aItem->GetClearance( NULL );
807  myClearance = std::max( hisClearance, myClearance );
808  }
809 
810  return myClearance;
811 }
812 
813 
814 bool ZONE_CONTAINER::HitTestFilledArea( const wxPoint& aRefPos ) const
815 {
816  return m_FilledPolysList.Contains( VECTOR2I( aRefPos.x, aRefPos.y ) );
817 }
818 
819 
820 void ZONE_CONTAINER::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList )
821 {
822  wxString msg;
823 
824  msg = _( "Zone Outline" );
825 
826  // Display Cutout instead of Outline for holes inside a zone
827  // i.e. when num contour !=0
828  // Check whether the selected corner is in a hole; i.e., in any contour but the first one.
829  if( m_CornerSelection != nullptr && m_CornerSelection->m_contour > 0 )
830  msg << wxT( " " ) << _( "(Cutout)" );
831 
832  aList.push_back( MSG_PANEL_ITEM( _( "Type" ), msg, DARKCYAN ) );
833 
834  if( GetIsKeepout() )
835  {
836  msg.Empty();
837 
838  if( GetDoNotAllowVias() )
839  AccumulateDescription( msg, _( "No via" ) );
840 
841  if( GetDoNotAllowTracks() )
842  AccumulateDescription( msg, _("No track") );
843 
845  AccumulateDescription( msg, _("No copper pour") );
846 
847  aList.push_back( MSG_PANEL_ITEM( _( "Keepout" ), msg, RED ) );
848  }
849  else if( IsOnCopperLayer() )
850  {
851  if( GetNetCode() >= 0 )
852  {
853  NETINFO_ITEM* net = GetNet();
854 
855  if( net )
856  msg = net->GetNetname();
857  else // Should not occur
858  msg = _( "<unknown>" );
859  }
860  else // a netcode < 0 is an error
861  msg = wxT( "<error>" );
862 
863  aList.push_back( MSG_PANEL_ITEM( _( "NetName" ), msg, RED ) );
864 
865  // Display net code : (useful in test or debug)
866  msg.Printf( wxT( "%d" ), GetNetCode() );
867  aList.push_back( MSG_PANEL_ITEM( _( "NetCode" ), msg, RED ) );
868 
869  // Display priority level
870  msg.Printf( wxT( "%d" ), GetPriority() );
871  aList.push_back( MSG_PANEL_ITEM( _( "Priority" ), msg, BLUE ) );
872  }
873  else
874  {
875  aList.push_back( MSG_PANEL_ITEM( _( "Non Copper Zone" ), wxEmptyString, RED ) );
876  }
877 
878  aList.push_back( MSG_PANEL_ITEM( _( "Layer" ), GetLayerName(), BROWN ) );
879 
880  msg.Printf( wxT( "%d" ), (int) m_Poly->TotalVertices() );
881  aList.push_back( MSG_PANEL_ITEM( _( "Corners" ), msg, BLUE ) );
882 
883  if( m_FillMode )
884  msg = _( "Segments" );
885  else
886  msg = _( "Polygons" );
887 
888  aList.push_back( MSG_PANEL_ITEM( _( "Fill Mode" ), msg, BROWN ) );
889 
890  // Useful for statistics :
891  msg.Printf( wxT( "%d" ), (int) m_HatchLines.size() );
892  aList.push_back( MSG_PANEL_ITEM( _( "Hatch Lines" ), msg, BLUE ) );
893 
894  if( !m_FilledPolysList.IsEmpty() )
895  {
896  msg.Printf( wxT( "%d" ), m_FilledPolysList.TotalVertices() );
897  aList.push_back( MSG_PANEL_ITEM( _( "Corner Count" ), msg, BLUE ) );
898  }
899 }
900 
901 
902 /* Geometric transforms: */
903 
904 void ZONE_CONTAINER::Move( const wxPoint& offset )
905 {
906  /* move outlines */
907  m_Poly->Move( VECTOR2I( offset ) );
908 
909  Hatch();
910 
911  m_FilledPolysList.Move( VECTOR2I( offset.x, offset.y ) );
912 
913  for( unsigned ic = 0; ic < m_FillSegmList.size(); ic++ )
914  {
915  m_FillSegmList[ic].m_Start += offset;
916  m_FillSegmList[ic].m_End += offset;
917  }
918 }
919 
920 
921 void ZONE_CONTAINER::MoveEdge( const wxPoint& offset, int aEdge )
922 {
923  int next_corner;
924 
925  if( m_Poly->GetNeighbourIndexes( aEdge, nullptr, &next_corner ) )
926  {
927  m_Poly->Vertex( aEdge ) += VECTOR2I( offset );
928  m_Poly->Vertex( next_corner ) += VECTOR2I( offset );
929  Hatch();
930  }
931 }
932 
933 
934 void ZONE_CONTAINER::Rotate( const wxPoint& centre, double angle )
935 {
936  wxPoint pos;
937 
938  for( auto iterator = m_Poly->IterateWithHoles(); iterator; iterator++ )
939  {
940  pos = static_cast<wxPoint>( *iterator );
941  RotatePoint( &pos, centre, angle );
942  iterator->x = pos.x;
943  iterator->y = pos.y;
944  }
945 
946  Hatch();
947 
948  /* rotate filled areas: */
949  for( auto ic = m_FilledPolysList.Iterate(); ic; ++ic )
950  RotatePoint( &ic->x, &ic->y, centre.x, centre.y, angle );
951 
952  for( unsigned ic = 0; ic < m_FillSegmList.size(); ic++ )
953  {
954  RotatePoint( &m_FillSegmList[ic].m_Start, centre, angle );
955  RotatePoint( &m_FillSegmList[ic].m_End, centre, angle );
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].m_Start.y, mirror_ref.y );
995  MIRROR( m_FillSegmList[ic].m_End.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 || fabs( 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 }
Definition: colors.h:57
void SetDoNotAllowTracks(bool aEnable)
Definition: class_zone.h:680
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:921
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:283
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:78
void GRPoly(EDA_RECT *ClipBox, wxDC *DC, int n, wxPoint Points[], bool Fill, int width, COLOR4D Color, COLOR4D BgColor)
Definition: gr_basic.cpp:767
int m_ZoneClearance
Clearance value in internal units.
Definition: class_zone.h:767
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:552
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:820
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
int GetNumCorners(void) const
Access to m_Poly parameters.
Definition: class_zone.h:480
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:201
void GRSetDrawMode(wxDC *DC, GR_DRAWMODE draw_mode)
Definition: gr_basic.cpp:290
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:702
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:151
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...
bool GetDoNotAllowCopperPour() const
Definition: class_zone.h:673
bool m_doNotAllowTracks
Definition: class_zone.h:764
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox (virtual)
Definition: class_zone.cpp:525
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
time_t m_TimeStamp
Time stamp used for logical links.
Definition: base_struct.h:183
int PointCount() const
Function PointCount()
bool Contains(const wxPoint &aPoint) const
Function Contains.
void SetCornerRadius(unsigned int aRadius)
Definition: class_zone.cpp:653
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:788
void GRLine(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, COLOR4D Color)
Definition: gr_basic.cpp:352
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:272
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:413
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:114
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:182
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:481
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
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:251
VECTOR2< int > VECTOR2I
Definition: vector2d.h:590
int GetThermalReliefCopperBridge(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:644
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:520
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:787
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:679
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:672
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:237
PCB_LAYER_ID m_Layer
void SetLayerSet(LSET aLayerSet)
Definition: class_zone.cpp:217
void MIRROR(T &aPoint, const T &aMirrorRef)
Definition: macros.h:111
SHAPE_POLY_SET * m_smoothedPoly
Definition: class_zone.h:742
#define MAXPTS
void SetClosed(bool aClosed)
Function SetClosed()
bool m_DisplayPcbTrackFill
Definition: pcbstruct.h:71
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:772
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:781
ZoneConnection GetPadConnection(D_PAD *aPad=NULL) const
Classes used in Pcbnew, CvPcb and GerbView.
std::vector< SEG > m_HatchLines
Definition: class_zone.h:811
ZoneConnection m_PadConnection
Definition: class_zone.h:766
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: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:584
bool m_IsFilled
True when a zone was filled, false after deleting the filled areas.
Definition: class_zone.h:775
int m_FillMode
How to fill areas: 0 => use filled polygons, 1 => fill with segments.
Definition: class_zone.h:785
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:741
int GetThermalReliefGap(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:635
ZONE_CONTAINER(BOARD *parent)
Definition: class_zone.cpp:53
unsigned m_priority
Definition: class_zone.h:752
int GetThermalWidth() const
Definition: class_pad.cpp:661
bool m_ContrastModeDisplay
Definition: pcbstruct.h:85
void Rotate(const wxPoint &centre, double angle) override
Function Rotate Move the outlines.
Definition: class_zone.cpp:934
bool m_doNotAllowVias
Definition: class_zone.h:763
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:209
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:157
int m_cornerSmoothingType
Definition: class_zone.h:743
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
int m_DisplayZonesMode
Definition: pcbstruct.h:77
Definition: colors.h:60
EDA_DRAW_FRAME * GetParent() const
Definition: draw_panel.cpp:174
HATCH_STYLE
Zone hatch styles.
Definition: class_zone.h:85
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:251
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)
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:806
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:236
Class LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
unsigned int m_cornerRadius
Definition: class_zone.h:744
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
Class DISPLAY_OPTIONS handles display options like enable/disable some optional drawings.
Definition: pcbstruct.h:62
void Move(const wxPoint &offset) override
Function Move Move the outlines.
Definition: class_zone.cpp:904
int GetNetCode() const
Function GetNetCode.
HATCH_STYLE m_hatchStyle
Definition: class_zone.h:809
Definition: seg.h:37
const wxPoint & GetPosition() const override
Function GetPosition.
Definition: class_zone.cpp:170
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:678
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:762
bool IsOnCopperLayer() const
Function IsOnCopperLayer.
Definition: class_zone.cpp:188
int m_ThermalReliefGap
Width of the copper bridge in thermal reliefs.
Definition: class_zone.h:778
bool GetDoNotAllowTracks() const
Definition: class_zone.h:675
int m_ZoneMinThickness
Minimum thickness value in filled areas.
Definition: class_zone.h:768
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
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:256
bool GetDoNotAllowVias() const
Definition: class_zone.h:674
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:661
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:814
VECTOR2I A
Definition: seg.h:47
Class EDA_RECT handles the component boundary box.
HATCH_STYLE GetHatchStyle() const
Definition: class_zone.h:564
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:569
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:165
void SetLocalFlags(int aFlags)
Definition: class_zone.h:257
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:427
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:684
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:677
unsigned GetPriority() const
Function GetPriority.
Definition: class_zone.h:119
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:686
#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:836
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.
std::vector< SEGMENT > m_FillSegmList
Segments used to fill the zone (m_FillMode ==1 ), when fill zone by segment is used.
Definition: class_zone.h:796
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:48
Definition: colors.h:62