more specctra dsn work
This commit is contained in:
parent
0f3b3ee2cb
commit
300d50b1bc
|
@ -5,6 +5,16 @@ Please add newer entries at the top, list the date and your name with
|
||||||
email address.
|
email address.
|
||||||
|
|
||||||
|
|
||||||
|
2008-Jan-22 UPDATE Dick Hollenbeck <dick@softplc.com>
|
||||||
|
================================================================================
|
||||||
|
+pcbnew:
|
||||||
|
* Actually able now to export a *.dsn file, but the contents of the file
|
||||||
|
is incomplete, not a complete input BOARD.
|
||||||
|
* Added DRAWSEGMENT::Show() for debugging.
|
||||||
|
* Changed specctra.h's POINT to use double for coordinates. Changed format
|
||||||
|
string for Format()ing a double.
|
||||||
|
* Changed specctra_export.cpp to actually output an incomplete file.
|
||||||
|
|
||||||
|
|
||||||
2008-Jan-21 UPDATE Dick Hollenbeck <dick@softplc.com>
|
2008-Jan-21 UPDATE Dick Hollenbeck <dick@softplc.com>
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
|
@ -36,6 +36,14 @@
|
||||||
#include "pcbnew.h"
|
#include "pcbnew.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class LEXER
|
||||||
|
* implements a lexical analyzer for the SPECCTRA DSN file format. It
|
||||||
|
* reads lexical tokens from the current LINE_READER through the NextTok()
|
||||||
|
* function. The NextTok() function returns one of the DSN_T values.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
namespace DSN {
|
namespace DSN {
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -535,6 +535,7 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class LEXER
|
* Class LEXER
|
||||||
|
* implements a lexical analyzer for the SPECCTRA DSN file format. It
|
||||||
* reads lexical tokens from the current LINE_READER through the NextTok()
|
* reads lexical tokens from the current LINE_READER through the NextTok()
|
||||||
* function. The NextTok() function returns one of the DSN_T values.
|
* function. The NextTok() function returns one of the DSN_T values.
|
||||||
*/
|
*/
|
||||||
|
@ -635,7 +636,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Function ThrowIOError
|
* Function ThrowIOError
|
||||||
* encapsulates the formatting of an error message which contains the exact
|
* encapsulates the formatting of an error message which contains the exact
|
||||||
* location within the input file of a lexical error.
|
* location within the input file of something the caller is rejecting.
|
||||||
*/
|
*/
|
||||||
void ThrowIOError( wxString aText, int charOffset ) throw (IOError);
|
void ThrowIOError( wxString aText, int charOffset ) throw (IOError);
|
||||||
|
|
||||||
|
|
|
@ -55,11 +55,10 @@
|
||||||
#include <wx/ffile.h>
|
#include <wx/ffile.h>
|
||||||
|
|
||||||
|
|
||||||
#define STANDALONE 0 // set to 1 for "stand alone, i.e. unit testing"
|
//#define STANDALONE // define "stand alone, i.e. unit testing"
|
||||||
// set to 0 for component of pcbnew
|
|
||||||
|
|
||||||
|
|
||||||
#if STANDALONE
|
#if defined(STANDALONE)
|
||||||
#define EDA_BASE // build_version.h behavior
|
#define EDA_BASE // build_version.h behavior
|
||||||
#undef COMMON_GLOBL
|
#undef COMMON_GLOBL
|
||||||
#define COMMON_GLOBL // build_version.h behavior
|
#define COMMON_GLOBL // build_version.h behavior
|
||||||
|
@ -3326,7 +3325,7 @@ const char* SPECCTRA_DB::GetQuoteChar( const char* wrapee )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SPECCTRA_DB::ExportPCB( wxString filename ) throw( IOError )
|
void SPECCTRA_DB::ExportPCB( wxString filename, bool aNameChange ) throw( IOError )
|
||||||
{
|
{
|
||||||
fp = wxFopen( filename, wxT("w") );
|
fp = wxFopen( filename, wxT("w") );
|
||||||
|
|
||||||
|
@ -3336,7 +3335,15 @@ void SPECCTRA_DB::ExportPCB( wxString filename ) throw( IOError )
|
||||||
}
|
}
|
||||||
|
|
||||||
if( pcb )
|
if( pcb )
|
||||||
|
{
|
||||||
|
if( aNameChange )
|
||||||
|
pcb->pcbname = CONV_TO_UTF8(filename);
|
||||||
|
|
||||||
pcb->Format( this, 0 );
|
pcb->Format( this, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// if an exception is thrown by Format, then ~SPECCTRA_DB() will close
|
||||||
|
// the file.
|
||||||
|
|
||||||
fclose( fp );
|
fclose( fp );
|
||||||
fp = 0;
|
fp = 0;
|
||||||
|
@ -3369,6 +3376,7 @@ PCB* SPECCTRA_DB::MakePCB()
|
||||||
pcb->unit = new UNIT_RES( pcb, T_unit );
|
pcb->unit = new UNIT_RES( pcb, T_unit );
|
||||||
|
|
||||||
pcb->structure = new STRUCTURE( pcb );
|
pcb->structure = new STRUCTURE( pcb );
|
||||||
|
pcb->structure->boundary = new BOUNDARY( pcb->structure );
|
||||||
|
|
||||||
pcb->placement = new PLACEMENT( pcb );
|
pcb->placement = new PLACEMENT( pcb );
|
||||||
|
|
||||||
|
@ -3506,13 +3514,13 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
||||||
}
|
}
|
||||||
|
|
||||||
if( hasVertex )
|
if( hasVertex )
|
||||||
out->Print( 0, " %f %f", vertex.x, vertex.y );
|
out->Print( 0, " %.6g %.6g", vertex.x, vertex.y );
|
||||||
|
|
||||||
if( side != T_NONE )
|
if( side != T_NONE )
|
||||||
out->Print( 0, " %s", LEXER::GetTokenText( side ) );
|
out->Print( 0, " %s", LEXER::GetTokenText( side ) );
|
||||||
|
|
||||||
if( isRotated )
|
if( isRotated )
|
||||||
out->Print( 0, " %f", rotation );
|
out->Print( 0, " %.6g", rotation );
|
||||||
|
|
||||||
if( mirror != T_NONE )
|
if( mirror != T_NONE )
|
||||||
out->Print( 0, " (mirror %s)", LEXER::GetTokenText( mirror ) );
|
out->Print( 0, " (mirror %s)", LEXER::GetTokenText( mirror ) );
|
||||||
|
@ -3572,7 +3580,7 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
||||||
|
|
||||||
// unit test this source file
|
// unit test this source file
|
||||||
|
|
||||||
#if STANDALONE
|
#if defined(STANDALONE)
|
||||||
|
|
||||||
using namespace DSN;
|
using namespace DSN;
|
||||||
|
|
||||||
|
|
|
@ -106,11 +106,21 @@ public:
|
||||||
|
|
||||||
struct POINT
|
struct POINT
|
||||||
{
|
{
|
||||||
float x;
|
double x;
|
||||||
float y;
|
double y;
|
||||||
|
|
||||||
POINT() { x=0.0; y=0.0; }
|
POINT() { x=0.0; y=0.0; }
|
||||||
|
|
||||||
|
bool operator==( const POINT& other ) const
|
||||||
|
{
|
||||||
|
return x==other.x && y==other.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=( const POINT& other ) const
|
||||||
|
{
|
||||||
|
return !( *this == other );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function Format
|
* Function Format
|
||||||
* writes this object as ASCII out to an OUTPUTFORMATTER according to the
|
* writes this object as ASCII out to an OUTPUTFORMATTER according to the
|
||||||
|
@ -121,7 +131,7 @@ struct POINT
|
||||||
*/
|
*/
|
||||||
void Format( OUTPUTFORMATTER* out, int nestLevel ) const throw( IOError )
|
void Format( OUTPUTFORMATTER* out, int nestLevel ) const throw( IOError )
|
||||||
{
|
{
|
||||||
out->Print( nestLevel, " %f %f", x, y );
|
out->Print( nestLevel, " %.6g %.6g", x, y );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -161,6 +171,8 @@ typedef std::vector<PROPERTY> PROPERTIES;
|
||||||
*/
|
*/
|
||||||
class ELEM
|
class ELEM
|
||||||
{
|
{
|
||||||
|
friend class SPECCTRA_DB;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DSN_T type;
|
DSN_T type;
|
||||||
ELEM* parent;
|
ELEM* parent;
|
||||||
|
@ -213,6 +225,11 @@ public:
|
||||||
{
|
{
|
||||||
// overridden in ELEM_HOLDER
|
// overridden in ELEM_HOLDER
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetParent( ELEM* aParent )
|
||||||
|
{
|
||||||
|
parent = aParent;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -223,7 +240,8 @@ public:
|
||||||
*/
|
*/
|
||||||
class ELEM_HOLDER : public ELEM
|
class ELEM_HOLDER : public ELEM
|
||||||
{
|
{
|
||||||
// see http://www.boost.org/libs/ptr_container/doc/ptr_sequence_adapter.html
|
friend class SPECCTRA_DB;
|
||||||
|
|
||||||
typedef boost::ptr_vector<ELEM> ELEM_ARRAY;
|
typedef boost::ptr_vector<ELEM> ELEM_ARRAY;
|
||||||
|
|
||||||
ELEM_ARRAY kids; ///< ELEM pointers
|
ELEM_ARRAY kids; ///< ELEM pointers
|
||||||
|
@ -393,7 +411,7 @@ public:
|
||||||
{
|
{
|
||||||
const char* quote = out->GetQuoteChar( layer_id.c_str() );
|
const char* quote = out->GetQuoteChar( layer_id.c_str() );
|
||||||
|
|
||||||
out->Print( nestLevel, "(%s %s%s%s %f %f %f %f)\n",
|
out->Print( nestLevel, "(%s %s%s%s %.6g %.6g %.6g %.6g)\n",
|
||||||
LEXER::GetTokenText( Type() ),
|
LEXER::GetTokenText( Type() ),
|
||||||
quote, layer_id.c_str(), quote,
|
quote, layer_id.c_str(), quote,
|
||||||
point0.x, point0.y,
|
point0.x, point0.y,
|
||||||
|
@ -546,7 +564,7 @@ class PATH : public ELEM
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PATH( ELEM* aParent, DSN_T aType ) :
|
PATH( ELEM* aParent, DSN_T aType = T_path ) :
|
||||||
ELEM( aType, aParent )
|
ELEM( aType, aParent )
|
||||||
{
|
{
|
||||||
aperture_width = 0.0;
|
aperture_width = 0.0;
|
||||||
|
@ -561,13 +579,13 @@ public:
|
||||||
{
|
{
|
||||||
const char* quote = out->GetQuoteChar( layer_id.c_str() );
|
const char* quote = out->GetQuoteChar( layer_id.c_str() );
|
||||||
|
|
||||||
out->Print( nestLevel, "(%s %s%s%s %f\n", LEXER::GetTokenText( Type() ),
|
out->Print( nestLevel, "(%s %s%s%s %.6g\n", LEXER::GetTokenText( Type() ),
|
||||||
quote, layer_id.c_str(), quote,
|
quote, layer_id.c_str(), quote,
|
||||||
aperture_width );
|
aperture_width );
|
||||||
|
|
||||||
for( unsigned i=0; i<points.size(); ++i )
|
for( unsigned i=0; i<points.size(); ++i )
|
||||||
{
|
{
|
||||||
out->Print( nestLevel+1, "%f %f\n", points[i].x, points[i].y );
|
out->Print( nestLevel+1, "%.6g %.6g\n", points[i].x, points[i].y );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( aperture_type == T_square )
|
if( aperture_type == T_square )
|
||||||
|
@ -587,6 +605,7 @@ class BOUNDARY : public ELEM
|
||||||
PATHS paths;
|
PATHS paths;
|
||||||
RECTANGLE* rectangle;
|
RECTANGLE* rectangle;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
BOUNDARY( ELEM* aParent, DSN_T aType = T_boundary ) :
|
BOUNDARY( ELEM* aParent, DSN_T aType = T_boundary ) :
|
||||||
|
@ -636,7 +655,7 @@ public:
|
||||||
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
||||||
{
|
{
|
||||||
const char* quote = out->GetQuoteChar( layer_id.c_str() );
|
const char* quote = out->GetQuoteChar( layer_id.c_str() );
|
||||||
out->Print( nestLevel, "(%s %s%s%s %f %f %f)\n", LEXER::GetTokenText( Type() ) ,
|
out->Print( nestLevel, "(%s %s%s%s %.6g %.6g %.6g)\n", LEXER::GetTokenText( Type() ) ,
|
||||||
quote, layer_id.c_str(), quote,
|
quote, layer_id.c_str(), quote,
|
||||||
diameter, vertex.x, vertex.y );
|
diameter, vertex.x, vertex.y );
|
||||||
}
|
}
|
||||||
|
@ -661,12 +680,12 @@ public:
|
||||||
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
||||||
{
|
{
|
||||||
const char* quote = out->GetQuoteChar( layer_id.c_str() );
|
const char* quote = out->GetQuoteChar( layer_id.c_str() );
|
||||||
out->Print( nestLevel, "(%s %s%s%s %f\n", LEXER::GetTokenText( Type() ) ,
|
out->Print( nestLevel, "(%s %s%s%s %.6g\n", LEXER::GetTokenText( Type() ) ,
|
||||||
quote, layer_id.c_str(), quote,
|
quote, layer_id.c_str(), quote,
|
||||||
aperture_width);
|
aperture_width);
|
||||||
|
|
||||||
for( int i=0; i<3; ++i )
|
for( int i=0; i<3; ++i )
|
||||||
out->Print( nestLevel+1, "%f %f\n", vertex[i].x, vertex[i].y );
|
out->Print( nestLevel+1, "%.6g %.6g\n", vertex[i].x, vertex[i].y );
|
||||||
|
|
||||||
out->Print( nestLevel, ")\n" );
|
out->Print( nestLevel, ")\n" );
|
||||||
}
|
}
|
||||||
|
@ -1072,7 +1091,7 @@ public:
|
||||||
const char* quote0 = out->GetQuoteChar( layer_id0.c_str() );
|
const char* quote0 = out->GetQuoteChar( layer_id0.c_str() );
|
||||||
const char* quote1 = out->GetQuoteChar( layer_id1.c_str() );
|
const char* quote1 = out->GetQuoteChar( layer_id1.c_str() );
|
||||||
|
|
||||||
out->Print( nestLevel, "(%s %s%s%s %s%s%s %f)\n", LEXER::GetTokenText( Type() ),
|
out->Print( nestLevel, "(%s %s%s%s %s%s%s %.6g)\n", LEXER::GetTokenText( Type() ),
|
||||||
quote0, layer_id0.c_str(), quote0,
|
quote0, layer_id0.c_str(), quote0,
|
||||||
quote1, layer_id1.c_str(), quote1,
|
quote1, layer_id1.c_str(), quote1,
|
||||||
layer_weight );
|
layer_weight );
|
||||||
|
@ -1113,7 +1132,7 @@ class PLANE : public KEEPOUT
|
||||||
public:
|
public:
|
||||||
PLANE( ELEM* aParent ) :
|
PLANE( ELEM* aParent ) :
|
||||||
KEEPOUT( aParent, T_plane )
|
KEEPOUT( aParent, T_plane )
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1232,11 +1251,11 @@ class GRID : public ELEM
|
||||||
|
|
||||||
DSN_T grid_type; ///< T_via | T_wire | T_via_keepout | T_place | T_snap
|
DSN_T grid_type; ///< T_via | T_wire | T_via_keepout | T_place | T_snap
|
||||||
|
|
||||||
float dimension;
|
double dimension;
|
||||||
|
|
||||||
DSN_T direction; ///< T_x | T_y | -1 for both
|
DSN_T direction; ///< T_x | T_y | -1 for both
|
||||||
|
|
||||||
float offset;
|
double offset;
|
||||||
|
|
||||||
DSN_T image_type;
|
DSN_T image_type;
|
||||||
|
|
||||||
|
@ -1254,7 +1273,7 @@ public:
|
||||||
|
|
||||||
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
||||||
{
|
{
|
||||||
out->Print( nestLevel, "(%s %s %f",
|
out->Print( nestLevel, "(%s %s %.6g",
|
||||||
LEXER::GetTokenText( Type() ),
|
LEXER::GetTokenText( Type() ),
|
||||||
LEXER::GetTokenText( grid_type ), dimension );
|
LEXER::GetTokenText( grid_type ), dimension );
|
||||||
|
|
||||||
|
@ -1270,7 +1289,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
if( offset != 0.0 )
|
if( offset != 0.0 )
|
||||||
out->Print( 0, " (offset %f)", offset );
|
out->Print( 0, " (offset %.6g)", offset );
|
||||||
|
|
||||||
out->Print( 0, ")\n");
|
out->Print( 0, ")\n");
|
||||||
}
|
}
|
||||||
|
@ -1335,6 +1354,24 @@ public:
|
||||||
delete place_rules;
|
delete place_rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetBOUNDARY( BOUNDARY *aBoundary )
|
||||||
|
{
|
||||||
|
delete boundary;
|
||||||
|
boundary = aBoundary;
|
||||||
|
if( boundary )
|
||||||
|
{
|
||||||
|
boundary->SetParent( this );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPlaceBOUNDARY( BOUNDARY *aBoundary )
|
||||||
|
{
|
||||||
|
delete place_boundary;
|
||||||
|
place_boundary = aBoundary;
|
||||||
|
if( place_boundary )
|
||||||
|
place_boundary->SetParent( this );
|
||||||
|
}
|
||||||
|
|
||||||
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
||||||
{
|
{
|
||||||
if( unit )
|
if( unit )
|
||||||
|
@ -1401,7 +1438,7 @@ class PLACE : public ELEM
|
||||||
DSN_T side;
|
DSN_T side;
|
||||||
|
|
||||||
bool isRotated;
|
bool isRotated;
|
||||||
float rotation;
|
double rotation;
|
||||||
|
|
||||||
bool hasVertex;
|
bool hasVertex;
|
||||||
POINT vertex;
|
POINT vertex;
|
||||||
|
@ -1457,7 +1494,7 @@ public:
|
||||||
|
|
||||||
void SetRotation( double aRotation )
|
void SetRotation( double aRotation )
|
||||||
{
|
{
|
||||||
rotation = (float) aRotation;
|
rotation = aRotation;
|
||||||
isRotated = (aRotation != 0.0);
|
isRotated = (aRotation != 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1607,7 +1644,7 @@ class PIN : public ELEM
|
||||||
friend class SPECCTRA_DB;
|
friend class SPECCTRA_DB;
|
||||||
|
|
||||||
std::string padstack_id;
|
std::string padstack_id;
|
||||||
float rotation;
|
double rotation;
|
||||||
bool isRotated;
|
bool isRotated;
|
||||||
std::string pin_id;
|
std::string pin_id;
|
||||||
POINT vertex;
|
POINT vertex;
|
||||||
|
@ -1622,7 +1659,7 @@ public:
|
||||||
|
|
||||||
void SetRotation( double aRotation )
|
void SetRotation( double aRotation )
|
||||||
{
|
{
|
||||||
rotation = (float) aRotation;
|
rotation = aRotation;
|
||||||
isRotated = (aRotation != 0.0);
|
isRotated = (aRotation != 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1630,7 +1667,7 @@ public:
|
||||||
{
|
{
|
||||||
const char* quote = out->GetQuoteChar( padstack_id.c_str() );
|
const char* quote = out->GetQuoteChar( padstack_id.c_str() );
|
||||||
if( isRotated )
|
if( isRotated )
|
||||||
out->Print( nestLevel, "(pin %s%s%s (rotate %1.2f)",
|
out->Print( nestLevel, "(pin %s%s%s (rotate %.6g)",
|
||||||
quote, padstack_id.c_str(), quote,
|
quote, padstack_id.c_str(), quote,
|
||||||
rotation
|
rotation
|
||||||
);
|
);
|
||||||
|
@ -1638,7 +1675,7 @@ public:
|
||||||
out->Print( nestLevel, "(pin %s%s%s", quote, padstack_id.c_str(), quote );
|
out->Print( nestLevel, "(pin %s%s%s", quote, padstack_id.c_str(), quote );
|
||||||
|
|
||||||
quote = out->GetQuoteChar( pin_id.c_str() );
|
quote = out->GetQuoteChar( pin_id.c_str() );
|
||||||
out->Print( 0, " %s%s%s %f %f)\n", quote, pin_id.c_str(), quote,
|
out->Print( 0, " %s%s%s %.6g %.6g)\n", quote, pin_id.c_str(), quote,
|
||||||
vertex.x, vertex.y );
|
vertex.x, vertex.y );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2356,11 +2393,11 @@ public:
|
||||||
{
|
{
|
||||||
out->Print( 0, "\n" );
|
out->Print( 0, "\n" );
|
||||||
perLine = 0;
|
perLine = 0;
|
||||||
perLine += out->Print( nestLevel+1, "%f %f", i->x, i->y );
|
perLine += out->Print( nestLevel+1, "%.6g %.6g", i->x, i->y );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
perLine += out->Print( 0, " %f %f", i->x, i->y );
|
perLine += out->Print( 0, " %.6g %.6g", i->x, i->y );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out->Print( 0, "\n" );
|
out->Print( 0, "\n" );
|
||||||
|
@ -2371,6 +2408,9 @@ public:
|
||||||
out->Print( nestLevel+1, "(net %s%s%s)\n", quote, net_id.c_str(), quote );
|
out->Print( nestLevel+1, "(net %s%s%s)\n", quote, net_id.c_str(), quote );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( via_number != -1 )
|
||||||
|
out->Print( nestLevel+1, "(via_number %d)\n", via_number );
|
||||||
|
|
||||||
if( type != T_NONE )
|
if( type != T_NONE )
|
||||||
out->Print( nestLevel+1, "(type %s)\n", LEXER::GetTokenText( type ) );
|
out->Print( nestLevel+1, "(type %s)\n", LEXER::GetTokenText( type ) );
|
||||||
|
|
||||||
|
@ -2599,10 +2639,6 @@ public:
|
||||||
{
|
{
|
||||||
time_stamp = time(NULL);
|
time_stamp = time(NULL);
|
||||||
}
|
}
|
||||||
~HISTORY()
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
||||||
{
|
{
|
||||||
|
@ -3071,6 +3107,14 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
|
||||||
void doNET_OUT( NET_OUT* growth ) throw( IOError );
|
void doNET_OUT( NET_OUT* growth ) throw( IOError );
|
||||||
void doSUPPLY_PIN( SUPPLY_PIN* growth ) throw( IOError );
|
void doSUPPLY_PIN( SUPPLY_PIN* growth ) throw( IOError );
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function exportEdges
|
||||||
|
* exports the EDGES_N layer of the board.
|
||||||
|
*/
|
||||||
|
void exportEdges( BOARD* aBoard ) throw( IOError );
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
SPECCTRA_DB()
|
SPECCTRA_DB()
|
||||||
|
@ -3160,9 +3204,11 @@ public:
|
||||||
* writes the internal PCB instance out as a SPECTRA DSN format file.
|
* writes the internal PCB instance out as a SPECTRA DSN format file.
|
||||||
*
|
*
|
||||||
* @param aFilename The file to save to.
|
* @param aFilename The file to save to.
|
||||||
|
* @param aNameChange If true, causes the pcb's name to change to "aFilename"
|
||||||
|
* and also to to be changed in the output file.
|
||||||
* @throw IOError, if an i/o error occurs saving the file.
|
* @throw IOError, if an i/o error occurs saving the file.
|
||||||
*/
|
*/
|
||||||
void ExportPCB( wxString aFilename ) throw( IOError );
|
void ExportPCB( wxString aFilename, bool aNameChange=false ) throw( IOError );
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include "specctra.h"
|
#include "specctra.h"
|
||||||
|
#include "collectors.h"
|
||||||
|
|
||||||
using namespace DSN;
|
using namespace DSN;
|
||||||
|
|
||||||
|
@ -40,6 +41,25 @@ using namespace DSN;
|
||||||
// see wxPcbStruct.h
|
// see wxPcbStruct.h
|
||||||
void WinEDA_PcbFrame::ExportToSPECCTRA( wxCommandEvent& event )
|
void WinEDA_PcbFrame::ExportToSPECCTRA( wxCommandEvent& event )
|
||||||
{
|
{
|
||||||
|
wxString fullFileName = GetScreen()->m_FileName;
|
||||||
|
wxString std_ext = wxT( ".dsn" );
|
||||||
|
wxString mask = wxT( "*" ) + std_ext;
|
||||||
|
|
||||||
|
ChangeFileNameExt( fullFileName, std_ext );
|
||||||
|
|
||||||
|
fullFileName = EDA_FileSelector( _( "Specctra DSN file:" ),
|
||||||
|
wxEmptyString, /* Chemin par defaut */
|
||||||
|
fullFileName, /* nom fichier par defaut */
|
||||||
|
std_ext, /* extension par defaut */
|
||||||
|
mask, /* Masque d'affichage */
|
||||||
|
this,
|
||||||
|
wxFD_SAVE,
|
||||||
|
FALSE
|
||||||
|
);
|
||||||
|
if( fullFileName == wxEmptyString )
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
SPECCTRA_DB db;
|
SPECCTRA_DB db;
|
||||||
|
|
||||||
db.SetPCB( SPECCTRA_DB::MakePCB() );
|
db.SetPCB( SPECCTRA_DB::MakePCB() );
|
||||||
|
@ -47,21 +67,212 @@ void WinEDA_PcbFrame::ExportToSPECCTRA( wxCommandEvent& event )
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
db.FromBOARD( m_Pcb );
|
db.FromBOARD( m_Pcb );
|
||||||
// db.Export( filename );
|
db.ExportPCB( fullFileName, true );
|
||||||
}
|
}
|
||||||
catch ( IOError ioe )
|
catch ( IOError ioe )
|
||||||
{
|
{
|
||||||
|
DisplayError( this, ioe.errorText );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if an exception is thrown by FromBOARD or Export(), then
|
||||||
|
// ~SPECCTRA_DB() will close the file.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace DSN {
|
namespace DSN {
|
||||||
|
|
||||||
|
struct POINT_PAIR
|
||||||
|
{
|
||||||
|
POINT p1; ///< start
|
||||||
|
POINT p2; ///< end
|
||||||
|
BOARD_ITEM* item; ///< the item which has these points, TRACK or DRAWSEGMENT
|
||||||
|
};
|
||||||
|
typedef std::vector<POINT_PAIR> POINT_PAIRS;
|
||||||
|
|
||||||
|
|
||||||
|
static inline void swap( POINT_PAIR& pair )
|
||||||
|
{
|
||||||
|
POINT temp = pair.p1;
|
||||||
|
pair.p1 = pair.p2;
|
||||||
|
pair.p2 = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static POINT mapPt( const wxPoint& pt )
|
||||||
|
{
|
||||||
|
POINT ret;
|
||||||
|
ret.x = pt.x;
|
||||||
|
ret.y = -pt.y; // make y negative, since it is increasing going down.
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function swapEnds
|
||||||
|
* will swap ends of any POINT_PAIR in the POINT_PAIRS list in order to
|
||||||
|
* make the consecutive POINT_PAIRs be "connected" at their ends.
|
||||||
|
*/
|
||||||
|
static void swapEnds( POINT_PAIRS& aList )
|
||||||
|
{
|
||||||
|
POINT temp;
|
||||||
|
|
||||||
|
if( aList.size() <= 1 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
for( unsigned i=0; i<aList.size(); ++i )
|
||||||
|
{
|
||||||
|
if( aList[i].p1 == aList[i+1].p1 )
|
||||||
|
swap( aList[i] );
|
||||||
|
|
||||||
|
else if( aList[i].p1 == aList[i+1].p2 )
|
||||||
|
{
|
||||||
|
swap( aList[i] );
|
||||||
|
swap( aList[i+1] );
|
||||||
|
++i; // skip next one, we swapped i+1 here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function isRectangle
|
||||||
|
* tests to see if the POINT_PAIRS list make up a vertically/horizontally
|
||||||
|
* oriented rectangle.
|
||||||
|
* @return bool - true if there are 4 point pairs making a rectangle.
|
||||||
|
*/
|
||||||
|
static bool isRectangle( POINT_PAIRS& aList )
|
||||||
|
{
|
||||||
|
if( aList.size() == 4 )
|
||||||
|
{
|
||||||
|
for( unsigned i=0; i<aList.size(); ++i )
|
||||||
|
{
|
||||||
|
if( i < aList.size()-1 )
|
||||||
|
if( aList[i].p2 != aList[i+1].p1 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( aList[i].p1.x != aList[i].p2.x
|
||||||
|
&& aList[i].p1.y != aList[i].p2.y )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ( aList[0].p1 == aList[3].p2 );
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SPECCTRA_DB::exportEdges( BOARD* aBoard ) throw( IOError )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )
|
void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )
|
||||||
{
|
{
|
||||||
|
TYPE_COLLECTOR items;
|
||||||
|
POINT_PAIRS ppairs;
|
||||||
|
POINT_PAIR pair;
|
||||||
|
|
||||||
|
if( !pcb )
|
||||||
|
pcb = SPECCTRA_DB::MakePCB();
|
||||||
|
|
||||||
|
//-----<header stuff>-------------------------------------------------
|
||||||
|
pcb->unit->units = T_mil;
|
||||||
|
pcb->resolution->units = T_mil;
|
||||||
|
pcb->resolution->value = 10;
|
||||||
|
|
||||||
|
//-----<board edges>--------------------------------------------------
|
||||||
|
|
||||||
|
// get all the DRAWSEGMENTS into 'items', then look for layer == EDGE_N,
|
||||||
|
// and those segments comprize the board's perimeter.
|
||||||
|
const KICAD_T scanDRAWSEGMENTS[] = { TYPEDRAWSEGMENT, EOT };
|
||||||
|
items.Collect( aBoard, scanDRAWSEGMENTS );
|
||||||
|
|
||||||
|
bool haveEdges = false;
|
||||||
|
ppairs.clear();
|
||||||
|
for( int i=0; i<items.GetCount(); ++i )
|
||||||
|
{
|
||||||
|
DRAWSEGMENT* item = (DRAWSEGMENT*) items[i];
|
||||||
|
|
||||||
|
wxASSERT( item->Type() == TYPEDRAWSEGMENT );
|
||||||
|
|
||||||
|
if( item->GetLayer() == EDGE_N )
|
||||||
|
{
|
||||||
|
pair.p1 = mapPt( item->m_Start );
|
||||||
|
pair.p2 = mapPt( item->m_End );
|
||||||
|
pair.item = item;
|
||||||
|
ppairs.push_back( pair );
|
||||||
|
haveEdges = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( haveEdges )
|
||||||
|
{
|
||||||
|
swapEnds( ppairs );
|
||||||
|
|
||||||
|
#if defined(DEBUG)
|
||||||
|
for( unsigned i=0; i<ppairs.size(); ++i )
|
||||||
|
{
|
||||||
|
POINT_PAIR* p = &ppairs[i];
|
||||||
|
p->item->Show( 0, std::cout );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
BOUNDARY* boundary = new BOUNDARY(0);
|
||||||
|
|
||||||
|
if( isRectangle( ppairs ) )
|
||||||
|
{
|
||||||
|
RECTANGLE* rect = new RECTANGLE( boundary );
|
||||||
|
|
||||||
|
rect->layer_id = "pcb";
|
||||||
|
// opposite corners
|
||||||
|
rect->point0 = ppairs[0].p1;
|
||||||
|
rect->point1 = ppairs[2].p1;
|
||||||
|
|
||||||
|
boundary->rectangle = rect;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PATH* path = new PATH( boundary );
|
||||||
|
|
||||||
|
path->layer_id = "pcb";
|
||||||
|
for( unsigned i=0; i<ppairs.size(); ++i )
|
||||||
|
{
|
||||||
|
// unless its a closed polygon, this probably won't work,
|
||||||
|
// otherwise it will.
|
||||||
|
path->points.push_back( ppairs[i].p1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
boundary->paths.push_back( path );
|
||||||
|
}
|
||||||
|
|
||||||
|
pcb->structure->SetBOUNDARY( boundary );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aBoard->ComputeBoundaryBox();
|
||||||
|
|
||||||
|
BOUNDARY* boundary = new BOUNDARY(0);
|
||||||
|
RECTANGLE* rect = new RECTANGLE( boundary );
|
||||||
|
|
||||||
|
rect->layer_id = "pcb";
|
||||||
|
|
||||||
|
// opposite corners
|
||||||
|
wxPoint bottomRight;
|
||||||
|
bottomRight.x = aBoard->m_BoundaryBox.GetRight();
|
||||||
|
bottomRight.y = aBoard->m_BoundaryBox.GetBottom();
|
||||||
|
|
||||||
|
rect->point0 = mapPt( aBoard->m_BoundaryBox.GetOrigin() );
|
||||||
|
rect->point1 = mapPt( bottomRight );
|
||||||
|
|
||||||
|
boundary->rectangle = rect;
|
||||||
|
|
||||||
|
pcb->structure->SetBOUNDARY( boundary );
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----<layers>-------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue