KiCad PCB EDA Suite
Loading...
Searching...
No Matches
plot_board_layers.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
31#include <wx/log.h>
32#include <eda_item.h>
33#include <layer_ids.h>
36#include <pcb_base_frame.h>
37#include <math/util.h> // for KiROUND
38#include <board.h>
39#include <footprint.h>
40#include <pcb_track.h>
41#include <pad.h>
42#include <zone.h>
43#include <pcb_shape.h>
44#include <pcb_target.h>
45#include <pcb_dimension.h>
46#include <pcbplot.h>
51#include <pcb_painter.h>
52#include <gbr_metadata.h>
53#include <advanced_config.h>
54
55/*
56 * Plot a solder mask layer. Solder mask layers have a minimum thickness value and cannot be
57 * drawn like standard layers, unless the minimum thickness is 0.
58 */
59static void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
60 const PCB_PLOT_PARAMS& aPlotOpt, int aMinThickness );
61
62
63void PlotBoardLayers( BOARD* aBoard, PLOTTER* aPlotter, const LSEQ& aLayers,
64 const PCB_PLOT_PARAMS& aPlotOptions )
65{
66 wxCHECK( aBoard && aPlotter && aLayers.size(), /* void */ );
67
68 for( LSEQ seq = aLayers; seq; ++seq )
69 PlotOneBoardLayer( aBoard, aPlotter, *seq, aPlotOptions );
70}
71
72
73void PlotInteractiveLayer( BOARD* aBoard, PLOTTER* aPlotter, const PCB_PLOT_PARAMS& aPlotOpt )
74{
75 for( const FOOTPRINT* fp : aBoard->Footprints() )
76 {
77 if( fp->GetLayer() == F_Cu && !aPlotOpt.m_PDFFrontFPPropertyPopups )
78 continue;
79
80 if( fp->GetLayer() == B_Cu && !aPlotOpt.m_PDFBackFPPropertyPopups )
81 continue;
82
83 std::vector<wxString> properties;
84
85 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
86 _( "Reference designator" ),
87 fp->Reference().GetShownText( false ) ) );
88
89 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
90 _( "Value" ),
91 fp->Value().GetShownText( false ) ) );
92
93 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
94 _( "Footprint" ),
95 fp->GetFPID().GetUniStringLibItemName() ) );
96
97 for( int i = 0; i < fp->GetFieldCount(); i++ )
98 {
99 PCB_FIELD* field = fp->GetFields().at( i );
100
101 if( field->IsReference() || field->IsValue() || field->IsFootprint() )
102 continue;
103
104 if( field->GetText().IsEmpty() )
105 continue;
106
107 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
108 field->GetName(),
109 field->GetText() ) );
110 }
111
112 // These 2 properties are not very useful in a plot file (like a PDF)
113#if 0
114 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), _( "Library Description" ),
115 fp->GetLibDescription() ) );
116
117 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
118 _( "Keywords" ),
119 fp->GetKeywords() ) );
120#endif
121 // Draw items are plotted with a position offset. So we need to move
122 // our boxes (which are not plotted) by the same offset.
123 VECTOR2I offset = -aPlotter->GetPlotOffsetUserUnits();
124
125 // Use a footprint bbox without texts to create the hyperlink area
126 BOX2I bbox = fp->GetBoundingBox( false, false );
127 bbox.Move( offset );
128 aPlotter->HyperlinkMenu( bbox, properties );
129
130 // Use a footprint bbox with visible texts only to create the bookmark area
131 // which is the area to zoom on ft selection
132 // However the bbox need to be inflated for a better look.
133 bbox = fp->GetBoundingBox( true, false );
134 bbox.Move( offset );
135 bbox.Inflate( bbox.GetWidth() /2, bbox.GetHeight() /2 );
136 aPlotter->Bookmark( bbox, fp->GetReference(), _( "Footprints" ) );
137 }
138}
139
140
141void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
142 const PCB_PLOT_PARAMS& aPlotOpt )
143{
144 PCB_PLOT_PARAMS plotOpt = aPlotOpt;
145 int soldermask_min_thickness = aBoard->GetDesignSettings().m_SolderMaskMinWidth;
146
147 // Set a default color and the text mode for this layer
148 aPlotter->SetColor( BLACK );
149 aPlotter->SetTextMode( aPlotOpt.GetTextMode() );
150
151 // Specify that the contents of the "Edges Pcb" layer are to be plotted in addition to the
152 // contents of the currently specified layer.
153 LSET layer_mask( aLayer );
154
155 if( IsCopperLayer( aLayer ) )
156 {
157 // Skip NPTH pads on copper layers ( only if hole size == pad size ):
158 // Drill mark will be plotted if drill mark is SMALL_DRILL_SHAPE or FULL_DRILL_SHAPE
159 if( plotOpt.GetFormat() == PLOT_FORMAT::DXF )
160 {
161 plotOpt.SetSkipPlotNPTH_Pads( false );
162 PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
163 }
164 else
165 {
166 plotOpt.SetSkipPlotNPTH_Pads( true );
167 PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
168 }
169 }
170 else
171 {
172 switch( aLayer )
173 {
174 case B_Mask:
175 case F_Mask:
176 plotOpt.SetSkipPlotNPTH_Pads( false );
177
178 // Disable plot pad holes
180
181 // Plot solder mask:
182 if( soldermask_min_thickness == 0 )
183 {
184 if( plotOpt.GetFormat() == PLOT_FORMAT::DXF )
185 PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
186 else
187 PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
188 }
189 else
190 {
191 PlotSolderMaskLayer( aBoard, aPlotter, layer_mask, plotOpt,
192 soldermask_min_thickness );
193 }
194
195 break;
196
197 case B_Adhes:
198 case F_Adhes:
199 case B_Paste:
200 case F_Paste:
201 plotOpt.SetSkipPlotNPTH_Pads( false );
202
203 // Disable plot pad holes
205
206 if( plotOpt.GetFormat() == PLOT_FORMAT::DXF )
207 PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
208 else
209 PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
210
211 break;
212
213 case F_SilkS:
214 case B_SilkS:
215 if( plotOpt.GetFormat() == PLOT_FORMAT::DXF && plotOpt.GetDXFPlotPolygonMode() )
216 // PlotLayerOutlines() is designed only for DXF plotters.
217 // and must not be used for other plot formats
218 PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
219 else
220 PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
221
222 // Gerber: Subtract soldermask from silkscreen if enabled
223 if( aPlotter->GetPlotterType() == PLOT_FORMAT::GERBER
224 && plotOpt.GetSubtractMaskFromSilk() )
225 {
226 if( aLayer == F_SilkS )
227 layer_mask = LSET( F_Mask );
228 else
229 layer_mask = LSET( B_Mask );
230
231 // Create the mask to subtract by creating a negative layer polarity
232 aPlotter->SetLayerPolarity( false );
233
234 // Disable plot pad holes
236
237 // Plot the mask
238 PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
239
240 // Disable the negative polarity
241 aPlotter->SetLayerPolarity( true );
242 }
243
244 break;
245
246 // These layers are plotted like silk screen layers.
247 // Mainly, pads on these layers are not filled.
248 // This is not necessary the best choice.
249 case Dwgs_User:
250 case Cmts_User:
251 case Eco1_User:
252 case Eco2_User:
253 case Edge_Cuts:
254 case Margin:
255 case F_CrtYd:
256 case B_CrtYd:
257 case F_Fab:
258 case B_Fab:
259 plotOpt.SetSkipPlotNPTH_Pads( false );
261
262 if( plotOpt.GetFormat() == PLOT_FORMAT::DXF && plotOpt.GetDXFPlotPolygonMode() )
263 // PlotLayerOutlines() is designed only for DXF plotters.
264 // and must not be used for other plot formats
265 PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
266 else
267 PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
268
269 break;
270
271 default:
272 plotOpt.SetSkipPlotNPTH_Pads( false );
274
275 if( plotOpt.GetFormat() == PLOT_FORMAT::DXF && plotOpt.GetDXFPlotPolygonMode() )
276 // PlotLayerOutlines() is designed only for DXF plotters.
277 // and must not be used for other plot formats
278 PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
279 else
280 PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
281
282 break;
283 }
284 }
285}
286
287
293void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
294 const PCB_PLOT_PARAMS& aPlotOpt )
295{
296 BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
297 int maxError = aBoard->GetDesignSettings().m_MaxError;
298
299 itemplotter.SetLayerSet( aLayerMask );
300
301 OUTLINE_MODE plotMode = aPlotOpt.GetPlotMode();
302 bool onCopperLayer = ( LSET::AllCuMask() & aLayerMask ).any();
303 bool onSolderMaskLayer = ( LSET( 2, F_Mask, B_Mask ) & aLayerMask ).any();
304 bool onSolderPasteLayer = ( LSET( 2, F_Paste, B_Paste ) & aLayerMask ).any();
305 bool onFrontFab = ( LSET( F_Fab ) & aLayerMask ).any();
306 bool onBackFab = ( LSET( B_Fab ) & aLayerMask ).any();
307 bool sketchPads = ( onFrontFab || onBackFab ) && aPlotOpt.GetSketchPadsOnFabLayers();
308
309 // Plot edge layer and graphic items
310 for( const BOARD_ITEM* item : aBoard->Drawings() )
311 itemplotter.PlotBoardGraphicItem( item );
312
313 // Draw footprint texts:
314 for( const FOOTPRINT* footprint : aBoard->Footprints() )
315 itemplotter.PlotFootprintTextItems( footprint );
316
317 // Draw footprint other graphic items:
318 for( const FOOTPRINT* footprint : aBoard->Footprints() )
319 itemplotter.PlotFootprintGraphicItems( footprint );
320
321 // Plot footprint pads
322 for( FOOTPRINT* footprint : aBoard->Footprints() )
323 {
324 aPlotter->StartBlock( nullptr );
325
326 for( PAD* pad : footprint->Pads() )
327 {
328 OUTLINE_MODE padPlotMode = plotMode;
329
330 if( !( pad->GetLayerSet() & aLayerMask ).any() )
331 {
332 if( sketchPads &&
333 ( ( onFrontFab && pad->GetLayerSet().Contains( F_Cu ) ) ||
334 ( onBackFab && pad->GetLayerSet().Contains( B_Cu ) ) ) )
335 {
336 padPlotMode = SKETCH;
337 }
338 else
339 {
340 continue;
341 }
342 }
343
344 if( onCopperLayer && !pad->IsOnCopperLayer() )
345 continue;
346
348 if( onCopperLayer && !pad->FlashLayer( aLayerMask ) )
349 continue;
350
352
353 // If we're plotting a single layer, the color for that layer can be used directly.
354 if( aLayerMask.count() == 1 )
355 {
356 color = aPlotOpt.ColorSettings()->GetColor( aLayerMask.Seq()[0] );
357 }
358 else
359 {
360 if( ( pad->GetLayerSet() & aLayerMask )[B_Cu] )
361 color = aPlotOpt.ColorSettings()->GetColor( B_Cu );
362
363 if( ( pad->GetLayerSet() & aLayerMask )[F_Cu] )
364 color = color.LegacyMix( aPlotOpt.ColorSettings()->GetColor( F_Cu ) );
365
366 if( sketchPads && aLayerMask[F_Fab] )
367 color = aPlotOpt.ColorSettings()->GetColor( F_Fab );
368 else if( sketchPads && aLayerMask[B_Fab] )
369 color = aPlotOpt.ColorSettings()->GetColor( B_Fab );
370 }
371
372 VECTOR2I margin;
373 int width_adj = 0;
374
375 if( onCopperLayer )
376 width_adj = itemplotter.getFineWidthAdj();
377
378 if( onSolderMaskLayer )
379 margin.x = margin.y = pad->GetSolderMaskExpansion();
380
381 if( onSolderPasteLayer )
382 margin = pad->GetSolderPasteMargin();
383
384 // not all shapes can have a different margin for x and y axis
385 // in fact only oval and rect shapes can have different values.
386 // Round shape have always the same x,y margin
387 // so define a unique value for other shapes that do not support different values
388 int mask_clearance = margin.x;
389
390 // Now offset the pad size by margin + width_adj
391 VECTOR2I padPlotsSize = pad->GetSize() + margin * 2 + VECTOR2I( width_adj, width_adj );
392
393 // Store these parameters that can be modified to plot inflated/deflated pads shape
394 PAD_SHAPE padShape = pad->GetShape();
395 VECTOR2I padSize = pad->GetSize();
396 VECTOR2I padDelta = pad->GetDelta(); // has meaning only for trapezoidal pads
397 // CornerRadius and CornerRadiusRatio can be modified
398 // the radius is built from the ratio, so saving/restoring the ratio is enough
399 double padCornerRadiusRatio = pad->GetRoundRectRadiusRatio();
400
401 // Don't draw a 0 sized pad.
402 // Note: a custom pad can have its pad anchor with size = 0
403 if( pad->GetShape() != PAD_SHAPE::CUSTOM
404 && ( padPlotsSize.x <= 0 || padPlotsSize.y <= 0 ) )
405 {
406 continue;
407 }
408
409 switch( pad->GetShape() )
410 {
412 case PAD_SHAPE::OVAL:
413 pad->SetSize( padPlotsSize );
414
415 if( aPlotOpt.GetSkipPlotNPTH_Pads() &&
417 ( pad->GetSize() == pad->GetDrillSize() ) &&
418 ( pad->GetAttribute() == PAD_ATTRIB::NPTH ) )
419 {
420 break;
421 }
422
423 itemplotter.PlotPad( pad, color, padPlotMode );
424 break;
425
427 pad->SetSize( padPlotsSize );
428
429 if( mask_clearance > 0 )
430 {
431 pad->SetShape( PAD_SHAPE::ROUNDRECT );
432 pad->SetRoundRectCornerRadius( mask_clearance );
433 }
434
435 itemplotter.PlotPad( pad, color, padPlotMode );
436 break;
437
439 // inflate/deflate a trapezoid is a bit complex.
440 // so if the margin is not null, build a similar polygonal pad shape,
441 // and inflate/deflate the polygonal shape
442 // because inflating/deflating using different values for y and y
443 // we are using only margin.x as inflate/deflate value
444 if( mask_clearance == 0 )
445 {
446 itemplotter.PlotPad( pad, color, padPlotMode );
447 }
448 else
449 {
450 PAD dummy( *pad );
451 dummy.SetAnchorPadShape( PAD_SHAPE::CIRCLE );
452 dummy.SetShape( PAD_SHAPE::CUSTOM );
453 SHAPE_POLY_SET outline;
454 outline.NewOutline();
455 int dx = padSize.x / 2;
456 int dy = padSize.y / 2;
457 int ddx = padDelta.x / 2;
458 int ddy = padDelta.y / 2;
459
460 outline.Append( -dx - ddy, dy + ddx );
461 outline.Append( dx + ddy, dy - ddx );
462 outline.Append( dx - ddy, -dy + ddx );
463 outline.Append( -dx + ddy, -dy - ddx );
464
465 // Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
466 // which can create bad shapes if margin.x is < 0
467 outline.InflateWithLinkedHoles( mask_clearance,
470 dummy.DeletePrimitivesList();
471 dummy.AddPrimitivePoly( outline, 0, true );
472
473 // Be sure the anchor pad is not bigger than the deflated shape because this
474 // anchor will be added to the pad shape when plotting the pad. So now the
475 // polygonal shape is built, we can clamp the anchor size
476 dummy.SetSize( VECTOR2I( 0, 0 ) );
477
478 itemplotter.PlotPad( &dummy, color, padPlotMode );
479 }
480
481 break;
482
484 {
485 // rounding is stored as a percent, but we have to update this ratio
486 // to force recalculation of other values after size changing (we do not
487 // really change the rounding percent value)
488 double radius_ratio = pad->GetRoundRectRadiusRatio();
489 pad->SetSize( padPlotsSize );
490 pad->SetRoundRectRadiusRatio( radius_ratio );
491
492 itemplotter.PlotPad( pad, color, padPlotMode );
493 break;
494 }
495
497 if( mask_clearance == 0 )
498 {
499 // the size can be slightly inflated by width_adj (PS/PDF only)
500 pad->SetSize( padPlotsSize );
501 itemplotter.PlotPad( pad, color, padPlotMode );
502 }
503 else
504 {
505 // Due to the polygonal shape of a CHAMFERED_RECT pad, the best way is to
506 // convert the pad shape to a full polygon, inflate/deflate the polygon
507 // and use a dummy CUSTOM pad to plot the final shape.
508 PAD dummy( *pad );
509 // Build the dummy pad outline with coordinates relative to the pad position
510 // pad offset and orientation 0. The actual pos, offset and rotation will be
511 // taken in account later by the plot function
512 dummy.SetPosition( VECTOR2I( 0, 0 ) );
513 dummy.SetOffset( VECTOR2I( 0, 0 ) );
514 dummy.SetOrientation( ANGLE_0 );
515 SHAPE_POLY_SET outline;
516 dummy.TransformShapeToPolygon( outline, UNDEFINED_LAYER, 0, maxError,
517 ERROR_INSIDE );
518 outline.InflateWithLinkedHoles( mask_clearance,
521
522 // Initialize the dummy pad shape:
523 dummy.SetAnchorPadShape( PAD_SHAPE::CIRCLE );
524 dummy.SetShape( PAD_SHAPE::CUSTOM );
525 dummy.DeletePrimitivesList();
526 dummy.AddPrimitivePoly( outline, 0, true );
527
528 // Be sure the anchor pad is not bigger than the deflated shape because this
529 // anchor will be added to the pad shape when plotting the pad.
530 // So we set the anchor size to 0
531 dummy.SetSize( VECTOR2I( 0, 0 ) );
532 // Restore pad position and offset
533 dummy.SetPosition( pad->GetPosition() );
534 dummy.SetOffset( pad->GetOffset() );
535 dummy.SetOrientation( pad->GetOrientation() );
536
537 itemplotter.PlotPad( &dummy, color, padPlotMode );
538 }
539
540 break;
541
543 {
544 // inflate/deflate a custom shape is a bit complex.
545 // so build a similar pad shape, and inflate/deflate the polygonal shape
546 PAD dummy( *pad );
547 dummy.SetParentGroup( nullptr );
548
549 SHAPE_POLY_SET shape;
550 pad->MergePrimitivesAsPolygon( &shape );
551
552 // Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
553 // which can create bad shapes if margin.x is < 0
554 shape.InflateWithLinkedHoles( mask_clearance,
557 dummy.DeletePrimitivesList();
558 dummy.AddPrimitivePoly( shape, 0, true );
559
560 // Be sure the anchor pad is not bigger than the deflated shape because this
561 // anchor will be added to the pad shape when plotting the pad. So now the
562 // polygonal shape is built, we can clamp the anchor size
563 if( mask_clearance < 0 ) // we expect margin.x = margin.y for custom pads
564 dummy.SetSize( padPlotsSize );
565
566 itemplotter.PlotPad( &dummy, color, padPlotMode );
567 break;
568 }
569 }
570
571 // Restore the pad parameters modified by the plot code
572 pad->SetSize( padSize );
573 pad->SetDelta( padDelta );
574 pad->SetShape( padShape );
575 pad->SetRoundRectRadiusRatio( padCornerRadiusRatio );
576 }
577
578 aPlotter->EndBlock( nullptr );
579 }
580
581 // Plot vias on copper layers, and if aPlotOpt.GetPlotViaOnMaskLayer() is true,
582 // plot them on solder mask
583
584 GBR_METADATA gbr_metadata;
585
586 bool isOnCopperLayer = ( aLayerMask & LSET::AllCuMask() ).any();
587
588 if( isOnCopperLayer )
589 {
592 }
593
594 aPlotter->StartBlock( nullptr );
595
596 for( const PCB_TRACK* track : aBoard->Tracks() )
597 {
598 if( track->Type() != PCB_VIA_T )
599 continue;
600
601 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
602
603 // vias are not plotted if not on selected layer
604 LSET via_mask_layer = via->GetLayerSet();
605
606 if( !( via_mask_layer & aLayerMask ).any() )
607 continue;
608
609 int via_margin = 0;
610 double width_adj = 0;
611
612 if( aLayerMask[B_Mask] || aLayerMask[F_Mask] )
613 via_margin = via->GetSolderMaskExpansion();
614
615 if( ( aLayerMask & LSET::AllCuMask() ).any() )
616 width_adj = itemplotter.getFineWidthAdj();
617
618 int diameter = via->GetWidth() + 2 * via_margin + width_adj;
619
621 if( onCopperLayer && !via->FlashLayer( aLayerMask ) )
622 continue;
623
624 // Don't draw a null size item :
625 if( diameter <= 0 )
626 continue;
627
628 // Some vias can be not connected (no net).
629 // Set the m_NotInNet for these vias to force a empty net name in gerber file
630 gbr_metadata.m_NetlistMetadata.m_NotInNet = via->GetNetname().IsEmpty();
631
632 gbr_metadata.SetNetName( via->GetNetname() );
633
634 COLOR4D color = aPlotOpt.ColorSettings()->GetColor(
635 LAYER_VIAS + static_cast<int>( via->GetViaType() ) );
636
637 // Set plot color (change WHITE to LIGHTGRAY because the white items are not seen on a
638 // white paper or screen
639 aPlotter->SetColor( color != WHITE ? color : LIGHTGRAY );
640 aPlotter->FlashPadCircle( via->GetStart(), diameter, plotMode, &gbr_metadata );
641 }
642
643 aPlotter->EndBlock( nullptr );
644 aPlotter->StartBlock( nullptr );
646
647 // Plot tracks (not vias) :
648 for( const PCB_TRACK* track : aBoard->Tracks() )
649 {
650 if( track->Type() == PCB_VIA_T )
651 continue;
652
653 if( !aLayerMask[track->GetLayer()] )
654 continue;
655
656 // Some track segments can be not connected (no net).
657 // Set the m_NotInNet for these segments to force a empty net name in gerber file
658 gbr_metadata.m_NetlistMetadata.m_NotInNet = track->GetNetname().IsEmpty();
659
660 gbr_metadata.SetNetName( track->GetNetname() );
661 int width = track->GetWidth() + itemplotter.getFineWidthAdj();
662 aPlotter->SetColor( itemplotter.getColor( track->GetLayer() ) );
663
664 if( track->Type() == PCB_ARC_T )
665 {
666 const PCB_ARC* arc = static_cast<const PCB_ARC*>( track );
667
668 // Too small arcs cannot be really handled: arc center (and arc radius)
669 // cannot be safely computed
670 if( !arc->IsDegenerated( 10 /* in IU */ ) )
671 {
672 aPlotter->ThickArc( arc->GetCenter(), arc->GetArcAngleStart(), arc->GetAngle(),
673 arc->GetRadius(), width, plotMode, &gbr_metadata );
674 }
675 else
676 {
677 // Approximate this very small arc by a segment.
678 aPlotter->ThickSegment( track->GetStart(), track->GetEnd(), width, plotMode,
679 &gbr_metadata );
680 }
681 }
682 else
683 {
684 aPlotter->ThickSegment( track->GetStart(), track->GetEnd(), width, plotMode,
685 &gbr_metadata );
686 }
687 }
688
689 aPlotter->EndBlock( nullptr );
690
691 // Plot filled ares
692 aPlotter->StartBlock( nullptr );
693
694 NETINFO_ITEM nonet( aBoard );
695
696 for( const ZONE* zone : aBoard->Zones() )
697 {
698 for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
699 {
700 if( !aLayerMask[layer] )
701 continue;
702
703 SHAPE_POLY_SET mainArea = zone->GetFilledPolysList( layer )->CloneDropTriangulation();
704 SHAPE_POLY_SET islands;
705
706 for( int i = mainArea.OutlineCount() - 1; i >= 0; i-- )
707 {
708 if( zone->IsIsland( layer, i ) )
709 {
710 islands.AddOutline( mainArea.CPolygon( i )[0] );
711 mainArea.DeletePolygon( i );
712 }
713 }
714
715 itemplotter.PlotZone( zone, layer, mainArea );
716
717 if( !islands.IsEmpty() )
718 {
719 ZONE dummy( *zone );
720 dummy.SetNet( &nonet );
721 itemplotter.PlotZone( &dummy, layer, islands );
722 }
723 }
724 }
725
726 aPlotter->EndBlock( nullptr );
727
728 // Adding drill marks, if required and if the plotter is able to plot them:
730 itemplotter.PlotDrillMarks();
731}
732
733
737void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
738 const PCB_PLOT_PARAMS& aPlotOpt )
739{
740 BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
741 itemplotter.SetLayerSet( aLayerMask );
742
743 SHAPE_POLY_SET outlines;
744
745 for( LSEQ seq = aLayerMask.Seq( aLayerMask.SeqStackupForPlotting() ); seq; ++seq )
746 {
747 PCB_LAYER_ID layer = *seq;
748
749 outlines.RemoveAllContours();
750 aBoard->ConvertBrdLayerToPolygonalContours( layer, outlines );
751
753
754 // Plot outlines
755 std::vector<VECTOR2I> cornerList;
756
757 // Now we have one or more basic polygons: plot each polygon
758 for( int ii = 0; ii < outlines.OutlineCount(); ii++ )
759 {
760 for( int kk = 0; kk <= outlines.HoleCount(ii); kk++ )
761 {
762 cornerList.clear();
763 const SHAPE_LINE_CHAIN& path = ( kk == 0 ) ? outlines.COutline( ii )
764 : outlines.CHole( ii, kk - 1 );
765
766 aPlotter->PlotPoly( path, FILL_T::NO_FILL );
767 }
768 }
769
770 // Plot pad holes
772 {
773 int smallDrill = ( aPlotOpt.GetDrillMarksType() == DRILL_MARKS::SMALL_DRILL_SHAPE )
775 : INT_MAX;
776
777 for( FOOTPRINT* footprint : aBoard->Footprints() )
778 {
779 for( PAD* pad : footprint->Pads() )
780 {
781 if( pad->HasHole() )
782 {
783 std::shared_ptr<SHAPE_SEGMENT> slot = pad->GetEffectiveHoleShape();
784
785 if( slot->GetSeg().A == slot->GetSeg().B ) // circular hole
786 {
787 int drill = std::min( smallDrill, slot->GetWidth() );
788 aPlotter->Circle( pad->GetPosition(), drill, FILL_T::NO_FILL );
789 }
790 else
791 {
792 // Note: small drill marks have no significance when applied to slots
793 aPlotter->ThickSegment( slot->GetSeg().A, slot->GetSeg().B,
794 slot->GetWidth(), SKETCH, nullptr );
795 }
796 }
797 }
798 }
799 }
800
801 // Plot vias holes
802 for( PCB_TRACK* track : aBoard->Tracks() )
803 {
804 if( track->Type() != PCB_VIA_T )
805 continue;
806
807 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
808
809 if( via->IsOnLayer( layer ) ) // via holes can be not through holes
810 aPlotter->Circle( via->GetPosition(), via->GetDrillValue(), FILL_T::NO_FILL );
811 }
812 }
813}
814
815
833void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
834 const PCB_PLOT_PARAMS& aPlotOpt, int aMinThickness )
835{
836 int maxError = aBoard->GetDesignSettings().m_MaxError;
837 PCB_LAYER_ID layer = aLayerMask[B_Mask] ? B_Mask : F_Mask;
838 SHAPE_POLY_SET buffer;
839 SHAPE_POLY_SET* boardOutline = nullptr;
840
841 if( aBoard->GetBoardPolygonOutlines( buffer ) )
842 boardOutline = &buffer;
843
844 // We remove 1nm as we expand both sides of the shapes, so allowing for a strictly greater
845 // than or equal comparison in the shape separation (boolean add)
846 int inflate = aMinThickness / 2 - 1;
847
848 BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
849 itemplotter.SetLayerSet( aLayerMask );
850
851 // Build polygons for each pad shape. The size of the shape on solder mask should be size
852 // of pad + clearance around the pad, where clearance = solder mask clearance + extra margin.
853 // Extra margin is half the min width for solder mask, which is used to merge too-close shapes
854 // (distance < aMinThickness), and will be removed when creating the actual shapes.
855
856 // Will contain shapes inflated by inflate value that will be merged and deflated by inflate
857 // value to build final polygons
858 SHAPE_POLY_SET areas;
859
860 // Will contain exact shapes of all items on solder mask
861 SHAPE_POLY_SET initialPolys;
862
863 auto plotFPTextItem =
864 [&]( const PCB_TEXT& aText )
865 {
866 if( !itemplotter.GetPlotFPText() )
867 return;
868
869 if( !aText.IsVisible() && !itemplotter.GetPlotInvisibleText() )
870 return;
871
872 if( aText.GetText() == wxT( "${REFERENCE}" ) && !itemplotter.GetPlotReference() )
873 return;
874
875 if( aText.GetText() == wxT( "${VALUE}" ) && !itemplotter.GetPlotValue() )
876 return;
877
878 // add shapes with their exact mask layer size in initialPolys
879 aText.TransformTextToPolySet( initialPolys, 0, maxError, ERROR_OUTSIDE );
880
881 // add shapes inflated by aMinThickness/2 in areas
882 aText.TransformTextToPolySet( areas, inflate, maxError, ERROR_OUTSIDE );
883 };
884
885 // Generate polygons with arcs inside the shape or exact shape to minimize shape changes
886 // created by arc to segment size correction.
888 {
889 // Plot footprint pads and graphics
890 for( const FOOTPRINT* footprint : aBoard->Footprints() )
891 {
892 // add shapes with their exact mask layer size in initialPolys
893 footprint->TransformPadsToPolySet( initialPolys, layer, 0, maxError, ERROR_OUTSIDE );
894 // add shapes inflated by aMinThickness/2 in areas
895 footprint->TransformPadsToPolySet( areas, layer, inflate, maxError, ERROR_OUTSIDE );
896
897 for( const PCB_FIELD* field : footprint->Fields() )
898 {
899 if( field->IsReference() && !itemplotter.GetPlotReference() )
900 continue;
901
902 if( field->IsValue() && !itemplotter.GetPlotValue() )
903 continue;
904
905 if( field->IsOnLayer( layer ) )
906 plotFPTextItem( static_cast<const PCB_TEXT&>( *field ) );
907 }
908
909 for( const BOARD_ITEM* item : footprint->GraphicalItems() )
910 {
911 if( item->IsOnLayer( layer ) )
912 {
913 if( item->Type() == PCB_TEXT_T )
914 {
915 plotFPTextItem( static_cast<const PCB_TEXT&>( *item ) );
916 }
917 else
918 {
919 // add shapes with their exact mask layer size in initialPolys
920 item->TransformShapeToPolygon( initialPolys, layer, 0, maxError,
922
923 // add shapes inflated by aMinThickness/2 in areas
924 item->TransformShapeToPolygon( areas, layer, inflate, maxError,
926 }
927 }
928 }
929 }
930
931 // Plot (untented) vias
932 for( const PCB_TRACK* track : aBoard->Tracks() )
933 {
934 if( track->Type() != PCB_VIA_T )
935 continue;
936
937 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
938
939 // Note: IsOnLayer() checks relevant mask layers of untented vias
940 if( !via->IsOnLayer( layer ) )
941 continue;
942
943 int clearance = via->GetSolderMaskExpansion();
944
945 // add shapes with their exact mask layer size in initialPolys
946 via->TransformShapeToPolygon( initialPolys, layer, clearance, maxError, ERROR_OUTSIDE );
947
948 // add shapes inflated by aMinThickness/2 in areas
949 clearance += inflate;
950 via->TransformShapeToPolygon( areas, layer, clearance, maxError, ERROR_OUTSIDE );
951 }
952
953 // Add filled zone areas.
954#if 0 // Set to 1 if a solder mask expansion must be applied to zones on solder mask
955 int zone_margin = aBoard->GetDesignSettings().m_SolderMaskExpansion;
956#else
957 int zone_margin = 0;
958#endif
959
960 for( const BOARD_ITEM* item : aBoard->Drawings() )
961 {
962 if( item->IsOnLayer( layer ) )
963 {
964 if( item->Type() == PCB_TEXT_T )
965 {
966 const PCB_TEXT* text = static_cast<const PCB_TEXT*>( item );
967
968 // add shapes with their exact mask layer size in initialPolys
969 text->TransformTextToPolySet( initialPolys, 0, maxError, ERROR_OUTSIDE );
970
971 // add shapes inflated by aMinThickness/2 in areas
972 text->TransformTextToPolySet( areas, inflate, maxError, ERROR_OUTSIDE );
973 }
974 else
975 {
976 // add shapes with their exact mask layer size in initialPolys
977 item->TransformShapeToPolygon( initialPolys, layer, 0, maxError,
979
980 // add shapes inflated by aMinThickness/2 in areas
981 item->TransformShapeToPolygon( areas, layer, inflate, maxError,
983 }
984 }
985 }
986
987 for( ZONE* zone : aBoard->Zones() )
988 {
989 if( !zone->IsOnLayer( layer ) )
990 continue;
991
992 // add shapes inflated by aMinThickness/2 in areas
993 zone->TransformSmoothedOutlineToPolygon( areas, inflate + zone_margin, maxError,
994 ERROR_OUTSIDE, boardOutline );
995
996 // add shapes with their exact mask layer size in initialPolys
997 zone->TransformSmoothedOutlineToPolygon( initialPolys, zone_margin, maxError,
998 ERROR_OUTSIDE, boardOutline );
999 }
1000 }
1001
1002 // Merge all polygons: After deflating, not merged (not overlapping) polygons will have the
1003 // initial shape (with perhaps small changes due to deflating transform)
1005 areas.Deflate( inflate, CORNER_STRATEGY::CHAMFER_ALL_CORNERS, maxError );
1006
1007 // To avoid a lot of code, use a ZONE to handle and plot polygons, because our polygons look
1008 // exactly like filled areas in zones.
1009 // Note, also this code is not optimized: it creates a lot of copy/duplicate data.
1010 // However it is not complex, and fast enough for plot purposes (copy/convert data is only a
1011 // very small calculation time for these calculations).
1012 ZONE zone( aBoard );
1013 zone.SetMinThickness( 0 ); // trace polygons only
1014 zone.SetLayer( layer );
1015
1016 // Combine the current areas to initial areas. This is mandatory because inflate/deflate
1017 // transform is not perfect, and we want the initial areas perfectly kept
1018 areas.BooleanAdd( initialPolys, SHAPE_POLY_SET::PM_FAST );
1020
1021 itemplotter.PlotZone( &zone, layer, areas );
1022}
1023
1024
1031static void initializePlotter( PLOTTER* aPlotter, const BOARD* aBoard,
1032 const PCB_PLOT_PARAMS* aPlotOpts )
1033{
1034 PAGE_INFO pageA4( wxT( "A4" ) );
1035 const PAGE_INFO& pageInfo = aBoard->GetPageSettings();
1036 const PAGE_INFO* sheet_info;
1037 double paperscale; // Page-to-paper ratio
1038 VECTOR2I paperSizeIU;
1039 VECTOR2I pageSizeIU( pageInfo.GetSizeIU( pcbIUScale.IU_PER_MILS ) );
1040 bool autocenter = false;
1041
1042 // Special options: to fit the sheet to an A4 sheet replace the paper size. However there
1043 // is a difference between the autoscale and the a4paper option:
1044 // - Autoscale fits the board to the paper size
1045 // - A4paper fits the original paper size to an A4 sheet
1046 // - Both of them fit the board to an A4 sheet
1047 if( aPlotOpts->GetA4Output() )
1048 {
1049 sheet_info = &pageA4;
1050 paperSizeIU = pageA4.GetSizeIU( pcbIUScale.IU_PER_MILS );
1051 paperscale = (double) paperSizeIU.x / pageSizeIU.x;
1052 autocenter = true;
1053 }
1054 else
1055 {
1056 sheet_info = &pageInfo;
1057 paperSizeIU = pageSizeIU;
1058 paperscale = 1;
1059
1060 // Need autocentering only if scale is not 1:1
1061 autocenter = (aPlotOpts->GetScale() != 1.0);
1062 }
1063
1064 BOX2I bbox = aBoard->ComputeBoundingBox();
1065 VECTOR2I boardCenter = bbox.Centre();
1066 VECTOR2I boardSize = bbox.GetSize();
1067
1068 double compound_scale;
1069
1070 // Fit to 80% of the page if asked; it could be that the board is empty, in this case
1071 // regress to 1:1 scale
1072 if( aPlotOpts->GetAutoScale() && boardSize.x > 0 && boardSize.y > 0 )
1073 {
1074 double xscale = (paperSizeIU.x * 0.8) / boardSize.x;
1075 double yscale = (paperSizeIU.y * 0.8) / boardSize.y;
1076
1077 compound_scale = std::min( xscale, yscale ) * paperscale;
1078 }
1079 else
1080 {
1081 compound_scale = aPlotOpts->GetScale() * paperscale;
1082 }
1083
1084 // For the plot offset we have to keep in mind the auxiliary origin too: if autoscaling is
1085 // off we check that plot option (i.e. autoscaling overrides auxiliary origin)
1086 VECTOR2I offset( 0, 0);
1087
1088 if( autocenter )
1089 {
1090 offset.x = KiROUND( boardCenter.x - ( paperSizeIU.x / 2.0 ) / compound_scale );
1091 offset.y = KiROUND( boardCenter.y - ( paperSizeIU.y / 2.0 ) / compound_scale );
1092 }
1093 else
1094 {
1095 if( aPlotOpts->GetUseAuxOrigin() )
1096 offset = aBoard->GetDesignSettings().GetAuxOrigin();
1097 }
1098
1099 aPlotter->SetPageSettings( *sheet_info );
1100
1101 aPlotter->SetViewport( offset, pcbIUScale.IU_PER_MILS/10, compound_scale, aPlotOpts->GetMirror() );
1102
1103 // Has meaning only for gerber plotter. Must be called only after SetViewport
1104 aPlotter->SetGerberCoordinatesFormat( aPlotOpts->GetGerberPrecision() );
1105
1106 // Has meaning only for SVG plotter. Must be called only after SetViewport
1107 aPlotter->SetSvgCoordinatesFormat( aPlotOpts->GetSvgPrecision() );
1108
1109 aPlotter->SetCreator( wxT( "PCBNEW" ) );
1110 aPlotter->SetColorMode( !aPlotOpts->GetBlackAndWhite() ); // default is plot in Black and White.
1111 aPlotter->SetTextMode( aPlotOpts->GetTextMode() );
1112}
1113
1114
1118static void FillNegativeKnockout( PLOTTER *aPlotter, const BOX2I &aBbbox )
1119{
1120 const int margin = 5 * pcbIUScale.IU_PER_MM; // Add a 5 mm margin around the board
1121 aPlotter->SetNegative( true );
1122 aPlotter->SetColor( WHITE ); // Which will be plotted as black
1123
1124 BOX2I area = aBbbox;
1125 area.Inflate( margin );
1126 aPlotter->Rect( area.GetOrigin(), area.GetEnd(), FILL_T::FILLED_SHAPE );
1127 aPlotter->SetColor( BLACK );
1128}
1129
1130
1134static void ConfigureHPGLPenSizes( HPGL_PLOTTER *aPlotter, const PCB_PLOT_PARAMS *aPlotOpts )
1135{
1136 // Compute penDiam (the value is given in mils) in pcb units, with plot scale (if Scale is 2,
1137 // penDiam value is always m_HPGLPenDiam so apparent penDiam is actually penDiam / Scale
1138 int penDiam = KiROUND( aPlotOpts->GetHPGLPenDiameter() * pcbIUScale.IU_PER_MILS / aPlotOpts->GetScale() );
1139
1140 // Set HPGL-specific options and start
1141 aPlotter->SetPenSpeed( aPlotOpts->GetHPGLPenSpeed() );
1142 aPlotter->SetPenNumber( aPlotOpts->GetHPGLPenNum() );
1143 aPlotter->SetPenDiameter( penDiam );
1144}
1145
1146
1153PLOTTER* StartPlotBoard( BOARD *aBoard, const PCB_PLOT_PARAMS *aPlotOpts, int aLayer,
1154 const wxString& aFullFileName, const wxString& aSheetName,
1155 const wxString& aSheetPath )
1156{
1157 // Create the plotter driver and set the few plotter specific options
1158 PLOTTER* plotter = nullptr;
1159
1160 switch( aPlotOpts->GetFormat() )
1161 {
1162 case PLOT_FORMAT::DXF:
1163 DXF_PLOTTER* DXF_plotter;
1164 DXF_plotter = new DXF_PLOTTER();
1165 DXF_plotter->SetUnits( aPlotOpts->GetDXFPlotUnits() );
1166
1167 plotter = DXF_plotter;
1168 break;
1169
1170 case PLOT_FORMAT::POST:
1171 PS_PLOTTER* PS_plotter;
1172 PS_plotter = new PS_PLOTTER();
1173 PS_plotter->SetScaleAdjust( aPlotOpts->GetFineScaleAdjustX(),
1174 aPlotOpts->GetFineScaleAdjustY() );
1175 plotter = PS_plotter;
1176 break;
1177
1178 case PLOT_FORMAT::PDF:
1179 plotter = new PDF_PLOTTER();
1180 break;
1181
1182 case PLOT_FORMAT::HPGL:
1183 HPGL_PLOTTER* HPGL_plotter;
1184 HPGL_plotter = new HPGL_PLOTTER();
1185
1186 // HPGL options are a little more convoluted to compute, so they get their own function
1187 ConfigureHPGLPenSizes( HPGL_plotter, aPlotOpts );
1188 plotter = HPGL_plotter;
1189 break;
1190
1192 // For Gerber plotter, a valid board layer must be set, in order to create a valid
1193 // Gerber header, especially the TF.FileFunction and .FilePolarity data
1194 if( aLayer < PCBNEW_LAYER_ID_START || aLayer >= PCB_LAYER_ID_COUNT )
1195 {
1196 wxLogError( wxString::Format(
1197 "Invalid board layer %d, cannot build a valid Gerber file header",
1198 aLayer ) );
1199 }
1200
1201 plotter = new GERBER_PLOTTER();
1202 break;
1203
1204 case PLOT_FORMAT::SVG:
1205 plotter = new SVG_PLOTTER();
1206 break;
1207
1208 default:
1209 wxASSERT( false );
1210 return nullptr;
1211 }
1212
1214 renderSettings->LoadColors( aPlotOpts->ColorSettings() );
1215 renderSettings->SetDefaultPenWidth( pcbIUScale.mmToIU( 0.0212 ) ); // Hairline at 1200dpi
1216
1217 if( aLayer >= 0 && aLayer < GAL_LAYER_ID_END )
1218 renderSettings->SetLayerName( aBoard->GetLayerName( ToLAYER_ID( aLayer ) ) );
1219
1220 plotter->SetRenderSettings( renderSettings );
1221
1222 // Compute the viewport and set the other options
1223
1224 // page layout is not mirrored, so temporarily change mirror option for the page layout
1225 PCB_PLOT_PARAMS plotOpts = *aPlotOpts;
1226
1227 if( plotOpts.GetPlotFrameRef() && plotOpts.GetMirror() )
1228 plotOpts.SetMirror( false );
1229
1230 initializePlotter( plotter, aBoard, &plotOpts );
1231
1232 if( plotter->OpenFile( aFullFileName ) )
1233 {
1234 plotter->ClearHeaderLinesList();
1235
1236 // For the Gerber "file function" attribute, set the layer number
1237 if( plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
1238 {
1239 bool useX2mode = plotOpts.GetUseGerberX2format();
1240
1241 GERBER_PLOTTER* gbrplotter = static_cast <GERBER_PLOTTER*> ( plotter );
1242 gbrplotter->DisableApertMacros( plotOpts.GetDisableGerberMacros() );
1243 gbrplotter->UseX2format( useX2mode );
1244 gbrplotter->UseX2NetAttributes( plotOpts.GetIncludeGerberNetlistInfo() );
1245
1246 // Attributes can be added using X2 format or as comment (X1 format)
1247 AddGerberX2Attribute( plotter, aBoard, aLayer, not useX2mode );
1248 }
1249
1250 if( plotter->StartPlot( wxT( "1" ) ) )
1251 {
1252 // Plot the frame reference if requested
1253 if( aPlotOpts->GetPlotFrameRef() )
1254 {
1255 PlotDrawingSheet( plotter, aBoard->GetProject(), aBoard->GetTitleBlock(),
1256 aBoard->GetPageSettings(), &aBoard->GetProperties(), wxT( "1" ),
1257 1, aSheetName, aSheetPath, aBoard->GetFileName(),
1258 renderSettings->GetLayerColor( LAYER_DRAWINGSHEET ) );
1259
1260 if( aPlotOpts->GetMirror() )
1261 initializePlotter( plotter, aBoard, aPlotOpts );
1262 }
1263
1264 // When plotting a negative board: draw a black rectangle (background for plot board
1265 // in white) and switch the current color to WHITE; note the color inversion is actually
1266 // done in the driver (if supported)
1267 if( aPlotOpts->GetNegative() )
1268 {
1269 BOX2I bbox = aBoard->ComputeBoundingBox();
1270 FillNegativeKnockout( plotter, bbox );
1271 }
1272
1273 return plotter;
1274 }
1275 }
1276
1277 delete plotter->RenderSettings();
1278 delete plotter;
1279 return nullptr;
1280}
int color
Definition: DXF_plotter.cpp:58
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
const VECTOR2I & GetAuxOrigin()
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:77
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:281
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr, bool aAllowUseArcsInPolygons=false, bool aIncludeNPTHAsOutlines=false)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
Definition: board.cpp:2369
const PAGE_INFO & GetPageSettings() const
Definition: board.h:668
const ZONES & Zones() const
Definition: board.h:326
void ConvertBrdLayerToPolygonalContours(PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aOutlines) const
Build a set of polygons which are the outlines of copper items (pads, tracks, vias,...
Definition: board.cpp:2742
TITLE_BLOCK & GetTitleBlock()
Definition: board.h:674
BOX2I ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
Definition: board.cpp:1555
const std::map< wxString, wxString > & GetProperties() const
Definition: board.h:353
const FOOTPRINTS & Footprints() const
Definition: board.h:322
const TRACKS & Tracks() const
Definition: board.h:320
const wxString & GetFileName() const
Definition: board.h:318
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:567
PROJECT * GetProject() const
Definition: board.h:475
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:797
const DRAWINGS & Drawings() const
Definition: board.h:324
const Vec & GetOrigin() const
Definition: box2.h:184
coord_type GetHeight() const
Definition: box2.h:189
coord_type GetWidth() const
Definition: box2.h:188
const Vec GetEnd() const
Definition: box2.h:186
void Move(const Vec &aMoveVector)
Move the rectangle by the aMoveVector.
Definition: box2.h:112
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:507
Vec Centre() const
Definition: box2.h:71
const Vec & GetSize() const
Definition: box2.h:180
void PlotDrillMarks()
Draw a drill mark for pads and vias.
void PlotZone(const ZONE *aZone, PCB_LAYER_ID aLayer, const SHAPE_POLY_SET &aPolysList)
void PlotBoardGraphicItem(const BOARD_ITEM *item)
Plot items like text and graphics but not tracks and footprints.
void SetLayerSet(LSET aLayerMask)
Definition: pcbplot.h:85
void PlotPad(const PAD *aPad, const COLOR4D &aColor, OUTLINE_MODE aPlotMode)
Plot a pad.
COLOR4D getColor(int aLayer) const
White color is special because it cannot be seen on a white paper in B&W mode.
void PlotFootprintTextItems(const FOOTPRINT *aFootprint)
int getFineWidthAdj() const
Definition: pcbplot.h:76
void PlotFootprintGraphicItems(const FOOTPRINT *aFootprint)
COLOR4D GetColor(int aLayer) const
When creating polygons to create a clearance polygonal area, the polygon must be same or bigger than ...
void SetUnits(DXF_UNITS aUnit)
Set the units to use for plotting the DXF file.
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:98
@ GBR_APERTURE_ATTRIB_VIAPAD
aperture used for vias.
Definition: gbr_metadata.h:102
Metadata which can be added in a gerber file as attribute in X2 format.
Definition: gbr_metadata.h:205
void SetNetName(const wxString &aNetname)
Definition: gbr_metadata.h:229
void SetApertureAttrib(GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB aApertAttribute)
Definition: gbr_metadata.h:209
GBR_NETLIST_METADATA m_NetlistMetadata
An item to handle object attribute.
Definition: gbr_metadata.h:262
void SetNetAttribType(int aNetAttribType)
Definition: gbr_metadata.h:219
@ GBR_NETINFO_NET
print info associated to a net (TO.N attribute)
bool m_NotInNet
true if a pad of a footprint cannot be connected (for instance a mechanical NPTH, ot a not named pad)...
void UseX2format(bool aEnable)
void UseX2NetAttributes(bool aEnable)
void DisableApertMacros(bool aDisable)
Disable Aperture Macro (AM) command, only for broken Gerber Readers.
virtual void SetPenSpeed(int speed)
Definition: plotter_hpgl.h:88
virtual void SetPenNumber(int number)
Definition: plotter_hpgl.h:93
virtual void SetPenDiameter(double diameter)
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
static const COLOR4D BLACK
Definition: color4d.h:402
PCB specific render settings.
Definition: pcb_painter.h:77
void LoadColors(const COLOR_SETTINGS *aSettings) override
void SetDefaultPenWidth(int aWidth)
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
void SetLayerName(const wxString &aLayerName)
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: layer_ids.h:520
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:574
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:418
LSEQ SeqStackupForPlotting() const
Return the sequence that is typical for a bottom-to-top stack-up.
Definition: lset.cpp:563
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:863
Handle the data for a net.
Definition: netinfo.h:56
Definition: pad.h:59
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:59
const VECTOR2D GetSizeIU(double aIUScale) const
Gets the page size in internal units.
Definition: page_info.h:171
bool IsDegenerated(int aThreshold=5) const
Definition: pcb_track.cpp:1586
EDA_ANGLE GetArcAngleStart() const
Definition: pcb_track.cpp:1566
double GetRadius() const
Definition: pcb_track.cpp:1549
EDA_ANGLE GetAngle() const
Definition: pcb_track.cpp:1556
virtual VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition: pcb_track.h:322
bool IsReference() const
Definition: pcb_field.h:70
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
Definition: pcb_field.cpp:92
bool IsValue() const
Definition: pcb_field.h:71
bool IsFootprint() const
Definition: pcb_field.h:72
Parameters and options when plotting/printing a board.
bool GetNegative() const
PLOT_FORMAT GetFormat() const
bool GetSkipPlotNPTH_Pads() const
void SetDrillMarksType(DRILL_MARKS aVal)
bool GetUseAuxOrigin() const
void SetSkipPlotNPTH_Pads(bool aSkip)
bool GetMirror() const
DXF_UNITS GetDXFPlotUnits() const
bool GetAutoScale() const
bool GetPlotInvisibleText() const
PLOT_TEXT_MODE GetTextMode() const
double GetHPGLPenDiameter() const
unsigned GetSvgPrecision() const
unsigned GetBlackAndWhite() const
double GetScale() const
bool GetDXFPlotPolygonMode() const
bool GetPlotReference() const
bool m_PDFFrontFPPropertyPopups
Generate PDF property popup menus for footprints.
void SetMirror(bool aFlag)
bool GetSketchPadsOnFabLayers() const
bool GetSubtractMaskFromSilk() const
int GetGerberPrecision() const
int GetHPGLPenSpeed() const
double GetFineScaleAdjustY() const
bool GetA4Output() const
int GetHPGLPenNum() const
DRILL_MARKS GetDrillMarksType() const
bool GetUseGerberX2format() const
bool GetPlotValue() const
bool GetIncludeGerberNetlistInfo() const
double GetFineScaleAdjustX() const
bool m_PDFBackFPPropertyPopups
on front and/or back of board
bool GetPlotFPText() const
bool GetPlotFrameRef() const
bool GetDisableGerberMacros() const
OUTLINE_MODE GetPlotMode() const
COLOR_SETTINGS * ColorSettings() const
Base plotter engine class.
Definition: plotter.h:104
virtual void ThickSegment(const VECTOR2I &start, const VECTOR2I &end, int width, OUTLINE_MODE tracemode, void *aData)
Definition: plotter.cpp:554
virtual void Circle(const VECTOR2I &pos, int diametre, FILL_T fill, int width=USE_DEFAULT_LINE_WIDTH)=0
virtual bool OpenFile(const wxString &aFullFilename)
Open or create the plot file aFullFilename.
Definition: plotter.cpp:74
virtual void SetNegative(bool aNegative)
Definition: plotter.h:124
virtual void SetSvgCoordinatesFormat(unsigned aPrecision)
Set the number of digits for mantissa in coordinates in mm for SVG plotter.
Definition: plotter.h:524
virtual void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: plotter.h:137
void SetRenderSettings(RENDER_SETTINGS *aSettings)
Definition: plotter.h:134
virtual bool StartPlot(const wxString &aPageNumber)=0
RENDER_SETTINGS * RenderSettings()
Definition: plotter.h:135
virtual void SetGerberCoordinatesFormat(int aResolution, bool aUseInches=false)
Definition: plotter.h:518
virtual void Bookmark(const BOX2I &aBox, const wxString &aName, const wxString &aGroupName=wxEmptyString)
Create a bookmark to a symbol.
Definition: plotter.h:475
virtual PLOT_FORMAT GetPlotterType() const =0
Returns the effective plot engine in use.
virtual void SetTextMode(PLOT_TEXT_MODE mode)
Change the current text mode.
Definition: plotter.h:513
virtual void SetCreator(const wxString &aCreator)
Definition: plotter.h:153
VECTOR2I GetPlotOffsetUserUnits()
Definition: plotter.h:551
void ClearHeaderLinesList()
Remove all lines from the list of free lines to print at the beginning of the file.
Definition: plotter.h:171
virtual void FlashPadCircle(const VECTOR2I &aPadPos, int aDiameter, OUTLINE_MODE aTraceMode, void *aData)=0
virtual void ThickArc(const EDA_SHAPE &aArcShape, OUTLINE_MODE aTraceMode, void *aData)
Definition: plotter.cpp:597
virtual void SetViewport(const VECTOR2I &aOffset, double aIusPerDecimil, double aScale, bool aMirror)=0
Set the plot offset and scaling for the current plot.
virtual void SetColorMode(bool aColorMode)
Plot in B/W or color.
Definition: plotter.h:131
virtual void StartBlock(void *aData)
calling this function allows one to define the beginning of a group of drawing items,...
Definition: plotter.h:536
virtual void PlotPoly(const std::vector< VECTOR2I > &aCornerList, FILL_T aFill, int aWidth=USE_DEFAULT_LINE_WIDTH, void *aData=nullptr)=0
Draw a polygon ( filled or not ).
virtual void HyperlinkMenu(const BOX2I &aBox, const std::vector< wxString > &aDestURLs)
Create a clickable hyperlink menu with a rectangular click area.
Definition: plotter.h:464
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:504
virtual void Rect(const VECTOR2I &p1, const VECTOR2I &p2, FILL_T fill, int width=USE_DEFAULT_LINE_WIDTH)=0
virtual void SetColor(const COLOR4D &color)=0
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:545
void SetScaleAdjust(double scaleX, double scaleY)
Set the 'fine' scaling for the postscript engine.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
Represent a set of closed polygons.
void RemoveAllContours()
Remove all outlines & holes (clears) the polygon set.
void InflateWithLinkedHoles(int aFactor, CORNER_STRATEGY aCornerStrategy, int aMaxError, POLYGON_MODE aFastMode)
Perform outline inflation/deflation, using round corners.
void Fracture(POLYGON_MODE aFastMode)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
void DeletePolygon(int aIdx)
Delete aIdx-th polygon from the set.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
void BooleanAdd(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset union For aFastMode meaning, see function booleanOp.
int HoleCount(int aOutline) const
Returns the number of holes in a given outline.
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)
void Simplify(POLYGON_MODE aFastMode)
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections) For aFastMo...
int NewOutline()
Creates a new empty polygon in the set and returns its index.
void Deflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError)
const SHAPE_LINE_CHAIN & CHole(int aOutline, int aHole) const
int OutlineCount() const
Return the number of outlines in the set.
SHAPE_POLY_SET CloneDropTriangulation() const
const POLYGON & CPolygon(int aIndex) const
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
Handle a list of polygons defining a copper zone.
Definition: zone.h:72
void SetMinThickness(int aMinThickness)
Definition: zone.h:270
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition: zone.cpp:261
@ WHITE
Definition: color4d.h:48
@ LIGHTGRAY
Definition: color4d.h:47
@ BLACK
Definition: color4d.h:44
void PlotDrawingSheet(PLOTTER *plotter, const PROJECT *aProject, const TITLE_BLOCK &aTitleBlock, const PAGE_INFO &aPageInfo, const std::map< wxString, wxString > *aProperties, const wxString &aSheetNumber, int aSheetCount, const wxString &aSheetName, const wxString &aSheetPath, const wxString &aFilename, COLOR4D aColor, bool aIsFirstPage)
@ CHAMFER_ALL_CORNERS
All angles are chamfered.
@ ROUND_ALL_CORNERS
All angles are rounded.
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition: eda_angle.h:435
@ FILLED_SHAPE
Handle special data (items attributes) during plot.
a few functions useful in geometry calculations.
@ ERROR_OUTSIDE
@ ERROR_INSIDE
double m_SmallDrillMarkSize
The diameter of the drill marks on print and plot outputs (in mm) when the "Drill marks" option is se...
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:880
@ LAYER_DRAWINGSHEET
drawingsheet frame and titleblock
Definition: layer_ids.h:221
@ GAL_LAYER_ID_END
Definition: layer_ids.h:268
@ LAYER_VIAS
Meta control for all vias opacity/visibility.
Definition: layer_ids.h:197
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ F_CrtYd
Definition: layer_ids.h:117
@ B_Adhes
Definition: layer_ids.h:97
@ Edge_Cuts
Definition: layer_ids.h:113
@ Dwgs_User
Definition: layer_ids.h:109
@ F_Paste
Definition: layer_ids.h:101
@ Cmts_User
Definition: layer_ids.h:110
@ F_Adhes
Definition: layer_ids.h:98
@ B_Mask
Definition: layer_ids.h:106
@ B_Cu
Definition: layer_ids.h:95
@ Eco1_User
Definition: layer_ids.h:111
@ F_Mask
Definition: layer_ids.h:107
@ B_Paste
Definition: layer_ids.h:100
@ F_Fab
Definition: layer_ids.h:120
@ Margin
Definition: layer_ids.h:114
@ F_SilkS
Definition: layer_ids.h:104
@ B_CrtYd
Definition: layer_ids.h:116
@ UNDEFINED_LAYER
Definition: layer_ids.h:61
@ Eco2_User
Definition: layer_ids.h:112
@ B_SilkS
Definition: layer_ids.h:103
@ PCB_LAYER_ID_COUNT
Definition: layer_ids.h:137
@ F_Cu
Definition: layer_ids.h:64
@ B_Fab
Definition: layer_ids.h:119
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:1022
OUTLINE_MODE
Definition: outline_mode.h:25
@ SKETCH
Definition: outline_mode.h:26
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
PAD_SHAPE
The set of pad shapes, used with PAD::{Set,Get}Shape()
Definition: pad_shapes.h:35
void AddGerberX2Attribute(PLOTTER *aPlotter, const BOARD *aBoard, int aLayer, bool aUseX1CompatibilityMode)
Calculate some X2 attributes as defined in the Gerber file format specification and add them to the g...
Definition: pcbplot.cpp:342
static void FillNegativeKnockout(PLOTTER *aPlotter, const BOX2I &aBbbox)
Prefill in black an area a little bigger than the board to prepare for the negative plot.
void PlotBoardLayers(BOARD *aBoard, PLOTTER *aPlotter, const LSEQ &aLayers, const PCB_PLOT_PARAMS &aPlotOptions)
Plot a sequence of board layer IDs.
void PlotStandardLayer(BOARD *aBoard, PLOTTER *aPlotter, LSET aLayerMask, const PCB_PLOT_PARAMS &aPlotOpt)
Plot a copper layer or mask.
static void PlotSolderMaskLayer(BOARD *aBoard, PLOTTER *aPlotter, LSET aLayerMask, const PCB_PLOT_PARAMS &aPlotOpt, int aMinThickness)
Functions to plot one board layer (silkscreen layers or other layers).
void PlotOneBoardLayer(BOARD *aBoard, PLOTTER *aPlotter, PCB_LAYER_ID aLayer, const PCB_PLOT_PARAMS &aPlotOpt)
Plot one copper or technical layer.
void PlotLayerOutlines(BOARD *aBoard, PLOTTER *aPlotter, LSET aLayerMask, const PCB_PLOT_PARAMS &aPlotOpt)
Plot outlines of copper layer.
static void ConfigureHPGLPenSizes(HPGL_PLOTTER *aPlotter, const PCB_PLOT_PARAMS *aPlotOpts)
Calculate the effective size of HPGL pens and set them in the plotter object.
PLOTTER * StartPlotBoard(BOARD *aBoard, const PCB_PLOT_PARAMS *aPlotOpts, int aLayer, const wxString &aFullFileName, const wxString &aSheetName, const wxString &aSheetPath)
Open a new plotfile using the options (and especially the format) specified in the options and prepar...
static void initializePlotter(PLOTTER *aPlotter, const BOARD *aBoard, const PCB_PLOT_PARAMS *aPlotOpts)
Set up most plot options for plotting a board (especially the viewport) Important thing: page size is...
void PlotInteractiveLayer(BOARD *aBoard, PLOTTER *aPlotter, const PCB_PLOT_PARAMS &aPlotOpt)
Plot interactive items (hypertext links, properties, etc.).
Plotting engine (HPGL)
Plotting engines similar to ps (PostScript, Gerber, svg)
std::vector< FAB_LAYER_COLOR > dummy
const double IU_PER_MM
Definition: base_units.h:76
const double IU_PER_MILS
Definition: base_units.h:77
constexpr int mmToIU(double mm) const
Definition: base_units.h:88
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:92
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:98
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:85
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588