KiCad PCB EDA Suite
gen_drill_report_files.cpp
Go to the documentation of this file.
1 
6 /*
7  * This program source code file is part of KiCad, a free EDA CAD application.
8  *
9  * Copyright (C) 1992-2017 Jean_Pierre Charras <jp.charras at wanadoo.fr>
10  * Copyright (C) 1992-2017 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 <class_plotter.h>
33 #include <base_struct.h>
34 #include <drawtxt.h>
35 #include <confirm.h>
36 #include <kicad_string.h>
37 #include <macros.h>
38 
39 #include <class_board.h>
40 
41 #include <pcbnew.h>
42 #include <pcbplot.h>
44 
45 /* Conversion utilities - these will be used often in there... */
46 inline double diameter_in_inches( double ius )
47 {
48  return ius * 0.001 / IU_PER_MILS;
49 }
50 
51 
52 inline double diameter_in_mm( double ius )
53 {
54  return ius / IU_PER_MM;
55 }
56 
57 
58 bool GENDRILL_WRITER_BASE::genDrillMapFile( const wxString& aFullFileName,
59  PlotFormat aFormat )
60 {
61  // Remark:
62  // Hole list must be created before calling this function, by buildHolesList(),
63  // for the right holes set (PTH, NPTH, buried/blind vias ...)
64 
65  double scale = 1.0;
66  wxPoint offset;
67  PLOTTER* plotter = NULL;
68  PAGE_INFO dummy( PAGE_INFO::A4, false );
69 
70  PCB_PLOT_PARAMS plot_opts; // starts plotting with default options
71 
72  LOCALE_IO toggle; // use standard C notation for float numbers
73 
74  const PAGE_INFO& page_info = m_pageInfo ? *m_pageInfo : dummy;
75 
76  // Calculate dimensions and center of PCB
78 
79  // Calculate the scale for the format type, scale 1 in HPGL, drawing on
80  // an A4 sheet in PS, + text description of symbols
81  switch( aFormat )
82  {
83  case PLOT_FORMAT_GERBER:
84  offset = GetOffset();
85  plotter = new GERBER_PLOTTER();
86  plotter->SetViewport( offset, IU_PER_MILS/10, scale, false );
87  plotter->SetGerberCoordinatesFormat( 5 ); // format x.5 unit = mm
88  break;
89 
90  case PLOT_FORMAT_HPGL: // Scale for HPGL format.
91  {
92  HPGL_PLOTTER* hpgl_plotter = new HPGL_PLOTTER;
93  plotter = hpgl_plotter;
94  hpgl_plotter->SetPenNumber( plot_opts.GetHPGLPenNum() );
95  hpgl_plotter->SetPenSpeed( plot_opts.GetHPGLPenSpeed() );
96  plotter->SetPageSettings( page_info );
97  plotter->SetViewport( offset, IU_PER_MILS/10, scale, false );
98  }
99  break;
100 
101 
102  default:
103  wxASSERT( false );
104  // fall through
105  case PLOT_FORMAT_PDF:
106  case PLOT_FORMAT_POST:
107  {
108  PAGE_INFO pageA4( wxT( "A4" ) );
109  wxSize pageSizeIU = pageA4.GetSizeIU();
110 
111  // Reserve a margin around the page.
112  int margin = KiROUND( 20 * IU_PER_MM );
113 
114  // Calculate a scaling factor to print the board on the sheet
115  double Xscale = double( pageSizeIU.x - ( 2 * margin ) ) / bbbox.GetWidth();
116 
117  // We should print the list of drill sizes, so reserve room for it
118  // 60% height for board 40% height for list
119  int ypagesize_for_board = KiROUND( pageSizeIU.y * 0.6 );
120  double Yscale = double( ypagesize_for_board - margin ) / bbbox.GetHeight();
121 
122  scale = std::min( Xscale, Yscale );
123 
124  // Experience shows the scale should not to large, because texts
125  // create problem (can be to big or too small).
126  // So the scale is clipped at 3.0;
127  scale = std::min( scale, 3.0 );
128 
129  offset.x = KiROUND( double( bbbox.Centre().x ) -
130  ( pageSizeIU.x / 2.0 ) / scale );
131  offset.y = KiROUND( double( bbbox.Centre().y ) -
132  ( ypagesize_for_board / 2.0 ) / scale );
133 
134  if( aFormat == PLOT_FORMAT_PDF )
135  plotter = new PDF_PLOTTER;
136  else
137  plotter = new PS_PLOTTER;
138 
139  plotter->SetPageSettings( pageA4 );
140  plotter->SetViewport( offset, IU_PER_MILS/10, scale, false );
141  }
142  break;
143 
144  case PLOT_FORMAT_DXF:
145  {
146  DXF_PLOTTER* dxf_plotter = new DXF_PLOTTER;
147  plotter = dxf_plotter;
148  plotter->SetPageSettings( page_info );
149  plotter->SetViewport( offset, IU_PER_MILS/10, scale, false );
150  }
151  break;
152 
153  case PLOT_FORMAT_SVG:
154  {
155  SVG_PLOTTER* svg_plotter = new SVG_PLOTTER;
156  plotter = svg_plotter;
157  plotter->SetPageSettings( page_info );
158  plotter->SetViewport( offset, IU_PER_MILS/10, scale, false );
159  }
160  break;
161  }
162 
163  plotter->SetCreator( wxT( "PCBNEW" ) );
164  plotter->SetDefaultLineWidth( 5 * IU_PER_MILS );
165  plotter->SetColorMode( false );
166 
167  if( ! plotter->OpenFile( aFullFileName ) )
168  {
169  delete plotter;
170  return false;
171  }
172 
173  plotter->StartPlot();
174 
175  // Draw items on edge layer (not all, only items useful for drill map
176  BRDITEMS_PLOTTER itemplotter( plotter, m_pcb, plot_opts );
177  itemplotter.SetLayerSet( Edge_Cuts );
178 
179  for( auto PtStruct : m_pcb->Drawings() )
180  {
181  switch( PtStruct->Type() )
182  {
183  case PCB_LINE_T:
184  itemplotter.PlotDrawSegment( (DRAWSEGMENT*) PtStruct );
185  break;
186 
187  case PCB_TEXT_T:
188  itemplotter.PlotTextePcb( (TEXTE_PCB*) PtStruct );
189  break;
190 
191  case PCB_DIMENSION_T:
192  case PCB_TARGET_T:
193  case PCB_MARKER_T: // do not draw
194  default:
195  break;
196  }
197  }
198 
199  int x, y;
200  int plotX, plotY, TextWidth;
201  int intervalle = 0;
202  char line[1024];
203  wxString msg;
204  int textmarginaftersymbol = KiROUND( 2 * IU_PER_MM );
205 
206  // Set Drill Symbols width
207  plotter->SetDefaultLineWidth( 0.2 * IU_PER_MM / scale );
208  plotter->SetCurrentLineWidth( -1 );
209 
210  // Plot board outlines and drill map
211  plotDrillMarks( plotter );
212 
213  // Print a list of symbols used.
214  int charSize = 3 * IU_PER_MM; // text size in IUs
215  double charScale = 1.0 / scale; // real scale will be 1/scale,
216  // because the global plot scale is scale
217  TextWidth = KiROUND( (charSize * charScale) / 10.0 ); // Set text width (thickness)
218  intervalle = KiROUND( charSize * charScale ) + TextWidth;
219 
220  // Trace information.
221  plotX = KiROUND( bbbox.GetX() + textmarginaftersymbol * charScale );
222  plotY = bbbox.GetBottom() + intervalle;
223 
224  // Plot title "Info"
225  wxString Text = wxT( "Drill Map:" );
226  plotter->Text( wxPoint( plotX, plotY ), COLOR4D::UNSPECIFIED, Text, 0,
227  wxSize( KiROUND( charSize * charScale ),
228  KiROUND( charSize * charScale ) ),
230  TextWidth, false, false );
231 
232  for( unsigned ii = 0; ii < m_toolListBuffer.size(); ii++ )
233  {
234  DRILL_TOOL& tool = m_toolListBuffer[ii];
235 
236  if( tool.m_TotalCount == 0 )
237  continue;
238 
239  plotY += intervalle;
240 
241  int plot_diam = KiROUND( tool.m_Diameter );
242  x = KiROUND( plotX - textmarginaftersymbol * charScale - plot_diam / 2.0 );
243  y = KiROUND( plotY + charSize * charScale );
244  plotter->Marker( wxPoint( x, y ), plot_diam, ii );
245 
246  // List the diameter of each drill in mm and inches.
247  sprintf( line, "%2.2fmm / %2.3f\" ",
248  diameter_in_mm( tool.m_Diameter ),
249  diameter_in_inches( tool.m_Diameter ) );
250 
251  msg = FROM_UTF8( line );
252 
253  // Now list how many holes and ovals are associated with each drill.
254  if( ( tool.m_TotalCount == 1 )
255  && ( tool.m_OvalCount == 0 ) )
256  sprintf( line, "(1 hole)" );
257  else if( tool.m_TotalCount == 1 ) // && ( toolm_OvalCount == 1 )
258  sprintf( line, "(1 slot)" );
259  else if( tool.m_OvalCount == 0 )
260  sprintf( line, "(%d holes)", tool.m_TotalCount );
261  else if( tool.m_OvalCount == 1 )
262  sprintf( line, "(%d holes + 1 slot)", tool.m_TotalCount - 1 );
263  else // if ( toolm_OvalCount > 1 )
264  sprintf( line, "(%d holes + %d slots)",
265  tool.m_TotalCount - tool.m_OvalCount,
266  tool.m_OvalCount );
267 
268  msg += FROM_UTF8( line );
269 
270  if( tool.m_Hole_NotPlated )
271  msg += wxT( " (not plated)" );
272 
273  plotter->Text( wxPoint( plotX, y ), COLOR4D::UNSPECIFIED, msg, 0,
274  wxSize( KiROUND( charSize * charScale ),
275  KiROUND( charSize * charScale ) ),
277  TextWidth, false, false );
278 
279  intervalle = KiROUND( ( ( charSize * charScale ) + TextWidth ) * 1.2 );
280 
281  if( intervalle < ( plot_diam + ( 1 * IU_PER_MM / scale ) + TextWidth ) )
282  intervalle = plot_diam + ( 1 * IU_PER_MM / scale ) + TextWidth;
283  }
284 
285  plotter->EndPlot();
286  delete plotter;
287 
288  return true;
289 }
290 
291 
292 bool GENDRILL_WRITER_BASE::GenDrillReportFile( const wxString& aFullFileName )
293 {
294  FILE_OUTPUTFORMATTER out( aFullFileName );
295 
296  static const char separator[] =
297  " =============================================================\n";
298 
299  wxASSERT( m_pcb );
300 
301  unsigned totalHoleCount;
302  wxString brdFilename = m_pcb->GetFileName();
303 
304  std::vector<DRILL_LAYER_PAIR> hole_sets = getUniqueLayerPairs();
305 
306  out.Print( 0, "Drill report for %s\n", TO_UTF8( brdFilename ) );
307  out.Print( 0, "Created on %s\n\n", TO_UTF8( DateAndTime() ) );
308 
309  // Output the cu layer stackup, so layer name references make sense.
310  out.Print( 0, "Copper Layer Stackup:\n" );
311  out.Print( 0, separator );
312 
314 
315  int conventional_layer_num = 1;
316 
317  for( LSEQ seq = cu.Seq(); seq; ++seq, ++conventional_layer_num )
318  {
319  out.Print( 0, " L%-2d: %-25s %s\n",
320  conventional_layer_num,
321  TO_UTF8( m_pcb->GetLayerName( *seq ) ),
322  layerName( *seq ).c_str() // generic layer name
323  );
324  }
325 
326  out.Print( 0, "\n\n" );
327 
328  /* output hole lists:
329  * 1 - through holes
330  * 2 - for partial holes only: by layer starting and ending pair
331  * 3 - Non Plated through holes
332  */
333 
334  bool buildNPTHlist = false; // First pass: build PTH list only
335 
336  // in this loop are plated only:
337  for( unsigned pair_ndx = 0; pair_ndx < hole_sets.size(); ++pair_ndx )
338  {
339  DRILL_LAYER_PAIR pair = hole_sets[pair_ndx];
340 
341  buildHolesList( pair, buildNPTHlist );
342 
343  if( pair == DRILL_LAYER_PAIR( F_Cu, B_Cu ) )
344  {
345  out.Print( 0, "Drill file '%s' contains\n",
346  TO_UTF8( getDrillFileName( pair, false, m_merge_PTH_NPTH ) ) );
347 
348  out.Print( 0, " plated through holes:\n" );
349  out.Print( 0, separator );
350  totalHoleCount = printToolSummary( out, false );
351  out.Print( 0, " Total plated holes count %u\n", totalHoleCount );
352  }
353  else // blind/buried
354  {
355  out.Print( 0, "Drill file '%s' contains\n",
356  TO_UTF8( getDrillFileName( pair, false, m_merge_PTH_NPTH ) ) );
357 
358  out.Print( 0, " holes connecting layer pair: '%s and %s' (%s vias):\n",
359  TO_UTF8( m_pcb->GetLayerName( ToLAYER_ID( pair.first ) ) ),
360  TO_UTF8( m_pcb->GetLayerName( ToLAYER_ID( pair.second ) ) ),
361  pair.first == F_Cu || pair.second == B_Cu ? "blind" : "buried"
362  );
363 
364  out.Print( 0, separator );
365  totalHoleCount = printToolSummary( out, false );
366  out.Print( 0, " Total plated holes count %u\n", totalHoleCount );
367  }
368 
369  out.Print( 0, "\n\n" );
370  }
371 
372  // NPTHoles. Generate the full list (pads+vias) if PTH and NPTH are merged,
373  // or only the NPTH list (which never has vias)
374  if( !m_merge_PTH_NPTH )
375  buildNPTHlist = true;
376 
377  buildHolesList( DRILL_LAYER_PAIR( F_Cu, B_Cu ), buildNPTHlist );
378 
379  // nothing wrong with an empty NPTH file in report.
380  if( m_merge_PTH_NPTH )
381  out.Print( 0, "Not plated through holes are merged with plated holes\n" );
382  else
383  out.Print( 0, "Drill file '%s' contains\n",
385  true, m_merge_PTH_NPTH ) ) );
386 
387  out.Print( 0, " unplated through holes:\n" );
388  out.Print( 0, separator );
389  totalHoleCount = printToolSummary( out, true );
390  out.Print( 0, " Total unplated holes count %u\n", totalHoleCount );
391 
392  return true;
393 }
394 
395 
397 {
398  // Plot the drill map:
399  wxPoint pos;
400 
401  for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ )
402  {
403  const HOLE_INFO& hole = m_holeListBuffer[ii];
404  pos = hole.m_Hole_Pos;
405 
406  // Always plot the drill symbol (for slots identifies the needed cutter!
407  aPlotter->Marker( pos, hole.m_Hole_Diameter, hole.m_Tool_Reference - 1 );
408 
409  if( hole.m_Hole_Shape != 0 )
410  {
411  wxSize oblong_size = hole.m_Hole_Size;
412  aPlotter->FlashPadOval( pos, oblong_size, hole.m_Hole_Orient, SKETCH, NULL );
413  }
414  }
415 
416  return true;
417 }
418 
419 
420 unsigned GENDRILL_WRITER_BASE::printToolSummary( OUTPUTFORMATTER& out, bool aSummaryNPTH ) const
421 {
422  unsigned totalHoleCount = 0;
423 
424  for( unsigned ii = 0; ii < m_toolListBuffer.size(); ii++ )
425  {
426  const DRILL_TOOL& tool = m_toolListBuffer[ii];
427 
428  if( aSummaryNPTH && !tool.m_Hole_NotPlated )
429  continue;
430 
431  if( !aSummaryNPTH && tool.m_Hole_NotPlated )
432  continue;
433 
434  // List the tool number assigned to each drill,
435  // in mm then in inches.
436  int tool_number = ii+1;
437  out.Print( 0, " T%d %2.2fmm %2.3f\" ", tool_number,
438  diameter_in_mm( tool.m_Diameter ),
439  diameter_in_inches( tool.m_Diameter ) );
440 
441  // Now list how many holes and ovals are associated with each drill.
442  if( ( tool.m_TotalCount == 1 ) && ( tool.m_OvalCount == 0 ) )
443  out.Print( 0, "(1 hole)\n" );
444  else if( tool.m_TotalCount == 1 )
445  out.Print( 0, "(1 hole) (with 1 slot)\n" );
446  else if( tool.m_OvalCount == 0 )
447  out.Print( 0, "(%d holes)\n", tool.m_TotalCount );
448  else if( tool.m_OvalCount == 1 )
449  out.Print( 0, "(%d holes) (with 1 slot)\n", tool.m_TotalCount );
450  else // tool.m_OvalCount > 1
451  out.Print( 0, "(%d holes) (with %d slots)\n",
452  tool.m_TotalCount, tool.m_OvalCount );
453 
454  totalHoleCount += tool.m_TotalCount;
455  }
456 
457  out.Print( 0, "\n" );
458 
459  return totalHoleCount;
460 }
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:646
double diameter_in_inches(double ius)
bool genDrillMapFile(const wxString &aFullFileName, PlotFormat aFormat)
Function GenDrillMapFile Plot a map of drill marks for holes.
double diameter_in_mm(double ius)
virtual void SetCreator(const wxString &aCreator)
static wxString FROM_UTF8(const char *cstring)
function FROM_UTF8 converts a UTF8 encoded C string to a wxString for all wxWidgets build modes...
Definition: macros.h:53
static int KiROUND(double v)
KiROUND rounds a floating point number to an int using "round halfway cases away from zero"...
Definition: common.h:107
Class LOCALE_IO is a class that can be instantiated within a scope in which you are expecting excepti...
Definition: common.h:166
virtual bool StartPlot()=0
This file is part of the common library.
virtual bool OpenFile(const wxString &aFullFilename)
Open or create the plot file aFullFilename.
Class BOARD to handle a board.
virtual const wxString getDrillFileName(DRILL_LAYER_PAIR aPair, bool aNPTH, bool aMerge_PTH_NPTH) const
int GetHeight() const
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:92
Class OUTPUTFORMATTER is an important interface (abstract class) used to output 8 bit text in a conve...
Definition: richio.h:327
const std::string layerName(PCB_LAYER_ID aLayer) const
minor helper function.
virtual void SetPageSettings(const PAGE_INFO &aPageSettings)
#define cu(a)
Definition: auxiliary.h:88
LSET GetEnabledLayers() const
Function GetEnabledLayers is a proxy function that calls the corresponding function in m_BoardSetting...
virtual void SetGerberCoordinatesFormat(int aResolution, bool aUseInches=false)
This file contains miscellaneous commonly used macros and functions.
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.
Definition: drawtxt.cpp:229
Board plot function definition file.
const EDA_RECT GetBoardEdgesBoundingBox() const
Function GetBoardEdgesBoundingBox Returns the board bounding box calculated using exclusively the boa...
Definition: class_board.h:797
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Function Seq returns an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:337
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
std::vector< DRILL_TOOL > m_toolListBuffer
virtual bool EndPlot()=0
Class LSET is a set of PCB_LAYER_IDs.
std::vector< DRILL_LAYER_PAIR > getUniqueLayerPairs() const
Get unique layer pairs by examining the micro and blind_buried vias.
bool GenDrillReportFile(const wxString &aFullFileName)
Function GenDrillReportFile Create a plain text report file giving a list of drill values and drill c...
void SetLayerSet(LSET aLayerMask)
Definition: pcbplot.h:104
int GetHPGLPenNum() const
const wxString & GetFileName() const
Definition: class_board.h:234
Class PAGE_INFO describes the page size and margins of a paper page on which to eventually print or p...
virtual void SetPenSpeed(int speed)
helper classes to handle hole info for drill files generators.
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Function GetLayerName returns the name of a layer given by aLayer.
PlotFormat
Enum PlotFormat is the set of supported output plot formats.
Definition: class_plotter.h:50
static const wxChar A4[]
int GetBottom() const
std::pair< PCB_LAYER_ID, PCB_LAYER_ID > DRILL_LAYER_PAIR
wxPoint Centre() const
Class PCB_PLOT_PARAMS handles plot parameters and options when plotting/printing a board...
class DIMENSION, a dimension (graphic item)
Definition: typeinfo.h:100
Class LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
virtual void SetViewport(const wxPoint &aOffset, double aIusPerDecimil, double aScale, bool aMirror)=0
Set the plot offset and scaling for the current plot.
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:101
unsigned printToolSummary(OUTPUTFORMATTER &aOut, bool aSummaryNPTH) const
Function printToolSummary prints m_toolListBuffer[] tools to aOut and returns total hole count...
void buildHolesList(DRILL_LAYER_PAIR aLayerPair, bool aGenerateNPTH_list)
Function BuildHolesList Create the list of holes and tools for a given board The list is sorted by in...
void Marker(const wxPoint &position, int diametre, unsigned aShapeId)
Draw a pattern shape number aShapeId, to coord position.
virtual void SetDefaultLineWidth(int width)=0
Set the default line width.
Base plotter engine class.
Definition: class_plotter.h:96
const wxPoint GetOffset()
Return the plot offset (usually the position of the auxiliary axis.
class MARKER_PCB, a marker used to show something
Definition: typeinfo.h:99
const int scale
static LIB_PART * dummy()
Used when a LIB_PART is not found in library to draw a dummy shape This component is a 400 mils squar...
virtual void FlashPadOval(const wxPoint &aPadPos, const wxSize &aSize, double aPadOrient, EDA_DRAW_MODE_T aTraceMode, void *aData)=0
virtual function FlashPadOval
virtual void SetPenNumber(int number)
int GetHPGLPenSpeed() const
Class EDA_RECT handles the component boundary box.
int GetX() const
The common library.
int GetWidth() const
void PlotTextePcb(TEXTE_PCB *pt_texte)
Class FILE_OUTPUTFORMATTER may be used for text file output.
Definition: richio.h:492
bool plotDrillMarks(PLOTTER *aPlotter)
Helper function.
This file is part of the common libary.
Basic classes for most KiCad items.
int PRINTF_FUNC Print(int nestLevel, const char *fmt,...)
Function Print formats and writes text to the output stream.
Definition: richio.cpp:404
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:91
std::vector< HOLE_INFO > m_holeListBuffer
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:774
virtual void SetColorMode(bool _color_mode)
wxString DateAndTime()
Function DateAndTime.
Definition: string.cpp:229
DLIST_ITERATOR_WRAPPER< BOARD_ITEM > Drawings()
Definition: class_board.h:251
#define min(a, b)
Definition: auxiliary.h:85
virtual void SetCurrentLineWidth(int width, void *aData=NULL)=0
Set the line width for the next drawing.
void PlotDrawSegment(DRAWSEGMENT *PtSegm)