KiCad PCB EDA Suite
plot_brditems_plotter.cpp
Go to the documentation of this file.
1 
7 /*
8  * This program source code file is part of KiCad, a free EDA CAD application.
9  *
10  * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, you may find one here:
24  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
25  * or you may search the http://www.gnu.org website for the version 2 license,
26  * or you may write to the Free Software Foundation, Inc.,
27  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
28  */
29 
30 #include <fctsys.h>
31 #include <common.h>
32 #include <plotter.h>
33 #include <base_struct.h>
34 #include <draw_graphic_text.h>
35 #include <trigo.h>
36 #include <macros.h>
37 #include <pcb_base_frame.h>
38 
39 #include <class_board.h>
40 #include <class_module.h>
41 #include <class_track.h>
42 #include <class_edge_mod.h>
43 #include <class_pcb_text.h>
44 #include <class_zone.h>
45 #include <class_drawsegment.h>
46 #include <class_pcb_target.h>
47 #include <class_dimension.h>
49 
50 #include <pcbnew.h>
51 #include <pcbplot.h>
52 #include <gbr_metadata.h>
53 
54 /* class BRDITEMS_PLOTTER is a helper class to plot board items
55  * and a group of board items
56  */
57 
59 {
60  COLOR4D color = m_board->Colors().GetLayerColor( aLayer );
61 
62  // A hack to avoid plotting ahite itmen in white color, expecting the paper
63  // is also white: use a non white color:
64  if( color == COLOR4D::WHITE )
65  color = COLOR4D( LIGHTGRAY );
66 
67  return color;
68 }
69 
70 
71 void BRDITEMS_PLOTTER::PlotPad( D_PAD* aPad, COLOR4D aColor, EDA_DRAW_MODE_T aPlotMode )
72 {
73  wxPoint shape_pos = aPad->ShapePos();
74  GBR_METADATA gbr_metadata;
75 
76  bool isOnCopperLayer = ( m_layerMask & LSET::AllCuMask() ).any();
77  bool isOnExternalCopperLayer = ( m_layerMask & LSET::ExternalCuMask() ).any();
78  bool isPadOnBoardTechLayers = ( aPad->GetLayerSet() & LSET::AllBoardTechMask() ).any();
79 
80  gbr_metadata.SetCmpReference( aPad->GetParent()->GetReference() );
81 
82  if( isOnCopperLayer )
83  {
84  gbr_metadata.SetNetAttribType( GBR_NETINFO_ALL );
85  gbr_metadata.SetCopper( true );
86 
87  if( isOnExternalCopperLayer )
88  gbr_metadata.SetPadName( aPad->GetName() );
89 
90  gbr_metadata.SetNetName( aPad->GetNetname() );
91 
92  // Some pads are mechanical pads ( through hole or smd )
93  // when this is the case, they have no pad name and/or are not plated.
94  // In this case gerber files have slightly different attributes.
96  aPad->GetName().IsEmpty() )
97  gbr_metadata.m_NetlistMetadata.m_NotInNet = true;
98 
99  if( !isOnExternalCopperLayer || !isPadOnBoardTechLayers )
100  {
101  // On internal layers one cannot use the GBR_NETLIST_METADATA::GBR_INFO_FLASHED_PAD
102  // attribute when the component is on an external layer (most of the case)
103  // Also, if a SMD pad is not on a tech layer (masks) use also net+cmp attribute, because
104  // it is not really a pad (can be a "pad", actually a node in a virtual component)
107 
108  if( !isPadOnBoardTechLayers )
109  // such a pad is not soldered and is not a connecting point.
110  // Just set aperture attribute as conductor
111  // If it is a through hole pad, it will be adjusted later
113 
114  switch( aPad->GetAttribute() )
115  {
116  case PAD_ATTRIB_HOLE_NOT_PLATED: // Mechanical pad through hole
118  break;
119 
120  case PAD_ATTRIB_STANDARD : // Pad through hole, a hole is also expected
122  break;
123 
124  default:
125  break;
126  }
127  }
128  else // Some attributes are reserved to the external copper layers
129  {
130  switch( aPad->GetAttribute() )
131  {
132  case PAD_ATTRIB_HOLE_NOT_PLATED: // Mechanical pad through hole
134  break;
135 
136  case PAD_ATTRIB_STANDARD : // Pad through hole, a hole is also expected
138  break;
139 
140  case PAD_ATTRIB_CONN: // Connector pads have no solder paste.
142  break;
143 
144  case PAD_ATTRIB_SMD: // SMD pads (One external copper layer only) with solder paste
145  if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) // perhaps a BGA pad
147  else
149  break;
150  }
151  }
152 
155  }
156  else
157  {
159  }
160 
161  // Set plot color (change WHITE to LIGHTGRAY because
162  // the white items are not seen on a white paper or screen
163  m_plotter->SetColor( aColor != WHITE ? aColor : LIGHTGRAY);
164 
165  switch( aPad->GetShape() )
166  {
167  case PAD_SHAPE_CIRCLE:
168  m_plotter->FlashPadCircle( shape_pos, aPad->GetSize().x, aPlotMode, &gbr_metadata );
169  break;
170 
171  case PAD_SHAPE_OVAL:
172  m_plotter->FlashPadOval( shape_pos, aPad->GetSize(),
173  aPad->GetOrientation(), aPlotMode, &gbr_metadata );
174  break;
175 
176  case PAD_SHAPE_TRAPEZOID:
177  {
178  wxPoint coord[4];
179  aPad->BuildPadPolygon( coord, wxSize(0,0), 0 );
180  m_plotter->FlashPadTrapez( shape_pos, coord,
181  aPad->GetOrientation(), aPlotMode, &gbr_metadata );
182  }
183  break;
184 
185  case PAD_SHAPE_ROUNDRECT:
186  m_plotter->FlashPadRoundRect( shape_pos, aPad->GetSize(), aPad->GetRoundRectCornerRadius(),
187  aPad->GetOrientation(), aPlotMode, &gbr_metadata );
188  break;
189 
191  {
192  SHAPE_POLY_SET polygons;
193  const int segmentToCircleCount = 64;
194  const int corner_radius = aPad->GetRoundRectCornerRadius( aPad->GetSize() );
195  TransformRoundChamferedRectToPolygon( polygons, shape_pos, aPad->GetSize(),
196  aPad->GetOrientation(), corner_radius, aPad->GetChamferRectRatio(),
197  aPad->GetChamferPositions(), segmentToCircleCount );
198 
199  if( polygons.OutlineCount() == 0 )
200  break;
201 
202  int min_dim = std::min( aPad->GetSize().x, aPad->GetSize().y ) /2;
203  m_plotter->FlashPadCustom( shape_pos,wxSize( min_dim, min_dim ), &polygons, aPlotMode, &gbr_metadata );
204  }
205  break;
206 
207  case PAD_SHAPE_CUSTOM:
208  {
209  SHAPE_POLY_SET polygons;
210  aPad->MergePrimitivesAsPolygon(&polygons, 64 );
211 
212  if( polygons.OutlineCount() == 0 )
213  break;
214 
215  aPad->CustomShapeAsPolygonToBoardPosition( &polygons, shape_pos, aPad->GetOrientation() );
216  m_plotter->FlashPadCustom( shape_pos, aPad->GetSize(), &polygons, aPlotMode, &gbr_metadata );
217  }
218  break;
219 
220  case PAD_SHAPE_RECT:
221  default:
222  m_plotter->FlashPadRect( shape_pos, aPad->GetSize(),
223  aPad->GetOrientation(), aPlotMode, &gbr_metadata );
224  break;
225  }
226 }
227 
228 
230 {
231  TEXTE_MODULE* textModule = &aModule->Reference();
232  LAYER_NUM textLayer = textModule->GetLayer();
233 
234  if( GetPlotReference() && m_layerMask[textLayer]
235  && ( textModule->IsVisible() || GetPlotInvisibleText() ) )
236  {
237  PlotTextModule( textModule, getColor( textLayer ) );
238  }
239 
240  textModule = &aModule->Value();
241  textLayer = textModule->GetLayer();
242 
243  if( GetPlotValue() && m_layerMask[textLayer]
244  && ( textModule->IsVisible() || GetPlotInvisibleText() ) )
245  {
246  PlotTextModule( textModule, getColor( textLayer ) );
247  }
248 
249  for( BOARD_ITEM* item = aModule->GraphicalItemsList().GetFirst(); item; item = item->Next() )
250  {
251  textModule = dyn_cast<TEXTE_MODULE*>( item );
252 
253  if( !textModule )
254  continue;
255 
256  if( !textModule->IsVisible() )
257  continue;
258 
259  textLayer = textModule->GetLayer();
260 
261  if( textLayer >= PCB_LAYER_ID_COUNT )
262  return false;
263 
264  if( !m_layerMask[textLayer] )
265  continue;
266 
267  if( textModule->GetText() == wxT( "%R" ) && !GetPlotReference() )
268  continue;
269 
270  if( textModule->GetText() == wxT( "%V" ) && !GetPlotValue() )
271  continue;
272 
273  PlotTextModule( textModule, getColor( textLayer ) );
274  }
275 
276  return true;
277 }
278 
279 
280 // plot items like text and graphics, but not tracks and module
282 {
283  for( auto item : m_board->Drawings() )
284  {
285  switch( item->Type() )
286  {
287  case PCB_LINE_T:
288  PlotDrawSegment( (DRAWSEGMENT*) item);
289  break;
290 
291  case PCB_TEXT_T:
292  PlotTextePcb( (TEXTE_PCB*) item );
293  break;
294 
295  case PCB_DIMENSION_T:
296  PlotDimension( (DIMENSION*) item );
297  break;
298 
299  case PCB_TARGET_T:
300  PlotPcbTarget( (PCB_TARGET*) item );
301  break;
302 
303  case PCB_MARKER_T:
304  default:
305  break;
306  }
307  }
308 }
309 
311 {
312  wxSize size;
313  wxPoint pos;
314  double orient;
315  int thickness;
316 
317  if( aColor == COLOR4D::WHITE )
318  aColor = COLOR4D( LIGHTGRAY );
319 
320  m_plotter->SetColor( aColor );
321 
322  // calculate some text parameters :
323  size = pt_texte->GetTextSize();
324  pos = pt_texte->GetTextPos();
325 
326  orient = pt_texte->GetDrawRotation();
327 
328  thickness = pt_texte->GetThickness();
329 
330  if( pt_texte->IsMirrored() )
331  size.x = -size.x; // Text is mirrored
332 
333  // Non bold texts thickness is clamped at 1/6 char size by the low level draw function.
334  // but in Pcbnew we do not manage bold texts and thickness up to 1/4 char size
335  // (like bold text) and we manage the thickness.
336  // So we set bold flag to true
337  bool allow_bold = pt_texte->IsBold() || thickness;
338 
339  GBR_METADATA gbr_metadata;
341  MODULE* parent = static_cast<MODULE*> ( pt_texte->GetParent() );
342  gbr_metadata.SetCmpReference( parent->GetReference() );
343 
344  m_plotter->Text( pos, aColor,
345  pt_texte->GetShownText(),
346  orient, size,
347  pt_texte->GetHorizJustify(), pt_texte->GetVertJustify(),
348  thickness, pt_texte->IsItalic(), allow_bold, false, &gbr_metadata );
349 }
350 
351 
353 {
354  if( !m_layerMask[aDim->GetLayer()] )
355  return;
356 
357  DRAWSEGMENT draw;
358 
359  draw.SetWidth( aDim->GetWidth() );
360  draw.SetLayer( aDim->GetLayer() );
361 
363 
364  // Set plot color (change WHITE to LIGHTGRAY because
365  // the white items are not seen on a white paper or screen
367 
368  PlotTextePcb( &aDim->Text() );
369 
370  draw.SetStart( aDim->m_crossBarO );
371  draw.SetEnd( aDim->m_crossBarF );
372  PlotDrawSegment( &draw );
373 
374  draw.SetStart( aDim->m_featureLineGO);
375  draw.SetEnd( aDim->m_featureLineGF );
376  PlotDrawSegment( &draw );
377 
378  draw.SetStart( aDim->m_featureLineDO );
379  draw.SetEnd( aDim->m_featureLineDF );
380  PlotDrawSegment( &draw );
381 
382  draw.SetStart( aDim->m_crossBarF );
383  draw.SetEnd( aDim->m_arrowD1F );
384  PlotDrawSegment( &draw );
385 
386  draw.SetStart( aDim->m_crossBarF );
387  draw.SetEnd( aDim->m_arrowD2F );
388  PlotDrawSegment( &draw );
389 
390  draw.SetStart( aDim->m_crossBarO );
391  draw.SetEnd( aDim->m_arrowG1F );
392  PlotDrawSegment( &draw );
393 
394  draw.SetStart( aDim->m_crossBarO );
395  draw.SetEnd( aDim->m_arrowG2F );
396  PlotDrawSegment( &draw );
397 }
398 
399 
401 {
402  int dx1, dx2, dy1, dy2, radius;
403 
404  if( !m_layerMask[aMire->GetLayer()] )
405  return;
406 
407  m_plotter->SetColor( getColor( aMire->GetLayer() ) );
408 
409  DRAWSEGMENT draw;
410 
411  draw.SetShape( S_CIRCLE );
412  draw.SetWidth( aMire->GetWidth() );
413  draw.SetLayer( aMire->GetLayer() );
414  draw.SetStart( aMire->GetPosition() );
415  radius = aMire->GetSize() / 3;
416 
417  if( aMire->GetShape() ) // shape X
418  radius = aMire->GetSize() / 2;
419 
420  // Draw the circle
421  draw.SetEnd( wxPoint( draw.GetStart().x + radius, draw.GetStart().y ));
422 
423  PlotDrawSegment( &draw );
424 
425  draw.SetShape( S_SEGMENT );
426 
427  radius = aMire->GetSize() / 2;
428  dx1 = radius;
429  dy1 = 0;
430  dx2 = 0;
431  dy2 = radius;
432 
433  if( aMire->GetShape() ) // Shape X
434  {
435  dx1 = dy1 = radius;
436  dx2 = dx1;
437  dy2 = -dy1;
438  }
439 
440  wxPoint mirePos( aMire->GetPosition() );
441 
442  // Draw the X or + shape:
443  draw.SetStart( wxPoint( mirePos.x - dx1, mirePos.y - dy1 ));
444  draw.SetEnd( wxPoint( mirePos.x + dx1, mirePos.y + dy1 ));
445  PlotDrawSegment( &draw );
446 
447  draw.SetStart( wxPoint( mirePos.x - dx2, mirePos.y - dy2 ));
448  draw.SetEnd( wxPoint( mirePos.x + dx2, mirePos.y + dy2 ));
449  PlotDrawSegment( &draw );
450 }
451 
452 
453 // Plot footprints graphic items (outlines)
455 {
456  for( MODULE* module = m_board->m_Modules; module; module = module->Next() )
457  {
458  for( BOARD_ITEM* item = module->GraphicalItemsList().GetFirst(); item; item = item->Next() )
459  {
460  EDGE_MODULE* edge = dyn_cast<EDGE_MODULE*>( item );
461 
462  if( edge && m_layerMask[edge->GetLayer()] )
463  Plot_1_EdgeModule( edge );
464  }
465  }
466 }
467 
468 
469 //* Plot a graphic item (outline) relative to a footprint
471 {
472  int type_trace; // Type of item to plot.
473  int thickness; // Segment thickness.
474  int radius; // Circle radius.
475 
476  if( aEdge->Type() != PCB_MODULE_EDGE_T )
477  return;
478 
479  m_plotter->SetColor( getColor( aEdge->GetLayer() ) );
480 
481  type_trace = aEdge->GetShape();
482  thickness = aEdge->GetWidth();
483 
484  wxPoint pos( aEdge->GetStart() );
485  wxPoint end( aEdge->GetEnd() );
486 
487  GBR_METADATA gbr_metadata;
489  MODULE* parent = static_cast<MODULE*> ( aEdge->GetParent() );
490  gbr_metadata.SetCmpReference( parent->GetReference() );
491 
492  bool isOnCopperLayer = ( m_layerMask & LSET::AllCuMask() ).any();
493 
494  if( isOnCopperLayer )
495  {
496  gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_ETCHEDCMP );
497  gbr_metadata.SetCopper( true );
498  }
499  else if( aEdge->GetLayer() == Edge_Cuts ) // happens also when plotting copper layers
500  {
501  gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_NONCONDUCTOR );
502  }
503 
504  switch( type_trace )
505  {
506  case S_SEGMENT:
507  m_plotter->ThickSegment( pos, end, thickness, GetPlotMode(), &gbr_metadata );
508  break;
509 
510  case S_CIRCLE:
511  radius = KiROUND( GetLineLength( end, pos ) );
512  m_plotter->ThickCircle( pos, radius * 2, thickness, GetPlotMode(), &gbr_metadata );
513  break;
514 
515  case S_ARC:
516  {
517  radius = KiROUND( GetLineLength( end, pos ) );
518  double startAngle = ArcTangente( end.y - pos.y, end.x - pos.x );
519  double endAngle = startAngle + aEdge->GetAngle();
520 
521  // when startAngle == endAngle ThickArc() doesn't know whether it's 0 deg and 360 deg
522  if( std::abs( aEdge->GetAngle() ) == 3600.0 )
523  m_plotter->ThickCircle( pos, radius * 2, thickness, GetPlotMode(), &gbr_metadata );
524  else
525  m_plotter->ThickArc( pos, -endAngle, -startAngle, radius, thickness, GetPlotMode(), &gbr_metadata );
526  }
527  break;
528 
529  case S_POLYGON:
530  if( aEdge->IsPolyShapeValid() )
531  {
532  const std::vector<wxPoint>& polyPoints = aEdge->BuildPolyPointsList();
533 
534  // We must compute true coordinates from m_PolyList
535  // which are relative to module position, orientation 0
536  MODULE* module = aEdge->GetParentModule();
537 
538  std::vector< wxPoint > cornerList;
539 
540  cornerList.reserve( polyPoints.size() );
541 
542  for( unsigned ii = 0; ii < polyPoints.size(); ii++ )
543  {
544  wxPoint corner = polyPoints[ii];
545 
546  if( module )
547  {
548  RotatePoint( &corner, module->GetOrientation() );
549  corner += module->GetPosition();
550  }
551 
552  cornerList.push_back( corner );
553  }
554 
555  if( !aEdge->IsPolygonFilled() )
556  {
557  for( size_t i = 1; i < cornerList.size(); i++ )
558  {
559  m_plotter->ThickSegment( cornerList[i-1], cornerList[i],
560  thickness, GetPlotMode(), &gbr_metadata );
561  }
562 
563  m_plotter->ThickSegment( cornerList.back(), cornerList.front(),
564  thickness, GetPlotMode(), &gbr_metadata );
565 
566  }
567  else
568  {
569  m_plotter->PlotPoly( cornerList, FILLED_SHAPE, thickness, &gbr_metadata );
570  }
571  }
572  break;
573  }
574 }
575 
576 
577 // Plot a PCB Text, i.e. a text found on a copper or technical layer
579 {
580  double orient;
581  int thickness;
582  wxPoint pos;
583  wxSize size;
584  wxString shownText( pt_texte->GetShownText() );
585 
586  if( shownText.IsEmpty() )
587  return;
588 
589  if( !m_layerMask[pt_texte->GetLayer()] )
590  return;
591 
592  GBR_METADATA gbr_metadata;
593 
594  if( IsCopperLayer( pt_texte->GetLayer() ) )
595  {
597  }
598 
599  COLOR4D color = getColor( pt_texte->GetLayer() );
601 
602  size = pt_texte->GetTextSize();
603  pos = pt_texte->GetTextPos();
604  orient = pt_texte->GetTextAngle();
605  thickness = pt_texte->GetThickness();
606 
607  if( pt_texte->IsMirrored() )
608  size.x = -size.x;
609 
610  // Non bold texts thickness is clamped at 1/6 char size by the low level draw function.
611  // but in Pcbnew we do not manage bold texts and thickness up to 1/4 char size
612  // (like bold text) and we manage the thickness.
613  // So we set bold flag to true
614  bool allow_bold = pt_texte->IsBold() || thickness;
615 
616  if( pt_texte->IsMultilineAllowed() )
617  {
618  std::vector<wxPoint> positions;
619  wxArrayString strings_list;
620  wxStringSplit( shownText, strings_list, '\n' );
621  positions.reserve( strings_list.Count() );
622 
623  pt_texte->GetPositionsOfLinesOfMultilineText( positions, strings_list.Count() );
624 
625  for( unsigned ii = 0; ii < strings_list.Count(); ii++ )
626  {
627  wxString& txt = strings_list.Item( ii );
628  m_plotter->Text( positions[ii], color, txt, orient, size,
629  pt_texte->GetHorizJustify(), pt_texte->GetVertJustify(),
630  thickness, pt_texte->IsItalic(), allow_bold, false, &gbr_metadata );
631  }
632  }
633  else
634  {
635  m_plotter->Text( pos, color, shownText, orient, size,
636  pt_texte->GetHorizJustify(), pt_texte->GetVertJustify(),
637  thickness, pt_texte->IsItalic(), allow_bold, false, &gbr_metadata );
638  }
639 }
640 
641 
642 /* Plot areas (given by .m_FilledPolysList member) in a zone
643  */
645 {
646  const SHAPE_POLY_SET& polysList = aZone->GetFilledPolysList();
647 
648  if( polysList.IsEmpty() )
649  return;
650 
651  GBR_METADATA gbr_metadata;
652 
653  bool isOnCopperLayer = aZone->IsOnCopperLayer();
654 
655  if( isOnCopperLayer )
656  {
657  gbr_metadata.SetNetName( aZone->GetNetname() );
658  gbr_metadata.SetCopper( true );
659 
660  // Zones with no net name can exist.
661  // they are not used to connect items, so the aperture attribute cannot
662  // be set as conductor
663  if( aZone->GetNetname().IsEmpty() )
665  else
666  {
669  }
670  }
671 
672  // We need a buffer to store corners coordinates:
673  static std::vector< wxPoint > cornerList;
674  cornerList.clear();
675 
676  m_plotter->SetColor( getColor( aZone->GetLayer() ) );
677 
678  /* Plot all filled areas: filled areas have a filled area and a thick
679  * outline we must plot the filled area itself ( as a filled polygon
680  * OR a set of segments ) and plot the thick outline itself
681  *
682  * in non filled mode the outline is plotted, but not the filling items
683  */
684  for( auto ic = polysList.CIterate(); ic; ++ic )
685  {
686  wxPoint pos( ic->x, ic->y );
687  cornerList.push_back( pos );
688 
689  if( ic.IsEndContour() ) // Plot the current filled area outline
690  {
691  // First, close the outline
692  if( cornerList[0] != cornerList[cornerList.size() - 1] )
693  {
694  cornerList.push_back( cornerList[0] );
695  }
696 
697  // Plot the current filled area and its outline
698  if( GetPlotMode() == FILLED )
699  {
700  // Plot the filled area polygon.
701  // The area can be filled by segments or uses solid polygons
702  if( aZone->GetFillMode() == ZONE_FILL_MODE::ZFM_POLYGONS ) // We are using solid polygons
703  {
704  m_plotter->PlotPoly( cornerList, FILLED_SHAPE, aZone->GetMinThickness(), &gbr_metadata );
705  }
706  else // We are using areas filled by segments: plot segments and outline
707  {
708  for( unsigned iseg = 0; iseg < aZone->FillSegments().size(); iseg++ )
709  {
710  wxPoint start = (wxPoint) aZone->FillSegments()[iseg].A;
711  wxPoint end = (wxPoint) aZone->FillSegments()[iseg].B;
712  m_plotter->ThickSegment( start, end,
713  aZone->GetMinThickness(),
714  GetPlotMode(), &gbr_metadata );
715  }
716 
717  // Plot the area outline only
718  if( aZone->GetMinThickness() > 0 )
719  m_plotter->PlotPoly( cornerList, NO_FILL, aZone->GetMinThickness() );
720  }
721  }
722  else
723  {
724  if( aZone->GetMinThickness() > 0 )
725  {
726  for( unsigned jj = 1; jj<cornerList.size(); jj++ )
727  m_plotter->ThickSegment( cornerList[jj -1], cornerList[jj],
728  aZone->GetMinThickness(),
729  GetPlotMode(), &gbr_metadata );
730  }
731 
733  }
734 
735  cornerList.clear();
736  }
737  }
738 }
739 
740 
741 /* Plot items type DRAWSEGMENT on layers allowed by aLayerMask
742  */
744 {
745  if( !m_layerMask[aSeg->GetLayer()] )
746  return;
747 
748  int radius = 0;
749  double StAngle = 0, EndAngle = 0;
750  int thickness = aSeg->GetWidth();
751 
752  m_plotter->SetColor( getColor( aSeg->GetLayer() ) );
753 
754  wxPoint start( aSeg->GetStart() );
755  wxPoint end( aSeg->GetEnd() );
756 
757  GBR_METADATA gbr_metadata;
758 
759  bool isOnCopperLayer = ( m_layerMask & LSET::AllCuMask() ).any();
760 
761  if( isOnCopperLayer && aSeg->GetLayer() == Edge_Cuts ) // can happens when plotting copper layers
762  {
764  }
765 
766  switch( aSeg->GetShape() )
767  {
768  case S_CIRCLE:
769  radius = KiROUND( GetLineLength( end, start ) );
770  m_plotter->ThickCircle( start, radius * 2, thickness, GetPlotMode(), &gbr_metadata );
771  break;
772 
773  case S_ARC:
774  radius = KiROUND( GetLineLength( end, start ) );
775  StAngle = ArcTangente( end.y - start.y, end.x - start.x );
776  EndAngle = StAngle + aSeg->GetAngle();
777 
778  // when startAngle == endAngle ThickArc() doesn't know whether it's 0 deg and 360 deg
779  if( std::abs( aSeg->GetAngle() ) == 3600.0 )
780  m_plotter->ThickCircle( start, radius * 2, thickness, GetPlotMode(), &gbr_metadata );
781  else
782  m_plotter->ThickArc( start, -EndAngle, -StAngle, radius, thickness, GetPlotMode(), &gbr_metadata );
783  break;
784 
785  case S_CURVE:
786  {
787  m_plotter->SetCurrentLineWidth( thickness, &gbr_metadata );
788  const std::vector<wxPoint>& bezierPoints = aSeg->GetBezierPoints();
789 
790  for( unsigned i = 1; i < bezierPoints.size(); i++ )
791  m_plotter->ThickSegment( bezierPoints[i - 1], bezierPoints[i],
792  thickness, GetPlotMode(), &gbr_metadata );
793  }
794  break;
795 
796  case S_POLYGON:
797  {
798  if( !aSeg->IsPolygonFilled() )
799  {
800  for( auto it = aSeg->GetPolyShape().IterateSegments( 0 ); it; it++ )
801  {
802  auto seg = it.Get();
803  m_plotter->ThickSegment( wxPoint( seg.A ), wxPoint( seg.B ),
804  thickness, GetPlotMode(), &gbr_metadata );
805  }
806  }
807  else
808  {
809  m_plotter->SetCurrentLineWidth( thickness, &gbr_metadata );
810  // Draw the polygon: only one polygon is expected
811  // However we provide a multi polygon shape drawing
812  // ( for the future or to show a non expected shape )
813  // This must be simplified and fractured to prevent overlapping polygons
814  // from generating invalid Gerber files
815  auto tmpPoly = SHAPE_POLY_SET( aSeg->GetPolyShape() );
817 
818  for( int jj = 0; jj < tmpPoly.OutlineCount(); ++jj )
819  {
820  SHAPE_LINE_CHAIN& poly = tmpPoly.Outline( jj );
821  m_plotter->PlotPoly( poly, FILLED_SHAPE, thickness, &gbr_metadata );
822  }
823  }
824  }
825  break;
826 
827  default:
828  m_plotter->ThickSegment( start, end, thickness, GetPlotMode(), &gbr_metadata );
829  }
830 }
831 
832 
837  const wxPoint &aDrillPos, wxSize aDrillSize,
838  const wxSize &aPadSize,
839  double aOrientation, int aSmallDrill )
840 {
841  // Small drill marks have no significance when applied to slots
842  if( aSmallDrill && aDrillShape == PAD_DRILL_SHAPE_CIRCLE )
843  aDrillSize.x = std::min( aSmallDrill, aDrillSize.x );
844 
845  // Round holes only have x diameter, slots have both
846  aDrillSize.x -= getFineWidthAdj();
847  aDrillSize.x = Clamp( 1, aDrillSize.x, aPadSize.x - 1 );
848 
849  if( aDrillShape == PAD_DRILL_SHAPE_OBLONG )
850  {
851  aDrillSize.y -= getFineWidthAdj();
852  aDrillSize.y = Clamp( 1, aDrillSize.y, aPadSize.y - 1 );
853  m_plotter->FlashPadOval( aDrillPos, aDrillSize, aOrientation, GetPlotMode(), NULL );
854  }
855  else
856  m_plotter->FlashPadCircle( aDrillPos, aDrillSize.x, GetPlotMode(), NULL );
857 }
858 
859 
861 {
862  /* If small drills marks were requested prepare a clamp value to pass
863  to the helper function */
864  int small_drill = (GetDrillMarksType() == PCB_PLOT_PARAMS::SMALL_DRILL_SHAPE) ?
865  SMALL_DRILL : 0;
866 
867  /* In the filled trace mode drill marks are drawn white-on-black to scrape
868  the underlying pad. This works only for drivers supporting color change,
869  obviously... it means that:
870  - PS, SVG and PDF output is correct (i.e. you have a 'donut' pad)
871  - In HPGL you can't see them
872  - In gerbers you can't see them, too. This is arguably the right thing to
873  do since having drill marks and high speed drill stations is a sure
874  recipe for broken tools and angry manufacturers. If you *really* want them
875  you could start a layer with negative polarity to scrape the film.
876  - In DXF they go into the 'WHITE' layer. This could be useful.
877  */
878  if( GetPlotMode() == FILLED )
880 
881  for( TRACK* pts = m_board->m_Track; pts != NULL; pts = pts->Next() )
882  {
883  const VIA* via = dyn_cast<const VIA*>( pts );
884 
885  if( via )
887  wxSize( via->GetDrillValue(), 0 ),
888  wxSize( via->GetWidth(), 0 ), 0, small_drill );
889  }
890 
891  for( MODULE* Module = m_board->m_Modules; Module != NULL; Module = Module->Next() )
892  {
893  for( D_PAD* pad = Module->PadsList(); pad != NULL; pad = pad->Next() )
894  {
895  if( pad->GetDrillSize().x == 0 )
896  continue;
897 
898  plotOneDrillMark( pad->GetDrillShape(),
899  pad->GetPosition(), pad->GetDrillSize(),
900  pad->GetSize(), pad->GetOrientation(),
901  small_drill );
902  }
903  }
904 
905  if( GetPlotMode() == FILLED )
907 }
D_PAD * Next() const
Definition: class_pad.h:160
void wxStringSplit(const wxString &aText, wxArrayString &aStrings, wxChar aSplitter)
Split aString to a string list separated at aSplitter.
Definition: common.cpp:187
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:676
a class to handle special data (items attributes) during plot.
bool IsBold() const
Definition: eda_text.h:186
void SetPadName(const wxString &aPadname)
Definition: gbr_metadata.h:163
#define SMALL_DRILL
Definition: pcbplot.h:72
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:59
double GetOrientation() const
Definition: class_module.h:188
aperture used for etched components
Definition: gbr_metadata.h:83
TEXTE_MODULE & Reference()
Definition: class_module.h:503
void SetShape(STROKE_T aShape)
int OutlineCount() const
Returns the number of outlines in the set
aperture used for edge connecto pad (outer layers)
Definition: gbr_metadata.h:93
EDA_TEXT_VJUSTIFY_T GetVertJustify() const
Definition: eda_text.h:204
bool IsMirrored() const
Definition: eda_text.h:192
int GetWidth() const
double GetLineLength(const wxPoint &aPointA, const wxPoint &aPointB)
Function GetLineLength returns the length of a line segment defined by aPointA and aPointB.
Definition: trigo.h:191
const T & Clamp(const T &lower, const T &value, const T &upper)
Function Clamp limits value within the range lower <= value <= upper.
Definition: macros.h:130
TEXTE_PCB class definition.
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:121
like PAD_STANDARD, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:66
bool MergePrimitivesAsPolygon(SHAPE_POLY_SET *aMergedPolygon=NULL, int aCircleToSegmentsCount=ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF)
Merge all basic shapes, converted to a polygon in one polygon, in m_customShapeAsPolygon.
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
wxPoint m_crossBarF
print info associated to a component (TO.C attribute)
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
wxPoint m_arrowD1F
virtual void SetColor(COLOR4D color)=0
virtual void ThickCircle(const wxPoint &pos, int diametre, int width, EDA_DRAW_MODE_T tracemode, void *aData)
Definition: plotter.cpp:511
const wxPoint & GetStart() const
Definition: class_track.h:126
STROKE_T GetShape() const
void PlotPad(D_PAD *aPad, COLOR4D aColor, EDA_DRAW_MODE_T aPlotMode)
Plot a pad.
int GetSize() const
bool IsVisible() const
Definition: eda_text.h:189
void SetNetAttribType(int aNetAttribType)
Definition: gbr_metadata.h:152
Class BOARD to handle a board.
void PlotDimension(DIMENSION *Dimension)
int color
Definition: DXF_plotter.cpp:62
polygon (not yet used for tracks, but could be in microwave apps)
bool IsEmpty() const
Returns true if the set is empty (no polygons at all)
Smd pad, appears on the solder paste layer (default)
Definition: pad_shapes.h:62
virtual PCB_LAYER_ID GetLayer() const override
Function GetLayer returns the primary layer this item is on.
Definition: class_zone.cpp:179
PLOTTER * m_plotter
Definition: pcbplot.h:78
ZONE_SEGMENT_FILL & FillSegments()
Definition: class_zone.h:243
void PlotDrillMarks()
Function PlotDrillMarks Draw a drill mark for pads and vias.
double GetTextAngle() const
Definition: eda_text.h:177
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:92
aperture used for through hole component on outer layer
Definition: gbr_metadata.h:88
bool PlotAllTextsModule(MODULE *aModule)
Classes to handle copper zones.
int GetThickness() const
Function GetThickness returns pen width.
Definition: eda_text.h:167
usual segment : line with rounded ends
void TransformRoundChamferedRectToPolygon(SHAPE_POLY_SET &aCornerBuffer, const wxPoint &aPosition, const wxSize &aSize, double aRotation, int aCornerRadius, double aChamferRatio, int aChamferCorners, int aCircleToSegmentsCount)
convert a rectangle with rounded corners and/or chamfered corners to a polygon Convert rounded corner...
const std::vector< wxPoint > & GetBezierPoints() const
wxPoint m_featureLineDF
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:216
const std::vector< wxPoint > BuildPolyPointsList() const
Build and return the list of corners in a std::vector<wxPoint> It must be used only to convert the SH...
virtual wxString GetShownText() const override
Returns the string actually shown after processing of the base text.
virtual void PlotPoly(const std::vector< wxPoint > &aCornerList, FILL_T aFill, int aWidth=USE_DEFAULT_LINE_WIDTH, void *aData=NULL)=0
Function PlotPoly.
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
#define abs(a)
Definition: auxiliary.h:84
PAD_DRILL_SHAPE_T
Enum PAD_DRILL_SHAPE_T is the set of pad drill shapes, used with D_PAD::{Set,Get}DrillShape()
Definition: pad_shapes.h:47
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
BOARD * m_board
Definition: pcbplot.h:79
PAD_ATTR_T GetAttribute() const
Definition: class_pad.h:412
Functions relatives to tracks, vias and segments used to fill zones.
virtual void ThickArc(const wxPoint &centre, double StAngle, double EndAngle, int rayon, int width, EDA_DRAW_MODE_T tracemode, void *aData)
Definition: plotter.cpp:473
virtual void FlashPadCustom(const wxPoint &aPadPos, const wxSize &aSize, SHAPE_POLY_SET *aPolygons, EDA_DRAW_MODE_T aTraceMode, void *aData)=0
virtual function FlashPadCustom
This file contains miscellaneous commonly used macros and functions.
int GetChamferPositions() const
has meaning only for chamfered rect pads
Definition: class_pad.h:690
virtual void Text(const wxPoint &aPos, const COLOR4D aColor, const wxString &aText, double aOrient, const wxSize &aSize, enum EDA_TEXT_HJUSTIFY_T aH_justify, enum EDA_TEXT_VJUSTIFY_T aV_justify, int aWidth, bool aItalic, bool aBold, bool aMultilineAllowed=false, void *aData=NULL)
Draws text with the plotter.
void PlotFilledAreas(ZONE_CONTAINER *aZone)
Classes used in Pcbnew, CvPcb and GerbView.
Board plot function definition file.
wxPoint m_featureLineGO
bool IsItalic() const
Definition: eda_text.h:183
DIMENSION class definition.
COLOR4D GetLayerColor(LAYER_NUM aLayer) const
Function GetLayerColor.
aperture used for BGA pad with a solder mask defined by the solder mask
Definition: gbr_metadata.h:92
virtual void FlashPadCircle(const wxPoint &aPadPos, int aDiameter, EDA_DRAW_MODE_T aTraceMode, void *aData)=0
virtual function FlashPadCircle
int GetWidth() const
EDA_TEXT_HJUSTIFY_T GetHorizJustify() const
Definition: eda_text.h:203
double ArcTangente(int dy, int dx)
Definition: trigo.cpp:170
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
void PlotPcbTarget(PCB_TARGET *PtMire)
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:143
Class SHAPE_POLY_SET.
TEXTE_MODULE & Value()
read/write accessors:
Definition: class_module.h:502
EDA_DRAW_MODE_T
Definition: eda_text.h:77
void PlotBoardGraphicItems()
plot items like text and graphics, but not tracks and modules
COLOR4D GetColor() const
ZONE_FILL_MODE GetFillMode() const
Definition: class_zone.h:171
const wxSize & GetTextSize() const
Definition: eda_text.h:228
Arcs (with rounded ends)
double GetChamferRectRatio() const
has meaning only for chamfered rect pads
Definition: class_pad.h:667
virtual void FlashPadRoundRect(const wxPoint &aPadPos, const wxSize &aSize, int aCornerRadius, double aOrient, EDA_DRAW_MODE_T aTraceMode, void *aData)=0
virtual function FlashPadRoundRect
LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
Definition: class_pad.h:409
wxPoint m_arrowG1F
void Plot_1_EdgeModule(EDGE_MODULE *aEdge)
wxPoint m_arrowD2F
wxPoint m_arrowG2F
const wxString & GetReference() const
Function GetReference.
Definition: class_module.h:462
MODULE * GetParentModule() const
Function GetParentModule returns a pointer to the parent module, or NULL if DRAWSEGMENT does not belo...
static LSET ExternalCuMask()
Function ExternalCuMask returns a mask holding the Front and Bottom layers.
Definition: lset.cpp:706
const wxString & GetName() const
Definition: class_pad.h:190
aperture used for mechanical pads (NPTH)
Definition: gbr_metadata.h:94
SHAPE_POLY_SET & GetPolyShape()
Bezier Curve.
const wxString & GetNetname() const
Function GetNetname.
T * GetFirst() const
Function GetFirst returns the first T* in the list without removing it, or NULL if the list is empty.
Definition: dlist.h:163
Like smd, does not appear on the solder paste layer (default) note also has a special attribute in Ge...
Definition: pad_shapes.h:63
class DIMENSION, a dimension (graphic item)
Definition: typeinfo.h:100
CONST_ITERATOR CIterate(int aFirst, int aLast, bool aIterateHoles=false) const
void Fracture(POLYGON_MODE aFastMode)
Converts a set of polygons with holes to a singe outline with "slits"/"fractures" connecting the oute...
int GetWidth() const
bool IsMultilineAllowed() const
Definition: eda_text.h:201
aperture used for connected items like tracks (not vias)
Definition: gbr_metadata.h:84
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:101
void SetStart(const wxPoint &aStart)
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
bool GetPlotValue() const
MODULE * GetParent() const
Definition: class_pad.h:162
void BuildPadPolygon(wxPoint aCoord[4], wxSize aInflateValue, double aRotation) const
Function BuildPadPolygon Has meaning only for polygonal pads (trapezoid and rectangular) Build the Co...
void SetNetName(const wxString &aNetname)
Definition: gbr_metadata.h:162
double GetAngle() const
const COLORS_DESIGN_SETTINGS & Colors() const
Function GetColorSettings.
Definition: class_board.h:572
virtual void FlashPadRect(const wxPoint &aPadPos, const wxSize &aSize, double aPadOrient, EDA_DRAW_MODE_T aTraceMode, void *aData)=0
virtual function FlashPadRect
class MARKER_PCB, a marker used to show something
Definition: typeinfo.h:99
BOARD_ITEM * Next() const
int GetWidth() const
Definition: class_track.h:120
Class to handle a graphic segment.
void plotOneDrillMark(PAD_DRILL_SHAPE_T aDrillShape, const wxPoint &aDrillPos, wxSize aDrillSize, const wxSize &aPadSize, double aOrientation, int aSmallDrill)
Helper function to plot a single drill mark.
virtual void FlashPadOval(const wxPoint &aPadPos, const wxSize &aSize, double aPadOrient, EDA_DRAW_MODE_T aTraceMode, void *aData)=0
virtual function FlashPadOval
DLIST< MODULE > m_Modules
Definition: class_board.h:249
Class SHAPE_LINE_CHAIN.
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees,...
Definition: class_pad.h:389
virtual void ThickSegment(const wxPoint &start, const wxPoint &end, int width, EDA_DRAW_MODE_T tracemode, void *aData)
Definition: plotter.cpp:456
void CustomShapeAsPolygonToBoardPosition(SHAPE_POLY_SET *aMergedPolygon, wxPoint aPosition, double aRotation) const
When created, the corners coordinates are relative to the pad position, orientation 0,...
LSET m_layerMask
Definition: pcbplot.h:80
TEXTE_PCB & Text()
size_t i
Definition: json11.cpp:597
wxPoint ShapePos() const
Definition: class_pad.cpp:562
int GetShape() const
aperture used for SMD pad with a solder mask defined by the solder mask
Definition: gbr_metadata.h:90
The common library.
int GetMinThickness() const
Definition: class_zone.h:200
bool GetPlotInvisibleText() const
bool IsPolyShapeValid() const
void PlotTextePcb(TEXTE_PCB *pt_texte)
Definition: colors.h:49
void SetEnd(const wxPoint &aEnd)
int GetRoundRectCornerRadius() const
Function GetRoundRectCornerRadius Has meaning only for rounded rect pads.
Definition: class_pad.h:538
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
static LSET AllBoardTechMask()
Function AllTechMask returns a mask holding board technical layers (no CU layer) on both side.
Definition: lset.cpp:753
const wxPoint & GetTextPos() const
Definition: eda_text.h:237
void GetPositionsOfLinesOfMultilineText(std::vector< wxPoint > &aPositions, int aLineCount) const
Function GetPositionsOfLinesOfMultilineText Populates aPositions with the position of each line of a ...
Definition: eda_text.cpp:315
wxPoint m_crossBarO
PCB_TARGET class definition.
void SetApertureAttrib(GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB aApertAttribute)
Definition: gbr_metadata.h:142
DLIST< BOARD_ITEM > & GraphicalItemsList()
Definition: class_module.h:165
bool m_NotInNet
true if a pad of a footprint cannot be connected (for instance a mechanical NPTH, ot a not named pad)...
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
int getFineWidthAdj()
Definition: pcbplot.h:95
DLIST< TRACK > m_Track
Definition: class_board.h:250
GBR_NETLIST_METADATA m_NetlistMetadata
a item to handle object attribute:
Definition: gbr_metadata.h:181
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:216
Module description (excepted pads)
virtual wxString GetShownText() const
Returns the string actually shown after processing of the base text.
Definition: eda_text.h:148
Basic classes for most KiCad items.
aperture used for not connected items (texts, outlines on copper)
Definition: gbr_metadata.h:86
const wxSize & GetSize() const
Definition: class_pad.h:269
EDGE_MODULE class definition.
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:91
BOARD_ITEM_CONTAINER * GetParent() const
void SetCopper(bool aValue)
Definition: gbr_metadata.h:171
virtual void FlashPadTrapez(const wxPoint &aPadPos, const wxPoint *aCorners, double aPadOrient, EDA_DRAW_MODE_T aTraceMode, void *aData)=0
virtual function FlashPadTrapez flash a trapezoidal pad
double GetDrawRotation() const
DrillMarksType GetDrillMarksType() const
wxPoint m_featureLineDO
print info associated to a net (TO.N attribute)
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
bool IsPolygonFilled() const
Polygonal shape is not always filled.
bool GetPlotReference() const
const wxPoint GetPosition() const override
Definition: class_module.h:183
bool IsOnCopperLayer() const
Function IsOnCopperLayer.
Definition: class_zone.cpp:185
void SetCmpReference(const wxString &aComponentRef)
Definition: gbr_metadata.h:164
COLOR4D getColor(LAYER_NUM aLayer)
Function getColor.
Class DIMENSION.
DLIST_ITERATOR_WRAPPER< BOARD_ITEM > Drawings()
Definition: class_board.h:256
const wxPoint GetPosition() const override
#define GBR_NETINFO_ALL
SEGMENT_ITERATOR IterateSegments(int aFirst, int aLast, bool aIterateHoles=false)
Returns an iterator object, for iterating between aFirst and aLast outline, with or without holes (de...
KICAD_T Type() const
Function Type()
Definition: base_struct.h:201
#define min(a, b)
Definition: auxiliary.h:85
const SHAPE_POLY_SET & GetFilledPolysList() const
Function GetFilledPolysList returns a reference to the list of filled polygons.
Definition: class_zone.h:566
EDA_DRAW_MODE_T GetPlotMode() const
virtual void SetCurrentLineWidth(int width, void *aData=NULL)=0
Set the line width for the next drawing.
void PlotDrawSegment(DRAWSEGMENT *PtSegm)
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39
wxPoint m_featureLineGF
void SetWidth(int aWidth)
void PlotTextModule(TEXTE_MODULE *aTextMod, COLOR4D aColor)