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-2024 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 <advanced_config.h>
28#include <board.h>
30#include <footprint.h>
31#include <pcb_textbox.h>
32#include <pcb_track.h>
33#include <pcb_shape.h>
34#include <pad.h>
35#include <zone.h>
36#include <fp_lib_table.h>
37#include "step_pcb_model.h"
38
39#include <pgm_base.h>
40#include <base_units.h>
41#include <filename_resolver.h>
42#include <trace_helpers.h>
43#include <project_pcb.h>
45
46#include <Message.hxx> // OpenCascade messenger
47#include <Message_PrinterOStream.hxx> // OpenCascade output messenger
48#include <Standard_Failure.hxx> // In open cascade
49
50#include <Standard_Version.hxx>
51
52#include <wx/crt.h>
53#include <wx/log.h>
54#include <core/profile.h> // To use GetRunningMicroSecs or another profiling utility
55
56#define OCC_VERSION_MIN 0x070500
57
58#if OCC_VERSION_HEX < OCC_VERSION_MIN
59#include <Message_Messenger.hxx>
60#endif
61
62
63void ReportMessage( const wxString& aMessage )
64{
65 wxPrintf( aMessage );
66 fflush( stdout ); // Force immediate printing (needed on mingw)
67}
68
69class KiCadPrinter : public Message_Printer
70{
71public:
72 KiCadPrinter( EXPORTER_STEP* aConverter ) : m_converter( aConverter ) {}
73
74protected:
75#if OCC_VERSION_HEX < OCC_VERSION_MIN
76 virtual void Send( const TCollection_ExtendedString& theString,
77 const Message_Gravity theGravity,
78 const Standard_Boolean theToPutEol ) const override
79 {
80 Send( TCollection_AsciiString( theString ), theGravity, theToPutEol );
81 }
82
83 virtual void Send( const TCollection_AsciiString& theString,
84 const Message_Gravity theGravity,
85 const Standard_Boolean theToPutEol ) const override
86#else
87 virtual void send( const TCollection_AsciiString& theString,
88 const Message_Gravity theGravity ) const override
89#endif
90 {
91 if( theGravity >= Message_Warning
92 || ( wxLog::IsAllowedTraceMask( traceKiCad2Step ) && theGravity == Message_Info ) )
93 {
94 ReportMessage( theString.ToCString() );
95
96#if OCC_VERSION_HEX < OCC_VERSION_MIN
97 if( theToPutEol )
98 ReportMessage( wxT( "\n" ) );
99#else
100 ReportMessage( wxT( "\n" ) );
101#endif
102 }
103
104 if( theGravity == Message_Warning )
106
107 if( theGravity >= Message_Alarm )
109
110 if( theGravity == Message_Fail )
112 }
113
114private:
116};
117
118
120 m_params( aParams ),
121 m_error( false ),
122 m_fail( false ),
123 m_warn( false ),
124 m_board( aBoard ),
125 m_pcbModel( nullptr )
126{
127 m_copperColor = COLOR4D( 0.7, 0.61, 0.0, 1.0 );
128
130 m_padColor = COLOR4D( 0.50, 0.50, 0.50, 1.0 );
131 else
133
134 // TODO: make configurable
136
137 // Init m_pcbBaseName to the board short filename (no path, no ext)
138 // m_pcbName is used later to identify items in step file
139 wxFileName fn( aBoard->GetFileName() );
140 m_pcbBaseName = fn.GetName();
141
142 // Remove the autosave prefix
144
145 m_resolver = std::make_unique<FILENAME_RESOLVER>();
146 m_resolver->Set3DConfigDir( wxT( "" ) );
147 // needed to add the project to the search stack
148 m_resolver->SetProject( aBoard->GetProject() );
149 m_resolver->SetProgramBase( &Pgm() );
150}
151
152
154{
155}
156
157
159{
160 bool hasdata = false;
161 std::vector<PAD*> padsMatchingNetFilter;
162 int maxError = m_board->GetDesignSettings().m_MaxError;
163
164 // Dump the pad holes into the PCB
165 for( PAD* pad : aFootprint->Pads() )
166 {
167 std::shared_ptr<SHAPE_SEGMENT> holeShape = pad->GetEffectiveHoleShape();
168
169 SHAPE_POLY_SET holePoly;
170 holeShape->TransformToPolygon( holePoly, maxError, ERROR_INSIDE );
171
172 for( PCB_LAYER_ID pcblayer : pad->GetLayerSet().Seq() )
173 {
174 if( pad->IsOnLayer( pcblayer ) )
175 m_poly_holes[pcblayer].Append( holePoly );
176 }
177
178 if( pad->HasHole() )
179 {
180 int platingThickness = pad->GetAttribute() == PAD_ATTRIB::PTH ? m_platingThickness : 0;
181
182 if( m_pcbModel->AddHole( *holeShape, platingThickness, F_Cu, B_Cu, false, aOrigin ) )
183 hasdata = true;
184
186 //if( m_layersToExport.Contains( F_SilkS ) || m_layersToExport.Contains( B_SilkS ) )
187 //{
188 // m_poly_holes[F_SilkS].Append( holePoly );
189 // m_poly_holes[B_SilkS].Append( holePoly );
190 //}
191 }
192
193 if( !m_params.m_NetFilter.IsEmpty() && !pad->GetNetname().Matches( m_params.m_NetFilter ) )
194 continue;
195
197 {
198 if( m_pcbModel->AddPadShape( pad, aOrigin, false ) )
199 hasdata = true;
200
202 {
203 for( PCB_LAYER_ID pcblayer : pad->GetLayerSet().Seq() )
204 {
205 if( pcblayer != F_Mask && pcblayer != B_Mask )
206 continue;
207
208 SHAPE_POLY_SET poly;
209 PCB_LAYER_ID cuLayer = ( pcblayer == F_Mask ) ? F_Cu : B_Cu;
210 pad->TransformShapeToPolygon( poly, cuLayer,
211 pad->GetSolderMaskExpansion( cuLayer ), maxError,
212 ERROR_INSIDE );
213
214 m_poly_shapes[pcblayer].Append( poly );
215 }
216 }
217 }
218
219 padsMatchingNetFilter.push_back( pad );
220 }
221
222 // Build 3D shapes of the footprint graphic items:
223 for( PCB_LAYER_ID pcblayer : m_layersToExport.Seq() )
224 {
225 if( IsCopperLayer( pcblayer ) && !m_params.m_ExportTracksVias )
226 continue;
227
228 SHAPE_POLY_SET buffer;
229
230 aFootprint->TransformFPShapesToPolySet( buffer, pcblayer, 0, maxError, ERROR_INSIDE,
231 true, /* include text */
232 true, /* include shapes */
233 false /* include private items */ );
234
235 if( m_params.m_NetFilter.IsEmpty() || !IsCopperLayer( pcblayer ) )
236 {
237 m_poly_shapes[pcblayer].Append( buffer );
238 }
239 else
240 {
241 // Only add shapes colliding with any matching pads
242 for( const SHAPE_POLY_SET::POLYGON& poly : buffer.CPolygons() )
243 {
244 for( PAD* pad : padsMatchingNetFilter )
245 {
246 if( !pad->IsOnLayer( pcblayer ) )
247 continue;
248
249 std::shared_ptr<SHAPE_POLY_SET> padPoly = pad->GetEffectivePolygon( pcblayer );
250 SHAPE_POLY_SET gfxPoly( poly );
251
252 if( padPoly->Collide( &gfxPoly ) )
253 {
254 m_poly_shapes[pcblayer].Append( gfxPoly );
255 break;
256 }
257 }
258 }
259 }
260 }
261
262 if( ( !(aFootprint->GetAttributes() & (FP_THROUGH_HOLE|FP_SMD)) ) && !m_params.m_IncludeUnspecified )
263 {
264 return hasdata;
265 }
266
267 if( ( aFootprint->GetAttributes() & FP_DNP ) && !m_params.m_IncludeDNP )
268 {
269 return hasdata;
270 }
271
272 // Prefetch the library for this footprint
273 // In case we need to resolve relative footprint paths
274 wxString libraryName = aFootprint->GetFPID().GetLibNickname();
275 wxString footprintBasePath = wxEmptyString;
276
277 double posX = aFootprint->GetPosition().x - aOrigin.x;
278 double posY = (aFootprint->GetPosition().y) - aOrigin.y;
279
280 if( m_board->GetProject() )
281 {
282 try
283 {
284 // FindRow() can throw an exception
285 const FP_LIB_TABLE_ROW* fpRow =
286 PROJECT_PCB::PcbFootprintLibs( m_board->GetProject() )->FindRow( libraryName, false );
287
288 if( fpRow )
289 footprintBasePath = fpRow->GetFullURI( true );
290 }
291 catch( ... )
292 {
293 // Do nothing if the libraryName is not found in lib table
294 }
295 }
296
297 // Exit early if we don't want to include footprint models
299 {
300 return hasdata;
301 }
302
303 bool componentFilter = !m_params.m_ComponentFilter.IsEmpty();
304 std::vector<wxString> componentFilterPatterns;
305
306 if( componentFilter )
307 {
308 wxStringTokenizer tokenizer( m_params.m_ComponentFilter, wxS( "," ), wxTOKEN_STRTOK );
309
310 while( tokenizer.HasMoreTokens() )
311 componentFilterPatterns.push_back( tokenizer.GetNextToken().Trim( false ) );
312
313 bool found = false;
314
315 for( const wxString& pattern : componentFilterPatterns )
316 {
317 if( aFootprint->GetReference().Matches( pattern ) )
318 {
319 found = true;
320 break;
321 }
322 }
323
324 if( !found )
325 return hasdata;
326 }
327
328 VECTOR2D newpos( pcbIUScale.IUTomm( posX ), pcbIUScale.IUTomm( posY ) );
329
330 for( const FP_3DMODEL& fp_model : aFootprint->Models() )
331 {
332 if( !fp_model.m_Show || fp_model.m_Filename.empty() )
333 continue;
334
335 std::vector<wxString> searchedPaths;
336 wxString mname = m_resolver->ResolvePath( fp_model.m_Filename, footprintBasePath, aFootprint );
337
338
339 if( mname.empty() || !wxFileName::FileExists( mname ) )
340 {
341 // the error path will return an empty name sometimes, at least report back the original filename
342 if( mname.empty() )
343 mname = fp_model.m_Filename;
344
345 ReportMessage( wxString::Format( wxT( "Could not add 3D model to %s.\n"
346 "File not found: %s\n" ),
347 aFootprint->GetReference(), mname ) );
348 continue;
349 }
350
351 std::string fname( mname.ToUTF8() );
352 std::string refName( aFootprint->GetReference().ToUTF8() );
353 try
354 {
355 bool bottomSide = aFootprint->GetLayer() == B_Cu;
356
357 // the rotation is stored in degrees but opencascade wants radians
358 VECTOR3D modelRot = fp_model.m_Rotation;
359 modelRot *= M_PI;
360 modelRot /= 180.0;
361
362 if( m_pcbModel->AddComponent( fname, refName, bottomSide,
363 newpos,
364 aFootprint->GetOrientation().AsRadians(),
365 fp_model.m_Offset, modelRot,
366 fp_model.m_Scale, m_params.m_SubstModels ) )
367 {
368 hasdata = true;
369 }
370 }
371 catch( const Standard_Failure& e )
372 {
373 ReportMessage( wxString::Format( wxT( "Could not add 3D model to %s.\n"
374 "OpenCASCADE error: %s\n" ),
375 aFootprint->GetReference(), e.GetMessageString() ) );
376 }
377
378 }
379
380 return hasdata;
381}
382
383
385{
386 if( !m_params.m_NetFilter.IsEmpty() && !aTrack->GetNetname().Matches( m_params.m_NetFilter ) )
387 return true;
388
389 int maxError = m_board->GetDesignSettings().m_MaxError;
390
391 if( aTrack->Type() == PCB_VIA_T )
392 {
393 PCB_VIA* via = static_cast<PCB_VIA*>( aTrack );
394
395 std::shared_ptr<SHAPE_SEGMENT> holeShape = via->GetEffectiveHoleShape();
396 SHAPE_POLY_SET holePoly;
397 holeShape->TransformToPolygon( holePoly, maxError, ERROR_INSIDE );
398
399 LSET layers( via->GetLayerSet() & m_layersToExport );
400
401 for( PCB_LAYER_ID pcblayer : layers.Seq() )
402 {
403 const std::shared_ptr<SHAPE>& shape = via->GetEffectiveShape( pcblayer );
404
405 SHAPE_POLY_SET poly;
406 shape->TransformToPolygon( poly, maxError, ERROR_INSIDE );
407 m_poly_shapes[pcblayer].Append( poly );
408 m_poly_holes[pcblayer].Append( holePoly );
409 }
410
412 //if( m_layersToExport.Contains( F_SilkS ) || m_layersToExport.Contains( B_SilkS ) )
413 //{
414 // m_poly_holes[F_SilkS].Append( holePoly );
415 // m_poly_holes[B_SilkS].Append( holePoly );
416 //}
417
418 PCB_LAYER_ID top_layer, bot_layer;
419 via->LayerPair( &top_layer, &bot_layer );
420
421 m_pcbModel->AddHole( *holeShape, m_platingThickness, top_layer, bot_layer, true, aOrigin );
422 m_pcbModel->AddBarrel( *holeShape, top_layer, bot_layer, true, aOrigin );
423
424 return true;
425 }
426
427 PCB_LAYER_ID pcblayer = aTrack->GetLayer();
428
429 if( !m_layersToExport.Contains( pcblayer ) )
430 return false;
431
432 aTrack->TransformShapeToPolygon( m_poly_shapes[pcblayer], pcblayer, 0, maxError, ERROR_INSIDE );
433
434 return true;
435}
436
437
439{
440 for( ZONE* zone : m_board->Zones() )
441 {
442 LSET layers = zone->GetLayerSet();
443
444 if( ( layers & LSET::AllCuMask() ).count() && !m_params.m_NetFilter.IsEmpty()
445 && !zone->GetNetname().Matches( m_params.m_NetFilter ) )
446 {
447 continue;
448 }
449
450 for( PCB_LAYER_ID layer : layers.Seq() )
451 {
452 SHAPE_POLY_SET fill_shape;
453 zone->TransformSolidAreasShapesToPolygon( layer, fill_shape );
455
456 fill_shape.SimplifyOutlines( ADVANCED_CFG::GetCfg().m_TriangulateSimplificationLevel );
457
458 m_poly_shapes[layer].Append( fill_shape );
459 }
460 }
461}
462
463
465{
466 PCB_LAYER_ID pcblayer = aItem->GetLayer();
467
468 if( !m_layersToExport.Contains( pcblayer ) )
469 return false;
470
471 int maxError = m_board->GetDesignSettings().m_MaxError;
472
473 switch( aItem->Type() )
474 {
475 case PCB_SHAPE_T:
476 {
477 PCB_SHAPE* graphic = static_cast<PCB_SHAPE*>( aItem );
478
479 if( IsCopperLayer( pcblayer ) && !m_params.m_NetFilter.IsEmpty()
480 && !graphic->GetNetname().Matches( m_params.m_NetFilter ) )
481 {
482 return true;
483 }
484
485 graphic->TransformShapeToPolygon( m_poly_shapes[pcblayer], pcblayer, 0, maxError,
486 ERROR_INSIDE );
487
488 break;
489 }
490
491 case PCB_TEXT_T:
492 {
493 PCB_TEXT* text = static_cast<PCB_TEXT*>( aItem );
494
495 text->TransformTextToPolySet( m_poly_shapes[pcblayer], 0, maxError, ERROR_INSIDE );
496 break;
497 }
498
499 case PCB_TEXTBOX_T:
500 {
501 PCB_TEXTBOX* textbox = static_cast<PCB_TEXTBOX*>( aItem );
502
503 textbox->TransformTextToPolySet( m_poly_shapes[pcblayer], 0, maxError, ERROR_INSIDE );
504 break;
505 }
506
507 case PCB_TABLE_T:
508 // JEY TODO: tables
509 break;
510
511 default: wxFAIL_MSG( "buildGraphic3DShape: unhandled item type" );
512 }
513
514 return true;
515}
516
517
519{
520 // Specialize the STEP_PCB_MODEL generator for specific output format
521 // it can have some minor actions for the generator
522 switch( m_params.m_Format )
523 {
525 m_pcbModel->SpecializeVariant( OUTPUT_FORMAT::FMT_OUT_STEP );
526 break;
527
529 m_pcbModel->SpecializeVariant( OUTPUT_FORMAT::FMT_OUT_BREP );
530 break;
531
533 m_pcbModel->SpecializeVariant( OUTPUT_FORMAT::FMT_OUT_XAO );
534 break;
535
537 m_pcbModel->SpecializeVariant( OUTPUT_FORMAT::FMT_OUT_GLTF );
538 break;
539
541 m_pcbModel->SpecializeVariant( OUTPUT_FORMAT::FMT_OUT_PLY );
542 break;
543
545 m_pcbModel->SpecializeVariant( OUTPUT_FORMAT::FMT_OUT_STL );
546 break;
547
548 default:
549 m_pcbModel->SpecializeVariant( OUTPUT_FORMAT::FMT_OUT_UNKNOWN );
550 break;
551 }
552}
553
554
556{
557 if( m_pcbModel )
558 return true;
559
560 SHAPE_POLY_SET pcbOutlines; // stores the board main outlines
561
562 if( !m_board->GetBoardPolygonOutlines( pcbOutlines,
563 /* error handler */ nullptr,
564 /* allows use arcs in outlines */ true ) )
565 {
566 wxLogWarning( _( "Board outline is malformed. Run DRC for a full analysis." ) );
567 }
568
569 VECTOR2D origin;
570
571 // Determine the coordinate system reference:
572 // Precedence of reference point is Drill Origin > Grid Origin > User Offset
575 else if( m_params.m_UseGridOrigin )
577 else
578 origin = m_params.m_Origin;
579
580 m_pcbModel = std::make_unique<STEP_PCB_MODEL>( m_pcbBaseName );
581
583
585 m_pcbModel->SetPadColor( m_padColor.r, m_padColor.g, m_padColor.b );
586
587 m_pcbModel->SetStackup( m_board->GetStackupOrDefault() );
588 m_pcbModel->SetEnabledLayers( m_layersToExport );
589 m_pcbModel->SetFuseShapes( m_params.m_FuseShapes );
590 m_pcbModel->SetNetFilter( m_params.m_NetFilter );
591
592 // Note: m_params.m_BoardOutlinesChainingEpsilon is used only to build the board outlines,
593 // not to set OCC chaining epsilon (much smaller)
594 //
595 // Set the min distance between 2 points for OCC to see these 2 points as merged
596 // OCC_MAX_DISTANCE_TO_MERGE_POINTS is acceptable for OCC, otherwise there are issues
597 // to handle the shapes chaining on copper layers, because the Z dist is 0.035 mm and the
598 // min dist must be much smaller (we use 0.001 mm giving good results)
599 m_pcbModel->OCCSetMergeMaxDistance( OCC_MAX_DISTANCE_TO_MERGE_POINTS );
600
602
603 // For copper layers, only pads and tracks are added, because adding everything on copper
604 // generate unreasonable file sizes and take a unreasonable calculation time.
605 for( FOOTPRINT* fp : m_board->Footprints() )
606 buildFootprint3DShapes( fp, origin );
607
609 {
610 for( PCB_TRACK* track : m_board->Tracks() )
611 buildTrack3DShape( track, origin );
612 }
613
614 for( BOARD_ITEM* item : m_board->Drawings() )
615 buildGraphic3DShape( item, origin );
616
618 {
619 buildZones3DShape( origin );
620 }
621
622 SHAPE_POLY_SET pcbOutlinesNoArcs = pcbOutlines;
623 pcbOutlinesNoArcs.ClearArcs();
624
625 for( PCB_LAYER_ID pcblayer : m_layersToExport.Seq() )
626 {
627 SHAPE_POLY_SET poly = m_poly_shapes[pcblayer];
629
630 poly.SimplifyOutlines( pcbIUScale.mmToIU( 0.003 ) );
632
633 SHAPE_POLY_SET holes = m_poly_holes[pcblayer];
635
636 // Mask layer is negative
637 if( pcblayer == F_Mask || pcblayer == B_Mask )
638 {
639 SHAPE_POLY_SET mask = pcbOutlinesNoArcs;
640
643
644 poly = mask;
645 }
646 else
647 {
648 // Subtract holes
650
651 // Clip to board outline
653 }
654
655 m_pcbModel->AddPolygonShapes( &poly, pcblayer, origin );
656 }
657
658 ReportMessage( wxT( "Create PCB solid model\n" ) );
659
660 wxString msg;
661 msg.Printf( wxT( "Board outline: find %d initial points\n" ), pcbOutlines.FullPointCount() );
662 ReportMessage( msg );
663
664 if( !m_pcbModel->CreatePCB( pcbOutlines, origin, m_params.m_ExportBoardBody ) )
665 {
666 ReportMessage( wxT( "could not create PCB solid model\n" ) );
667 return false;
668 }
669
670 return true;
671}
672
673
675{
676 // Display the export time, for statistics
677 int64_t stats_startExportTime = GetRunningMicroSecs();
678
679 // setup opencascade message log
680 Message::DefaultMessenger()->RemovePrinters( STANDARD_TYPE( Message_PrinterOStream ) );
681 Message::DefaultMessenger()->AddPrinter( new KiCadPrinter( this ) );
682
683 ReportMessage( _( "Determining PCB data\n" ) );
684
685 if( m_params.m_OutputFile.IsEmpty() )
686 {
687 wxFileName fn = m_board->GetFileName();
688 fn.SetName( fn.GetName() );
689 fn.SetExt( m_params.GetDefaultExportExtension() );
690
691 m_params.m_OutputFile = fn.GetFullName();
692 }
693
695
698
700 {
703 }
704
706 {
709 }
710
712
713 try
714 {
715 ReportMessage( wxString::Format( _( "Build %s data\n" ), m_params.GetFormatName() ) );
716
717 if( !buildBoard3DShapes() )
718 {
719 ReportMessage( _( "\n** Error building STEP board model. Export aborted. **\n" ) );
720 return false;
721 }
722
723 ReportMessage( wxString::Format( _( "Writing %s file\n" ), m_params.GetFormatName() ) );
724
725 bool success = true;
727 success = m_pcbModel->WriteSTEP( m_outputFile, m_params.m_OptimizeStep );
729 success = m_pcbModel->WriteBREP( m_outputFile );
731 success = m_pcbModel->WriteXAO( m_outputFile );
733 success = m_pcbModel->WriteGLTF( m_outputFile );
735 success = m_pcbModel->WritePLY( m_outputFile );
737 success = m_pcbModel->WriteSTL( m_outputFile );
738
739 if( !success )
740 {
741 ReportMessage( wxString::Format( _( "\n** Error writing %s file. **\n" ),
743 return false;
744 }
745 else
746 {
747 ReportMessage( wxString::Format( _( "%s file '%s' created.\n" ),
749 }
750 }
751 catch( const Standard_Failure& e )
752 {
753 ReportMessage( e.GetMessageString() );
754 ReportMessage( wxString::Format( _( "\n** Error exporting %s file. Export aborted. **\n" ),
756 return false;
757 }
758 catch( ... )
759 {
760 ReportMessage( wxString::Format( _( "\n** Error exporting %s file. Export aborted. **\n" ),
762 return false;
763 }
764
765 if( m_fail || m_error )
766 {
767 wxString msg;
768
769 if( m_fail )
770 {
771 msg = wxString::Format( _( "Unable to create %s file.\n"
772 "Check that the board has a valid outline and models." ),
774 }
775 else if( m_error || m_warn )
776 {
777 msg = wxString::Format( _( "%s file has been created, but there are warnings." ),
779 }
780
781 ReportMessage( msg );
782 }
783
784 // Display calculation time in seconds
785 double calculation_time = (double)( GetRunningMicroSecs() - stats_startExportTime) / 1e6;
786 ReportMessage( wxString::Format( _( "\nExport time %.3f s\n" ), calculation_time ) );
787
788 return true;
789}
@ ERROR_INSIDE
Definition: approximation.h:34
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.
BASE_SET & set(size_t pos)
Definition: base_set.h:115
const VECTOR2I & GetGridOrigin()
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:79
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:237
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:290
BOARD_STACKUP GetStackupOrDefault() const
Definition: board.cpp:2287
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:2493
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:775
const ZONES & Zones() const
Definition: board.h:335
const FOOTPRINTS & Footprints() const
Definition: board.h:331
const TRACKS & Tracks() const
Definition: board.h:329
const wxString & GetFileName() const
Definition: board.h:327
PROJECT * GetProject() const
Definition: board.h:491
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:892
const DRAWINGS & Drawings() const
Definition: board.h:333
double AsRadians() const
Definition: eda_angle.h:117
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:101
wxString GetFormatName() const
wxString GetDefaultExportExtension() const
int m_platingThickness
Definition: exporter_step.h:90
void buildZones3DShape(VECTOR2D aOrigin)
LSET m_layersToExport
Definition: exporter_step.h:85
void initOutputVariant()
std::map< PCB_LAYER_ID, SHAPE_POLY_SET > m_poly_holes
Definition: exporter_step.h:83
BOARD * m_board
Definition: exporter_step.h:75
wxString m_outputFile
Definition: exporter_step.h:53
bool buildGraphic3DShape(BOARD_ITEM *aItem, VECTOR2D aOrigin)
EXPORTER_STEP_PARAMS m_params
Definition: exporter_step.h:67
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
Definition: exporter_step.h:80
bool buildFootprint3DShapes(FOOTPRINT *aFootprint, VECTOR2D aOrigin)
std::unique_ptr< FILENAME_RESOLVER > m_resolver
Definition: exporter_step.h:68
bool buildBoard3DShapes()
std::unique_ptr< STEP_PCB_MODEL > m_pcbModel
Definition: exporter_step.h:76
std::map< PCB_LAYER_ID, SHAPE_POLY_SET > m_poly_shapes
Definition: exporter_step.h:82
bool buildTrack3DShape(PCB_TRACK *aTrack, VECTOR2D aOrigin)
KIGFX::COLOR4D m_copperColor
Definition: exporter_step.h:87
KIGFX::COLOR4D m_padColor
Definition: exporter_step.h:88
EDA_ANGLE GetOrientation() const
Definition: footprint.h:227
std::deque< PAD * > & Pads()
Definition: footprint.h:206
int GetAttributes() const
Definition: footprint.h:290
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: footprint.h:236
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:3704
const LIB_ID & GetFPID() const
Definition: footprint.h:248
std::vector< FP_3DMODEL > & Models()
Definition: footprint.h:220
const wxString & GetReference() const
Definition: footprint.h:602
VECTOR2I GetPosition() const override
Definition: footprint.h:224
Hold a record identifying a library accessed by the appropriate footprint library #PLUGIN object in t...
Definition: fp_lib_table.h:42
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:392
double g
Green component.
Definition: color4d.h:393
double b
Blue component.
Definition: color4d.h:394
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...
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:36
static LSET ExternalCuMask()
Return a mask holding the Front and Bottom layers.
Definition: lset.cpp:694
static LSET InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
Definition: lset.cpp:665
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:676
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:410
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
Definition: lset.h:60
Definition: pad.h:54
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:930
void TransformTextToPolySet(SHAPE_POLY_SET &aBuffer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc) const
Function TransformTextToPolySet Convert the text to a polygonSet describing the actual character stro...
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:1968
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.
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset difference For aFastMode meaning, see function booleanOp.
void ClearArcs()
Removes all arc references from all the outlines and holes in the polyset.
int FullPointCount() const
Return the number of points in the shape poly set.
void BooleanIntersection(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset intersection For aFastMode meaning, see function booleanOp.
std::vector< SHAPE_LINE_CHAIN > POLYGON
represents a single polygon outline with holes.
void Simplify(POLYGON_MODE aFastMode)
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections) For aFastMo...
void Unfracture(POLYGON_MODE aFastMode)
Convert a single outline slitted ("fractured") polygon into a set ouf outlines with holes.
void SimplifyOutlines(int aMaxError=0)
Simplifies the lines in the polyset.
void TransformToPolygon(SHAPE_POLY_SET &aBuffer, int aError, ERROR_LOC aErrorLoc) const override
Fills a SHAPE_POLY_SET with a polygon representation of this shape.
const std::vector< POLYGON > & CPolygons() const
Handle a list of polygons defining a copper zone.
Definition: zone.h:73
#define _(s)
void ReportMessage(const wxString &aMessage)
@ FP_SMD
Definition: footprint.h:76
@ FP_DNP
Definition: footprint.h:83
@ FP_THROUGH_HOLE
Definition: footprint.h:75
static const std::string AutoSaveFilePrefix
const wxChar *const traceKiCad2Step
Flag to enable KiCad2Step debug tracing.
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:531
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ B_Mask
Definition: layer_ids.h:98
@ B_Cu
Definition: layer_ids.h:65
@ F_Mask
Definition: layer_ids.h:97
@ F_SilkS
Definition: layer_ids.h:100
@ B_SilkS
Definition: layer_ids.h:101
@ F_Cu
Definition: layer_ids.h:64
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: pgm_base.cpp:1060
see class PGM_BASE
int64_t GetRunningMicroSecs()
An alternate way to calculate an elapsed time (in microsecondes) to class PROF_COUNTER.
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:86
constexpr int mmToIU(double mm) const
Definition: base_units.h:88
wxLogTrace helper definitions.
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:88
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:93
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:92
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
Definition: typeinfo.h:94
Definition of file extensions used in Kicad.