Loading gerbview/CMakeLists.txt +1 −0 Original line number Original line Diff line number Diff line Loading @@ -17,6 +17,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} set(DIALOGS_SRCS set(DIALOGS_SRCS dialogs/gerbview_dialog_display_options_frame_base.cpp dialogs/gerbview_dialog_display_options_frame_base.cpp dialogs/gerbview_dialog_display_options_frame.cpp dialogs/gerbview_dialog_display_options_frame.cpp dialogs/dialog_layers_select_to_pcb_base.cpp dialogs/dialog_print_using_printer.cpp dialogs/dialog_print_using_printer.cpp dialogs/dialog_print_using_printer_base.cpp dialogs/dialog_print_using_printer_base.cpp ) ) Loading gerbview/export_to_pcbnew.cpp +228 −125 Original line number Original line Diff line number Diff line Loading @@ -10,13 +10,50 @@ #include "confirm.h" #include "confirm.h" #include "kicad_string.h" #include "kicad_string.h" #include "gestfich.h" #include "gestfich.h" #include "trigo.h" #include "gerbview.h" #include "gerbview.h" #include "class_board_design_settings.h" #include "class_board_design_settings.h" #include "class_gerber_draw_item.h" #include "class_gerber_draw_item.h" static int SavePcbFormatAscii( GERBVIEW_FRAME* frame, FILE* File, int* LayerLookUpTable ); /* A helper class to export a Gerber set of files to Pcbnew */ class GBR_TO_PCB_EXPORTER { GERBVIEW_FRAME* m_gerbview_frame; // the maint gerber frame FILE * m_file; // .brd file to write to BOARD* m_pcb; // the board to populate and export public: GBR_TO_PCB_EXPORTER(GERBVIEW_FRAME * aFrame, FILE * aFile ); ~GBR_TO_PCB_EXPORTER(); bool ExportPcb( int* LayerLookUpTable ); private: bool WriteSetup( ); // Write the SETUP section data file bool WriteGeneralDescrPcb( ); void export_non_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ); void export_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ); void export_flashed_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ); void export_segline_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ); void export_segarc_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ); void cleanBoard(); }; GBR_TO_PCB_EXPORTER::GBR_TO_PCB_EXPORTER( GERBVIEW_FRAME * aFrame, FILE * aFile ) { m_gerbview_frame = aFrame; m_file = aFile; m_pcb = NULL; } GBR_TO_PCB_EXPORTER::~GBR_TO_PCB_EXPORTER() { // the destructor should destroy all owned sub-objects delete m_pcb; } /* Export data in pcbnew format /* Export data in pcbnew format Loading Loading @@ -45,8 +82,6 @@ void GERBVIEW_FRAME::ExportDataInPcbnewFormat( wxCommandEvent& event ) wxString PcbExt( wxT( ".brd" ) ); wxString PcbExt( wxT( ".brd" ) ); FILE* dest; msg = wxT( "*" ) + PcbExt; msg = wxT( "*" ) + PcbExt; FullFileName = EDA_FileSelector( _( "Board file name:" ), FullFileName = EDA_FileSelector( _( "Board file name:" ), wxEmptyString, wxEmptyString, Loading @@ -68,53 +103,83 @@ void GERBVIEW_FRAME::ExportDataInPcbnewFormat( wxCommandEvent& event ) if( !IsOK( this, _( "Ok to change the existing file ?" ) ) ) if( !IsOK( this, _( "Ok to change the existing file ?" ) ) ) return; return; } } dest = wxFopen( FullFileName, wxT( "wt" ) ); FILE * file = wxFopen( FullFileName, wxT( "wt" ) ); if( dest == 0 ) if( file == NULL ) { { msg = _( "Unable to create " ) + FullFileName; msg = _( "Unable to create " ) + FullFileName; DisplayError( this, msg ); DisplayError( this, msg ); return; return; } } GetScreen()->SetFileName( FullFileName ); GetScreen()->SetFileName( FullFileName ); SavePcbFormatAscii( this, dest, LayerLookUpTable ); GBR_TO_PCB_EXPORTER gbr_exporter( this, file ); fclose( dest ); gbr_exporter.ExportPcb( LayerLookUpTable ); fclose( file ); } } } } void GBR_TO_PCB_EXPORTER::cleanBoard() { // delete redundant vias for( TRACK * track = m_pcb->m_Track; track; track = track->Next() ) { if( track->m_Shape != VIA_THROUGH ) continue; static int WriteSetup( FILE* File, BOARD* Pcb ) // Search and delete others vias TRACK* next_track; TRACK* alt_track = track->Next(); for( ; alt_track; alt_track = next_track ) { { char text[1024]; next_track = alt_track->Next(); if( alt_track->m_Shape != VIA_THROUGH ) continue; fprintf( File, "$SETUP\n" ); if( alt_track->m_Start != track->m_Start ) sprintf( text, "InternalUnit %f INCH\n", 1.0 / PCB_INTERNAL_UNIT ); continue; fprintf( File, "%s", text ); fprintf( File, "Layers %d\n", Pcb->GetCopperLayerCount() ); // delete track alt_track->UnLink(); delete alt_track; } } } fprintf( File, "$EndSETUP\n\n" ); bool GBR_TO_PCB_EXPORTER::WriteSetup( ) return 1; { fprintf( m_file, "$SETUP\n" ); fprintf( m_file, "InternalUnit %f INCH\n", 1.0 / PCB_INTERNAL_UNIT ); fprintf( m_file, "Layers %d\n", m_pcb->GetCopperLayerCount() ); fprintf( m_file, "$EndSETUP\n\n" ); return true; } } static bool WriteGeneralDescrPcb( BOARD* Pcb, FILE* File ) bool GBR_TO_PCB_EXPORTER::WriteGeneralDescrPcb( ) { { int NbLayers; int nbLayers; /* Print the copper layer count */ /* Print the copper layer count */ NbLayers = Pcb->GetCopperLayerCount(); nbLayers = m_pcb->GetCopperLayerCount(); fprintf( File, "$GENERAL\n" ); if( nbLayers <= 1 ) // Minimal layers count in Pcbnew is 2 fprintf( File, "LayerCount %d\n", NbLayers ); { nbLayers = 2; m_pcb->SetCopperLayerCount(2); } fprintf( m_file, "$GENERAL\n" ); fprintf( m_file, "encoding utf-8\n"); fprintf( m_file, "LayerCount %d\n", nbLayers ); /* Compute and print the board bounding box */ /* Compute and print the board bounding box */ Pcb->ComputeBoundingBox(); m_pcb->ComputeBoundingBox(); fprintf( File, "Di %d %d %d %d\n", fprintf( m_file, "Di %d %d %d %d\n", Pcb->m_BoundaryBox.GetX(), Pcb->m_BoundaryBox.GetY(), m_pcb->m_BoundaryBox.GetX(), m_pcb->m_BoundaryBox.GetY(), Pcb->m_BoundaryBox.GetRight(), m_pcb->m_BoundaryBox.GetRight(), Pcb->m_BoundaryBox.GetBottom() ); m_pcb->m_BoundaryBox.GetBottom() ); fprintf( File, "$EndGENERAL\n\n" ); fprintf( m_file, "$EndGENERAL\n\n" ); return TRUE; return true; } } Loading @@ -124,17 +189,13 @@ static bool WriteGeneralDescrPcb( BOARD* Pcb, FILE* File ) * @param LayerLookUpTable = look up table: pcbnew layer for each gerber layer * @param LayerLookUpTable = look up table: pcbnew layer for each gerber layer * @return 1 if OK, 0 if fail * @return 1 if OK, 0 if fail */ */ static int SavePcbFormatAscii( GERBVIEW_FRAME* frame, FILE* aFile, bool GBR_TO_PCB_EXPORTER::ExportPcb( int* LayerLookUpTable ) int* LayerLookUpTable ) { { char line[256]; char line[256]; BOARD* gerberPcb = frame->GetBoard(); BOARD* gerberPcb = m_gerbview_frame->GetBoard(); BOARD* pcb; wxBeginBusyCursor(); // create an image of gerber data // create an image of gerber data pcb = new BOARD( NULL, frame ); m_pcb = new BOARD( NULL, m_gerbview_frame ); BOARD_ITEM* item = gerberPcb->m_Drawings; BOARD_ITEM* item = gerberPcb->m_Drawings; for( ; item; item = item->Next() ) for( ; item; item = item->Next() ) { { Loading @@ -145,105 +206,147 @@ static int SavePcbFormatAscii( GERBVIEW_FRAME* frame, FILE* aFile, continue; continue; if( pcb_layer_number > LAST_COPPER_LAYER ) if( pcb_layer_number > LAST_COPPER_LAYER ) { export_non_copper_item( gerb_item, pcb_layer_number ); DRAWSEGMENT* drawitem = new DRAWSEGMENT( pcb, TYPE_DRAWSEGMENT ); drawitem->SetLayer( pcb_layer_number ); else drawitem->m_Start = gerb_item->m_Start; export_copper_item( gerb_item, pcb_layer_number ); drawitem->m_End = gerb_item->m_End; } drawitem->m_Width = gerb_item->m_Size.x; if( gerb_item->m_Shape == GBR_ARC ) cleanBoard(); { double cx = gerb_item->m_ArcCentre.x; double cy = gerb_item->m_ArcCentre.y; double a = atan2( gerb_item->m_Start.y - cy, gerb_item->m_Start.x - cx ); double b = atan2( gerb_item->m_End.y - cy, gerb_item->m_End.x - cx ); drawitem->m_Shape = S_ARC; // Switch the locale to standard C (needed to print floating point numbers) drawitem->m_Angle = (int) fmod( SetLocaleTo_C_standard(); (a - b) / M_PI * 1800.0 + 3600.0, 3600.0 ); drawitem->m_Start.x = (int) cx; // write PCB header drawitem->m_Start.y = (int) cy; fprintf( m_file, "PCBNEW-BOARD Version %d date %s\n\n", g_CurrentVersionPCB, } DateAndTime( line ) ); WriteGeneralDescrPcb( ); WriteSetup( ); // write items on file m_pcb->Save( m_file ); pcb->Add( drawitem ); SetLocaleTo_Default(); // revert to the current locale return true; } } else void GBR_TO_PCB_EXPORTER::export_non_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ) { { TRACK* newtrack; DRAWSEGMENT* drawitem = new DRAWSEGMENT( m_pcb, TYPE_DRAWSEGMENT ); // replace spots with vias when possible drawitem->SetLayer( aLayer ); if( gerb_item->m_Shape == GBR_SPOT_CIRCLE drawitem->m_Start = aGbrItem->m_Start; || gerb_item->m_Shape == GBR_SPOT_RECT drawitem->m_End = aGbrItem->m_End; || gerb_item->m_Shape == GBR_SPOT_OVAL ) drawitem->m_Width = aGbrItem->m_Size.x; if( aGbrItem->m_Shape == GBR_ARC ) { { newtrack = new SEGVIA( pcb ); double a = atan2( (double)( aGbrItem->m_Start.y - aGbrItem->m_ArcCentre.y), (double)( aGbrItem->m_Start.x - aGbrItem->m_ArcCentre.x ) ); double b = atan2( (double)( aGbrItem->m_End.y - aGbrItem->m_ArcCentre.y ), (double)( aGbrItem->m_End.x - aGbrItem->m_ArcCentre.x ) ); // A spot is found, and can be a via: change it to via, and drawitem->m_Shape = S_ARC; // delete other drawitem->m_Angle = wxRound( (a - b) / M_PI * 1800.0 ); // spots at same location drawitem->m_Start = aGbrItem->m_ArcCentre; newtrack->m_Shape = VIA_THROUGH; if( drawitem->m_Angle < 0 ) newtrack->SetLayer( 0x0F ); // Layers are 0 to 15 (Cu/Cmp) newtrack->SetDrillDefault(); newtrack->m_Start = newtrack->m_End = gerb_item->m_Start; newtrack->m_Width = (gerb_item->m_Size.x + gerb_item->m_Size.y) / 2; } else // a true TRACK { { newtrack = new TRACK( pcb ); NEGATE( drawitem->m_Angle ); newtrack->SetLayer( pcb_layer_number ); drawitem->m_End = aGbrItem->m_Start; newtrack->m_Start = gerb_item->m_Start; newtrack->m_End = gerb_item->m_End; newtrack->m_Width = gerb_item->m_Size.x; } } pcb->Add( newtrack ); } } m_pcb->Add( drawitem ); } } // delete redundant vias void GBR_TO_PCB_EXPORTER::export_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ) for( TRACK * track = pcb->m_Track; track; track = track->Next() ) { { if( track->m_Shape != VIA_THROUGH ) switch( aGbrItem->m_Shape ) continue; // Search and delete others vias TRACK* next_track; TRACK* alt_track = track->Next(); for( ; alt_track; alt_track = next_track ) { { next_track = alt_track->Next(); case GBR_SPOT_CIRCLE: if( alt_track->m_Shape != VIA_THROUGH ) case GBR_SPOT_RECT: continue; case GBR_SPOT_OVAL: // replace spots with vias when possible export_flashed_copper_item( aGbrItem, aLayer ); break; if( alt_track->m_Start != track->m_Start ) case GBR_ARC: continue; // export_segarc_copper_item( aGbrItem, aLayer ); break; // delete track default: alt_track->UnLink(); export_segline_copper_item( aGbrItem, aLayer ); delete alt_track; break; } } } } // Switch the locale to standard C (needed to print floating point numbers void GBR_TO_PCB_EXPORTER::export_segline_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ) // like 1.3) { SetLocaleTo_C_standard(); TRACK * newtrack = new TRACK( m_pcb ); newtrack->SetLayer( aLayer ); newtrack->m_Start = aGbrItem->m_Start; newtrack->m_End = aGbrItem->m_End; newtrack->m_Width = aGbrItem->m_Size.x; m_pcb->Add( newtrack ); } // write the PCB heading void GBR_TO_PCB_EXPORTER::export_segarc_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ) fprintf( aFile, "PCBNEW-BOARD Version %d date %s\n\n", g_CurrentVersionPCB, { DateAndTime( line ) ); double a = atan2( (double)( aGbrItem->m_Start.y - aGbrItem->m_ArcCentre.y ), WriteGeneralDescrPcb( pcb, aFile ); (double)( aGbrItem->m_Start.x - aGbrItem->m_ArcCentre.x ) ); WriteSetup( aFile, pcb ); double b = atan2( (double)( aGbrItem->m_End.y - aGbrItem->m_ArcCentre.y ), (double)( aGbrItem->m_End.x - aGbrItem->m_ArcCentre.x ) ); int arc_angle = wxRound( ( (a - b) / M_PI * 1800.0 ) ); wxPoint start = aGbrItem->m_Start; wxPoint end = aGbrItem->m_End; /* Because Pcbnew does not know arcs in tracks, * approximate arc by segments (16 segment per 360 deg) */ #define DELTA 3600/16 if( arc_angle < 0 ) { NEGATE( arc_angle ); EXCHG( start, end ); } wxPoint curr_start = start; for( int rot = DELTA; rot < (arc_angle - DELTA); rot += DELTA ) { TRACK * newtrack = new TRACK( m_pcb ); newtrack->SetLayer( aLayer ); newtrack->m_Start = curr_start; wxPoint curr_end = start; RotatePoint( &curr_end, aGbrItem->m_ArcCentre, rot ); newtrack->m_End = curr_end; newtrack->m_Width = aGbrItem->m_Size.x; m_pcb->Add( newtrack ); curr_start = curr_end; } if( end != curr_start ) { TRACK * newtrack = new TRACK( m_pcb ); newtrack->SetLayer( aLayer ); newtrack->m_Start = curr_start; newtrack->m_End = end; newtrack->m_Width = aGbrItem->m_Size.x; m_pcb->Add( newtrack ); } } // write the useful part of the pcb pcb->Save( aFile ); // the destructor should destroy all owned sub-objects /* delete pcb; * creates a via from a flashed gerber item. * Flashed items are usually pads or vias, so we try to export all of them * using vias */ void GBR_TO_PCB_EXPORTER::export_flashed_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ) { SEGVIA * newtrack = new SEGVIA( m_pcb ); SetLocaleTo_Default(); // revert to the current locale newtrack->m_Shape = VIA_THROUGH; wxEndBusyCursor(); newtrack->SetLayer( 0x0F ); // Layers are 0 to 15 (Cu/Cmp) return 1; newtrack->SetDrillDefault(); newtrack->m_Start = newtrack->m_End = aGbrItem->m_Start; newtrack->m_Width = (aGbrItem->m_Size.x + aGbrItem->m_Size.y) / 2; m_pcb->Add( newtrack ); } } Loading
gerbview/CMakeLists.txt +1 −0 Original line number Original line Diff line number Diff line Loading @@ -17,6 +17,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} set(DIALOGS_SRCS set(DIALOGS_SRCS dialogs/gerbview_dialog_display_options_frame_base.cpp dialogs/gerbview_dialog_display_options_frame_base.cpp dialogs/gerbview_dialog_display_options_frame.cpp dialogs/gerbview_dialog_display_options_frame.cpp dialogs/dialog_layers_select_to_pcb_base.cpp dialogs/dialog_print_using_printer.cpp dialogs/dialog_print_using_printer.cpp dialogs/dialog_print_using_printer_base.cpp dialogs/dialog_print_using_printer_base.cpp ) ) Loading
gerbview/export_to_pcbnew.cpp +228 −125 Original line number Original line Diff line number Diff line Loading @@ -10,13 +10,50 @@ #include "confirm.h" #include "confirm.h" #include "kicad_string.h" #include "kicad_string.h" #include "gestfich.h" #include "gestfich.h" #include "trigo.h" #include "gerbview.h" #include "gerbview.h" #include "class_board_design_settings.h" #include "class_board_design_settings.h" #include "class_gerber_draw_item.h" #include "class_gerber_draw_item.h" static int SavePcbFormatAscii( GERBVIEW_FRAME* frame, FILE* File, int* LayerLookUpTable ); /* A helper class to export a Gerber set of files to Pcbnew */ class GBR_TO_PCB_EXPORTER { GERBVIEW_FRAME* m_gerbview_frame; // the maint gerber frame FILE * m_file; // .brd file to write to BOARD* m_pcb; // the board to populate and export public: GBR_TO_PCB_EXPORTER(GERBVIEW_FRAME * aFrame, FILE * aFile ); ~GBR_TO_PCB_EXPORTER(); bool ExportPcb( int* LayerLookUpTable ); private: bool WriteSetup( ); // Write the SETUP section data file bool WriteGeneralDescrPcb( ); void export_non_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ); void export_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ); void export_flashed_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ); void export_segline_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ); void export_segarc_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ); void cleanBoard(); }; GBR_TO_PCB_EXPORTER::GBR_TO_PCB_EXPORTER( GERBVIEW_FRAME * aFrame, FILE * aFile ) { m_gerbview_frame = aFrame; m_file = aFile; m_pcb = NULL; } GBR_TO_PCB_EXPORTER::~GBR_TO_PCB_EXPORTER() { // the destructor should destroy all owned sub-objects delete m_pcb; } /* Export data in pcbnew format /* Export data in pcbnew format Loading Loading @@ -45,8 +82,6 @@ void GERBVIEW_FRAME::ExportDataInPcbnewFormat( wxCommandEvent& event ) wxString PcbExt( wxT( ".brd" ) ); wxString PcbExt( wxT( ".brd" ) ); FILE* dest; msg = wxT( "*" ) + PcbExt; msg = wxT( "*" ) + PcbExt; FullFileName = EDA_FileSelector( _( "Board file name:" ), FullFileName = EDA_FileSelector( _( "Board file name:" ), wxEmptyString, wxEmptyString, Loading @@ -68,53 +103,83 @@ void GERBVIEW_FRAME::ExportDataInPcbnewFormat( wxCommandEvent& event ) if( !IsOK( this, _( "Ok to change the existing file ?" ) ) ) if( !IsOK( this, _( "Ok to change the existing file ?" ) ) ) return; return; } } dest = wxFopen( FullFileName, wxT( "wt" ) ); FILE * file = wxFopen( FullFileName, wxT( "wt" ) ); if( dest == 0 ) if( file == NULL ) { { msg = _( "Unable to create " ) + FullFileName; msg = _( "Unable to create " ) + FullFileName; DisplayError( this, msg ); DisplayError( this, msg ); return; return; } } GetScreen()->SetFileName( FullFileName ); GetScreen()->SetFileName( FullFileName ); SavePcbFormatAscii( this, dest, LayerLookUpTable ); GBR_TO_PCB_EXPORTER gbr_exporter( this, file ); fclose( dest ); gbr_exporter.ExportPcb( LayerLookUpTable ); fclose( file ); } } } } void GBR_TO_PCB_EXPORTER::cleanBoard() { // delete redundant vias for( TRACK * track = m_pcb->m_Track; track; track = track->Next() ) { if( track->m_Shape != VIA_THROUGH ) continue; static int WriteSetup( FILE* File, BOARD* Pcb ) // Search and delete others vias TRACK* next_track; TRACK* alt_track = track->Next(); for( ; alt_track; alt_track = next_track ) { { char text[1024]; next_track = alt_track->Next(); if( alt_track->m_Shape != VIA_THROUGH ) continue; fprintf( File, "$SETUP\n" ); if( alt_track->m_Start != track->m_Start ) sprintf( text, "InternalUnit %f INCH\n", 1.0 / PCB_INTERNAL_UNIT ); continue; fprintf( File, "%s", text ); fprintf( File, "Layers %d\n", Pcb->GetCopperLayerCount() ); // delete track alt_track->UnLink(); delete alt_track; } } } fprintf( File, "$EndSETUP\n\n" ); bool GBR_TO_PCB_EXPORTER::WriteSetup( ) return 1; { fprintf( m_file, "$SETUP\n" ); fprintf( m_file, "InternalUnit %f INCH\n", 1.0 / PCB_INTERNAL_UNIT ); fprintf( m_file, "Layers %d\n", m_pcb->GetCopperLayerCount() ); fprintf( m_file, "$EndSETUP\n\n" ); return true; } } static bool WriteGeneralDescrPcb( BOARD* Pcb, FILE* File ) bool GBR_TO_PCB_EXPORTER::WriteGeneralDescrPcb( ) { { int NbLayers; int nbLayers; /* Print the copper layer count */ /* Print the copper layer count */ NbLayers = Pcb->GetCopperLayerCount(); nbLayers = m_pcb->GetCopperLayerCount(); fprintf( File, "$GENERAL\n" ); if( nbLayers <= 1 ) // Minimal layers count in Pcbnew is 2 fprintf( File, "LayerCount %d\n", NbLayers ); { nbLayers = 2; m_pcb->SetCopperLayerCount(2); } fprintf( m_file, "$GENERAL\n" ); fprintf( m_file, "encoding utf-8\n"); fprintf( m_file, "LayerCount %d\n", nbLayers ); /* Compute and print the board bounding box */ /* Compute and print the board bounding box */ Pcb->ComputeBoundingBox(); m_pcb->ComputeBoundingBox(); fprintf( File, "Di %d %d %d %d\n", fprintf( m_file, "Di %d %d %d %d\n", Pcb->m_BoundaryBox.GetX(), Pcb->m_BoundaryBox.GetY(), m_pcb->m_BoundaryBox.GetX(), m_pcb->m_BoundaryBox.GetY(), Pcb->m_BoundaryBox.GetRight(), m_pcb->m_BoundaryBox.GetRight(), Pcb->m_BoundaryBox.GetBottom() ); m_pcb->m_BoundaryBox.GetBottom() ); fprintf( File, "$EndGENERAL\n\n" ); fprintf( m_file, "$EndGENERAL\n\n" ); return TRUE; return true; } } Loading @@ -124,17 +189,13 @@ static bool WriteGeneralDescrPcb( BOARD* Pcb, FILE* File ) * @param LayerLookUpTable = look up table: pcbnew layer for each gerber layer * @param LayerLookUpTable = look up table: pcbnew layer for each gerber layer * @return 1 if OK, 0 if fail * @return 1 if OK, 0 if fail */ */ static int SavePcbFormatAscii( GERBVIEW_FRAME* frame, FILE* aFile, bool GBR_TO_PCB_EXPORTER::ExportPcb( int* LayerLookUpTable ) int* LayerLookUpTable ) { { char line[256]; char line[256]; BOARD* gerberPcb = frame->GetBoard(); BOARD* gerberPcb = m_gerbview_frame->GetBoard(); BOARD* pcb; wxBeginBusyCursor(); // create an image of gerber data // create an image of gerber data pcb = new BOARD( NULL, frame ); m_pcb = new BOARD( NULL, m_gerbview_frame ); BOARD_ITEM* item = gerberPcb->m_Drawings; BOARD_ITEM* item = gerberPcb->m_Drawings; for( ; item; item = item->Next() ) for( ; item; item = item->Next() ) { { Loading @@ -145,105 +206,147 @@ static int SavePcbFormatAscii( GERBVIEW_FRAME* frame, FILE* aFile, continue; continue; if( pcb_layer_number > LAST_COPPER_LAYER ) if( pcb_layer_number > LAST_COPPER_LAYER ) { export_non_copper_item( gerb_item, pcb_layer_number ); DRAWSEGMENT* drawitem = new DRAWSEGMENT( pcb, TYPE_DRAWSEGMENT ); drawitem->SetLayer( pcb_layer_number ); else drawitem->m_Start = gerb_item->m_Start; export_copper_item( gerb_item, pcb_layer_number ); drawitem->m_End = gerb_item->m_End; } drawitem->m_Width = gerb_item->m_Size.x; if( gerb_item->m_Shape == GBR_ARC ) cleanBoard(); { double cx = gerb_item->m_ArcCentre.x; double cy = gerb_item->m_ArcCentre.y; double a = atan2( gerb_item->m_Start.y - cy, gerb_item->m_Start.x - cx ); double b = atan2( gerb_item->m_End.y - cy, gerb_item->m_End.x - cx ); drawitem->m_Shape = S_ARC; // Switch the locale to standard C (needed to print floating point numbers) drawitem->m_Angle = (int) fmod( SetLocaleTo_C_standard(); (a - b) / M_PI * 1800.0 + 3600.0, 3600.0 ); drawitem->m_Start.x = (int) cx; // write PCB header drawitem->m_Start.y = (int) cy; fprintf( m_file, "PCBNEW-BOARD Version %d date %s\n\n", g_CurrentVersionPCB, } DateAndTime( line ) ); WriteGeneralDescrPcb( ); WriteSetup( ); // write items on file m_pcb->Save( m_file ); pcb->Add( drawitem ); SetLocaleTo_Default(); // revert to the current locale return true; } } else void GBR_TO_PCB_EXPORTER::export_non_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ) { { TRACK* newtrack; DRAWSEGMENT* drawitem = new DRAWSEGMENT( m_pcb, TYPE_DRAWSEGMENT ); // replace spots with vias when possible drawitem->SetLayer( aLayer ); if( gerb_item->m_Shape == GBR_SPOT_CIRCLE drawitem->m_Start = aGbrItem->m_Start; || gerb_item->m_Shape == GBR_SPOT_RECT drawitem->m_End = aGbrItem->m_End; || gerb_item->m_Shape == GBR_SPOT_OVAL ) drawitem->m_Width = aGbrItem->m_Size.x; if( aGbrItem->m_Shape == GBR_ARC ) { { newtrack = new SEGVIA( pcb ); double a = atan2( (double)( aGbrItem->m_Start.y - aGbrItem->m_ArcCentre.y), (double)( aGbrItem->m_Start.x - aGbrItem->m_ArcCentre.x ) ); double b = atan2( (double)( aGbrItem->m_End.y - aGbrItem->m_ArcCentre.y ), (double)( aGbrItem->m_End.x - aGbrItem->m_ArcCentre.x ) ); // A spot is found, and can be a via: change it to via, and drawitem->m_Shape = S_ARC; // delete other drawitem->m_Angle = wxRound( (a - b) / M_PI * 1800.0 ); // spots at same location drawitem->m_Start = aGbrItem->m_ArcCentre; newtrack->m_Shape = VIA_THROUGH; if( drawitem->m_Angle < 0 ) newtrack->SetLayer( 0x0F ); // Layers are 0 to 15 (Cu/Cmp) newtrack->SetDrillDefault(); newtrack->m_Start = newtrack->m_End = gerb_item->m_Start; newtrack->m_Width = (gerb_item->m_Size.x + gerb_item->m_Size.y) / 2; } else // a true TRACK { { newtrack = new TRACK( pcb ); NEGATE( drawitem->m_Angle ); newtrack->SetLayer( pcb_layer_number ); drawitem->m_End = aGbrItem->m_Start; newtrack->m_Start = gerb_item->m_Start; newtrack->m_End = gerb_item->m_End; newtrack->m_Width = gerb_item->m_Size.x; } } pcb->Add( newtrack ); } } m_pcb->Add( drawitem ); } } // delete redundant vias void GBR_TO_PCB_EXPORTER::export_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ) for( TRACK * track = pcb->m_Track; track; track = track->Next() ) { { if( track->m_Shape != VIA_THROUGH ) switch( aGbrItem->m_Shape ) continue; // Search and delete others vias TRACK* next_track; TRACK* alt_track = track->Next(); for( ; alt_track; alt_track = next_track ) { { next_track = alt_track->Next(); case GBR_SPOT_CIRCLE: if( alt_track->m_Shape != VIA_THROUGH ) case GBR_SPOT_RECT: continue; case GBR_SPOT_OVAL: // replace spots with vias when possible export_flashed_copper_item( aGbrItem, aLayer ); break; if( alt_track->m_Start != track->m_Start ) case GBR_ARC: continue; // export_segarc_copper_item( aGbrItem, aLayer ); break; // delete track default: alt_track->UnLink(); export_segline_copper_item( aGbrItem, aLayer ); delete alt_track; break; } } } } // Switch the locale to standard C (needed to print floating point numbers void GBR_TO_PCB_EXPORTER::export_segline_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ) // like 1.3) { SetLocaleTo_C_standard(); TRACK * newtrack = new TRACK( m_pcb ); newtrack->SetLayer( aLayer ); newtrack->m_Start = aGbrItem->m_Start; newtrack->m_End = aGbrItem->m_End; newtrack->m_Width = aGbrItem->m_Size.x; m_pcb->Add( newtrack ); } // write the PCB heading void GBR_TO_PCB_EXPORTER::export_segarc_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ) fprintf( aFile, "PCBNEW-BOARD Version %d date %s\n\n", g_CurrentVersionPCB, { DateAndTime( line ) ); double a = atan2( (double)( aGbrItem->m_Start.y - aGbrItem->m_ArcCentre.y ), WriteGeneralDescrPcb( pcb, aFile ); (double)( aGbrItem->m_Start.x - aGbrItem->m_ArcCentre.x ) ); WriteSetup( aFile, pcb ); double b = atan2( (double)( aGbrItem->m_End.y - aGbrItem->m_ArcCentre.y ), (double)( aGbrItem->m_End.x - aGbrItem->m_ArcCentre.x ) ); int arc_angle = wxRound( ( (a - b) / M_PI * 1800.0 ) ); wxPoint start = aGbrItem->m_Start; wxPoint end = aGbrItem->m_End; /* Because Pcbnew does not know arcs in tracks, * approximate arc by segments (16 segment per 360 deg) */ #define DELTA 3600/16 if( arc_angle < 0 ) { NEGATE( arc_angle ); EXCHG( start, end ); } wxPoint curr_start = start; for( int rot = DELTA; rot < (arc_angle - DELTA); rot += DELTA ) { TRACK * newtrack = new TRACK( m_pcb ); newtrack->SetLayer( aLayer ); newtrack->m_Start = curr_start; wxPoint curr_end = start; RotatePoint( &curr_end, aGbrItem->m_ArcCentre, rot ); newtrack->m_End = curr_end; newtrack->m_Width = aGbrItem->m_Size.x; m_pcb->Add( newtrack ); curr_start = curr_end; } if( end != curr_start ) { TRACK * newtrack = new TRACK( m_pcb ); newtrack->SetLayer( aLayer ); newtrack->m_Start = curr_start; newtrack->m_End = end; newtrack->m_Width = aGbrItem->m_Size.x; m_pcb->Add( newtrack ); } } // write the useful part of the pcb pcb->Save( aFile ); // the destructor should destroy all owned sub-objects /* delete pcb; * creates a via from a flashed gerber item. * Flashed items are usually pads or vias, so we try to export all of them * using vias */ void GBR_TO_PCB_EXPORTER::export_flashed_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ) { SEGVIA * newtrack = new SEGVIA( m_pcb ); SetLocaleTo_Default(); // revert to the current locale newtrack->m_Shape = VIA_THROUGH; wxEndBusyCursor(); newtrack->SetLayer( 0x0F ); // Layers are 0 to 15 (Cu/Cmp) return 1; newtrack->SetDrillDefault(); newtrack->m_Start = newtrack->m_End = aGbrItem->m_Start; newtrack->m_Width = (aGbrItem->m_Size.x + aGbrItem->m_Size.y) / 2; m_pcb->Add( newtrack ); } }