diff --git a/utils/kicad2step/kicad2step.cpp b/utils/kicad2step/kicad2step.cpp index d3e1601937..51d0eb57ef 100644 --- a/utils/kicad2step/kicad2step.cpp +++ b/utils/kicad2step/kicad2step.cpp @@ -54,6 +54,7 @@ private: wxString m_outputFile; double m_xOrigin; double m_yOrigin; + double m_minDistance; }; static const wxCmdLineEntryDesc cmdLineDesc[] = @@ -78,6 +79,9 @@ static const wxCmdLineEntryDesc cmdLineDesc[] = { wxCMD_LINE_SWITCH, NULL, "no-virtual", _( "exclude 3D models for components with 'virtual' attribute" ).mb_str(), wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL }, + { wxCMD_LINE_OPTION, NULL, "min-distance", + _( "Minimum distance between points to treat them as separate ones (default 0.01 mm)" ).mb_str(), + wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, { wxCMD_LINE_SWITCH, "h", NULL, _( "display this message" ).mb_str(), wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP }, { wxCMD_LINE_NONE } @@ -98,6 +102,7 @@ bool KICAD2MCAD::OnInit() m_includeVirtual = true; m_xOrigin = 0.0; m_yOrigin = 0.0; + m_minDistance = MIN_DISTANCE; if( !wxAppConsole::OnInit() ) return false; @@ -181,6 +186,28 @@ bool KICAD2MCAD::OnCmdLineParsed( wxCmdLineParser& parser ) } } } + + + if( parser.Found( "min-distance", &tstr ) ) + { + std::istringstream istr; + istr.str( std::string( tstr.ToUTF8() ) ); + istr >> m_minDistance; + + if( istr.fail() ) + { + parser.Usage(); + return false; + } + + if( !istr.eof() ) + { + std::string tunit; + istr >> tunit; + + if( !tunit.compare( "in" ) || !tunit.compare( "inch" ) ) + { + m_minDistance *= 25.4; } else if( tunit.compare( "mm" ) ) { @@ -243,6 +270,7 @@ int KICAD2MCAD::OnRun() KICADPCB pcb; pcb.SetOrigin( m_xOrigin, m_yOrigin ); + pcb.SetMinDistance( m_minDistance ); if( pcb.ReadFile( m_filename ) ) { diff --git a/utils/kicad2step/pcb/base.h b/utils/kicad2step/pcb/base.h index 6d5f5c3c8c..058b9354d9 100644 --- a/utils/kicad2step/pcb/base.h +++ b/utils/kicad2step/pcb/base.h @@ -30,6 +30,9 @@ #ifndef KICADBASE_H #define KICADBASE_H +///> Minimum distance between points to treat them as separate ones (mm) +static constexpr double MIN_DISTANCE = 0.01; + namespace SEXPR { class SEXPR; diff --git a/utils/kicad2step/pcb/kicadpcb.cpp b/utils/kicad2step/pcb/kicadpcb.cpp index 7cc3dacb71..984c810a21 100644 --- a/utils/kicad2step/pcb/kicadpcb.cpp +++ b/utils/kicad2step/pcb/kicadpcb.cpp @@ -87,12 +87,11 @@ KICADPCB::KICADPCB() m_resolver.Set3DConfigDir( cfgdir.GetPath() ); m_thickness = 1.6; m_pcb = NULL; + m_minDistance = MIN_DISTANCE; m_useGridOrigin = false; m_useDrillOrigin = false; m_hasGridOrigin = false; m_hasDrillOrigin = false; - - return; } @@ -477,6 +476,7 @@ bool KICADPCB::ComposePCB( bool aComposeVirtual ) m_pcb = new PCBMODEL(); m_pcb->SetPCBThickness( m_thickness ); + m_pcb->SetMinDistance( m_minDistance ); for( auto i : m_curves ) { diff --git a/utils/kicad2step/pcb/kicadpcb.h b/utils/kicad2step/pcb/kicadpcb.h index 89cb371c82..63310a0f04 100644 --- a/utils/kicad2step/pcb/kicadpcb.h +++ b/utils/kicad2step/pcb/kicadpcb.h @@ -62,6 +62,8 @@ private: // set to TRUE if the origin was actually parsed bool m_hasGridOrigin; bool m_hasDrillOrigin; + // minimum distance between points to treat them as separate entities (mm) + double m_minDistance; // the names of layers in use, and the internal layer ID std::map m_layersNames; @@ -99,6 +101,11 @@ public: m_useDrillOrigin = aUseOrigin; } + void SetMinDistance( double aDistance ) + { + m_minDistance = aDistance; + } + bool ReadFile( const wxString& aFileName ); bool ComposePCB( bool aComposeVirtual = true ); bool WriteSTEP( const wxString& aFileName, bool aOverwrite ); diff --git a/utils/kicad2step/pcb/oce_utils.cpp b/utils/kicad2step/pcb/oce_utils.cpp index 189c7d76f5..6f38709239 100644 --- a/utils/kicad2step/pcb/oce_utils.cpp +++ b/utils/kicad2step/pcb/oce_utils.cpp @@ -84,7 +84,7 @@ static constexpr double THICKNESS_DEFAULT = 1.6; // nominal offset from the board static constexpr double BOARD_OFFSET = 0.05; // min. length**2 below which 2 points are considered coincident -static constexpr double MIN_LENGTH2 = 0.0001; // = 0.01*0.01 +static constexpr double MIN_LENGTH2 = MIN_DISTANCE * MIN_DISTANCE; static void getEndPoints( const KICADCURVE& aCurve, double& spx0, double& spy0, double& epx0, double& epy0 ) @@ -226,6 +226,7 @@ PCBMODEL::PCBMODEL() m_precision = USER_PREC; m_angleprec = USER_ANGLE_PREC; m_thickness = THICKNESS_DEFAULT; + m_minDistance2 = MIN_LENGTH2; m_minx = 1.0e10; // absurdly large number; any valid PCB X value will be smaller m_mincurve = m_curves.end(); BRepBuilderAPI::Precision( 1.0e-6 ); @@ -252,7 +253,7 @@ bool PCBMODEL::AddOutlineSegment( KICADCURVE* aCurve ) double dy = aCurve->m_end.y - aCurve->m_start.y; double distance = dx * dx + dy * dy; - if( distance < MIN_LENGTH2 ) + if( distance < m_minDistance2 ) { std::ostringstream ostr; #ifdef __WXDEBUG__ @@ -271,7 +272,7 @@ bool PCBMODEL::AddOutlineSegment( KICADCURVE* aCurve ) double dy = aCurve->m_end.y - aCurve->m_start.y; double rad = dx * dx + dy * dy; - if( rad < MIN_LENGTH2 ) + if( rad < m_minDistance2 ) { std::ostringstream ostr; #ifdef __WXDEBUG__ @@ -311,7 +312,7 @@ bool PCBMODEL::AddOutlineSegment( KICADCURVE* aCurve ) dy = aCurve->m_ep.y - aCurve->m_end.y; rad = dx * dx + dy * dy; - if( rad < MIN_LENGTH2 ) + if( rad < m_minDistance2 ) { std::ostringstream ostr; #ifdef __WXDEBUG__ @@ -528,6 +529,7 @@ bool PCBMODEL::AddPadHole( KICADPAD* aPad ) p3.y += aPad->m_position.y; OUTLINE oln; + oln.SetMinSqDistance( m_minDistance2 ); KICADCURVE crv0, crv1, crv2, crv3; // crv0 = arc @@ -679,6 +681,7 @@ bool PCBMODEL::CreatePCB() m_hasPCB = true; // whether or not operations fail we note that CreatePCB has been invoked TopoDS_Shape board; OUTLINE oln; // loop to assemble (represents PCB outline and cutouts) + oln.SetMinSqDistance( m_minDistance2 ); oln.AddSegment( *m_mincurve ); m_curves.erase( m_mincurve ); @@ -1279,6 +1282,7 @@ TDF_Label PCBMODEL::transferModel( Handle( TDocStd_Document )& source, OUTLINE::OUTLINE() { m_closed = false; + m_minDistance2 = MIN_LENGTH2; return; } @@ -1330,7 +1334,7 @@ bool OUTLINE::AddSegment( const KICADCURVE& aCurve ) dx = epx1 - spx0; dy = epy1 - spy0; - if( dx * dx + dy * dy < MIN_LENGTH2 ) + if( dx * dx + dy * dy < m_minDistance2 ) { m_curves.push_front( aCurve ); m_closed = testClosed( m_curves.front(), m_curves.back() ); @@ -1341,7 +1345,7 @@ bool OUTLINE::AddSegment( const KICADCURVE& aCurve ) dx = spx1 - spx0; dy = spy1 - spy0; - if( dx * dx + dy * dy < MIN_LENGTH2 ) + if( dx * dx + dy * dy < m_minDistance2 ) { KICADCURVE curve = aCurve; reverseCurve( curve ); @@ -1356,7 +1360,7 @@ bool OUTLINE::AddSegment( const KICADCURVE& aCurve ) dx = spx1 - epx0; dy = spy1 - epy0; - if( dx * dx + dy * dy < MIN_LENGTH2 ) + if( dx * dx + dy * dy < m_minDistance2 ) { m_curves.push_back( aCurve ); m_closed = testClosed( m_curves.front(), m_curves.back() ); @@ -1367,7 +1371,7 @@ bool OUTLINE::AddSegment( const KICADCURVE& aCurve ) dx = epx1 - epx0; dy = epy1 - epy0; - if( dx * dx + dy * dy < MIN_LENGTH2 ) + if( dx * dx + dy * dy < m_minDistance2 ) { KICADCURVE curve = aCurve; reverseCurve( curve ); @@ -1470,7 +1474,7 @@ bool OUTLINE::addEdge( BRepBuilderAPI_MakeWire* aWire, KICADCURVE& aCurve, DOUBL double dy = aLastPoint.y - aCurve.m_end.y; double distance = dx * dx + dy * dy; - if( distance > 0 && distance < MIN_LENGTH2 ) + if( distance > 0 && distance < m_minDistance2 ) { std::ostringstream ostr; @@ -1551,7 +1555,7 @@ bool OUTLINE::testClosed( KICADCURVE& aFrontCurve, KICADCURVE& aBackCurve ) double dy = epy1 - spy0; double r = dx * dx + dy * dy; - if( r < MIN_LENGTH2 ) + if( r < m_minDistance2 ) return true; return false; diff --git a/utils/kicad2step/pcb/oce_utils.h b/utils/kicad2step/pcb/oce_utils.h index f6b8f7bdcf..c4585d88d6 100644 --- a/utils/kicad2step/pcb/oce_utils.h +++ b/utils/kicad2step/pcb/oce_utils.h @@ -49,7 +49,8 @@ class KICADPAD; class OUTLINE { private: - bool m_closed; // set true if the loop is closed + bool m_closed; // set true if the loop is closed + double m_minDistance2; // min squared distance to treat points as separate entities (mm) bool addEdge( BRepBuilderAPI_MakeWire* aWire, KICADCURVE& aCurve, DOUBLET& aLastPoint ); bool testClosed( KICADCURVE& aFrontCurve, KICADCURVE& aBackCurve ); @@ -69,6 +70,11 @@ public: return m_closed; } + void SetMinSqDistance( double aDistance ) + { + m_minDistance2 = aDistance; + } + bool MakeShape( TopoDS_Shape& aShape, double aThickness ); }; @@ -87,6 +93,7 @@ class PCBMODEL double m_angleprec; // angle numeric precision double m_thickness; // PCB thickness, mm double m_minx; // minimum X value in curves (leftmost curve feature) + double m_minDistance2; // minimum squared distance between items (mm) std::list< KICADCURVE >::iterator m_mincurve; // iterator to the leftmost curve std::list< KICADCURVE > m_curves; @@ -124,6 +131,12 @@ public: // aThickness > THICKNESS_MIN == use aThickness void SetPCBThickness( double aThickness ); + void SetMinDistance( double aDistance ) + { + // m_minDistance2 keeps a squared distance value + m_minDistance2 = aDistance * aDistance; + } + // create the PCB model using the current outlines and drill holes bool CreatePCB();