KiCad PCB EDA Suite
Loading...
Searching...
No Matches
exporter_step.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) 2022 Mark Roszko <[email protected]>
5 * Copyright (C) 2016 Cirilo Bernardo <[email protected]>
6 * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include "exporter_step.h"
27#include <board.h>
29#include <footprint.h>
30#include <pcb_track.h>
31#include <pcb_shape.h>
32#include <pad.h>
33#include <zone.h>
34#include <fp_lib_table.h>
35#include "step_pcb_model.h"
36
37#include <pgm_base.h>
38#include <base_units.h>
39#include <filename_resolver.h>
40#include <trace_helpers.h>
41#include <project_pcb.h>
42
43#include <Message.hxx> // OpenCascade messenger
44#include <Message_PrinterOStream.hxx> // OpenCascade output messenger
45#include <Standard_Failure.hxx> // In open cascade
46
47#include <Standard_Version.hxx>
48
49#include <wx/crt.h>
50#include <wx/log.h>
51#include <core/profile.h> // To use GetRunningMicroSecs or another profiling utility
52
53#define OCC_VERSION_MIN 0x070500
54
55#if OCC_VERSION_HEX < OCC_VERSION_MIN
56#include <Message_Messenger.hxx>
57#endif
58
59
60void ReportMessage( const wxString& aMessage )
61{
62 wxPrintf( aMessage );
63 fflush( stdout ); // Force immediate printing (needed on mingw)
64}
65
66class KiCadPrinter : public Message_Printer
67{
68public:
69 KiCadPrinter( EXPORTER_STEP* aConverter ) : m_converter( aConverter ) {}
70
71protected:
72#if OCC_VERSION_HEX < OCC_VERSION_MIN
73 virtual void Send( const TCollection_ExtendedString& theString,
74 const Message_Gravity theGravity,
75 const Standard_Boolean theToPutEol ) const override
76 {
77 Send( TCollection_AsciiString( theString ), theGravity, theToPutEol );
78 }
79
80 virtual void Send( const TCollection_AsciiString& theString,
81 const Message_Gravity theGravity,
82 const Standard_Boolean theToPutEol ) const override
83#else
84 virtual void send( const TCollection_AsciiString& theString,
85 const Message_Gravity theGravity ) const override
86#endif
87 {
88 if( theGravity >= Message_Warning
89 || ( wxLog::IsAllowedTraceMask( traceKiCad2Step ) && theGravity == Message_Info ) )
90 {
91 ReportMessage( theString.ToCString() );
92
93#if OCC_VERSION_HEX < OCC_VERSION_MIN
94 if( theToPutEol )
95 ReportMessage( wxT( "\n" ) );
96#else
97 ReportMessage( wxT( "\n" ) );
98#endif
99 }
100
101 if( theGravity == Message_Warning )
103
104 if( theGravity >= Message_Alarm )
106
107 if( theGravity == Message_Fail )
109 }
110
111private:
113};
114
115
117{
118 switch( m_format )
119 {
120 case EXPORTER_STEP_PARAMS::FORMAT::STEP: return wxS( "step" ); break;
121 case EXPORTER_STEP_PARAMS::FORMAT::GLB: return wxS( "glb" ); break;
122 default: return wxEmptyString; // shouldn't happen
123 }
124}
125
127{
128 switch( m_format )
129 {
130 // honestly these names shouldn't be translated since they are mostly industry standard acronyms
131 case EXPORTER_STEP_PARAMS::FORMAT::STEP: return wxS( "STEP" ); break;
132 case EXPORTER_STEP_PARAMS::FORMAT::GLB: return wxS("Binary GLTF" ); break;
133 default: return wxEmptyString; // shouldn't happen
134 }
135}
136
137
139 m_params( aParams ),
140 m_error( false ),
141 m_fail( false ),
142 m_warn( false ),
143 m_board( aBoard ),
144 m_pcbModel( nullptr ),
145 m_boardThickness( DEFAULT_BOARD_THICKNESS_MM )
146{
147 m_solderMaskColor = COLOR4D( 0.08, 0.20, 0.14, 0.83 );
148 m_copperColor = COLOR4D( 0.7, 0.61, 0.0, 1.0 );
149
150 // Init m_pcbBaseName to the board short filename (no path, no ext)
151 // m_pcbName is used later to identify items in step file
152 wxFileName fn( aBoard->GetFileName() );
153 m_pcbBaseName = fn.GetName();
154
155 m_resolver = std::make_unique<FILENAME_RESOLVER>();
156 m_resolver->Set3DConfigDir( wxT( "" ) );
157 // needed to add the project to the search stack
158 m_resolver->SetProject( aBoard->GetProject() );
159 m_resolver->SetProgramBase( &Pgm() );
160}
161
162
164{
165}
166
167
169{
170 bool hasdata = false;
171
172 // Dump the pad holes into the PCB
173 for( PAD* pad : aFootprint->Pads() )
174 {
175 if( m_pcbModel->AddPadHole( pad, aOrigin ) )
176 hasdata = true;
177
178 if( ExportTracksAndVias() )
179 {
180 if( m_pcbModel->AddPadShape( pad, aOrigin ) )
181 hasdata = true;
182 }
183 }
184
185 // Build 3D shapes of the footprint graphic items on external layers:
186 if( ExportTracksAndVias() )
187 {
188 int maxError = m_board->GetDesignSettings().m_MaxError;
190 false, /* include text */
191 true, /* include shapes */
192 false /* include private items */ );
194 false, /* include text */
195 true, /* include shapes */
196 false /* include private items */ );
197 }
198
199 if( ( !(aFootprint->GetAttributes() & (FP_THROUGH_HOLE|FP_SMD)) ) && !m_params.m_includeUnspecified )
200 {
201 return hasdata;
202 }
203
204 if( ( aFootprint->GetAttributes() & FP_DNP ) && !m_params.m_includeDNP )
205 {
206 return hasdata;
207 }
208
209 // Prefetch the library for this footprint
210 // In case we need to resolve relative footprint paths
211 wxString libraryName = aFootprint->GetFPID().GetLibNickname();
212 wxString footprintBasePath = wxEmptyString;
213
214 double posX = aFootprint->GetPosition().x - aOrigin.x;
215 double posY = (aFootprint->GetPosition().y) - aOrigin.y;
216
217 if( m_board->GetProject() )
218 {
219 try
220 {
221 // FindRow() can throw an exception
222 const FP_LIB_TABLE_ROW* fpRow =
223 PROJECT_PCB::PcbFootprintLibs( m_board->GetProject() )->FindRow( libraryName, false );
224
225 if( fpRow )
226 footprintBasePath = fpRow->GetFullURI( true );
227 }
228 catch( ... )
229 {
230 // Do nothing if the libraryName is not found in lib table
231 }
232 }
233
234 // Exit early if we don't want to include footprint models
236 {
237 return hasdata;
238 }
239
240 VECTOR2D newpos( pcbIUScale.IUTomm( posX ), pcbIUScale.IUTomm( posY ) );
241
242 for( const FP_3DMODEL& fp_model : aFootprint->Models() )
243 {
244 if( !fp_model.m_Show || fp_model.m_Filename.empty() )
245
246 continue;
247
248 std::vector<wxString> searchedPaths;
249 wxString mname = m_resolver->ResolvePath( fp_model.m_Filename, footprintBasePath );
250
251
252 if( !wxFileName::FileExists( mname ) )
253 {
254 ReportMessage( wxString::Format( wxT( "Could not add 3D model to %s.\n"
255 "File not found: %s\n" ),
256 aFootprint->GetReference(), mname ) );
257 continue;
258 }
259
260 std::string fname( mname.ToUTF8() );
261 std::string refName( aFootprint->GetReference().ToUTF8() );
262 try
263 {
264 bool bottomSide = aFootprint->GetLayer() == B_Cu;
265
266 // the rotation is stored in degrees but opencascade wants radians
267 VECTOR3D modelRot = fp_model.m_Rotation;
268 modelRot *= M_PI;
269 modelRot /= 180.0;
270
271 if( m_pcbModel->AddComponent( fname, refName, bottomSide,
272 newpos,
273 aFootprint->GetOrientation().AsRadians(),
274 fp_model.m_Offset, modelRot,
275 fp_model.m_Scale, m_params.m_substModels ) )
276 {
277 hasdata = true;
278 }
279 }
280 catch( const Standard_Failure& e )
281 {
282 ReportMessage( wxString::Format( wxT( "Could not add 3D model to %s.\n"
283 "OpenCASCADE error: %s\n" ),
284 aFootprint->GetReference(), e.GetMessageString() ) );
285 }
286
287 }
288
289 return hasdata;
290}
291
292
294{
295 if( aTrack->Type() == PCB_VIA_T )
296 {
297 return m_pcbModel->AddViaShape( static_cast<const PCB_VIA*>( aTrack ), aOrigin );
298 }
299
300 PCB_LAYER_ID pcblayer = aTrack->GetLayer();
301
302 if( pcblayer != F_Cu && pcblayer != B_Cu )
303 return false;
304
305 if( aTrack->Type() == PCB_ARC_T )
306 {
307 int maxError = m_board->GetDesignSettings().m_MaxError;
308
309 if( pcblayer == F_Cu )
310 aTrack->TransformShapeToPolygon( m_top_copper_shapes, pcblayer, 0, maxError, ERROR_INSIDE );
311 else
312 aTrack->TransformShapeToPolygon( m_bottom_copper_shapes, pcblayer, 0, maxError, ERROR_INSIDE );
313 }
314 else
315 m_pcbModel->AddTrackSegment( aTrack, aOrigin );
316
317 return true;
318}
319
320
322{
323 for( ZONE* zone : m_board->Zones() )
324 {
325 for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
326 {
327 if( layer == F_Cu || layer == B_Cu )
328 {
329 SHAPE_POLY_SET copper_shape;
330 zone->TransformSolidAreasShapesToPolygon( layer, copper_shape );
332
333 m_pcbModel->AddCopperPolygonShapes( &copper_shape, layer == F_Cu, aOrigin, false );
334 }
335 }
336 }
337}
338
339
341{
342 PCB_SHAPE* graphic = dynamic_cast<PCB_SHAPE*>( aItem );
343
344 if( ! graphic )
345 return false;
346
347 PCB_LAYER_ID pcblayer = graphic->GetLayer();
348
349 if( pcblayer != F_Cu && pcblayer != B_Cu )
350 return false;
351
352 SHAPE_POLY_SET copper_shapes;
353 int maxError = m_board->GetDesignSettings().m_MaxError;
354
355
356 if( pcblayer == F_Cu )
357 graphic->TransformShapeToPolygon( m_top_copper_shapes, pcblayer, 0,
358 maxError, ERROR_INSIDE );
359 else
360 graphic->TransformShapeToPolygon( m_bottom_copper_shapes, pcblayer, 0,
361 maxError, ERROR_INSIDE );
362
363 return true;
364}
365
366
368{
369 if( m_pcbModel )
370 return true;
371
372 SHAPE_POLY_SET pcbOutlines; // stores the board main outlines
373
374 if( !m_board->GetBoardPolygonOutlines( pcbOutlines,
375 /* error handler */ nullptr,
376 /* allows use arcs in outlines */ true ) )
377 {
378 wxLogWarning( _( "Board outline is malformed. Run DRC for a full analysis." ) );
379 }
380
381 VECTOR2D origin;
382
383 // Determine the coordinate system reference:
384 // Precedence of reference point is Drill Origin > Grid Origin > User Offset
387 else if( m_params.m_useGridOrigin )
389 else
390 origin = m_params.m_origin;
391
392 m_pcbModel = std::make_unique<STEP_PCB_MODEL>( m_pcbBaseName );
393
394 // TODO: Handle when top & bottom soldermask colours are different...
397
398 m_pcbModel->SetPCBThickness( m_boardThickness );
399
400 // Note: m_params.m_BoardOutlinesChainingEpsilon is used only to build the board outlines,
401 // not to set OCC chaining epsilon (much smaller)
402 //
403 // Set the min distance between 2 points for OCC to see these 2 points as merged
404 // OCC_MAX_DISTANCE_TO_MERGE_POINTS is acceptable for OCC, otherwise there are issues
405 // to handle the shapes chaining on copper layers, because the Z dist is 0.035 mm and the
406 // min dist must be much smaller (we use 0.001 mm giving good results)
407 m_pcbModel->OCCSetMergeMaxDistance( OCC_MAX_DISTANCE_TO_MERGE_POINTS );
408
410
411 // For copper layers, only pads and tracks are added, because adding everything on copper
412 // generate unreasonable file sizes and take a unreasonable calculation time.
413 for( FOOTPRINT* fp : m_board->Footprints() )
414 buildFootprint3DShapes( fp, origin );
415
416 if( ExportTracksAndVias() )
417 {
418 for( PCB_TRACK* track : m_board->Tracks() )
419 buildTrack3DShape( track, origin );
420
421 for( BOARD_ITEM* item : m_board->Drawings() )
422 buildGraphic3DShape( item, origin );
423 }
424
425 m_pcbModel->AddCopperPolygonShapes( &m_top_copper_shapes, true, origin, true );
426 m_pcbModel->AddCopperPolygonShapes( &m_bottom_copper_shapes, false, origin, true );
427
429 {
430 buildZones3DShape( origin );
431 }
432
433 ReportMessage( wxT( "Create PCB solid model\n" ) );
434
435 wxString msg;
436 msg.Printf( wxT( "Board outline: find %d initial points\n" ), pcbOutlines.FullPointCount() );
437 ReportMessage( msg );
438
439 if( !m_pcbModel->CreatePCB( pcbOutlines, origin ) )
440 {
441 ReportMessage( wxT( "could not create PCB solid model\n" ) );
442 return false;
443 }
444
445 return true;
446}
447
448
450{
452
454
455 if( bds.GetStackupDescriptor().GetCount() )
456 {
457 int thickness = 0;
458
459 for( BOARD_STACKUP_ITEM* item : bds.GetStackupDescriptor().GetList() )
460 {
461 switch( item->GetType() )
462 {
464 // Dielectric can have sub-layers. Layer 0 is the main layer
465 // Not frequent, but possible
466 for( int idx = 0; idx < item->GetSublayersCount(); idx++ )
467 thickness += item->GetThickness( idx );
468
469 break;
470
472 if( item->IsEnabled() )
473 thickness += item->GetThickness();
474
475 break;
476
477 default:
478 break;
479 }
480 }
481
482 if( thickness > 0 )
483 m_boardThickness = pcbIUScale.IUTomm( thickness );
484 }
485}
486
487
489{
490 // Display the export time, for statistics
491 unsigned stats_startExportTime = GetRunningMicroSecs();
492
493 // setup opencascade message log
494 Message::DefaultMessenger()->RemovePrinters( STANDARD_TYPE( Message_PrinterOStream ) );
495 Message::DefaultMessenger()->AddPrinter( new KiCadPrinter( this ) );
496
497 ReportMessage( _( "Determining PCB data\n" ) );
499 wxString msg;
500 msg.Printf( _( "Board Thickness from stackup: %.3f mm\n" ), m_boardThickness );
501 ReportMessage( msg );
502
503 if( m_params.m_outputFile.IsEmpty() )
504 {
505 wxFileName fn = m_board->GetFileName();
506 fn.SetName( fn.GetName() );
507 fn.SetExt( m_params.GetDefaultExportExtension() );
508
509 m_params.m_outputFile = fn.GetFullName();
510 }
511
512 try
513 {
514 ReportMessage( wxString::Format( _( "Build %s data\n" ), m_params.GetFormatName() ) );
515
516 if( !buildBoard3DShapes() )
517 {
518 ReportMessage( _( "\n** Error building STEP board model. Export aborted. **\n" ) );
519 return false;
520 }
521
522 ReportMessage( wxString::Format( _( "Writing %s file\n" ), m_params.GetFormatName() ) );
523
524 bool success = true;
526 success = m_pcbModel->WriteSTEP( m_outputFile );
528 success = m_pcbModel->WriteGLTF( m_outputFile );
529
530 if( !success )
531 {
532 ReportMessage( wxString::Format( _( "\n** Error writing %s file. **\n" ),
534 return false;
535 }
536 else
537 {
538 ReportMessage( wxString::Format( _( "%s file '%s' created.\n" ),
540 }
541 }
542 catch( const Standard_Failure& e )
543 {
544 ReportMessage( e.GetMessageString() );
545 ReportMessage( wxString::Format( _( "\n** Error exporting %s file. Export aborted. **\n" ),
547 return false;
548 }
549 catch( ... )
550 {
551 ReportMessage( wxString::Format( _( "\n** Error exporting %s file. Export aborted. **\n" ),
553 return false;
554 }
555
556 if( m_fail || m_error )
557 {
558 if( m_fail )
559 {
560 msg = wxString::Format( _( "Unable to create %s file.\n"
561 "Check that the board has a valid outline and models." ),
563 }
564 else if( m_error || m_warn )
565 {
566 msg = wxString::Format( _( "%s file has been created, but there are warnings." ),
568 }
569
570 ReportMessage( msg );
571 }
572
573 // Display calculation time in seconds
574 double calculation_time = (double)( GetRunningMicroSecs() - stats_startExportTime) / 1e6;
575 ReportMessage( wxString::Format( _( "\nExport time %.3f s\n" ), calculation_time ) );
576
577 return true;
578}
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
#define DEFAULT_BOARD_THICKNESS_MM
@ BS_ITEM_TYPE_COPPER
Definition: board_stackup.h:43
@ BS_ITEM_TYPE_DIELECTRIC
Definition: board_stackup.h:44
Container for design settings for a BOARD object.
const VECTOR2I & GetGridOrigin()
const VECTOR2I & GetAuxOrigin()
BOARD_STACKUP & GetStackupDescriptor()
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:77
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:204
Manage one layer needed to make a physical board.
Definition: board_stackup.h:91
const std::vector< BOARD_STACKUP_ITEM * > & GetList() const
int GetCount() const
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:271
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr, bool aAllowUseArcsInPolygons=false)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
Definition: board.cpp:2056
ZONES & Zones()
Definition: board.h:319
FOOTPRINTS & Footprints()
Definition: board.h:313
TRACKS & Tracks()
Definition: board.h:310
const wxString & GetFileName() const
Definition: board.h:308
DRAWINGS & Drawings()
Definition: board.h:316
PROJECT * GetProject() const
Definition: board.h:449
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:731
double AsRadians() const
Definition: eda_angle.h:153
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
wxString GetDefaultExportExtension()
void buildZones3DShape(VECTOR2D aOrigin)
KIGFX::COLOR4D m_solderMaskColor
SHAPE_POLY_SET m_top_copper_shapes
SHAPE_POLY_SET m_bottom_copper_shapes
wxString m_outputFile
Definition: exporter_step.h:96
bool buildGraphic3DShape(BOARD_ITEM *aItem, VECTOR2D aOrigin)
EXPORTER_STEP_PARAMS m_params
EXPORTER_STEP(BOARD *aBoard, const EXPORTER_STEP_PARAMS &aParams)
wxString m_pcbBaseName
the name of the project (board short filename (no path, no ext) used to identify items in step file
bool buildFootprint3DShapes(FOOTPRINT *aFootprint, VECTOR2D aOrigin)
std::unique_ptr< FILENAME_RESOLVER > m_resolver
bool ExportTracksAndVias()
Return rue to export tracks and vias on top and bottom copper layers.
bool buildBoard3DShapes()
std::unique_ptr< STEP_PCB_MODEL > m_pcbModel
void calculatePcbThickness()
bool buildTrack3DShape(PCB_TRACK *aTrack, VECTOR2D aOrigin)
KIGFX::COLOR4D m_copperColor
double m_boardThickness
EDA_ANGLE GetOrientation() const
Definition: footprint.h:209
int GetAttributes() const
Definition: footprint.h:277
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: footprint.h:218
PADS & Pads()
Definition: footprint.h:188
void TransformFPShapesToPolySet(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool aIncludeText=true, bool aIncludeShapes=true, bool aIncludePrivateItems=false) const
Generate shapes of graphic items (outlines) on layer aLayer as polygons and adds these polygons to aB...
Definition: footprint.cpp:3055
const LIB_ID & GetFPID() const
Definition: footprint.h:230
std::vector< FP_3DMODEL > & Models()
Definition: footprint.h:202
const wxString & GetReference() const
Definition: footprint.h:556
VECTOR2I GetPosition() const override
Definition: footprint.h:206
Hold a record identifying a library accessed by the appropriate footprint library PLUGIN object in th...
Definition: fp_lib_table.h:41
const FP_LIB_TABLE_ROW * FindRow(const wxString &aNickName, bool aCheckIfEnabled=false)
Return an FP_LIB_TABLE_ROW if aNickName is found in this table or in any chained fall back table frag...
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
double r
Red component.
Definition: color4d.h:376
double g
Green component.
Definition: color4d.h:377
double b
Blue component.
Definition: color4d.h:378
EXPORTER_STEP * m_converter
KiCadPrinter(EXPORTER_STEP *aConverter)
virtual void Send(const TCollection_ExtendedString &theString, const Message_Gravity theGravity, const Standard_Boolean theToPutEol) const override
virtual void Send(const TCollection_AsciiString &theString, const Message_Gravity theGravity, const Standard_Boolean theToPutEol) const override
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:87
const wxString GetFullURI(bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
Definition: pad.h:58
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the shape to a closed polygon.
Definition: pcb_shape.cpp:568
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: pcb_shape.h:67
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the track shape to a closed polygon.
Definition: pcb_track.cpp:1230
static FP_LIB_TABLE * PcbFootprintLibs(PROJECT *aProject)
Return the table of footprint libraries without Kiway.
Definition: project_pcb.cpp:37
Represent a set of closed polygons.
int FullPointCount() const
Return the number of points in the shape poly set.
void Unfracture(POLYGON_MODE aFastMode)
Convert a single outline slitted ("fractured") polygon into a set ouf outlines with holes.
Handle a list of polygons defining a copper zone.
Definition: zone.h:72
#define _(s)
void ReportMessage(const wxString &aMessage)
@ FP_SMD
Definition: footprint.h:73
@ FP_DNP
Definition: footprint.h:80
@ FP_THROUGH_HOLE
Definition: footprint.h:72
@ ERROR_INSIDE
const wxChar *const traceKiCad2Step
Flag to enable KiCad2Step debug tracing.
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ B_Cu
Definition: layer_ids.h:96
@ F_Cu
Definition: layer_ids.h:65
see class PGM_BASE
unsigned GetRunningMicroSecs()
An alternate way to calculate an elapsed time (in microsecondes) to class PROF_COUNTER.
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:115
static constexpr double OCC_MAX_DISTANCE_TO_MERGE_POINTS
Default distance between points to treat them as separate ones (mm) 0.001 mm or less is a reasonable ...
constexpr double IUTomm(int iu) const
Definition: base_units.h:87
wxLogTrace helper definitions.
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:94
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:95