Commit 8e3b896b authored by unknown's avatar unknown Committed by jean-pierre charras

idf tools: code cleanup and debugging

parent a90680aa
......@@ -187,4 +187,4 @@ int main( int argc, char **argv )
fprintf( fp, ".END_ELECTRICAL\n" );
return 0;
}
}
\ No newline at end of file
......@@ -31,6 +31,7 @@
* would be more likely if we used a 1:1 scale.
*/
#include <iostream>
#include <iomanip>
#include <fstream>
......@@ -45,6 +46,7 @@
#include <vector>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <libgen.h>
#include <unistd.h>
......@@ -111,6 +113,7 @@ VRML_COLOR colors[NCOLORS] = { \
bool WriteHeader( IDF3_BOARD& board, std::ofstream& file );
bool MakeBoard( IDF3_BOARD& board, std::ofstream& file );
bool MakeComponents( IDF3_BOARD& board, std::ofstream& file, bool compact );
bool MakeOtherOutlines( IDF3_BOARD& board, std::ofstream& file );
bool PopulateVRML( VRML_LAYER& model, const std::list< IDF_OUTLINE* >* items, bool bottom,
double scale, double dX = 0.0, double dY = 0.0, double angle = 0.0 );
bool AddSegment( VRML_LAYER& model, IDF_SEGMENT* seg, int icont, int iseg );
......@@ -124,12 +127,19 @@ VRML_IDS* GetColor( std::map<std::string, VRML_IDS*>& cmap,
void PrintUsage( void )
{
cout << "-\nUsage: idf2vrml -f input_file.emn -s scale_factor -k\n";
cout << "flags: -k: produce KiCad-firendly VRML output; default is compact VRML\n-\n";
cout << "-\nUsage: idf2vrml -f input_file.emn -s scale_factor {-k} {-d} {-z} {-m}\n";
cout << "flags:\n";
cout << " -k: produce KiCad-friendly VRML output; default is compact VRML\n";
cout << " -d: suppress substitution of default outlines\n";
cout << " -z: suppress rendering of zero-height outlines\n";
cout << " -m: print object mapping to stdout for debugging purposes\n";
cout << "example to produce a model for use by KiCad: idf2vrml -f input.emn -s 0.3937008 -k\n\n";
return;
}
bool nozeroheights;
bool showObjectMapping;
int main( int argc, char **argv )
{
// IDF implicitly requires the C locale
......@@ -148,9 +158,13 @@ int main( int argc, char **argv )
std::string inputFilename;
double scaleFactor = 1.0;
bool compact = true;
bool nooutlinesubs = false;
int ichar;
while( ( ichar = getopt( argc, argv, ":f:s:k" ) ) != -1 )
nozeroheights = false;
showObjectMapping = false;
while( ( ichar = getopt( argc, argv, ":f:s:kdzm" ) ) != -1 )
{
switch( ichar )
{
......@@ -184,6 +198,18 @@ int main( int argc, char **argv )
compact = false;
break;
case 'd':
nooutlinesubs = true;
break;
case 'z':
nozeroheights = true;
break;
case 'm':
showObjectMapping = true;
break;
case ':':
cerr << "* Missing parameter to option '-" << ((char) optopt) << "'\n";
PrintUsage();
......@@ -215,10 +241,11 @@ int main( int argc, char **argv )
cout << "** Reading file: " << inputFilename << "\n";
if( !pcb.ReadFile( FROM_UTF8( inputFilename.c_str() ) ) )
if( !pcb.ReadFile( FROM_UTF8( inputFilename.c_str() ), nooutlinesubs ) )
{
CLEANUP;
cerr << "* Could not read file: " << inputFilename << "\n";
cerr << "** Failed to read IDF data:\n";
cerr << pcb.GetError() << "\n\n";
return -1;
}
......@@ -261,6 +288,9 @@ int main( int argc, char **argv )
// STEP 2: Render the components
MakeComponents( pcb, ofile, compact );
// STEP 3: Render the OTHER outlines
MakeOtherOutlines( pcb, ofile );
ofile << "]\n}\n";
ofile.close();
......@@ -328,7 +358,7 @@ bool MakeBoard( IDF3_BOARD& board, std::ofstream& file )
vpcb.EnsureWinding( 0, false );
int nvcont = vpcb.GetNContours();
int nvcont = vpcb.GetNContours() - 1;
while( nvcont > 0 )
vpcb.EnsureWinding( nvcont--, true );
......@@ -553,13 +583,10 @@ bool WriteTriangles( std::ofstream& file, VRML_IDS* vID, VRML_LAYER* layer, bool
file << "coord Coordinate {\n";
file << "point [\n";
// XXX: TODO: check return values of Write() routines; they may fail
// even though the stream is good (bad internal data)
// Coordinates (vertices)
if( plane )
{
if( ! layer->WriteVertices( top_z, file, precision ) )
if( !layer->WriteVertices( top_z, file, precision ) )
{
cerr << "* errors writing planar vertices to " << vID->objectName << "\n";
cerr << "** " << layer->GetError() << "\n";
......@@ -567,7 +594,7 @@ bool WriteTriangles( std::ofstream& file, VRML_IDS* vID, VRML_LAYER* layer, bool
}
else
{
if( ! layer->Write3DVertices( top_z, bottom_z, file, precision ) )
if( !layer->Write3DVertices( top_z, bottom_z, file, precision ) )
{
cerr << "* errors writing 3D vertices to " << vID->objectName << "\n";
cerr << "** " << layer->GetError() << "\n";
......@@ -717,6 +744,7 @@ bool MakeComponents( IDF3_BOARD& board, std::ofstream& file, bool compact )
std::map< std::string, VRML_IDS*> cmap; // map colors by outline UID
VRML_IDS* vcp;
IDF3_COMP_OUTLINE* pout;
while( sc != ec )
{
......@@ -732,12 +760,28 @@ bool MakeComponents( IDF3_BOARD& board, std::ofstream& file, bool compact )
while( so != eo )
{
if( (*so)->GetOutline()->GetThickness() < 0.00000001 && nozeroheights )
{
vpcb.Clear();
++so;
continue;
}
(*so)->GetOffsets( tX, tY, tZ, tA );
tX += vX;
tY += vY;
tA += vA;
vcp = GetColor( cmap, cidx, ((IDF3_COMP_OUTLINE*)((*so)->GetOutline()))->GetUID() );
if( ( pout = (IDF3_COMP_OUTLINE*)((*so)->GetOutline()) ) )
{
vcp = GetColor( cmap, cidx, pout->GetUID() );
}
else
{
vpcb.Clear();
++so;
continue;
}
if( !compact )
{
......@@ -764,6 +808,12 @@ bool MakeComponents( IDF3_BOARD& board, std::ofstream& file, bool compact )
if( !compact || !vcp->used )
{
vpcb.EnsureWinding( 0, false );
int nvcont = vpcb.GetNContours() - 1;
while( nvcont > 0 )
vpcb.EnsureWinding( nvcont--, true );
vpcb.Tesselate( NULL );
}
......@@ -792,6 +842,10 @@ bool MakeComponents( IDF3_BOARD& board, std::ofstream& file, bool compact )
vcp = GetColor( cmap, cidx, ((IDF3_COMP_OUTLINE*)((*so)->GetOutline()))->GetUID() );
vcp->bottom = bottom;
// note: this can happen because IDF allows some negative heights/thicknesses
if( bot > top )
std::swap( bot, top );
WriteTriangles( file, vcp, &vpcb, false,
false, top, bot, board.GetUserPrecision(), compact );
......@@ -828,7 +882,8 @@ VRML_IDS* GetColor( std::map<std::string, VRML_IDS*>& cmap, int& index, const st
ostr << "OBJECTn" << refnum++;
id->objectName = ostr.str();
cout << "* " << ostr.str() << " = '" << uid << "'\n";
if( showObjectMapping )
cout << "* " << ostr.str() << " = '" << uid << "'\n";
cmap.insert( std::pair<std::string, VRML_IDS*>(uid, id) );
......@@ -840,3 +895,93 @@ VRML_IDS* GetColor( std::map<std::string, VRML_IDS*>& cmap, int& index, const st
return cit->second;
}
bool MakeOtherOutlines( IDF3_BOARD& board, std::ofstream& file )
{
int cidx = 2; // color index; start at 2 since 0,1 are special (board, NOGEOM_NOPART)
VRML_LAYER vpcb;
double scale = board.GetUserScale();
double thick = board.GetBoardThickness() / 2.0;
// set the arc parameters according to output scale
int tI;
double tMin, tMax;
vpcb.GetArcParams( tI, tMin, tMax );
vpcb.SetArcParams( tI, tMin * scale, tMax * scale );
// Add the component outlines
const std::map< std::string, OTHER_OUTLINE* >*const comp = board.GetOtherOutlines();
std::map< std::string, OTHER_OUTLINE* >::const_iterator sc = comp->begin();
std::map< std::string, OTHER_OUTLINE* >::const_iterator ec = comp->end();
double top, bot;
bool bottom;
int nvcont;
std::map< std::string, VRML_IDS*> cmap; // map colors by outline UID
VRML_IDS* vcp;
OTHER_OUTLINE* pout;
while( sc != ec )
{
pout = sc->second;
if( pout->GetSide() == IDF3::LYR_BOTTOM )
bottom = true;
else
bottom = false;
if( pout->GetThickness() < 0.00000001 && nozeroheights )
{
vpcb.Clear();
++sc;
continue;
}
vcp = GetColor( cmap, cidx, pout->GetOutlineIdentifier() );
if( !PopulateVRML( vpcb, pout->GetOutlines(), bottom,
board.GetUserScale(), 0, 0, 0 ) )
{
return false;
}
vpcb.EnsureWinding( 0, false );
nvcont = vpcb.GetNContours() - 1;
while( nvcont > 0 )
vpcb.EnsureWinding( nvcont--, true );
vpcb.Tesselate( NULL );
if( bottom )
{
top = -thick;
bot = ( top - pout->GetThickness() ) * scale;
top *= scale;
}
else
{
bot = thick;
top = (bot + pout->GetThickness() ) * scale;
bot *= scale;
}
// note: this can happen because IDF allows some negative heights/thicknesses
if( bot > top )
std::swap( bot, top );
vcp->bottom = bottom;
WriteTriangles( file, vcp, &vpcb, false,
false, top, bot, board.GetUserPrecision(), false );
vpcb.Clear();
++sc;
}
return true;
}
This diff is collapsed.
......@@ -86,6 +86,16 @@ namespace IDF3 {
FILE_ERROR // other errors while processing the file
};
/**
* ENUM IDF_VERSION
* represents the supported IDF versions (3.0 and 2.0 ONLY)
*/
enum IDF_VERSION
{
IDF_V2 = 0, // version 2 has read support only; files written as IDFv3
IDF_V3 // version 3 has full read/write support
};
/**
* ENUM KEY_OWNER
* represents the type of CAD which has ownership an object
......@@ -194,6 +204,7 @@ namespace IDF3 {
{
UNIT_MM = 0, //< Units in the file are in millimeters
UNIT_THOU, //< Units in the file are in mils (aka thou)
UNIT_TNM, //< Deprecated Ten Nanometer Units from IDFv2
UNIT_INVALID
};
......@@ -261,6 +272,7 @@ namespace IDF3 {
*/
class IDF_NOTE
{
friend class IDF3_BOARD;
private:
std::string text; // note text as per IDFv3
double xpos; // text X position as per IDFv3
......@@ -268,11 +280,8 @@ private:
double height; // text height as per IDFv3
double length; // text length as per IDFv3
public:
IDF_NOTE();
/**
* Function ReadNote
* Function readNote
* reads a note entry from an IDFv3 file
*
* @param aBoardFile is an open BOARD file; the file position must be set to the start of a NOTE entry
......@@ -282,10 +291,10 @@ public:
* @return bool: true if a note item was read, false otherwise. In case of unrecoverable errors
* an exception is thrown
*/
bool ReadNote( std::ifstream& aBoardFile, IDF3::FILE_STATE& aBoardState, IDF3::IDF_UNIT aBoardUnit );
bool readNote( std::ifstream& aBoardFile, IDF3::FILE_STATE& aBoardState, IDF3::IDF_UNIT aBoardUnit );
/**
* Function WriteNote
* Function writeNote
* writes a note entry to an IDFv3 file
*
* @param aBoardFile is an open BOARD file; the file position must be within a NOTE section
......@@ -294,7 +303,10 @@ public:
* @return bool: true if the item was successfully written, false otherwise. In case of
* unrecoverable errors an exception is thrown
*/
bool WriteNote( std::ofstream& aBoardFile, IDF3::IDF_UNIT aBoardUnit );
bool writeNote( std::ofstream& aBoardFile, IDF3::IDF_UNIT aBoardUnit );
public:
IDF_NOTE();
/**
* Function SetText
......@@ -341,6 +353,8 @@ public:
*/
class IDF_DRILL_DATA
{
friend class IDF3_BOARD;
friend class IDF3_COMPONENT;
private:
double dia;
double x;
......@@ -352,11 +366,35 @@ private:
std::string holetype;
IDF3::KEY_OWNER owner;
/**
* Function read
* read a drill entry from an IDFv3 file
*
* @param aBoardFile is an open IDFv3 file; the file position must be within the DRILLED_HOLES section
* @param aBoardUnit is the board file's native unit (MM or THOU)
* @param aBoardState is the state value of the parser
*
* @return bool: true if data was successfully read, otherwise false. In case of an
* unrecoverable error an exception is thrown
*/
bool read( std::ifstream& aBoardFile, IDF3::IDF_UNIT aBoardUnit, IDF3::FILE_STATE aBoardState,
IDF3::IDF_VERSION aIdfVersion );
/**
* Function write
* writes a single line representing a hole within a .DRILLED_HOLES section
* In case of an unrecoverable error an exception is thrown.
*
* @param aBoardFile is an open BOARD file
* @param aBoardUnit is the native unit of the output file
*/
void write( std::ofstream& aBoardFile, IDF3::IDF_UNIT aBoardUnit );
public:
/**
* Constructor IDF_DRILL_DATA
* creates an empty drill entry which can be populated by the
* Read() function
* read() function
*/
IDF_DRILL_DATA();
......@@ -391,38 +429,12 @@ public:
*/
bool Matches( double aDrillDia, double aPosX, double aPosY );
/**
* Function Read
* read a drill entry from an IDFv3 file
*
* @param aBoardFile is an open IDFv3 file; the file position must be within the DRILLED_HOLES section
* @param aBoardUnit is the board file's native unit (MM or THOU)
* @param aBoardState is the state value of the parser
*
* @return bool: true if data was successfully read, otherwise false. In case of an
* unrecoverable error an exception is thrown
*/
bool Read( std::ifstream& aBoardFile, IDF3::IDF_UNIT aBoardUnit, IDF3::FILE_STATE aBoardState );
/**
* Function Write
* writes a single line representing a hole within a .DRILLED_HOLES section
*
* @param aBoardFile is an open BOARD file
* @param aBoardUnit is the native unit of the output file
*
* @return bool: true if the data was successfully written, otherwise false. In case of
* an unrecoverable error an exception is thrown
*/
bool Write( std::ofstream& aBoardFile, IDF3::IDF_UNIT aBoardUnit );
/**
* Function GettDrillDia
* returns the drill diameter in mm
*/
double GetDrillDia();
/**
* Function GettDrillXPos
* returns the drill's X position in mm
......@@ -455,6 +467,11 @@ public:
* PIN, VIA, MTG, TOOL, or a user-specified string
*/
const std::string& GetDrillHoleType();
IDF3::KEY_OWNER GetDrillOwner( void )
{
return owner;
}
};
......
......@@ -229,8 +229,13 @@ bool IDF3::WriteLayersText( std::ofstream& aBoardFile, IDF3::IDF_LAYER aLayer )
break;
default:
ERROR_IDF << "Invalid IDF layer" << aLayer << "\n";
return false;
do{
std::ostringstream ostr;
ostr << "invalid IDF layer: " << aLayer;
throw( IDF_ERROR( __FILE__, __FUNCTION__, __LINE__, ostr.str() ) );
} while( 0 );
break;
}
......@@ -293,3 +298,26 @@ std::string IDF3::GetLayerString( IDF3::IDF_LAYER aLayer )
return ostr.str();
}
std::string IDF3::GetOwnerString( IDF3::KEY_OWNER aOwner )
{
switch( aOwner )
{
case IDF3::UNOWNED:
return "UNOWNED";
case IDF3::MCAD:
return "MCAD";
case IDF3::ECAD:
return "ECAD";
default:
break;
}
ostringstream ostr;
ostr << "UNKNOWN: " << aOwner;
return ostr.str();
}
......@@ -59,9 +59,12 @@ static inline wxString FROM_UTF8( const char* cstring )
// minimum drill diameters / slot widths to be represented in the IDF output
#define IDF_MIN_DIA_MM ( 0.001 )
#define IDF_MIN_DIA_THOU ( 0.00039 )
#define IDF_MIN_DIA_TNM ( 100 )
// conversion between mm and thou
#define IDF_MM_TO_THOU 0.0254
// conversion from thou to mm
#define IDF_THOU_TO_MM 0.0254
// conversion from TNM to mm
#define IDF_TNM_TO_MM 0.00001
namespace IDF3
{
......@@ -166,6 +169,7 @@ std::string GetPlacementString( IDF3::IDF_PLACEMENT aPlacement );
*/
std::string GetLayerString( IDF3::IDF_LAYER aLayer );
std::string GetOwnerString( IDF3::KEY_OWNER aOwner );
}
#endif // IDF_HELPERS_H
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment