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