diff --git a/pcbnew/exporters/export_idf.cpp b/pcbnew/exporters/export_idf.cpp index c6aadba5e0..6becbe26cf 100644 --- a/pcbnew/exporters/export_idf.cpp +++ b/pcbnew/exporters/export_idf.cpp @@ -326,6 +326,14 @@ static void idf_export_module( BOARD* aPcb, MODULE* aModule, if( !modfile->Is3DType( S3D_MASTER::FILE3D_IDF ) ) continue; + if( refdes.empty() ) + { + refdes = TO_UTF8( aModule->GetReference() ); + + if( refdes.empty() || !refdes.compare( "~" ) ) + refdes = aIDFBoard.GetRefDes(); + } + double rotz = modfile->m_MatRotation.z + aModule->GetOrientation()/10.0; double locx = modfile->m_MatPosition.x; double locy = modfile->m_MatPosition.y; @@ -333,8 +341,6 @@ static void idf_export_module( BOARD* aPcb, MODULE* aModule, bool top = ( aModule->GetLayer() == LAYER_N_BACK ) ? false : true; - refdes = TO_UTF8( aModule->GetReference() ); - if( top ) { locy = -locy; @@ -358,7 +364,7 @@ static void idf_export_module( BOARD* aPcb, MODULE* aModule, locx += aModule->GetPosition().x * scale + dx; locy += -aModule->GetPosition().y * scale + dy; - aIDFBoard.PlaceComponent(modfile->GetShape3DName(), refdes, locx, locy, locz, rotz, top); + aIDFBoard.PlaceComponent( modfile->GetShape3DName(), refdes, locx, locy, locz, rotz, top ); } return; @@ -376,22 +382,30 @@ bool Export_IDF3( BOARD* aPcb, const wxString& aFullFileName, double aUseThou ) SetLocaleTo_C_standard(); - idfBoard.Setup( aPcb->GetFileName(), aFullFileName, aUseThou, - aPcb->GetDesignSettings().GetBoardThickness() ); + try + { + idfBoard.Setup( aPcb->GetFileName(), aFullFileName, aUseThou, + aPcb->GetDesignSettings().GetBoardThickness() ); - // set up the global offsets - EDA_RECT bbox = aPcb->ComputeBoundingBox( true ); - idfBoard.SetOffset( -bbox.Centre().x * idfBoard.GetScale(), - bbox.Centre().y * idfBoard.GetScale() ); + // set up the global offsets + EDA_RECT bbox = aPcb->ComputeBoundingBox( true ); + idfBoard.SetOffset( -bbox.Centre().x * idfBoard.GetScale(), + bbox.Centre().y * idfBoard.GetScale() ); - // Export the board outline - idf_export_outline( aPcb, idfBoard ); + // Export the board outline + idf_export_outline( aPcb, idfBoard ); - // Output the drill holes and module (library) data. - for( MODULE* module = aPcb->m_Modules; module != 0; module = module->Next() ) - idf_export_module( aPcb, module, idfBoard ); + // Output the drill holes and module (library) data. + for( MODULE* module = aPcb->m_Modules; module != 0; module = module->Next() ) + idf_export_module( aPcb, module, idfBoard ); - idfBoard.Finish(); + idfBoard.Finish(); + } + catch( IO_ERROR ioe ) + { + wxLogDebug( wxT( "An error occurred attemping export to IDFv3.\n\nError: %s" ), + GetChars( ioe.errorText ) ); + } SetLocaleTo_Default(); diff --git a/pcbnew/exporters/idf.cpp b/pcbnew/exporters/idf.cpp index 364f9f9a23..e609d96ad1 100644 --- a/pcbnew/exporters/idf.cpp +++ b/pcbnew/exporters/idf.cpp @@ -3,7 +3,7 @@ * * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2013 Cirilo Bernardo + * Copyright (C) 2013-2014 Cirilo Bernardo * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -311,6 +312,39 @@ void IDF_SEGMENT::SwapEnds( void ) } +void IDF_OUTLINE::push( IDF_SEGMENT* item ) +{ + if( !outline.empty() ) + { + if( item->IsCircle() ) + { + // not allowed + wxString msg = wxT( "INVALID GEOMETRY: a circle is being added to a non-empty outline" ); + THROW_IO_ERROR( msg ); + } + else + { + if( outline.back()->IsCircle() ) + { + // we can't add lines to a circle + wxString msg = wxT( "INVALID GEOMETRY: a line is being added to a circular outline" ); + THROW_IO_ERROR( msg ); + } + else if( !item->MatchesStart( outline.back()->endPoint ) ) + { + // startPoint[N] != endPoint[N -1] + wxString msg = wxT( "INVALID GEOMETRY: disjoint segments" ); + THROW_IO_ERROR( msg ); + } + } + } + + outline.push_back( item ); + dir += ( outline.back()->endPoint.x - outline.back()->startPoint.x ) + * ( outline.back()->endPoint.y + outline.back()->startPoint.y ); +} + + IDF_DRILL_DATA::IDF_DRILL_DATA( double aDrillDia, double aPosX, double aPosY, IDF3::KEY_PLATING aPlating, const std::string aRefDes, @@ -452,6 +486,7 @@ bool IDF_DRILL_DATA::Write( FILE* aLayoutFile ) IDF_BOARD::IDF_BOARD() { + refdesIndex = 0; outlineIndex = 0; scale = 1e-6; boardThickness = 1.6; // default to 1.6mm thick boards @@ -466,7 +501,20 @@ IDF_BOARD::IDF_BOARD() IDF_BOARD::~IDF_BOARD() { - Finish(); + // simply close files if they are open; do not attempt + // anything else since a previous exception may have left + // data in a bad state. + if( layoutFile != NULL ) + { + fclose( layoutFile ); + layoutFile = NULL; + } + + if( libFile != NULL ) + { + fclose( libFile ); + libFile = NULL; + } } @@ -525,7 +573,7 @@ bool IDF_BOARD::Setup( wxString aBoardName, TO_UTF8( brdname.GetFullName() ), useThou ? "THOU" : "MM" ); fprintf( libFile, ".HEADER\n" - "BOARD_FILE 3.0 \"Created by KiCad %s\" %.4d/%.2d/%.2d.%.2d:%.2d:%.2d 1\n" + "LIBRARY_FILE 3.0 \"Created by KiCad %s\" %.4d/%.2d/%.2d.%.2d:%.2d:%.2d 1\n" ".END_HEADER\n\n", TO_UTF8( GetBuildVersion() ), tdate.GetYear(), tdate.GetMonth() + 1, tdate.GetDay(), @@ -775,6 +823,16 @@ bool IDF_BOARD::PlaceComponent( const wxString aComponentFile, const std::string } +std::string IDF_BOARD::GetRefDes( void ) +{ + std::ostringstream ostr; + + ostr << "NOREFDES_" << refdesIndex++; + + return ostr.str(); +} + + bool IDF_BOARD::WriteDrills( void ) { if( !layoutFile ) @@ -1500,9 +1558,11 @@ bool IDF_COMP::parseRec2( const std::string aLine, bool& isNewItem ) return false; } - teststr.str( "" ); + teststr.clear(); teststr << geometry << "_" << partno; - isNewItem = parent->RegisterOutline( teststr.str() ); + + if( !parent->RegisterOutline( teststr.str() ) ) + isNewItem = true; return true; } diff --git a/pcbnew/exporters/idf.h b/pcbnew/exporters/idf.h index ba6d413fdd..526406df3f 100644 --- a/pcbnew/exporters/idf.h +++ b/pcbnew/exporters/idf.h @@ -5,7 +5,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2013 Cirilo Bernardo + * Copyright (C) 2013-2014 Cirilo Bernardo * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -292,15 +292,7 @@ public: } // push a segment onto the internal list - void push( IDF_SEGMENT* item ) - { - // XXX - check that startPoint[N] == endPoint[N -1], otherwise THROW - // XXX - a Circle must stand alone; if we add to a circle or add a - // circle to an existing list, we should throw an exception. - outline.push_back( item ); - dir += ( outline.back()->endPoint.x - outline.back()->startPoint.x ) - * ( outline.back()->endPoint.y + outline.back()->startPoint.y ); - } + void push( IDF_SEGMENT* item ); }; @@ -459,6 +451,7 @@ private: double scale; ///< scale from KiCad IU to IDF output units double boardThickness; ///< total thickness of the PCB bool hasBrdOutlineHdr; ///< true when a board outline header has been written + int refdesIndex; ///< index to generate REFDES for modules which have none double offsetX; ///< offset to roughly center the board on the world origin double offsetY; @@ -538,6 +531,8 @@ public: bool PlaceComponent( const wxString aComponentFile, const std::string aRefDes, double aXLoc, double aYLoc, double aZLoc, double aRotation, bool isOnTop ); + + std::string GetRefDes( void ); };