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) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6  * Copyright (C) 1992-2015 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 <colors_selection.h>
38 #include <richio.h>
39 #include <macros.h>
40 #include <wxBasePcbFrame.h>
41 #include <msgpanel.h>
42 #include <bitmaps.h>
43 
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 = -1;
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 CPolyLine(); // 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 CPolyLine( *aZone.m_Poly );
81 
82  // For corner moving, corner index to drag, or -1 if no selection
83  m_CornerSelection = -1;
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  SetLocalFlags( aZone.GetLocalFlags() );
105 }
106 
107 
109 {
111 
113  m_Poly->Copy( aOther.m_Poly ); // copy outlines
114  m_CornerSelection = -1; // for corner moving, corner index to drag or -1 if no selection
115  m_ZoneClearance = aOther.m_ZoneClearance; // clearance value
117  m_FillMode = aOther.m_FillMode; // filling mode (segments/polygons)
124  m_Poly->m_HatchLines = aOther.m_Poly->m_HatchLines; // copy vector <CSegment>
127  m_FillSegmList.clear();
129 
130  return *this;
131 }
132 
133 
135 {
136  delete m_Poly;
137  m_Poly = NULL;
138 }
139 
140 
142 {
143  return new ZONE_CONTAINER( *this );
144 }
145 
146 
148 {
149  bool change = ( !m_FilledPolysList.IsEmpty() ) ||
150  ( m_FillSegmList.size() > 0 );
151 
153  m_FillSegmList.clear();
154  m_IsFilled = false;
155 
156  return change;
157 }
158 
159 
161 {
162  static const wxPoint dummy;
163 
164  return m_Poly ? GetCornerPosition( 0 ) : dummy;
165 }
166 
167 
168 void ZONE_CONTAINER::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, GR_DRAWMODE aDrawMode,
169  const wxPoint& offset )
170 {
171  if( !DC )
172  return;
173 
174  wxPoint seg_start, seg_end;
175  LAYER_ID curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer;
176  BOARD* brd = GetBoard();
177 
178  COLOR4D color = brd->GetLayerColor( m_Layer );
179 
180  if( brd->IsLayerVisible( m_Layer ) == false && !( aDrawMode & GR_HIGHLIGHT ) )
181  return;
182 
183  GRSetDrawMode( DC, aDrawMode );
184  DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)panel->GetDisplayOptions();
185 
186  if( displ_opts->m_ContrastModeDisplay )
187  {
188  if( !IsOnLayer( curr_layer ) )
189  color = COLOR4D( DARKDARKGRAY );
190  }
191 
192  if( ( aDrawMode & GR_HIGHLIGHT ) && !( aDrawMode & GR_AND ) )
193  color.SetToLegacyHighlightColor();
194 
195  color.a = 0.588;
196 
197  // draw the lines
198  int i_start_contour = 0;
199  std::vector<wxPoint> lines;
200  lines.reserve( (GetNumCorners() * 2) + 2 );
201 
202  for( int ic = 0; ic < GetNumCorners(); ic++ )
203  {
204  seg_start = GetCornerPosition( ic ) + offset;
205 
206  if( !m_Poly->m_CornersList.IsEndContour( ic ) && ic < GetNumCorners() - 1 )
207  {
208  seg_end = GetCornerPosition( ic + 1 ) + offset;
209  }
210  else
211  {
212  seg_end = GetCornerPosition( i_start_contour ) + offset;
213  i_start_contour = ic + 1;
214  }
215 
216  lines.push_back( seg_start );
217  lines.push_back( seg_end );
218  }
219 
220  GRLineArray( panel->GetClipBox(), DC, lines, 0, color );
221 
222  // draw hatches
223  lines.clear();
224  lines.reserve( (m_Poly->m_HatchLines.size() * 2) + 2 );
225 
226  for( unsigned ic = 0; ic < m_Poly->m_HatchLines.size(); ic++ )
227  {
228  seg_start = m_Poly->m_HatchLines[ic].m_Start + offset;
229  seg_end = m_Poly->m_HatchLines[ic].m_End + offset;
230  lines.push_back( seg_start );
231  lines.push_back( seg_end );
232  }
233 
234  GRLineArray( panel->GetClipBox(), DC, lines, 0, color );
235 }
236 
237 
239  wxDC* DC, GR_DRAWMODE aDrawMode, const wxPoint& offset )
240 {
241  static std::vector <wxPoint> CornersBuffer;
242  DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)panel->GetDisplayOptions();
243 
244  // outline_mode is false to show filled polys,
245  // and true to show polygons outlines only (test and debug purposes)
246  bool outline_mode = displ_opts->m_DisplayZonesMode == 2 ? true : false;
247 
248  if( DC == NULL )
249  return;
250 
251  if( displ_opts->m_DisplayZonesMode == 1 ) // Do not show filled areas
252  return;
253 
254  if( m_FilledPolysList.IsEmpty() ) // Nothing to draw
255  return;
256 
257  BOARD* brd = GetBoard();
258  LAYER_ID curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer;
259  COLOR4D color = brd->GetLayerColor( m_Layer );
260 
261  if( brd->IsLayerVisible( m_Layer ) == false && !( aDrawMode & GR_HIGHLIGHT ) )
262  return;
263 
264  GRSetDrawMode( DC, aDrawMode );
265 
266  if( displ_opts->m_ContrastModeDisplay )
267  {
268  if( !IsOnLayer( curr_layer ) )
269  color = COLOR4D( DARKDARKGRAY );
270  }
271 
272  if( ( aDrawMode & GR_HIGHLIGHT ) && !( aDrawMode & GR_AND ) )
273  color.SetToLegacyHighlightColor();
274 
275  color.a = 0.588;
276 
277 
278  for ( int ic = 0; ic < m_FilledPolysList.OutlineCount(); ic++ )
279  {
280  const SHAPE_LINE_CHAIN& path = m_FilledPolysList.COutline( ic );
281 
282  CornersBuffer.clear();
283 
284  wxPoint p0;
285 
286  for( int j = 0; j < path.PointCount(); j++ )
287  {
288  const VECTOR2I& corner = path.CPoint( j );
289 
290  wxPoint coord( corner.x + offset.x, corner.y + offset.y );
291 
292  if( j == 0 )
293  p0 = coord;
294 
295  CornersBuffer.push_back( coord );
296  }
297 
298  CornersBuffer.push_back( p0 );
299 
300  // Draw outlines:
301  if( ( m_ZoneMinThickness > 1 ) || outline_mode )
302  {
303  int ilim = CornersBuffer.size() - 1;
304 
305  for( int is = 0, ie = ilim; is <= ilim; ie = is, is++ )
306  {
307  int x0 = CornersBuffer[is].x;
308  int y0 = CornersBuffer[is].y;
309  int x1 = CornersBuffer[ie].x;
310  int y1 = CornersBuffer[ie].y;
311 
312  // Draw only basic outlines, not extra segments.
313  if( !displ_opts->m_DisplayPcbTrackFill || GetState( FORCE_SKETCH ) )
314  GRCSegm( panel->GetClipBox(), DC,
315  x0, y0, x1, y1,
316  m_ZoneMinThickness, color );
317  else
318  GRFillCSegm( panel->GetClipBox(), DC,
319  x0, y0, x1, y1, m_ZoneMinThickness, color );
320  }
321  }
322 
323  // Draw areas:
324  if( m_FillMode == 0 && !outline_mode )
325  GRPoly( panel->GetClipBox(), DC, CornersBuffer.size(), &CornersBuffer[0],
326  true, 0, color, color );
327  }
328 
329  if( m_FillMode == 1 && !outline_mode ) // filled with segments
330  {
331  for( unsigned ic = 0; ic < m_FillSegmList.size(); ic++ )
332  {
333  wxPoint start = m_FillSegmList[ic].m_Start + offset;
334  wxPoint end = m_FillSegmList[ic].m_End + offset;
335 
336  if( !displ_opts->m_DisplayPcbTrackFill || GetState( FORCE_SKETCH ) )
337  GRCSegm( panel->GetClipBox(), DC, start.x, start.y, end.x, end.y,
338  m_ZoneMinThickness, color );
339  else
340  GRFillCSegm( panel->GetClipBox(), DC, start.x, start.y, end.x, end.y,
341  m_ZoneMinThickness, color );
342  }
343  }
344 }
345 
346 
348 {
349  const int PRELOAD = 0x7FFFFFFF; // Biggest integer (32 bits)
350 
351  int ymax = -PRELOAD;
352  int ymin = PRELOAD;
353  int xmin = PRELOAD;
354  int xmax = -PRELOAD;
355 
356  int count = GetNumCorners();
357 
358  for( int i = 0; i<count; ++i )
359  {
360  wxPoint corner = GetCornerPosition( i );
361 
362  ymax = std::max( ymax, corner.y );
363  xmax = std::max( xmax, corner.x );
364  ymin = std::min( ymin, corner.y );
365  xmin = std::min( xmin, corner.x );
366  }
367 
368  EDA_RECT ret( wxPoint( xmin, ymin ), wxSize( xmax - xmin + 1, ymax - ymin + 1 ) );
369 
370  return ret;
371 }
372 
373 
375  GR_DRAWMODE draw_mode )
376 {
377  GR_DRAWMODE current_gr_mode = draw_mode;
378  bool is_close_segment = false;
379 
380  if( !DC )
381  return;
382 
383  LAYER_ID curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer;
384  BOARD* brd = GetBoard();
385  COLOR4D color = brd->GetLayerColor( m_Layer );
386  DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)panel->GetDisplayOptions();
387 
388  if( displ_opts->m_ContrastModeDisplay )
389  {
390  if( !IsOnLayer( curr_layer ) )
391  color = COLOR4D( DARKDARKGRAY );
392  }
393 
394  // draw the lines
395  wxPoint start_contour_pos = GetCornerPosition( 0 );
396  int icmax = GetNumCorners() - 1;
397 
398  for( int ic = 0; ic <= icmax; ic++ )
399  {
400  int xi = GetCornerPosition( ic ).x;
401  int yi = GetCornerPosition( ic ).y;
402  int xf, yf;
403 
404  if( !m_Poly->m_CornersList.IsEndContour( ic ) && ic < icmax )
405  {
406  is_close_segment = false;
407  xf = GetCornerPosition( ic + 1 ).x;
408  yf = GetCornerPosition( ic + 1 ).y;
409 
410  if( m_Poly->m_CornersList.IsEndContour( ic + 1 ) || (ic == icmax - 1) )
411  current_gr_mode = GR_XOR;
412  else
413  current_gr_mode = draw_mode;
414  }
415  else // Draw the line from last corner to the first corner of the current contour
416  {
417  is_close_segment = true;
418  current_gr_mode = GR_XOR;
419  xf = start_contour_pos.x;
420  yf = start_contour_pos.y;
421 
422  // Prepare the next contour for drawing, if exists
423  if( ic < icmax )
424  start_contour_pos = GetCornerPosition( ic + 1 );
425  }
426 
427  GRSetDrawMode( DC, current_gr_mode );
428 
429  if( is_close_segment )
430  GRLine( panel->GetClipBox(), DC, xi, yi, xf, yf, 0, WHITE );
431  else
432  GRLine( panel->GetClipBox(), DC, xi, yi, xf, yf, 0, color );
433  }
434 }
435 
436 
438 {
439  if( aPad == NULL || aPad->GetThermalGap() == 0 )
440  return m_ThermalReliefGap;
441  else
442  return aPad->GetThermalGap();
443 }
444 
445 
447 {
448  if( aPad == NULL || aPad->GetThermalWidth() == 0 )
450  else
451  return aPad->GetThermalWidth();
452 }
453 
454 
455 void ZONE_CONTAINER::SetCornerRadius( unsigned int aRadius )
456 {
457  m_cornerRadius = aRadius;
458  if( m_cornerRadius > (unsigned int) Mils2iu( MAX_ZONE_CORNER_RADIUS_MILS ) )
460 };
461 
462 
463 bool ZONE_CONTAINER::HitTest( const wxPoint& aPosition ) const
464 {
465  if( HitTestForCorner( aPosition ) >= 0 )
466  return true;
467 
468  if( HitTestForEdge( aPosition ) >= 0 )
469  return true;
470 
471  return false;
472 }
473 
475 {
476  m_CornerSelection = HitTestForCorner( aPosition );
477 
478  if( m_CornerSelection < 0 )
479  m_CornerSelection = HitTestForEdge( aPosition );
480 }
481 
482 
483 // Zones outlines have no thickness, so it Hit Test functions
484 // we must have a default distance between the test point
485 // and a corner or a zone edge:
486 #define MAX_DIST_IN_MM 0.25
487 
488 int ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos ) const
489 {
490  int distmax = Millimeter2iu( MAX_DIST_IN_MM );
491  return m_Poly->HitTestForCorner( refPos, distmax );
492 }
493 
494 
495 int ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos ) const
496 {
497  int distmax = Millimeter2iu( MAX_DIST_IN_MM );
498  return m_Poly->HitTestForEdge( refPos, distmax );
499 }
500 
501 
502 bool ZONE_CONTAINER::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
503 {
504  EDA_RECT arect = aRect;
505  arect.Inflate( aAccuracy );
506  EDA_RECT bbox = m_Poly->GetBoundingBox();
507  bbox.Normalize();
508 
509  if( aContained )
510  return arect.Contains( bbox );
511  else // Test for intersection between aRect and the polygon
512  // For a polygon, using its bounding box has no sense here
513  {
514  // Fast test: if aRect is outside the polygon bounding box,
515  // rectangles cannot intersect
516  if( ! bbox.Intersects( arect ) )
517  return false;
518 
519  // aRect is inside the polygon bounding box,
520  // and can intersect the polygon: use a fine test.
521  // aRect intersects the polygon if at least one aRect corner
522  // is inside the polygon
523  wxPoint corner = arect.GetOrigin();
524 
525  if( HitTestInsideZone( corner ) )
526  return true;
527 
528  corner.x = arect.GetEnd().x;
529 
530  if( HitTestInsideZone( corner ) )
531  return true;
532 
533  corner = arect.GetEnd();
534 
535  if( HitTestInsideZone( corner ) )
536  return true;
537 
538  corner.x = arect.GetOrigin().x;
539 
540  if( HitTestInsideZone( corner ) )
541  return true;
542 
543  // No corner inside arect, but outlines can intersect arect
544  // if one of outline corners is inside arect
545  int count = m_Poly->GetCornersCount();
546  for( int ii =0; ii < count; ii++ )
547  {
548  if( arect.Contains( m_Poly->GetPos( ii ) ) )
549  return true;
550  }
551 
552  return false;
553  }
554 }
555 
556 
558 {
559  int myClearance = m_ZoneClearance;
560 
561 #if 0 // Maybe the netclass clearance should not come into play for a zone?
562  // At least the policy decision can be controlled by the zone
563  // itself, i.e. here. On reasons of insufficient documentation,
564  // the user will be less bewildered if we simply respect the
565  // "zone clearance" setting in the zone properties dialog. (At least
566  // until there is a UI boolean for this.)
567 
568  NETCLASSPTR myClass = GetNetClass();
569 
570  if( myClass )
571  myClearance = std::max( myClearance, myClass->GetClearance() );
572 #endif
573 
574  if( aItem )
575  {
576  int hisClearance = aItem->GetClearance( NULL );
577  myClearance = std::max( hisClearance, myClearance );
578  }
579 
580  return myClearance;
581 }
582 
583 
584 bool ZONE_CONTAINER::HitTestFilledArea( const wxPoint& aRefPos ) const
585 {
586  return m_FilledPolysList.Contains( VECTOR2I( aRefPos.x, aRefPos.y ) );
587 }
588 
589 
590 void ZONE_CONTAINER::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList )
591 {
592  wxString msg;
593 
594  msg = _( "Zone Outline" );
595 
596  // Display Cutout instead of Outline for holes inside a zone
597  // i.e. when num contour !=0
598  int ncont = m_Poly->GetContour( m_CornerSelection );
599 
600  if( ncont )
601  msg << wxT( " " ) << _( "(Cutout)" );
602 
603  aList.push_back( MSG_PANEL_ITEM( _( "Type" ), msg, DARKCYAN ) );
604 
605  if( GetIsKeepout() )
606  {
607  msg.Empty();
608 
609  if( GetDoNotAllowVias() )
610  AccumulateDescription( msg, _( "No via" ) );
611 
612  if( GetDoNotAllowTracks() )
613  AccumulateDescription( msg, _("No track") );
614 
616  AccumulateDescription( msg, _("No copper pour") );
617 
618  aList.push_back( MSG_PANEL_ITEM( _( "Keepout" ), msg, RED ) );
619  }
620  else if( IsOnCopperLayer() )
621  {
622  if( GetNetCode() >= 0 )
623  {
624  NETINFO_ITEM* net = GetNet();
625 
626  if( net )
627  msg = net->GetNetname();
628  else // Should not occur
629  msg = _( "<unknown>" );
630  }
631  else // a netcode < 0 is an error
632  msg = wxT( "<error>" );
633 
634  aList.push_back( MSG_PANEL_ITEM( _( "NetName" ), msg, RED ) );
635 
636  // Display net code : (useful in test or debug)
637  msg.Printf( wxT( "%d" ), GetNetCode() );
638  aList.push_back( MSG_PANEL_ITEM( _( "NetCode" ), msg, RED ) );
639 
640  // Display priority level
641  msg.Printf( wxT( "%d" ), GetPriority() );
642  aList.push_back( MSG_PANEL_ITEM( _( "Priority" ), msg, BLUE ) );
643  }
644  else
645  {
646  aList.push_back( MSG_PANEL_ITEM( _( "Non Copper Zone" ), wxEmptyString, RED ) );
647  }
648 
649  aList.push_back( MSG_PANEL_ITEM( _( "Layer" ), GetLayerName(), BROWN ) );
650 
651  msg.Printf( wxT( "%d" ), (int) m_Poly->m_CornersList.GetCornersCount() );
652  aList.push_back( MSG_PANEL_ITEM( _( "Corners" ), msg, BLUE ) );
653 
654  if( m_FillMode )
655  msg = _( "Segments" );
656  else
657  msg = _( "Polygons" );
658 
659  aList.push_back( MSG_PANEL_ITEM( _( "Fill Mode" ), msg, BROWN ) );
660 
661  // Useful for statistics :
662  msg.Printf( wxT( "%d" ), (int) m_Poly->m_HatchLines.size() );
663  aList.push_back( MSG_PANEL_ITEM( _( "Hatch Lines" ), msg, BLUE ) );
664 
665  if( !m_FilledPolysList.IsEmpty() )
666  {
667  msg.Printf( wxT( "%d" ), m_FilledPolysList.TotalVertices() );
668  aList.push_back( MSG_PANEL_ITEM( _( "Corner Count" ), msg, BLUE ) );
669  }
670 }
671 
672 
673 /* Geometric transforms: */
674 
675 void ZONE_CONTAINER::Move( const wxPoint& offset )
676 {
677  /* move outlines */
678  for( unsigned ii = 0; ii < m_Poly->m_CornersList.GetCornersCount(); ii++ )
679  {
680  SetCornerPosition( ii, GetCornerPosition( ii ) + offset );
681  }
682 
683  m_Poly->Hatch();
684 
685  m_FilledPolysList.Move( VECTOR2I( offset.x, offset.y ) );
686 
687  for( unsigned ic = 0; ic < m_FillSegmList.size(); ic++ )
688  {
689  m_FillSegmList[ic].m_Start += offset;
690  m_FillSegmList[ic].m_End += offset;
691  }
692 }
693 
694 
695 void ZONE_CONTAINER::MoveEdge( const wxPoint& offset, int aEdge )
696 {
697  // Move the start point of the selected edge:
698  SetCornerPosition( aEdge, GetCornerPosition( aEdge ) + offset );
699 
700  // Move the end point of the selected edge:
701  if( m_Poly->m_CornersList.IsEndContour( aEdge ) || aEdge == GetNumCorners() - 1 )
702  {
703  int icont = m_Poly->GetContour( aEdge );
704  aEdge = m_Poly->GetContourStart( icont );
705  }
706  else
707  {
708  aEdge++;
709  }
710 
711  SetCornerPosition( aEdge, GetCornerPosition( aEdge ) + offset );
712 
713  m_Poly->Hatch();
714 }
715 
716 
717 void ZONE_CONTAINER::Rotate( const wxPoint& centre, double angle )
718 {
719  wxPoint pos;
720 
721  for( unsigned ic = 0; ic < m_Poly->m_CornersList.GetCornersCount(); ic++ )
722  {
723  pos = m_Poly->m_CornersList.GetPos( ic );
724  RotatePoint( &pos, centre, angle );
725  m_Poly->SetX( ic, pos.x );
726  m_Poly->SetY( ic, pos.y );
727  }
728 
729  m_Poly->Hatch();
730 
731  /* rotate filled areas: */
732  for( SHAPE_POLY_SET::ITERATOR ic = m_FilledPolysList.Iterate(); ic; ++ic )
733  RotatePoint( &ic->x, &ic->y, centre.x, centre.y, angle );
734 
735  for( unsigned ic = 0; ic < m_FillSegmList.size(); ic++ )
736  {
737  RotatePoint( &m_FillSegmList[ic].m_Start, centre, angle );
738  RotatePoint( &m_FillSegmList[ic].m_End, centre, angle );
739  }
740 }
741 
742 
743 void ZONE_CONTAINER::Flip( const wxPoint& aCentre )
744 {
745  Mirror( aCentre );
746  int copperLayerCount = GetBoard()->GetCopperLayerCount();
747  SetLayer( FlipLayer( GetLayer(), copperLayerCount ) );
748 }
749 
750 
751 void ZONE_CONTAINER::Mirror( const wxPoint& mirror_ref )
752 {
753  for( unsigned ic = 0; ic < m_Poly->m_CornersList.GetCornersCount(); ic++ )
754  {
755  int py = mirror_ref.y - m_Poly->m_CornersList.GetY( ic );
756  m_Poly->m_CornersList.SetY( ic, py + mirror_ref.y );
757  }
758 
759  m_Poly->Hatch();
760 
761  for( SHAPE_POLY_SET::ITERATOR ic = m_FilledPolysList.Iterate(); ic; ++ic )
762  {
763  int py = mirror_ref.y - ic->y;
764  ic->y = py + mirror_ref.y;
765  }
766 
767  for( unsigned ic = 0; ic < m_FillSegmList.size(); ic++ )
768  {
769  MIRROR( m_FillSegmList[ic].m_Start.y, mirror_ref.y );
770  MIRROR( m_FillSegmList[ic].m_End.y, mirror_ref.y );
771  }
772 }
773 
774 
776 {
777  if( aPad == NULL || aPad->GetZoneConnection() == PAD_ZONE_CONN_INHERITED )
778  return m_PadConnection;
779  else
780  return aPad->GetZoneConnection();
781 }
782 
783 
784 void ZONE_CONTAINER::AddPolygon( std::vector< wxPoint >& aPolygon )
785 {
786  if( aPolygon.empty() )
787  return;
788 
789  for( unsigned i = 0; i < aPolygon.size(); i++ )
790  {
791  if( i == 0 )
792  m_Poly->Start( GetLayer(), aPolygon[i].x, aPolygon[i].y, GetHatchStyle() );
793  else
794  AppendCorner( aPolygon[i] );
795  }
796 
798 }
799 
800 
801 
803 {
804  wxString text;
805  NETINFO_ITEM* net;
806  BOARD* board = GetBoard();
807 
808  int ncont = m_Poly->GetContour( m_CornerSelection );
809 
810  if( ncont )
811  text << wxT( " " ) << _( "(Cutout)" );
812 
813  if( GetIsKeepout() )
814  text << wxT( " " ) << _( "(Keepout)" );
815 
816  text << wxString::Format( wxT( " (%08lX)" ), m_TimeStamp );
817 
818  // Display net name for copper zones
819  if( !GetIsKeepout() )
820  {
821  if( GetNetCode() >= 0 )
822  {
823  if( board )
824  {
825  net = GetNet();
826 
827  if( net )
828  {
829  text << wxT( " [" ) << net->GetNetname() << wxT( "]" );
830  }
831  }
832  else
833  {
834  text << _( "** NO BOARD DEFINED **" );
835  }
836  }
837  else
838  { // A netcode < 0 is an error:
839  // Netname not found or area not initialised
840  text << wxT( " [" ) << GetNetname() << wxT( "]" );
841  text << wxT( " <" ) << _( "Not Found" ) << wxT( ">" );
842  }
843  }
844 
845  wxString msg;
846  msg.Printf( _( "Zone Outline %s on %s" ), GetChars( text ),
847  GetChars( GetLayerName() ) );
848 
849  return msg;
850 }
851 
852 
854 {
855  return add_zone_xpm;
856 }
Definition: colors.h:57
void SetDoNotAllowTracks(bool aEnable)
Definition: class_zone.h:535
void MoveEdge(const wxPoint &offset, int aEdge)
Function MoveEdge Move the outline Edge.
Definition: class_zone.cpp:695
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:168
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:78
void SetHatchPitch(int pitch)
Definition: PolyLine.h:424
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:570
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:374
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:590
bool IsEndContour(int ic) const
Definition: PolyLine.h:131
const ZONE_SETTINGS & GetZoneSettings() const
Definition: class_board.h:554
int GetNumCorners(void) const
Access to m_Poly parameters.
Definition: class_zone.h:411
wxString GetSelectMenuText() const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
Definition: class_zone.cpp:802
const wxPoint & GetPos(int ic) const
Definition: PolyLine.h:394
const EDA_RECT GetBoundingBox()
Definition: PolyLine.cpp:551
PNG memory record (file in memory).
Definition: bitmap_types.h:38
void GRSetDrawMode(wxDC *DC, GR_DRAWMODE draw_mode)
Definition: gr_basic.cpp:290
void Copy(const CPolyLine *src)
Definition: PolyLine.cpp:929
EDA_ITEM * Clone() const override
Function Clone creates a duplicate of this item with linked list members set to NULL.
Definition: class_zone.cpp:141
void Start(LAYER_NUM layer, int x, int y, int hatch)
Definition: PolyLine.cpp:186
bool GetDoNotAllowCopperPour() const
Definition: class_zone.h:528
bool m_doNotAllowTracks
Definition: class_zone.h:567
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox (virtual)
Definition: class_zone.cpp:347
time_t m_TimeStamp
Time stamp used for logical links.
Definition: base_struct.h:169
int PointCount() const
Function PointCount()
bool Contains(const wxPoint &aPoint) const
Function Contains.
void SetCornerRadius(unsigned int aRadius)
Definition: class_zone.cpp:455
enum HATCH_STYLE GetHatchStyle() const
Definition: PolyLine.h:399
void SetX(int ic, int x)
Definition: PolyLine.h:409
void GRLine(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, COLOR4D Color)
Definition: gr_basic.cpp:352
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:238
void Hatch()
Definition: PolyLine.cpp:714
ZoneConnection
How pads are covered by copper in zone.
Definition: zones.h:55
COLOR4D GetLayerColor(LAYER_ID aLayer) const
Function GetLayerColor gets a layer color for any valid layer, including non-copper ones...
int HitTestForEdge(const wxPoint &refPos) const
Function HitTestForEdge tests if the given wxPoint is near a segment defined by 2 corners...
Definition: class_zone.cpp:495
virtual void SetLayer(LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
int GetCopperLayerCount() const
Function GetCopperLayerCount.
class ZONE_CONTAINER, a zone area
Definition: typeinfo.h:114
void RemoveAllContours(void)
function RemoveAllContours removes all corners from the list.
Definition: PolyLine.cpp:499
int TotalVertices() const
Returns total number of vertices stored in the set.
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.
CPOLYGONS_LIST m_CornersList
Definition: PolyLine.h:487
unsigned GetCornersCount() const
Definition: PolyLine.h:146
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:317
int OutlineCount() const
Returns the number of outlines in the set
int HitTestForCorner(const wxPoint &aPos, int aDistMax) const
Function HitTestForCorner test is the point aPos is near (< aDistMax ) a corner.
Definition: PolyLine.cpp:1182
int GetState(int type) const
Definition: base_struct.h:237
int m_CornerSelection
The index of the corner being moved or -1 if no corner is selected.
Definition: class_zone.h:591
LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
VECTOR2< int > VECTOR2I
Definition: vector2d.h:580
int GetThermalReliefCopperBridge(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:446
Class BOARD_CONNECTED_ITEM is a base class derived from BOARD_ITEM for items that can be connected an...
wxString GetLayerName() const
Function GetLayerName returns the name of the PCB layer on which the item resides.
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in 1/10000 inches.
Definition: class_zone.cpp:557
void SetDoNotAllowVias(bool aEnable)
Definition: class_zone.h:534
This file contains miscellaneous commonly used macros and functions.
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:527
virtual bool IsOnLayer(LAYER_ID aLayer) const
Function IsOnLayer tests to see if this object is on the given layer.
CPolyLine * m_Poly
Outline of the zone.
Definition: class_zone.h:546
std::vector< CSegment > m_HatchLines
Definition: PolyLine.h:488
const wxPoint & GetOrigin() const
void MIRROR(T &aPoint, const T &aMirrorRef)
Definition: macros.h:111
CPolyLine * m_smoothedPoly
Definition: class_zone.h:547
bool m_DisplayPcbTrackFill
Definition: pcbstruct.h:71
LAYER_ID m_Layer
int m_ArcToSegmentsCount
The number of segments to convert a circle to a polygon.
Definition: class_zone.h:575
double a
Alpha component.
Definition: color4d.h:284
int HitTestForCorner(const wxPoint &refPos) const
Function HitTestForCorner tests if the given wxPoint near a corner Set m_CornerSelection to -1 if not...
Definition: class_zone.cpp:488
int m_ThermalReliefCopperBridge
Definition: class_zone.h:584
int Append(int x, int y, int aOutline=-1, int aHole=-1)
Appends a vertex at the end of the given outline/hole (default: the last outline) ...
ZoneConnection GetPadConnection(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:775
Classes used in Pcbnew, CvPcb and GerbView.
ZoneConnection m_PadConnection
Definition: class_zone.h:569
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:108
GR_DRAWMODE
Drawmode. Compositing mode plus a flag or two.
Definition: gr_basic.h:41
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 HitTestInsideZone(const wxPoint &aPosition) const
Function HitTest tests if a point is inside the zone area, i.e.
Definition: class_zone.h:232
bool m_IsFilled
True when a zone was filled, false after deleting the filled areas.
Definition: class_zone.h:578
int m_FillMode
How to fill areas: 0 => use filled polygons, 1 => fill with segments.
Definition: class_zone.h:588
virtual void Flip(const wxPoint &aCentre) override
Function Flip Flip this object, i.e.
Definition: class_zone.cpp:743
ZoneConnection GetZoneConnection() const
Definition: class_pad.cpp:559
int GetThermalReliefGap(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:437
ZONE_CONTAINER(BOARD *parent)
Definition: class_zone.cpp:53
unsigned m_priority
Definition: class_zone.h:555
int GetThermalWidth() const
Definition: class_pad.cpp:570
bool m_ContrastModeDisplay
Definition: pcbstruct.h:85
void Rotate(const wxPoint &centre, double angle) override
Function Rotate Move the outlines.
Definition: class_zone.cpp:717
bool m_doNotAllowVias
Definition: class_zone.h:566
int GetThermalGap() const
Definition: class_pad.cpp:581
void SetY(int ic, int y)
Definition: PolyLine.h:414
bool UnFill()
Function UnFill Removes the zone filling.
Definition: class_zone.cpp:147
int m_cornerSmoothingType
Definition: class_zone.h:548
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
const wxPoint & GetPos(int ic) const
Definition: PolyLine.h:136
virtual int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const
Function GetClearance returns the clearance in 1/10000 inches.
int GetHatchPitch() const
Definition: PolyLine.h:396
void AddPolygon(std::vector< wxPoint > &aPolygon)
Definition: class_zone.cpp:784
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:612
void SetSelectedCorner(int aCorner)
Definition: class_zone.h:200
unsigned int m_cornerRadius
Definition: class_zone.h:549
const wxPoint GetEnd() const
Class DISPLAY_OPTIONS handles display options like enable/disable some optional drawings.
Definition: pcbstruct.h:62
ITERATOR Iterate(int aFirst, int aLast)
Returns an iterator object, for iterating between aFirst and aLast outline.
int HitTestForEdge(const wxPoint &aPos, int aDistMax) const
Function HitTestForEdge test is the point aPos is near (< aDistMax ) a vertex.
Definition: PolyLine.cpp:1140
void Move(const wxPoint &offset) override
Function Move Move the outlines.
Definition: class_zone.cpp:675
int GetNetCode() const
Function GetNetCode.
bool IsLayerVisible(LAYER_ID aLayer) const
Function IsLayerVisible is a proxy function that calls the correspondent function in m_BoardSettings ...
Definition: class_board.h:440
const wxPoint & GetPosition() const override
Function GetPosition.
Definition: class_zone.cpp:160
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:533
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.
bool m_doNotAllowCopperPour
Definition: class_zone.h:565
bool IsOnCopperLayer() const
Function IsOnCopperLayer.
Definition: class_zone.h:166
int m_ThermalReliefGap
Width of the copper bridge in thermal reliefs.
Definition: class_zone.h:581
bool GetDoNotAllowTracks() const
Definition: class_zone.h:530
int m_ZoneMinThickness
Minimum thickness value in filled areas.
Definition: class_zone.h:571
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
void SetHatchStyle(enum HATCH_STYLE style)
Definition: PolyLine.h:419
const wxString & GetNetname() const
Function GetNetname.
void SetCornerPosition(int aCornerIndex, wxPoint new_pos)
Definition: class_zone.h:426
int GetCornersCount() const
Definition: PolyLine.h:339
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:206
void CloseLastContour()
function CloseLastContour Set the .end_contour member of the last corner of the last contour to true ...
Definition: PolyLine.h:254
bool GetDoNotAllowVias() const
Definition: class_zone.h:529
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:166
LAYER_ID FlipLayer(LAYER_ID aLayerId, int aCopperLayersCount)
Function FlippedLayerNumber.
Definition: lset.cpp:444
LAYER_ID
Enum LAYER_ID is the set of PCB layers.
Class SHAPE_LINE_CHAIN.
int GetHatchStyle() const
Definition: class_zone.h:437
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
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:463
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:584
Class EDA_RECT handles the component boundary box.
BASE_SCREEN * GetScreen()
Definition: draw_panel.cpp:188
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:151
void SetLocalFlags(int aFlags)
Definition: class_zone.h:207
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
void SetY(int ic, int aValue)
Definition: PolyLine.h:129
int GetContourStart(int icont)
Function GetContourStart.
Definition: PolyLine.cpp:641
Definition: colors.h:49
int GetY(int ic) const
Definition: PolyLine.h:128
virtual BOARD * GetBoard() const
Function GetBoard returns the BOARD in which this BOARD_ITEM resides, or NULL if none.
#define MAX_DIST_IN_MM
Definition: class_zone.cpp:486
void AppendCorner(wxPoint position)
Definition: class_zone.h:432
int GetContour(int ic)
Function GetContour.
Definition: PolyLine.cpp:627
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:182
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:751
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:532
unsigned GetPriority() const
Function GetPriority.
Definition: class_zone.h:106
BITMAP_DEF GetMenuImage() const override
Function GetMenuImage returns a pointer to an image to be used in menus.
Definition: class_zone.cpp:853
Message panel definition file.
const wxPoint & GetCornerPosition(int aCornerIndex) const
Definition: class_zone.h:421
#define FORCE_SKETCH
Definition: pcbnew.h:69
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1) const
Returns true is 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:599
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
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39
Definition: colors.h:62