53#include <Message_PrinterOStream.hxx>
54#include <Standard_Failure.hxx>
56#include <Standard_Version.hxx>
62#define OCC_VERSION_MIN 0x070500
64#if OCC_VERSION_HEX < OCC_VERSION_MIN
65#include <Message_Messenger.hxx>
77#if OCC_VERSION_HEX < OCC_VERSION_MIN
78 virtual void Send(
const TCollection_ExtendedString& theString,
79 const Message_Gravity theGravity,
80 const Standard_Boolean theToPutEol )
const override
82 Send( TCollection_AsciiString( theString ), theGravity, theToPutEol );
85 virtual void Send(
const TCollection_AsciiString& theString,
86 const Message_Gravity theGravity,
87 const Standard_Boolean theToPutEol )
const override
89 virtual void send(
const TCollection_AsciiString& theString,
90 const Message_Gravity theGravity )
const override
93 wxString msg( theString.ToCString() );
95#if OCC_VERSION_HEX < OCC_VERSION_MIN
148 m_resolver = std::make_unique<FILENAME_RESOLVER>();
168 if( aLayer == aStartLayer || aLayer == aEndLayer )
187 int startIdx = layerToIndex( aStartLayer );
188 int endIdx = layerToIndex( aEndLayer );
189 int layerIdx = layerToIndex( aLayer );
194 int minIdx = std::min( startIdx, endIdx );
195 int maxIdx = std::max( startIdx, endIdx );
197 return ( layerIdx >= minIdx && layerIdx <= maxIdx );
204 bool hasdata =
false;
205 std::vector<PAD*> padsMatchingNetFilter;
211 std::shared_ptr<SHAPE_SEGMENT> holeShape =
pad->GetEffectiveHoleShape();
214 holeShape->TransformToPolygon( holePoly,
pad->GetMaxError(),
ERROR_INSIDE );
221 if(
pad->IsOnLayer( pcblayer ) )
229 if(
m_pcbModel->AddHole( *holeShape, platingThickness,
F_Cu,
B_Cu,
false, aOrigin,
true,
true ) )
245 if( secondaryDrill.
size.
x > 0 )
248 secondaryDrill.
size.
x );
250 secondaryDrill.
end, aOrigin );
276 if( tertiaryDrill.
size.
x > 0 )
279 tertiaryDrill.
size.
x );
281 tertiaryDrill.
end, aOrigin );
310 wxLogTrace(
traceKiCad2Step, wxT(
"PAD post-machining check: frontPM.mode.has_value=%d frontPM.size=%d frontPM.depth=%d frontPM.angle=%d" ),
312 wxLogTrace(
traceKiCad2Step, wxT(
"PAD post-machining check: backPM.mode.has_value=%d backPM.size=%d backPM.depth=%d backPM.angle=%d" ),
316 bool frontPMValid = frontPM.
mode.has_value() && frontPM.
size > 0 &&
322 wxLogTrace(
traceKiCad2Step, wxT(
"PAD front post-machining: mode=%d (COUNTERBORE=2, COUNTERSINK=3)" ),
323 static_cast<int>( *frontPM.
mode ) );
330 frontPM.
depth,
true, aOrigin );
335 frontPM.
depth, frontPM.
angle,
true, aOrigin );
341 for(
const auto& [layer, diameter] : knockouts )
358 bool backPMValid = backPM.
mode.has_value() && backPM.
size > 0 &&
364 wxLogTrace(
traceKiCad2Step, wxT(
"PAD back post-machining: mode=%d (COUNTERBORE=2, COUNTERSINK=3)" ),
365 static_cast<int>( *backPM.
mode ) );
372 backPM.
depth,
false, aOrigin );
383 for(
const auto& [layer, diameter] : knockouts )
400 if( !
m_params.m_NetFilter.IsEmpty() && !
pad->GetNetname().Matches(
m_params.m_NetFilter ) )
405 if(
m_pcbModel->AddPadShape(
pad, aOrigin,
false, castellated ? aClipPolygon :
nullptr) )
417 pad->TransformShapeToPolygon( poly, cuLayer,
pad->GetSolderMaskExpansion( cuLayer ),
425 padsMatchingNetFilter.push_back(
pad );
447 std::map<const SHAPE_POLY_SET::POLYGON*, PAD*> polyPadMap;
452 for(
PAD*
pad : padsMatchingNetFilter )
454 if( !
pad->IsOnLayer( pcblayer ) )
457 std::shared_ptr<SHAPE_POLY_SET> padPoly =
pad->GetEffectivePolygon( pcblayer );
460 if( padPoly->Collide( &gfxPoly ) )
462 polyPadMap[&poly] =
pad;
474 auto it = polyPadMap.find( &poly );
476 if( it == polyPadMap.end() )
496 wxString footprintBasePath = wxEmptyString;
499 double posY = (aFootprint->
GetPosition().y) - aOrigin.
y;
503 std::optional<LIBRARY_TABLE_ROW*> fpRow =
515 bool componentFilter = !
m_params.m_ComponentFilter.IsEmpty();
516 std::vector<wxString> componentFilterPatterns;
518 if( componentFilter )
520 wxStringTokenizer tokenizer(
m_params.m_ComponentFilter,
", \t\r\n", wxTOKEN_STRTOK );
522 while( tokenizer.HasMoreTokens() )
523 componentFilterPatterns.push_back( tokenizer.GetNextToken() );
527 for(
const wxString& pattern : componentFilterPatterns )
544 if( !fp_model.m_Show || fp_model.m_Filename.empty() )
547 std::vector<wxString> searchedPaths;
548 std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
550 embeddedFilesStack.push_back(
m_board->GetEmbeddedFiles() );
552 wxString mname =
m_resolver->ResolvePath( fp_model.m_Filename, footprintBasePath,
553 std::move( embeddedFilesStack ) );
555 if( mname.empty() || !wxFileName::FileExists( mname ) )
559 mname = fp_model.m_Filename;
561 m_reporter->Report( wxString::Format(
_(
"Could not add 3D model for %s.\n"
562 "File not found: %s\n" ),
569 std::string fname( mname.ToUTF8() );
570 std::string refName( aFootprint->
GetReference().ToUTF8() );
577 VECTOR3D modelRot = fp_model.m_Rotation;
581 if(
m_pcbModel->AddComponent( fname, refName, bottomSide, newpos,
583 fp_model.m_Offset, modelRot,
584 fp_model.m_Scale,
m_params.m_SubstModels ) )
589 catch(
const Standard_Failure& e )
591 m_reporter->Report( wxString::Format(
_(
"Could not add 3D model for %s.\n"
592 "OpenCASCADE error: %s\n" ),
594 e.GetMessageString() ),
606 bool skipCopper = !
m_params.m_ExportTracksVias
607 || ( !
m_params.m_NetFilter.IsEmpty()
628 std::shared_ptr<SHAPE_SEGMENT> holeShape =
via->GetEffectiveHoleShape();
630 holeShape->TransformToPolygon( holePoly,
via->GetMaxError(),
ERROR_INSIDE );
638 via->LayerPair( &top_layer, &bot_layer );
644 const std::shared_ptr<SHAPE>& shape =
via->GetEffectiveShape( pcblayer );
652 m_pcbModel->AddBarrel( *holeShape, top_layer, bot_layer,
true, aOrigin,
via->GetNetname() );
671 if( secondaryDrill.
size.
x > 0 )
674 secondaryDrill.
size.
x );
676 secondaryDrill.
end, aOrigin );
702 if( tertiaryDrill.
size.
x > 0 )
705 tertiaryDrill.
size.
x );
707 tertiaryDrill.
end, aOrigin );
736 wxLogTrace(
traceKiCad2Step, wxT(
"VIA post-machining check: frontPM.mode.has_value=%d frontPM.size=%d frontPM.depth=%d frontPM.angle=%d" ),
738 wxLogTrace(
traceKiCad2Step, wxT(
"VIA post-machining check: backPM.mode.has_value=%d backPM.size=%d backPM.depth=%d backPM.angle=%d" ),
742 bool frontPMValid = frontPM.
mode.has_value() && frontPM.
size > 0 &&
748 wxLogTrace(
traceKiCad2Step, wxT(
"VIA front post-machining: mode=%d (COUNTERBORE=2, COUNTERSINK=3)" ),
749 static_cast<int>( *frontPM.
mode ) );
756 frontPM.
depth,
true, aOrigin );
761 frontPM.
depth, frontPM.
angle,
true, aOrigin );
767 for(
const auto& [layer, diameter] : knockouts )
784 bool backPMValid = backPM.
mode.has_value() && backPM.
size > 0 &&
790 wxLogTrace(
traceKiCad2Step, wxT(
"VIA back post-machining: mode=%d (COUNTERBORE=2, COUNTERSINK=3)" ),
791 static_cast<int>( *backPM.
mode ) );
798 backPM.
depth,
false, aOrigin );
809 for(
const auto& [layer, diameter] : knockouts )
847 LSET layers = zone->GetLayerSet();
850 && !zone->GetNetname().Matches(
m_params.m_NetFilter ) )
858 zone->TransformSolidAreasShapesToPolygon( layer, fill_shape );
863 m_poly_shapes[layer][zone->GetNetname()].Append( fill_shape );
883 switch( aItem->
Type() )
911 for(
SHAPE* shape : shapes )
916 SHAPE_SEGMENT seg( a, b, graphic->GetWidth() );
917 seg.TransformToPolygon( m_poly_shapes[pcblayer][graphic->GetNetname()],
918 maxError, ERROR_INSIDE );
922 for(
SHAPE* shape : shapes )
968 textbox->PCB_SHAPE::TransformShapeToPolygon(
m_poly_shapes[pcblayer][wxEmptyString], pcblayer, 0,
996 default: wxFAIL_MSG(
"buildGraphic3DShape: unhandled item type" );
1059 if( !
m_board->GetBoardPolygonOutlines( pcbOutlines,
1064 wxLogWarning(
_(
"Board outline is malformed. Run DRC for a full analysis." ) );
1075 origin =
m_board->GetDesignSettings().GetAuxOrigin();
1076 else if(
m_params.m_UseGridOrigin )
1077 origin =
m_board->GetDesignSettings().GetGridOrigin();
1131 poly.SimplifyOutlines(
pcbIUScale.mmToIU( 0.003 ) );
1139 m_pcbModel->AddPolygonShapes( &mask, pcblayer, origin, wxEmptyString );
1147 poly.SimplifyOutlines(
pcbIUScale.mmToIU( 0.003 ) );
1151 poly.BooleanSubtract( holes );
1154 poly.BooleanIntersection( pcbOutlinesNoArcs );
1156 m_pcbModel->AddPolygonShapes( &poly, pcblayer, origin, netname );
1163 m_reporter->Report( wxString::Format( wxT(
"Board outline: found %d initial points.\n" ),
1183 struct SCOPED_PRINTER
1185 Handle( Message_Printer ) m_handle;
1187 SCOPED_PRINTER(
const Handle( Message_Printer ) & aHandle ) : m_handle( aHandle )
1189 Message::DefaultMessenger()->AddPrinter( m_handle );
1192 ~SCOPED_PRINTER() { Message::DefaultMessenger()->RemovePrinter( m_handle ); }
1195 Message::DefaultMessenger()->RemovePrinters( STANDARD_TYPE( Message_PrinterOStream ) );
1200 if(
m_params.m_OutputFile.IsEmpty() )
1202 wxFileName fn =
m_board->GetFileName();
1203 fn.SetName( fn.GetName() );
1204 fn.SetExt(
m_params.GetDefaultExportExtension() );
1206 m_params.m_OutputFile = fn.GetFullName();
1230 m_reporter->Report( wxString::Format( wxT(
"Build %s data.\n" ),
m_params.GetFormatName() ),
1236 "** Error building STEP board model. Export aborted. **\n" ),
1241 m_reporter->Report( wxString::Format( wxT(
"Writing %s file.\n" ),
m_params.GetFormatName() ),
1244 bool success =
true;
1267 "** Error writing %s file. **\n" ),
1274 m_reporter->Report( wxString::Format( wxT(
"%s file '%s' created.\n" ),
1280 catch(
const Standard_Failure& e )
1284 "** Error exporting %s file. Export aborted. **\n" ),
1293 "** Error exporting %s file. Export aborted. **\n" ),
1303 "Export time %.3f s\n" ),
constexpr EDA_IU_SCALE pcbIUScale
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
wxString GetNetname() const
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
virtual void TransformShapeToPolySet(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, KIGFX::RENDER_SETTINGS *aRenderSettings=nullptr) const
Convert the item shape to a polyset.
Information pertinent to a Pcbnew printed circuit board.
const wxString & GetFileName() const
PROJECT * GetProject() const
KICAD_T Type() const
Returns the type of object.
const SHAPE_POLY_SET & GetHatching() const
virtual std::vector< SHAPE * > MakeEffectiveShapes(bool aEdgeOnly=false) const
Make a set of SHAPE objects representing the EDA_SHAPE.
bool IsHatchedFill() const
LINE_STYLE GetLineStyle() const
void buildZones3DShape(VECTOR2D aOrigin)
bool buildTrack3DShape(PCB_TRACK *aTrack, const VECTOR2D &aOrigin)
bool buildFootprint3DShapes(FOOTPRINT *aFootprint, const VECTOR2D &aOrigin, SHAPE_POLY_SET *aClipPolygon)
std::map< PCB_LAYER_ID, SHAPE_POLY_SET > m_poly_holes
bool isLayerInBackdrillSpan(PCB_LAYER_ID aLayer, PCB_LAYER_ID aStartLayer, PCB_LAYER_ID aEndLayer) const
Check if a copper layer is within a backdrill layer span (inclusive).
EXPORTER_STEP_PARAMS m_params
wxString m_pcbBaseName
the name of the project (board short filename (no path, no ext) used to identify items in step file
std::unique_ptr< FILENAME_RESOLVER > m_resolver
bool buildBoard3DShapes()
std::unique_ptr< STEP_PCB_MODEL > m_pcbModel
std::map< PCB_LAYER_ID, std::map< wxString, SHAPE_POLY_SET > > m_poly_shapes
KIGFX::COLOR4D m_copperColor
EXPORTER_STEP(BOARD *aBoard, const EXPORTER_STEP_PARAMS &aParams, REPORTER *aReporter)
bool buildGraphic3DShape(BOARD_ITEM *aItem, const VECTOR2D &aOrigin)
KIGFX::COLOR4D m_padColor
virtual void Send(const TCollection_ExtendedString &theString, const Message_Gravity theGravity, const Standard_Boolean theToPutEol) const override
SEVERITY getSeverity(const Message_Gravity theGravity) const
KICAD_PRINTER(REPORTER *aReporter)
virtual void Send(const TCollection_AsciiString &theString, const Message_Gravity theGravity, const Standard_Boolean theToPutEol) const override
A color representation with 4 components: red, green, blue, alpha.
PCB specific render settings.
void SetGapLengthRatio(double aRatio)
void SetDashLengthRatio(double aRatio)
std::optional< LIBRARY_TABLE_ROW * > GetRow(const wxString &aNickname, LIBRARY_TABLE_SCOPE aScope=LIBRARY_TABLE_SCOPE::BOTH) const
Like LIBRARY_MANAGER::GetRow but filtered to the LIBRARY_TABLE_TYPE of this adapter.
std::optional< wxString > GetFullURI(LIBRARY_TABLE_TYPE aType, const wxString &aNickname, bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
LSET is a set of PCB_LAYER_IDs.
static const LSET & ExternalCuMask()
Return a mask holding the Front and Bottom layers.
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
static const LSET & InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
A PADSTACK defines the characteristics of a single or multi-layer pad, in the IPC sense of the word.
POST_MACHINING_PROPS & FrontPostMachining()
DRILL_PROPS & TertiaryDrill()
DRILL_PROPS & SecondaryDrill()
POST_MACHINING_PROPS & BackPostMachining()
Parameters and options when plotting/printing a board.
double GetDashedLineGapRatio() const
double GetDashedLineDashRatio() const
int GetWidth() const override
int GetSolderMaskExpansion() const
void TransformShapeToPolySet(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, KIGFX::RENDER_SETTINGS *aRenderSettings=nullptr) const override
Convert the item shape to a polyset.
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.
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Test to see if this object is on the given layer.
bool IsBorderEnabled() const
Disables the border, this is done by changing the stroke internally.
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...
int GetSolderMaskExpansion() const
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.
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Test to see if this object is on the given layer.
static FOOTPRINT_LIBRARY_ADAPTER * FootprintLibAdapter(PROJECT *aProject)
A pure virtual class used to derive REPORTER objects from.
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 Deflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError)
void BooleanSubtract(const SHAPE_POLY_SET &b)
Perform boolean polyset difference.
const std::vector< POLYGON > & CPolygons() const
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.
An abstract shape on 2D plane.
Simple container to manage line stroke parameters.
static void Stroke(const SHAPE *aShape, LINE_STYLE aLineStyle, int aWidth, const KIGFX::RENDER_SETTINGS *aRenderSettings, const std::function< void(const VECTOR2I &a, const VECTOR2I &b)> &aStroker)
Handle a list of polygons defining a copper zone.
void TransformCircleToPolygon(SHAPE_LINE_CHAIN &aBuffer, const VECTOR2I &aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a circle to a polygon, using multiple straight lines.
@ ROUND_ALL_CORNERS
All angles are rounded.
const wxChar *const traceKiCad2Step
Flag to enable KiCad2Step debug tracing.
Handle(KICAD3D_INFO) KICAD3D_INFO
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
bool IsInnerCopperLayer(int aLayerId)
Test whether a layer is an inner (In1_Cu to In30_Cu) copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
@ PTH
Plated through hole pad.
@ CASTELLATED
a pad with a castellated through hole
BARCODE class definition.
PGM_BASE & Pgm()
The global program "get" accessor.
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 ...
LINE_STYLE
Dashed line types.
! The properties of a padstack drill. Drill position is always the pad position (origin).
VECTOR2I size
Drill diameter (x == y) or slot dimensions (x != y)
std::optional< PAD_DRILL_POST_MACHINING_MODE > mode
wxLogTrace helper definitions.
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D
VECTOR3< double > VECTOR3D
Definition of file extensions used in Kicad.