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 The 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, true,
183 true ) )
184 {
185 hasdata = true;
186 }
187
189 //if( m_layersToExport.Contains( F_SilkS ) || m_layersToExport.Contains( B_SilkS ) )
190 //{
191 // m_poly_holes[F_SilkS].Append( holePoly );
192 // m_poly_holes[B_SilkS].Append( holePoly );
193 //}
194 }
195
196 if( !m_params.m_NetFilter.IsEmpty() && !pad->GetNetname().Matches( m_params.m_NetFilter ) )
197 continue;
198
200 {
201 if( m_pcbModel->AddPadShape( pad, aOrigin, false ) )
202 hasdata = true;
203
205 {
206 for( PCB_LAYER_ID pcblayer : pad->GetLayerSet().Seq() )
207 {
208 if( pcblayer != F_Mask && pcblayer != B_Mask )
209 continue;
210
211 SHAPE_POLY_SET poly;
212 PCB_LAYER_ID cuLayer = ( pcblayer == F_Mask ) ? F_Cu : B_Cu;
213 pad->TransformShapeToPolygon( poly, cuLayer,
214 pad->GetSolderMaskExpansion( cuLayer ), maxError,
215 ERROR_INSIDE );
216
217 m_poly_shapes[pcblayer].Append( poly );
218 }
219 }
220 }
221
222 padsMatchingNetFilter.push_back( pad );
223 }
224
225 // Build 3D shapes of the footprint graphic items:
226 for( PCB_LAYER_ID pcblayer : m_layersToExport.Seq() )
227 {
228 if( IsCopperLayer( pcblayer ) && !m_params.m_ExportTracksVias )
229 continue;
230
231 SHAPE_POLY_SET buffer;
232
233 aFootprint->TransformFPShapesToPolySet( buffer, pcblayer, 0, maxError, ERROR_INSIDE,
234 true, /* include text */
235 true, /* include shapes */
236 false /* include private items */ );
237
238 if( m_params.m_NetFilter.IsEmpty() || !IsCopperLayer( pcblayer ) )
239 {
240 m_poly_shapes[pcblayer].Append( buffer );
241 }
242 else
243 {
244 // Only add shapes colliding with any matching pads
245 for( const SHAPE_POLY_SET::POLYGON& poly : buffer.CPolygons() )
246 {
247 for( PAD* pad : padsMatchingNetFilter )
248 {
249 if( !pad->IsOnLayer( pcblayer ) )
250 continue;
251
252 std::shared_ptr<SHAPE_POLY_SET> padPoly = pad->GetEffectivePolygon( pcblayer );
253 SHAPE_POLY_SET gfxPoly( poly );
254
255 if( padPoly->Collide( &gfxPoly ) )
256 {
257 m_poly_shapes[pcblayer].Append( gfxPoly );
258 break;
259 }
260 }
261 }
262 }
263 }
264
265 if( ( !(aFootprint->GetAttributes() & (FP_THROUGH_HOLE|FP_SMD)) ) && !m_params.m_IncludeUnspecified )
266 {
267 return hasdata;
268 }
269
270 if( ( aFootprint->GetAttributes() & FP_DNP ) && !m_params.m_IncludeDNP )
271 {
272 return hasdata;
273 }
274
275 // Prefetch the library for this footprint
276 // In case we need to resolve relative footprint paths
277 wxString libraryName = aFootprint->GetFPID().GetLibNickname();
278 wxString footprintBasePath = wxEmptyString;
279
280 double posX = aFootprint->GetPosition().x - aOrigin.x;
281 double posY = (aFootprint->GetPosition().y) - aOrigin.y;
282
283 if( m_board->GetProject() )
284 {
285 try
286 {
287 // FindRow() can throw an exception
288 const FP_LIB_TABLE_ROW* fpRow =
289 PROJECT_PCB::PcbFootprintLibs( m_board->GetProject() )->FindRow( libraryName, false );
290
291 if( fpRow )
292 footprintBasePath = fpRow->GetFullURI( true );
293 }
294 catch( ... )
295 {
296 // Do nothing if the libraryName is not found in lib table
297 }
298 }
299
300 // Exit early if we don't want to include footprint models
302 {
303 return hasdata;
304 }
305
306 bool componentFilter = !m_params.m_ComponentFilter.IsEmpty();
307 std::vector<wxString> componentFilterPatterns;
308
309 if( componentFilter )
310 {
311 wxStringTokenizer tokenizer( m_params.m_ComponentFilter, wxS( "," ), wxTOKEN_STRTOK );
312
313 while( tokenizer.HasMoreTokens() )
314 componentFilterPatterns.push_back( tokenizer.GetNextToken().Trim( false ) );
315
316 bool found = false;
317
318 for( const wxString& pattern : componentFilterPatterns )
319 {
320 if( aFootprint->GetReference().Matches( pattern ) )
321 {
322 found = true;
323 break;
324 }
325 }
326
327 if( !found )
328 return hasdata;
329 }
330
331 VECTOR2D newpos( pcbIUScale.IUTomm( posX ), pcbIUScale.IUTomm( posY ) );
332
333 for( const FP_3DMODEL& fp_model : aFootprint->Models() )
334 {
335 if( !fp_model.m_Show || fp_model.m_Filename.empty() )
336 continue;
337
338 std::vector<wxString> searchedPaths;
339 wxString mname = m_resolver->ResolvePath( fp_model.m_Filename, footprintBasePath, aFootprint );
340
341
342 if( mname.empty() || !wxFileName::FileExists( mname ) )
343 {
344 // the error path will return an empty name sometimes, at least report back the original filename
345 if( mname.empty() )
346 mname = fp_model.m_Filename;
347
348 ReportMessage( wxString::Format( wxT( "Could not add 3D model to %s.\n"
349 "File not found: %s\n" ),
350 aFootprint->GetReference(), mname ) );
351 continue;
352 }
353
354 std::string fname( mname.ToUTF8() );
355 std::string refName( aFootprint->GetReference().ToUTF8() );
356 try
357 {
358 bool bottomSide = aFootprint->GetLayer() == B_Cu;
359
360 // the rotation is stored in degrees but opencascade wants radians
361 VECTOR3D modelRot = fp_model.m_Rotation;
362 modelRot *= M_PI;
363 modelRot /= 180.0;
364
365 if( m_pcbModel->AddComponent( fname, refName, bottomSide,
366 newpos,
367 aFootprint->GetOrientation().AsRadians(),
368 fp_model.m_Offset, modelRot,
369 fp_model.m_Scale, m_params.m_SubstModels ) )
370 {
371 hasdata = true;
372 }
373 }
374 catch( const Standard_Failure& e )
375 {
376 ReportMessage( wxString::Format( wxT( "Could not add 3D model to %s.\n"
377 "OpenCASCADE error: %s\n" ),
378 aFootprint->GetReference(), e.GetMessageString() ) );
379 }
380
381 }
382
383 return hasdata;
384}
385
386
388{
389 bool skipCopper = !m_params.m_ExportTracksVias
390 || ( !m_params.m_NetFilter.IsEmpty()
391 && !aTrack->GetNetname().Matches( m_params.m_NetFilter ) );
392
393 int maxError = m_board->GetDesignSettings().m_MaxError;
394
396 {
397 if( aTrack->IsOnLayer( F_Mask ) )
398 {
399 SHAPE_POLY_SET poly;
400 aTrack->TransformShapeToPolygon( poly, F_Mask, 0, maxError, ERROR_INSIDE );
401
402 m_poly_shapes[F_Mask].Append( poly );
403 }
404
405 if( aTrack->IsOnLayer( B_Mask ) )
406 {
407 SHAPE_POLY_SET poly;
408 aTrack->TransformShapeToPolygon( poly, B_Mask, 0, maxError, ERROR_INSIDE );
409
410 m_poly_shapes[B_Mask].Append( poly );
411 }
412 }
413
414 if( aTrack->Type() == PCB_VIA_T )
415 {
416 PCB_VIA* via = static_cast<PCB_VIA*>( aTrack );
417
418 std::shared_ptr<SHAPE_SEGMENT> holeShape = via->GetEffectiveHoleShape();
419 SHAPE_POLY_SET holePoly;
420 holeShape->TransformToPolygon( holePoly, maxError, ERROR_INSIDE );
421
422 LSET layers( via->GetLayerSet() & m_layersToExport );
423
424 PCB_LAYER_ID top_layer, bot_layer;
425 via->LayerPair( &top_layer, &bot_layer );
426
427 if( !skipCopper )
428 {
429 for( PCB_LAYER_ID pcblayer : layers.Seq() )
430 {
431 const std::shared_ptr<SHAPE>& shape = via->GetEffectiveShape( pcblayer );
432
433 SHAPE_POLY_SET poly;
434 shape->TransformToPolygon( poly, maxError, ERROR_INSIDE );
435 m_poly_shapes[pcblayer].Append( poly );
436 m_poly_holes[pcblayer].Append( holePoly );
437 }
438
439 m_pcbModel->AddBarrel( *holeShape, top_layer, bot_layer, true, aOrigin );
440 }
441
443 //if( m_layersToExport.Contains( F_SilkS ) || m_layersToExport.Contains( B_SilkS ) )
444 //{
445 // m_poly_holes[F_SilkS].Append( holePoly );
446 // m_poly_holes[B_SilkS].Append( holePoly );
447 //}
448
449 m_pcbModel->AddHole( *holeShape, m_platingThickness, top_layer, bot_layer, true, aOrigin,
451
452 return true;
453 }
454
455 if( skipCopper )
456 return true;
457
458 PCB_LAYER_ID pcblayer = aTrack->GetLayer();
459
460 if( !m_layersToExport.Contains( pcblayer ) )
461 return false;
462
463 aTrack->TransformShapeToPolygon( m_poly_shapes[pcblayer], pcblayer, 0, maxError, ERROR_INSIDE );
464
465 return true;
466}
467
468
470{
471 for( ZONE* zone : m_board->Zones() )
472 {
473 LSET layers = zone->GetLayerSet();
474
475 if( ( layers & LSET::AllCuMask() ).count() && !m_params.m_NetFilter.IsEmpty()
476 && !zone->GetNetname().Matches( m_params.m_NetFilter ) )
477 {
478 continue;
479 }
480
481 for( PCB_LAYER_ID layer : layers.Seq() )
482 {
483 SHAPE_POLY_SET fill_shape;
484 zone->TransformSolidAreasShapesToPolygon( layer, fill_shape );
485 fill_shape.Unfracture();
486
487 fill_shape.SimplifyOutlines( ADVANCED_CFG::GetCfg().m_TriangulateSimplificationLevel );
488
489 m_poly_shapes[layer].Append( fill_shape );
490 }
491 }
492}
493
494
496{
497 PCB_LAYER_ID pcblayer = aItem->GetLayer();
498
499 if( !m_layersToExport.Contains( pcblayer ) )
500 return false;
501
502 if( IsCopperLayer( pcblayer ) && !m_params.m_ExportTracksVias )
503 return false;
504
506 return false;
507
508 int maxError = m_board->GetDesignSettings().m_MaxError;
509
510 switch( aItem->Type() )
511 {
512 case PCB_SHAPE_T:
513 {
514 PCB_SHAPE* graphic = static_cast<PCB_SHAPE*>( aItem );
515
516 if( IsCopperLayer( pcblayer ) && !m_params.m_NetFilter.IsEmpty()
517 && !graphic->GetNetname().Matches( m_params.m_NetFilter ) )
518 {
519 return true;
520 }
521
522 graphic->TransformShapeToPolygon( m_poly_shapes[pcblayer], pcblayer, 0, maxError,
523 ERROR_INSIDE );
524
525 break;
526 }
527
528 case PCB_TEXT_T:
529 {
530 PCB_TEXT* text = static_cast<PCB_TEXT*>( aItem );
531
532 text->TransformTextToPolySet( m_poly_shapes[pcblayer], 0, maxError, ERROR_INSIDE );
533 break;
534 }
535
536 case PCB_TEXTBOX_T:
537 {
538 PCB_TEXTBOX* textbox = static_cast<PCB_TEXTBOX*>( aItem );
539
540 textbox->TransformTextToPolySet( m_poly_shapes[pcblayer], 0, maxError, ERROR_INSIDE );
541 break;
542 }
543
544 case PCB_TABLE_T:
545 // JEY TODO: tables
546 break;
547
548 default: wxFAIL_MSG( "buildGraphic3DShape: unhandled item type" );
549 }
550
551 return true;
552}
553
554
556{
557 // Specialize the STEP_PCB_MODEL generator for specific output format
558 // it can have some minor actions for the generator
559 switch( m_params.m_Format )
560 {
562 m_pcbModel->SpecializeVariant( OUTPUT_FORMAT::FMT_OUT_STEP );
563 break;
564
566 m_pcbModel->SpecializeVariant( OUTPUT_FORMAT::FMT_OUT_BREP );
567 break;
568
570 m_pcbModel->SpecializeVariant( OUTPUT_FORMAT::FMT_OUT_XAO );
571 break;
572
574 m_pcbModel->SpecializeVariant( OUTPUT_FORMAT::FMT_OUT_GLTF );
575 break;
576
578 m_pcbModel->SpecializeVariant( OUTPUT_FORMAT::FMT_OUT_PLY );
579 break;
580
582 m_pcbModel->SpecializeVariant( OUTPUT_FORMAT::FMT_OUT_STL );
583 break;
584
585 default:
586 m_pcbModel->SpecializeVariant( OUTPUT_FORMAT::FMT_OUT_UNKNOWN );
587 break;
588 }
589}
590
591
593{
594 if( m_pcbModel )
595 return true;
596
597 SHAPE_POLY_SET pcbOutlines; // stores the board main outlines
598
599 if( !m_board->GetBoardPolygonOutlines( pcbOutlines,
600 /* error handler */ nullptr,
601 /* allows use arcs in outlines */ true ) )
602 {
603 wxLogWarning( _( "Board outline is malformed. Run DRC for a full analysis." ) );
604 }
605
606 VECTOR2D origin;
607
608 // Determine the coordinate system reference:
609 // Precedence of reference point is Drill Origin > Grid Origin > User Offset
612 else if( m_params.m_UseGridOrigin )
614 else
615 origin = m_params.m_Origin;
616
617 m_pcbModel = std::make_unique<STEP_PCB_MODEL>( m_pcbBaseName );
618
620
622 m_pcbModel->SetPadColor( m_padColor.r, m_padColor.g, m_padColor.b );
623
624 m_pcbModel->SetStackup( m_board->GetStackupOrDefault() );
625 m_pcbModel->SetEnabledLayers( m_layersToExport );
626 m_pcbModel->SetFuseShapes( m_params.m_FuseShapes );
627 m_pcbModel->SetNetFilter( m_params.m_NetFilter );
628
629 // Note: m_params.m_BoardOutlinesChainingEpsilon is used only to build the board outlines,
630 // not to set OCC chaining epsilon (much smaller)
631 //
632 // Set the min distance between 2 points for OCC to see these 2 points as merged
633 // OCC_MAX_DISTANCE_TO_MERGE_POINTS is acceptable for OCC, otherwise there are issues
634 // to handle the shapes chaining on copper layers, because the Z dist is 0.035 mm and the
635 // min dist must be much smaller (we use 0.001 mm giving good results)
636 m_pcbModel->OCCSetMergeMaxDistance( OCC_MAX_DISTANCE_TO_MERGE_POINTS );
637
639
640 // For copper layers, only pads and tracks are added, because adding everything on copper
641 // generate unreasonable file sizes and take a unreasonable calculation time.
642 for( FOOTPRINT* fp : m_board->Footprints() )
643 buildFootprint3DShapes( fp, origin );
644
645 for( PCB_TRACK* track : m_board->Tracks() )
646 buildTrack3DShape( track, origin );
647
648 for( BOARD_ITEM* item : m_board->Drawings() )
649 buildGraphic3DShape( item, origin );
650
652 {
653 buildZones3DShape( origin );
654 }
655
656 SHAPE_POLY_SET pcbOutlinesNoArcs = pcbOutlines;
657 pcbOutlinesNoArcs.ClearArcs();
658
659 for( PCB_LAYER_ID pcblayer : m_layersToExport.Seq() )
660 {
661 SHAPE_POLY_SET poly = m_poly_shapes[pcblayer];
662 poly.Simplify();
663
664 poly.SimplifyOutlines( pcbIUScale.mmToIU( 0.003 ) );
665 poly.Simplify();
666
667 SHAPE_POLY_SET holes = m_poly_holes[pcblayer];
668 holes.Simplify();
669
670 // Mask layer is negative
671 if( pcblayer == F_Mask || pcblayer == B_Mask )
672 {
673 SHAPE_POLY_SET mask = pcbOutlinesNoArcs;
674
675 mask.BooleanSubtract( poly );
676 mask.BooleanSubtract( holes );
677
678 poly = mask;
679 }
680 else
681 {
682 // Subtract holes
683 poly.BooleanSubtract( holes );
684
685 // Clip to board outline
686 poly.BooleanIntersection( pcbOutlinesNoArcs );
687 }
688
689 m_pcbModel->AddPolygonShapes( &poly, pcblayer, origin );
690 }
691
692 ReportMessage( wxT( "Create PCB solid model\n" ) );
693
694 wxString msg;
695 msg.Printf( wxT( "Board outline: find %d initial points\n" ), pcbOutlines.FullPointCount() );
696 ReportMessage( msg );
697
698 if( !m_pcbModel->CreatePCB( pcbOutlines, origin, m_params.m_ExportBoardBody ) )
699 {
700 ReportMessage( wxT( "could not create PCB solid model\n" ) );
701 return false;
702 }
703
704 return true;
705}
706
707
709{
710 // Display the export time, for statistics
711 int64_t stats_startExportTime = GetRunningMicroSecs();
712
713 // setup opencascade message log
714 Message::DefaultMessenger()->RemovePrinters( STANDARD_TYPE( Message_PrinterOStream ) );
715 Message::DefaultMessenger()->AddPrinter( new KiCadPrinter( this ) );
716
717 ReportMessage( _( "Determining PCB data\n" ) );
718
719 if( m_params.m_OutputFile.IsEmpty() )
720 {
721 wxFileName fn = m_board->GetFileName();
722 fn.SetName( fn.GetName() );
723 fn.SetExt( m_params.GetDefaultExportExtension() );
724
725 m_params.m_OutputFile = fn.GetFullName();
726 }
727
729
732
734 {
737 }
738
740 {
743 }
744
746
747 try
748 {
749 ReportMessage( wxString::Format( _( "Build %s data\n" ), m_params.GetFormatName() ) );
750
751 if( !buildBoard3DShapes() )
752 {
753 ReportMessage( _( "\n** Error building STEP board model. Export aborted. **\n" ) );
754 return false;
755 }
756
757 ReportMessage( wxString::Format( _( "Writing %s file\n" ), m_params.GetFormatName() ) );
758
759 bool success = true;
761 success = m_pcbModel->WriteSTEP( m_outputFile, m_params.m_OptimizeStep );
763 success = m_pcbModel->WriteBREP( m_outputFile );
765 success = m_pcbModel->WriteXAO( m_outputFile );
767 success = m_pcbModel->WriteGLTF( m_outputFile );
769 success = m_pcbModel->WritePLY( m_outputFile );
771 success = m_pcbModel->WriteSTL( m_outputFile );
772
773 if( !success )
774 {
775 ReportMessage( wxString::Format( _( "\n** Error writing %s file. **\n" ),
777 return false;
778 }
779 else
780 {
781 ReportMessage( wxString::Format( _( "%s file '%s' created.\n" ),
783 }
784 }
785 catch( const Standard_Failure& e )
786 {
787 ReportMessage( e.GetMessageString() );
788 ReportMessage( wxString::Format( _( "\n** Error exporting %s file. Export aborted. **\n" ),
790 return false;
791 }
792 catch( ... )
793 {
794 ReportMessage( wxString::Format( _( "\n** Error exporting %s file. Export aborted. **\n" ),
796 return false;
797 }
798
799 if( m_fail || m_error )
800 {
801 wxString msg;
802
803 if( m_fail )
804 {
805 msg = wxString::Format( _( "Unable to create %s file.\n"
806 "Check that the board has a valid outline and models." ),
808 }
809 else if( m_error || m_warn )
810 {
811 msg = wxString::Format( _( "%s file has been created, but there are warnings." ),
813 }
814
815 ReportMessage( msg );
816 }
817
818 // Display calculation time in seconds
819 double calculation_time = (double)( GetRunningMicroSecs() - stats_startExportTime) / 1e6;
820 ReportMessage( wxString::Format( _( "\nExport time %.3f s\n" ), calculation_time ) );
821
822 return true;
823}
@ 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:116
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:239
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:295
BOARD_STACKUP GetStackupOrDefault() const
Definition: board.cpp:2330
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:2536
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:817
const ZONES & Zones() const
Definition: board.h:340
const FOOTPRINTS & Footprints() const
Definition: board.h:336
const TRACKS & Tracks() const
Definition: board.h:334
const wxString & GetFileName() const
Definition: board.h:332
PROJECT * GetProject() const
Definition: board.h:499
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:934
const DRAWINGS & Drawings() const
Definition: board.h:338
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:225
std::deque< PAD * > & Pads()
Definition: footprint.h:204
int GetAttributes() const
Definition: footprint.h:288
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: footprint.h:234
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:3905
const LIB_ID & GetFPID() const
Definition: footprint.h:246
std::vector< FP_3DMODEL > & Models()
Definition: footprint.h:218
const wxString & GetReference() const
Definition: footprint.h:620
VECTOR2I GetPosition() const override
Definition: footprint.h:222
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:37
static LSET ExternalCuMask()
Return a mask holding the Front and Bottom layers.
Definition: lset.cpp:580
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:551
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:562
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:295
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
Definition: lset.h:63
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:771
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:1990
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Test to see if this object is on the given layer.
Definition: pcb_track.cpp:958
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 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 Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
std::vector< SHAPE_LINE_CHAIN > POLYGON
represents a single polygon outline with holes.
void Unfracture()
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 BooleanIntersection(const SHAPE_POLY_SET &b)
Perform boolean polyset intersection.
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.
void BooleanSubtract(const SHAPE_POLY_SET &b)
Perform boolean polyset difference.
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:80
@ FP_DNP
Definition: footprint.h:87
@ FP_THROUGH_HOLE
Definition: footprint.h:79
static const std::string AutoSaveFilePrefix
const wxChar *const traceKiCad2Step
Flag to enable KiCad2Step debug tracing.
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition: layer_ids.h:581
bool IsInnerCopperLayer(int aLayerId)
Test whether a layer is an inner (In1_Cu to In30_Cu) copper layer.
Definition: layer_ids.h:603
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:1073
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.