Loading pcbnew/dsn.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -737,7 +737,7 @@ L_read: goto exit; goto exit; } } // else it was something like +5V, reset head back // else it was something like +5V, fall through below } } // a quoted string // a quoted string Loading pcbnew/specctra.cpp +24 −16 Original line number Original line Diff line number Diff line Loading @@ -212,7 +212,7 @@ void SPECCTRA_DB::readTIME( time_t* time_stamp ) throw( IOError ) const char* ptok = lexer->CurText(); const char* ptok = lexer->CurText(); mytime.tm_mon = 0; // remains of we don't find a month match. mytime.tm_mon = 0; // remains if we don't find a month match. for( int m=0; months[m]; ++m ) for( int m=0; months[m]; ++m ) { { if( !stricmp( months[m], ptok ) ) if( !stricmp( months[m], ptok ) ) Loading 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->rectangle || growth->circle || growth->path || growth->qarc ) if( growth->Length() ) unexpected( tok ); unexpected( tok ); break; break; default: default: Loading @@ -2000,24 +2000,32 @@ L_done_that: switch( tok ) switch( tok ) { { case T_rect: case T_rect: growth->rectangle = new RECTANGLE( growth ); RECTANGLE* rectangle; doRECTANGLE( growth->rectangle ); rectangle = new RECTANGLE( growth ); growth->Append( rectangle ); doRECTANGLE( rectangle ); break; break; case T_circle: case T_circle: growth->circle = new CIRCLE( growth ); CIRCLE* circle; doCIRCLE( growth->circle ); circle = new CIRCLE( growth ); growth->Append( circle ); doCIRCLE( circle ); break; break; case T_path: case T_path: case T_polygon: case T_polygon: growth->path = new PATH( growth, tok ); PATH* path; doPATH( growth->path ); path = new PATH( growth, tok ); growth->Append( path ); doPATH( path ); break; break; case T_qarc: case T_qarc: growth->qarc = new QARC( growth ); QARC* qarc; doQARC( growth->qarc ); qarc = new QARC( growth ); growth->Append( qarc ); doQARC( qarc ); break; break; case T_connect: case T_connect: Loading Loading @@ -3650,16 +3658,16 @@ int main( int argc, char** argv ) { { // wxString filename( wxT("/tmp/fpcroute/Sample_1sided/demo_1sided.dsn") ); // wxString filename( wxT("/tmp/fpcroute/Sample_1sided/demo_1sided.dsn") ); // wxString filename( wxT("/tmp/testdesigns/test.dsn") ); // wxString filename( wxT("/tmp/testdesigns/test.dsn") ); wxString filename( wxT("/tmp/testdesigns/test.ses") ); // wxString filename( wxT("/tmp/testdesigns/test.ses") ); // wxString filename( wxT("/tmp/specctra_big.dsn") ); wxString filename( wxT("/tmp/specctra_big.dsn") ); SPECCTRA_DB db; SPECCTRA_DB db; bool failed = false; bool failed = false; try try { { // db.LoadPCB( filename ); db.LoadPCB( filename ); db.LoadSESSION( filename ); // db.LoadSESSION( filename ); } } catch( IOError ioe ) catch( IOError ioe ) { { Loading @@ -3672,8 +3680,8 @@ int main( int argc, char** argv ) // export what we read in, making this test program basically a beautifier // export what we read in, making this test program basically a beautifier db.ExportSESSION( wxT("/tmp/export.ses") ); // db.ExportSESSION( wxT("/tmp/export.ses") ); // db.ExportPCB( wxT("/tmp/export.dsn") ); db.ExportPCB( wxT("/tmp/export.dsn") ); } } Loading pcbnew/specctra.h +101 −68 Original line number Original line Diff line number Diff line Loading @@ -111,6 +111,11 @@ struct POINT POINT() { x=0.0; y=0.0; } POINT() { x=0.0; y=0.0; } POINT( double aX, double aY ) : x(aX), y(aY) { } bool operator==( const POINT& other ) const bool operator==( const POINT& other ) const { { return x==other.x && y==other.y; return x==other.x && y==other.y; Loading Loading @@ -407,6 +412,17 @@ public: { { } } void SetLayerId( const char* aLayerId ) { layer_id = aLayerId; } void SetCorners( const POINT& aPoint0, const POINT& aPoint1 ) { point0 = aPoint0; point1 = aPoint1; } 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() ); Loading Loading @@ -451,9 +467,10 @@ public: else else { { out->Print( 0, "\n" ); singleLine = false; singleLine = false; for( STRINGS::const_iterator i = rules.begin(); i!=rules.end(); ++i ) for( STRINGS::const_iterator i = rules.begin(); i!=rules.end(); ++i ) out->Print( nestLevel, "%s\n", i->c_str() ); out->Print( nestLevel+1, "%s\n", i->c_str() ); out->Print( nestLevel, ")" ); out->Print( nestLevel, ")" ); } } Loading Loading @@ -671,6 +688,16 @@ public: quote, layer_id.c_str(), quote, quote, layer_id.c_str(), quote, diameter, vertex.x, vertex.y ); diameter, vertex.x, vertex.y ); } } void SetLayerId( const char* aLayerId ) { layer_id = aLayerId; } void SetDiameter( double aDiameter ) { diameter = aDiameter; } }; }; Loading Loading @@ -870,28 +897,42 @@ public: void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { { out->Print( nestLevel, "(%s\n", LEXER::GetTokenText( Type() ) ); const int RIGHTMARGIN = 80; int perLine = out->Print( nestLevel, "(%s", LEXER::GetTokenText( Type() ) ); for( STRINGS::iterator i=padstacks.begin(); i!=padstacks.end(); ++i ) for( STRINGS::iterator i=padstacks.begin(); i!=padstacks.end(); ++i ) { { if( perLine > RIGHTMARGIN ) { out->Print( 0, "\n" ); perLine = out->Print( nestLevel+1, "%s", ""); } const char* quote = out->GetQuoteChar( i->c_str() ); const char* quote = out->GetQuoteChar( i->c_str() ); out->Print( nestLevel+1, "%s%s%s\n", quote, i->c_str(), quote ); perLine += out->Print( 0, " %s%s%s", quote, i->c_str(), quote ); } } if( spares.size() ) if( spares.size() ) { { out->Print( nestLevel+1, "(spare\n" ); out->Print( 0, "\n" ); perLine = out->Print( nestLevel+1, "(spare" ); for( STRINGS::iterator i=spares.begin(); i!=spares.end(); ++i ) for( STRINGS::iterator i=spares.begin(); i!=spares.end(); ++i ) { { if( perLine > RIGHTMARGIN ) { out->Print( 0, "\n" ); perLine = out->Print( nestLevel+2, "%s", ""); } const char* quote = out->GetQuoteChar( i->c_str() ); const char* quote = out->GetQuoteChar( i->c_str() ); out->Print( nestLevel+2, "%s%s%s\n", quote, i->c_str(), quote ); perLine += out->Print( 0, " %s%s%s", quote, i->c_str(), quote ); } } out->Print( nestLevel+1, ")\n" ); out->Print( 0, ")" ); } } out->Print( nestLevel, ")\n" ); out->Print( 0, ")\n" ); } } }; }; Loading Loading @@ -1600,55 +1641,34 @@ public: }; }; class SHAPE : public ELEM class SHAPE : public ELEM_HOLDER { { friend class SPECCTRA_DB; friend class SPECCTRA_DB; DSN_T connect; DSN_T connect; //----- only one of these is used, like a union ----- /*----- only one of these is used, like a union ----- single item, but now in the kids list PATH* path; ///< used for both path and polygon PATH* path; ///< used for both path and polygon RECTANGLE* rectangle; RECTANGLE* rectangle; CIRCLE* circle; CIRCLE* circle; QARC* qarc; QARC* qarc; //--------------------------------------------------- //--------------------------------------------------- */ WINDOWS windows; WINDOWS windows; public: public: SHAPE( ELEM* aParent, DSN_T aType = T_shape ) : SHAPE( ELEM* aParent, DSN_T aType = T_shape ) : ELEM( aType, aParent ) ELEM_HOLDER( aType, aParent ) { { connect = T_on; connect = T_on; path = 0; rectangle = 0; circle = 0; qarc = 0; } ~SHAPE() { delete path; delete rectangle; delete circle; delete qarc; } } void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { { if( path ) ELEM_HOLDER::FormatContents( out, nestLevel ); path->Format( out, nestLevel ); else if( rectangle ) rectangle->Format( out, nestLevel ); else if( circle ) circle->Format( out, nestLevel ); else if( qarc ) qarc->Format( out, nestLevel ); if( connect == T_off ) if( connect == T_off ) out->Print( nestLevel, "(connect %s)\n", LEXER::GetTokenText( connect ) ); out->Print( nestLevel, "(connect %s)\n", LEXER::GetTokenText( connect ) ); Loading Loading @@ -1817,6 +1837,11 @@ public: delete rules; delete rules; } } void SetPadstackId( const char* aPadstackId ) { padstack_id = aPadstackId; } void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { { const char* quote = out->GetQuoteChar( padstack_id.c_str() ); const char* quote = out->GetQuoteChar( padstack_id.c_str() ); Loading Loading @@ -1865,6 +1890,7 @@ public: return ELEM::GetUnits(); return ELEM::GetUnits(); } } }; }; typedef boost::ptr_vector<PADSTACK> PADSTACKS; /** /** Loading @@ -1882,7 +1908,6 @@ class LIBRARY : public ELEM typedef boost::ptr_vector<IMAGE> IMAGES; typedef boost::ptr_vector<IMAGE> IMAGES; IMAGES images; IMAGES images; typedef boost::ptr_vector<PADSTACK> PADSTACKS; PADSTACKS padstacks; PADSTACKS padstacks; public: public: Loading Loading @@ -1916,6 +1941,11 @@ public: return ELEM::GetUnits(); return ELEM::GetUnits(); } } void AddPadstack( PADSTACK* aPadstack ) { padstacks.push_back( aPadstack ); } }; }; Loading Loading @@ -2215,35 +2245,32 @@ public: void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { { const int RIGHTMARGIN = 80; const char* quote = out->GetQuoteChar( class_id.c_str() ); const char* quote = out->GetQuoteChar( class_id.c_str() ); out->Print( nestLevel, "(%s %s%s%s", LEXER::GetTokenText( Type() ), quote, class_id.c_str(), quote ); const int NETGAP = 2; int perLine = out->Print( nestLevel, "(%s %s%s%s", const int RIGHTMARGIN = 92; LEXER::GetTokenText( Type() ), quote, class_id.c_str(), quote ); int perRow=RIGHTMARGIN; for( STRINGS::iterator i=net_ids.begin(); i!=net_ids.end(); ++i ) for( STRINGS::iterator i=net_ids.begin(); i!=net_ids.end(); ++i ) { { quote = out->GetQuoteChar( i->c_str() ); if( perLine > RIGHTMARGIN ) int slength = strlen( i->c_str() ); if( *quote!='\0' ) slength += 2; if( perRow + slength + NETGAP > RIGHTMARGIN ) { { out->Print( 0, "\n" ); out->Print( 0, "\n" ); perRow = 0; perLine = out->Print( nestLevel+1, "%s", "" ); perRow += out->Print( nestLevel+1, "%s%s%s", quote, i->c_str(), quote ); } else { perRow += out->Print( 0, "%*c%s%s%s", NETGAP, ' ', quote, i->c_str(), quote ); } } quote = out->GetQuoteChar( i->c_str() ); perLine += out->Print( 0, " %s%s%s", quote, i->c_str(), quote ); } } bool newLine = false; if( circuit.size() || layer_rules.size() || topology ) { out->Print( 0, "\n" ); out->Print( 0, "\n" ); newLine = true; } for( STRINGS::iterator i=circuit.begin(); i!=circuit.end(); ++i ) for( STRINGS::iterator i=circuit.begin(); i!=circuit.end(); ++i ) out->Print( nestLevel+1, "%s\n", i->c_str() ); out->Print( nestLevel+1, "%s\n", i->c_str() ); Loading @@ -2254,7 +2281,7 @@ public: if( topology ) if( topology ) topology->Format( out, nestLevel+1 ); topology->Format( out, nestLevel+1 ); out->Print( nestLevel, ")\n" ); out->Print( newLine ? nestLevel : 0, ")\n" ); } } }; }; Loading Loading @@ -2444,6 +2471,9 @@ public: perLine += out->Print( 0, "%.6g %.6g", i->x, i->y ); perLine += out->Print( 0, "%.6g %.6g", i->x, i->y ); } } if( net_id.size() || via_number!=-1 || type!=T_NONE || attr!=T_NONE || supply) out->Print( 0, " " ); if( net_id.size() ) if( net_id.size() ) { { if( perLine > RIGHTMARGIN ) if( perLine > RIGHTMARGIN ) Loading Loading @@ -3183,13 +3213,6 @@ class SPECCTRA_DB : public OUTPUTFORMATTER 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() Loading Loading @@ -3288,7 +3311,17 @@ public: /** /** * Function FromBOARD * Function FromBOARD * adds the entire BOARD to the PCB but does not write it out. * adds the entire BOARD to the PCB but does not write it out. Note that * the BOARD given to this function must have all the MODULEs on the component * side of the BOARD. * * See void WinEDA_PcbFrame::ExportToSPECCTRA( wxCommandEvent& event ) * for how this can be done before calling this function. * @todo * I would have liked to put the flipping logic into the ExportToSPECCTRA() * function directly, but for some strange reason, * void Change_Side_Module( MODULE* Module, wxDC* DC ) is a member of * 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 * @throw IOError, if the BOARD cannot be converted, and the text of the Loading pcbnew/specctra_export.cpp +289 −19 Original line number Original line Diff line number Diff line Loading @@ -34,6 +34,7 @@ #include "specctra.h" #include "specctra.h" #include "collectors.h" #include "collectors.h" #include "wxPcbStruct.h" // Change_Side_Module() using namespace DSN; using namespace DSN; Loading Loading @@ -61,27 +62,59 @@ void WinEDA_PcbFrame::ExportToSPECCTRA( wxCommandEvent& event ) SPECCTRA_DB db; SPECCTRA_DB db; bool ok = true; wxString errorText; db.SetPCB( SPECCTRA_DB::MakePCB() ); db.SetPCB( SPECCTRA_DB::MakePCB() ); // DSN Images (=Kicad MODULES and pads) must be presented from the // top view. So we temporarily flip any modules which are on the back // side of the board to the front, and record this in the MODULE's flag field. for( MODULE* module = m_Pcb->m_Modules; module; module = module->Next() ) { module->flag = 0; if( module->GetLayer() == COPPER_LAYER_N ) { Change_Side_Module( module, NULL ); module->flag = 1; } } try try { { db.FromBOARD( m_Pcb ); db.FromBOARD( m_Pcb ); db.ExportPCB( fullFileName, true ); db.ExportPCB( fullFileName, true ); // if an exception is thrown by FromBOARD or Export(), then // if an exception is thrown by FromBOARD or ExportPCB(), then // ~SPECCTRA_DB() will close the file. // ~SPECCTRA_DB() will close the file. } } catch ( IOError ioe ) catch ( IOError ioe ) { { DisplayError( this, ioe.errorText ); ok = false; return; } // @todo display a message saying the export is complete. // display no messages until we flip back the modules below. errorText = ioe.errorText; } } // DSN Images (=Kicad MODULES and pads) must be presented from the // top view. Restore those that were flipped. for( MODULE* module = m_Pcb->m_Modules; module; module = module->Next() ) { if( module->flag ) { Change_Side_Module( module, NULL ); module->flag = 0; } } if( ok ) { // @todo display a message saying the export is complete. } else DisplayError( this, errorText ); } namespace DSN { namespace DSN { Loading @@ -103,6 +136,22 @@ static inline void swap( POINT_PAIR& pair ) } } static inline double scale( int kicadDist ) { return kicadDist/10.0; } static inline double mapX( int x ) { return scale(x); } static inline double mapY( int y ) { return -scale(y); // make y negative, since it is increasing going down. } /** /** * Function mapPt * Function mapPt * converts a Kicad point into a DSN file point. Kicad's BOARD coordinates * converts a Kicad point into a DSN file point. Kicad's BOARD coordinates Loading @@ -112,8 +161,8 @@ static inline void swap( POINT_PAIR& pair ) static POINT mapPt( const wxPoint& pt ) static POINT mapPt( const wxPoint& pt ) { { POINT ret; POINT ret; ret.x = pt.x / 10.0; ret.x = mapX( pt.x ); ret.y = -pt.y /10.0; // make y negative, since it is increasing going down. ret.y = mapY( pt.y ); return ret; return ret; } } Loading Loading @@ -172,8 +221,199 @@ static bool isRectangle( POINT_PAIRS& aList ) } } void SPECCTRA_DB::exportEdges( BOARD* aBoard ) throw( IOError ) /**************************************************************************/ static int Pad_list_Sort_by_Shapes( const void* refptr, const void* objptr ) /**************************************************************************/ { const D_PAD* padref = *(D_PAD**)refptr; const D_PAD* padcmp = *(D_PAD**)objptr; return D_PAD::Compare( padref, padcmp ); } /** * Function makePADSTACKs * makes all the PADSTACKs, and marks each D_PAD with the index into the * LIBRARY::padstacks list that it matches. */ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibrary, PADSTACKS& aPadstacks ) { if( aPads.GetCount() ) { { qsort( (void*) aPads.BasePtr(), aPads.GetCount(), sizeof(D_PAD*), Pad_list_Sort_by_Shapes ); } D_PAD* old_pad = NULL; int padstackNdx = 0; for( int i=0; i<aPads.GetCount(); ++i ) { D_PAD* pad = (D_PAD*) aPads[i]; pad->m_logical_connexion = padstackNdx; if( old_pad && 0==D_PAD::Compare( old_pad, pad ) ) { continue; } old_pad = pad; // this is the index into the library->padstacks, be careful. pad->m_logical_connexion = padstackNdx++; PADSTACK* padstack = new PADSTACK( aLibrary ); SHAPE* shape = new SHAPE( padstack ); padstack->Append( shape ); switch( pad->m_PadShape ) { default: case PAD_CIRCLE: { CIRCLE* circle; double diameter = scale(pad->m_Size.x); int coppers = 0; if( pad->IsOnLayer( COPPER_LAYER_N ) ) { circle = new CIRCLE( shape ); circle->SetLayerId( CONV_TO_UTF8(aBoard->GetLayerName( COPPER_LAYER_N )) ); circle->SetDiameter( diameter ); shape->Append( circle ); ++coppers; } if( pad->IsOnLayer( LAYER_CMP_N ) ) { circle = new CIRCLE( shape ); circle->SetLayerId( CONV_TO_UTF8(aBoard->GetLayerName( LAYER_CMP_N )) ); circle->SetDiameter( diameter ); shape->Append( circle ); ++coppers; } char name[50]; snprintf( name, sizeof(name), "Round%dPad_%.6g_mil", coppers, scale(pad->m_Size.x) ); name[ sizeof(name)-1 ] = 0; // @todo verify that all pad names are unique, there is a chance that // D_PAD::Compare() could say two pads are different, yet the get the same // name here. If so, blend in the padNdx into the name. padstack->SetPadstackId( name ); aLibrary->AddPadstack( padstack ); } break; case PAD_RECT: { double dx = scale( pad->m_Size.x ) / 2.0; double dy = scale( pad->m_Size.y ) / 2.0; RECTANGLE* rect; int coppers = 0; if( pad->IsOnLayer( COPPER_LAYER_N ) ) { rect = new RECTANGLE( shape ); rect->SetLayerId( CONV_TO_UTF8(aBoard->GetLayerName( COPPER_LAYER_N )) ); rect->SetCorners( POINT(-dx,-dy), POINT(dx,dy) ); shape->Append( rect ); ++coppers; } if( pad->IsOnLayer( LAYER_CMP_N ) ) { rect = new RECTANGLE( shape ); rect->SetLayerId( CONV_TO_UTF8(aBoard->GetLayerName( LAYER_CMP_N )) ); rect->SetCorners( POINT(-dx,-dy), POINT(dx,dy) ); shape->Append( rect ); ++coppers; } char name[50]; snprintf( name, sizeof(name), "Rect%dPad_%.6gx%.6g_mil", coppers, scale(pad->m_Size.x), scale(pad->m_Size.y) ); name[ sizeof(name)-1 ] = 0; // @todo verify that all pad names are unique, there is a chance that // D_PAD::Compare() could say two pads are different, yet the get the same // name here. If so, blend in the padNdx into the name. padstack->SetPadstackId( name ); aLibrary->AddPadstack( padstack ); } break; #if 0 pad_type = "RECTANGULAR"; fprintf( file, " %s %d\n", pad_type, pad->m_Drill.x ); fprintf( file, "RECTANGLE %d %d %d %d\n", -dx + pad->m_Offset.x, -dy - pad->m_Offset.y, dx + pad->m_Offset.x, -pad->m_Offset.y + dy ); break; case PAD_OVAL: /* description du contour par 2 linges et 2 arcs */ { pad_type = "FINGER"; fprintf( file, " %s %d\n", pad_type, pad->m_Drill.x ); int dr = dx - dy; if( dr >= 0 ) // ovale horizontal { int rayon = dy; fprintf( file, "LINE %d %d %d %d\n", -dr + pad->m_Offset.x, -pad->m_Offset.y - rayon, dr + pad->m_Offset.x, -pad->m_Offset.y - rayon ); fprintf( file, "ARC %d %d %d %d %d %d\n", dr + pad->m_Offset.x, -pad->m_Offset.y - rayon, dr + pad->m_Offset.x, -pad->m_Offset.y + rayon, dr + pad->m_Offset.x, -pad->m_Offset.y ); fprintf( file, "LINE %d %d %d %d\n", dr + pad->m_Offset.x, -pad->m_Offset.y + rayon, -dr + pad->m_Offset.x, -pad->m_Offset.y + rayon ); fprintf( file, "ARC %d %d %d %d %d %d\n", -dr + pad->m_Offset.x, -pad->m_Offset.y + rayon, -dr + pad->m_Offset.x, -pad->m_Offset.y - rayon, -dr + pad->m_Offset.x, -pad->m_Offset.y ); } else // ovale vertical { dr = -dr; int rayon = dx; fprintf( file, "LINE %d %d %d %d\n", -rayon + pad->m_Offset.x, -pad->m_Offset.y - dr, -rayon + pad->m_Offset.x, -pad->m_Offset.y + dr ); fprintf( file, "ARC %d %d %d %d %d %d\n", -rayon + pad->m_Offset.x, -pad->m_Offset.y + dr, rayon + pad->m_Offset.x, -pad->m_Offset.y + dr, pad->m_Offset.x, -pad->m_Offset.y + dr ); fprintf( file, "LINE %d %d %d %d\n", rayon + pad->m_Offset.x, -pad->m_Offset.y + dr, rayon + pad->m_Offset.x, -pad->m_Offset.y - dr ); fprintf( file, "ARC %d %d %d %d %d %d\n", rayon + pad->m_Offset.x, -pad->m_Offset.y - dr, -rayon + pad->m_Offset.x, -pad->m_Offset.y - dr, pad->m_Offset.x, -pad->m_Offset.y - dr ); } break; } case PAD_TRAPEZOID: pad_type = "POLYGON"; break; #endif } } } } Loading Loading @@ -304,6 +544,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError ) } } } } //-----<zone containers become planes>-------------------------------------------- //-----<zone containers become planes>-------------------------------------------- { { static const KICAD_T scanZONEs[] = { TYPEZONE_CONTAINER, EOT }; static const KICAD_T scanZONEs[] = { TYPEZONE_CONTAINER, EOT }; Loading Loading @@ -334,19 +575,48 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError ) } } } } // keepouts could go here, there are none in Kicad at this time. // although COPPER_PLANEs probably will need them for the thru holes, etc. // but in that case they are WINDOWs within the COPPER_PLANEs. //-----<build the padstack list here, no output>------------------------ //-----<build the padstack list here, no output>------------------------ { { // get all the DRAWSEGMENTS into 'items', then look for layer == EDGE_N, static const KICAD_T scanPADs[] = { TYPEPAD, EOT }; // and those segments comprize the board's perimeter. static const KICAD_T scanPADnVIAs[] = { TYPEPAD, TYPEVIA, EOT }; items.Collect( aBoard, scanPADnVIAs ); for( int i=0; i<items.GetCount(); ++i ) TYPE_COLLECTOR pads; // get all the D_PADs into pads. pads.Collect( aBoard, scanPADs ); makePADSTACKs( aBoard, pads, pcb->library, pcb->library->padstacks ); for( int p=0; p<pads.GetCount(); ++p ) pads[p]->Show( 0, std::cout ); /* static const KICAD_T scanMODULEs[] = { TYPEMODULE, EOT }; items.Collect( aBoard, scanMODULEs ); for( int m=0; m<items.GetCount(); ++m ) { { // items[i]->Show( 0, std::cout ); MODULE* module = (MODULE*) items[m]; // collate all the pads, and make a component. for( int p=0; p<pads.GetCount(); ++p ) { D_PAD* pad = (D_PAD*) pads[p]; D(pad->Show( 0, std::cout );) // lookup and maybe add this pad to the padstack. wxString padName = lookupPad( pcb->library->padstacks, pad ); } } } } */ } //-----<via_descriptor>------------------------------------------------- //-----<via_descriptor>------------------------------------------------- { { Loading Loading
pcbnew/dsn.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -737,7 +737,7 @@ L_read: goto exit; goto exit; } } // else it was something like +5V, reset head back // else it was something like +5V, fall through below } } // a quoted string // a quoted string Loading
pcbnew/specctra.cpp +24 −16 Original line number Original line Diff line number Diff line Loading @@ -212,7 +212,7 @@ void SPECCTRA_DB::readTIME( time_t* time_stamp ) throw( IOError ) const char* ptok = lexer->CurText(); const char* ptok = lexer->CurText(); mytime.tm_mon = 0; // remains of we don't find a month match. mytime.tm_mon = 0; // remains if we don't find a month match. for( int m=0; months[m]; ++m ) for( int m=0; months[m]; ++m ) { { if( !stricmp( months[m], ptok ) ) if( !stricmp( months[m], ptok ) ) Loading 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->rectangle || growth->circle || growth->path || growth->qarc ) if( growth->Length() ) unexpected( tok ); unexpected( tok ); break; break; default: default: Loading @@ -2000,24 +2000,32 @@ L_done_that: switch( tok ) switch( tok ) { { case T_rect: case T_rect: growth->rectangle = new RECTANGLE( growth ); RECTANGLE* rectangle; doRECTANGLE( growth->rectangle ); rectangle = new RECTANGLE( growth ); growth->Append( rectangle ); doRECTANGLE( rectangle ); break; break; case T_circle: case T_circle: growth->circle = new CIRCLE( growth ); CIRCLE* circle; doCIRCLE( growth->circle ); circle = new CIRCLE( growth ); growth->Append( circle ); doCIRCLE( circle ); break; break; case T_path: case T_path: case T_polygon: case T_polygon: growth->path = new PATH( growth, tok ); PATH* path; doPATH( growth->path ); path = new PATH( growth, tok ); growth->Append( path ); doPATH( path ); break; break; case T_qarc: case T_qarc: growth->qarc = new QARC( growth ); QARC* qarc; doQARC( growth->qarc ); qarc = new QARC( growth ); growth->Append( qarc ); doQARC( qarc ); break; break; case T_connect: case T_connect: Loading Loading @@ -3650,16 +3658,16 @@ int main( int argc, char** argv ) { { // wxString filename( wxT("/tmp/fpcroute/Sample_1sided/demo_1sided.dsn") ); // wxString filename( wxT("/tmp/fpcroute/Sample_1sided/demo_1sided.dsn") ); // wxString filename( wxT("/tmp/testdesigns/test.dsn") ); // wxString filename( wxT("/tmp/testdesigns/test.dsn") ); wxString filename( wxT("/tmp/testdesigns/test.ses") ); // wxString filename( wxT("/tmp/testdesigns/test.ses") ); // wxString filename( wxT("/tmp/specctra_big.dsn") ); wxString filename( wxT("/tmp/specctra_big.dsn") ); SPECCTRA_DB db; SPECCTRA_DB db; bool failed = false; bool failed = false; try try { { // db.LoadPCB( filename ); db.LoadPCB( filename ); db.LoadSESSION( filename ); // db.LoadSESSION( filename ); } } catch( IOError ioe ) catch( IOError ioe ) { { Loading @@ -3672,8 +3680,8 @@ int main( int argc, char** argv ) // export what we read in, making this test program basically a beautifier // export what we read in, making this test program basically a beautifier db.ExportSESSION( wxT("/tmp/export.ses") ); // db.ExportSESSION( wxT("/tmp/export.ses") ); // db.ExportPCB( wxT("/tmp/export.dsn") ); db.ExportPCB( wxT("/tmp/export.dsn") ); } } Loading
pcbnew/specctra.h +101 −68 Original line number Original line Diff line number Diff line Loading @@ -111,6 +111,11 @@ struct POINT POINT() { x=0.0; y=0.0; } POINT() { x=0.0; y=0.0; } POINT( double aX, double aY ) : x(aX), y(aY) { } bool operator==( const POINT& other ) const bool operator==( const POINT& other ) const { { return x==other.x && y==other.y; return x==other.x && y==other.y; Loading Loading @@ -407,6 +412,17 @@ public: { { } } void SetLayerId( const char* aLayerId ) { layer_id = aLayerId; } void SetCorners( const POINT& aPoint0, const POINT& aPoint1 ) { point0 = aPoint0; point1 = aPoint1; } 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() ); Loading Loading @@ -451,9 +467,10 @@ public: else else { { out->Print( 0, "\n" ); singleLine = false; singleLine = false; for( STRINGS::const_iterator i = rules.begin(); i!=rules.end(); ++i ) for( STRINGS::const_iterator i = rules.begin(); i!=rules.end(); ++i ) out->Print( nestLevel, "%s\n", i->c_str() ); out->Print( nestLevel+1, "%s\n", i->c_str() ); out->Print( nestLevel, ")" ); out->Print( nestLevel, ")" ); } } Loading Loading @@ -671,6 +688,16 @@ public: quote, layer_id.c_str(), quote, quote, layer_id.c_str(), quote, diameter, vertex.x, vertex.y ); diameter, vertex.x, vertex.y ); } } void SetLayerId( const char* aLayerId ) { layer_id = aLayerId; } void SetDiameter( double aDiameter ) { diameter = aDiameter; } }; }; Loading Loading @@ -870,28 +897,42 @@ public: void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { { out->Print( nestLevel, "(%s\n", LEXER::GetTokenText( Type() ) ); const int RIGHTMARGIN = 80; int perLine = out->Print( nestLevel, "(%s", LEXER::GetTokenText( Type() ) ); for( STRINGS::iterator i=padstacks.begin(); i!=padstacks.end(); ++i ) for( STRINGS::iterator i=padstacks.begin(); i!=padstacks.end(); ++i ) { { if( perLine > RIGHTMARGIN ) { out->Print( 0, "\n" ); perLine = out->Print( nestLevel+1, "%s", ""); } const char* quote = out->GetQuoteChar( i->c_str() ); const char* quote = out->GetQuoteChar( i->c_str() ); out->Print( nestLevel+1, "%s%s%s\n", quote, i->c_str(), quote ); perLine += out->Print( 0, " %s%s%s", quote, i->c_str(), quote ); } } if( spares.size() ) if( spares.size() ) { { out->Print( nestLevel+1, "(spare\n" ); out->Print( 0, "\n" ); perLine = out->Print( nestLevel+1, "(spare" ); for( STRINGS::iterator i=spares.begin(); i!=spares.end(); ++i ) for( STRINGS::iterator i=spares.begin(); i!=spares.end(); ++i ) { { if( perLine > RIGHTMARGIN ) { out->Print( 0, "\n" ); perLine = out->Print( nestLevel+2, "%s", ""); } const char* quote = out->GetQuoteChar( i->c_str() ); const char* quote = out->GetQuoteChar( i->c_str() ); out->Print( nestLevel+2, "%s%s%s\n", quote, i->c_str(), quote ); perLine += out->Print( 0, " %s%s%s", quote, i->c_str(), quote ); } } out->Print( nestLevel+1, ")\n" ); out->Print( 0, ")" ); } } out->Print( nestLevel, ")\n" ); out->Print( 0, ")\n" ); } } }; }; Loading Loading @@ -1600,55 +1641,34 @@ public: }; }; class SHAPE : public ELEM class SHAPE : public ELEM_HOLDER { { friend class SPECCTRA_DB; friend class SPECCTRA_DB; DSN_T connect; DSN_T connect; //----- only one of these is used, like a union ----- /*----- only one of these is used, like a union ----- single item, but now in the kids list PATH* path; ///< used for both path and polygon PATH* path; ///< used for both path and polygon RECTANGLE* rectangle; RECTANGLE* rectangle; CIRCLE* circle; CIRCLE* circle; QARC* qarc; QARC* qarc; //--------------------------------------------------- //--------------------------------------------------- */ WINDOWS windows; WINDOWS windows; public: public: SHAPE( ELEM* aParent, DSN_T aType = T_shape ) : SHAPE( ELEM* aParent, DSN_T aType = T_shape ) : ELEM( aType, aParent ) ELEM_HOLDER( aType, aParent ) { { connect = T_on; connect = T_on; path = 0; rectangle = 0; circle = 0; qarc = 0; } ~SHAPE() { delete path; delete rectangle; delete circle; delete qarc; } } void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { { if( path ) ELEM_HOLDER::FormatContents( out, nestLevel ); path->Format( out, nestLevel ); else if( rectangle ) rectangle->Format( out, nestLevel ); else if( circle ) circle->Format( out, nestLevel ); else if( qarc ) qarc->Format( out, nestLevel ); if( connect == T_off ) if( connect == T_off ) out->Print( nestLevel, "(connect %s)\n", LEXER::GetTokenText( connect ) ); out->Print( nestLevel, "(connect %s)\n", LEXER::GetTokenText( connect ) ); Loading Loading @@ -1817,6 +1837,11 @@ public: delete rules; delete rules; } } void SetPadstackId( const char* aPadstackId ) { padstack_id = aPadstackId; } void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { { const char* quote = out->GetQuoteChar( padstack_id.c_str() ); const char* quote = out->GetQuoteChar( padstack_id.c_str() ); Loading Loading @@ -1865,6 +1890,7 @@ public: return ELEM::GetUnits(); return ELEM::GetUnits(); } } }; }; typedef boost::ptr_vector<PADSTACK> PADSTACKS; /** /** Loading @@ -1882,7 +1908,6 @@ class LIBRARY : public ELEM typedef boost::ptr_vector<IMAGE> IMAGES; typedef boost::ptr_vector<IMAGE> IMAGES; IMAGES images; IMAGES images; typedef boost::ptr_vector<PADSTACK> PADSTACKS; PADSTACKS padstacks; PADSTACKS padstacks; public: public: Loading Loading @@ -1916,6 +1941,11 @@ public: return ELEM::GetUnits(); return ELEM::GetUnits(); } } void AddPadstack( PADSTACK* aPadstack ) { padstacks.push_back( aPadstack ); } }; }; Loading Loading @@ -2215,35 +2245,32 @@ public: void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { { const int RIGHTMARGIN = 80; const char* quote = out->GetQuoteChar( class_id.c_str() ); const char* quote = out->GetQuoteChar( class_id.c_str() ); out->Print( nestLevel, "(%s %s%s%s", LEXER::GetTokenText( Type() ), quote, class_id.c_str(), quote ); const int NETGAP = 2; int perLine = out->Print( nestLevel, "(%s %s%s%s", const int RIGHTMARGIN = 92; LEXER::GetTokenText( Type() ), quote, class_id.c_str(), quote ); int perRow=RIGHTMARGIN; for( STRINGS::iterator i=net_ids.begin(); i!=net_ids.end(); ++i ) for( STRINGS::iterator i=net_ids.begin(); i!=net_ids.end(); ++i ) { { quote = out->GetQuoteChar( i->c_str() ); if( perLine > RIGHTMARGIN ) int slength = strlen( i->c_str() ); if( *quote!='\0' ) slength += 2; if( perRow + slength + NETGAP > RIGHTMARGIN ) { { out->Print( 0, "\n" ); out->Print( 0, "\n" ); perRow = 0; perLine = out->Print( nestLevel+1, "%s", "" ); perRow += out->Print( nestLevel+1, "%s%s%s", quote, i->c_str(), quote ); } else { perRow += out->Print( 0, "%*c%s%s%s", NETGAP, ' ', quote, i->c_str(), quote ); } } quote = out->GetQuoteChar( i->c_str() ); perLine += out->Print( 0, " %s%s%s", quote, i->c_str(), quote ); } } bool newLine = false; if( circuit.size() || layer_rules.size() || topology ) { out->Print( 0, "\n" ); out->Print( 0, "\n" ); newLine = true; } for( STRINGS::iterator i=circuit.begin(); i!=circuit.end(); ++i ) for( STRINGS::iterator i=circuit.begin(); i!=circuit.end(); ++i ) out->Print( nestLevel+1, "%s\n", i->c_str() ); out->Print( nestLevel+1, "%s\n", i->c_str() ); Loading @@ -2254,7 +2281,7 @@ public: if( topology ) if( topology ) topology->Format( out, nestLevel+1 ); topology->Format( out, nestLevel+1 ); out->Print( nestLevel, ")\n" ); out->Print( newLine ? nestLevel : 0, ")\n" ); } } }; }; Loading Loading @@ -2444,6 +2471,9 @@ public: perLine += out->Print( 0, "%.6g %.6g", i->x, i->y ); perLine += out->Print( 0, "%.6g %.6g", i->x, i->y ); } } if( net_id.size() || via_number!=-1 || type!=T_NONE || attr!=T_NONE || supply) out->Print( 0, " " ); if( net_id.size() ) if( net_id.size() ) { { if( perLine > RIGHTMARGIN ) if( perLine > RIGHTMARGIN ) Loading Loading @@ -3183,13 +3213,6 @@ class SPECCTRA_DB : public OUTPUTFORMATTER 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() Loading Loading @@ -3288,7 +3311,17 @@ public: /** /** * Function FromBOARD * Function FromBOARD * adds the entire BOARD to the PCB but does not write it out. * adds the entire BOARD to the PCB but does not write it out. Note that * the BOARD given to this function must have all the MODULEs on the component * side of the BOARD. * * See void WinEDA_PcbFrame::ExportToSPECCTRA( wxCommandEvent& event ) * for how this can be done before calling this function. * @todo * I would have liked to put the flipping logic into the ExportToSPECCTRA() * function directly, but for some strange reason, * void Change_Side_Module( MODULE* Module, wxDC* DC ) is a member of * 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 * @throw IOError, if the BOARD cannot be converted, and the text of the Loading
pcbnew/specctra_export.cpp +289 −19 Original line number Original line Diff line number Diff line Loading @@ -34,6 +34,7 @@ #include "specctra.h" #include "specctra.h" #include "collectors.h" #include "collectors.h" #include "wxPcbStruct.h" // Change_Side_Module() using namespace DSN; using namespace DSN; Loading Loading @@ -61,27 +62,59 @@ void WinEDA_PcbFrame::ExportToSPECCTRA( wxCommandEvent& event ) SPECCTRA_DB db; SPECCTRA_DB db; bool ok = true; wxString errorText; db.SetPCB( SPECCTRA_DB::MakePCB() ); db.SetPCB( SPECCTRA_DB::MakePCB() ); // DSN Images (=Kicad MODULES and pads) must be presented from the // top view. So we temporarily flip any modules which are on the back // side of the board to the front, and record this in the MODULE's flag field. for( MODULE* module = m_Pcb->m_Modules; module; module = module->Next() ) { module->flag = 0; if( module->GetLayer() == COPPER_LAYER_N ) { Change_Side_Module( module, NULL ); module->flag = 1; } } try try { { db.FromBOARD( m_Pcb ); db.FromBOARD( m_Pcb ); db.ExportPCB( fullFileName, true ); db.ExportPCB( fullFileName, true ); // if an exception is thrown by FromBOARD or Export(), then // if an exception is thrown by FromBOARD or ExportPCB(), then // ~SPECCTRA_DB() will close the file. // ~SPECCTRA_DB() will close the file. } } catch ( IOError ioe ) catch ( IOError ioe ) { { DisplayError( this, ioe.errorText ); ok = false; return; } // @todo display a message saying the export is complete. // display no messages until we flip back the modules below. errorText = ioe.errorText; } } // DSN Images (=Kicad MODULES and pads) must be presented from the // top view. Restore those that were flipped. for( MODULE* module = m_Pcb->m_Modules; module; module = module->Next() ) { if( module->flag ) { Change_Side_Module( module, NULL ); module->flag = 0; } } if( ok ) { // @todo display a message saying the export is complete. } else DisplayError( this, errorText ); } namespace DSN { namespace DSN { Loading @@ -103,6 +136,22 @@ static inline void swap( POINT_PAIR& pair ) } } static inline double scale( int kicadDist ) { return kicadDist/10.0; } static inline double mapX( int x ) { return scale(x); } static inline double mapY( int y ) { return -scale(y); // make y negative, since it is increasing going down. } /** /** * Function mapPt * Function mapPt * converts a Kicad point into a DSN file point. Kicad's BOARD coordinates * converts a Kicad point into a DSN file point. Kicad's BOARD coordinates Loading @@ -112,8 +161,8 @@ static inline void swap( POINT_PAIR& pair ) static POINT mapPt( const wxPoint& pt ) static POINT mapPt( const wxPoint& pt ) { { POINT ret; POINT ret; ret.x = pt.x / 10.0; ret.x = mapX( pt.x ); ret.y = -pt.y /10.0; // make y negative, since it is increasing going down. ret.y = mapY( pt.y ); return ret; return ret; } } Loading Loading @@ -172,8 +221,199 @@ static bool isRectangle( POINT_PAIRS& aList ) } } void SPECCTRA_DB::exportEdges( BOARD* aBoard ) throw( IOError ) /**************************************************************************/ static int Pad_list_Sort_by_Shapes( const void* refptr, const void* objptr ) /**************************************************************************/ { const D_PAD* padref = *(D_PAD**)refptr; const D_PAD* padcmp = *(D_PAD**)objptr; return D_PAD::Compare( padref, padcmp ); } /** * Function makePADSTACKs * makes all the PADSTACKs, and marks each D_PAD with the index into the * LIBRARY::padstacks list that it matches. */ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibrary, PADSTACKS& aPadstacks ) { if( aPads.GetCount() ) { { qsort( (void*) aPads.BasePtr(), aPads.GetCount(), sizeof(D_PAD*), Pad_list_Sort_by_Shapes ); } D_PAD* old_pad = NULL; int padstackNdx = 0; for( int i=0; i<aPads.GetCount(); ++i ) { D_PAD* pad = (D_PAD*) aPads[i]; pad->m_logical_connexion = padstackNdx; if( old_pad && 0==D_PAD::Compare( old_pad, pad ) ) { continue; } old_pad = pad; // this is the index into the library->padstacks, be careful. pad->m_logical_connexion = padstackNdx++; PADSTACK* padstack = new PADSTACK( aLibrary ); SHAPE* shape = new SHAPE( padstack ); padstack->Append( shape ); switch( pad->m_PadShape ) { default: case PAD_CIRCLE: { CIRCLE* circle; double diameter = scale(pad->m_Size.x); int coppers = 0; if( pad->IsOnLayer( COPPER_LAYER_N ) ) { circle = new CIRCLE( shape ); circle->SetLayerId( CONV_TO_UTF8(aBoard->GetLayerName( COPPER_LAYER_N )) ); circle->SetDiameter( diameter ); shape->Append( circle ); ++coppers; } if( pad->IsOnLayer( LAYER_CMP_N ) ) { circle = new CIRCLE( shape ); circle->SetLayerId( CONV_TO_UTF8(aBoard->GetLayerName( LAYER_CMP_N )) ); circle->SetDiameter( diameter ); shape->Append( circle ); ++coppers; } char name[50]; snprintf( name, sizeof(name), "Round%dPad_%.6g_mil", coppers, scale(pad->m_Size.x) ); name[ sizeof(name)-1 ] = 0; // @todo verify that all pad names are unique, there is a chance that // D_PAD::Compare() could say two pads are different, yet the get the same // name here. If so, blend in the padNdx into the name. padstack->SetPadstackId( name ); aLibrary->AddPadstack( padstack ); } break; case PAD_RECT: { double dx = scale( pad->m_Size.x ) / 2.0; double dy = scale( pad->m_Size.y ) / 2.0; RECTANGLE* rect; int coppers = 0; if( pad->IsOnLayer( COPPER_LAYER_N ) ) { rect = new RECTANGLE( shape ); rect->SetLayerId( CONV_TO_UTF8(aBoard->GetLayerName( COPPER_LAYER_N )) ); rect->SetCorners( POINT(-dx,-dy), POINT(dx,dy) ); shape->Append( rect ); ++coppers; } if( pad->IsOnLayer( LAYER_CMP_N ) ) { rect = new RECTANGLE( shape ); rect->SetLayerId( CONV_TO_UTF8(aBoard->GetLayerName( LAYER_CMP_N )) ); rect->SetCorners( POINT(-dx,-dy), POINT(dx,dy) ); shape->Append( rect ); ++coppers; } char name[50]; snprintf( name, sizeof(name), "Rect%dPad_%.6gx%.6g_mil", coppers, scale(pad->m_Size.x), scale(pad->m_Size.y) ); name[ sizeof(name)-1 ] = 0; // @todo verify that all pad names are unique, there is a chance that // D_PAD::Compare() could say two pads are different, yet the get the same // name here. If so, blend in the padNdx into the name. padstack->SetPadstackId( name ); aLibrary->AddPadstack( padstack ); } break; #if 0 pad_type = "RECTANGULAR"; fprintf( file, " %s %d\n", pad_type, pad->m_Drill.x ); fprintf( file, "RECTANGLE %d %d %d %d\n", -dx + pad->m_Offset.x, -dy - pad->m_Offset.y, dx + pad->m_Offset.x, -pad->m_Offset.y + dy ); break; case PAD_OVAL: /* description du contour par 2 linges et 2 arcs */ { pad_type = "FINGER"; fprintf( file, " %s %d\n", pad_type, pad->m_Drill.x ); int dr = dx - dy; if( dr >= 0 ) // ovale horizontal { int rayon = dy; fprintf( file, "LINE %d %d %d %d\n", -dr + pad->m_Offset.x, -pad->m_Offset.y - rayon, dr + pad->m_Offset.x, -pad->m_Offset.y - rayon ); fprintf( file, "ARC %d %d %d %d %d %d\n", dr + pad->m_Offset.x, -pad->m_Offset.y - rayon, dr + pad->m_Offset.x, -pad->m_Offset.y + rayon, dr + pad->m_Offset.x, -pad->m_Offset.y ); fprintf( file, "LINE %d %d %d %d\n", dr + pad->m_Offset.x, -pad->m_Offset.y + rayon, -dr + pad->m_Offset.x, -pad->m_Offset.y + rayon ); fprintf( file, "ARC %d %d %d %d %d %d\n", -dr + pad->m_Offset.x, -pad->m_Offset.y + rayon, -dr + pad->m_Offset.x, -pad->m_Offset.y - rayon, -dr + pad->m_Offset.x, -pad->m_Offset.y ); } else // ovale vertical { dr = -dr; int rayon = dx; fprintf( file, "LINE %d %d %d %d\n", -rayon + pad->m_Offset.x, -pad->m_Offset.y - dr, -rayon + pad->m_Offset.x, -pad->m_Offset.y + dr ); fprintf( file, "ARC %d %d %d %d %d %d\n", -rayon + pad->m_Offset.x, -pad->m_Offset.y + dr, rayon + pad->m_Offset.x, -pad->m_Offset.y + dr, pad->m_Offset.x, -pad->m_Offset.y + dr ); fprintf( file, "LINE %d %d %d %d\n", rayon + pad->m_Offset.x, -pad->m_Offset.y + dr, rayon + pad->m_Offset.x, -pad->m_Offset.y - dr ); fprintf( file, "ARC %d %d %d %d %d %d\n", rayon + pad->m_Offset.x, -pad->m_Offset.y - dr, -rayon + pad->m_Offset.x, -pad->m_Offset.y - dr, pad->m_Offset.x, -pad->m_Offset.y - dr ); } break; } case PAD_TRAPEZOID: pad_type = "POLYGON"; break; #endif } } } } Loading Loading @@ -304,6 +544,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError ) } } } } //-----<zone containers become planes>-------------------------------------------- //-----<zone containers become planes>-------------------------------------------- { { static const KICAD_T scanZONEs[] = { TYPEZONE_CONTAINER, EOT }; static const KICAD_T scanZONEs[] = { TYPEZONE_CONTAINER, EOT }; Loading Loading @@ -334,19 +575,48 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError ) } } } } // keepouts could go here, there are none in Kicad at this time. // although COPPER_PLANEs probably will need them for the thru holes, etc. // but in that case they are WINDOWs within the COPPER_PLANEs. //-----<build the padstack list here, no output>------------------------ //-----<build the padstack list here, no output>------------------------ { { // get all the DRAWSEGMENTS into 'items', then look for layer == EDGE_N, static const KICAD_T scanPADs[] = { TYPEPAD, EOT }; // and those segments comprize the board's perimeter. static const KICAD_T scanPADnVIAs[] = { TYPEPAD, TYPEVIA, EOT }; items.Collect( aBoard, scanPADnVIAs ); for( int i=0; i<items.GetCount(); ++i ) TYPE_COLLECTOR pads; // get all the D_PADs into pads. pads.Collect( aBoard, scanPADs ); makePADSTACKs( aBoard, pads, pcb->library, pcb->library->padstacks ); for( int p=0; p<pads.GetCount(); ++p ) pads[p]->Show( 0, std::cout ); /* static const KICAD_T scanMODULEs[] = { TYPEMODULE, EOT }; items.Collect( aBoard, scanMODULEs ); for( int m=0; m<items.GetCount(); ++m ) { { // items[i]->Show( 0, std::cout ); MODULE* module = (MODULE*) items[m]; // collate all the pads, and make a component. for( int p=0; p<pads.GetCount(); ++p ) { D_PAD* pad = (D_PAD*) pads[p]; D(pad->Show( 0, std::cout );) // lookup and maybe add this pad to the padstack. wxString padName = lookupPad( pcb->library->padstacks, pad ); } } } } */ } //-----<via_descriptor>------------------------------------------------- //-----<via_descriptor>------------------------------------------------- { { Loading