KiCad PCB EDA Suite
plot_board_layers.cpp
Go to the documentation of this file.
1 
8 /*
9  * This program source code file is part of KiCad, a free EDA CAD application.
10  *
11  * Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, you may find one here:
25  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
26  * or you may search the http://www.gnu.org website for the version 2 license,
27  * or you may write to the Free Software Foundation, Inc.,
28  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
29  */
30 
31 
32 #include <fctsys.h>
33 #include <common.h>
34 #include <plotter.h>
35 #include <base_struct.h>
36 #include <gr_text.h>
38 #include <trigo.h>
39 #include <pcb_base_frame.h>
40 #include <macros.h>
41 
42 #include <class_board.h>
43 #include <class_module.h>
44 #include <class_track.h>
45 #include <class_edge_mod.h>
46 #include <class_pcb_text.h>
47 #include <class_zone.h>
48 #include <class_drawsegment.h>
49 #include <class_pcb_target.h>
50 #include <class_dimension.h>
51 
52 #include <pcbnew.h>
53 #include <pcbplot.h>
54 #include <gbr_metadata.h>
55 
56 /*
57  * Plot a solder mask layer. Solder mask layers have a minimum thickness value and cannot be
58  * drawn like standard layers, unless the minimum thickness is 0.
59  */
60 static void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
61  const PCB_PLOT_PARAMS& aPlotOpt, int aMinThickness );
62 
63 /*
64  * Creates the plot for silkscreen layers. Silkscreen layers have specific requirement for
65  * pads (not filled) and texts (with option to remove them from some copper areas (pads...)
66  */
67 void PlotSilkScreen( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
68  const PCB_PLOT_PARAMS& aPlotOpt )
69 {
70  BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
71  itemplotter.SetLayerSet( aLayerMask );
72 
73  // Plot edge layer and graphic items
74  itemplotter.PlotBoardGraphicItems();
75 
76  // Plot footprint outlines :
77  itemplotter.Plot_Edges_Modules();
78 
79  // Plot pads (creates pads outlines, for pads on silkscreen layers)
80  LSET layersmask_plotpads = aLayerMask;
81 
82  // Calculate the mask layers of allowed layers for pads
83 
84  if( !aPlotOpt.GetPlotPadsOnSilkLayer() ) // Do not plot pads on silk screen layers
85  layersmask_plotpads.set( B_SilkS, false ).set( F_SilkS, false );
86 
87  if( layersmask_plotpads.any() )
88  {
89  for( auto Module : aBoard->Modules() )
90  {
91  aPlotter->StartBlock( NULL );
92 
93  for( auto pad : Module->Pads() )
94  {
95  // See if the pad is on this layer
96  LSET masklayer = pad->GetLayerSet();
97  if( !( masklayer & layersmask_plotpads ).any() )
98  continue;
99 
101 
102  if( layersmask_plotpads[B_SilkS] )
103  color = aBoard->Colors().GetLayerColor( B_SilkS );
104 
105  if( layersmask_plotpads[F_SilkS] )
106  color = ( color == COLOR4D::BLACK) ? aBoard->Colors().GetLayerColor( F_SilkS ) : color;
107 
108  itemplotter.PlotPad( pad, color, SKETCH );
109  }
110 
111  aPlotter->EndBlock( NULL );
112  }
113  }
114 
115  // Plot footprints fields (ref, value ...)
116  for( auto module : aBoard->Modules() )
117  {
118  if( ! itemplotter.PlotAllTextsModule( module ) )
119  {
120  wxLogMessage( _( "Your BOARD has a bad layer number for footprint %s" ),
121  module->GetReference() );
122  }
123  }
124 
125  // Plot filled areas
126  aPlotter->StartBlock( NULL );
127 
128  // Plot all zones together so we don't end up with divots where zones touch each other.
129  ZONE_CONTAINER* zone = nullptr;
130  SHAPE_POLY_SET aggregateArea;
131 
132  for( ZONE_CONTAINER* candidate : aBoard->Zones() )
133  {
134  if( !aLayerMask[ candidate->GetLayer() ] )
135  continue;
136 
137  if( !zone )
138  zone = candidate;
139 
140  aggregateArea.BooleanAdd( candidate->GetFilledPolysList(), SHAPE_POLY_SET::PM_FAST );
141  }
142 
144  itemplotter.PlotFilledAreas( zone, aggregateArea );
145 
146  aPlotter->EndBlock( NULL );
147 }
148 
149 void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
150  const PCB_PLOT_PARAMS& aPlotOpt )
151 {
152  PCB_PLOT_PARAMS plotOpt = aPlotOpt;
153  int soldermask_min_thickness = aBoard->GetDesignSettings().m_SolderMaskMinWidth;
154 
155  // Set a default color and the text mode for this layer
156  aPlotter->SetColor( aPlotOpt.GetColor() );
157  aPlotter->SetTextMode( aPlotOpt.GetTextMode() );
158 
159  // Specify that the contents of the "Edges Pcb" layer are to be plotted in addition to the
160  // contents of the currently specified layer.
161  LSET layer_mask( aLayer );
162 
163  if( !aPlotOpt.GetExcludeEdgeLayer() )
164  layer_mask.set( Edge_Cuts );
165 
166  if( IsCopperLayer( aLayer ) )
167  {
168  // Skip NPTH pads on copper layers ( only if hole size == pad size ):
169  // Drill mark will be plotted if drill mark is SMALL_DRILL_SHAPE or FULL_DRILL_SHAPE
170  if( plotOpt.GetFormat() == PLOT_FORMAT_DXF )
171  {
172  plotOpt.SetSkipPlotNPTH_Pads( false );
173  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
174  }
175  else
176  {
177  plotOpt.SetSkipPlotNPTH_Pads( true );
178  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
179  }
180  }
181  else
182  {
183  switch( aLayer )
184  {
185  case B_Mask:
186  case F_Mask:
187  plotOpt.SetSkipPlotNPTH_Pads( false );
188  // Disable plot pad holes
190 
191  // Plot solder mask:
192  if( soldermask_min_thickness == 0 )
193  {
194  if( plotOpt.GetFormat() == PLOT_FORMAT_DXF )
195  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
196  else
197  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
198  }
199  else
200  PlotSolderMaskLayer( aBoard, aPlotter, layer_mask, plotOpt,
201  soldermask_min_thickness );
202 
203  break;
204 
205  case B_Adhes:
206  case F_Adhes:
207  case B_Paste:
208  case F_Paste:
209  plotOpt.SetSkipPlotNPTH_Pads( false );
210  // Disable plot pad holes
212 
213  if( plotOpt.GetFormat() == PLOT_FORMAT_DXF )
214  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
215  else
216  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
217  break;
218 
219  case F_SilkS:
220  case B_SilkS:
221  if( plotOpt.GetFormat() == PLOT_FORMAT_DXF && plotOpt.GetDXFPlotPolygonMode() )
222  // PlotLayerOutlines() is designed only for DXF plotters.
223  // and must not be used for other plot formats
224  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
225  else
226  PlotSilkScreen( aBoard, aPlotter, layer_mask, plotOpt );
227 
228  // Gerber: Subtract soldermask from silkscreen if enabled
229  if( aPlotter->GetPlotterType() == PLOT_FORMAT_GERBER
230  && plotOpt.GetSubtractMaskFromSilk() )
231  {
232  if( aLayer == F_SilkS )
233  layer_mask = LSET( F_Mask );
234  else
235  layer_mask = LSET( B_Mask );
236 
237  // Create the mask to subtract by creating a negative layer polarity
238  aPlotter->SetLayerPolarity( false );
239 
240  // Disable plot pad holes
242 
243  // Plot the mask
244  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
245  }
246  break;
247 
248  // These layers are plotted like silk screen layers.
249  // Mainly, pads on these layers are not filled.
250  // This is not necessary the best choice.
251  case Dwgs_User:
252  case Cmts_User:
253  case Eco1_User:
254  case Eco2_User:
255  case Edge_Cuts:
256  case Margin:
257  case F_CrtYd:
258  case B_CrtYd:
259  case F_Fab:
260  case B_Fab:
261  plotOpt.SetSkipPlotNPTH_Pads( false );
263 
264  if( plotOpt.GetFormat() == PLOT_FORMAT_DXF && plotOpt.GetDXFPlotPolygonMode() )
265  // PlotLayerOutlines() is designed only for DXF plotters.
266  // and must not be used for other plot formats
267  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
268  else
269  PlotSilkScreen( aBoard, aPlotter, layer_mask, plotOpt );
270  break;
271 
272  default:
273  plotOpt.SetSkipPlotNPTH_Pads( false );
275 
276  if( plotOpt.GetFormat() == PLOT_FORMAT_DXF && plotOpt.GetDXFPlotPolygonMode() )
277  // PlotLayerOutlines() is designed only for DXF plotters.
278  // and must not be used for other plot formats
279  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
280  else
281  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
282  break;
283  }
284  }
285 }
286 
287 
288 /* Plot a copper layer or mask.
289  * Silk screen layers are not plotted here.
290  */
291 void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter,
292  LSET aLayerMask, const PCB_PLOT_PARAMS& aPlotOpt )
293 {
294  BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
295 
296  itemplotter.SetLayerSet( aLayerMask );
297 
298  EDA_DRAW_MODE_T plotMode = aPlotOpt.GetPlotMode();
299 
300  // Plot edge layer and graphic items
301  itemplotter.PlotBoardGraphicItems();
302 
303  // Draw footprint texts:
304  for( auto module : aBoard->Modules() )
305  {
306  if( ! itemplotter.PlotAllTextsModule( module ) )
307  {
308  wxLogMessage( _( "Your BOARD has a bad layer number for footprint %s" ),
309  module->GetReference() );
310  }
311  }
312 
313  // Draw footprint other graphic items:
314  for( auto module : aBoard->Modules() )
315  {
316  for( auto item : module->GraphicalItems() )
317  {
318  if( item->Type() == PCB_MODULE_EDGE_T && aLayerMask[ item->GetLayer() ] )
319  itemplotter.Plot_1_EdgeModule( (EDGE_MODULE*) item );
320  }
321  }
322 
323  // Plot footprint pads
324  for( auto module : aBoard->Modules() )
325  {
326  aPlotter->StartBlock( NULL );
327 
328  for( auto pad : module->Pads() )
329  {
330  if( (pad->GetLayerSet() & aLayerMask) == 0 )
331  continue;
332 
333  wxSize margin;
334  double width_adj = 0;
335 
336  if( ( aLayerMask & LSET::AllCuMask() ).any() )
337  width_adj = itemplotter.getFineWidthAdj();
338 
339  static const LSET speed( 4, B_Mask, F_Mask, B_Paste, F_Paste );
340 
341  LSET anded = ( speed & aLayerMask );
342 
343  if( anded == LSET( F_Mask ) || anded == LSET( B_Mask ) )
344  {
345  margin.x = margin.y = pad->GetSolderMaskMargin();
346  }
347  else if( anded == LSET( F_Paste ) || anded == LSET( B_Paste ) )
348  {
349  margin = pad->GetSolderPasteMargin();
350  }
351 
352  // Now offset the pad size by margin + width_adj
353  // this is easy for most shapes, but not for a trapezoid or a custom shape
354  wxSize padPlotsSize;
355  wxSize extraSize = margin * 2;
356  extraSize.x += width_adj;
357  extraSize.y += width_adj;
358  wxSize deltaSize = pad->GetDelta(); // has meaning only for trapezoidal pads
359 
360  if( pad->GetShape() == PAD_SHAPE_TRAPEZOID )
361  { // The easy way is to use BuildPadPolygon to calculate
362  // size and delta of the trapezoidal pad after offseting:
363  wxPoint coord[4];
364  pad->BuildPadPolygon( coord, extraSize/2, 0.0 );
365  // Calculate the size and delta from polygon corners coordinates:
366  // coord[0] is the lower left
367  // coord[1] is the upper left
368  // coord[2] is the upper right
369  // coord[3] is the lower right
370 
371  // the size is the distance between middle of segments
372  // (left/right or top/bottom)
373  // size X is the dist between left and right middle points:
374  padPlotsSize.x = ( ( -coord[0].x + coord[3].x ) // the lower segment X length
375  + ( -coord[1].x + coord[2].x ) ) // the upper segment X length
376  / 2; // the Y size is the half sum
377  // size Y is the dist between top and bottom middle points:
378  padPlotsSize.y = ( ( coord[0].y - coord[1].y ) // the left segment Y lenght
379  + ( coord[3].y - coord[2].y ) ) // the right segment Y lenght
380  / 2; // the Y size is the half sum
381 
382  // calculate the delta ( difference of lenght between 2 opposite edges )
383  // The delta.x is the delta along the X axis, therefore the delta of Y lenghts
384  wxSize delta;
385 
386  if( coord[0].y != coord[3].y )
387  delta.x = coord[0].y - coord[3].y;
388  else
389  delta.y = coord[1].x - coord[0].x;
390 
391  pad->SetDelta( delta );
392  }
393  else
394  padPlotsSize = pad->GetSize() + extraSize;
395 
396  // Don't draw a null size item :
397  if( padPlotsSize.x <= 0 || padPlotsSize.y <= 0 )
398  continue;
399 
401 
402  if( pad->GetLayerSet()[B_Cu] )
403  color = aBoard->Colors().GetItemColor( LAYER_PAD_BK );
404 
405  if( pad->GetLayerSet()[F_Cu] )
406  color = color.LegacyMix( aBoard->Colors().GetItemColor( LAYER_PAD_FR ) );
407 
408  // Temporary set the pad size to the required plot size:
409  wxSize tmppadsize = pad->GetSize();
410 
411  switch( pad->GetShape() )
412  {
413  case PAD_SHAPE_CIRCLE:
414  case PAD_SHAPE_OVAL:
415  pad->SetSize( padPlotsSize );
416 
417  if( aPlotOpt.GetSkipPlotNPTH_Pads() &&
419  ( pad->GetSize() == pad->GetDrillSize() ) &&
420  ( pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED ) )
421  break;
422 
423  itemplotter.PlotPad( pad, color, plotMode );
424  break;
425 
426  case PAD_SHAPE_TRAPEZOID:
427  case PAD_SHAPE_RECT:
428  case PAD_SHAPE_ROUNDRECT:
430  pad->SetSize( padPlotsSize );
431  itemplotter.PlotPad( pad, color, plotMode );
432  break;
433 
434  case PAD_SHAPE_CUSTOM:
435  {
436  // inflate/deflate a custom shape is a bit complex.
437  // so build a similar pad shape, and inflate/deflate the polygonal shape
438  D_PAD dummy( *pad );
439  SHAPE_POLY_SET shape;
440  pad->MergePrimitivesAsPolygon( &shape );
441  // Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
442  // which can create bad shapes if margin.x is < 0
443  int maxError = aBoard->GetDesignSettings().m_MaxError;
444  int numSegs = std::max( GetArcToSegmentCount( margin.x, maxError, 360.0 ), 6 );
445  shape.InflateWithLinkedHoles( margin.x, numSegs, SHAPE_POLY_SET::PM_FAST );
446  dummy.DeletePrimitivesList();
447  dummy.AddPrimitive( shape, 0 );
448  dummy.MergePrimitivesAsPolygon();
449 
450  // Be sure the anchor pad is not bigger than the deflated shape because this
451  // anchor will be added to the pad shape when plotting the pad. So now the
452  // polygonal shape is built, we can clamp the anchor size
453  if( margin.x < 0 ) // we expect margin.x = margin.y for custom pads
454  dummy.SetSize( padPlotsSize );
455 
456  itemplotter.PlotPad( &dummy, color, plotMode );
457  }
458  break;
459  }
460 
461  pad->SetSize( tmppadsize ); // Restore the pad size
462  pad->SetDelta( deltaSize );
463  }
464 
465  aPlotter->EndBlock( NULL );
466  }
467 
468  // Plot vias on copper layers, and if aPlotOpt.GetPlotViaOnMaskLayer() is true,
469  // plot them on solder mask
470 
471  GBR_METADATA gbr_metadata;
472 
473  bool isOnCopperLayer = ( aLayerMask & LSET::AllCuMask() ).any();
474 
475  if( isOnCopperLayer )
476  {
479  }
480 
481  aPlotter->StartBlock( NULL );
482 
483  for( auto track : aBoard->Tracks() )
484  {
485  const VIA* Via = dyn_cast<const VIA*>( track );
486 
487  if( !Via )
488  continue;
489 
490  // vias are not plotted if not on selected layer, but if layer is SOLDERMASK_LAYER_BACK
491  // or SOLDERMASK_LAYER_FRONT, vias are drawn only if they are on the corresponding
492  // external copper layer
493  LSET via_mask_layer = Via->GetLayerSet();
494 
495  if( aPlotOpt.GetPlotViaOnMaskLayer() )
496  {
497  if( via_mask_layer[B_Cu] )
498  via_mask_layer.set( B_Mask );
499 
500  if( via_mask_layer[F_Cu] )
501  via_mask_layer.set( F_Mask );
502  }
503 
504  if( !( via_mask_layer & aLayerMask ).any() )
505  continue;
506 
507  int via_margin = 0;
508  double width_adj = 0;
509 
510  // If the current layer is a solder mask, use the global mask clearance for vias
511  if( aLayerMask[B_Mask] || aLayerMask[F_Mask] )
512  via_margin = aBoard->GetDesignSettings().m_SolderMaskMargin;
513 
514  if( ( aLayerMask & LSET::AllCuMask() ).any() )
515  width_adj = itemplotter.getFineWidthAdj();
516 
517  int diameter = Via->GetWidth() + 2 * via_margin + width_adj;
518 
519  // Don't draw a null size item :
520  if( diameter <= 0 )
521  continue;
522 
523  // Some vias can be not connected (no net).
524  // Set the m_NotInNet for these vias to force a empty net name in gerber file
525  gbr_metadata.m_NetlistMetadata.m_NotInNet = Via->GetNetname().IsEmpty();
526 
527  gbr_metadata.SetNetName( Via->GetNetname() );
528 
529  COLOR4D color = aBoard->Colors().GetItemColor( LAYER_VIAS + Via->GetViaType() );
530  // Set plot color (change WHITE to LIGHTGRAY because the white items are not seen on a
531  // white paper or screen
532  aPlotter->SetColor( color != WHITE ? color : LIGHTGRAY);
533  aPlotter->FlashPadCircle( Via->GetStart(), diameter, plotMode, &gbr_metadata );
534  }
535 
536  aPlotter->EndBlock( NULL );
537  aPlotter->StartBlock( NULL );
539 
540  // Plot tracks (not vias) :
541  for( auto track : aBoard->Tracks() )
542  {
543  if( track->Type() == PCB_VIA_T )
544  continue;
545 
546  if( !aLayerMask[track->GetLayer()] )
547  continue;
548 
549  // Some track segments can be not connected (no net).
550  // Set the m_NotInNet for these segments to force a empty net name in gerber file
551  gbr_metadata.m_NetlistMetadata.m_NotInNet = track->GetNetname().IsEmpty();
552 
553  gbr_metadata.SetNetName( track->GetNetname() );
554  int width = track->GetWidth() + itemplotter.getFineWidthAdj();
555  aPlotter->SetColor( itemplotter.getColor( track->GetLayer() ) );
556  aPlotter->ThickSegment( track->GetStart(), track->GetEnd(), width, plotMode, &gbr_metadata );
557  }
558 
559  aPlotter->EndBlock( NULL );
560 
561  // Plot filled ares
562  aPlotter->StartBlock( NULL );
563 
564  // Plot all zones of the same layer & net together so we don't end up with divots where
565  // zones touch each other.
566  std::set<ZONE_CONTAINER*> plotted;
567 
568  for( ZONE_CONTAINER* zone : aBoard->Zones() )
569  {
570  if( !aLayerMask[ zone->GetLayer() ] || plotted.count( zone ) )
571  continue;
572 
573  plotted.insert( zone );
574 
575  SHAPE_POLY_SET aggregateArea = zone->GetFilledPolysList();
576  bool needFracture = false; // If 2 or more filled areas are combined, resulting
577  // aggregateArea will be simplified and fractured
578  // (Long calculation time)
579 
580  for( ZONE_CONTAINER* candidate : aBoard->Zones() )
581  {
582  if( !aLayerMask[ candidate->GetLayer() ] || plotted.count( candidate ) )
583  continue;
584 
585  if( candidate->GetNetCode() != zone->GetNetCode() )
586  continue;
587 
588  // Merging zones of the same net can be done only for areas
589  // having compatible settings for drawings:
590  // use or not outline thickness, and if using outline thickness,
591  // having the same thickness
592  // because after merging only one outline thickness is used
593  if( candidate->GetFilledPolysUseThickness() != zone->GetFilledPolysUseThickness() )
594  // Should not happens, because usually the same option is used for filling
595  continue;
596 
597  if( zone->GetFilledPolysUseThickness() &&
598  ( candidate->GetMinThickness() != zone->GetMinThickness() ) )
599  continue;
600 
601  plotted.insert( candidate );
602  aggregateArea.Append( candidate->GetFilledPolysList() );
603  needFracture = true;
604  }
605 
606  if( needFracture )
607  {
610  }
611 
612  itemplotter.PlotFilledAreas( zone, aggregateArea );
613  }
614  aPlotter->EndBlock( NULL );
615 
616  // Adding drill marks, if required and if the plotter is able to plot them:
618  itemplotter.PlotDrillMarks();
619 }
620 
621 
622 // Seems like we want to plot from back to front?
623 static const PCB_LAYER_ID plot_seq[] = {
624 
625  B_Adhes, // 32
626  F_Adhes,
627  B_Paste,
628  F_Paste,
629  B_SilkS,
630  B_Mask,
631  F_Mask,
632  Dwgs_User,
633  Cmts_User,
634  Eco1_User,
635  Eco2_User,
636  Edge_Cuts,
637  Margin,
638 
639  F_CrtYd, // CrtYd & Body are footprint only
640  B_CrtYd,
641  F_Fab,
642  B_Fab,
643 
644  B_Cu,
645  In30_Cu,
646  In29_Cu,
647  In28_Cu,
648  In27_Cu,
649  In26_Cu,
650  In25_Cu,
651  In24_Cu,
652  In23_Cu,
653  In22_Cu,
654  In21_Cu,
655  In20_Cu,
656  In19_Cu,
657  In18_Cu,
658  In17_Cu,
659  In16_Cu,
660  In15_Cu,
661  In14_Cu,
662  In13_Cu,
663  In12_Cu,
664  In11_Cu,
665  In10_Cu,
666  In9_Cu,
667  In8_Cu,
668  In7_Cu,
669  In6_Cu,
670  In5_Cu,
671  In4_Cu,
672  In3_Cu,
673  In2_Cu,
674  In1_Cu,
675  F_Cu,
676 
677  F_SilkS,
678 };
679 
680 
681 /*
682  * Plot outlines of copper, for copper layer
683  */
684 void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
685  const PCB_PLOT_PARAMS& aPlotOpt )
686 {
687 
688  BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
689  itemplotter.SetLayerSet( aLayerMask );
690 
691  SHAPE_POLY_SET outlines;
692 
693  for( LSEQ seq = aLayerMask.Seq( plot_seq, arrayDim( plot_seq ) ); seq; ++seq )
694  {
695  PCB_LAYER_ID layer = *seq;
696 
697  outlines.RemoveAllContours();
698  aBoard->ConvertBrdLayerToPolygonalContours( layer, outlines );
699 
700  outlines.Simplify( SHAPE_POLY_SET::PM_FAST );
701 
702  // Plot outlines
703  std::vector< wxPoint > cornerList;
704 
705  // Now we have one or more basic polygons: plot each polygon
706  for( int ii = 0; ii < outlines.OutlineCount(); ii++ )
707  {
708  for(int kk = 0; kk <= outlines.HoleCount (ii); kk++ )
709  {
710  cornerList.clear();
711  const SHAPE_LINE_CHAIN& path = (kk == 0) ? outlines.COutline( ii ) : outlines.CHole( ii, kk - 1 );
712 
713  for( int jj = 0; jj < path.PointCount(); jj++ )
714  cornerList.emplace_back( (wxPoint) path.CPoint( jj ) );
715 
716  // Ensure the polygon is closed
717  if( cornerList[0] != cornerList[cornerList.size() - 1] )
718  cornerList.push_back( cornerList[0] );
719 
720  aPlotter->PlotPoly( cornerList, NO_FILL );
721  }
722  }
723 
724  // Plot pad holes
726  {
727  int smallDrill = (aPlotOpt.GetDrillMarksType() == PCB_PLOT_PARAMS::SMALL_DRILL_SHAPE)
728  ? SMALL_DRILL : INT_MAX;
729 
730  for( auto module : aBoard->Modules() )
731  {
732  for( auto pad : module->Pads() )
733  {
734  wxSize hole = pad->GetDrillSize();
735 
736  if( hole.x == 0 || hole.y == 0 )
737  continue;
738 
739  if( hole.x == hole.y )
740  {
741  hole.x = std::min( smallDrill, hole.x );
742  aPlotter->Circle( pad->GetPosition(), hole.x, NO_FILL );
743  }
744  else
745  {
746  // Note: small drill marks have no significance when applied to slots
747  wxPoint drl_start, drl_end;
748  int width;
749  pad->GetOblongDrillGeometry( drl_start, drl_end, width );
750  aPlotter->ThickSegment( pad->GetPosition() + drl_start,
751  pad->GetPosition() + drl_end, width, SKETCH, NULL );
752  }
753  }
754  }
755  }
756 
757  // Plot vias holes
758  for( auto track : aBoard->Tracks() )
759  {
760  const VIA* via = dyn_cast<const VIA*>( track );
761 
762  if( via && via->IsOnLayer( layer ) ) // via holes can be not through holes
763  {
764  aPlotter->Circle( via->GetPosition(), via->GetDrillValue(), NO_FILL );
765  }
766  }
767  }
768 }
769 
770 
771 /* Plot a solder mask layer.
772  * Solder mask layers have a minimum thickness value and cannot be drawn like standard layers,
773  * unless the minimum thickness is 0.
774  * Currently the algo is:
775  * 1 - build all pad shapes as polygons with a size inflated by
776  * mask clearance + (min width solder mask /2)
777  * 2 - Merge shapes
778  * 3 - deflate result by (min width solder mask /2)
779  * 4 - ORing result by all pad shapes as polygons with a size inflated by
780  * mask clearance only (because deflate sometimes creates shape artifacts)
781  * 5 - draw result as polygons
782  *
783  * TODO:
784  * make this calculation only for shapes with clearance near than (min width solder mask)
785  * (using DRC algo)
786  * plot all other shapes by flashing the basing shape
787  * (shapes will be better, and calculations faster)
788  */
789 void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
790  const PCB_PLOT_PARAMS& aPlotOpt, int aMinThickness )
791 {
792  PCB_LAYER_ID layer = aLayerMask[B_Mask] ? B_Mask : F_Mask;
793 
794  // We remove 1nm as we expand both sides of the shapes, so allowing for
795  // a strictly greater than or equal comparison in the shape separation (boolean add)
796  // means that we will end up with separate shapes that then are shrunk
797  int inflate = aMinThickness/2 - 1;
798 
799  BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
800  itemplotter.SetLayerSet( aLayerMask );
801 
802  // Plot edge layer and graphic items.
803  // They do not have a solder Mask margin, because they graphic items
804  // on this layer (like logos), not actually areas around pads.
805  itemplotter.PlotBoardGraphicItems();
806 
807  for( auto module : aBoard->Modules() )
808  {
809  for( auto item : module->GraphicalItems() )
810  {
811  itemplotter.PlotAllTextsModule( module );
812 
813  if( item->Type() == PCB_MODULE_EDGE_T && item->GetLayer() == layer )
814  itemplotter.Plot_1_EdgeModule( (EDGE_MODULE*) item );
815  }
816  }
817 
818  // Build polygons for each pad shape. The size of the shape on solder mask should be size
819  // of pad + clearance around the pad, where clearance = solder mask clearance + extra margin.
820  // Extra margin is half the min width for solder mask, which is used to merge too-close shapes
821  // (distance < aMinThickness), and will be removed when creating the actual shapes.
822  SHAPE_POLY_SET areas; // Contains shapes to plot
823  SHAPE_POLY_SET initialPolys; // Contains exact shapes to plot
824 
825  // Plot pads
826  for( auto module : aBoard->Modules() )
827  {
828  // add shapes with exact size
829  module->TransformPadsShapesWithClearanceToPolygon( layer, initialPolys, 0 );
830  // add shapes inflated by aMinThickness/2
831  module->TransformPadsShapesWithClearanceToPolygon( layer, areas, inflate );
832  }
833 
834  // Plot vias on solder masks, if aPlotOpt.GetPlotViaOnMaskLayer() is true,
835  if( aPlotOpt.GetPlotViaOnMaskLayer() )
836  {
837  // The current layer is a solder mask, use the global mask clearance for vias
838  int via_clearance = aBoard->GetDesignSettings().m_SolderMaskMargin;
839  int via_margin = via_clearance + inflate;
840 
841  for( auto track : aBoard->Tracks() )
842  {
843  const VIA* via = dyn_cast<const VIA*>( track );
844 
845  if( !via )
846  continue;
847 
848  // vias are plotted only if they are on the corresponding external copper layer
849  LSET via_set = via->GetLayerSet();
850 
851  if( via_set[B_Cu] )
852  via_set.set( B_Mask );
853 
854  if( via_set[F_Cu] )
855  via_set.set( F_Mask );
856 
857  if( !( via_set & aLayerMask ).any() )
858  continue;
859 
860  via->TransformShapeWithClearanceToPolygon( areas, via_margin );
861  via->TransformShapeWithClearanceToPolygon( initialPolys, via_clearance );
862  }
863  }
864 
865  // Add filled zone areas.
866 #if 0 // Set to 1 if a solder mask margin must be applied to zones on solder mask
867  int zone_margin = aBoard->GetDesignSettings().m_SolderMaskMargin;
868 #else
869  int zone_margin = 0;
870 #endif
871 
872  for( ZONE_CONTAINER* zone : aBoard->Zones() )
873  {
874  if( zone->GetLayer() != layer )
875  continue;
876 
877  // Some intersecting zones, despite being on the same layer with the same net, cannot be
878  // merged due to other parameters such as fillet radius. The copper pour will end up
879  // effectively merged though, so we want to keep the corners of such intersections sharp.
880  std::set<VECTOR2I> colinearCorners;
881  zone->GetColinearCorners( aBoard, colinearCorners );
882 
883  zone->TransformOutlinesShapeWithClearanceToPolygon( areas, inflate + zone_margin, false,
884  &colinearCorners );
885  zone->TransformOutlinesShapeWithClearanceToPolygon( initialPolys, zone_margin, false,
886  &colinearCorners );
887  }
888 
889  // To avoid a lot of code, use a ZONE_CONTAINER to handle and plot polygons, because our
890  // polygons look exactly like filled areas in zones.
891  // Note, also this code is not optimized: it creates a lot of copy/duplicate data.
892  // However it is not complex, and fast enough for plot purposes (copy/convert data is only a
893  // very small calculation time for these calculations).
894  ZONE_CONTAINER zone( aBoard );
895  zone.SetMinThickness( 0 ); // trace polygons only
896  zone.SetLayer( layer );
897  int maxError = aBoard->GetDesignSettings().m_MaxError;
898  int numSegs = std::max( GetArcToSegmentCount( inflate, maxError, 360.0 ), 6 );
899 
900  areas.BooleanAdd( initialPolys, SHAPE_POLY_SET::PM_FAST );
901  areas.Deflate( inflate, numSegs );
902 
903  // Combine the current areas to initial areas. This is mandatory because inflate/deflate
904  // transform is not perfect, and we want the initial areas perfectly kept
905  areas.BooleanAdd( initialPolys, SHAPE_POLY_SET::PM_FAST );
907 
908  itemplotter.PlotFilledAreas( &zone, areas );
909 }
910 
911 
918 static void initializePlotter( PLOTTER *aPlotter, BOARD * aBoard,
919  PCB_PLOT_PARAMS *aPlotOpts )
920 {
921  PAGE_INFO pageA4( wxT( "A4" ) );
922  const PAGE_INFO& pageInfo = aBoard->GetPageSettings();
923  const PAGE_INFO* sheet_info;
924  double paperscale; // Page-to-paper ratio
925  wxSize paperSizeIU;
926  wxSize pageSizeIU( pageInfo.GetSizeIU() );
927  bool autocenter = false;
928 
929  // Special options: to fit the sheet to an A4 sheet replace the paper size. However there
930  // is a difference between the autoscale and the a4paper option:
931  // - Autoscale fits the board to the paper size
932  // - A4paper fits the original paper size to an A4 sheet
933  // - Both of them fit the board to an A4 sheet
934  if( aPlotOpts->GetA4Output() )
935  {
936  sheet_info = &pageA4;
937  paperSizeIU = pageA4.GetSizeIU();
938  paperscale = (double) paperSizeIU.x / pageSizeIU.x;
939  autocenter = true;
940  }
941  else
942  {
943  sheet_info = &pageInfo;
944  paperSizeIU = pageSizeIU;
945  paperscale = 1;
946 
947  // Need autocentering only if scale is not 1:1
948  autocenter = (aPlotOpts->GetScale() != 1.0);
949  }
950 
951  EDA_RECT bbox = aBoard->ComputeBoundingBox();
952  wxPoint boardCenter = bbox.Centre();
953  wxSize boardSize = bbox.GetSize();
954 
955  double compound_scale;
956 
957  // Fit to 80% of the page if asked; it could be that the board is empty, in this case
958  // regress to 1:1 scale
959  if( aPlotOpts->GetAutoScale() && boardSize.x > 0 && boardSize.y > 0 )
960  {
961  double xscale = (paperSizeIU.x * 0.8) / boardSize.x;
962  double yscale = (paperSizeIU.y * 0.8) / boardSize.y;
963 
964  compound_scale = std::min( xscale, yscale ) * paperscale;
965  }
966  else
967  compound_scale = aPlotOpts->GetScale() * paperscale;
968 
969 
970  // For the plot offset we have to keep in mind the auxiliary origin too: if autoscaling is
971  // off we check that plot option (i.e. autoscaling overrides auxiliary origin)
972  wxPoint offset( 0, 0);
973 
974  if( autocenter )
975  {
976  offset.x = KiROUND( boardCenter.x - ( paperSizeIU.x / 2.0 ) / compound_scale );
977  offset.y = KiROUND( boardCenter.y - ( paperSizeIU.y / 2.0 ) / compound_scale );
978  }
979  else
980  {
981  if( aPlotOpts->GetUseAuxOrigin() )
982  offset = aBoard->GetAuxOrigin();
983  }
984 
985  aPlotter->SetPageSettings( *sheet_info );
986 
987  aPlotter->SetViewport( offset, IU_PER_MILS/10, compound_scale, aPlotOpts->GetMirror() );
988  // Has meaning only for gerber plotter. Must be called only after SetViewport
989  aPlotter->SetGerberCoordinatesFormat( aPlotOpts->GetGerberPrecision() );
990 
991  aPlotter->SetDefaultLineWidth( aPlotOpts->GetLineWidth() );
992  aPlotter->SetCreator( wxT( "PCBNEW" ) );
993  aPlotter->SetColorMode( false ); // default is plot in Black and White.
994  aPlotter->SetTextMode( aPlotOpts->GetTextMode() );
995 }
996 
997 
1001 static void FillNegativeKnockout( PLOTTER *aPlotter, const EDA_RECT &aBbbox )
1002 {
1003  const int margin = 5 * IU_PER_MM; // Add a 5 mm margin around the board
1004  aPlotter->SetNegative( true );
1005  aPlotter->SetColor( WHITE ); // Which will be plotted as black
1006  EDA_RECT area = aBbbox;
1007  area.Inflate( margin );
1008  aPlotter->Rect( area.GetOrigin(), area.GetEnd(), FILLED_SHAPE );
1009  aPlotter->SetColor( BLACK );
1010 }
1011 
1012 
1016 static void ConfigureHPGLPenSizes( HPGL_PLOTTER *aPlotter, PCB_PLOT_PARAMS *aPlotOpts )
1017 {
1018  // Compute penDiam (the value is given in mils) in pcb units, with plot scale (if Scale is 2,
1019  // penDiam value is always m_HPGLPenDiam so apparent penDiam is actually penDiam / Scale
1020  int penDiam = KiROUND( aPlotOpts->GetHPGLPenDiameter() * IU_PER_MILS / aPlotOpts->GetScale() );
1021 
1022  // Set HPGL-specific options and start
1023  aPlotter->SetPenSpeed( aPlotOpts->GetHPGLPenSpeed() );
1024  aPlotter->SetPenNumber( aPlotOpts->GetHPGLPenNum() );
1025  aPlotter->SetPenDiameter( penDiam );
1026 }
1027 
1028 
1034 PLOTTER* StartPlotBoard( BOARD *aBoard, PCB_PLOT_PARAMS *aPlotOpts, int aLayer,
1035  const wxString& aFullFileName, const wxString& aSheetDesc )
1036 {
1037  // Create the plotter driver and set the few plotter specific options
1038  PLOTTER* plotter = NULL;
1039 
1040  switch( aPlotOpts->GetFormat() )
1041  {
1042  case PLOT_FORMAT_DXF:
1043  DXF_PLOTTER* DXF_plotter;
1044  DXF_plotter = new DXF_PLOTTER();
1045  DXF_plotter->SetUnits(
1046  static_cast<DXF_PLOTTER::DXF_UNITS>( aPlotOpts->GetDXFPlotUnits() ) );
1047 
1048  plotter = DXF_plotter;
1049  break;
1050 
1051  case PLOT_FORMAT_POST:
1052  PS_PLOTTER* PS_plotter;
1053  PS_plotter = new PS_PLOTTER();
1054  PS_plotter->SetScaleAdjust( aPlotOpts->GetFineScaleAdjustX(),
1055  aPlotOpts->GetFineScaleAdjustY() );
1056  plotter = PS_plotter;
1057  break;
1058 
1059  case PLOT_FORMAT_PDF:
1060  plotter = new PDF_PLOTTER();
1061  break;
1062 
1063  case PLOT_FORMAT_HPGL:
1064  HPGL_PLOTTER* HPGL_plotter;
1065  HPGL_plotter = new HPGL_PLOTTER();
1066 
1067  // HPGL options are a little more convoluted to compute, so they get their own function
1068  ConfigureHPGLPenSizes( HPGL_plotter, aPlotOpts );
1069  plotter = HPGL_plotter;
1070  break;
1071 
1072  case PLOT_FORMAT_GERBER:
1073  plotter = new GERBER_PLOTTER();
1074  break;
1075 
1076  case PLOT_FORMAT_SVG:
1077  plotter = new SVG_PLOTTER();
1078  break;
1079 
1080  default:
1081  wxASSERT( false );
1082  return NULL;
1083  }
1084 
1085  // Compute the viewport and set the other options
1086 
1087  // page layout is not mirrored, so temporarily change mirror option for the page layout
1088  PCB_PLOT_PARAMS plotOpts = *aPlotOpts;
1089 
1090  if( plotOpts.GetPlotFrameRef() && plotOpts.GetMirror() )
1091  plotOpts.SetMirror( false );
1092 
1093  initializePlotter( plotter, aBoard, &plotOpts );
1094 
1095  if( plotter->OpenFile( aFullFileName ) )
1096  {
1097  plotter->ClearHeaderLinesList();
1098 
1099  // For the Gerber "file function" attribute, set the layer number
1100  if( plotter->GetPlotterType() == PLOT_FORMAT_GERBER )
1101  {
1102  bool useX2mode = plotOpts.GetUseGerberX2format();
1103 
1104  GERBER_PLOTTER* gbrplotter = static_cast <GERBER_PLOTTER*> ( plotter );
1105  gbrplotter->UseX2format( useX2mode );
1106  gbrplotter->UseX2NetAttributes( plotOpts.GetIncludeGerberNetlistInfo() );
1107 
1108  // Attributes can be added using X2 format or as comment (X1 format)
1109  AddGerberX2Attribute( plotter, aBoard, aLayer, not useX2mode );
1110  }
1111 
1112  plotter->StartPlot();
1113 
1114  // Plot the frame reference if requested
1115  if( aPlotOpts->GetPlotFrameRef() )
1116  {
1117  PlotWorkSheet( plotter, aBoard->GetTitleBlock(), aBoard->GetPageSettings(),
1118  1, 1, aSheetDesc, aBoard->GetFileName() );
1119 
1120  if( aPlotOpts->GetMirror() )
1121  initializePlotter( plotter, aBoard, aPlotOpts );
1122  }
1123 
1124  // When plotting a negative board: draw a black rectangle (background for plot board
1125  // in white) and switch the current color to WHITE; note the color inversion is actually
1126  // done in the driver (if supported)
1127  if( aPlotOpts->GetNegative() )
1128  {
1129  EDA_RECT bbox = aBoard->ComputeBoundingBox();
1130  FillNegativeKnockout( plotter, bbox );
1131  }
1132 
1133  return plotter;
1134  }
1135 
1136  delete plotter;
1137  return NULL;
1138 }
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:676
a class to handle special data (items attributes) during plot.
int m_SolderMaskMargin
Solder mask margin.
#define SMALL_DRILL
Definition: pcbplot.h:72
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:60
const PAGE_INFO & GetPageSettings() const
Definition: class_board.h:546
virtual void SetCreator(const wxString &aCreator)
Definition: plotter.h:161
int OutlineCount() const
Returns the number of outlines in the set
void UseX2NetAttributes(bool aEnable)
Definition: plotter.h:1277
virtual void EndBlock(void *aData)
calling this function allows one to define the end of a group of drawing items for instance in SVG or...
Definition: plotter.h:478
TEXTE_PCB class definition.
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
bool GetPlotFrameRef() const
virtual LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
bool GetDXFPlotPolygonMode() const
like PAD_STANDARD, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:66
static void initializePlotter(PLOTTER *aPlotter, BOARD *aBoard, PCB_PLOT_PARAMS *aPlotOpts)
Set up most plot options for plotting a board (especially the viewport) Important thing: page size is...
void BooleanAdd(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset union For aFastMode meaning, see function booleanOp
virtual bool StartPlot()=0
virtual void SetColor(COLOR4D color)=0
static void FillNegativeKnockout(PLOTTER *aPlotter, const EDA_RECT &aBbbox)
Prefill in black an area a little bigger than the board to prepare for the negative plot.
const wxPoint & GetStart() const
Definition: class_track.h:109
void PlotPad(D_PAD *aPad, COLOR4D aColor, EDA_DRAW_MODE_T aPlotMode)
Plot a pad.
virtual bool OpenFile(const wxString &aFullFilename)
Open or create the plot file aFullFilename.
Definition: plotter.cpp:81
void SetNetAttribType(int aNetAttribType)
Definition: gbr_metadata.h:163
virtual void SetColorMode(bool aColorMode)
Plot in B/W or color.
Definition: plotter.h:126
void SetScaleAdjust(double scaleX, double scaleY)
Set the 'fine' scaling for the postscript engine.
Definition: plotter.h:710
virtual void SetLayerPolarity(bool aPositive)
Function SetLayerPolarity sets current Gerber layer polarity to positive or negative by writing %LPD*...
Definition: plotter.h:443
static const PCB_LAYER_ID plot_seq[]
void PlotStandardLayer(BOARD *aBoard, PLOTTER *aPlotter, LSET aLayerMask, const PCB_PLOT_PARAMS &aPlotOpt)
Function PlotStandardLayer plot copper or technical layers.
int color
Definition: DXF_plotter.cpp:62
PlotFormat GetFormat() const
void PlotSilkScreen(BOARD *aBoard, PLOTTER *aPlotter, LSET aLayerMask, const PCB_PLOT_PARAMS &aPlotOpt)
Function PlotSilkScreen plot silkscreen layers which have specific requirements, mainly for pads.
void TransformShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, int aClearanceValue, int aError=ARC_HIGH_DEF, bool ignoreLineWidth=false) const override
Function TransformShapeWithClearanceToPolygon Convert the track shape to a closed polygon Used in fil...
void PlotDrillMarks()
Function PlotDrillMarks Draw a drill mark for pads and vias.
void SetMirror(bool aFlag)
virtual void SetPenDiameter(double diameter)
virtual void StartBlock(void *aData)
calling this function allows one to define the beginning of a group of drawing items,...
Definition: plotter.h:469
bool PlotAllTextsModule(MODULE *aModule)
void UseX2format(bool aEnable)
Definition: plotter.h:1276
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:531
int GetHPGLPenSpeed() const
const SHAPE_LINE_CHAIN & CHole(int aOutline, int aHole) const
void AddGerberX2Attribute(PLOTTER *aPlotter, const BOARD *aBoard, LAYER_NUM aLayer, bool aUseX1CompatibilityMode)
Calculates some X2 attributes, as defined in the Gerber file format specification and add them to the...
Definition: pcbplot.cpp:354
void SetUnits(DXF_UNITS aUnit)
Set the units to use for plotting the DXF file.
void SetDrillMarksType(DrillMarksType aVal)
virtual void PlotPoly(const std::vector< wxPoint > &aCornerList, FILL_T aFill, int aWidth=USE_DEFAULT_LINE_WIDTH, void *aData=NULL)=0
Function PlotPoly.
virtual void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: plotter.cpp:590
int PointCount() const
Function PointCount()
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:367
const wxString & GetFileName() const
Definition: class_board.h:216
double GetScale() const
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
void PlotFilledAreas(ZONE_CONTAINER *aZone, SHAPE_POLY_SET &aPolysList)
bool GetUseGerberX2format() const
virtual void SetGerberCoordinatesFormat(int aResolution, bool aUseInches=false)
Definition: plotter.h:457
Definitions for tracks, vias and zones.
This file contains miscellaneous commonly used macros and functions.
bool GetMirror() const
void PlotWorkSheet(PLOTTER *plotter, const TITLE_BLOCK &aTitleBlock, const PAGE_INFO &aPageInfo, int aSheetNumber, int aNumberOfSheets, const wxString &aSheetDesc, const wxString &aFilename, const COLOR4D aColor)
Classes used in Pcbnew, CvPcb and GerbView.
Board plot function definition file.
COLOR4D GetItemColor(int aItemIdx) const
Function GetItemColor.
static void PlotSolderMaskLayer(BOARD *aBoard, PLOTTER *aPlotter, LSET aLayerMask, const PCB_PLOT_PARAMS &aPlotOpt, int aMinThickness)
DIMENSION class definition.
const VECTOR2I & CPoint(int aIndex) const
Function Point()
const wxPoint GetEnd() const
Definition: eda_rect.h:116
COLOR4D GetLayerColor(LAYER_NUM aLayer) const
Function GetLayerColor.
virtual void FlashPadCircle(const wxPoint &aPadPos, int aDiameter, EDA_DRAW_MODE_T aTraceMode, void *aData)=0
virtual function FlashPadCircle
void PlotLayerOutlines(BOARD *aBoard, PLOTTER *aPlotter, LSET aLayerMask, const PCB_PLOT_PARAMS &aPlotOpt)
Function PlotLayerOutlines plot copper outline of a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
bool GetA4Output() const
int GetGerberPrecision() const
Class LSET is a set of PCB_LAYER_IDs.
void SetLayerSet(LSET aLayerMask)
Definition: pcbplot.h:104
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
MODULES & Modules()
Definition: class_board.h:227
void PlotOneBoardLayer(BOARD *aBoard, PLOTTER *aPlotter, PCB_LAYER_ID aLayer, const PCB_PLOT_PARAMS &aPlotOpt)
Function PlotOneBoardLayer main function to plot one copper or technical layer.
Class SHAPE_POLY_SET.
const wxPoint GetOrigin() const
Definition: eda_rect.h:114
EDA_DRAW_MODE_T
Definition: eda_text.h:59
Class PAGE_INFO describes the page size and margins of a paper page on which to eventually print or p...
Definition: page_info.h:54
void PlotBoardGraphicItems()
plot items like text and graphics, but not tracks and modules
virtual void SetTextMode(PlotTextMode mode)
Change the current text mode.
Definition: plotter.h:452
COLOR4D GetColor() const
virtual void SetPenSpeed(int speed)
Definition: plotter.h:630
bool GetIncludeGerberNetlistInfo() const
void Plot_1_EdgeModule(EDGE_MODULE *aEdge)
void Deflate(int aAmount, int aCircleSegmentsCount, CORNER_STRATEGY aCornerStrategy=ROUND_ALL_CORNERS)
void SetSkipPlotNPTH_Pads(bool aSkip)
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Function SetLayer sets the layer this item is on.
Definition: class_zone.cpp:230
VIATYPE_T GetViaType() const
Definition: class_track.h:346
void ConvertBrdLayerToPolygonalContours(PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aOutlines)
Function ConvertBrdLayerToPolygonalContours Build a set of polygons which are the outlines of copper ...
bool GetSkipPlotNPTH_Pads() const
a few functions useful in geometry calculations.
void Simplify(POLYGON_MODE aFastMode)
Simplifies the polyset (merges overlapping polys, eliminates degeneracy/self-intersections) For aFast...
static void ConfigureHPGLPenSizes(HPGL_PLOTTER *aPlotter, PCB_PLOT_PARAMS *aPlotOpts)
Calculate the effective size of HPGL pens and set them in the plotter object.
const wxPoint & GetAuxOrigin() const
Definition: class_board.h:354
const wxString & GetNetname() const
Function GetNetname.
bool GetAutoScale() const
Class PCB_PLOT_PARAMS handles plot parameters and options when plotting/printing a board.
#define _(s)
int HoleCount(int aOutline) const
Returns the number of holes in a given outline
const wxPoint GetPosition() const override
Definition: class_track.h:319
PLOTTER * StartPlotBoard(BOARD *aBoard, PCB_PLOT_PARAMS *aPlotOpts, int aLayer, const wxString &aFullFileName, const wxString &aSheetDesc)
Open a new plotfile using the options (and especially the format) specified in the options and prepar...
virtual void SetNegative(bool aNegative)
Definition: plotter.h:118
double GetFineScaleAdjustX() const
void Fracture(POLYGON_MODE aFastMode)
Converts a set of polygons with holes to a singe outline with "slits"/"fractures" connecting the oute...
Class LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
virtual void SetViewport(const wxPoint &aOffset, double aIusPerDecimil, double aScale, bool aMirror)=0
Set the plot offset and scaling for the current plot.
aperture used for connected items like tracks (not vias)
Definition: gbr_metadata.h:84
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Definition: macros.h:108
virtual void SetDefaultLineWidth(int width)=0
Set the default line width.
int GetLineWidth() const
int GetHPGLPenNum() const
void SetNetName(const wxString &aNetname)
Definition: gbr_metadata.h:173
Base plotter engine class.
Definition: plotter.h:97
const COLORS_DESIGN_SETTINGS & Colors() const
Function GetColorSettings.
Definition: class_board.h:561
ZONE_CONTAINERS & Zones()
Definition: class_board.h:241
bool GetPlotViaOnMaskLayer() const
smd pads, front layer
TITLE_BLOCK & GetTitleBlock()
Definition: class_board.h:552
int GetWidth() const
Definition: class_track.h:103
Class to handle a graphic segment.
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
#define max(a, b)
Definition: auxiliary.h:86
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:161
bool GetSubtractMaskFromSilk() const
Class SHAPE_LINE_CHAIN.
virtual PlotFormat GetPlotterType() const =0
Returns the effective plot engine in use.
virtual void ThickSegment(const wxPoint &start, const wxPoint &end, int width, EDA_DRAW_MODE_T tracemode, void *aData)
Definition: plotter.cpp:505
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
virtual void SetPenNumber(int number)
Definition: plotter.h:635
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
double GetHPGLPenDiameter() const
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
#define IU_PER_MILS
Definition: plotter.cpp:136
The common library.
PlotTextMode GetTextMode() const
void InflateWithLinkedHoles(int aFactor, int aCircleSegmentsCount, POLYGON_MODE aFastMode)
Performs outline inflation/deflation, using round corners.
virtual void Rect(const wxPoint &p1, const wxPoint &p2, FILL_T fill, int width=USE_DEFAULT_LINE_WIDTH)=0
wxPoint Centre() const
Definition: eda_rect.h:62
void ClearHeaderLinesList()
Function ClearHeaderLinesList remove all lines from the list of free lines to print at the beginning ...
Definition: plotter.h:185
Definition: colors.h:49
EDA_RECT ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Function ComputeBoundingBox calculates the bounding box containing all board items (or board edge seg...
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
double GetFineScaleAdjustY() const
bool GetPlotPadsOnSilkLayer() const
PCB_TARGET class definition.
void SetApertureAttrib(GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB aApertAttribute)
Definition: gbr_metadata.h:153
bool m_NotInNet
true if a pad of a footprint cannot be connected (for instance a mechanical NPTH, ot a not named pad)...
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
int getFineWidthAdj()
Definition: pcbplot.h:95
GBR_NETLIST_METADATA m_NetlistMetadata
a item to handle object attribute:
Definition: gbr_metadata.h:205
bool GetNegative() const
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Function IsOnLayer tests to see if this object is on the given layer.
Module description (excepted pads)
Definition: colors.h:45
bool GetUseAuxOrigin() const
EDGE_MODULE class definition.
DXF_PLOTTER::DXF_UNITS GetDXFPlotUnits() const
void SetMinThickness(int aMinThickness)
Definition: class_zone.h:186
DrillMarksType GetDrillMarksType() const
print info associated to a net (TO.N attribute)
COLOR4D getColor(LAYER_NUM aLayer)
Function getColor.
TRACKS & Tracks()
Definition: class_board.h:218
virtual void Circle(const wxPoint &pos, int diametre, FILL_T fill, int width=USE_DEFAULT_LINE_WIDTH)=0
bool GetExcludeEdgeLayer() const
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
int m_SolderMaskMinWidth
Solder mask min width.
const wxSize GetSize() const
Definition: eda_rect.h:103
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:114
#define min(a, b)
Definition: auxiliary.h:85
EDA_DRAW_MODE_T GetPlotMode() const
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39
void Unfracture(POLYGON_MODE aFastMode)
Converts a single outline slitted ("fractured") polygon into a set ouf outlines with holes.