Loading change_log.txt +8 −0 Original line number Original line Diff line number Diff line Loading @@ -5,6 +5,14 @@ Please add newer entries at the top, list the date and your name with email address. email address. 2008-Jan-25 UPDATE Dick Hollenbeck <dick@softplc.com> ================================================================================ +pcbnew: SPECCTRA export does padstacks ok, except that oval arcs need to be split into quarter circle arcs, and no consideration is given to "layer types" See page bottom of page 74 of the SECCTRA Design Language Reference, May 2000. Still working today... 2008-Jan-25 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr> 2008-Jan-25 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr> ================================================================================ ================================================================================ Loading pcbnew/specctra.cpp +9 −17 Original line number Original line Diff line number Diff line Loading @@ -1985,7 +1985,7 @@ void SPECCTRA_DB::doSHAPE( SHAPE* growth ) throw( IOError ) case T_polygon: case T_polygon: case T_qarc: case T_qarc: L_done_that: L_done_that: if( growth->Length() ) if( growth->shape ) unexpected( tok ); unexpected( tok ); break; break; default: default: Loading @@ -2000,32 +2000,24 @@ L_done_that: switch( tok ) switch( tok ) { { case T_rect: case T_rect: RECTANGLE* rectangle; growth->shape = new RECTANGLE( growth ); rectangle = new RECTANGLE( growth ); doRECTANGLE( (RECTANGLE*) growth->shape ); growth->Append( rectangle ); doRECTANGLE( rectangle ); break; break; case T_circle: case T_circle: CIRCLE* circle; growth->shape = new CIRCLE( growth ); circle = new CIRCLE( growth ); doCIRCLE( (CIRCLE*)growth->shape ); growth->Append( circle ); doCIRCLE( circle ); break; break; case T_path: case T_path: case T_polygon: case T_polygon: PATH* path; growth->shape = new PATH( growth, tok ); path = new PATH( growth, tok ); doPATH( (PATH*)growth->shape ); growth->Append( path ); doPATH( path ); break; break; case T_qarc: case T_qarc: QARC* qarc; growth->shape = new QARC( growth ); qarc = new QARC( growth ); doQARC( (QARC*)growth->shape ); growth->Append( qarc ); doQARC( qarc ); break; break; case T_connect: case T_connect: Loading pcbnew/specctra.h +139 −34 Original line number Original line Diff line number Diff line Loading @@ -126,6 +126,25 @@ struct POINT return !( *this == other ); return !( *this == other ); } } POINT& operator+=( const POINT& other ) { x += other.x; y += other.y; return *this; } POINT& operator=( const POINT& other ) { x = other.x; if( x == -0.0 ) // correct -0.0 so output looks nice. x = 0.0; y = other.y; if( y == -0.0 ) y = 0.0; return *this; } /** /** * 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 Loading Loading @@ -425,13 +444,16 @@ public: void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { { const char* newline = nestLevel ? "\n" : ""; 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 %.6g %.6g %.6g %.6g)\n", out->Print( nestLevel, "(%s %s%s%s %.6g %.6g %.6g %.6g)%s", 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, point1.x, point1.y ); point1.x, point1.y, newline ); } } }; }; Loading Loading @@ -587,12 +609,20 @@ public: aperture_type = T_round; aperture_type = T_round; } } ~PATH() void AppendPoint( const POINT& aPoint ) { { points.push_back( aPoint ); } void SetLayerId( const char* aLayerId ) { layer_id = aLayerId; } } void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { { const char* newline = nestLevel ? "\n" : ""; const char* quote = out->GetQuoteChar( layer_id.c_str() ); const char* quote = out->GetQuoteChar( layer_id.c_str() ); const int RIGHTMARGIN = 80; const int RIGHTMARGIN = 80; Loading @@ -607,6 +637,7 @@ public: { { out->Print( 0, "\n" ); out->Print( 0, "\n" ); perLine = out->Print( nestLevel+1, "%s", "" ); perLine = out->Print( nestLevel+1, "%s", "" ); newline = "\n"; } } else else perLine += out->Print( 0, " " ); perLine += out->Print( 0, " " ); Loading @@ -617,10 +648,10 @@ public: if( aperture_type == T_square ) if( aperture_type == T_square ) { { out->Print( 0, "\n" ); out->Print( 0, "\n" ); out->Print( nestLevel+1, "(aperture_type square)\n" ); out->Print( nestLevel+1, "(aperture_type square))\n" ); } } else out->Print( 0, ")\n" ); out->Print( 0, ")%s", newline ); } } }; }; typedef boost::ptr_vector<PATH> PATHS; typedef boost::ptr_vector<PATH> PATHS; Loading Loading @@ -672,7 +703,7 @@ class CIRCLE : public ELEM std::string layer_id; std::string layer_id; double diameter; double diameter; POINT vertex; POINT vertex; // POINT's constructor sets to (0,0) public: public: CIRCLE( ELEM* aParent ) : CIRCLE( ELEM* aParent ) : Loading @@ -683,10 +714,17 @@ public: void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { { const char* newline = nestLevel ? "\n" : ""; 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 %.6g %.6g %.6g)\n", LEXER::GetTokenText( Type() ) , out->Print( nestLevel, "(%s %s%s%s %.6g", LEXER::GetTokenText( Type() ), quote, layer_id.c_str(), quote, quote, layer_id.c_str(), quote, diameter, vertex.x, vertex.y ); diameter ); if( vertex.x!=0.0 || vertex.y!=0.0 ) out->Print( 0, " %.6g %.6g)%s", vertex.x, vertex.y, newline ); else out->Print( 0, ")%s", newline ); } } void SetLayerId( const char* aLayerId ) void SetLayerId( const char* aLayerId ) Loading @@ -698,6 +736,11 @@ public: { { diameter = aDiameter; diameter = aDiameter; } } void SetVertex( const POINT& aVertex ) { vertex = aVertex; } }; }; Loading @@ -718,15 +761,34 @@ public: void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { { const char* newline = nestLevel ? "\n" : ""; 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 %.6g\n", LEXER::GetTokenText( Type() ) , out->Print( nestLevel, "(%s %s%s%s %.6g", 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, "%.6g %.6g\n", vertex[i].x, vertex[i].y ); out->Print( 0, " %.6g %.6g", vertex[i].x, vertex[i].y ); out->Print( nestLevel, ")\n" ); out->Print( 0, ")%s", newline ); } void SetLayerId( const char* aLayerId ) { layer_id = aLayerId; } void SetStart( const POINT& aStart ) { vertex[0] = aStart; } void SetEnd( const POINT& aEnd ) { vertex[1] = aEnd; } void SetCenter( const POINT& aCenter ) { vertex[2] = aCenter; } } }; }; Loading Loading @@ -1641,40 +1703,85 @@ public: }; }; class SHAPE : public ELEM_HOLDER /** * Class SHAPE * corresponds to the "(shape ..)" element in the specctra dsn spec. * It is not a <shape_descriptor> which is one of things that this * elements contains, i.e. in its "shape" field. This class also implements * the "(outline ...)" element as a dual personality. */ class SHAPE : public ELEM { { friend class SPECCTRA_DB; friend class SPECCTRA_DB; DSN_T connect; DSN_T connect; /*----- only one of these is used, like a union ----- /* <shape_descriptor >::= single item, but now in the kids list [<rectangle_descriptor> | <circle_descriptor> | PATH* path; ///< used for both path and polygon <polygon_descriptor> | RECTANGLE* rectangle; <path_descriptor> | CIRCLE* circle; <qarc_descriptor> ] QARC* qarc; */ //--------------------------------------------------- */ ELEM* shape; WINDOWS windows; WINDOWS windows; public: public: SHAPE( ELEM* aParent, DSN_T aType = T_shape ) : SHAPE( ELEM* aParent, DSN_T aType = T_shape ) : ELEM_HOLDER( aType, aParent ) ELEM( aType, aParent ) { { connect = T_on; connect = T_on; shape = 0; } ~SHAPE() { delete shape; } } void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void SetShape( ELEM* aShape ) { { ELEM_HOLDER::FormatContents( out, nestLevel ); delete shape; shape = aShape; if( aShape ) { wxASSERT(aShape->Type()==T_rect || aShape->Type()==T_circle || aShape->Type()==T_qarc || aShape->Type()==T_path || aShape->Type()==T_polygon); aShape->SetParent( this ); } } void SetConnect( DSN_T aConnect ) { connect = aConnect; } void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { out->Print( nestLevel, "(%s ", LEXER::GetTokenText( Type() ) ); if( shape ) shape->Format( out, 0 ); if( connect == T_off ) if( connect == T_off ) out->Print( nestLevel, "(connect %s)\n", LEXER::GetTokenText( connect ) ); out->Print( 0, "(connect %s)", LEXER::GetTokenText( connect ) ); if( windows.size() ) { out->Print( 0, "\n" ); for( WINDOWS::iterator i=windows.begin(); i!=windows.end(); ++i ) for( WINDOWS::iterator i=windows.begin(); i!=windows.end(); ++i ) i->Format( out, nestLevel ); i->Format( out, nestLevel+1 ); out->Print( nestLevel, ")\n" ); } else out->Print( 0, ")\n" ); } } }; }; Loading Loading @@ -3324,10 +3431,8 @@ public: * of class WinEDA_BasePcbFrame rather than class BOARD. * of class WinEDA_BasePcbFrame rather than class BOARD. * * * @param aBoard The BOARD to convert to a PCB. * @param aBoard The BOARD to convert to a PCB. * @throw IOError, if the BOARD cannot be converted, and the text of the * exception tells the error message. */ */ void FromBOARD( BOARD* aBoard ) throw( IOError ); void FromBOARD( BOARD* aBoard ); /** /** Loading Loading
change_log.txt +8 −0 Original line number Original line Diff line number Diff line Loading @@ -5,6 +5,14 @@ Please add newer entries at the top, list the date and your name with email address. email address. 2008-Jan-25 UPDATE Dick Hollenbeck <dick@softplc.com> ================================================================================ +pcbnew: SPECCTRA export does padstacks ok, except that oval arcs need to be split into quarter circle arcs, and no consideration is given to "layer types" See page bottom of page 74 of the SECCTRA Design Language Reference, May 2000. Still working today... 2008-Jan-25 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr> 2008-Jan-25 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr> ================================================================================ ================================================================================ Loading
pcbnew/specctra.cpp +9 −17 Original line number Original line Diff line number Diff line Loading @@ -1985,7 +1985,7 @@ void SPECCTRA_DB::doSHAPE( SHAPE* growth ) throw( IOError ) case T_polygon: case T_polygon: case T_qarc: case T_qarc: L_done_that: L_done_that: if( growth->Length() ) if( growth->shape ) unexpected( tok ); unexpected( tok ); break; break; default: default: Loading @@ -2000,32 +2000,24 @@ L_done_that: switch( tok ) switch( tok ) { { case T_rect: case T_rect: RECTANGLE* rectangle; growth->shape = new RECTANGLE( growth ); rectangle = new RECTANGLE( growth ); doRECTANGLE( (RECTANGLE*) growth->shape ); growth->Append( rectangle ); doRECTANGLE( rectangle ); break; break; case T_circle: case T_circle: CIRCLE* circle; growth->shape = new CIRCLE( growth ); circle = new CIRCLE( growth ); doCIRCLE( (CIRCLE*)growth->shape ); growth->Append( circle ); doCIRCLE( circle ); break; break; case T_path: case T_path: case T_polygon: case T_polygon: PATH* path; growth->shape = new PATH( growth, tok ); path = new PATH( growth, tok ); doPATH( (PATH*)growth->shape ); growth->Append( path ); doPATH( path ); break; break; case T_qarc: case T_qarc: QARC* qarc; growth->shape = new QARC( growth ); qarc = new QARC( growth ); doQARC( (QARC*)growth->shape ); growth->Append( qarc ); doQARC( qarc ); break; break; case T_connect: case T_connect: Loading
pcbnew/specctra.h +139 −34 Original line number Original line Diff line number Diff line Loading @@ -126,6 +126,25 @@ struct POINT return !( *this == other ); return !( *this == other ); } } POINT& operator+=( const POINT& other ) { x += other.x; y += other.y; return *this; } POINT& operator=( const POINT& other ) { x = other.x; if( x == -0.0 ) // correct -0.0 so output looks nice. x = 0.0; y = other.y; if( y == -0.0 ) y = 0.0; return *this; } /** /** * 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 Loading Loading @@ -425,13 +444,16 @@ public: void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { { const char* newline = nestLevel ? "\n" : ""; 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 %.6g %.6g %.6g %.6g)\n", out->Print( nestLevel, "(%s %s%s%s %.6g %.6g %.6g %.6g)%s", 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, point1.x, point1.y ); point1.x, point1.y, newline ); } } }; }; Loading Loading @@ -587,12 +609,20 @@ public: aperture_type = T_round; aperture_type = T_round; } } ~PATH() void AppendPoint( const POINT& aPoint ) { { points.push_back( aPoint ); } void SetLayerId( const char* aLayerId ) { layer_id = aLayerId; } } void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { { const char* newline = nestLevel ? "\n" : ""; const char* quote = out->GetQuoteChar( layer_id.c_str() ); const char* quote = out->GetQuoteChar( layer_id.c_str() ); const int RIGHTMARGIN = 80; const int RIGHTMARGIN = 80; Loading @@ -607,6 +637,7 @@ public: { { out->Print( 0, "\n" ); out->Print( 0, "\n" ); perLine = out->Print( nestLevel+1, "%s", "" ); perLine = out->Print( nestLevel+1, "%s", "" ); newline = "\n"; } } else else perLine += out->Print( 0, " " ); perLine += out->Print( 0, " " ); Loading @@ -617,10 +648,10 @@ public: if( aperture_type == T_square ) if( aperture_type == T_square ) { { out->Print( 0, "\n" ); out->Print( 0, "\n" ); out->Print( nestLevel+1, "(aperture_type square)\n" ); out->Print( nestLevel+1, "(aperture_type square))\n" ); } } else out->Print( 0, ")\n" ); out->Print( 0, ")%s", newline ); } } }; }; typedef boost::ptr_vector<PATH> PATHS; typedef boost::ptr_vector<PATH> PATHS; Loading Loading @@ -672,7 +703,7 @@ class CIRCLE : public ELEM std::string layer_id; std::string layer_id; double diameter; double diameter; POINT vertex; POINT vertex; // POINT's constructor sets to (0,0) public: public: CIRCLE( ELEM* aParent ) : CIRCLE( ELEM* aParent ) : Loading @@ -683,10 +714,17 @@ public: void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { { const char* newline = nestLevel ? "\n" : ""; 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 %.6g %.6g %.6g)\n", LEXER::GetTokenText( Type() ) , out->Print( nestLevel, "(%s %s%s%s %.6g", LEXER::GetTokenText( Type() ), quote, layer_id.c_str(), quote, quote, layer_id.c_str(), quote, diameter, vertex.x, vertex.y ); diameter ); if( vertex.x!=0.0 || vertex.y!=0.0 ) out->Print( 0, " %.6g %.6g)%s", vertex.x, vertex.y, newline ); else out->Print( 0, ")%s", newline ); } } void SetLayerId( const char* aLayerId ) void SetLayerId( const char* aLayerId ) Loading @@ -698,6 +736,11 @@ public: { { diameter = aDiameter; diameter = aDiameter; } } void SetVertex( const POINT& aVertex ) { vertex = aVertex; } }; }; Loading @@ -718,15 +761,34 @@ public: void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { { const char* newline = nestLevel ? "\n" : ""; 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 %.6g\n", LEXER::GetTokenText( Type() ) , out->Print( nestLevel, "(%s %s%s%s %.6g", 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, "%.6g %.6g\n", vertex[i].x, vertex[i].y ); out->Print( 0, " %.6g %.6g", vertex[i].x, vertex[i].y ); out->Print( nestLevel, ")\n" ); out->Print( 0, ")%s", newline ); } void SetLayerId( const char* aLayerId ) { layer_id = aLayerId; } void SetStart( const POINT& aStart ) { vertex[0] = aStart; } void SetEnd( const POINT& aEnd ) { vertex[1] = aEnd; } void SetCenter( const POINT& aCenter ) { vertex[2] = aCenter; } } }; }; Loading Loading @@ -1641,40 +1703,85 @@ public: }; }; class SHAPE : public ELEM_HOLDER /** * Class SHAPE * corresponds to the "(shape ..)" element in the specctra dsn spec. * It is not a <shape_descriptor> which is one of things that this * elements contains, i.e. in its "shape" field. This class also implements * the "(outline ...)" element as a dual personality. */ class SHAPE : public ELEM { { friend class SPECCTRA_DB; friend class SPECCTRA_DB; DSN_T connect; DSN_T connect; /*----- only one of these is used, like a union ----- /* <shape_descriptor >::= single item, but now in the kids list [<rectangle_descriptor> | <circle_descriptor> | PATH* path; ///< used for both path and polygon <polygon_descriptor> | RECTANGLE* rectangle; <path_descriptor> | CIRCLE* circle; <qarc_descriptor> ] QARC* qarc; */ //--------------------------------------------------- */ ELEM* shape; WINDOWS windows; WINDOWS windows; public: public: SHAPE( ELEM* aParent, DSN_T aType = T_shape ) : SHAPE( ELEM* aParent, DSN_T aType = T_shape ) : ELEM_HOLDER( aType, aParent ) ELEM( aType, aParent ) { { connect = T_on; connect = T_on; shape = 0; } ~SHAPE() { delete shape; } } void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void SetShape( ELEM* aShape ) { { ELEM_HOLDER::FormatContents( out, nestLevel ); delete shape; shape = aShape; if( aShape ) { wxASSERT(aShape->Type()==T_rect || aShape->Type()==T_circle || aShape->Type()==T_qarc || aShape->Type()==T_path || aShape->Type()==T_polygon); aShape->SetParent( this ); } } void SetConnect( DSN_T aConnect ) { connect = aConnect; } void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { out->Print( nestLevel, "(%s ", LEXER::GetTokenText( Type() ) ); if( shape ) shape->Format( out, 0 ); if( connect == T_off ) if( connect == T_off ) out->Print( nestLevel, "(connect %s)\n", LEXER::GetTokenText( connect ) ); out->Print( 0, "(connect %s)", LEXER::GetTokenText( connect ) ); if( windows.size() ) { out->Print( 0, "\n" ); for( WINDOWS::iterator i=windows.begin(); i!=windows.end(); ++i ) for( WINDOWS::iterator i=windows.begin(); i!=windows.end(); ++i ) i->Format( out, nestLevel ); i->Format( out, nestLevel+1 ); out->Print( nestLevel, ")\n" ); } else out->Print( 0, ")\n" ); } } }; }; Loading Loading @@ -3324,10 +3431,8 @@ public: * of class WinEDA_BasePcbFrame rather than class BOARD. * of class WinEDA_BasePcbFrame rather than class BOARD. * * * @param aBoard The BOARD to convert to a PCB. * @param aBoard The BOARD to convert to a PCB. * @throw IOError, if the BOARD cannot be converted, and the text of the * exception tells the error message. */ */ void FromBOARD( BOARD* aBoard ) throw( IOError ); void FromBOARD( BOARD* aBoard ); /** /** Loading