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-2020 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 <eda_item.h>
34 #include <geometry/shape_segment.h>
35 #include <pcb_base_frame.h>
36 #include <math/util.h> // for KiROUND
37 
38 #include <class_board.h>
39 #include <class_module.h>
40 #include <class_track.h>
41 #include <fp_shape.h>
42 #include <pcb_text.h>
43 #include <class_zone.h>
44 #include <pcb_shape.h>
45 #include <class_pcb_target.h>
46 #include <class_dimension.h>
47 
48 #include <pcbplot.h>
49 #include <pcb_painter.h>
50 #include <gbr_metadata.h>
51 
52 /*
53  * Plot a solder mask layer. Solder mask layers have a minimum thickness value and cannot be
54  * drawn like standard layers, unless the minimum thickness is 0.
55  */
56 static void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
57  const PCB_PLOT_PARAMS& aPlotOpt, int aMinThickness );
58 
59 
60 void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
61  const PCB_PLOT_PARAMS& aPlotOpt )
62 {
63  PCB_PLOT_PARAMS plotOpt = aPlotOpt;
64  int soldermask_min_thickness = aBoard->GetDesignSettings().m_SolderMaskMinWidth;
65 
66  // Set a default color and the text mode for this layer
67  aPlotter->SetColor( aPlotOpt.GetColor() );
68  aPlotter->SetTextMode( aPlotOpt.GetTextMode() );
69 
70  // Specify that the contents of the "Edges Pcb" layer are to be plotted in addition to the
71  // contents of the currently specified layer.
72  LSET layer_mask( aLayer );
73 
74  if( !aPlotOpt.GetExcludeEdgeLayer() )
75  layer_mask.set( Edge_Cuts );
76 
77  if( IsCopperLayer( aLayer ) )
78  {
79  // Skip NPTH pads on copper layers ( only if hole size == pad size ):
80  // Drill mark will be plotted if drill mark is SMALL_DRILL_SHAPE or FULL_DRILL_SHAPE
81  if( plotOpt.GetFormat() == PLOT_FORMAT::DXF )
82  {
83  plotOpt.SetSkipPlotNPTH_Pads( false );
84  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
85  }
86  else
87  {
88  plotOpt.SetSkipPlotNPTH_Pads( true );
89  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
90  }
91  }
92  else
93  {
94  switch( aLayer )
95  {
96  case B_Mask:
97  case F_Mask:
98  plotOpt.SetSkipPlotNPTH_Pads( false );
99  // Disable plot pad holes
101 
102  // Plot solder mask:
103  if( soldermask_min_thickness == 0 )
104  {
105  if( plotOpt.GetFormat() == PLOT_FORMAT::DXF )
106  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
107  else
108  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
109  }
110  else
111  PlotSolderMaskLayer( aBoard, aPlotter, layer_mask, plotOpt,
112  soldermask_min_thickness );
113 
114  break;
115 
116  case B_Adhes:
117  case F_Adhes:
118  case B_Paste:
119  case F_Paste:
120  plotOpt.SetSkipPlotNPTH_Pads( false );
121  // Disable plot pad holes
123 
124  if( plotOpt.GetFormat() == PLOT_FORMAT::DXF )
125  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
126  else
127  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
128  break;
129 
130  case F_SilkS:
131  case B_SilkS:
132  if( plotOpt.GetFormat() == PLOT_FORMAT::DXF && plotOpt.GetDXFPlotPolygonMode() )
133  // PlotLayerOutlines() is designed only for DXF plotters.
134  // and must not be used for other plot formats
135  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
136  else
137  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
138 
139  // Gerber: Subtract soldermask from silkscreen if enabled
140  if( aPlotter->GetPlotterType() == PLOT_FORMAT::GERBER
141  && plotOpt.GetSubtractMaskFromSilk() )
142  {
143  if( aLayer == F_SilkS )
144  layer_mask = LSET( F_Mask );
145  else
146  layer_mask = LSET( B_Mask );
147 
148  // Create the mask to subtract by creating a negative layer polarity
149  aPlotter->SetLayerPolarity( false );
150 
151  // Disable plot pad holes
153 
154  // Plot the mask
155  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
156  }
157  break;
158 
159  // These layers are plotted like silk screen layers.
160  // Mainly, pads on these layers are not filled.
161  // This is not necessary the best choice.
162  case Dwgs_User:
163  case Cmts_User:
164  case Eco1_User:
165  case Eco2_User:
166  case Edge_Cuts:
167  case Margin:
168  case F_CrtYd:
169  case B_CrtYd:
170  case F_Fab:
171  case B_Fab:
172  plotOpt.SetSkipPlotNPTH_Pads( false );
174 
175  if( plotOpt.GetFormat() == PLOT_FORMAT::DXF && plotOpt.GetDXFPlotPolygonMode() )
176  // PlotLayerOutlines() is designed only for DXF plotters.
177  // and must not be used for other plot formats
178  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
179  else
180  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
181  break;
182 
183  default:
184  plotOpt.SetSkipPlotNPTH_Pads( false );
186 
187  if( plotOpt.GetFormat() == PLOT_FORMAT::DXF && plotOpt.GetDXFPlotPolygonMode() )
188  // PlotLayerOutlines() is designed only for DXF plotters.
189  // and must not be used for other plot formats
190  PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
191  else
192  PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
193  break;
194  }
195  }
196 }
197 
198 
199 /*
200  * Plot a copper layer or mask.
201  * Silk screen layers are not plotted here.
202  */
203 void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
204  const PCB_PLOT_PARAMS& aPlotOpt )
205 {
206  BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
207 
208  itemplotter.SetLayerSet( aLayerMask );
209 
210  OUTLINE_MODE plotMode = aPlotOpt.GetPlotMode();
211  bool onCopperLayer = ( LSET::AllCuMask() & aLayerMask ).any();
212  bool onSolderMaskLayer = ( LSET( 2, F_Mask, B_Mask ) & aLayerMask ).any();
213  bool onSolderPasteLayer = ( LSET( 2, F_Paste, B_Paste ) & aLayerMask ).any();
214  bool onFrontFab = ( LSET( F_Fab ) & aLayerMask ).any();
215  bool onBackFab = ( LSET( B_Fab ) & aLayerMask ).any();
216  bool sketchPads = ( onFrontFab || onBackFab ) && aPlotOpt.GetSketchPadsOnFabLayers();
217 
218  // Plot edge layer and graphic items
219  itemplotter.PlotBoardGraphicItems();
220 
221  // Draw footprint texts:
222  for( MODULE* module : aBoard->Modules() )
223  itemplotter.PlotFootprintTextItems( module );
224 
225  // Draw footprint other graphic items:
226  for( MODULE* module : aBoard->Modules() )
227  itemplotter.PlotFootprintGraphicItems( module );
228 
229  // Plot footprint pads
230  for( MODULE* module : aBoard->Modules() )
231  {
232  aPlotter->StartBlock( NULL );
233 
234  for( D_PAD* pad : module->Pads() )
235  {
236  OUTLINE_MODE padPlotMode = plotMode;
237 
238  if( !( pad->GetLayerSet() & aLayerMask ).any() )
239  {
240  if( sketchPads &&
241  ( ( onFrontFab && pad->GetLayerSet().Contains( F_Cu ) ) ||
242  ( onBackFab && pad->GetLayerSet().Contains( B_Cu ) ) ) )
243  padPlotMode = SKETCH;
244  else
245  continue;
246  }
247 
249  if( onCopperLayer && !pad->FlashLayer( aLayerMask ) )
250  continue;
251 
253 
254  if( pad->GetLayerSet()[B_Cu] )
255  color = aPlotOpt.ColorSettings()->GetColor( LAYER_PAD_BK );
256 
257  if( pad->GetLayerSet()[F_Cu] )
258  color = color.LegacyMix( aPlotOpt.ColorSettings()->GetColor( LAYER_PAD_FR ) );
259 
260  if( sketchPads && aLayerMask[F_Fab] )
261  color = aPlotOpt.ColorSettings()->GetColor( F_Fab );
262  else if( sketchPads && aLayerMask[B_Fab] )
263  color = aPlotOpt.ColorSettings()->GetColor( B_Fab );
264 
265  wxSize margin;
266  int width_adj = 0;
267 
268  if( onCopperLayer )
269  width_adj = itemplotter.getFineWidthAdj();
270 
271  if( onSolderMaskLayer )
272  margin.x = margin.y = pad->GetSolderMaskMargin();
273 
274  if( onSolderPasteLayer )
275  margin = pad->GetSolderPasteMargin();
276 
277  // Now offset the pad size by margin + width_adj
278  wxSize padPlotsSize = pad->GetSize() + margin * 2 + wxSize( width_adj, width_adj );
279 
280  // Store these parameters that can be modified to plot inflated/deflated pads shape
281  PAD_SHAPE_T padShape = pad->GetShape();
282  wxSize padSize = pad->GetSize();
283  wxSize padDelta = pad->GetDelta(); // has meaning only for trapezoidal pads
284  double padCornerRadius = pad->GetRoundRectCornerRadius();
285 
286  // Don't draw a null size item :
287  if( padPlotsSize.x <= 0 || padPlotsSize.y <= 0 )
288  continue;
289 
290  switch( pad->GetShape() )
291  {
292  case PAD_SHAPE_CIRCLE:
293  case PAD_SHAPE_OVAL:
294  pad->SetSize( padPlotsSize );
295 
296  if( aPlotOpt.GetSkipPlotNPTH_Pads() &&
298  ( pad->GetSize() == pad->GetDrillSize() ) &&
299  ( pad->GetAttribute() == PAD_ATTRIB_NPTH ) )
300  break;
301 
302  itemplotter.PlotPad( pad, color, padPlotMode );
303  break;
304 
305  case PAD_SHAPE_RECT:
306  pad->SetSize( padPlotsSize );
307 
308  if( margin.x > 0 )
309  {
310  pad->SetShape( PAD_SHAPE_ROUNDRECT );
311  pad->SetRoundRectCornerRadius( margin.x );
312  }
313 
314  itemplotter.PlotPad( pad, color, padPlotMode );
315  break;
316 
317  case PAD_SHAPE_TRAPEZOID:
318  {
319  wxSize scale( padPlotsSize.x / padSize.x, padPlotsSize.y / padSize.y );
320  pad->SetDelta( wxSize( padDelta.x * scale.x, padDelta.y * scale.y ) );
321  pad->SetSize( padPlotsSize );
322 
323  itemplotter.PlotPad( pad, color, padPlotMode );
324  }
325  break;
326 
327  case PAD_SHAPE_ROUNDRECT:
329  // Chamfer and rounding are stored as a percent and so don't need scaling
330  pad->SetSize( padPlotsSize );
331  itemplotter.PlotPad( pad, color, padPlotMode );
332  break;
333 
334  case PAD_SHAPE_CUSTOM:
335  {
336  // inflate/deflate a custom shape is a bit complex.
337  // so build a similar pad shape, and inflate/deflate the polygonal shape
338  D_PAD dummy( *pad );
339  SHAPE_POLY_SET shape;
340  pad->MergePrimitivesAsPolygon( &shape, UNDEFINED_LAYER );
341  // Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
342  // which can create bad shapes if margin.x is < 0
343  int maxError = aBoard->GetDesignSettings().m_MaxError;
344  int numSegs = GetArcToSegmentCount( margin.x, maxError, 360.0 );
345  shape.InflateWithLinkedHoles( margin.x, numSegs, SHAPE_POLY_SET::PM_FAST );
346  dummy.DeletePrimitivesList();
347  dummy.AddPrimitivePoly( shape, 0 );
348 
349  // Be sure the anchor pad is not bigger than the deflated shape because this
350  // anchor will be added to the pad shape when plotting the pad. So now the
351  // polygonal shape is built, we can clamp the anchor size
352  if( margin.x < 0 ) // we expect margin.x = margin.y for custom pads
353  dummy.SetSize( padPlotsSize );
354 
355  itemplotter.PlotPad( &dummy, color, padPlotMode );
356  }
357  break;
358  }
359 
360  // Restore the pad parameters modified by the plot code
361  pad->SetSize( padSize );
362  pad->SetDelta( padDelta );
363  pad->SetShape( padShape );
364  pad->SetRoundRectCornerRadius( padCornerRadius );
365  }
366 
367  aPlotter->EndBlock( NULL );
368  }
369 
370  // Plot vias on copper layers, and if aPlotOpt.GetPlotViaOnMaskLayer() is true,
371  // plot them on solder mask
372 
373  GBR_METADATA gbr_metadata;
374 
375  bool isOnCopperLayer = ( aLayerMask & LSET::AllCuMask() ).any();
376 
377  if( isOnCopperLayer )
378  {
381  }
382 
383  aPlotter->StartBlock( NULL );
384 
385  for( TRACK* track : aBoard->Tracks() )
386  {
387  const VIA* via = dyn_cast<const VIA*>( track );
388 
389  if( !via )
390  continue;
391 
392  // vias are not plotted if not on selected layer, but if layer is SOLDERMASK_LAYER_BACK
393  // or SOLDERMASK_LAYER_FRONT, vias are drawn only if they are on the corresponding
394  // external copper layer
395  LSET via_mask_layer = via->GetLayerSet();
396 
397  if( aPlotOpt.GetPlotViaOnMaskLayer() )
398  {
399  if( via_mask_layer[B_Cu] )
400  via_mask_layer.set( B_Mask );
401 
402  if( via_mask_layer[F_Cu] )
403  via_mask_layer.set( F_Mask );
404  }
405 
406  if( !( via_mask_layer & aLayerMask ).any() )
407  continue;
408 
409  int via_margin = 0;
410  double width_adj = 0;
411 
412  // If the current layer is a solder mask, use the global mask clearance for vias
413  if( aLayerMask[B_Mask] || aLayerMask[F_Mask] )
414  via_margin = aBoard->GetDesignSettings().m_SolderMaskMargin;
415 
416  if( ( aLayerMask & LSET::AllCuMask() ).any() )
417  width_adj = itemplotter.getFineWidthAdj();
418 
419  int diameter = via->GetWidth() + 2 * via_margin + width_adj;
420 
422  if( onCopperLayer && !via->FlashLayer( aLayerMask ) )
423  continue;
424 
425  // Don't draw a null size item :
426  if( diameter <= 0 )
427  continue;
428 
429  // Some vias can be not connected (no net).
430  // Set the m_NotInNet for these vias to force a empty net name in gerber file
431  gbr_metadata.m_NetlistMetadata.m_NotInNet = via->GetNetname().IsEmpty();
432 
433  gbr_metadata.SetNetName( via->GetNetname() );
434 
435  COLOR4D color = aPlotOpt.ColorSettings()->GetColor(
436  LAYER_VIAS + static_cast<int>( via->GetViaType() ) );
437  // Set plot color (change WHITE to LIGHTGRAY because the white items are not seen on a
438  // white paper or screen
439  aPlotter->SetColor( color != WHITE ? color : LIGHTGRAY );
440  aPlotter->FlashPadCircle( via->GetStart(), diameter, plotMode, &gbr_metadata );
441  }
442 
443  aPlotter->EndBlock( NULL );
444  aPlotter->StartBlock( NULL );
446 
447  // Plot tracks (not vias) :
448  for( TRACK* track : aBoard->Tracks() )
449  {
450  if( track->Type() == PCB_VIA_T )
451  continue;
452 
453  if( !aLayerMask[track->GetLayer()] )
454  continue;
455 
456  // Some track segments can be not connected (no net).
457  // Set the m_NotInNet for these segments to force a empty net name in gerber file
458  gbr_metadata.m_NetlistMetadata.m_NotInNet = track->GetNetname().IsEmpty();
459 
460  gbr_metadata.SetNetName( track->GetNetname() );
461  int width = track->GetWidth() + itemplotter.getFineWidthAdj();
462  aPlotter->SetColor( itemplotter.getColor( track->GetLayer() ) );
463 
464  if( track->Type() == PCB_ARC_T )
465  {
466  ARC* arc = static_cast<ARC*>( track );
467  VECTOR2D center( arc->GetCenter() );
468  int radius = arc->GetRadius();
469  double start_angle = arc->GetArcAngleStart();
470  double end_angle = start_angle + arc->GetAngle();
471 
472  aPlotter->ThickArc( wxPoint( center.x, center.y ), -end_angle, -start_angle,
473  radius, width, plotMode, &gbr_metadata );
474  }
475  else
476  {
477  aPlotter->ThickSegment( track->GetStart(), track->GetEnd(), width, plotMode,
478  &gbr_metadata );
479  }
480 
481  }
482 
483  aPlotter->EndBlock( NULL );
484 
485  // Plot filled ares
486  aPlotter->StartBlock( NULL );
487 
488  NETINFO_ITEM nonet( aBoard );
489 
490  for( ZONE_CONTAINER* zone : aBoard->Zones() )
491  {
492  for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
493  {
494  if( !aLayerMask[layer] )
495  continue;
496 
497  SHAPE_POLY_SET mainArea = zone->GetFilledPolysList( layer );
498  SHAPE_POLY_SET islands;
499 
500  for( int i = mainArea.OutlineCount() - 1; i >= 0; i-- )
501  {
502  if( zone->IsIsland( layer, i ) )
503  {
504  islands.AddOutline( mainArea.CPolygon( i )[0] );
505  mainArea.DeletePolygon( i );
506  }
507  }
508 
509  itemplotter.PlotFilledAreas( zone, mainArea );
510 
511  if( !islands.IsEmpty() )
512  {
513  ZONE_CONTAINER dummy( *zone );
514  dummy.SetNet( &nonet );
515  itemplotter.PlotFilledAreas( &dummy, islands );
516  }
517  }
518  }
519 
520  aPlotter->EndBlock( NULL );
521 
522  // Adding drill marks, if required and if the plotter is able to plot them:
524  itemplotter.PlotDrillMarks();
525 }
526 
527 
528 // Seems like we want to plot from back to front?
529 static const PCB_LAYER_ID plot_seq[] = {
530 
531  B_Adhes, // 32
532  F_Adhes,
533  B_Paste,
534  F_Paste,
535  B_SilkS,
536  B_Mask,
537  F_Mask,
538  Dwgs_User,
539  Cmts_User,
540  Eco1_User,
541  Eco2_User,
542  Edge_Cuts,
543  Margin,
544 
545  F_CrtYd, // CrtYd & Body are footprint only
546  B_CrtYd,
547  F_Fab,
548  B_Fab,
549 
550  B_Cu,
551  In30_Cu,
552  In29_Cu,
553  In28_Cu,
554  In27_Cu,
555  In26_Cu,
556  In25_Cu,
557  In24_Cu,
558  In23_Cu,
559  In22_Cu,
560  In21_Cu,
561  In20_Cu,
562  In19_Cu,
563  In18_Cu,
564  In17_Cu,
565  In16_Cu,
566  In15_Cu,
567  In14_Cu,
568  In13_Cu,
569  In12_Cu,
570  In11_Cu,
571  In10_Cu,
572  In9_Cu,
573  In8_Cu,
574  In7_Cu,
575  In6_Cu,
576  In5_Cu,
577  In4_Cu,
578  In3_Cu,
579  In2_Cu,
580  In1_Cu,
581  F_Cu,
582 
583  F_SilkS,
584 };
585 
586 
587 /*
588  * Plot outlines of copper, for copper layer
589  */
590 void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
591  const PCB_PLOT_PARAMS& aPlotOpt )
592 {
593  BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
594  itemplotter.SetLayerSet( aLayerMask );
595 
596  SHAPE_POLY_SET outlines;
597 
598  for( LSEQ seq = aLayerMask.Seq( plot_seq, arrayDim( plot_seq ) ); seq; ++seq )
599  {
600  PCB_LAYER_ID layer = *seq;
601 
602  outlines.RemoveAllContours();
603  aBoard->ConvertBrdLayerToPolygonalContours( layer, outlines );
604 
605  outlines.Simplify( SHAPE_POLY_SET::PM_FAST );
606 
607  // Plot outlines
608  std::vector<wxPoint> cornerList;
609 
610  // Now we have one or more basic polygons: plot each polygon
611  for( int ii = 0; ii < outlines.OutlineCount(); ii++ )
612  {
613  for(int kk = 0; kk <= outlines.HoleCount (ii); kk++ )
614  {
615  cornerList.clear();
616  const SHAPE_LINE_CHAIN& path = (kk == 0) ? outlines.COutline( ii ) : outlines.CHole( ii, kk - 1 );
617 
618  for( int jj = 0; jj < path.PointCount(); jj++ )
619  cornerList.emplace_back( (wxPoint) path.CPoint( jj ) );
620 
621  // Ensure the polygon is closed
622  if( cornerList[0] != cornerList[cornerList.size() - 1] )
623  cornerList.push_back( cornerList[0] );
624 
625  aPlotter->PlotPoly( cornerList, FILL_TYPE::NO_FILL );
626  }
627  }
628 
629  // Plot pad holes
631  {
632  int smallDrill = (aPlotOpt.GetDrillMarksType() == PCB_PLOT_PARAMS::SMALL_DRILL_SHAPE)
633  ? SMALL_DRILL : INT_MAX;
634 
635  for( MODULE* module : aBoard->Modules() )
636  {
637  for( D_PAD* pad : module->Pads() )
638  {
639  wxSize hole = pad->GetDrillSize();
640 
641  if( hole.x == 0 || hole.y == 0 )
642  continue;
643 
644  if( hole.x == hole.y )
645  {
646  hole.x = std::min( smallDrill, hole.x );
647  aPlotter->Circle( pad->GetPosition(), hole.x, FILL_TYPE::NO_FILL );
648  }
649  else
650  {
651  // Note: small drill marks have no significance when applied to slots
652  const SHAPE_SEGMENT* seg = pad->GetEffectiveHoleShape();
653  aPlotter->ThickSegment( (wxPoint) seg->GetSeg().A,
654  (wxPoint) seg->GetSeg().B,
655  seg->GetWidth(), SKETCH, NULL );
656  }
657  }
658  }
659  }
660 
661  // Plot vias holes
662  for( TRACK* track : aBoard->Tracks() )
663  {
664  const VIA* via = dyn_cast<const VIA*>( track );
665 
666  if( via && via->IsOnLayer( layer ) ) // via holes can be not through holes
667  {
668  aPlotter->Circle( via->GetPosition(), via->GetDrillValue(), FILL_TYPE::NO_FILL );
669  }
670  }
671  }
672 }
673 
674 
675 /* Plot a solder mask layer.
676  * Solder mask layers have a minimum thickness value and cannot be drawn like standard layers,
677  * unless the minimum thickness is 0.
678  * Currently the algo is:
679  * 1 - build all pad shapes as polygons with a size inflated by
680  * mask clearance + (min width solder mask /2)
681  * 2 - Merge shapes
682  * 3 - deflate result by (min width solder mask /2)
683  * 4 - ORing result by all pad shapes as polygons with a size inflated by
684  * mask clearance only (because deflate sometimes creates shape artifacts)
685  * 5 - draw result as polygons
686  *
687  * We have 2 algos:
688  * the initial algo, that create polygons for every shape, inflate and deflate polygons
689  * with Min Thickness/2, and merges the result.
690  * Drawback: pads attributes are lost (annoying in Gerber)
691  * the new algo:
692  * create initial polygons for every shape (pad or polygon),
693  * inflate and deflate polygons
694  * with Min Thickness/2, and merges the result (like initial algo)
695  * remove all initial polygons.
696  * The remaining polygons are areas with thickness < min thickness
697  * plot all initial shapes by flashing (or using regions) for pad and polygons
698  * (shapes will be better) and remaining polygons to
699  * remove areas with thickness < min thickness from final mask
700  *
701  * TODO: remove old code after more testing.
702  */
703 #define NEW_ALGO 1
704 
705 void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
706  const PCB_PLOT_PARAMS& aPlotOpt, int aMinThickness )
707 {
708  int maxError = aBoard->GetDesignSettings().m_MaxError;
709  PCB_LAYER_ID layer = aLayerMask[B_Mask] ? B_Mask : F_Mask;
710  SHAPE_POLY_SET buffer;
711  SHAPE_POLY_SET* boardOutline = nullptr;
712 
713  if( aBoard->GetBoardPolygonOutlines( buffer ) )
714  boardOutline = &buffer;
715 
716  // We remove 1nm as we expand both sides of the shapes, so allowing for
717  // a strictly greater than or equal comparison in the shape separation (boolean add)
718  // means that we will end up with separate shapes that then are shrunk
719  int inflate = aMinThickness/2 - 1;
720 
721  BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
722  itemplotter.SetLayerSet( aLayerMask );
723 
724  // Plot edge layer and graphic items.
725  // They do not have a solder Mask margin, because they are graphic items
726  // on this layer (like logos), not actually areas around pads.
727 
728  itemplotter.PlotBoardGraphicItems();
729 
730  for( MODULE* module : aBoard->Modules() )
731  {
732  for( BOARD_ITEM* item : module->GraphicalItems() )
733  {
734  itemplotter.PlotFootprintTextItems( module );
735 
736  if( item->Type() == PCB_FP_SHAPE_T && item->GetLayer() == layer )
737  itemplotter.PlotFootprintGraphicItem( (FP_SHAPE*) item );
738  }
739  }
740 
741  // Build polygons for each pad shape. The size of the shape on solder mask should be size
742  // of pad + clearance around the pad, where clearance = solder mask clearance + extra margin.
743  // Extra margin is half the min width for solder mask, which is used to merge too-close shapes
744  // (distance < aMinThickness), and will be removed when creating the actual shapes.
745 
746  // Will contain shapes inflated by inflate value that will be merged and deflated by
747  // inflate value to build final polygons
748  // After calculations the remaining polygons are polygons to plot
749  SHAPE_POLY_SET areas;
750  // Will contain exact shapes of all items on solder mask
751  SHAPE_POLY_SET initialPolys;
752 
753 #if NEW_ALGO
754  // Generate polygons with arcs inside the shape or exact shape
755  // to minimize shape changes created by arc to segment size correction.
757 #endif
758  {
759  // Plot pads
760  for( MODULE* module : aBoard->Modules() )
761  {
762  // add shapes with their exact mask layer size in initialPolys
763  module->TransformPadsShapesWithClearanceToPolygon( initialPolys, layer, 0, maxError,
764  ERROR_OUTSIDE );
765  // add shapes inflated by aMinThickness/2 in areas
766  module->TransformPadsShapesWithClearanceToPolygon( areas, layer, inflate, maxError,
767  ERROR_OUTSIDE );
768  }
769 
770  // Plot vias on solder masks, if aPlotOpt.GetPlotViaOnMaskLayer() is true,
771  if( aPlotOpt.GetPlotViaOnMaskLayer() )
772  {
773  // The current layer is a solder mask, use the global mask clearance for vias
774  int via_clearance = aBoard->GetDesignSettings().m_SolderMaskMargin;
775  int via_margin = via_clearance + inflate;
776 
777  for( TRACK* track : aBoard->Tracks() )
778  {
779  const VIA* via = dyn_cast<const VIA*>( track );
780 
781  if( !via )
782  continue;
783 
784  // vias are plotted only if they are on the corresponding external copper layer
785  LSET via_set = via->GetLayerSet();
786 
787  if( via_set[B_Cu] )
788  via_set.set( B_Mask );
789 
790  if( via_set[F_Cu] )
791  via_set.set( F_Mask );
792 
793  if( !( via_set & aLayerMask ).any() )
794  continue;
795 
796  // add shapes with their exact mask layer size in initialPolys
797  via->TransformShapeWithClearanceToPolygon( initialPolys, layer, via_clearance,
798  maxError, ERROR_OUTSIDE );
799  // add shapes inflated by aMinThickness/2 in areas
800  via->TransformShapeWithClearanceToPolygon( areas, layer, via_margin, maxError,
801  ERROR_OUTSIDE );
802  }
803  }
804 
805  // Add filled zone areas.
806 #if 0 // Set to 1 if a solder mask margin must be applied to zones on solder mask
807  int zone_margin = aBoard->GetDesignSettings().m_SolderMaskMargin;
808 #else
809  int zone_margin = 0;
810 #endif
811 
812  for( ZONE_CONTAINER* zone : aBoard->Zones() )
813  {
814  if( zone->GetLayer() != layer )
815  continue;
816 
817  // add shapes inflated by aMinThickness/2 in areas
818  zone->TransformSmoothedOutlineToPolygon( areas, inflate + zone_margin, boardOutline );
819  // add shapes with their exact mask layer size in initialPolys
820  zone->TransformSmoothedOutlineToPolygon( initialPolys, zone_margin, boardOutline );
821  }
822 
823  int numSegs = GetArcToSegmentCount( inflate, maxError, 360.0 );
824 
825  // Merge all polygons: After deflating, not merged (not overlapping) polygons
826  // will have the initial shape (with perhaps small changes due to deflating transform)
828  areas.Deflate( inflate, numSegs );
829  }
830 
831 #if !NEW_ALGO
832  // To avoid a lot of code, use a ZONE_CONTAINER to handle and plot polygons, because our
833  // polygons look exactly like filled areas in zones.
834  // Note, also this code is not optimized: it creates a lot of copy/duplicate data.
835  // However it is not complex, and fast enough for plot purposes (copy/convert data is only a
836  // very small calculation time for these calculations).
837  ZONE_CONTAINER zone( aBoard );
838  zone.SetMinThickness( 0 ); // trace polygons only
839  zone.SetLayer( layer );
840  // Combine the current areas to initial areas. This is mandatory because inflate/deflate
841  // transform is not perfect, and we want the initial areas perfectly kept
842  areas.BooleanAdd( initialPolys, SHAPE_POLY_SET::PM_FAST );
844 
845  itemplotter.PlotFilledAreas( &zone, areas );
846 #else
847 
848  // Remove initial shapes: each shape will be added later, as flashed item or region
849  // with a suitable attribute.
850  // Do not merge pads is mandatory in Gerber files: They must be identified as pads
851 
852  // we deflate areas in polygons, to avoid after subtracting initial shapes
853  // having small artifacts due to approximations during polygon transforms
855 
856  // Slightly inflate polygons to avoid any gap between them and other shapes,
857  // These gaps are created by arc to segments approximations
858  areas.Inflate( Millimeter2iu( 0.002 ),6 );
859 
860  // Now, only polygons with a too small thickness are stored in areas.
862 
863  // Plot each initial shape (pads and polygons on mask layer), with suitable attributes:
864  PlotStandardLayer( aBoard, aPlotter, aLayerMask, aPlotOpt );
865 
866  // Add shapes corresponding to areas having too small thickness.
867  std::vector<wxPoint> cornerList;
868 
869  for( int ii = 0; ii < areas.OutlineCount(); ii++ )
870  {
871  cornerList.clear();
872  const SHAPE_LINE_CHAIN& path = areas.COutline( ii );
873 
874  // polygon area in mm^2 :
875  double curr_area = path.Area() / ( IU_PER_MM * IU_PER_MM );
876 
877  // Skip very small polygons: they are certainly artifacts created by
878  // arc approximations and polygon transforms
879  // (inflate/deflate transforms)
880  constexpr double poly_min_area_mm2 = 0.01; // 0.01 mm^2 gives a good filtering
881 
882  if( curr_area < poly_min_area_mm2 )
883  continue;
884 
885  for( int jj = 0; jj < path.PointCount(); jj++ )
886  cornerList.emplace_back( (wxPoint) path.CPoint( jj ) );
887 
888  // Ensure the polygon is closed
889  if( cornerList[0] != cornerList[cornerList.size() - 1] )
890  cornerList.push_back( cornerList[0] );
891 
892  aPlotter->PlotPoly( cornerList, FILL_TYPE::FILLED_SHAPE );
893  }
894 #endif
895 }
896 
897 
904 static void initializePlotter( PLOTTER *aPlotter, BOARD * aBoard,
905  PCB_PLOT_PARAMS *aPlotOpts )
906 {
907  PAGE_INFO pageA4( wxT( "A4" ) );
908  const PAGE_INFO& pageInfo = aBoard->GetPageSettings();
909  const PAGE_INFO* sheet_info;
910  double paperscale; // Page-to-paper ratio
911  wxSize paperSizeIU;
912  wxSize pageSizeIU( pageInfo.GetSizeIU() );
913  bool autocenter = false;
914 
915  // Special options: to fit the sheet to an A4 sheet replace the paper size. However there
916  // is a difference between the autoscale and the a4paper option:
917  // - Autoscale fits the board to the paper size
918  // - A4paper fits the original paper size to an A4 sheet
919  // - Both of them fit the board to an A4 sheet
920  if( aPlotOpts->GetA4Output() )
921  {
922  sheet_info = &pageA4;
923  paperSizeIU = pageA4.GetSizeIU();
924  paperscale = (double) paperSizeIU.x / pageSizeIU.x;
925  autocenter = true;
926  }
927  else
928  {
929  sheet_info = &pageInfo;
930  paperSizeIU = pageSizeIU;
931  paperscale = 1;
932 
933  // Need autocentering only if scale is not 1:1
934  autocenter = (aPlotOpts->GetScale() != 1.0);
935  }
936 
937  EDA_RECT bbox = aBoard->ComputeBoundingBox();
938  wxPoint boardCenter = bbox.Centre();
939  wxSize boardSize = bbox.GetSize();
940 
941  double compound_scale;
942 
943  // Fit to 80% of the page if asked; it could be that the board is empty, in this case
944  // regress to 1:1 scale
945  if( aPlotOpts->GetAutoScale() && boardSize.x > 0 && boardSize.y > 0 )
946  {
947  double xscale = (paperSizeIU.x * 0.8) / boardSize.x;
948  double yscale = (paperSizeIU.y * 0.8) / boardSize.y;
949 
950  compound_scale = std::min( xscale, yscale ) * paperscale;
951  }
952  else
953  compound_scale = aPlotOpts->GetScale() * paperscale;
954 
955 
956  // For the plot offset we have to keep in mind the auxiliary origin too: if autoscaling is
957  // off we check that plot option (i.e. autoscaling overrides auxiliary origin)
958  wxPoint offset( 0, 0);
959 
960  if( autocenter )
961  {
962  offset.x = KiROUND( boardCenter.x - ( paperSizeIU.x / 2.0 ) / compound_scale );
963  offset.y = KiROUND( boardCenter.y - ( paperSizeIU.y / 2.0 ) / compound_scale );
964  }
965  else
966  {
967  if( aPlotOpts->GetUseAuxOrigin() )
968  offset = aBoard->GetDesignSettings().m_AuxOrigin;
969  }
970 
971  aPlotter->SetPageSettings( *sheet_info );
972 
973  aPlotter->SetViewport( offset, IU_PER_MILS/10, compound_scale, aPlotOpts->GetMirror() );
974  // Has meaning only for gerber plotter. Must be called only after SetViewport
975  aPlotter->SetGerberCoordinatesFormat( aPlotOpts->GetGerberPrecision() );
976  // Has meaning only for SVG plotter. Must be called only after SetViewport
977  aPlotter->SetSvgCoordinatesFormat( aPlotOpts->GetSvgPrecision(), aPlotOpts->GetSvgUseInch() );
978 
979  aPlotter->SetCreator( wxT( "PCBNEW" ) );
980  aPlotter->SetColorMode( false ); // default is plot in Black and White.
981  aPlotter->SetTextMode( aPlotOpts->GetTextMode() );
982 }
983 
984 
988 static void FillNegativeKnockout( PLOTTER *aPlotter, const EDA_RECT &aBbbox )
989 {
990  const int margin = 5 * IU_PER_MM; // Add a 5 mm margin around the board
991  aPlotter->SetNegative( true );
992  aPlotter->SetColor( WHITE ); // Which will be plotted as black
993  EDA_RECT area = aBbbox;
994  area.Inflate( margin );
995  aPlotter->Rect( area.GetOrigin(), area.GetEnd(), FILL_TYPE::FILLED_SHAPE );
996  aPlotter->SetColor( BLACK );
997 }
998 
999 
1003 static void ConfigureHPGLPenSizes( HPGL_PLOTTER *aPlotter, PCB_PLOT_PARAMS *aPlotOpts )
1004 {
1005  // Compute penDiam (the value is given in mils) in pcb units, with plot scale (if Scale is 2,
1006  // penDiam value is always m_HPGLPenDiam so apparent penDiam is actually penDiam / Scale
1007  int penDiam = KiROUND( aPlotOpts->GetHPGLPenDiameter() * IU_PER_MILS / aPlotOpts->GetScale() );
1008 
1009  // Set HPGL-specific options and start
1010  aPlotter->SetPenSpeed( aPlotOpts->GetHPGLPenSpeed() );
1011  aPlotter->SetPenNumber( aPlotOpts->GetHPGLPenNum() );
1012  aPlotter->SetPenDiameter( penDiam );
1013 }
1014 
1015 
1021 PLOTTER* StartPlotBoard( BOARD *aBoard, PCB_PLOT_PARAMS *aPlotOpts, int aLayer,
1022  const wxString& aFullFileName, const wxString& aSheetDesc )
1023 {
1024  // Create the plotter driver and set the few plotter specific options
1025  PLOTTER* plotter = NULL;
1026 
1027  switch( aPlotOpts->GetFormat() )
1028  {
1029  case PLOT_FORMAT::DXF:
1030  DXF_PLOTTER* DXF_plotter;
1031  DXF_plotter = new DXF_PLOTTER();
1032  DXF_plotter->SetUnits( aPlotOpts->GetDXFPlotUnits() );
1033 
1034  plotter = DXF_plotter;
1035  break;
1036 
1037  case PLOT_FORMAT::POST:
1038  PS_PLOTTER* PS_plotter;
1039  PS_plotter = new PS_PLOTTER();
1040  PS_plotter->SetScaleAdjust( aPlotOpts->GetFineScaleAdjustX(),
1041  aPlotOpts->GetFineScaleAdjustY() );
1042  plotter = PS_plotter;
1043  break;
1044 
1045  case PLOT_FORMAT::PDF:
1046  plotter = new PDF_PLOTTER();
1047  break;
1048 
1049  case PLOT_FORMAT::HPGL:
1050  HPGL_PLOTTER* HPGL_plotter;
1051  HPGL_plotter = new HPGL_PLOTTER();
1052 
1053  // HPGL options are a little more convoluted to compute, so they get their own function
1054  ConfigureHPGLPenSizes( HPGL_plotter, aPlotOpts );
1055  plotter = HPGL_plotter;
1056  break;
1057 
1058  case PLOT_FORMAT::GERBER:
1059  plotter = new GERBER_PLOTTER();
1060  break;
1061 
1062  case PLOT_FORMAT::SVG:
1063  plotter = new SVG_PLOTTER();
1064  break;
1065 
1066  default:
1067  wxASSERT( false );
1068  return NULL;
1069  }
1070 
1072  renderSettings->LoadColors( aPlotOpts->ColorSettings() );
1073  renderSettings->SetDefaultPenWidth( Millimeter2iu( 0.0212 ) ); // Hairline at 1200dpi
1074  plotter->SetRenderSettings( renderSettings );
1075 
1076  // Compute the viewport and set the other options
1077 
1078  // page layout is not mirrored, so temporarily change mirror option for the page layout
1079  PCB_PLOT_PARAMS plotOpts = *aPlotOpts;
1080 
1081  if( plotOpts.GetPlotFrameRef() && plotOpts.GetMirror() )
1082  plotOpts.SetMirror( false );
1083 
1084  initializePlotter( plotter, aBoard, &plotOpts );
1085 
1086  if( plotter->OpenFile( aFullFileName ) )
1087  {
1088  plotter->ClearHeaderLinesList();
1089 
1090  // For the Gerber "file function" attribute, set the layer number
1091  if( plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
1092  {
1093  bool useX2mode = plotOpts.GetUseGerberX2format();
1094 
1095  GERBER_PLOTTER* gbrplotter = static_cast <GERBER_PLOTTER*> ( plotter );
1096  gbrplotter->DisableApertMacros( plotOpts.GetDisableGerberMacros() );
1097  gbrplotter->UseX2format( useX2mode );
1098  gbrplotter->UseX2NetAttributes( plotOpts.GetIncludeGerberNetlistInfo() );
1099 
1100  // Attributes can be added using X2 format or as comment (X1 format)
1101  AddGerberX2Attribute( plotter, aBoard, aLayer, not useX2mode );
1102  }
1103 
1104  plotter->StartPlot();
1105 
1106  // Plot the frame reference if requested
1107  if( aPlotOpts->GetPlotFrameRef() )
1108  {
1109  PlotWorkSheet( plotter, aBoard->GetProject(), aBoard->GetTitleBlock(),
1110  aBoard->GetPageSettings(), "1", 1, aSheetDesc, aBoard->GetFileName() );
1111 
1112  if( aPlotOpts->GetMirror() )
1113  initializePlotter( plotter, aBoard, aPlotOpts );
1114  }
1115 
1116  // When plotting a negative board: draw a black rectangle (background for plot board
1117  // in white) and switch the current color to WHITE; note the color inversion is actually
1118  // done in the driver (if supported)
1119  if( aPlotOpts->GetNegative() )
1120  {
1121  EDA_RECT bbox = aBoard->ComputeBoundingBox();
1122  FillNegativeKnockout( plotter, bbox );
1123  }
1124 
1125  return plotter;
1126  }
1127 
1128  delete plotter->RenderSettings();
1129  delete plotter;
1130  return NULL;
1131 }
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:749
OUTLINE_MODE GetPlotMode() const
a class to handle special data (items attributes) during plot.
void PlotFootprintGraphicItems(MODULE *aModule)
#define SMALL_DRILL
Definition: pcbplot.h:60
OUTLINE_MODE
Definition: outline_mode.h:24
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:61
virtual wxPoint GetCenter() const override
Function GetCenter()
Definition: class_track.h:312
const POLYGON & CPolygon(int aIndex) const
const PAGE_INFO & GetPageSettings() const
Definition: class_board.h:573
virtual void SetCreator(const wxString &aCreator)
Definition: plotter.h:182
virtual void LoadColors(const COLOR_SETTINGS *aSettings) override
Definition: pcb_painter.cpp:87
int OutlineCount() const
Returns the number of outlines in the set
void UseX2NetAttributes(bool aEnable)
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:499
bool GetPlotFrameRef() const
virtual LSET GetLayerSet() const override
Function GetLayerSet returns a std::bitset of all layers on which the item physically resides.
bool GetDXFPlotPolygonMode() const
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
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
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.
virtual void Rect(const wxPoint &p1, const wxPoint &p2, FILL_TYPE fill, int width=USE_DEFAULT_LINE_WIDTH)=0
const wxPoint & GetStart() const
Definition: class_track.h:116
static constexpr double IU_PER_MM
Mock up a conversion function.
virtual bool OpenFile(const wxString &aFullFilename)
Open or create the plot file aFullFilename.
Definition: plotter.cpp:76
void SetNetAttribType(int aNetAttribType)
Definition: gbr_metadata.h:170
virtual void SetColorMode(bool aColorMode)
Plot in B/W or color.
Definition: plotter.h:161
bool GetDisableGerberMacros() const
void SetScaleAdjust(double scaleX, double scaleY)
Set the 'fine' scaling for the postscript engine.
virtual void SetLayerPolarity(bool aPositive)
Set the current Gerber layer polarity to positive or negative by writing %LPD*% or %LPC*% to the Gerb...
Definition: plotter.h:459
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:60
bool IsEmpty() const
Returns true if the set is empty (no polygons at all)
void SetRenderSettings(RENDER_SETTINGS *aSettings)
Definition: plotter.h:164
PROJECT * GetProject() const
Definition: class_board.h:397
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:490
class ARC, an arc track segment on a copper layer
Definition: typeinfo.h:98
void UseX2format(bool aEnable)
wxString GetNetname() const
Function GetNetname.
virtual void PlotPoly(const std::vector< wxPoint > &aCornerList, FILL_TYPE aFill, int aWidth=USE_DEFAULT_LINE_WIDTH, void *aData=NULL)=0
Draw a polygon ( filled or not )
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: class_board.h:558
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:94
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:351
void SetUnits(DXF_UNITS aUnit)
Set the units to use for plotting the DXF file.
Definition: color4d.h:45
void SetDrillMarksType(DrillMarksType aVal)
void Inflate(int aAmount, int aCircleSegmentsCount, CORNER_STRATEGY aCornerStrategy=ROUND_ALL_CORNERS)
Performs outline inflation/deflation.
like PAD_PTH, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:85
int PointCount() const
Function PointCount()
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:410
const wxString & GetFileName() const
Definition: class_board.h:279
double GetScale() const
void PlotFilledAreas(ZONE_CONTAINER *aZone, SHAPE_POLY_SET &aPolysList)
bool GetUseGerberX2format() const
virtual void ThickSegment(const wxPoint &start, const wxPoint &end, int width, OUTLINE_MODE tracemode, void *aData)
Definition: plotter.cpp:506
PAD_SHAPE_T
Enum PAD_SHAPE_T is the set of pad shapes, used with D_PAD::{Set,Get}Shape()
Definition: pad_shapes.h:33
virtual void SetGerberCoordinatesFormat(int aResolution, bool aUseInches=false)
Definition: plotter.h:473
virtual void SetSvgCoordinatesFormat(unsigned aResolution, bool aUseInches=false)
Definition: plotter.h:478
A single base class (TRACK) represents both tracks and vias, with subclasses for curved tracks (ARC) ...
const SEG & GetSeg() const
bool GetMirror() const
void TransformShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, PCB_LAYER_ID aLayer, int aClearanceValue, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Function TransformShapeWithClearanceToPolygon Convert the track shape to a closed polygon Used in fil...
Classes used in Pcbnew, CvPcb and GerbView.
void DeletePolygon(int aIdx)
Deletes aIdx-th polygon from the set
Board plot function definition file.
static void PlotSolderMaskLayer(BOARD *aBoard, PLOTTER *aPlotter, LSET aLayerMask, const PCB_PLOT_PARAMS &aPlotOpt, int aMinThickness)
void PlotFootprintTextItems(MODULE *aModule)
PCB_RENDER_SETTINGS Stores PCB specific render settings.
Definition: pcb_painter.h:64
DIMENSION class definition.
const VECTOR2I & CPoint(int aIndex) const
Function Point()
const wxPoint GetEnd() const
Definition: eda_rect.h:116
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
LSET is a set of PCB_LAYER_IDs.
PLOT_FORMAT GetFormat() const
void SetLayerSet(LSET aLayerMask)
Definition: pcbplot.h:92
#define NULL
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:284
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.
SHAPE_POLY_SET.
unsigned GetSvgPrecision() const
bool FlashLayer(int aLayer) const
Checks to see whether the via should have a pad on the specific layer.
const wxPoint GetOrigin() const
Definition: eda_rect.h:114
virtual PLOT_FORMAT GetPlotterType() const =0
Returns the effective plot engine in use.
PAGE_INFO describes the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:54
void PlotBoardGraphicItems()
plot items like text and graphics, but not tracks and footprints
COLOR4D GetColor() const
void PlotPad(D_PAD *aPad, COLOR4D aColor, OUTLINE_MODE aPlotMode)
Plot a pad.
virtual void SetPenSpeed(int speed)
Definition: plotter_hpgl.h:63
bool GetIncludeGerberNetlistInfo() const
virtual void SetTextMode(PLOT_TEXT_MODE mode)
Change the current text mode.
Definition: plotter.h:468
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:234
PLOT_TEXT_MODE GetTextMode() const
void ConvertBrdLayerToPolygonalContours(PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aOutlines)
Build a set of polygons which are the outlines of copper items (pads, tracks, vias,...
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.
double GetRadius() const
bool GetAutoScale() const
PCB_PLOT_PARAMS handles plot parameters and options when plotting/printing a board.
virtual void Circle(const wxPoint &pos, int diametre, FILL_TYPE fill, int width=USE_DEFAULT_LINE_WIDTH)=0
int HoleCount(int aOutline) const
Returns the number of holes in a given outline
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:152
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...
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:121
Definition: color4d.h:49
int GetHPGLPenNum() const
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, wxString *aErrorText=nullptr, std::vector< wxPoint > *aDiscontinuities=nullptr, std::vector< wxPoint > *aIntersections=nullptr)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index
double GetAngle() const
void DisableApertMacros(bool aDisable)
Disable Aperture Macro (AM) command, only for broken Gerber Readers Regions will be used instead of A...
void SetNetName(const wxString &aNetname)
Definition: gbr_metadata.h:180
Base plotter engine class.
Definition: plotter.h:131
COLOR4D GetColor(int aLayer) const
bool GetSketchPadsOnFabLayers() const
NETINFO_ITEM handles the data for a net.
Definition: netinfo.h:65
RENDER_SETTINGS * RenderSettings()
Definition: plotter.h:165
ZONE_CONTAINERS & Zones()
Definition: class_board.h:290
bool GetPlotViaOnMaskLayer() const
const int scale
smd pads, front layer
TITLE_BLOCK & GetTitleBlock()
Definition: class_board.h:579
int GetWidth() const
Definition: class_track.h:110
Meta control for all vias opacity/visibility.
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
Information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:186
bool GetSubtractMaskFromSilk() const
SHAPE_LINE_CHAIN.
When creating polygons to create a clearance polygonal area, the polygon must be same or bigger than ...
void PlotFootprintGraphicItem(FP_SHAPE *aShape)
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
virtual void SetPenNumber(int number)
Definition: plotter_hpgl.h:68
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
double GetHPGLPenDiameter() const
VECTOR2I A
Definition: seg.h:47
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
VIATYPE GetViaType() const
Definition: class_track.h:384
#define IU_PER_MILS
Definition: plotter.cpp:137
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
void InflateWithLinkedHoles(int aFactor, int aCircleSegmentsCount, POLYGON_MODE aFastMode)
Performs outline inflation/deflation, using round corners.
wxPoint Centre() const
Definition: eda_rect.h:62
void ClearHeaderLinesList()
Remove all lines from the list of free lines to print at the beginning of the file.
Definition: plotter.h:204
virtual void ThickArc(const wxPoint &centre, double StAngle, double EndAngle, int rayon, int width, OUTLINE_MODE tracemode, void *aData)
Definition: plotter.cpp:530
EDA_RECT ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
double GetFineScaleAdjustY() const
PCB_TARGET class definition.
void SetApertureAttrib(GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB aApertAttribute)
Definition: gbr_metadata.h:160
COLOR_SETTINGS * ColorSettings() const
DXF_UNITS GetDXFPlotUnits() const
double GetArcAngleStart() const
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
bool GetSvgUseInch() const
void PlotWorkSheet(PLOTTER *plotter, const PROJECT *aProject, const TITLE_BLOCK &aTitleBlock, const PAGE_INFO &aPageInfo, const wxString &aSheetNumber, int aNumberOfSheets, const wxString &aSheetDesc, const wxString &aFilename, COLOR4D aColor, bool aIsFirstPage)
int getFineWidthAdj()
Definition: pcbplot.h:83
GBR_NETLIST_METADATA m_NetlistMetadata
a item to handle object attribute:
Definition: gbr_metadata.h:212
bool GetNegative() const
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset difference For aFastMode meaning, see function booleanOp
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Function IsOnLayer tests to see if this object is on the given layer.
bool GetUseAuxOrigin() const
void SetDefaultPenWidth(int aWidth)
wxPoint GetPosition() const override
Definition: class_track.h:423
void SetMinThickness(int aMinThickness)
Definition: class_zone.h:225
DrillMarksType GetDrillMarksType() const
int GetWidth() const
static constexpr int Millimeter2iu(double mm)
print info associated to a net (TO.N attribute)
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
wxPoint m_AuxOrigin
origin for plot exports
COLOR4D getColor(LAYER_NUM aLayer)
Function getColor.
TRACKS & Tracks()
Definition: class_board.h:281
bool GetExcludeEdgeLayer() const
virtual void FlashPadCircle(const wxPoint &aPadPos, int aDiameter, OUTLINE_MODE aTraceMode, void *aData)=0
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
Definition: eda_rect.cpp:363
const wxSize GetSize() const
Definition: eda_rect.h:103
virtual void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: plotter.h:167
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:100
VECTOR2I B
Definition: seg.h:48